1
use crate::{
2
    capture::{Activated, Capture},
3
    codec::PacketCodec,
4
    Error,
5
};
6

            
7
/// Implement an Iterator of Packet
8
pub struct PacketIter<S: Activated + ?Sized, C> {
9
    capture: Capture<S>,
10
    codec: C,
11
}
12

            
13
impl<S: Activated + ?Sized, C> PacketIter<S, C> {
14
8
    pub(crate) fn new(capture: Capture<S>, codec: C) -> Self {
15
8
        Self { capture, codec }
16
8
    }
17

            
18
    /// Returns a mutable reference to the inner [`Capture`].
19
2
    pub fn capture_mut(&mut self) -> &mut Capture<S> {
20
2
        &mut self.capture
21
2
    }
22
}
23

            
24
impl<S: Activated + ?Sized, C> From<PacketIter<S, C>> for (Capture<S>, C) {
25
2
    fn from(iter: PacketIter<S, C>) -> Self {
26
2
        (iter.capture, iter.codec)
27
2
    }
28
}
29

            
30
impl<S: Activated + ?Sized, C: PacketCodec> Iterator for PacketIter<S, C> {
31
    type Item = Result<C::Item, Error>;
32

            
33
8
    fn next(&mut self) -> Option<Self::Item> {
34
8
        match self.capture.next_packet() {
35
2
            Ok(packet) => Some(Ok(self.codec.decode(packet))),
36
2
            Err(Error::NoMorePackets) => None,
37
4
            Err(e) => Some(Err(e)),
38
        }
39
8
    }
40
}
41

            
42
#[cfg(feature = "lending-iter")]
43
mod lending_iter {
44
    use crate::Activated;
45
    use crate::Capture;
46
    use crate::Error;
47
    use crate::Packet;
48
    use gat_std::iter::{IntoIterator, Iterator};
49

            
50
    pub struct PacketLendingIter<S: Activated + ?Sized> {
51
        capture: Capture<S>,
52
    }
53

            
54
    impl<S: Activated + ?Sized + 'static> IntoIterator for Capture<S> {
55
        type IntoIter = PacketLendingIter<S>;
56

            
57
8
        fn into_iter(self) -> Self::IntoIter {
58
8
            PacketLendingIter { capture: self }
59
8
        }
60
    }
61

            
62
    impl<S: Activated + ?Sized + 'static> Iterator for PacketLendingIter<S> {
63
        type Item<'a> = Result<Packet<'a>, Error>;
64

            
65
8
        fn next(&mut self) -> Option<Self::Item<'_>> {
66
8
            match self.capture.next_packet() {
67
2
                Ok(packet) => Some(Ok(packet)),
68
2
                Err(Error::NoMorePackets) => None,
69
4
                Err(e) => Some(Err(e)),
70
            }
71
8
        }
72
    }
