hook/unix/
mod.rs

1/**
2do not impl close/read hook !!!!!
3it will not pass linux CI !!!!!
4 */
5use crate::unix::common::*;
6use once_cell::sync::Lazy;
7use std::ffi::c_void;
8
9#[macro_use]
10mod common;
11
12#[cfg(any(
13    target_os = "macos",
14    target_os = "ios",
15    target_os = "tvos",
16    target_os = "watchos",
17    target_os = "freebsd",
18    target_os = "dragonfly",
19    target_os = "openbsd",
20    target_os = "netbsd"
21))]
22mod bsd;
23
24#[cfg(any(
25    target_os = "linux",
26    target_os = "l4re",
27    target_os = "android",
28    target_os = "emscripten"
29))]
30mod linux_like;
31
32//sleep相关
33#[no_mangle]
34pub extern "C" fn sleep(secs: libc::c_uint) -> libc::c_uint {
35    let rqtp = libc::timespec {
36        tv_sec: secs as i64,
37        tv_nsec: 0,
38    };
39    let mut rmtp = libc::timespec {
40        tv_sec: 0,
41        tv_nsec: 0,
42    };
43    nanosleep(&rqtp, &mut rmtp);
44    rmtp.tv_sec as u32
45}
46
47#[no_mangle]
48pub extern "C" fn usleep(secs: libc::c_uint) -> libc::c_int {
49    let secs = secs as i64;
50    let sec = secs / 1_000_000;
51    let nsec = (secs % 1_000_000) * 1000;
52    let rqtp = libc::timespec {
53        tv_sec: sec,
54        tv_nsec: nsec,
55    };
56    let mut rmtp = libc::timespec {
57        tv_sec: 0,
58        tv_nsec: 0,
59    };
60    nanosleep(&rqtp, &mut rmtp)
61}
62
63static NANOSLEEP: Lazy<extern "C" fn(*const libc::timespec, *mut libc::timespec) -> libc::c_int> =
64    init_hook!("nanosleep");
65
66#[no_mangle]
67pub extern "C" fn nanosleep(rqtp: *const libc::timespec, rmtp: *mut libc::timespec) -> libc::c_int {
68    //todo 用wait_event实现
69    let mut rqtp = unsafe { *rqtp };
70    if rqtp.tv_sec < 0 || rqtp.tv_nsec < 0 {
71        return -1;
72    }
73    let nanos_time = match (rqtp.tv_sec as u64).checked_mul(1_000_000_000) {
74        Some(v) => v.checked_add(rqtp.tv_nsec as u64).unwrap_or(u64::MAX),
75        None => u64::MAX,
76    };
77    let timeout_time = timer_utils::add_timeout_time(nanos_time);
78    loop {
79        let _ = base_coroutine::EventLoop::round_robin_timeout_schedule(timeout_time);
80        // 可能schedule完还剩一些时间,此时本地队列没有任务可做
81        let schedule_finished_time = timer_utils::now();
82        let left_time = match timeout_time.checked_sub(schedule_finished_time) {
83            Some(v) => v,
84            None => {
85                if !rmtp.is_null() {
86                    unsafe {
87                        (*rmtp).tv_sec = 0;
88                        (*rmtp).tv_nsec = 0;
89                    }
90                }
91                return 0;
92            }
93        } as i64;
94        let sec = left_time / 1_000_000_000;
95        let nsec = left_time % 1_000_000_000;
96        rqtp = libc::timespec {
97            tv_sec: sec,
98            tv_nsec: nsec,
99        };
100        //注意这里获取的是原始系统函数nanosleep的指针
101        //相当于libc::nanosleep(&rqtp, rmtp)
102        if (Lazy::force(&NANOSLEEP))(&rqtp, rmtp) == 0 {
103            reset_errno();
104            return 0;
105        }
106    }
107}
108
109//socket相关
110static CONNECT: Lazy<
111    extern "C" fn(libc::c_int, *const libc::sockaddr, libc::socklen_t) -> libc::c_int,
112> = init_hook!("connect");
113
114#[no_mangle]
115pub extern "C" fn connect(
116    socket: libc::c_int,
117    address: *const libc::sockaddr,
118    len: libc::socklen_t,
119) -> libc::c_int {
120    let blocking = is_blocking(socket);
121    //阻塞,epoll_wait/kevent等待直到写事件
122    if blocking {
123        set_non_blocking(socket, true);
124    }
125    let event_loop = base_coroutine::EventLoop::next();
126    let mut r;
127    loop {
128        r = (Lazy::force(&CONNECT))(socket, address, len);
129        if r == 0 {
130            reset_errno();
131            break;
132        }
133        let errno = std::io::Error::last_os_error().raw_os_error();
134        if errno == Some(libc::EINPROGRESS) {
135            //等待写事件
136            if let Err(e) =
137                event_loop.wait_write_event(socket, Some(std::time::Duration::from_secs(1)))
138            {
139                match e.kind() {
140                    //maybe invoke by Monitor::signal(), just ignore this
141                    std::io::ErrorKind::Interrupted => reset_errno(),
142                    _ => {
143                        r = -1;
144                        break;
145                    }
146                }
147            }
148            unsafe {
149                let mut len: libc::socklen_t = std::mem::zeroed();
150                let mut err: libc::c_int = 0;
151                r = libc::getsockopt(
152                    socket,
153                    libc::SOL_SOCKET,
154                    libc::SO_ERROR,
155                    &mut err as *mut _ as *mut c_void,
156                    &mut len,
157                );
158                if r != 0 {
159                    break;
160                }
161                if err == 0 {
162                    reset_errno();
163                    r = 0;
164                    break;
165                };
166                set_errno(err);
167            }
168            r = -1;
169            break;
170        } else if errno != Some(libc::EINTR) {
171            r = -1;
172            break;
173        }
174    }
175    if blocking {
176        set_non_blocking(socket, false);
177    }
178    r
179}
180
181static LISTEN: Lazy<extern "C" fn(libc::c_int, libc::c_int) -> libc::c_int> = init_hook!("listen");
182
183#[no_mangle]
184pub extern "C" fn listen(socket: libc::c_int, backlog: libc::c_int) -> libc::c_int {
185    let _ = base_coroutine::EventLoop::round_robin_schedule();
186    //unnecessary non blocking impl for listen
187    (Lazy::force(&LISTEN))(socket, backlog)
188}
189
190static ACCEPT: Lazy<
191    extern "C" fn(libc::c_int, *mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int,
192> = init_hook!("accept");
193
194#[no_mangle]
195pub extern "C" fn accept(
196    socket: libc::c_int,
197    address: *mut libc::sockaddr,
198    address_len: *mut libc::socklen_t,
199) -> libc::c_int {
200    impl_read_hook!(
201        (Lazy::force(&ACCEPT))(socket, address, address_len),
202        Some(std::time::Duration::from_secs(1))
203    )
204}
205
206static SHUTDOWN: Lazy<extern "C" fn(libc::c_int, libc::c_int) -> libc::c_int> =
207    init_hook!("shutdown");
208
209#[no_mangle]
210pub extern "C" fn shutdown(socket: libc::c_int, how: libc::c_int) -> libc::c_int {
211    let _ = base_coroutine::EventLoop::round_robin_schedule();
212    //取消对fd的监听
213    match how {
214        libc::SHUT_RD => base_coroutine::EventLoop::round_robin_del_read_event(socket),
215        libc::SHUT_WR => base_coroutine::EventLoop::round_robin_del_write_event(socket),
216        libc::SHUT_RDWR => base_coroutine::EventLoop::round_robin_del_event(socket),
217        _ => {
218            crate::unix::common::set_errno(libc::EINVAL);
219            return -1;
220        }
221    }
222    (Lazy::force(&SHUTDOWN))(socket, how)
223}
224
225static POLL: Lazy<extern "C" fn(*mut libc::pollfd, libc::nfds_t, libc::c_int) -> libc::c_int> =
226    init_hook!("poll");
227
228#[no_mangle]
229pub extern "C" fn poll(
230    fds: *mut libc::pollfd,
231    nfds: libc::nfds_t,
232    timeout: libc::c_int,
233) -> libc::c_int {
234    let mut t = if timeout < 0 {
235        libc::c_int::MAX
236    } else {
237        timeout
238    };
239    let mut x = 1;
240    let mut r;
241    // just check select every x ms
242    loop {
243        unsafe {
244            let mut set: libc::sigset_t = std::mem::zeroed();
245            libc::sigaddset(&mut set, libc::SIGURG);
246            let mut oldset: libc::sigset_t = std::mem::zeroed();
247            libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut oldset);
248            r = (Lazy::force(&POLL))(fds, nfds, 0);
249            libc::pthread_sigmask(libc::SIG_SETMASK, &oldset, std::ptr::null_mut());
250        }
251        if r != 0 || t == 0 {
252            break;
253        }
254        usleep((t.min(x) * 1000) as libc::c_uint);
255        if t != libc::c_int::MAX {
256            t = if t > x { t - x } else { 0 };
257        }
258        if x < 16 {
259            x <<= 1;
260        }
261    }
262    r
263}
264
265static SELECT: Lazy<
266    extern "C" fn(
267        libc::c_int,
268        *mut libc::fd_set,
269        *mut libc::fd_set,
270        *mut libc::fd_set,
271        *mut libc::timeval,
272    ) -> libc::c_int,
273> = init_hook!("select");
274
275#[no_mangle]
276pub extern "C" fn select(
277    nfds: libc::c_int,
278    readfds: *mut libc::fd_set,
279    writefds: *mut libc::fd_set,
280    errorfds: *mut libc::fd_set,
281    timeout: *mut libc::timeval,
282) -> libc::c_int {
283    let mut t = if timeout.is_null() {
284        libc::c_uint::MAX
285    } else {
286        unsafe {
287            ((*timeout).tv_sec as libc::c_uint) * 1_000_000 + (*timeout).tv_usec as libc::c_uint
288        }
289    };
290    let mut o = libc::timeval {
291        tv_sec: 0,
292        tv_usec: 0,
293    };
294    let mut s: [libc::fd_set; 3] = unsafe { std::mem::zeroed() };
295    unsafe {
296        if !readfds.is_null() {
297            s[0] = *readfds;
298        }
299        if !writefds.is_null() {
300            s[1] = *writefds;
301        }
302        if !errorfds.is_null() {
303            s[2] = *errorfds;
304        }
305    }
306    let mut x = 1;
307    let mut r;
308    // just check poll every x ms
309    loop {
310        unsafe {
311            let mut set: libc::sigset_t = std::mem::zeroed();
312            libc::sigaddset(&mut set, libc::SIGURG);
313            let mut oldset: libc::sigset_t = std::mem::zeroed();
314            libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut oldset);
315            r = (Lazy::force(&SELECT))(nfds, readfds, writefds, errorfds, &mut o);
316            libc::pthread_sigmask(libc::SIG_SETMASK, &oldset, std::ptr::null_mut());
317        }
318        if r != 0 || t == 0 {
319            break;
320        }
321        usleep(t.min(x) * 1000);
322        if t != libc::c_uint::MAX {
323            t = if t > x { t - x } else { 0 };
324        }
325        if x < 16 {
326            x <<= 1;
327        }
328        unsafe {
329            if !readfds.is_null() {
330                *readfds = s[0];
331            }
332            if !writefds.is_null() {
333                *writefds = s[1];
334            }
335            if !errorfds.is_null() {
336                *errorfds = s[2];
337            }
338        }
339        o.tv_sec = 0;
340        o.tv_usec = 0;
341    }
342    r
343}
344
345//write相关
346static SEND: Lazy<
347    extern "C" fn(libc::c_int, *const libc::c_void, libc::size_t, libc::c_int) -> libc::ssize_t,
348> = init_hook!("send");
349
350#[no_mangle]
351pub extern "C" fn send(
352    socket: libc::c_int,
353    buf: *const libc::c_void,
354    len: libc::size_t,
355    flags: libc::c_int,
356) -> libc::ssize_t {
357    impl_expected_write_hook!(
358        (Lazy::force(&SEND))(socket, buf, len, flags),
359        Some(std::time::Duration::from_secs(1))
360    )
361}
362
363static WRITE: Lazy<extern "C" fn(libc::c_int, *const libc::c_void, libc::size_t) -> libc::ssize_t> =
364    init_hook!("write");
365
366#[no_mangle]
367pub extern "C" fn write(
368    fd: libc::c_int,
369    buf: *const libc::c_void,
370    count: libc::size_t,
371) -> libc::ssize_t {
372    impl_expected_write_hook!(
373        (Lazy::force(&WRITE))(fd, buf, count),
374        Some(std::time::Duration::from_secs(1))
375    )
376}
377
378static WRITEV: Lazy<extern "C" fn(libc::c_int, *const libc::iovec, libc::c_int) -> libc::ssize_t> =
379    init_hook!("writev");
380
381#[no_mangle]
382pub extern "C" fn writev(
383    fd: libc::c_int,
384    iov: *const libc::iovec,
385    iovcnt: libc::c_int,
386) -> libc::ssize_t {
387    impl_write_hook!(
388        (Lazy::force(&WRITEV))(fd, iov, iovcnt),
389        Some(std::time::Duration::from_secs(1))
390    )
391}
392
393static SENDTO: Lazy<
394    extern "C" fn(
395        libc::c_int,
396        *const libc::c_void,
397        libc::size_t,
398        libc::c_int,
399        *const libc::sockaddr,
400        libc::socklen_t,
401    ) -> libc::ssize_t,
402> = init_hook!("sendto");
403
404#[no_mangle]
405pub extern "C" fn sendto(
406    socket: libc::c_int,
407    buf: *const libc::c_void,
408    len: libc::size_t,
409    flags: libc::c_int,
410    addr: *const libc::sockaddr,
411    addrlen: libc::socklen_t,
412) -> libc::ssize_t {
413    impl_expected_write_hook!(
414        (Lazy::force(&SENDTO))(socket, buf, len, flags, addr, addrlen),
415        Some(std::time::Duration::from_secs(1))
416    )
417}
418
419static SENDMSG: Lazy<
420    extern "C" fn(libc::c_int, *const libc::msghdr, libc::c_int) -> libc::ssize_t,
421> = init_hook!("sendmsg");
422
423#[no_mangle]
424pub extern "C" fn sendmsg(
425    fd: libc::c_int,
426    msg: *const libc::msghdr,
427    flags: libc::c_int,
428) -> libc::ssize_t {
429    impl_write_hook!(
430        (Lazy::force(&SENDMSG))(fd, msg, flags),
431        Some(std::time::Duration::from_secs(1))
432    )
433}
434
435static PWRITE: Lazy<
436    extern "C" fn(libc::c_int, *const libc::c_void, libc::size_t, libc::off_t) -> libc::ssize_t,
437> = init_hook!("pwrite");
438
439#[no_mangle]
440pub extern "C" fn pwrite(
441    fd: libc::c_int,
442    buf: *const libc::c_void,
443    count: libc::size_t,
444    offset: libc::off_t,
445) -> libc::ssize_t {
446    impl_expected_write_hook!(
447        (Lazy::force(&PWRITE))(fd, buf, count, offset),
448        Some(std::time::Duration::from_secs(1))
449    )
450}
451
452static PWRITEV: Lazy<
453    extern "C" fn(libc::c_int, *const libc::iovec, libc::c_int, libc::off_t) -> libc::ssize_t,
454> = init_hook!("pwritev");
455
456#[no_mangle]
457pub extern "C" fn pwritev(
458    fd: libc::c_int,
459    iov: *const libc::iovec,
460    iovcnt: libc::c_int,
461    offset: libc::off_t,
462) -> libc::ssize_t {
463    impl_write_hook!(
464        (Lazy::force(&PWRITEV))(fd, iov, iovcnt, offset),
465        Some(std::time::Duration::from_secs(1))
466    )
467}
468
469//read相关
470static RECV: Lazy<
471    extern "C" fn(libc::c_int, *mut libc::c_void, libc::size_t, libc::c_int) -> libc::ssize_t,
472> = init_hook!("recv");
473
474#[no_mangle]
475pub extern "C" fn recv(
476    socket: libc::c_int,
477    buf: *mut libc::c_void,
478    len: libc::size_t,
479    flags: libc::c_int,
480) -> libc::ssize_t {
481    impl_expected_read_hook!(
482        (Lazy::force(&RECV))(socket, buf, len, flags),
483        Some(std::time::Duration::from_secs(1))
484    )
485}
486
487static READV: Lazy<extern "C" fn(libc::c_int, *const libc::iovec, libc::c_int) -> libc::ssize_t> =
488    init_hook!("readv");
489
490#[no_mangle]
491pub extern "C" fn readv(
492    fd: libc::c_int,
493    iov: *const libc::iovec,
494    iovcnt: libc::c_int,
495) -> libc::ssize_t {
496    impl_read_hook!(
497        (Lazy::force(&READV))(fd, iov, iovcnt),
498        Some(std::time::Duration::from_secs(1))
499    )
500}
501
502static PREAD: Lazy<
503    extern "C" fn(libc::c_int, *mut libc::c_void, libc::size_t, libc::off_t) -> libc::ssize_t,
504> = init_hook!("pread");
505
506#[no_mangle]
507pub extern "C" fn pread(
508    fd: libc::c_int,
509    buf: *mut libc::c_void,
510    count: libc::size_t,
511    offset: libc::off_t,
512) -> libc::ssize_t {
513    impl_expected_read_hook!(
514        (Lazy::force(&PREAD))(fd, buf, count, offset),
515        Some(std::time::Duration::from_secs(1))
516    )
517}
518
519static PREADV: Lazy<
520    extern "C" fn(libc::c_int, *const libc::iovec, libc::c_int, libc::off_t) -> libc::ssize_t,
521> = init_hook!("preadv");
522
523#[no_mangle]
524pub extern "C" fn preadv(
525    fd: libc::c_int,
526    iov: *const libc::iovec,
527    iovcnt: libc::c_int,
528    offset: libc::off_t,
529) -> libc::ssize_t {
530    impl_read_hook!(
531        (Lazy::force(&PREADV))(fd, iov, iovcnt, offset),
532        Some(std::time::Duration::from_secs(1))
533    )
534}
535
536static RECVFROM: Lazy<
537    extern "C" fn(
538        libc::c_int,
539        *mut libc::c_void,
540        libc::size_t,
541        libc::c_int,
542        *mut libc::sockaddr,
543        *mut libc::socklen_t,
544    ) -> libc::ssize_t,
545> = init_hook!("recvfrom");
546
547#[no_mangle]
548pub extern "C" fn recvfrom(
549    socket: libc::c_int,
550    buf: *mut libc::c_void,
551    len: libc::size_t,
552    flags: libc::c_int,
553    addr: *mut libc::sockaddr,
554    addrlen: *mut libc::socklen_t,
555) -> libc::ssize_t {
556    impl_expected_read_hook!(
557        (Lazy::force(&RECVFROM))(socket, buf, len, flags, addr, addrlen),
558        Some(std::time::Duration::from_secs(1))
559    )
560}
561
562static RECVMSG: Lazy<extern "C" fn(libc::c_int, *mut libc::msghdr, libc::c_int) -> libc::ssize_t> =
563    init_hook!("recvmsg");
564
565#[no_mangle]
566pub extern "C" fn recvmsg(
567    fd: libc::c_int,
568    msg: *mut libc::msghdr,
569    flags: libc::c_int,
570) -> libc::ssize_t {
571    impl_read_hook!(
572        (Lazy::force(&RECVMSG))(fd, msg, flags),
573        Some(std::time::Duration::from_secs(1))
574    )
575}