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