添加msg的提供者的逻辑
完成基础版本的交互逻辑已经具备同步消息的框架了。就是状态维护上有点瑕疵等待完善。
This commit is contained in:
		@@ -23,6 +23,7 @@ winapi = { version = "0.3.9", features = ["winuser", "psapi"] }
 | 
			
		||||
base64 = "0.21"
 | 
			
		||||
serde = { version = "1.0", features = ["derive"] }
 | 
			
		||||
serde_json = "1.0"
 | 
			
		||||
dirs = "4.0"
 | 
			
		||||
 | 
			
		||||
[profile.test]
 | 
			
		||||
env = { "RUST_LOG" = "debug" }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "cookies": "",
 | 
			
		||||
  "magic": "3",
 | 
			
		||||
  "magic": "2022-10-20 11:25:09.92",
 | 
			
		||||
  "password": "ZWtrb2Jhb19fX19fX19fXzlytojwgd3qVW7PNYs7Y9s=",
 | 
			
		||||
  "user_name": "ekko.bao"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										278
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										278
									
								
								src/lib.rs
									
									
									
									
									
								
							@@ -1,11 +1,9 @@
 | 
			
		||||
 | 
			
		||||
use log::Log;
 | 
			
		||||
use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
 | 
			
		||||
use rand::{random, Rng};
 | 
			
		||||
use rand::Rng;
 | 
			
		||||
use reqwest::header::HeaderMap;
 | 
			
		||||
use reqwest::{Client, Response};
 | 
			
		||||
use scraper::{Html, Selector};
 | 
			
		||||
use core::ascii;
 | 
			
		||||
use std::error::Error;
 | 
			
		||||
use std::io::{self, Write};
 | 
			
		||||
use std::time::Duration;
 | 
			
		||||
@@ -14,10 +12,14 @@ use std::sync::Arc;
 | 
			
		||||
use tokio::{task, time};
 | 
			
		||||
use std::collections::BTreeMap;
 | 
			
		||||
extern crate log;
 | 
			
		||||
use serde_json::{self, to_string, Value};
 | 
			
		||||
use serde_json::{self, Value};
 | 
			
		||||
use serde::Serialize;
 | 
			
		||||
use std::fs::File;
 | 
			
		||||
use std::fs::{self, File};
 | 
			
		||||
use std::io::BufReader;
 | 
			
		||||
use dirs;
 | 
			
		||||
use std::path::Path;
 | 
			
		||||
use std::time::UNIX_EPOCH;
 | 
			
		||||
use std::io::Read;
 | 
			
		||||
 | 
			
		||||
pub mod wclip;
 | 
			
		||||
pub mod sys_res;
 | 
			
		||||
