def _read_mode_ts(self, size, kind): """Read Time Stamp option. Structure of Timestamp (TS) option [:rfc:`791`]:: +--------+--------+--------+--------+ |01000100| length | pointer|oflw|flg| +--------+--------+--------+--------+ | internet address | +--------+--------+--------+--------+ | timestamp | +--------+--------+--------+--------+ | . | . . Arguments: size (int): length of option kind (Literal[68]): option kind value (TS) Returns: DataType_Opt_TimeStamp: extracted Time Stamp option Raises: ProtocolError: If the option is malformed. """ if size > 40 or size < 4: raise ProtocolError(f'{self.alias}: [OptNo {kind}] invalid format') _tptr = self._read_unpack(1) _oflg = self._read_binary(1) _oflw = int(_oflg[:4], base=2) _flag = int(_oflg[4:], base=2) if _tptr < 5: raise ProtocolError(f'{self.alias}: [OptNo {kind}] invalid format') data = dict( kind=kind, type=self._read_opt_type(kind), length=size, pointer=_tptr, overflow=_oflw, flag=_flag, ) endpoint = min(_tptr, size) if _flag == 0: if (size - 4) % 4 != 0: raise ProtocolError( f'{self.alias}: [OptNo {kind}] invalid format') counter = 5 timestamp = list() while counter < endpoint: counter += 4 time = self._read_unpack(4, lilendian=True) timestamp.append(datetime.datetime.fromtimestamp(time)) data['timestamp'] = timestamp or None elif _flag in (1, 3): if (size - 4) % 8 != 0: raise ProtocolError( f'{self.alias}: [OptNo {kind}] invalid format') counter = 5 ipaddress = list() # pylint: disable=redefined-outer-name timestamp = list() while counter < endpoint: counter += 8 ipaddress.append(self._read_ipv4_addr()) time = self._read_unpack(4, lilendian=True) timestamp.append(datetime.datetime.fromtimestamp(time)) data['ip'] = tuple(ipaddress) or None data['timestamp'] = tuple(timestamp) or None else: data['data'] = self._read_fileng(size - 4) or None return data
def _read_mode_ts(self, size, kind): """Read Time Stamp option. Positional arguments: * size - int, length of option * kind - int, 68 (TS) Returns: * dict -- extracted Time Stamp (TS) option Structure of Timestamp (TS) option [RFC 791]: +--------+--------+--------+--------+ |01000100| length | pointer|oflw|flg| +--------+--------+--------+--------+ | internet address | +--------+--------+--------+--------+ | timestamp | +--------+--------+--------+--------+ | . | . . Octets Bits Name Description 0 0 ip.ts.kind Kind (25) 0 0 ip.ts.type.copy Copied Flag (0) 0 1 ip.ts.type.class Option Class (0) 0 3 ip.ts.type.number Option Number (25) 1 8 ip.ts.length Length (≤40) 2 16 ip.ts.pointer Pointer (≥5) 3 24 ip.ts.overflow Overflow Octets 3 28 ip.ts.flag Flag 4 32 ip.ts.ip Internet Address 8 64 ip.ts.timestamp Timestamp """ if size > 40 or size < 4: raise ProtocolError(f'{self.alias}: [Optno {kind}] invalid format') _tptr = self._read_unpack(1) _oflg = self._read_binary(1) _oflw = int(_oflg[:4], base=2) _flag = int(_oflg[4:], base=2) if _tptr < 5: raise ProtocolError(f'{self.alias}: [Optno {kind}] invalid format') data = dict( kind=kind, type=self._read_opt_type(kind), length=size, pointer=_tptr, overflow=_oflw, flag=_flag, ) endpoint = min(_tptr, size) if _flag == 0: if (size - 4) % 4 != 0: raise ProtocolError( f'{self.alias}: [Optno {kind}] invalid format') counter = 5 timestamp = list() while counter < endpoint: counter += 4 time = self._read_unpack(4, lilendian=True) timestamp.append(datetime.datetime.fromtimestamp(time)) data['timestamp'] = timestamp or None elif _flag == 1 or _flag == 3: if (size - 4) % 8 != 0: raise ProtocolError( f'{self.alias}: [Optno {kind}] invalid format') counter = 5 ipaddress = list() timestamp = list() while counter < endpoint: counter += 8 ipaddress.append(self._read_ipv4_addr()) time = self._read_unpack(4, lilendian=True) timestamp.append(datetime.datetime.fromtimestamp(time)) data['ip'] = ipaddress or None data['timestamp'] = timestamp or None else: data['data'] = self._read_fileng(size - 4) or None return data