def _replay(pcap_path: str, dst_ip: str, dst_lidar_port: int, dst_imu_port: int) -> Iterator[bool]: """Replay UDP packets out over the network. Todo: Not really sure about this interface Args: pcap_path: Path to the pcap file to replay dst_ip: IP to send packets to dst_lidar_port: Destination port for lidar packets dst_imu_port: Destination port for imu packets Returns: An iterator that reports whether packets were sent successfully as it's consumed. """ pcap_info = _pcap.replay_get_pcap_info(pcap_path, 10000) pcap_port_guess = _guess_ports(pcap_info) pcap_handle = _pcap.replay_initialize(pcap_path, dst_ip, dst_ip, { pcap_port_guess[0]: dst_lidar_port, pcap_port_guess[1]: dst_imu_port }) try: packet_info = _pcap.packet_info() while _pcap.next_packet_info(pcap_handle, packet_info): yield _pcap.replay_packet(pcap_handle) finally: _pcap.replay_uninitialize(pcap_handle) yield False
def _pcap_info(path: str) -> Iterator[_pcap.packet_info]: handle = _pcap.replay_initialize(path) try: while True: if handle is None: raise ValueError("I/O operation on closed packet source") packet_info = _pcap.packet_info() if not _pcap.next_packet_info(handle, packet_info): break yield packet_info finally: if handle: _pcap.replay_uninitialize(handle)
def test_read_write_lidar_imu(lidar_packets, imu_packets): lidar_size = 12608 imu_size = 48 frag_size = 1480 lidar_src_port = 7000 lidar_dst_port = 7001 imu_src_port = 8000 imu_dst_port = 8001 src_address = "127.0.0.1" dst_address = src_address lidar_buf = bytearray(lidar_size) imu_buf = bytearray(imu_size) tmp_dir = tempfile.mkdtemp() file_path = os.path.join(tmp_dir, "pcap_test.pcap") try: lidar_data, record = write_test_pcap(file_path, lidar_packets, lidar_size, frag_size, lidar_src_port, lidar_dst_port) imu_data, record = write_test_pcap(file_path, imu_packets, imu_size, frag_size, imu_src_port, imu_dst_port, record=record) _pcap.record_uninitialize(record) lidar_result = bytearray() imu_result = bytearray() pcap_read = _pcap.replay_initialize(file_path, src_address, dst_address, {}) info = _pcap.packet_info() while _pcap.next_packet_info(pcap_read, info): if info.dst_port == imu_dst_port: _pcap.read_packet(pcap_read, imu_buf) imu_result += imu_buf if info.dst_port == lidar_dst_port: _pcap.read_packet(pcap_read, lidar_buf) lidar_result += lidar_buf assert lidar_data == lidar_result assert imu_data == imu_result _pcap.replay_uninitialize(pcap_read) finally: os.remove(file_path) os.rmdir(tmp_dir)
def _guess_ports(pcap_path: str) -> Tuple[Optional[int], Optional[int]]: p = _pcap.replay_initialize(pcap_path) packet_info = _pcap.packet_info() loop = True count = 10000 sizes: Dict[int, Dict[int, int]] = {} while loop and count > 0: if not _pcap.next_packet_info(p, packet_info): loop = False else: if packet_info.payload_size not in sizes: sizes[packet_info.payload_size] = {} if packet_info.dst_port not in sizes[packet_info.payload_size]: sizes[packet_info.payload_size][packet_info.dst_port] = 0 sizes[packet_info.payload_size][packet_info.dst_port] += 1 count -= 1 _pcap.replay_uninitialize(p) return _guess_lidar_port(sizes), _guess_imu_port(sizes)
def __init__(self, pcap_path: str, info: SensorInfo, *, rate: float = 0.0, lidar_port: int = 0, imu_port: int = 0) -> None: """Read a single-sensor data stream from a packet capture. This assumes a pcap contains the packet stream of a single sensor and attempts to guess which destination ports were associated with lidar vs. imu data based on packet sizes, unless explicitly specified. When a rate is specified, output packets in (a multiple of) real time using the pcap packet capture timestamps. Args: info: Sensor metadata pcap_path: File path of recorded pcap rate: Output packets in real time, if non-zero lidar_port: Specify the destination port of lidar packets imu_port: Specify the destination port of imu packets Returns: An iterator of lidar and IMU packets. """ pcap_info = _pcap.replay_get_pcap_info(pcap_path, 10000) lidar_port_guess, imu_port_guess = _guess_ports(pcap_info) # use guessed values unless ports are specified (0 is falsey) self._lidar_port = lidar_port or lidar_port_guess self._imu_port = imu_port or imu_port_guess self._metadata = info self._rate = rate self._handle = _pcap.replay_initialize(pcap_path, "", "", {}) self._lock = Lock()