1 // Copyright © 2017 Mozilla Foundation
2 //
3 // This program is made available under an ISC-style license.  See the
4 // accompanying file LICENSE for details
5 
6 #![warn(unused_extern_crates)]
7 #![recursion_limit = "1024"]
8 #[macro_use]
9 extern crate error_chain;
10 #[macro_use]
11 extern crate log;
12 
13 pub mod codec;
14 #[allow(deprecated)]
15 pub mod errors;
16 pub mod messages;
17 pub mod shm;
18 
19 pub mod ipccore;
20 pub mod rpccore;
21 pub mod sys;
22 
23 pub use crate::messages::{ClientMessage, ServerMessage};
24 
25 #[cfg(unix)]
26 use std::os::unix::io::IntoRawFd;
27 #[cfg(windows)]
28 use std::os::windows::io::IntoRawHandle;
29 
30 // This must match the definition of
31 // ipc::FileDescriptor::PlatformHandleType in Gecko.
32 #[cfg(windows)]
33 pub type PlatformHandleType = std::os::windows::raw::HANDLE;
34 #[cfg(unix)]
35 pub type PlatformHandleType = libc::c_int;
36 
37 // This stands in for RawFd/RawHandle.
38 #[derive(Debug)]
39 pub struct PlatformHandle(PlatformHandleType);
40 
41 #[cfg(unix)]
42 pub const INVALID_HANDLE_VALUE: PlatformHandleType = -1isize as PlatformHandleType;
43 
44 #[cfg(windows)]
45 pub const INVALID_HANDLE_VALUE: PlatformHandleType = winapi::um::handleapi::INVALID_HANDLE_VALUE;
46 
47 #[cfg(unix)]
valid_handle(handle: PlatformHandleType) -> bool48 fn valid_handle(handle: PlatformHandleType) -> bool {
49     handle >= 0
50 }
51 
52 #[cfg(windows)]
valid_handle(handle: PlatformHandleType) -> bool53 fn valid_handle(handle: PlatformHandleType) -> bool {
54     handle != INVALID_HANDLE_VALUE && !handle.is_null()
55 }
56 
57 impl PlatformHandle {
new(raw: PlatformHandleType) -> PlatformHandle58     pub fn new(raw: PlatformHandleType) -> PlatformHandle {
59         assert!(valid_handle(raw));
60         PlatformHandle(raw)
61     }
62 
63     #[cfg(windows)]
from<T: IntoRawHandle>(from: T) -> PlatformHandle64     pub fn from<T: IntoRawHandle>(from: T) -> PlatformHandle {
65         PlatformHandle::new(from.into_raw_handle())
66     }
67 
68     #[cfg(unix)]
from<T: IntoRawFd>(from: T) -> PlatformHandle69     pub fn from<T: IntoRawFd>(from: T) -> PlatformHandle {
70         PlatformHandle::new(from.into_raw_fd())
71     }
72 
73     #[allow(clippy::missing_safety_doc)]
into_raw(self) -> PlatformHandleType74     pub unsafe fn into_raw(self) -> PlatformHandleType {
75         let handle = self.0;
76         std::mem::forget(self);
77         handle
78     }
79 
80     #[cfg(unix)]
duplicate(h: PlatformHandleType) -> Result<PlatformHandle, std::io::Error>81     pub fn duplicate(h: PlatformHandleType) -> Result<PlatformHandle, std::io::Error> {
82         unsafe {
83             let newfd = libc::dup(h);
84             if !valid_handle(newfd) {
85                 return Err(std::io::Error::last_os_error());
86             }
87             Ok(PlatformHandle::from(newfd))
88         }
89     }
90 
91     #[allow(clippy::missing_safety_doc)]
92     #[cfg(windows)]
duplicate(h: PlatformHandleType) -> Result<PlatformHandle, std::io::Error>93     pub unsafe fn duplicate(h: PlatformHandleType) -> Result<PlatformHandle, std::io::Error> {
94         let dup = duplicate_platform_handle(h, None)?;
95         Ok(PlatformHandle::new(dup))
96     }
97 }
98 
99 impl Drop for PlatformHandle {
drop(&mut self)100     fn drop(&mut self) {
101         unsafe { close_platform_handle(self.0) }
102     }
103 }
104 
105 #[cfg(unix)]
close_platform_handle(handle: PlatformHandleType)106 unsafe fn close_platform_handle(handle: PlatformHandleType) {
107     libc::close(handle);
108 }
109 
110 #[cfg(windows)]
close_platform_handle(handle: PlatformHandleType)111 unsafe fn close_platform_handle(handle: PlatformHandleType) {
112     winapi::um::handleapi::CloseHandle(handle);
113 }
114 
115 #[cfg(windows)]
116 use winapi::shared::minwindef::DWORD;
117 
118 // Duplicate `source_handle`.
119 // - If `target_pid` is `Some(...)`, `source_handle` is closed.
120 // - If `target_pid` is `None`, `source_handle` is not closed.
121 #[cfg(windows)]
duplicate_platform_handle( source_handle: PlatformHandleType, target_pid: Option<DWORD>, ) -> Result<PlatformHandleType, std::io::Error>122 pub(crate) unsafe fn duplicate_platform_handle(
123     source_handle: PlatformHandleType,
124     target_pid: Option<DWORD>,
125 ) -> Result<PlatformHandleType, std::io::Error> {
126     use winapi::shared::minwindef::FALSE;
127     use winapi::um::{handleapi, processthreadsapi, winnt};
128 
129     let source = processthreadsapi::GetCurrentProcess();
130     let (target, close_source) = if let Some(pid) = target_pid {
131         let target = processthreadsapi::OpenProcess(winnt::PROCESS_DUP_HANDLE, FALSE, pid);
132         if !valid_handle(target) {
133             return Err(std::io::Error::new(
134                 std::io::ErrorKind::Other,
135                 "invalid target process",
136             ));
137         }
138         (target, true)
139     } else {
140         (source, false)
141     };
142 
143     let mut target_handle = std::ptr::null_mut();
144     let mut options = winnt::DUPLICATE_SAME_ACCESS;
145     if close_source {
146         options |= winnt::DUPLICATE_CLOSE_SOURCE;
147     }
148     let ok = handleapi::DuplicateHandle(
149         source,
150         source_handle,
151         target,
152         &mut target_handle,
153         0,
154         FALSE,
155         options,
156     );
157     handleapi::CloseHandle(target);
158     if ok == FALSE {
159         return Err(std::io::Error::new(
160             std::io::ErrorKind::Other,
161             "DuplicateHandle failed",
162         ));
163     }
164     Ok(target_handle)
165 }
166 
167 #[cfg(windows)]
server_platform_init()168 pub fn server_platform_init() {
169     use winapi::shared::winerror;
170     use winapi::um::combaseapi;
171     use winapi::um::objbase;
172 
173     unsafe {
174         let r = combaseapi::CoInitializeEx(std::ptr::null_mut(), objbase::COINIT_MULTITHREADED);
175         assert!(winerror::SUCCEEDED(r));
176     }
177 }
178 
179 #[cfg(unix)]
server_platform_init()180 pub fn server_platform_init() {}
181