Integrate GapString and a few tweaks

This commit is contained in:
Neale Pickett 2008-01-18 19:09:09 -07:00
parent 473d1fc440
commit 9d487edfb3
4 changed files with 103 additions and 59 deletions

View File

@ -10,47 +10,82 @@ def unpack(fmt, buf):
"""Unpack buf based on fmt, return the rest as a string.""" """Unpack buf based on fmt, return the rest as a string."""
size = struct.calcsize(fmt) size = struct.calcsize(fmt)
vals = struct.unpack(fmt, buf[:size]) vals = struct.unpack(fmt, str(buf[:size]))
return vals + (buf[size:],) return vals + (buf[size:],)
def to_printable(c): class HexDumper:
if c in printable: def __init__(self, fd=sys.stdout):
return c self.fd = fd
elif c == '\0': self.offset = 0
return '' self.buf = []
elif c == '\r':
return '' def _to_printable(self, c):
elif c == '\n': if not c:
return '' return ''
else: elif c in printable:
return '·' return c
elif c == '\0':
return ''
elif c == '\r':
return ''
elif c == '\n':
return ''
else:
return '·'
def _flush(self):
if not self.buf:
return
o = []
for c in self.buf:
if c:
o.append('%02x' % ord(c))
else:
o.append('--')
o += ([' '] * (16 - len(self.buf)))
p = [self._to_printable(c) for c in self.buf]
self.fd.write('%08x ' % self.offset)
self.fd.write(' '.join(o[:8]))
self.fd.write(' ')
self.fd.write(' '.join(o[8:]))
self.fd.write('')
self.fd.write(''.join(p))
self.fd.write('\n')
self.buf = []
self.offset += 16
def dump_chr(self, c):
self.buf.append(c)
if len(self.buf) == 16:
self._flush()
def dump_drop(self):
self.buf.append(None)
if len(self.buf) == 16:
self._flush()
def finish(self):
self._flush()
self.fd.write('%08x\n' % self.offset)
def hexdump(buf, f=sys.stdout): def hexdump(buf, f=sys.stdout):
"Print a hex dump of buf" "Print a hex dump of buf"
offset = 0 d = HexDumper()
while buf: for c in buf:
s = buf[:16] d.dump_chr(c)
o = [('%02x' % ord(c)) for c in s] + ([' '] * (16 - len(s))) d.finish()
p = [to_printable(c) for c in s]
f.write('%08x ' % offset)
f.write(' '.join(o[:8]))
f.write(' ')
f.write(' '.join(o[8:]))
f.write('')
f.write(''.join(p))
f.write('\n')
buf = buf[16:]
offset += 16
def cstring(buf): def cstring(buf):

View File

@ -186,11 +186,10 @@ tabula_recta = caesars('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
def xor(n, txt): def xor(n, txt):
out = '' if n == 0:
for c in txt: return txt
o = ord(c) ^ n out = [(chr(ord(c) ^ n)) for c in txt]
out += chr(o) return ''.join(out)
return out
def xors(txt): def xors(txt):
ret = [] ret = []

View File

@ -48,7 +48,7 @@ class GapString:
else: else:
for c in i: for c in i:
d.dump_chr(c) d.dump_chr(c)
d.flush() d.finish()
def extend(self, other): def extend(self, other):
self.contents += other.contents self.contents += other.contents
@ -56,10 +56,14 @@ class GapString:
def __getslice__(self, start, end): def __getslice__(self, start, end):
end = min(self.length, end) end = min(self.length, end)
start = min(self.length, start)
new = self.__class__(self.drop) new = self.__class__(self.drop)
new.contents = self.contents[:] new.contents = self.contents[:]
new.length = end - start new.length = end - start
if new.length == 0:
return new
l = self.length - new.length - start l = self.length - new.length - start
# Trim off the beginning # Trim off the beginning

48
ip.py
View File

@ -5,6 +5,7 @@ import struct
import socket import socket
import warnings import warnings
import heapq import heapq
import gapstr
def unpack(fmt, buf): def unpack(fmt, buf):
@ -110,18 +111,13 @@ class Frame:
self.dst_addr, self.dport, self.dst_addr, self.dport,
len(self.payload)) len(self.payload))
class Chunk: class Chunk:
"""Chunk of frames, possibly with gaps. """Chunk of frames, possibly with gaps.
Currently, gaps show up as a string of 0x33, ascii '3'.
""" """
def __init__(self, seq=None, drop='3'): def __init__(self, seq=None):
# chr(0x33) == '3'. If you see a bunch of 3s, in the ascii or
# the hex view, suspect a drop.
assert len(drop) == 1, "Don't yet support len(drop) > 1"
self.drop = drop
self.collection = {} self.collection = {}
self.length = 0 self.length = 0
self.seq = seq self.seq = seq
@ -130,8 +126,8 @@ class Chunk:
def add(self, frame): def add(self, frame):
if not self.first: if not self.first:
self.first = frame self.first = frame
if self.seq is None: if self.seq is None:
self.seq = frame.seq self.seq = frame.seq
assert frame.seq >= self.seq, (frame.seq, self.seq) assert frame.seq >= self.seq, (frame.seq, self.seq)
self.collection[frame.seq] = frame self.collection[frame.seq] = frame
end = frame.seq - self.seq + len(frame.payload) end = frame.seq - self.seq + len(frame.payload)
@ -150,25 +146,35 @@ class Chunk:
else: else:
return '<Chunk (no frames)>' return '<Chunk (no frames)>'
def __str__(self): def gapstr(self, drop='?'):
s = '' """Return contents as a GapString"""
while len(s) < self.length:
f = self.collection.get(self.seq + len(s)) ret = gapstr.GapString(drop)
while len(ret) < self.length:
f = self.collection.get(self.seq + len(ret))
if f: if f:
s += f.payload ret.append(f.payload)
else: else:
# This is where to fix it for len(drop) > 1. # This is where to fix big inefficiency for dropped packets.
# This is also where to fix big inefficiency for dropped packets. l = 1
s += self.drop while ((len(ret) + l < self.length) and
return s (not (self.seq + len(ret) + l) in self.collection)):
l += 1
ret.append(l)
return ret
def __str__(self):
return str(self.gapstr())
def extend(self, other): def extend(self, other):
self.seq = min(self.seq or other.seq, other.seq) self.seq = min(self.seq or other.seq, other.seq)
for frame in other.collection.itervalues(): self.length = self.length + other.length
self.add(frame) if not self.first:
self.first = other.first
self.collection.update(other.collection)
def __add__(self, next): def __add__(self, next):
new = self.__class__(self.seq, self.drop) new = self.__class__(self.seq)
new.extend(self) new.extend(self)
new.extend(next) new.extend(next)
return new return new