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."""
size = struct.calcsize(fmt)
vals = struct.unpack(fmt, buf[:size])
vals = struct.unpack(fmt, str(buf[:size]))
return vals + (buf[size:],)
def to_printable(c):
if c in printable:
return c
elif c == '\0':
return ''
elif c == '\r':
return ''
elif c == '\n':
return ''
else:
return '·'
class HexDumper:
def __init__(self, fd=sys.stdout):
self.fd = fd
self.offset = 0
self.buf = []
def _to_printable(self, c):
if not c:
return ''
elif c in printable:
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):
"Print a hex dump of buf"
offset = 0
d = HexDumper()
while buf:
s = buf[:16]
o = [('%02x' % ord(c)) for c in s] + ([' '] * (16 - len(s)))
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
for c in buf:
d.dump_chr(c)
d.finish()
def cstring(buf):

View File

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

View File

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

48
ip.py
View File

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