1
use std::os::unix::io::{AsRawFd, RawFd};
2

            
3
use crate::{
4
    capture::{Activated, Capture, State},
5
    raw, Error,
6
};
7

            
8
/// Newtype [`Capture`] wrapper that exposes `pcap_get_selectable_fd()`.
9
pub struct SelectableCapture<T: State + ?Sized> {
10
    inner: Capture<T>,
11
    fd: RawFd,
12
}
13

            
14
impl<T: Activated + ?Sized> SelectableCapture<T> {
15
4
    pub fn new(capture: Capture<T>) -> Result<Self, Error> {
16
4
        let fd = unsafe { raw::pcap_get_selectable_fd(capture.as_ptr()) };
17
4
        if fd == -1 {
18
2
            return Err(Error::InvalidRawFd);
19
2
        }
20
2
        Ok(Self { inner: capture, fd })
21
4
    }
22

            
23
2
    pub fn get_inner_mut(&mut self) -> &mut Capture<T> {
24
2
        &mut self.inner
25
2
    }
26
}
27

            
28
impl<T: Activated + ?Sized> AsRawFd for SelectableCapture<T> {
29
2
    fn as_raw_fd(&self) -> RawFd {
30
2
        self.fd
31
2
    }
32
}
33

            
34
#[cfg(test)]
35
mod tests {
36
    use crate::{
37
        capture::{testmod::test_capture, Active},
38
        raw::testmod::{as_pcap_t, RAWMTX},
39
    };
40

            
41
    use super::*;
42

            
43
    #[test]
44
    fn test_selectable_capture() {
45
        let _m = RAWMTX.lock();
46

            
47
        let mut dummy: isize = 777;
48
        let pcap = as_pcap_t(&mut dummy);
49

            
50
        let test_capture = test_capture::<Active>(pcap);
51
        let capture = test_capture.capture;
52

            
53
        let ctx = raw::pcap_get_selectable_fd_context();
54
        ctx.expect()
55
            .withf_st(move |arg1| *arg1 == pcap)
56
            .return_once(|_| 5);
57

            
58
        let mut selectable = SelectableCapture::new(capture).unwrap();
59
        assert!(!selectable.get_inner_mut().is_nonblock());
60
        assert_eq!(selectable.as_raw_fd(), 5);
61
    }
62

            
63
    #[test]
64
    fn test_selectable_capture_error() {
65
        let _m = RAWMTX.lock();
66

            
67
        let mut dummy: isize = 777;
68
        let pcap = as_pcap_t(&mut dummy);
69

            
70
        let test_capture = test_capture::<Active>(pcap);
71
        let capture = test_capture.capture;
72

            
73
        let ctx = raw::pcap_get_selectable_fd_context();
74
        ctx.expect()
75
            .withf_st(move |arg1| *arg1 == pcap)
76
            .return_once(|_| -1);
77

            
78
        let result = SelectableCapture::new(capture);
79
        assert!(result.is_err());
80
    }
81
}