diff options
-rw-r--r-- | client.py | 15 | ||||
-rw-r--r-- | client_proto.py | 19 | ||||
-rwxr-xr-x | proxy.py | 31 | ||||
-rwxr-xr-x | spicedump.py | 47 |
4 files changed, 79 insertions, 33 deletions
@@ -8,6 +8,15 @@ import client_proto logger = logging.getLogger('client') +DEBUG_ENABLE_PDB=False + +if DEBUG_ENABLE_PDB: + def debug_break(): + import pdb; pdb.set_trace() +else: + def debug_break(): + pass + # TODO - parse spice/protocol.h directly (to keep in sync automatically) SPICE_MAGIC = "REDQ" SPICE_VERSION_MAJOR = 2 @@ -47,15 +56,15 @@ class SpiceDataHeader(Struct): inst = cls(*args, **kw) if inst.e.sub_list != 0 and inst.e.sub_list >= inst.e.size: logger.error('too large sub_list packet - %s' % inst) - import pdb; pdb.set_trace() + debug_break() return None if inst.e.type < 0 or inst.e.type >= 400: logger.error('bad type of packet - %s' % inst) - import pdb; pdb.set_trace() + debug_break() return None if inst.e.size > 2000000: logger.error('too large packet - %s' % inst) - import pdb; pdb.set_trace() + debug_break() return None return inst diff --git a/client_proto.py b/client_proto.py index d5d4515..4f66852 100644 --- a/client_proto.py +++ b/client_proto.py @@ -2,18 +2,23 @@ Decode spice protocol using spice demarshaller. """ -ANNOTATE = False +ANNOTATE = True NO_PRINT_PROTECTION = False import logging - -logger = logging.getLogger('client_proto') - +import os from collections import namedtuple import struct import sys + +# we assume we are side by side with spice. hopefully, that is so. +spice_dir = os.path.join(os.path.dirname(sys.modules[__name__].__file__), + '../spice') + +logger = logging.getLogger('client_proto') + if not 'proto' in locals(): - sys.path.append('../spice/python_modules') + sys.path.append(os.path.join(spice_dir, 'python_modules')) import spice_parser import ptypes proto = None @@ -346,9 +351,9 @@ def set_proto(major_version, minor_version): return globals().update(dict(major_version=major_version, minor_version=minor_version)) if major_version == 1 : - proto = spice_parser.parse('../spice/spice1.proto') + proto = spice_parser.parse(os.path.join(spice_dir, 'spice1.proto')) else: - proto = spice_parser.parse('../spice/spice.proto') + proto = spice_parser.parse(os.path.join(spice_dir, 'spice.proto')) channels = make_channels_dict(proto) num_spice_messages = sum(len(ch.client) + len(ch.server) for ch in @@ -40,9 +40,9 @@ class twowaydict(dict): BROKEN_PIPE_ERRNO, TRANSPORT_NOT_CONNECTED_ERRNO = 32, 107 -def make_accepter(port): +def make_accepter(port, host='127.0.0.1'): accepter = Socket(AF_INET, SOCK_STREAM) - accepter.bind(('0.0.0.0', port)) + accepter.bind((host, port)) accepter.listen(1) return accepter @@ -53,9 +53,9 @@ def connect(addr): return s class Proxy(object): - def __init__(self, local_port, remote_addr): + def __init__(self, local_port, remote_addr, host='127.0.0.1'): self._drop_next = False - self._proxy = _proxy(self, local_port, remote_addr) + self._proxy = _proxy(self, local_port, remote_addr, host) def drop_next(self): self._drop_next = True def check_drop_next(self): @@ -66,9 +66,9 @@ class Proxy(object): for x in self._proxy: yield x -def _proxy(proxy, local_port, remote_addr): +def _proxy(proxy, local_port, remote_addr, host = '127.0.0.1'): print "proxying from %s to %s" % (local_port, remote_addr) - accepter = make_accepter(local_port) + accepter = make_accepter(local_port, host) open_socks = twowaydict() close_errnos = set([BROKEN_PIPE_ERRNO, TRANSPORT_NOT_CONNECTED_ERRNO]) while True: @@ -136,6 +136,21 @@ def tests(): from_port, to_port = port_num, port_num+1000 proxy(port_num, ('localhost', port_num+1000)) -if __name__ == '__main__': - tests() +def main(): + import argparse + import sys + parser = argparse.ArgumentParser() + parser.add_argument('-l', '--local-port', type=int, required=True, help='set proxy local port') + parser.add_argument('-H', '--remote-host', default='localhost', help='set proxy remote address') + parser.add_argument('-p', '--remote-port', type=int, required=True, help='set proxy remote address') + parser.add_argument('-v', '--verbose', dest='verbose', action='count', help='verbosity', default=0) + opts, rest = parser.parse_known_args(sys.argv[1:]) + local_port = opts.local_port + remote_addr = (opts.remote_host, opts.remote_port) + p = proxy(local_port=local_port, remote_addr=remote_addr) + for ret in p: + if opts.verbose: + print repr(ret) +if __name__ == '__main__': + main() diff --git a/spicedump.py b/spicedump.py index aac6ff3..9f7c8bb 100755 --- a/spicedump.py +++ b/spicedump.py @@ -3,9 +3,10 @@ import sys from collections import defaultdict from itertools import izip_longest from time import time -from optparse import OptionParser +import argparse import textwrap import logging +import re import pcaputil from proxy import proxy, closeallsockets @@ -68,14 +69,26 @@ class SurfaceStatistics(object): for i, l in enumerate(textwrap.wrap(','.join(map(str, v)), width=40)): yield '%20s: %s' % (k if i == 0 else '', l) +def debug_break(): + import rpdb2; rpdb2.start_embedded_debugger('a') + def spicedump(p, opts, stdscr=None): + show_every_command = True + periodic_hist = False import pcapspice spice = pcapspice.spice_iter(p) hist = Histogram() surface_stat = SurfaceStatistics() last_print = start_time = time() messages = [] - filter = opts.filter + filter_exp = opts.filter + if filter_exp: + if filter_exp[0] == '-': + def filter(result_name, exp=re.compile(filter_exp[1:])): + return exp.match(result_name) + else: + def filter(result_name, exp=re.compile(filter_exp)): + return not exp.match(result_name) if stdscr: stdscr.erase() # replace the "for d in spice:" loop with a select @@ -87,7 +100,7 @@ def spicedump(p, opts, stdscr=None): d = spice.next() result_name = d.msg.data.result_name result_value = d.msg.data.result_value - if filter and result_name not in filter: + if filter_exp and filter(result_name): continue if hasattr(p, 'drop_next'): pass @@ -108,7 +121,9 @@ def spicedump(p, opts, stdscr=None): messages.extend(str(d).split('\n')) old_time, old_count = hist[result_name] hist[result_name] = (cur_time, old_count + 1) - if True or cur_time - last_print > dt: + if show_every_command: + print result_name + if periodic_hist and cur_time - last_print > dt: show(hist.show(), surface_stat.show()) print '\n'.join(messages[-20:]) last_print = cur_time @@ -122,22 +137,24 @@ def fromproxy(stdscr, local_port, remote_addr, opts): return spicedump(p, opts, stdscr=stdscr) if __name__ == '__main__': - parser = OptionParser() - parser.add_option('-p', '--proxy', dest='proxy', help='use proxy', + parser = argparse.ArgumentParser() + parser.add_argument('-p', '--proxy', dest='proxy', help='use proxy', action='store_true') - parser.add_option('-l', '--localport', dest='local_port', help='set proxy local port') - parser.add_option('-r', '--remoteaddr', dest='remote_addr', help='set proxy remote address') - parser.add_option('-v', '--verbose', dest='verbose', action='count', help='verbosity', default=0) - parser.add_option('-c', '--curses', dest='curses', action='store_true', help='use curses') - parser.add_option('-f', '--filter', dest='filter', help='filter messages') - opts, rest = parser.parse_args(sys.argv[1:]) + parser.add_argument('-l', '--local-port', type=int, help='set proxy local port') + parser.add_argument('-H', '--remote-host', default='localhost', help='set proxy remote address') + parser.add_argument('-p', '--remote-port', type=int, required=True, help='set proxy remote address') + parser.add_argument('-v', '--verbose', dest='verbose', action='count', help='verbosity', default=0) + parser.add_argument('-c', '--curses', dest='curses', action='store_true', help='use curses') + parser.add_argument('-f', '--filter', dest='filter', help='filter messages') + parser.add_argument('--record', dest='record', help='TODO: record to file, can be used to playback') + parser.add_argument('--playback', dest='playback', help='TODO: playback a previously recorded file') + opts, rest = parser.parse_known_args(sys.argv[1:]) if opts.verbose >= 2 in sys.argv: logging.basicConfig(filename='spicedump.log', level=logging.DEBUG) print "saving debug log to spicedump.log" if opts.proxy: - local_port = int(opts.local_port) - remote_addr = opts.remote_addr.split(':') - remote_addr = (remote_addr[0], int(remote_addr[1])) + local_port = opts.local_port + remote_addr = (opts.remote_host, opts.remote_port) main = (lambda stdscr, opts, local_port=local_port, remote_addr=remote_addr: fromproxy(stdscr, local_port, remote_addr, opts)) else: |