pnet::transport_channel_iterator!
[−]
macro_rules! transport_channel_iterator { ($ty:ident, $iter:ident, $func:ident) => ( /// An iterator over packets of type $ty pub struct $iter<'a> { tr: &'a mut TransportReceiver } /// Return a packet iterator with packets of type $ty for some transport receiver pub fn $func(tr: &mut TransportReceiver) -> $iter { $iter { tr: tr } } impl<'a> $iter<'a> { /// Get the next ($ty, IpAddr) pair for the given channel pub fn next(&mut self) -> io::Result<($ty, net::IpAddr)> { let mut caddr: libc::sockaddr_storage = unsafe { mem::zeroed() }; let res = internal::recv_from(self.tr.socket.fd, &mut self.tr.buffer[..], &mut caddr); let offset = match self.tr.channel_type { Layer4(Ipv4(_)) => { let ip_header = Ipv4Packet::new(&self.tr.buffer[..]).unwrap(); ip_header.get_header_length() as usize * 4usize }, Layer3(_) => { fixup_packet(&mut self.tr.buffer[..]); 0 }, _ => 0 }; return match res { Ok(len) => { let packet = $ty::new(&self.tr.buffer[offset..len]).unwrap(); let addr = internal::sockaddr_to_addr( &caddr, mem::size_of::<libc::sockaddr_storage>() ); Ok((packet, addr.unwrap().ip())) }, Err(e) => Err(e), }; #[cfg(any(target_os = "freebsd", target_os = "macos"))] fn fixup_packet(buffer: &mut [u8]) { use packet::ipv4::MutableIpv4Packet; let buflen = buffer.len(); let mut new_packet = MutableIpv4Packet::new(buffer).unwrap(); let length = u16::from_be(new_packet.get_total_length()); new_packet.set_total_length(length); // OS X does this awesome thing where it removes the header length // from the total length sometimes. let length = new_packet.get_total_length() as usize + (new_packet.get_header_length() as usize * 4usize); if length == buflen { new_packet.set_total_length(length as u16) } let offset = u16::from_be(new_packet.get_fragment_offset()); new_packet.set_fragment_offset(offset); } #[cfg(all(not(target_os = "freebsd"), not(target_os = "macos")))] fn fixup_packet(_buffer: &mut [u8]) {} } } ) }
Create an iterator for some packet type.
Usage:
transport_channel_iterator!(Ipv4Packet, // Type to iterate over Ipv4TransportChannelIterator, // Name for iterator struct ipv4_packet_iter) // Name of function to create iterator