73
}
74

            
75
#[cfg(test)]
76
mod tests {
77
    use crate::{
78
        capture::{
79
            activated::testmod::{next_ex_expect, PACKET},
80
            testmod::test_capture,
81
            Active, Offline,
82
        },
83
        codec::testmod::Codec,
84
        raw::{
85
            self,
86
            testmod::{as_pcap_t, geterr_expect, RAWMTX},
87
        },
88
    };
89

            
90
    #[cfg(feature = "lending-iter")]
91
    use gat_std::iter::{IntoIterator, Iterator};
92

            
93
    use super::*;
94

            
95
    #[cfg(feature = "lending-iter")]
96
    use super::lending_iter::*;
97

            
98
    #[test]
99
    fn test_iter_next() {
100
        let _m = RAWMTX.lock();
101

            
102
        let mut value: isize = 777;
103
        let pcap = as_pcap_t(&mut value);
104

            
105
        let test_capture = test_capture::<Active>(pcap);
106
        let capture = test_capture.capture;
107
        let mut packet_iter = capture.iter(Codec);
108

            
109
        let _nxt = next_ex_expect(pcap);
110

            
111
        let next = packet_iter.next().unwrap();
112
        let next_packet = next.unwrap();
113
        assert_eq!(next_packet.header, *PACKET.header);
114
        assert_eq!(*next_packet.data, *PACKET.data);
115

            
116
        let _nxt = next_ex_expect(pcap);
117

            
118
        let next_packet = packet_iter.capture_mut().next_packet().unwrap();
119
        assert_eq!(next_packet, PACKET);
120

            
121
        let _nxt = next_ex_expect(pcap);
122

            
123
        let (mut capture, _) = packet_iter.into();
124

            
125
        let next_packet = capture.next_packet().unwrap();
126
        assert_eq!(next_packet, PACKET);
127
    }
128

            
129
    #[test]
130
    fn test_iter_timeout() {
131
        let _m = RAWMTX.lock();
132

            
133
        let mut value: isize = 777;
134
        let pcap = as_pcap_t(&mut value);
135

            
136
        let test_capture = test_capture::<Active>(pcap);
137
        let capture = test_capture.capture;
138

            
139
        let mut packet_iter = capture.iter(Codec);
140

            
141
        let ctx = raw::pcap_next_ex_context();
142
        ctx.expect()
143
            .withf_st(move |arg1, _, _| *arg1 == pcap)
144
            .return_once_st(move |_, _, _| 0);
145

            
146
        let next = packet_iter.next().unwrap();
147
        let err = next.unwrap_err();
148
        assert_eq!(err, Error::TimeoutExpired);
149
    }
150

            
151
    #[test]
152
    fn test_next_packet_read_error() {
153
        let _m = RAWMTX.lock();
154

            
155
        let mut value: isize = 777;
156
        let pcap = as_pcap_t(&mut value);
157

            
158
        let test_capture = test_capture::<Active>(pcap);
159
        let capture = test_capture.capture;
160

            
161
        let mut packet_iter = capture.iter(Codec);
162

            
163
        let ctx = raw::pcap_next_ex_context();
164
        ctx.expect()
165
            .withf_st(move |arg1, _, _| *arg1 == pcap)
166
            .return_once_st(move |_, _, _| -1);
167

            
168
        let _err = geterr_expect(pcap);
169

            
170
        let next = packet_iter.next().unwrap();
171
        assert!(next.is_err());
172
    }
173

            
174
    #[test]
175
    fn test_next_packet_no_more_packets() {
176
        let _m = RAWMTX.lock();
177

            
178
        let mut value: isize = 777;
179
        let pcap = as_pcap_t(&mut value);
180

            
181
        let test_capture = test_capture::<Offline>(pcap);
182
        let capture = test_capture.capture;
183

            
184
        let mut packet_iter = capture.iter(Codec);
185

            
186
        let ctx = raw::pcap_next_ex_context();
187
        ctx.expect()
188
            .withf_st(move |arg1, _, _| *arg1 == pcap)
189
            .return_once_st(move |_, _, _| -2);
190

            
191
        let next = packet_iter.next();
192
        assert!(next.is_none());
193
    }
194

            
195
    #[test]
196
    #[cfg(feature = "lending-iter")]
197
    fn test_lending_iter() {
198
        let _m = RAWMTX.lock();
199

            
200
        let mut value: isize = 777;
201
        let pcap = as_pcap_t(&mut value);
202

            
203
        let test_capture = test_capture::<Active>(pcap);
204
        let capture = test_capture.capture;
205
        let mut packet_iter: PacketLendingIter<Active> = capture.into_iter();
206

            
207
        let _nxt = next_ex_expect(pcap);
208

            
209
        let next = packet_iter.next().unwrap();
210
        let next_packet = next.unwrap();
211
        assert_eq!(next_packet, PACKET);
212
    }
213

            
214
    #[test]
215
    #[cfg(feature = "lending-iter")]
216
    fn test_lending_iter_timeout() {
217
        let _m = RAWMTX.lock();
218

            
219
        let mut value: isize = 777;
220
        let pcap = as_pcap_t(&mut value);
221

            
222
        let test_capture = test_capture::<Active>(pcap);
223
        let capture = test_capture.capture;
224
        let mut packet_iter: PacketLendingIter<Active> = capture.into_iter();
225

            
226
        let ctx = raw::pcap_next_ex_context();
227
        ctx.expect()
228
            .withf_st(move |arg1, _, _| *arg1 == pcap)
229
            .return_once_st(move |_, _, _| 0);
230

            
231
        let next = packet_iter.next().unwrap();
232
        let err = next.unwrap_err();
233
        assert_eq!(err, Error::TimeoutExpired);
234
    }
235

            
236
    #[test]
237
    #[cfg(feature = "lending-iter")]
238
    fn test_lending_iter_read_error() {
239
        let _m = RAWMTX.lock();
240

            
241
        let mut value: isize = 777;
242
        let pcap = as_pcap_t(&mut value);
243

            
244
        let test_capture = test_capture::<Active>(pcap);
245
        let capture = test_capture.capture;
246
        let mut packet_iter: PacketLendingIter<Active> = capture.into_iter();
247

            
248
        let ctx = raw::pcap_next_ex_context();
249
        ctx.expect()
250
            .withf_st(move |arg1, _, _| *arg1 == pcap)
251
            .return_once_st(move |_, _, _| -1);
252

            
253
        let _err = geterr_expect(pcap);
254

            
255
        let next = packet_iter.next().unwrap();
256
        assert!(next.is_err());
257
    }
258

            
259
    #[test]
260
    #[cfg(feature = "lending-iter")]
261
    fn test_lending_iter_no_more_packets() {
262
        let _m = RAWMTX.lock();
263

            
264
        let mut value: isize = 777;
265
        let pcap = as_pcap_t(&mut value);
266

            
267
        let test_capture = test_capture::<Offline>(pcap);
268
        let capture = test_capture.capture;
269
        let mut packet_iter: PacketLendingIter<Offline> = capture.into_iter();
270

            
271
        let ctx = raw::pcap_next_ex_context();
272
        ctx.expect()
273
            .withf_st(move |arg1, _, _| *arg1 == pcap)
274
            .return_once_st(move |_, _, _| -2);
275

            
276
        let next = packet_iter.next();
277
        assert!(next.is_none());
278
    }
279
}