@@ -126,6 +128,8 @@ pub struct ClipboardSync {
 | 
			
		||||
    ip: String,
 | 
			
		||||
    clip: wclip::Wclip,
 | 
			
		||||
    cfg: Config,
 | 
			
		||||
    pipe: MsgSyncPipe,
 | 
			
		||||
    characters: Character,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const USER_AGENT: &str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.42";
 | 
			
		||||
@@ -140,43 +144,163 @@ pub struct ClipboardMsgs {
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
enum MsgSyncState {
 | 
			
		||||
    None,
 | 
			
		||||
    ForceInVM,
 | 
			
		||||
    NeedSync,
 | 
			
		||||
    Idle,
 | 
			
		||||
    FocusOnVM,
 | 
			
		||||
    WaitingSendMsg,
 | 
			
		||||
    WaitingRecMsg,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone)]
 | 
			
		||||
pub enum Character {
 | 
			
		||||
    Producer,
 | 
			
		||||
    Consumer,
 | 
			
		||||
}
 | 
			
		||||
struct MsgSyncPipe {
 | 
			
		||||
    pub pipe_file: String,
 | 
			
		||||
    atime: Duration,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 这里使用一个共享的pipe文件的atime来同步消息状态,
 | 
			
		||||
 * 当消费者请求消息时,将尝试访问pipe文件,更新访问时间。使得生产者知道此时应该要发送消息了。
 | 
			
		||||
 * 生产者尝试访问pipe文件发现atime被更新,说明此时有消费者请求发送消息,那么就发送消息并将atime更新,使得消费者知道此时有一条消息更新了,
 | 
			
		||||
 */
 | 
			
		||||
impl MsgSyncPipe {
 | 
			
		||||
    pub fn new(c:&Character) -> Result<MsgSyncPipe, Box<dyn Error>> {
 | 
			
		||||
        let pipe_file = match c {
 | 
			
		||||
            Character::Producer => Self::get_producer_pipe()?,
 | 
			
		||||
            Character::Consumer => Self::get_consumer_pipe()?,
 | 
			
		||||
        };
 | 
			
		||||
        let atime = Self::get_pipe_atime(&pipe_file);
 | 
			
		||||
        Ok(MsgSyncPipe {
 | 
			
		||||
            pipe_file,
 | 
			
		||||
            atime,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_pipe_atime(path:&str) -> Duration {
 | 
			
		||||
        let metadata = fs::metadata(path).unwrap();
 | 
			
		||||
        // 获取最后访问时间
 | 
			
		||||
        if let Ok(accessed) = metadata.accessed() {
 | 
			
		||||
            accessed.duration_since(UNIX_EPOCH).unwrap()
 | 
			
		||||
        } else {
 | 
			
		||||
            Duration::new(0, 0)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn get_update(&mut self) -> bool {
 | 
			
		||||
        let atime = Self::get_pipe_atime(&self.pipe_file);
 | 
			
		||||
        log::trace!("pipe file access time: {:?}", atime);
 | 
			
		||||
        if atime > self.atime {
 | 
			
		||||
            self.atime = atime;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn set_update(&mut self) {
 | 
			
		||||
        // read pipe file to update access time
 | 
			
		||||
        // let mut file = File::options().read(true).open(&self.pipe_file).unwrap();
 | 
			
		||||
        // let mut buffer = Vec::new();
 | 
			
		||||
        // log::trace!("try update pipe file access time");
 | 
			
		||||
        // let _ = file.read_to_end(&mut buffer);
 | 
			
		||||
        let mut file = File::options().write(true).open(&self.pipe_file).unwrap();
 | 
			
		||||
        let _ = file.write("sstar_l0l3clip_sync".as_bytes());
 | 
			
		||||
        drop(file);
 | 
			
		||||
        self.get_update();
 | 
			
		||||
        log::trace!("pipe file access time updated: {:?}", self.atime);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_consumer_pipe() -> Result<String, Box<dyn Error>> {
 | 
			
		||||
        let path = match dirs::home_dir() {
 | 
			
		||||
            Some(path) => path,
 | 
			
		||||
            None => return Err("can not get user HOME dir".into()),
 | 
			
		||||
        };
 | 
			
		||||
        let path = path.join(".sstar_l0l3clip_sync");
 | 
			
		||||
        if !path.exists() {
 | 
			
		||||
            let mut file = fs::OpenOptions::new().create(true).write(true).open(&path)?;
 | 
			
		||||
            let _ = file.write("sstar_l0l3clip_sync".as_bytes());
 | 
			
		||||
        }
 | 
			
		||||
        Ok(path.to_str().unwrap().to_string())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_producer_pipe() -> Result<String, Box<dyn Error>> {
 | 
			
		||||
        let path = match dirs::home_dir() {
 | 
			
		||||
            Some(path) => path,
 | 
			
		||||
            None => return Err("can not get home dir".into()),
 | 
			
		||||
        };
 | 
			
		||||
        let path = path.join(".sstar_l0l3clip_sync").to_str().unwrap().to_string();
 | 
			
		||||
        let mut path = path.split(':').into_iter();
 | 
			
		||||
        let _ = path.next(); //ignore driver letter
 | 
			
		||||
        let sub_path = path.next().unwrap().to_string();
 | 
			
		||||
        for drive in 'C'..='Z' {
 | 
			
		||||
            let sub_path = format!("{}:{}", drive, sub_path);
 | 
			
		||||
            let sub_path = sub_path.replace("baoyucang", "BYC10");
 | 
			
		||||
            log::trace!("trying to find pipe file in {}", sub_path);
 | 
			
		||||
            if Path::new(&sub_path).exists() {
 | 
			
		||||
                return Ok(sub_path);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return Err("You should mapping l0 c:\\ to l3".into())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
static VM_EXE_NAME:&str = "mstsc.exe";
 | 
			
		||||
// 同步获取消息的线程
 | 
			
		||||
async fn msg_sync(ctx:Arc<Mutex<ClipboardSync>>) {
 | 
			
		||||
    let VM_EXE_NAME = "Code.exe".to_string();
 | 
			
		||||
async fn msg_reciver(ctx:Arc<Mutex<ClipboardSync>>) {
 | 
			
		||||
    let mut ctx = ctx.lock().await;
 | 
			
		||||
    let mut sta = MsgSyncState::None;
 | 
			
		||||
    let mut sta = MsgSyncState::Idle;
 | 
			
		||||
    let mut turn_time;
 | 
			
		||||
    //let _ = ctx.update_msg().await;
 | 
			
		||||
    loop{
 | 
			
		||||
        log::trace!("current state is {:?}", sta);
 | 
			
		||||
        match sta{
 | 
			
		||||
            MsgSyncState::None => {
 | 
			
		||||
                turn_time = 200;
 | 
			
		||||
    fn on_vm() -> bool {
 | 
			
		||||
        let vm_exe_name =VM_EXE_NAME.to_string();
 | 
			
		||||
        let prog_name = get_foredround_window_name();
 | 
			
		||||
                if prog_name == VM_EXE_NAME {
 | 
			
		||||
                    sta = MsgSyncState::ForceInVM;
 | 
			
		||||
        prog_name == vm_exe_name
 | 
			
		||||
    }
 | 
			
		||||
    let mut state_time = time::Instant::now();
 | 
			
		||||
    loop{
 | 
			
		||||
        // log::trace!("current state is {:?}", sta);
 | 
			
		||||
        match sta{
 | 
			
		||||
            MsgSyncState::Idle => {
 | 
			
		||||
                turn_time = 200;
 | 
			
		||||
                // 如果当前前台的窗口是VM的窗口说明鼠标在VM窗口内切换到等待移出的逻辑
 | 
			
		||||
                if on_vm() {
 | 
			
		||||
                    sta = MsgSyncState::FocusOnVM;
 | 
			
		||||
                    turn_time = 0;
 | 
			
		||||
                } else {
 | 
			
		||||
                    log::trace!("foreground prog is [{}] {}, waiting: [{}] {}", prog_name, prog_name.len(), VM_EXE_NAME, VM_EXE_NAME.len());
 | 
			
		||||
                    log::trace!("Idle, waiting for mouse move to vm window");
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            MsgSyncState::ForceInVM => {
 | 
			
		||||
            MsgSyncState::FocusOnVM => {
 | 
			
		||||
                turn_time = 100;
 | 
			
		||||
                let prog_name = get_foredround_window_name();
 | 
			
		||||
                if prog_name != VM_EXE_NAME {
 | 
			
		||||
                // 如果已经移出VM窗口,说明从L3切换到了L0,可能存在需要更新msg的情况那么就开始请求对方发送消息
 | 
			
		||||
                if !on_vm() {
 | 
			
		||||
                    turn_time = 0;
 | 
			
		||||
                    sta = MsgSyncState::NeedSync;
 | 
			
		||||
                    //请求远端发送消息
 | 
			
		||||
                    ctx.pipe.set_update();
 | 
			
		||||
                    sta = MsgSyncState::WaitingSendMsg;
 | 
			
		||||
                    state_time = time::Instant::now();
 | 
			
		||||
                    log::trace!("waiting for remote send msg...");
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            MsgSyncState::NeedSync => {
 | 
			
		||||
            MsgSyncState::WaitingSendMsg => {
 | 
			
		||||
                turn_time = 50;
 | 
			
		||||
                // 如果这里检测到了对方更新了文件状态,说明其已经发送完毕消息,我们开始时接收。
 | 
			
		||||
                if ctx.pipe.get_update() {
 | 
			
		||||
                    sta = MsgSyncState::WaitingRecMsg;
 | 
			
		||||
                    turn_time = 0;
 | 
			
		||||
                let _ = ctx.update_msg().await;
 | 
			
		||||
                sta = MsgSyncState::None;
 | 
			
		||||
                } else {
 | 
			
		||||
                    //最多等待1秒钟,如果超过1秒钟还没收到消息,那么就切换到空闲状态
 | 
			
		||||
                    if time::Instant::now() - state_time > Duration::new(1, 0) {
 | 
			
		||||
                        sta = MsgSyncState::Idle;
 | 
			
		||||
                        turn_time = 0;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            MsgSyncState::WaitingRecMsg => {
 | 
			
		||||
                turn_time = 0;
 | 
			
		||||
                log::trace!("now we can recv msg");
 | 
			
		||||
                // 接收完毕消息后切换到新的一轮判断中来
 | 
			
		||||
                let _ = ctx.recv_msg().await;
 | 
			
		||||
                sta = MsgSyncState::Idle;
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
        if turn_time != 0 {
 | 
			
		||||
@@ -184,9 +308,81 @@ async fn msg_sync(ctx:Arc<Mutex<ClipboardSync>>) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 同步获取消息的线程
 | 
			
		||||
async fn msg_sender(ctx:Arc<Mutex<ClipboardSync>>) {
 | 
			
		||||
    let mut ctx = ctx.lock().await;
 | 
			
		||||
    let mut sta = MsgSyncState::Idle;
 | 
			
		||||
    let mut turn_time;
 | 
			
		||||
    fn on_edge() -> bool {
 | 
			
		||||
        let (width, height) = sys_res::screen_size();
 | 
			
		||||
        let (x,y) = sys_res::cursor_pos();
 | 
			
		||||
        let margin = 20;
 | 
			
		||||
        if x < margin ||  y< margin || x > width - margin || y > height - margin {
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
        log::trace!("cursor pos:({},{})", x, y);
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
    loop{
 | 
			
		||||
        // log::trace!("current state is {:?}", sta);
 | 
			
		||||
        match sta{
 | 
			
		||||
            MsgSyncState::Idle => {
 | 
			
		||||
                turn_time = 0;
 | 
			
		||||
                // 更新下最新的文件状态,保证后续判断准确
 | 
			
		||||
                ctx.pipe.get_update(); // refresh pipe file status
 | 
			
		||||
                sta = MsgSyncState::FocusOnVM;
 | 
			
		||||
            },
 | 
			
		||||
            MsgSyncState::FocusOnVM => {
 | 
			
		||||
                turn_time = 100;
 | 
			
		||||
                // 当前处于窗口边缘,尝试切换到发送消息的逻辑:等待对方请求发送
 | 
			
		||||
                if on_edge() {
 | 
			
		||||
                    sta = MsgSyncState::WaitingSendMsg;
 | 
			
		||||
                    turn_time = 0;
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            MsgSyncState::WaitingSendMsg => {
 | 
			
		||||
                turn_time = 50;
 | 
			
		||||
                // 如果对方需要发送消息那么他会更新atime,这里就尝试发送消息
 | 
			
		||||
                if ctx.pipe.get_update() {
 | 
			
		||||
                    let _ = ctx.clip2msg().await;
 | 
			
		||||
                    log::trace!("send msg done");
 | 
			
		||||
                    turn_time = 0;
 | 
			
		||||
                    sta = MsgSyncState::WaitingRecMsg;
 | 
			
		||||
                    ctx.pipe.set_update();//sent ok set update flag
 | 
			
		||||
                // 如果文件没更新说明不需要发送消息,并且鼠标也不在边缘说明重新移回VM窗口内了,可以切换到等待状态
 | 
			
		||||
                } else if !on_edge()  {
 | 
			
		||||
                    turn_time = 0;
 | 
			
		||||
                    sta = MsgSyncState::Idle;
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            MsgSyncState::WaitingRecMsg => {
 | 
			
		||||
                turn_time = 0;
 | 
			
		||||
                sta = MsgSyncState::Idle;
 | 
			
		||||
                // 发送消息后鼠标还是保持在边缘说明当前鼠标还是在VM窗口外面,需要等待鼠标移动到VM窗口内,然后再发送消息
 | 
			
		||||
                if on_edge()  {
 | 
			
		||||
                    turn_time = 100;
 | 
			
		||||
                    sta = MsgSyncState::WaitingRecMsg;
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
        if turn_time != 0 {
 | 
			
		||||
            time::sleep(Duration::new(0, turn_time*1000*1000)).await;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub async fn start_msg_sync(ctx:Arc<Mutex<ClipboardSync>>) -> Result<task::JoinHandle<()>, Box<dyn Error>>{
 | 
			
		||||
    let handle = task::spawn(msg_sync(ctx));
 | 
			
		||||
    match ctx.lock().await.characters {
 | 
			
		||||
        Character::Consumer => {
 | 
			
		||||
            let handle = task::spawn(msg_reciver(ctx.clone()));
 | 
			
		||||
            Ok(handle)
 | 
			
		||||
        },
 | 
			
		||||
        Character::Producer => {
 | 
			
		||||
            let handle = task::spawn(msg_sender(ctx.clone()));
 | 
			
		||||
            Ok(handle)
 | 
			
		||||
        },
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum Msg <'a>{
 | 
			
		||||
@@ -197,13 +393,14 @@ enum Msg <'a>{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ClipboardSync {
 | 
			
		||||
    pub fn new(ip: &str, info_file:&str) -> Result<ClipboardSync, Box<dyn Error>> {
 | 
			
		||||
        let cfg =  Config::new(info_file)?;
 | 
			
		||||
    pub fn new(ip: &str, info_file:&str, c:&Character) -> Result<ClipboardSync, Box<dyn Error>> {
 | 
			
		||||
        Ok(ClipboardSync {
 | 
			
		||||
            web: Client::new(),
 | 
			
		||||
            ip: ip.to_string(),
 | 
			
		||||
            clip: wclip::Wclip::new(),
 | 
			
		||||
            cfg,
 | 
			
		||||
            cfg: Config::new(info_file)?,
 | 
			
		||||
            pipe: MsgSyncPipe::new(c)?,
 | 
			
		||||
            characters: c.clone(),
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -306,7 +503,7 @@ impl ClipboardSync {
 | 
			
		||||
        Ok(resp)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn update_msg(&mut self) -> Result<(), Box<dyn Error>> {
 | 
			
		||||
    pub async fn recv_msg(&mut self) -> Result<(), Box<dyn Error>> {
 | 
			
		||||
        let resp = self.get_newest_msg().await?;
 | 
			
		||||
        self.msg2clip(&resp).await;
 | 
			
		||||
        Ok(())
 | 
			
		||||
@@ -394,7 +591,7 @@ impl ClipboardSync {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn send_msg(&mut self, msg: &str) -> Result<(), Box<dyn Error>> {
 | 
			
		||||
    async fn send_msg(&mut self, msg: &str) -> Result<(), Box<dyn Error>> {
 | 
			
		||||
        let url = format!("http://{}/SSWeb/rd/copy_paste.jsp?send=y", self.ip);
 | 
			
		||||
        let mut headers = HeaderMap::new();
 | 
			
		||||
        headers.insert("Host", "ssweb".parse().unwrap());
 | 
			
		||||
@@ -418,7 +615,7 @@ impl ClipboardSync {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn split_msg(&mut self, msg: &str) -> Result<Vec<String>, i32>  {
 | 
			
		||||
    async fn split_msg(&mut self, msg: &str) -> Result<Vec<String>, i32>  {
 | 
			
		||||
        let mut start = 0;
 | 
			
		||||
        let mut msgs = Vec::new();
 | 
			
		||||
        let mut cur = 0;
 | 
			
		||||
@@ -473,7 +670,10 @@ impl ClipboardSync {
 | 
			
		||||
                Ok(msgs) => msgs,
 | 
			
		||||
                Err(_) => return,
 | 
			
		||||
            },
 | 
			
		||||
            None => return,
 | 
			
		||||
            None => {
 | 
			
		||||
                log::info!("clipboard is not string, ignore it");
 | 
			
		||||
                return
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
        //遍历所有分包并进行发送
 | 
			
		||||
        for item in msg {
 | 
			
		||||
@@ -487,7 +687,7 @@ async fn test_message2clip()
 | 
			
		||||
{
 | 
			
		||||
    use std::fs::File;
 | 
			
		||||
    use std::io::Read;
 | 
			
		||||
    let mut ins = ClipboardSync::new("127.0.0.1", "info.json").unwrap();
 | 
			
		||||
    let mut ins = ClipboardSync::new("127.0.0.1", "info.json", &Character::Producer).unwrap();
 | 
			
		||||
    let mut html = String::new();
 | 
			
		||||
    File::open("message.html").unwrap().read_to_string(&mut html).unwrap();
 | 
			
		||||
    ins.msg2clip(&html).await;
 | 
			
		||||
@@ -496,7 +696,7 @@ async fn test_message2clip()
 | 
			
		||||
#[tokio::test]
 | 
			
		||||
async fn test_start_msg_sync()
 | 
			
		||||
{
 | 
			
		||||
    let ins = ClipboardSync::new("127.0.0.1:5000", "info.json").unwrap();
 | 
			
		||||
    let ins = ClipboardSync::new("127.0.0.1:5000", "info.json", &Character::Producer).unwrap();
 | 
			
		||||
    let ctx = Arc::new(Mutex::new(ins));
 | 
			
		||||
    let handle = start_msg_sync(ctx.clone()).await.unwrap();
 | 
			
		||||
    time::sleep(Duration::new(10, 0)).await;
 | 
			
		||||
@@ -505,7 +705,7 @@ async fn test_start_msg_sync()
 | 
			
		||||
 | 
			
		||||
#[tokio::test]
 | 
			
		||||
async fn test_split_msg() {
 | 
			
		||||
    let mut ins = ClipboardSync::new("127.0.0.1:5000", "info.json").unwrap();
 | 
			
		||||
    let mut ins = ClipboardSync::new("127.0.0.1:5000", "info.json", &Character::Producer).unwrap();
 | 
			
		||||
    let raw_msg = "在这个快速发展的世界中,technology is evolving at an unprecedented rate! 我们需要不断学习和适应新的变化。#创新@未来$梦想%实现^挑战&机遇*合作+成长=成功~体验|分享<知识>探索{可能性}。Let's work together to create a better tomorrow! 生活充满了各种可能性,我们要勇敢面对每一个挑战。1234567890!@#$%^&*()_+-=<>?[]{},.。;:‘’“”()【】《》——";
 | 
			
		||||
    let msgs = ins.split_msg(raw_msg).await.unwrap();
 | 
			
		||||
    println!("{:?}", msgs);
 | 
			
		||||
@@ -513,7 +713,7 @@ async fn test_split_msg() {
 | 
			
		||||
 | 
			
		||||
#[tokio::test]
 | 
			
		||||
async fn test_send_send_msg() {
 | 
			
		||||
    let mut ins = ClipboardSync::new("127.0.0.1:5000", "info.json").unwrap();
 | 
			
		||||
    let mut ins = ClipboardSync::new("127.0.0.1:5000", "info.json", &Character::Producer).unwrap();
 | 
			
		||||
    let raw_msg = "在这个快速发展的世界中,technology is evolving at an unprecedented rate! 我们需要不断学习和适应新的变化。#创新@未来$梦想%实现^挑战&机遇*合作+成长=成功~体验|分享<知识>探索{可能性}。Let's work together to create a better tomorrow! 生活充满了各种可能性,我们要勇敢面对每一个挑战。1234567890!@#$%^&*()_+-=<>?[]{},.。;:‘’“”()【】《》——";
 | 
			
		||||
    ins.clip.set(&raw_msg);
 | 
			
		||||
    ins.clip2msg().await;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										42
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -1,21 +1,16 @@
 | 
			
		||||
extern crate log;
 | 
			
		||||
use clipboard_sync::ClipboardSync;
 | 
			
		||||
use std::net::IpAddr;
 | 
			
		||||
use trust_dns_resolver::{
 | 
			
		||||
    config::{ResolverConfig, ResolverOpts},
 | 
			
		||||
    Resolver,
 | 
			
		||||
};
 | 
			
		||||
use tokio::sync::{Mutex};
 | 
			
		||||
use clipboard_sync::{ClipboardSync, Character};
 | 
			
		||||
// use std::net::IpAddr;
 | 
			
		||||
// use trust_dns_resolver::{
 | 
			
		||||
//     config::{ResolverConfig, ResolverOpts},
 | 
			
		||||
//     Resolver,
 | 
			
		||||
// };
 | 
			
		||||
use tokio::sync::Mutex;
 | 
			
		||||
use std::sync::Arc;
 | 
			
		||||
use clap::{App, Arg, ArgGroup};
 | 
			
		||||
use clap::{App, Arg};
 | 
			
		||||
 | 
			
		||||
// const SERVER:&str = "172.19.36.79";
 | 
			
		||||
const SERVER:&str = "127.0.0.1:5000";
 | 
			
		||||
 | 
			
		||||
enum Character {
 | 
			
		||||
    Producer,
 | 
			
		||||
    Consumer,
 | 
			
		||||
}
 | 
			
		||||
const SERVER:&str = "192.168.0.116:5000";
 | 
			
		||||
 | 
			
		||||
fn param_parser() -> (Character, String) {
 | 
			
		||||
    let mut character = Character::Consumer;
 | 
			
		||||
@@ -61,11 +56,11 @@ fn param_parser() -> (Character, String) {
 | 
			
		||||
    (character, info_file.to_string())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async fn producer(info: &str) {
 | 
			
		||||
    let mut ins: ClipboardSync = match ClipboardSync::new(SERVER, &info)  {
 | 
			
		||||
async fn start(info: &str, c:&Character) {
 | 
			
		||||
    let mut ins: ClipboardSync = match ClipboardSync::new(SERVER, &info, &c)  {
 | 
			
		||||
        Ok(ins) => ins,
 | 
			
		||||
        Err(e) => {
 | 
			
		||||
            log::error!("create syns instance fail: {}", e);
 | 
			
		||||
            log::error!("create clipboard sync instance fail: {}", e);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
@@ -81,10 +76,6 @@ async fn producer(info: &str) {
 | 
			
		||||
    let _ = handle.await;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async fn consumer(_info: &str) {
 | 
			
		||||
    log::warn!("TODO: support Producer in the feature")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::main]
 | 
			
		||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
 | 
			
		||||
    env_logger::init();
 | 
			
		||||
@@ -107,13 +98,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
 | 
			
		||||
    //     }
 | 
			
		||||
    // }
 | 
			
		||||
    let (character, info) = param_parser();
 | 
			
		||||
    match character{
 | 
			
		||||
        Character::Producer => {
 | 
			
		||||
            producer(&info).await;
 | 
			
		||||
        }
 | 
			
		||||
        Character::Consumer => {
 | 
			
		||||
            consumer(&info).await;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    start(&info, &character).await;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,7 @@ pub fn get_foredround_window_rect() -> Option<(i32, i32, i32, i32)> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn get_foredround_window_name() -> String {
 | 
			
		||||
    let mut name = String::new();
 | 
			
		||||
    let full_path;
 | 
			
		||||
    unsafe {
 | 
			
		||||
        let foreground_window = GetForegroundWindow();
 | 
			
		||||
 | 
			
		||||
@@ -71,11 +71,11 @@ pub fn get_foredround_window_name() -> String {
 | 
			
		||||
        // let mut class_name: [u16; 256] = [0; 256];
 | 
			
		||||
        // GetClassNameW(foreground_window, class_name.as_mut_ptr(), 256);
 | 
			
		||||
 | 
			
		||||
        name = String::from_utf16_lossy(&image_name);
 | 
			
		||||
        full_path = String::from_utf16_lossy(&image_name);
 | 
			
		||||
        // let mut class_name_str = OsString::from_wide(&class_name);
 | 
			
		||||
        // log::info!("Class Name: {}", class_name_str.to_string_lossy().to_string());
 | 
			
		||||
    }
 | 
			
		||||
    let name = name.split('\\').last().unwrap().trim_end_matches('\0').to_string();
 | 
			
		||||
    let name = full_path.split('\\').last().unwrap().trim_end_matches('\0').to_string();
 | 
			
		||||
    //let name = path.file_name().unwrap().to_string_lossy().to_string();
 | 
			
		||||
    // println!("Current Proc Name: [{}]", name);
 | 
			
		||||
    name
 | 
			
		||||
@@ -93,7 +93,7 @@ fn test_screen_size() {
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_get_foredround_window_rect() {
 | 
			
		||||
    // env_logger::init();
 | 
			
		||||
    let (x, y, width, height) = get_foredround_window_rect().unwrap();
 | 
			
		||||
    let (_x, _y, width, height) = get_foredround_window_rect().unwrap();
 | 
			
		||||
    // assert!(x >= 0);
 | 
			
		||||
    // assert!(y >= 0);
 | 
			
		||||
    assert!(width > 0);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user