1extern "C" {
2 #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks")))]
3 #[cfg_attr(
4 any(
5 target_os = "linux",
6 target_os = "emscripten",
7 target_os = "fuchsia",
8 target_os = "l4re"
9 ),
10 link_name = "__errno_location"
11 )]
12 #[cfg_attr(
13 any(
14 target_os = "netbsd",
15 target_os = "openbsd",
16 target_os = "android",
17 target_os = "redox",
18 target_env = "newlib"
19 ),
20 link_name = "__errno"
21 )]
22 #[cfg_attr(
23 any(target_os = "solaris", target_os = "illumos"),
24 link_name = "___errno"
25 )]
26 #[cfg_attr(
27 any(
28 target_os = "macos",
29 target_os = "ios",
30 target_os = "freebsd",
31 target_os = "watchos"
32 ),
33 link_name = "__error"
34 )]
35 #[cfg_attr(target_os = "haiku", link_name = "_errnop")]
36 fn errno_location() -> *mut libc::c_int;
37}
38
39pub extern "C" fn reset_errno() {
40 set_errno(0)
41}
42
43pub extern "C" fn set_errno(errno: libc::c_int) {
44 unsafe { errno_location().write(errno) }
45}
46
47pub extern "C" fn set_non_blocking(socket: libc::c_int, on: bool) -> bool {
48 unsafe {
49 let flags = libc::fcntl(socket, libc::F_GETFL);
50 if flags < 0 {
51 return false;
52 }
53 libc::fcntl(
54 socket,
55 libc::F_SETFL,
56 if on {
57 flags | libc::O_NONBLOCK
58 } else {
59 flags & !libc::O_NONBLOCK
60 },
61 ) == 0
62 }
63}
64
65pub extern "C" fn is_blocking(socket: libc::c_int) -> bool {
66 !is_non_blocking(socket)
67}
68
69pub extern "C" fn is_non_blocking(socket: libc::c_int) -> bool {
70 unsafe {
71 let flags = libc::fcntl(socket, libc::F_GETFL);
72 if flags < 0 {
73 return false;
74 }
75 (flags & libc::O_NONBLOCK) != 0
76 }
77}
78
79#[macro_export]
81macro_rules! init_hook {
82 ( $symbol:literal ) => {{
83 once_cell::sync::Lazy::new(|| unsafe {
84 let symbol = std::ffi::CString::new(String::from($symbol)).expect(&String::from(
85 "can not transfer \"".to_owned() + $symbol + "\" to CString",
86 ));
87 let ptr = libc::dlsym(libc::RTLD_NEXT, symbol.as_ptr());
88 if ptr.is_null() {
89 panic!("system {} not found !", $symbol);
90 }
91 std::mem::transmute(ptr)
92 })
93 }};
94}
95
96#[macro_export]
97macro_rules! impl_simple_hook {
98 ( ($fn: expr) ( $socket:expr, $($arg: expr),* $(,)* ), $timeout:expr) => {{
99 let ns_time = ($timeout as Option<std::time::Duration>).map(|d|d.as_nanos() as u64).unwrap_or(u64::MAX);
100 let timeout_time = timer_utils::add_timeout_time(ns_time);
101 let _ = base_coroutine::EventLoop::round_robin_timeout_schedule(timeout_time);
102 unsafe {
103 let mut set: libc::sigset_t = std::mem::zeroed();
104 libc::sigaddset(&mut set, libc::SIGURG);
105 let mut oldset: libc::sigset_t = std::mem::zeroed();
106 libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut oldset);
107 let r = $fn($socket ,$($arg, )*);
108 libc::pthread_sigmask(libc::SIG_SETMASK, &oldset, std::ptr::null_mut());
109 r
110 }
111 }};
112}
113
114#[macro_export]
116macro_rules! impl_read_hook {
117 ( ($fn: expr) ( $socket:expr, $($arg: expr),* $(,)* ), $timeout:expr) => {{
118 let socket = $socket;
119 let blocking = $crate::unix::common::is_blocking(socket);
120 if blocking {
121 $crate::unix::common::set_non_blocking(socket, true);
122 }
123 let event_loop = base_coroutine::EventLoop::next();
124 let mut r;
125 loop {
126 unsafe {
127 let mut set: libc::sigset_t = std::mem::zeroed();
128 libc::sigaddset(&mut set, libc::SIGURG);
129 let mut oldset: libc::sigset_t = std::mem::zeroed();
130 libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut oldset);
131 r = $fn($socket ,$($arg, )*);
132 libc::pthread_sigmask(libc::SIG_SETMASK, &oldset, std::ptr::null_mut());
133 }
134 if r != -1 {
135 $crate::unix::common::reset_errno();
136 break;
137 }
138 let error_kind = std::io::Error::last_os_error().kind();
139 if error_kind == std::io::ErrorKind::WouldBlock {
140 if let Err(e) = event_loop.wait_read_event(socket, $timeout) {
142 match e.kind() {
143 std::io::ErrorKind::Interrupted => $crate::unix::common::reset_errno(),
145 _ => break,
146 }
147 }
148 } else if error_kind != std::io::ErrorKind::Interrupted {
149 break;
150 }
151 }
152 if blocking {
153 $crate::unix::common::set_non_blocking(socket, false);
154 }
155 r
156 }};
157}
158
159#[macro_export]
160macro_rules! impl_expected_read_hook {
161 ( ($fn: expr) ( $socket:expr, $buffer:expr, $length:expr ), $timeout:expr) => {{
162 let socket = $socket;
163 let blocking = $crate::unix::common::is_blocking(socket);
164 if blocking {
165 $crate::unix::common::set_non_blocking(socket, true);
166 }
167 let event_loop = base_coroutine::EventLoop::next();
168 let mut received = 0;
169 let mut r = 0;
170 while received < $length {
171 unsafe {
172 let mut set: libc::sigset_t = std::mem::zeroed();
173 libc::sigaddset(&mut set, libc::SIGURG);
174 let mut oldset: libc::sigset_t = std::mem::zeroed();
175 libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut oldset);
176 r = $fn(
177 $socket,
178 ($buffer as usize + received) as *mut libc::c_void,
179 $length - received
180 );
181 libc::pthread_sigmask(libc::SIG_SETMASK, &oldset, std::ptr::null_mut());
182 }
183 if r != -1 {
184 $crate::unix::common::reset_errno();
185 received += r as libc::size_t;
186 if received >= $length {
187 r = received as libc::ssize_t;
188 break;
189 }
190 if r == 0 {
191 break;
192 }
193 }
194 let error_kind = std::io::Error::last_os_error().kind();
195 if error_kind == std::io::ErrorKind::WouldBlock {
196 if let Err(e) = event_loop.wait_read_event(socket, $timeout) {
198 match e.kind() {
199 std::io::ErrorKind::Interrupted => $crate::unix::common::reset_errno(),
201 _ => break,
202 }
203 }
204 } else if error_kind != std::io::ErrorKind::Interrupted {
205 break;
206 }
207 }
208 if blocking {
209 $crate::unix::common::set_non_blocking(socket, false);
210 }
211 r
212 }};
213 ( ($fn: expr) ( $socket:expr, $buffer:expr, $length:expr, $($arg: expr),* $(,)* ), $timeout:expr) => {{
214 let socket = $socket;
215 let blocking = $crate::unix::common::is_blocking(socket);
216 if blocking {
217 $crate::unix::common::set_non_blocking(socket, true);
218 }
219 let event_loop = base_coroutine::EventLoop::next();
220 let mut received = 0;
221 let mut r = 0;
222 while received < $length {
223 unsafe {
224 let mut set: libc::sigset_t = std::mem::zeroed();
225 libc::sigaddset(&mut set, libc::SIGURG);
226 let mut oldset: libc::sigset_t = std::mem::zeroed();
227 libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut oldset);
228 r = $fn(
229 $socket,
230 ($buffer as usize + received) as *mut libc::c_void,
231 $length - received,
232 $($arg, )*
233 );
234 libc::pthread_sigmask(libc::SIG_SETMASK, &oldset, std::ptr::null_mut());
235 }
236 if r != -1 {
237 $crate::unix::common::reset_errno();
238 received += r as libc::size_t;
239 if received >= $length {
240 r = received as libc::ssize_t;
241 break;
242 }
243 if r == 0 {
244 break;
245 }
246 }
247 let error_kind = std::io::Error::last_os_error().kind();
248 if error_kind == std::io::ErrorKind::WouldBlock {
249 if let Err(e) = event_loop.wait_read_event(socket, $timeout) {
251 match e.kind() {
252 std::io::ErrorKind::Interrupted => $crate::unix::common::reset_errno(),
254 _ => break,
255 }
256 }
257 } else if error_kind != std::io::ErrorKind::Interrupted {
258 break;
259 }
260 }
261 if blocking {
262 $crate::unix::common::set_non_blocking(socket, false);
263 }
264 r
265 }};
266}
267
268#[macro_export]
270macro_rules! impl_write_hook {
271 ( ($fn: expr) ( $socket:expr, $($arg: expr),* $(,)* ), $timeout:expr ) => {{
272 let socket = $socket;
273 let blocking = $crate::unix::common::is_blocking(socket);
274 if blocking {
275 $crate::unix::common::set_non_blocking(socket, true);
276 }
277 let event_loop = base_coroutine::EventLoop::next();
278 let mut r;
279 loop {
280 unsafe {
281 let mut set: libc::sigset_t = std::mem::zeroed();
282 libc::sigaddset(&mut set, libc::SIGURG);
283 let mut oldset: libc::sigset_t = std::mem::zeroed();
284 libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut oldset);
285 r = $fn($socket, $($arg, )*);
286 libc::pthread_sigmask(libc::SIG_SETMASK, &oldset, std::ptr::null_mut());
287 }
288 if r != -1 {
289 $crate::unix::common::reset_errno();
290 break;
291 }
292 let error_kind = std::io::Error::last_os_error().kind();
293 if error_kind == std::io::ErrorKind::WouldBlock {
294 if let Err(e) = event_loop.wait_write_event(socket, $timeout) {
296 match e.kind() {
297 std::io::ErrorKind::Interrupted => $crate::unix::common::reset_errno(),
299 _ => break,
300 }
301 }
302 } else if error_kind != std::io::ErrorKind::Interrupted {
303 break;
304 }
305 }
306 if blocking {
307 $crate::unix::common::set_non_blocking(socket, false);
308 }
309 r
310 }};
311}
312
313#[macro_export]
314macro_rules! impl_expected_write_hook {
315 ( ($fn: expr) ( $socket:expr, $buffer:expr, $length:expr), $timeout:expr) => {{
316 let socket = $socket;
317 let blocking = $crate::unix::common::is_blocking(socket);
318 if blocking {
319 $crate::unix::common::set_non_blocking(socket, true);
320 }
321 let event_loop = base_coroutine::EventLoop::next();
322 let mut sent = 0;
323 let mut r = 0;
324 while sent < $length {
325 unsafe {
326 let mut set: libc::sigset_t = std::mem::zeroed();
327 libc::sigaddset(&mut set, libc::SIGURG);
328 let mut oldset: libc::sigset_t = std::mem::zeroed();
329 libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut oldset);
330 r = $fn(
331 $socket,
332 ($buffer as usize + sent) as *const libc::c_void,
333 $length - sent
334 );
335 libc::pthread_sigmask(libc::SIG_SETMASK, &oldset, std::ptr::null_mut());
336 }
337 if r != -1 {
338 $crate::unix::common::reset_errno();
339 sent += r as libc::size_t;
340 if sent >= $length {
341 r = sent as libc::ssize_t;
342 break;
343 }
344 if r == 0 {
345 break;
346 }
347 }
348 let error_kind = std::io::Error::last_os_error().kind();
349 if error_kind == std::io::ErrorKind::WouldBlock {
350 if let Err(e) = event_loop.wait_write_event(socket, $timeout) {
352 match e.kind() {
353 std::io::ErrorKind::Interrupted => $crate::unix::common::reset_errno(),
355 _ => break,
356 }
357 }
358 } else if error_kind != std::io::ErrorKind::Interrupted {
359 break;
360 }
361 }
362 if blocking {
363 $crate::unix::common::set_non_blocking(socket, false);
364 }
365 r
366 }};
367 ( ($fn: expr) ( $socket:expr, $buffer:expr, $length:expr, $($arg: expr),* $(,)* ), $timeout:expr) => {{
368 let socket = $socket;
369 let blocking = $crate::unix::common::is_blocking(socket);
370 if blocking {
371 $crate::unix::common::set_non_blocking(socket, true);
372 }
373 let event_loop = base_coroutine::EventLoop::next();
374 let mut sent = 0;
375 let mut r = 0;
376 while sent < $length {
377 unsafe {
378 let mut set: libc::sigset_t = std::mem::zeroed();
379 libc::sigaddset(&mut set, libc::SIGURG);
380 let mut oldset: libc::sigset_t = std::mem::zeroed();
381 libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut oldset);
382 r = $fn(
383 $socket,
384 ($buffer as usize + sent) as *const libc::c_void,
385 $length - sent,
386 $($arg, )*
387 );
388 libc::pthread_sigmask(libc::SIG_SETMASK, &oldset, std::ptr::null_mut());
389 }
390 if r != -1 {
391 $crate::unix::common::reset_errno();
392 sent += r as libc::size_t;
393 if sent >= $length {
394 r = sent as libc::ssize_t;
395 break;
396 }
397 if r == 0 {
398 break;
399 }
400 }
401 let error_kind = std::io::Error::last_os_error().kind();
402 if error_kind == std::io::ErrorKind::WouldBlock {
403 if let Err(e) = event_loop.wait_write_event(socket, $timeout) {
405 match e.kind() {
406 std::io::ErrorKind::Interrupted => $crate::unix::common::reset_errno(),
408 _ => break,
409 }
410 }
411 } else if error_kind != std::io::ErrorKind::Interrupted {
412 break;
413 }
414 }
415 if blocking {
416 $crate::unix::common::set_non_blocking(socket, false);
417 }
418 r
419 }};
420}