Skip to content

Commit 7ebd4cf

Browse files
committed
working on pcapng protocol impl (read done)
1 parent 3738773 commit 7ebd4cf

File tree

1 file changed

+44
-3
lines changed

1 file changed

+44
-3
lines changed

pcapkit/protocols/misc/pcapng.py

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@
159159
from pcapkit.protocols.schema.misc.pcapng import ZigBeeAPSKey as Schema_ZigBeeAPSKey
160160
from pcapkit.protocols.schema.misc.pcapng import ZigBeeNWKKey as Schema_ZigBeeNWKKey
161161
from pcapkit.utilities.compat import StrEnum
162-
from pcapkit.utilities.exceptions import EndianError, FileError, UnsupportedCall
162+
from pcapkit.utilities.exceptions import EndianError, FileError, ProtocolError, UnsupportedCall
163163
from pcapkit.utilities.warnings import RegistryWarning, warn
164164

165165
__all__ = ['PCAPNG']
@@ -725,7 +725,8 @@ def unpack(self, length: 'Optional[int]' = None, **kwargs: 'Any') -> 'Data_PCAPN
725725
self.__header__ = cast('Schema_PCAPNG', self.__schema__.unpack(self._file, length, packet)) # type: ignore[call-arg,misc]
726726
return self.read(length, **kwargs)
727727

728-
def read(self, length: 'Optional[int]' = None, **kwargs: 'Any') -> 'Data_PCAPNG':
728+
def read(self, length: 'Optional[int]' = None, *, _read: 'bool' = True,
729+
_seek_set: 'int' = 0, **kwargs: 'Any') -> 'Data_PCAPNG':
729730
r"""Read PCAP-NG file blocks.
730731
731732
Structure of PCAP-NG file blocks:
@@ -746,12 +747,49 @@ def read(self, length: 'Optional[int]' = None, **kwargs: 'Any') -> 'Data_PCAPNG'
746747
747748
Args:
748749
length: Length of data to be read.
750+
\_read: If the class is called in a parsing scenario.
751+
\_seek_set: File offset before reading.
749752
**kwargs: Arbitrary keyword arguments.
750753
751754
Returns:
752755
Parsed packet data.
753756
754757
"""
758+
schema = self.__header__
759+
760+
if schema.block.length < 12 or schema.block.length % 4 != 0:
761+
raise ProtocolError(f'PCAP-NG: [Block {schema.type}] invalid length: {schema.block.length}')
762+
763+
name = self.__block__[schema.type]
764+
if isinstance(name, str):
765+
meth_name = f'_read_block_{name}'
766+
meth = cast('BlockParser',
767+
getattr(self, meth_name, self._read_block_unknown))
768+
else:
769+
meth = name[0]
770+
block = meth(schema.block, header=schema)
771+
772+
if not _read:
773+
# move backward to the beginning of the packet
774+
self._file.seek(0, io.SEEK_SET)
775+
else:
776+
# NOTE: We create a copy of the block data here for parsing
777+
# scenarios to keep the original packet data intact.
778+
seek_cur = self._file.tell()
779+
780+
# move backward to the beginning of the block
781+
self._file.seek(_seek_set, io.SEEK_SET)
782+
783+
#: bytes: Raw block data.
784+
self._data = self._read_fileng(schema.block.length)
785+
786+
# move backward to the beginning of next block
787+
self._file.seek(seek_cur, io.SEEK_SET)
788+
789+
#: io.BytesIO: Source packet stream.
790+
self._file = io.BytesIO(self._data)
791+
792+
return block
755793

756794
def make(self,
757795
**kwargs: 'Any') -> 'Schema_PCAPNG':
@@ -801,16 +839,19 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, length: 'Opt
801839
self._ctx = ctx
802840

803841
if file is None:
842+
_read = False
804843
#: bytes: Raw packet data.
805844
self._data = self.pack(**kwargs)
806845
#: io.BytesIO: Source packet stream.
807846
self._file = io.BytesIO(self._data)
808847
else:
848+
_read = True
809849
#: io.BytesIO: Source packet stream.
810850
self._file = io.BytesIO(file) if isinstance(file, bytes) else file
851+
_seek_set = self._file.tell()
811852

812853
#: pcapkit.corekit.infoclass.Info: Parsed packet data.
813-
self._info = self.unpack(length, **kwargs)
854+
self._info = self.unpack(length, _read=_read, _seek_set=_seek_set, **kwargs)
814855

815856
def __length_hint__(self) -> 'Literal[12]':
816857
"""Return an estimated length for the object."""

0 commit comments

Comments
 (0)