- commit
- 6a1cbae
- parent
- 8cd7cb0
- author
- Neale Pickett
- date
- 2021-07-02 17:18:59 -0600 MDT
Add xmodem example
7 files changed,
+69,
-17
+5,
-2
1@@ -11,6 +11,9 @@ and room to grow these explorations into full-blown decoders.
2 Get going
3 =========
4
5-Documentation sucks, sorry.
6-The way we go about things is to copy `dumbdecode.py` to a new file,
7+Documentation doesn't exist. Sorry.
8+The way we go about things is to copy [dumbdecode](examples/dumbdecode.py) to a new file,
9 and start hacking onto it.
10+
11+You may find the [example xmodem decoder](examples/xmodem.py) to be helpful!
12+It illustrates a fair amount of what the library provides.
R netarch/dumbdecode.py =>
examples/dumbdecode.py
+1,
-2
1@@ -1,7 +1,6 @@
2 #! /usr/bin/python3
3
4 import netarch
5-import sys
6
7 class DumbPacket(netarch.Packet):
8 def parse(self, data):
9@@ -10,4 +9,4 @@ class DumbPacket(netarch.Packet):
10 class DumbSession(netarch.Session):
11 Packet = DumbPacket
12
13-netarch.main(DumbSession, sys.argv[1:])
14+netarch.main(DumbSession)
+0,
-0
+45,
-0
1@@ -0,0 +1,45 @@
2+#! /usr/bin/python3
3+
4+import netarch
5+
6+class XmodemPacket(netarch.Packet):
7+ def parse(self, data):
8+ datastream = netarch.Unpacker(data)
9+ self.opcode = datastream.uint8()
10+ self.payload = datastream.buf
11+
12+ def opcode_1(self):
13+ "Xfer"
14+ datastream = netarch.Unpacker(self.payload)
15+ self["seq"] = datastream.uint8()
16+ self["~seq"] = datastream.uint8()
17+
18+ assert self["seq"] == 255 - self["~seq"]
19+ assert len(datastream.buf) == 0x81
20+
21+ self["checksum"] = datastream.uint8(pos=-1)
22+ self.payload = datastream.buf
23+
24+ def opcode_4(self):
25+ "EOT"
26+
27+ def opcode_6(self):
28+ "ACK"
29+
30+ def opcode_21(self):
31+ "Begin transmission?"
32+
33+class XmodemSession(netarch.Session):
34+ Packet = XmodemPacket
35+
36+ def process(self, packet):
37+ packet.show()
38+
39+ if packet.opcode == 21:
40+ # Open a new file for output
41+ self.out = self.open_out("data.bin")
42+ elif packet.opcode == 1:
43+ self.out.write(bytes(packet.payload))
44+
45+
46+netarch.main(XmodemSession)
+5,
-2
1@@ -2,8 +2,9 @@
2
3 import binascii
4 import struct
5+import sys
6 from . import ip
7-
8+from .unpack import Unpacker
9
10
11 def cstring(buf):
12@@ -180,8 +181,10 @@ def _registry(encoding):
13
14 codecs.register(_registry)
15
16-def main(session, pcaps):
17+def main(session, pcaps=None):
18 s = None
19+ if not pcaps:
20+ pcaps = sys.argv[1:]
21 reseq = ip.Dispatch(*pcaps)
22 for _, d in reseq:
23 srv, first, chunk = d
+12,
-10
1@@ -39,7 +39,7 @@ class Unpacker:
2 self.endian = endian
3 self.buf = buf
4
5- def uint(self, size, endian=None):
6+ def uint(self, size, pos=0, endian=None):
7 endian = endian or self.endian
8 if size not in (8, 16, 32, 64):
9 # XXX: I'm pretty sure this can be done, but I don't want to code it up right now.
10@@ -53,20 +53,22 @@ class Unpacker:
11 r = (1, 0, 3, 2, 5, 4, 7, 6)[:noctets]
12 else:
13 raise ValueError("Unsupported byte order")
14- pull, self.buf = self.buf[:noctets], self.buf[noctets:]
15+ if pos < 0:
16+ pos += len(self.buf)
17+ pull, self.buf = self.buf[pos:pos+noctets], self.buf[:pos] + self.buf[pos+noctets:]
18 acc = 0
19 for i in r:
20 acc = (acc << 8) | pull[i]
21 return acc
22
23- def uint8(self):
24- return self.uint(8)
25- def uint16(self, endian=None):
26- return self.uint(16, endian)
27- def uint32(self, endian=None):
28- return self.uint(32, endian)
29- def uint64(self, endian=None):
30- return self.uint(64, endian)
31+ def uint8(self, pos=0):
32+ return self.uint(8, pos)
33+ def uint16(self, pos=0, endian=None):
34+ return self.uint(16, pos, endian)
35+ def uint32(self, pos=0, endian=None):
36+ return self.uint(32, pos, endian)
37+ def uint64(self, pos=0, endian=None):
38+ return self.uint(64, pos, endian)
39
40 if __name__ == "__main__":
41 import doctest
M
setup.py
+1,
-1
1@@ -38,7 +38,7 @@ setup(
2 # For a discussion on single-sourcing the version across setup.py and the
3 # project code, see
4 # https://packaging.python.org/en/latest/single_source_version.html
5- version='1.0.1', # Required
6+ version='2.1.0', # Required
7
8 # This is a one-line description or tagline of what your project does. This
9 # corresponds to the "Summary" metadata field: