1pub mod pispas_server {
2 use std::net::{TcpListener, TcpStream};
3 use std::io::{Write};
4 #[cfg(not(target_os = "windows"))]
5
6 use {
7 users::{get_user_by_uid},
8 users::os::unix::UserExt,
9 nix::sys::signal::{self, Signal},
10 nix::unistd::Pid,
11 };
12
13
14
15 const DEFAULT_CICLES_TO_WAIT_IN_MS: u64 = 500;
16 use anyhow::anyhow;
17 use std::collections::HashMap;
18 use std::thread;
19
20 use easy_trace::instruments::tracing::{error, info, warn};
21 use easy_trace::prelude::debug;
22 use parking_lot::RwLock;
23 use sharing::service::{Action, DriverStatus};
24 use std::io::Read;
25
26 use std::sync::atomic::{AtomicBool, Ordering};
27 use std::sync::Arc;
28 use std::thread::sleep;
29 use std::time::Duration;
30 #[cfg(target_os = "windows")]
31 use {
32 std::os::windows::ffi::OsStrExt,
33 winapi::um::{
34 errhandlingapi::GetLastError,
35 fileapi::CreateFileW,
36 handleapi::CloseHandle,
37 handleapi::DuplicateHandle,
38 minwinbase::STILL_ACTIVE,
39 processthreadsapi::GetCurrentProcess,
40 processthreadsapi::{GetExitCodeProcess, TerminateProcess},
41 winnt::{DUPLICATE_SAME_ACCESS, HANDLE},
42 winnt::{FILE_SHARE_READ, FILE_SHARE_WRITE},
43 winnt::{GENERIC_READ, GENERIC_WRITE},
44 }
45 };
46
47
48 pub type CancelToken = Arc<AtomicBool>;#[derive(Debug)]
50 pub struct HandlePair {
51 #[cfg(windows)]
52 pub original: HANDLE, #[cfg(windows)]
54 pub duplicated: Option<HANDLE>, #[cfg(unix)]
57 pub _original: std::fs::File, #[cfg(unix)]
59 pub duplicated: Option<i32>, #[cfg(unix)]
62 pub file_path: String, }
64
65
66 #[derive(Debug, Clone)]
67 pub struct MyHandler {
68 #[cfg(windows)]
69 pub handle: HANDLE,
70 #[cfg(unix)]
71 pub pid: u32,
72 #[cfg(unix)]
73 process_dead: Arc<std::sync::atomic::AtomicBool>,
74 }
75 unsafe impl Send for MyHandler {}
76
77 unsafe impl Sync for MyHandler {}
78 #[cfg(unix)]
79 impl MyHandler {
80 pub fn new(pid: u32) -> Self {
81 Self {
82 pid,
83 process_dead: Arc::new(AtomicBool::new(false)),
84 }
85 }
86
87 pub fn _get_pid(&self) -> u32 {
88 self.pid
89 }
90
91 pub fn try_wait(&self) -> sharing::PisPasResult<Option<i32>> {
92 if self.process_dead.load(Ordering::Relaxed) {
93 return Ok(Some(0));
94 }
95
96 let pid = Pid::from_raw(self.pid as i32);
97
98 match signal::kill(pid, None) {
99 Ok(_) => {
100 Ok(None)
102 }
103 Err(nix::errno::Errno::ESRCH) => {
104 self.process_dead.store(true, Ordering::Relaxed);
106 tracing::info!("Process {} has terminated", self.pid);
107 Ok(Some(0))
108 }
109 Err(e) => {
110 tracing::warn!("Error checking process {}: {} - assuming alive", self.pid, e);
112 Ok(None)
113 }
114 }
115 }
116
117 pub fn kill(&self) -> sharing::PisPasResult<()> {
118 let pid = Pid::from_raw(self.pid as i32);
119
120 match signal::kill(pid, None) {
122 Ok(_) => {
123 match signal::kill(pid, Signal::SIGTERM) {
125 Ok(_) => {
126 tracing::info!("Sent SIGTERM to process {}", self.pid);
127 std::thread::sleep(Duration::from_millis(1000));
128
129 match signal::kill(pid, None) {
131 Ok(_) => {
132 match signal::kill(pid, Signal::SIGKILL) {
134 Ok(_) => {
135 tracing::info!("Sent SIGKILL to process {}", self.pid);
136 self.process_dead.store(true, Ordering::Relaxed);
137 Ok(())
138 }
139 Err(e) => {
140 tracing::error!("Failed to kill process {}: {}", self.pid, e);
141 Err(anyhow!("Failed to kill process {}: {}", self.pid, e))
142 }
143 }
144 }
145 Err(_) => {
146 tracing::info!("Process {} terminated gracefully with SIGTERM", self.pid);
148 self.process_dead.store(true, Ordering::Relaxed);
149 Ok(())
150 }
151 }
152 }
153 Err(e) => {
154 tracing::error!("Failed to send SIGTERM to process {}: {}", self.pid, e);
155 Err(anyhow!("Failed to send SIGTERM to process {}: {}", self.pid, e))
156 }
157 }
158 }
159 Err(nix::errno::Errno::ESRCH) => {
160 tracing::info!("Process {} not found (already dead)", self.pid);
162 self.process_dead.store(true, Ordering::Relaxed);
163 Ok(())
164 }
165 Err(e) => {
166 tracing::error!("Error accessing process {}: {}", self.pid, e);
167 Err(anyhow!("Error accessing process {}: {}", self.pid, e))
168 }
169 }
170 }
171
172 pub fn _is_alive(&self) -> sharing::PisPasResult<bool> {
173 if self.process_dead.load(Ordering::Relaxed) {
174 return Ok(false);
175 }
176
177 let pid = Pid::from_raw(self.pid as i32);
178 info!("Trying to kill pid {}", self.pid);
179 match signal::kill(pid, None) {
180 Ok(_) => Ok(true),
181 Err(nix::errno::Errno::ESRCH) => {
182 self.process_dead.store(true, Ordering::Relaxed);
183 Ok(false)
184 }
185 Err(e) => {
186 tracing::warn!("Error checking if process {} is alive: {}", self.pid, e);
187 Ok(true)
189 }
190 }
191 }
192 }
193 #[cfg(windows)]
194 impl MyHandler {
195 pub fn new(handle: HANDLE) -> Self {
196 Self { handle }
197 }
198 pub fn get_handle(&self) -> HANDLE {
199 self.handle
200 }
201 }
202 impl Clone for HandlePair {
203 fn clone(&self) -> Self {
204 #[cfg(windows)]
205 {
206 Self {
207 original: self.original,
208 duplicated: self.duplicated,
209 }
210 }
211
212 #[cfg(unix)]
213 {
214 match std::fs::File::open(&self.file_path) {
217 Ok(file) => Self {
218 _original: file,
219 duplicated: self.duplicated,
220 file_path: self.file_path.clone(),
221 },
222 Err(_) => {
223 let temp_file = std::fs::File::create("/tmp/pispas_clone_dummy")
225 .unwrap_or_else(|_| panic!("Failed to create dummy file"));
226 Self {
227 _original: temp_file,
228 duplicated: self.duplicated,
229 file_path: self.file_path.clone(),
230 }
231 }
232 }
233 }
234 }
235 }
236
237 unsafe impl Send for HandlePair {}
240 unsafe impl Sync for HandlePair {}
241
242 impl HandlePair {
243 #[cfg(windows)]
244 pub fn new(original: HANDLE, duplicated: Option<HANDLE>) -> Self {
245 Self {
246 original,
247 duplicated,
248 }
249 }
250
251 #[cfg(unix)]
252 pub fn new_unix(original: std::fs::File, file_path: String) -> Self {
253 Self {
254 _original: original,
255 duplicated: None,
256 file_path,
257 }
258 }
259
260 #[cfg(windows)]
261 pub fn _get_handle(&self) -> HANDLE {
262 self.original
263 }
264
265
266 #[cfg(windows)]
267 pub fn get_duplicated(&self) -> HANDLE {
268 self.duplicated.unwrap_or(std::ptr::null_mut())
269 }
270
271 #[cfg(unix)]
272 pub fn get_duplicated(&self) -> i32 {
273 self.duplicated.unwrap_or(-1)
274 }
275
276 #[cfg(windows)]
277 pub fn has_original(&self) -> bool {
278 !self.original.is_null()
279 }
280
281 #[cfg(unix)]
282 pub fn has_original(&self) -> bool {
283 true }
285
286 #[cfg(windows)]
287 pub fn is_valid(&self) -> bool {
288 !self.original.is_null()
289 && self.duplicated.is_some()
290 && self.get_duplicated() != std::ptr::null_mut()
291 }
292
293 #[cfg(unix)]
294 pub fn is_valid(&self) -> bool {
295 self.duplicated.is_some() && self.get_duplicated() != -1
296 }
297
298 #[cfg(windows)]
299 pub fn close_all(&self) {
300 unsafe {
301 if !self.original.is_null() {
302 CloseHandle(self.original);
303 }
304 if let Some(dup_handle) = self.duplicated {
305 if dup_handle != std::ptr::null_mut() {
306 CloseHandle(dup_handle);
307 }
308 }
309 }
310 }
311
312 pub fn close_duplicated(&self) {
313 #[cfg(windows)]
314 {
315 if let Some(dup_handle) = self.duplicated {
316 if dup_handle != std::ptr::null_mut() {
317 unsafe {
318 CloseHandle(dup_handle);
319 }
320 }
321 }
322 }
323
324 #[cfg(unix)]
325 {
326 if let Some(fd) = self.duplicated {
328 if fd != -1 {
329 unsafe {
330 libc::close(fd);
331 }
332 }
333 }
334 }
335 }
336
337
338 #[cfg(unix)]
345 pub fn close_all(&self) {
346 if let Some(fd) = self.duplicated {
349 if fd != -1 {
350 unsafe {
351 libc::close(fd);
352 }
353 }
354 }
355 }
356 }
357
358 #[derive(Debug)]
359 pub struct Server {
360 process: Option<MyHandler>,
361 tray_status: Arc<RwLock<DriverStatus>>,
362 subcribe_vector: Vec<Arc<RwLock<TcpStream>>>,
363 started: bool,
364 last_status_send: Arc<RwLock<String>>,
365 map_files: Arc<RwLock<HashMap<String, Option<HandlePair>>>>,
366 }
367
368 impl Server {
369 pub fn new() -> Self {
370 Self {
371 process: None,
372 tray_status: Arc::new(RwLock::new(DriverStatus::Launched)),
373 subcribe_vector: Vec::new(),
374 started: false,
375 last_status_send: Arc::new(RwLock::new(String::new())),
376 map_files: Arc::new(RwLock::new(HashMap::new())),
377 }
378 }
379
380 #[cfg(unix)]
381 fn create_or_open_protected_file(
382 &mut self,
383 file_path: &str,
384 ) -> sharing::PisPasResult<(std::fs::File, i32)> {
385 use std::fs::OpenOptions;
386 use std::os::unix::io::{AsRawFd};
387
388 info!("Creating/opening protected file (Unix): {}", file_path);
389
390 if let Some(parent) = std::path::Path::new(file_path).parent() {
392 std::fs::create_dir_all(parent)
393 .map_err(|e| anyhow!("Failed to create directory: {}", e))?;
394 }
395
396 if let Err(e) = self.verify_and_restore_from_backup(file_path) {
397 warn!("Failed to verify/restore backup for {}: {}", file_path, e);
398 }
399
400
401 let original_file = OpenOptions::new()
403 .create(true)
404 .read(true)
405 .write(true)
406 .open(file_path)
407 .map_err(|e| anyhow!("Failed to open file: {}", e))?;
408
409 let original_fd = original_file.as_raw_fd();
411 let duplicated_fd = unsafe { libc::dup(original_fd) };
412
413 if duplicated_fd == -1 {
414 return Err(anyhow!("Failed to duplicate file descriptor"));
415 }
416
417 info!(
418 "File opened with protection (Unix): {}, original_fd={}, duplicated_fd={}",
419 file_path, original_fd, duplicated_fd
420 );
421
422 Ok((original_file, duplicated_fd))
423 }
424 #[cfg(target_os = "windows")]
425
426 fn create_or_open_protected_file(
430 &mut self,
431 file_path: &str,
432 target_process: HANDLE,
433 ) -> sharing::PisPasResult<(HANDLE, HANDLE)> {
434 info!(
435 "Creating/opening protected file: {}, target process: {:?}",
436 file_path, target_process
437 );
438
439
440 if let Some(parent) = std::path::Path::new(file_path).parent() {
442 std::fs::create_dir_all(parent)
443 .map_err(|e| anyhow!("Failed to create directory: {}", e))?;
444 }
445
446
447 if let Err(e) = self.verify_and_restore_from_backup(file_path) {
448 warn!("Failed to verify/restore backup for {}: {}", file_path, e);
449 }
450
451 let wide_path: Vec<u16> = std::ffi::OsStr::new(file_path)
453 .encode_wide()
454 .chain(std::iter::once(0))
455 .collect();
456
457 let original_handle = unsafe {
458 CreateFileW(
459 wide_path.as_ptr(),
460 GENERIC_READ | GENERIC_WRITE,
461 FILE_SHARE_READ | FILE_SHARE_WRITE,
462 std::ptr::null_mut(),
463 winapi::um::fileapi::OPEN_ALWAYS, 0,
465 std::ptr::null_mut(),
466 )
467 };
468
469 if original_handle == winapi::um::handleapi::INVALID_HANDLE_VALUE {
470 let error_code = unsafe { GetLastError() };
471 return Err(anyhow!(
472 "Failed to open file with protection: error code {}",
473 error_code
474 ));
475 }
476
477 info!("File opened with delete protection: {}", file_path);
478
479 let mut duplicated_handle: HANDLE = std::ptr::null_mut();
481 let current_process = unsafe { GetCurrentProcess() };
482
483 let result = unsafe {
484 DuplicateHandle(
485 current_process,
486 original_handle,
487 target_process,
488 &mut duplicated_handle,
489 0,
490 1,
491 DUPLICATE_SAME_ACCESS,
492 )
493 };
494
495 if result == 0 {
496 let error_code = unsafe { GetLastError() };
497 unsafe { CloseHandle(original_handle) };
498 return Err(anyhow!(
499 "Failed to duplicate handle to target process: error code {}",
500 error_code
501 ));
502 }
503
504 info!(
505 "Handle duplicated with delete protection for {}: original={:?}, duplicated={:?}",
506 file_path, original_handle, duplicated_handle
507 );
508
509 Ok((original_handle, duplicated_handle))
510 }
511
512 #[cfg(target_os = "windows")]
513 fn close_duplicated_handle_from_map(&mut self) {
514 let mut map_files = self.map_files.write();
515 info!("Closing all duplicated handles in map maps {:?}", map_files);
516
517 for (path, handle_opt) in map_files.iter_mut() {
518 if let Some(safe_handle) = handle_opt {
519 safe_handle.close_duplicated();
520 safe_handle.duplicated = None;
521 info!("Closed duplicated handle for: {}", path);
522 }
523 }
524 }
525
526 fn handle_get_handle_request(
527 &mut self,
528 file_path: &str,
529 stream: Arc<RwLock<TcpStream>>,
530 ) -> sharing::PisPasResult<()> {
531 info!("Handling GET_HANDLE request for file: {}", file_path);
532
533 #[cfg(windows)]
535 let target_process = if let Some(process_pair) = &self.process {
536 process_pair.get_handle()
537 } else {
538 error!("No target process available for handle duplication");
539 let response = "HANDLE_ERROR:No target process available";
540 Self::write_stream(stream, response)?;
541 return Ok(());
542 };
543
544 {
546 let map_files = self.map_files.read();
547 if let Some(Some(handle_pair)) = map_files.get(file_path) {
548 if handle_pair.has_original() {
549 info!("Found existing original for: {}, re-duplicating", file_path);
550
551 #[cfg(windows)]
552 {
553 let mut new_duplicated: HANDLE = std::ptr::null_mut();
555 let result = unsafe {
556 DuplicateHandle(
557 GetCurrentProcess(),
558 handle_pair.original, target_process, &mut new_duplicated,
561 0,
562 1,
563 DUPLICATE_SAME_ACCESS,
564 )
565 };
566
567 if result != 0 {
568 drop(map_files); let mut map_files = self.map_files.write();
572 if let Some(Some(hp)) = map_files.get_mut(file_path) {
573 hp.duplicated = Some(new_duplicated);
574 }
575
576 let response = format!("HANDLE_OK:{}", new_duplicated as usize);
577 Self::write_stream(stream, &response)?;
578 info!("Re-duplicated handle successfully: {:?}", new_duplicated);
579 return Ok(());
580 } else {
581 let error_code = unsafe { GetLastError() };
582 error!("Failed to re-duplicate: error {}", error_code);
583 }
585 }
586
587 #[cfg(unix)]
588 {
589 use std::os::fd::AsRawFd;
590
591 let duplicated_fd = unsafe { libc::dup(handle_pair._original.as_raw_fd()) };
592 if duplicated_fd != -1 {
593 drop(map_files);
594
595 let mut map_files = self.map_files.write();
596 if let Some(Some(hp)) = map_files.get_mut(file_path) {
597 hp.duplicated = Some(duplicated_fd);
598 }
599
600 let response = format!("HANDLE_OK:{}", duplicated_fd);
601 Self::write_stream(stream, &response)?;
602 info!("Re-duplicated fd successfully: {}", duplicated_fd);
603 return Ok(());
604 }
605 }
606 }
607 }
608 }
609
610 #[cfg(windows)]
612 match self.create_or_open_protected_file(file_path, target_process) {
613 Ok((original_handle, duplicated_handle)) => {
614 let handle_pair = HandlePair::new(original_handle, Some(duplicated_handle));
615
616 {
617 let mut map_files = self.map_files.write();
618 map_files.insert(file_path.to_string(), Some(handle_pair));
619 }
620
621 let response = format!("HANDLE_OK:{}", duplicated_handle as usize);
622 Self::write_stream(stream, &response)?;
623 info!("Successfully created and mapped file handle for: {}", file_path);
624 info!(
625 "Original handle protected in service: {:?}",
626 original_handle
627 );
628 info!(
629 "Duplicated handle sent to target process: {:?}",
630 duplicated_handle
631 );
632 }
633 Err(e) => {
634 error!("Failed to create/open protected file {}: {}", file_path, e);
635 let mut map_files = self.map_files.write();
636 map_files.insert(file_path.to_string(), None);
637 let response = format!("HANDLE_ERROR:{}", e);
638 Self::write_stream(stream, &response)?;
639 }
640 }
641
642 #[cfg(unix)]
643 match self.create_or_open_protected_file(file_path) {
644 Ok((original_file, duplicated_fd)) => {
645 let handle_pair = HandlePair::new_unix(original_file, file_path.to_string());
646 let mut handle_pair = handle_pair;
648 handle_pair.duplicated = Some(duplicated_fd);
649
650 {
651 let mut map_files = self.map_files.write();
652 map_files.insert(file_path.to_string(), Some(handle_pair));
653 }
654
655 let response = format!("HANDLE_OK:{}", duplicated_fd);
656 Self::write_stream(stream, &response)?;
657 info!("Successfully created and mapped file descriptor for: {}", file_path);
658 }
659 Err(e) => {
660 error!("Failed to create/open protected file {}: {}", file_path, e);
661 let mut map_files = self.map_files.write();
662 map_files.insert(file_path.to_string(), None);
663 let response = format!("HANDLE_ERROR:{}", e);
664 Self::write_stream(stream, &response)?;
665 }
666 }
667
668 Ok(())
669 }
670
671
672 fn verify_and_restore_from_backup(&self, file_path: &str) -> sharing::PisPasResult<()> {
674 let backup_dir = sharing::paths::user_home();
675
676 if !backup_dir.exists() {
677 info!(
678 "Backup directory does not exist, creating: {}",
679 backup_dir.display()
680 );
681 match std::fs::create_dir_all(&backup_dir) {
682 Ok(_) => info!("Backup directory created: {}", backup_dir.display()),
683 Err(e) => {
684 error!("Failed to create backup directory: {}", e);
685 return Ok(()); }
687 }
688 }
689
690 info!("🔍 Checking backup directory: {}", backup_dir.display());
691
692 if let Some(filename) = std::path::Path::new(file_path).file_name() {
693 let backup_file_path = backup_dir.join(filename);
694
695 if !backup_file_path.exists() {
697 info!(
698 "✅ No backup found for: {} - will create new file",
699 filename.to_string_lossy()
700 );
701 return Ok(());
702 }
703
704 info!("🎯 Backup found: {}", backup_file_path.display());
705
706 if !std::path::Path::new(file_path).exists() {
708 info!(
709 "🔄 Original file missing, restoring from backup: {}",
710 file_path
711 );
712
713 if let Some(parent) = std::path::Path::new(file_path).parent() {
715 std::fs::create_dir_all(parent).map_err(|e| {
716 anyhow!("Failed to create directory for restore: {}", e)
717 })?;
718 }
719
720 std::fs::copy(&backup_file_path, file_path)
721 .map_err(|e| anyhow!("Failed to restore from backup: {}", e))?;
722
723 info!(
724 "✅ RESTORED: {} ← {}",
725 file_path,
726 backup_file_path.display()
727 );
728 return Ok(());
729 }
730
731 match self.files_are_different(file_path, &backup_file_path) {
733 Ok(true) => {
734 info!("Files differ, OVERWRITING with backup: {}", file_path);
735 std::fs::copy(&backup_file_path, file_path)
736 .map_err(|e| anyhow!("Failed to overwrite with backup: {}", e))?;
737 info!(
738 "OVERWRITTEN: {} ← {}",
739 file_path,
740 backup_file_path.display()
741 );
742 }
743 Ok(false) => {
744 info!("Files match, no restoration needed: {}", file_path);
745 }
746 Err(e) => {
747 warn!("Failed to compare files: {}", e);
748 }
749 }
750 } else {
751 warn!("Could not extract filename from path: {}", file_path);
752 }
753
754 Ok(())
755 }
756
757
758 pub fn cleanup_file_handles(&mut self) {
760 info!("Cleaning up all mapped file handles");
761 let mut map_files = self.map_files.write();
762
763 for (_, handle_opt) in map_files.iter() {
764 if let Some(safe_handle) = handle_opt {
765 safe_handle.close_all();
766 }
767 }
768
769 map_files.clear();
770 info!("All file handles cleaned up");
771 }
772
773 pub fn _list_mapped_files(&self) -> Vec<String> {
775 let map_files = self.map_files.read();
776 map_files.keys().cloned().collect()
777 }
778
779 pub fn _remove_file_mapping(&mut self, file_path: &str) -> sharing::PisPasResult<()> {
781 let mut map_files = self.map_files.write();
782
783 if let Some(handle_opt) = map_files.remove(file_path) {
784 if let Some(safe_handle) = handle_opt {
785 safe_handle.close_all();
786 }
787 info!("File mapping removed: {}", file_path);
788 } else {
789 warn!(
790 "Attempted to remove non-existent file mapping: {}",
791 file_path
792 );
793 }
794
795 Ok(())
796 }
797
798 fn write_stream(
799 stream: Arc<RwLock<TcpStream>>,
800 message: &str,
801 ) -> sharing::PisPasResult<()> {
802 match stream.write().write_all(message.as_bytes()) {
803 Ok(_) => {
804 info!("Message sent: {}", message);
805 Ok(())
806 }
807 Err(e) => {
808 error!("Error writing to stream: {:?}", e);
809 return Err(anyhow!("Error writing to stream: {:?}", e));
810 }
811 }
812 }
813
814 pub fn change_status(&mut self, status: DriverStatus) {
815 info!("Attempting to change status to: {:?}", status);
816
817 let old_status = {
818 let current_status = self.tray_status.read();
819 info!("Current status: {:?}", *current_status);
820 current_status.clone()
821 };
822
823 {
824 let mut tray_status = self.tray_status.write();
825 *tray_status = status.clone();
826 info!("Status successfully changed to: {:?}", *tray_status);
827 }
828
829 if old_status != status {
831 self.notify_subscriber(&status.to_string());
832 }
833 }
834
835 #[cfg(unix)]
836 fn launch_process(&mut self, _: bool) -> sharing::PisPasResult<DriverStatus> {
837 match sharing::natives::api::get_first_logged_user() {
838 Ok((username, uid)) => {
839 if let Some(user) = get_user_by_uid(uid) {
840 let tray_string = format!(
841 "{}/.config/pispas/{}",
842 user.home_dir().display(),
843 sharing::PRINT_SERVICE
844 );
845 info!("Launching tray icon for user: {} at path: {}", username, tray_string);
846 match sharing::natives::api::run_in_all_sessions(&tray_string, "", Some(&username), Some(uid)) {
847 Ok(pid) => {
848 self.change_status(DriverStatus::Running);
849 self.process = Some(MyHandler::new(pid));
850 self.started = true;
851 info!("Tray icon launched for user: {} with PID: {}", username, pid);
852 }
853 Err(err) => {
854 self.change_status(DriverStatus::Warning);
855 self.process = None;
856 error!("Error launching tray icon: {} for user {}", err, username);
857 }
858 }
859 }
860 }
861 Err(e) => {
862 self.change_status(DriverStatus::Warning);
863 self.process = None;
864 error!("Failed to get first logged user: {}", e);
865 }
866 }
867 Ok(self.tray_status.read().clone())
868 }
869 #[cfg(target_os = "windows")]
870 fn launch_process(&mut self, launch_first: bool) -> sharing::PisPasResult<DriverStatus> {
871 info!(
872 "Launching Print service current thread_id {:?}",
873 thread::current().id()
874 );
875 let print_service = sharing::paths::print_service_path().display().to_string();
876
877 let cmd = format!("\"{}\"", print_service);
878 info!("Command to run: {}", cmd);
879
880 match sharing::natives::api::run_in_all_sessions(
881 &print_service,
882 "",
883 false,
884 launch_first,
885 ) {
886 Ok(proc) => {
887 if let Some(handler) = proc {
888 let handler = MyHandler::new(handler);
889 info!("Handle: {:?}", handler.get_handle());
890 self.change_status(DriverStatus::Running);
891 self.process = Some(handler);
892 self.started = true;
893 info!("PrintService launched successfully");
894 } else {
895 error!("Error launching PrintService: None");
896 }
897 }
898 Err(e) => {
899 self.change_status(DriverStatus::Warning);
900 self.process = None;
901 return Err(anyhow!("Error launching Pispas Service: {}", e));
902 }
903 }
904 Ok(self.tray_status.read().clone())
905 }
906 #[cfg(target_os = "windows")]
907 pub fn stop_process(&mut self) -> sharing::PisPasResult<DriverStatus> {
908 if let Some(proc_handler) = self.process.as_mut() {
909 info!(
910 "Stopping Print service current thread_id {:?}",
911 thread::current().id()
912 );
913 let result = unsafe { TerminateProcess(proc_handler.get_handle(), 1) }; if result != 0 {
915 info!("PrintService stopped");
916 unsafe { CloseHandle(proc_handler.get_handle()) };
917 self.change_status(DriverStatus::Stopped);
918 self.process = None;
919 self.started = false;
920
921 } else {
923 let error_code = unsafe { GetLastError() };
924 self.change_status(DriverStatus::Warning);
925 return Err(anyhow!("Error stopping Pispas Service: {}", error_code));
926 }
927 sharing::proc::kill_process_by_name(sharing::ORDER_KITCHEN);
928 } else {
929 warn!("Stop request for non running service");
930 }
931 Ok(self.tray_status.read().clone())
932 }
933 #[cfg(unix)]
934 fn stop_process(&mut self) -> sharing::PisPasResult<DriverStatus> {
935 if let Some(proc) = self.process.as_mut() {
936 debug!("Stopping PispasModules current thread_id {:?}", std::thread::current().id());
937 match proc.kill() {
938 Ok(_) => {
939 debug!("PispasModules stopped");
940 self.process = None;
941 self.change_status(DriverStatus::Stopped);
942 }
943 Err(e) => {
944 warn!("Error stopping web-driver: {} (process might already be dead)", e);
945 self.process = None;
946 self.change_status(DriverStatus::Stopped);
947 }
948 }
949 } else {
950 warn!("Stop request for non running service");
951 }
952 kill_process_by_name(sharing::PRINT_SERVICE);
954 Ok(self.tray_status.read().clone())
955 }
956
957 fn handle_close_handle_request(
959 &mut self,
960 file_path: &str,
961 stream: Arc<RwLock<TcpStream>>,
962 ) -> sharing::PisPasResult<()> {
963 info!("Handling CLOSE_HANDLE request for file: {}", file_path);
964
965 let mut map_files = self.map_files.write();
966
967 if let Some(handle_opt) = map_files.get(file_path) {
968 if let Some(safe_handle) = handle_opt {
969 if safe_handle.has_original() {
970 info!("Closing handle for file: {}", file_path);
971 safe_handle.close_all();
972
973 map_files.remove(file_path);
975
976 let response = "HANDLE_CLOSED:OK";
978 Self::write_stream(stream, response)?;
979 info!("Successfully closed and removed handle for: {}", file_path);
980 } else {
981 map_files.remove(file_path);
983 let response = "HANDLE_CLOSED:INVALID";
984 Self::write_stream(stream, response)?;
985 info!("Removed invalid handle for: {}", file_path);
986 }
987 } else {
988 map_files.remove(file_path);
990 let response = "HANDLE_CLOSED:NOT_FOUND";
991 Self::write_stream(stream, response)?;
992 info!("Removed failed handle entry for: {}", file_path);
993 }
994 } else {
995 let response = "HANDLE_CLOSED:NOT_FOUND";
997 Self::write_stream(stream, response)?;
998 warn!("Attempted to close non-existent handle for: {}", file_path);
999 }
1000
1001 Ok(())
1002 }
1003 fn process_message(
1004 pispas_service: Arc<RwLock<Server>>,
1005 message: &str,
1006 stream: Arc<RwLock<TcpStream>>,
1007 needs_close: CancelToken,
1008 ) -> sharing::PisPasResult<()> {
1009 info!("Message received: {}", message);
1010 let action: Action = message.into();
1011 info!("Action: {:?}", action.to_string());
1012 if message == Action::Subscribe.to_string() {
1013 pispas_service.write().subcribe_vector.push(stream.clone());
1014 info!(
1015 "Subscribed new client, total: {}",
1016 pispas_service.read().subcribe_vector.len()
1017 );
1018 }
1019 let status = pispas_service.read().tray_status.read().clone();
1020 if message == Action::Restart.to_string() {
1021 if status == DriverStatus::Running || status == DriverStatus::Warning {
1022 info!(
1023 "Restart stream request, change tray status to Stopped == {:?}",
1024 status
1025 );
1026 pispas_service.write().change_status(DriverStatus::Restart);
1027 } else if status == DriverStatus::Stopped {
1031 pispas_service.write().change_status(DriverStatus::Launched);
1032 }
1033 }
1034
1035 if message == Action::Stop.to_string() {
1036 pispas_service.write().change_status(DriverStatus::Stopped);
1037 info!(
1038 "Stop stream request, change tray status to Stopped == {:?}",
1039 DriverStatus::Stopped
1040 );
1041 }
1042
1043 if message == Action::Start.to_string() && status == DriverStatus::Stopped {
1044 pispas_service.write().change_status(DriverStatus::Launched);
1045 info!(
1046 "Start stream request, change tray status to Running == {:?}",
1047 DriverStatus::Launched
1048 );
1049 }
1050
1051 if message == Action::Update.to_string() {
1052 let rt = tokio::runtime::Runtime::new().unwrap();
1054 rt.block_on(updates::check_and_launch(&sharing::get_version()));
1055 }
1056 if message.starts_with("MessageBox:") {
1057 let msg = message.trim_start_matches("MessageBox:").trim();
1058 if !msg.is_empty() {
1059 pispas_service
1060 .write()
1061 .notify_subscriber(&DriverStatus::MessageBox(msg.to_string()).to_string());
1062 } else {
1063 info!("No message provided for MessageBox.");
1064 }
1065 }
1066 if let Action::GetHandle(file_path) = &action {
1068 let mut service = pispas_service.write();
1069 service.handle_get_handle_request(&file_path, stream.clone())?;
1070 needs_close.store(true, Ordering::Relaxed);
1071 return Ok(());
1072 }
1073 if let Action::CloseHandle(file_path) = &action {
1074 let mut service = pispas_service.write();
1075 service.handle_close_handle_request(&file_path, stream.clone())?;
1076 needs_close.store(true, Ordering::Relaxed);
1077 return Ok(());
1078 }
1079 if message == Action::Close.to_string() {
1080 let mut service = pispas_service.write();
1081
1082 if let Some(pos) = service
1083 .subcribe_vector
1084 .iter()
1085 .position(|s| Arc::ptr_eq(s, &stream))
1086 {
1087 service.subcribe_vector.remove(pos);
1088 info!(
1089 "Unsubscribed a client, total: {}",
1090 service.subcribe_vector.len()
1091 );
1092 }
1093 }
1094 let new_status = pispas_service.read().tray_status.read().clone();
1095 info!("Tray status changed to: {:?}", new_status);
1096 if message == Action::Subscribe.to_string() {
1097 match stream.write().set_nonblocking(true) {
1098 Ok(_) => {
1099 info!("Non blocking set");
1100 }
1101 Err(e) => {
1102 info!("Non blocking not available {:?}", e);
1103 }
1104 };
1105 Self::write_stream(stream, new_status.to_string().as_str())?;
1106 } else {
1107 info!("Close stream request");
1108 needs_close.store(true, Ordering::Relaxed);
1109 }
1110 Ok(())
1111 }
1112
1113 pub fn notify_subscriber(&mut self, message: &str) {
1114 if message == *self.last_status_send.read() {
1115 return;
1116 }
1117 let mut stream_remove = Vec::new();
1118 for (i, sub) in self.subcribe_vector.iter().enumerate() {
1119 match Self::write_stream(sub.clone(), message) {
1120 Ok(_) => {
1121 info!("Message to client subcribe sent: {}", message);
1122 if !message.starts_with("MessageBox:") {
1123 *self.last_status_send.write() = message.to_string();
1124 }
1125 }
1126 Err(e) => {
1127 stream_remove.push(i);
1128 error!("Error writing to stream: {:?}", e);
1129 }
1130 }
1131 }
1132 if !stream_remove.is_empty() {
1133 for &index in stream_remove.iter().rev() {
1134 self.subcribe_vector.remove(index);
1135 }
1136 }
1137 }
1138
1139 pub fn handle_message(
1140 pispas_service: Arc<RwLock<Server>>,
1141 stream: Arc<RwLock<TcpStream>>,
1142 stop: CancelToken,
1143 ) {
1144 let need_close = CancelToken::default();
1145 if let Err(e) = stream.write().set_nonblocking(true) {
1146 info!("Non blocking not available {:?}", e);
1147 };
1148 loop {
1149 sleep(Duration::from_millis(DEFAULT_CICLES_TO_WAIT_IN_MS));
1150 if need_close.load(Ordering::Relaxed) || stop.load(Ordering::Relaxed) {
1151 sleep(Duration::from_millis(DEFAULT_CICLES_TO_WAIT_IN_MS));
1152 info!("Terminate thread");
1153 break;
1154 }
1155
1156 let mut buffer = Vec::new(); loop {
1159 let mut partial_buffer = [0; 1024];
1160 match stream.write().read(&mut partial_buffer) {
1161 Ok(size) => {
1162 if size == 0 {
1163 sleep(Duration::from_millis(DEFAULT_CICLES_TO_WAIT_IN_MS)); continue;
1165 }
1166 buffer.extend_from_slice(&partial_buffer[..size]);
1167 if size < partial_buffer.len() {
1168 break; }
1170 }
1171 Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
1172 sleep(Duration::from_millis(DEFAULT_CICLES_TO_WAIT_IN_MS)); continue;
1175 }
1176 Err(e) => {
1177 error!("Failed to read from socket in dedicated thread: {}", e);
1178 break;
1179 }
1180 }
1181 }
1182
1183 let message = String::from_utf8_lossy(&buffer).to_string();
1184
1185 match Server::process_message(
1186 pispas_service.clone(),
1187 &message,
1188 stream.clone(),
1189 need_close.clone(),
1190 ) {
1191 Ok(_) => {}
1192 Err(e) => {
1193 error!("Error processing message: {:?}", e);
1194 }
1195 }
1196 info!("Message processed: {}", message);
1197 }
1198 }
1199
1200 fn watchdog(thread_service: Arc<RwLock<Server>>, thread_cancel: CancelToken) {
1201 thread::spawn(move || loop {
1203 if thread_cancel.load(Ordering::Relaxed) {
1204 info!("WATCHDOG: Terminate thread, stop requested");
1205 if let Err(e) = thread_service.write().on_service_stop() {
1206 error!("Failed to execute service stop cleanup: {}", e);
1207 }
1208 match thread_service.write().stop_process() {
1209 Ok(_) => {
1210 thread_service
1211 .write()
1212 .notify_subscriber(DriverStatus::Stopped.to_string().as_str());
1213 }
1214 Err(e) => {
1215 error!("Failed to stop process {}", e);
1216 }
1217 }
1218
1219 sharing::proc::kill_process_by_name(sharing::TRAY_ICON_NAME);
1220 return;
1221 }
1222
1223 match thread_service.write().check() {
1224 Ok(_) => {}
1225 Err(e) => {
1226 error!("Failed to check process {}", e);
1227 }
1228 }
1229 #[cfg(target_os = "windows")]
1230 {
1231 let thread_clone = thread_service.clone();
1232 Self::still_active_process(thread_clone.clone());
1233 }
1234
1235 sleep(Duration::from_millis(800));
1236 });
1237 }
1238
1239
1240 #[cfg(target_os = "windows")]
1241 fn still_active_process(thread_clone: Arc<RwLock<Server>>) {
1242 let proc_handler = {
1243 let guard = thread_clone.write();
1244 guard.process.clone()
1245 };
1246 if let Some(proc_handler) = proc_handler {
1247 let mut exit_code: u32 = 0;
1248 let ret = unsafe { GetExitCodeProcess(proc_handler.get_handle(), &mut exit_code) };
1249
1250 if ret == 0 {
1251 error!("Failed to get exit code of process");
1252 let error_code = unsafe { GetLastError() };
1253 error!("Error code: {}", error_code);
1254 let mut guard = thread_clone.write();
1255 guard.process = None;
1256 } else if exit_code != STILL_ACTIVE {
1257 let status = {
1259 let guard = thread_clone.read();
1260 let x = guard.tray_status.read().clone();
1261 x
1262 };
1263 if status == DriverStatus::Running || status == DriverStatus::Warning {
1264 let mut guard = thread_clone.write();
1266 guard.process = None;
1267 static EXIT_CODES_TO_IGNORE: &[u32] = &[3221226091, 3228369022, 1073807364];
1268
1269 if EXIT_CODES_TO_IGNORE.contains(&exit_code) {
1270 warn!("process exited with code {}, restarting but ignoring warning, changing status to Launched", exit_code);
1271 guard.change_status(DriverStatus::Launched);
1272 } else {
1273 error!("process exited, re*starting with exit_code {}", exit_code);
1274 guard.change_status(DriverStatus::Warning);
1275 }
1276 sleep(Duration::from_millis(1000)); } else if status != DriverStatus::Stopped {
1278 info!(
1279 "process exited, keeping stopped. Driver status: {:?}",
1280 status
1281 );
1282 }
1283 }
1284 }
1285 }
1286
1287 pub fn on_service_stop(&mut self) -> sharing::PisPasResult<()> {
1289 info!("Service stopping - backing up protected files");
1290
1291 let backup_dir = sharing::paths::user_home();
1293
1294 let map_files = self.map_files.read();
1295 let mut backup_count = 0;
1296 info!("Backing up files to: {}", backup_dir.display());
1297 for (original_path, handle_opt) in map_files.iter() {
1298 if let Some(safe_handle) = handle_opt {
1299 if safe_handle.is_valid() {
1300 #[cfg(windows)]
1301 {
1302 use winapi::um::fileapi::FlushFileBuffers;
1303 unsafe {
1304 FlushFileBuffers(safe_handle.original);
1305 }
1306 }
1307
1308 #[cfg(unix)]
1309 {
1310 use std::os::unix::io::AsRawFd;
1311 unsafe {
1312 libc::fsync(safe_handle._original.as_raw_fd());
1313 }
1314 }
1315 if let Some(filename) = std::path::Path::new(original_path).file_name() {
1316 let backup_file_path = backup_dir.join(filename);
1317
1318 match std::fs::copy(original_path, &backup_file_path) {
1319 Ok(_) => {
1320 info!(
1321 "Backed up: {} → {}",
1322 original_path,
1323 backup_file_path.display()
1324 );
1325 backup_count += 1;
1326 }
1327 Err(e) => {
1328 error!("Failed to backup {}: {}", original_path, e);
1329 }
1330 }
1331 }
1332 }
1333 }
1334 }
1335
1336 info!(
1337 "Backup completed: {} files backed up to {}",
1338 backup_count,
1339 backup_dir.display()
1340 );
1341 drop(map_files); self.cleanup_file_handles();
1343
1344 Ok(())
1345 }
1346
1347 fn files_are_different(
1349 &self,
1350 file1: &str,
1351 file2: &std::path::Path,
1352 ) -> sharing::PisPasResult<bool> {
1353 use std::fs;
1354
1355 let content1 =
1356 fs::read(file1).map_err(|e| anyhow!("Failed to read {}: {}", file1, e))?;
1357 let content2 = fs::read(file2)
1358 .map_err(|e| anyhow!("Failed to read {}: {}", file2.display(), e))?;
1359
1360 Ok(content1 != content2)
1361 }
1362
1363 fn start_server(
1364 listener: Arc<RwLock<TcpListener>>,
1365 stop_arc: CancelToken,
1366 pispas_service: Arc<RwLock<Server>>,
1367 ) {
1368 loop {
1369 sleep(Duration::from_millis(DEFAULT_CICLES_TO_WAIT_IN_MS));
1370 for connection in listener.write().incoming() {
1371 match connection {
1372 Ok(stream) => {
1373 info!("New connection");
1374 let stream_arc = Arc::new(RwLock::new(stream));
1375 let thread_stream = stream_arc.clone();
1376
1377 let thread_token = stop_arc.clone();
1378 let thread_service = pispas_service.clone();
1379 thread::spawn(move || {
1380 info!("New thread thread_id: {:?}", thread::current().id());
1381 Server::handle_message(
1382 thread_service.clone(),
1383 thread_stream,
1384 thread_token,
1385 );
1386 });
1387 }
1388 Err(_) => {
1389 sleep(Duration::from_millis(DEFAULT_CICLES_TO_WAIT_IN_MS)); if stop_arc.load(Ordering::Relaxed) {
1391 if let Err(e) = pispas_service.write().on_service_stop() {
1392 error!("Failed to execute service stop cleanup: {}", e);
1393 }
1394 info!("STOP KILL KILL server");
1395 return;
1396 }
1397 }
1398 }
1399 }
1400 }
1401 }
1402
1403 pub fn run_server(pispas_service: Arc<RwLock<Server>>, stop_arc: CancelToken) {
1404 let socket_name = sharing::CHANNEL_NAME;
1405
1406 if std::path::Path::new(socket_name).exists() {
1408 info!("Removing stale socket file: {}", socket_name);
1409 if let Err(e) = std::fs::remove_file(socket_name) {
1410 warn!("Failed to remove stale socket, trying anyway: {}", e);
1411 }
1412 }
1413
1414 let listener_result = TcpListener::bind(sharing::CHANNEL_NAME);
1415
1416 let listener = match listener_result {
1417 Ok(listener) => {
1418 info!("✅ Successfully bound to socket: {}", socket_name);
1419 listener
1420 }
1421 Err(e) => {
1422 error!("❌ Error binding to socket: {:?}", e);
1423 return;
1424 }
1425 };
1426
1427 let cleanup_socket_name = socket_name.to_string();
1429 let cleanup_stop_arc = stop_arc.clone();
1430
1431 thread::spawn(move || {
1432 while !cleanup_stop_arc.load(Ordering::Relaxed) {
1433 sleep(Duration::from_millis(3000));
1434 }
1435 info!("🧹 Cleaning up socket on shutdown: {}", cleanup_socket_name);
1436 let _ = std::fs::remove_file(&cleanup_socket_name);
1437 });
1438
1439 if let Err(error) = listener.set_nonblocking(true) {
1440 error!("Failed to set non-blocking: {:?}", error);
1441 }
1442 let thread_cancel = stop_arc.clone();
1443 let listener: Arc<RwLock<TcpListener>> = Arc::new(RwLock::new(listener));
1444 let thread_service = pispas_service.clone();
1445 updates::launch_thread(stop_arc.clone());
1446
1447 Server::watchdog(thread_service.clone(), thread_cancel.clone());
1448
1449 #[cfg(target_os = "macos")]
1450 thread::spawn(move || {
1451 info!("Waiting for user login to launch tray...");
1452
1453 loop {
1454 if let Ok((username, uid)) = sharing::natives::api::get_first_logged_user() {
1455 if let Some(user) = get_user_by_uid(uid) {
1456 let tray_string = format!(
1457 "{}/.config/pispas/{}",
1458 user.home_dir().display(),
1459 sharing::TRAY_ICON_NAME
1460 );
1461 info!("User {} logged in, launching tray", username);
1462 let _ = sharing::natives::api::run_in_all_sessions(&tray_string, "", Some(&username), Some(uid));
1463 break;
1464 }
1465 }
1466 sleep(Duration::from_secs(3));
1467 }
1468 });
1469
1470
1471 let tray_string = sharing::paths::tray_icon_path().display().to_string();
1472 #[cfg(target_os = "windows")]
1473 if let Err(err) =
1474 sharing::natives::api::run_in_all_sessions(&tray_string, "", true, false)
1475 {
1476 error!("Error launching tray icon: {} for all users", err);
1477 }
1478
1479 #[cfg(not(target_os = "windows"))]
1480 if let Err(err) =
1481 sharing::natives::api::run_in_all_sessions(&tray_string, "", None, None)
1482 {
1483 error!("Error launching tray icon: {} for all users", err);
1484 }
1485
1486 Server::start_server(listener.clone(), stop_arc.clone(), pispas_service.clone());
1487
1488 info!("🧹 Final cleanup of socket: {}", socket_name);
1490 let _ = std::fs::remove_file(socket_name);
1491 }
1492
1493 #[cfg(target_os = "macos")]
1494 pub fn check(&mut self) -> sharing::PisPasResult<()> {
1495 let status = self.tray_status.read().clone();
1496 if let Some(proc) = self.process.as_mut() {
1497 match proc.try_wait() {
1498 Ok(Some(exit_status)) => {
1499 if status == DriverStatus::Running
1500 || status == DriverStatus::Warning
1501 {
1502 tracing::warn!("Web driver process exited with status: {} restarting", exit_status);
1503 self.launch_process(false)?;
1504 self.change_status(DriverStatus::Warning);
1505 self.notify_subscriber(&DriverStatus::Warning.to_string().as_str());
1506 std::thread::sleep(Duration::from_secs(2));
1507
1508 } else {
1509 tracing::warn!("Web driver process exited with status: {} keep stopped", exit_status);
1510 }
1511 }
1512 Err(e) => {
1513 tracing::error!("Error checking web driver process: {} stopping", e);
1514 }
1515 Ok(None) => {
1516 if status == DriverStatus::Stopped {
1517 tracing::warn!("Web driver process running with status: {:?}", status);
1518 self.stop_process()?;
1519 self.notify_subscriber(&DriverStatus::Stopped.to_string().as_str())
1520 }
1521 if status == DriverStatus::Restart {
1522 warn!("Web driver process running with status: {:?}, restarting", status);
1523 self.stop_process()?;
1524 std::thread::sleep(Duration::from_secs(1));
1525 self.launch_process(false)?;
1526 self.change_status(DriverStatus::Running);
1527 self.notify_subscriber(&self.tray_status.clone().read().to_string().as_str());
1528 }
1529 }
1530 }
1531 }
1532 else{
1533 if status == DriverStatus::Running || status == DriverStatus::Launched {
1534 tracing::warn!("Web driver process launched with status: {:?}", status);
1535 self.launch_process(false)?;
1536 self.change_status(DriverStatus::Running);
1537 self.notify_subscriber(&self.tray_status.clone().read().to_string().as_str());
1538 }
1539 debug!("Web driver process is None, launching new process");
1540 debug!("status: {:?}", status);
1541 }
1542
1543 Ok(())
1544 }
1545
1546 #[cfg(target_os = "windows")]
1547 pub fn check(&mut self) -> sharing::PisPasResult<()> {
1548 let status = {
1549 let guard = self.tray_status.read();
1550 guard.clone()
1551 };
1552
1553 match self.process {
1554 Some(_) => {
1555 match status {
1556 DriverStatus::Stopped => {
1557 warn!("PrintService process stopped with status: {:?}", status);
1558 self.stop_process()?;
1559 self.close_duplicated_handle_from_map();
1560 self.notify_subscriber(&status.to_string());
1561 }
1562 DriverStatus::Launched => {
1563 self.change_status(DriverStatus::Running);
1564 }
1565 DriverStatus::Restart => {
1566 warn!("PrintService process restarted with status: {:?}", status);
1567 self.close_duplicated_handle_from_map();
1568 self.stop_process()?;
1569 sleep(Duration::from_millis(700));
1570 self.launch_process(false)?;
1571 sleep(Duration::from_millis(700));
1572 self.change_status(DriverStatus::Running);
1573 let new_status = {
1574 let guard = self.tray_status.read();
1575 guard.to_string()
1576 };
1577 self.notify_subscriber(&new_status);
1578 }
1579 _ => {} }
1581 }
1582 None => {
1583 match status {
1584 DriverStatus::Launched | DriverStatus::Running => {
1585 warn!("PrintService process launched with status: {:?}", status);
1586 let is_launched = !self.started;
1587 self.launch_process(is_launched)?;
1588 self.change_status(DriverStatus::Running);
1589 let new_status = {
1590 let guard = self.tray_status.read();
1591 guard.to_string()
1592 };
1593 self.notify_subscriber(&new_status);
1594 }
1595 DriverStatus::Warning => {
1596 warn!("PrintService process warning with status: {:?}", status);
1597 self.close_duplicated_handle_from_map();
1598 self.launch_process(false)?;
1599 self.change_status(DriverStatus::Warning);
1600 let new_status = {
1601 let guard = self.tray_status.read();
1602 guard.to_string()
1603 };
1604 self.notify_subscriber(&new_status);
1605 }
1606 DriverStatus::Stopped => {
1607 self.close_duplicated_handle_from_map();
1608 debug!("PrintService process stopped with status: {:?}", status);
1609 if self.started {
1610 self.change_status(DriverStatus::Stopped);
1611 self.notify_subscriber(&status.to_string());
1612 }
1613 }
1614 _ => {} }
1616 }
1617 }
1618 Ok(())
1619 }
1620 }
1621}
1622
1623pub use pispas_server::*;
1624