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 __iter__(self) -> Iterator[Packet]: buf = bytearray(2**16) packet_info = _pcap.packet_info() real_start_ts = time.monotonic() pcap_start_ts = None while True: with self._lock: if self._handle is None: break if not _pcap.next_packet_info(self._handle, packet_info): break n = _pcap.read_packet(self._handle, buf) if self._rate: if not pcap_start_ts: pcap_start_ts = packet_info.timestamp real_delta = time.monotonic() - real_start_ts pcap_delta = (packet_info.timestamp - pcap_start_ts) / self._rate delta = max(0, pcap_delta.total_seconds() - real_delta) time.sleep(delta) if packet_info.dst_port == self._lidar_port and n != 0: yield LidarPacket(buf[0:n], self._metadata) elif packet_info.dst_port == self._imu_port and n != 0: yield ImuPacket(buf[0:n], self._metadata)
def __iter__(self) -> Iterator[Packet]: with self._lock: if self._handle is None: raise ValueError("I/O operation on closed packet source") buf = bytearray(2**16) packet_info = _pcap.packet_info() real_start_ts = time.monotonic() pcap_start_ts = None metadata = self._metadata while True: with self._lock: if (self._handle is None or not _pcap.next_packet_info(self._handle, packet_info)): break timestamp = packet_info.timestamp n = _pcap.read_packet(self._handle, buf) if self._rate: if not pcap_start_ts: pcap_start_ts = packet_info.timestamp real_delta = time.monotonic() - real_start_ts pcap_delta = (packet_info.timestamp - pcap_start_ts) / self._rate delta = max(0, pcap_delta - real_delta) time.sleep(delta) if packet_info.dst_port == self._lidar_port and n != 0: yield LidarPacket(buf[0:n], metadata, timestamp) elif packet_info.dst_port == self._imu_port and n != 0: yield ImuPacket(buf[0:n], metadata, timestamp)
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)