makepad_studio/file_system/
file_client_desktop.rs

1use {
2    crate::{
3        makepad_micro_serde::*,
4        makepad_platform::*,
5        makepad_file_protocol::{FileRequest, FileClientMessage},
6        makepad_file_server::{FileServerConnection, FileServer, FileSystemRoots},
7    },
8    std::{
9        //env,
10        io::{Read, Write},
11        net::{ TcpStream},
12        sync::mpsc::{self, Receiver, Sender, TryRecvError},
13        thread,
14    },
15};
16
17#[derive(Default)]
18pub struct FileClient {
19//    bind: Option<String>,
20    //path: String,
21    pub inner: Option<FileClientInner>
22}
23
24pub struct FileClientInner {
25    pub request_sender: Sender<FileRequest>,
26    pub message_signal: SignalToUI,
27    pub message_receiver: Receiver<FileClientMessage>,
28}
29
30impl FileClient {
31    pub fn init(&mut self, _cx:&mut Cx, roots:FileSystemRoots){
32        if self.inner.is_none() {
33            self.inner = Some(FileClientInner::new_with_local_server(roots))
34        }
35    }
36    
37        
38    pub fn load_file_tree(&mut self) {
39        self.send_request(FileRequest::LoadFileTree {with_data: false});
40    }
41        
42    pub fn load_snapshot_image(&mut self, root:&str, hash:&str) {
43        self.send_request(FileRequest::LoadSnapshotImage {root:root.to_string(), hash:hash.to_string()});
44    }
45        
46    pub fn send_request(&self, request: FileRequest) {
47        self.inner.as_ref().unwrap().request_sender.send(request).unwrap();
48    }
49    
50    pub fn request_sender(&mut self) -> impl FnMut(FileRequest) + '_ {
51        let request_sender = &self.inner.as_ref().unwrap().request_sender;
52        move | request | request_sender.send(request).unwrap()
53    }
54    
55    pub fn poll_messages(&self)->Vec<FileClientMessage> {
56        let mut messages = Vec::new();
57        let inner = self.inner.as_ref().unwrap();
58        loop {
59            match inner.message_receiver.try_recv() {
60                Ok(message) => messages.push(message),
61                Err(TryRecvError::Empty) => break,
62                _ => panic!(),
63            }
64        }
65        messages
66    }
67}
68
69impl FileClientInner {
70    pub fn new_with_local_server(roots:FileSystemRoots) -> Self {
71        let (request_sender, request_receiver) = mpsc::channel();
72        let message_signal = SignalToUI::new();
73        let (message_sender, message_receiver) = mpsc::channel();
74        
75        /*let mut root = "./".to_string();
76        for arg in std::env::args(){
77            if let Some(prefix) = arg.strip_prefix("--root="){
78                root = prefix.to_string();
79                break;
80            }
81        }
82
83        let base_path = env::current_dir().unwrap().join(root);
84        let final_path = base_path.join(subdir.split('/').collect::<PathBuf>());*/
85        
86        let mut server = FileServer::new(roots);
87        spawn_local_request_handler(
88            request_receiver,
89            server.connect(Box::new({
90                let message_sender = message_sender.clone();
91                let message_signal = message_signal.clone();
92                move | notification | {
93                    message_sender.send(FileClientMessage::Notification(notification)).unwrap();
94                    message_signal.set();
95                }
96            })),
97            message_signal.clone(),
98            message_sender,
99        );
100        //spawn_connection_listener(TcpListener::bind("127.0.0.1:0").unwrap(), server);
101        
102        Self {
103            request_sender,
104            message_signal,
105            message_receiver
106        }
107    }
108    
109    pub fn new_connect_remote(to_server: &str) -> Self {
110        let (request_sender, request_receiver) = mpsc::channel();
111        let message_signal = SignalToUI::new();
112        let (message_sender, message_receiver) = mpsc::channel();
113        
114        let stream = TcpStream::connect(to_server).unwrap();
115        spawn_request_sender(request_receiver, stream.try_clone().unwrap());
116        spawn_response_or_notification_receiver(stream, message_signal.clone(), message_sender,);
117        
118        Self {
119            request_sender,
120            message_signal,
121            message_receiver
122        }
123    }
124    
125}
126/*
127fn _spawn_connection_listener(listener: TcpListener, mut server: FileServer) {
128    thread::spawn(move || {
129        log!("Server listening on {}", listener.local_addr().unwrap());
130        for stream in listener.incoming() {
131            let stream = stream.unwrap();
132            log!("Incoming connection from {}", stream.peer_addr().unwrap());
133            let (action_sender, action_receiver) = mpsc::channel();
134            let _connection = server.connect(Box::new({
135                let action_sender = action_sender.clone();
136                move | notification | {
137                    action_sender.send(FileClientAction::Notification(notification)).unwrap();
138                }
139            }));
140            spawn_remote_request_handler(
141                connection,
142                stream.try_clone().unwrap(),
143                action_sender,
144            );
145            spawn_response_or_notification_sender(action_receiver, stream);
146        }
147    });
148}*/
149
150fn _spawn_remote_request_handler(
151    connection: FileServerConnection,
152    mut stream: TcpStream,
153    message_sender: Sender<FileClientMessage>,
154) {
155    thread::spawn(move || loop {
156        let mut len_bytes = [0; 4];
157        stream.read_exact(&mut len_bytes).unwrap();
158        let len = u32::from_be_bytes(len_bytes);
159        let mut request_bytes = vec![0; len as usize];
160        stream.read_exact(&mut request_bytes).unwrap();
161        
162        let request = DeBin::deserialize_bin(request_bytes.as_slice()).unwrap();
163        let response = connection.handle_request(request);
164        message_sender.send(FileClientMessage::Response(response)).unwrap();
165    });
166}
167
168fn _spawn_response_or_notification_sender(
169    message_receiver: Receiver<FileClientMessage>,
170    mut stream: TcpStream,
171) {
172    thread::spawn(move || loop {
173        let message = message_receiver.recv().unwrap();
174        let mut message_bytes = Vec::new();
175        
176        message.ser_bin(&mut message_bytes);
177        
178        let len_bytes = message_bytes.len().to_be_bytes();
179        stream.write_all(&len_bytes).unwrap();
180        stream.write_all(&message_bytes).unwrap();
181    });
182}
183
184fn spawn_request_sender(request_receiver: Receiver<FileRequest>, mut stream: TcpStream) {
185    thread::spawn(move || loop {
186        let request = request_receiver.recv().unwrap();
187        let mut request_bytes = Vec::new();
188        request.ser_bin(&mut request_bytes);
189        let len_bytes = request_bytes.len().to_be_bytes();
190        stream.write_all(&len_bytes).unwrap();
191        stream.write_all(&request_bytes).unwrap();
192    });
193}
194
195fn spawn_response_or_notification_receiver(
196    mut stream: TcpStream,
197    message_signal: SignalToUI,
198    message_sender: Sender<FileClientMessage>,
199) {
200    thread::spawn(move || loop {
201        let mut len_bytes = [0; 4];
202        stream.read_exact(&mut len_bytes).unwrap();
203        
204        let len = u32::from_be_bytes(len_bytes);
205        let mut action_bytes = vec![0; len as usize];
206        stream.read_exact(&mut action_bytes).unwrap();
207        let action = DeBin::deserialize_bin(action_bytes.as_slice()).unwrap();
208        message_sender.send(action).unwrap();
209        message_signal.set()
210    });
211}
212
213fn spawn_local_request_handler(
214    request_receiver: Receiver<FileRequest>,
215    connection: FileServerConnection,
216    action_signal: SignalToUI,
217    action_sender: Sender<FileClientMessage>,
218) {
219    thread::spawn(move || loop {
220        if let Ok(request) = request_receiver.recv(){
221            let response = connection.handle_request(request);
222            action_sender.send(FileClientMessage::Response(response)).unwrap();
223            action_signal.set()
224        }
225    });
226}