diff options
Diffstat (limited to 'libmproxy/protocol')
-rw-r--r-- | libmproxy/protocol/__init__.py | 11 | ||||
-rw-r--r-- | libmproxy/protocol/http.py | 26 | ||||
-rw-r--r-- | libmproxy/protocol/tcp.py | 57 |
3 files changed, 74 insertions, 20 deletions
diff --git a/libmproxy/protocol/__init__.py b/libmproxy/protocol/__init__.py index 5419c5ef..5e11e750 100644 --- a/libmproxy/protocol/__init__.py +++ b/libmproxy/protocol/__init__.py @@ -12,6 +12,7 @@ class ConnectionTypeChange(Exception): class ProtocolHandler(object): def __init__(self, c): self.c = c + """@type : libmproxy.proxy.ConnectionHandler""" def handle_messages(self): """ @@ -27,13 +28,17 @@ class ProtocolHandler(object): """ raise NotImplementedError +from . import http, tcp -from .http import HTTPHandler +protocols = dict( + http = dict(handler=http.HTTPHandler, flow=http.HTTPFlow), + tcp = dict(handler=tcp.TCPHandler), +) def _handler(conntype, connection_handler): - if conntype == "http": - return HTTPHandler(connection_handler) + if conntype in protocols: + return protocols[conntype]["handler"](connection_handler) raise NotImplementedError diff --git a/libmproxy/protocol/http.py b/libmproxy/protocol/http.py index 4a3933e7..b79fc7b3 100644 --- a/libmproxy/protocol/http.py +++ b/libmproxy/protocol/http.py @@ -1,17 +1,11 @@ -import Cookie +import Cookie, urllib, urlparse, time, copy from email.utils import parsedate_tz, formatdate, mktime_tz -import urllib -import urlparse -import time -import copy -from ..flow import SimpleStateObject -from netlib import http, tcp, http_status -from netlib.odict import ODict, ODictCaseless import netlib.utils -from .. import encoding, utils, version, filt, controller -from ..proxy import ProxyError, ServerConnection, ClientConnection +from netlib import http, tcp, http_status, stateobject, odict +from netlib.odict import ODict, ODictCaseless from . import ProtocolHandler, ConnectionTypeChange, KILL -import libmproxy.flow +from .. import encoding, utils, version, filt, controller +from ..proxy import ProxyError, ClientConnection, ServerConnection HDR_FORM_URLENCODED = "application/x-www-form-urlencoded" CONTENT_MISSING = 0 @@ -57,7 +51,7 @@ class decoded(object): if self.ce: self.o.encode(self.ce) - +# FIXME: Move out of http class BackreferenceMixin(object): """ If an attribute from the _backrefattr tuple is set, @@ -73,12 +67,10 @@ class BackreferenceMixin(object): def __setattr__(self, key, value): super(BackreferenceMixin, self).__setattr__(key, value) if key in self._backrefattr and value is not None: - # check if there is already a different object set as backref - assert (getattr(value, self._backrefname, self) or self) is self setattr(value, self._backrefname, self) # FIXME: Move out of http -class Error(SimpleStateObject): +class Error(stateobject.SimpleStateObject): """ An Error. @@ -107,7 +99,7 @@ class Error(SimpleStateObject): return c # FIXME: Move out of http -class Flow(SimpleStateObject, BackreferenceMixin): +class Flow(stateobject.SimpleStateObject, BackreferenceMixin): def __init__(self, conntype, client_conn, server_conn, error): self.conntype = conntype self.client_conn = client_conn @@ -167,7 +159,7 @@ class Flow(SimpleStateObject, BackreferenceMixin): self._backup = None -class HTTPMessage(SimpleStateObject): +class HTTPMessage(stateobject.SimpleStateObject): def __init__(self): self.flow = None # Will usually set by backref mixin diff --git a/libmproxy/protocol/tcp.py b/libmproxy/protocol/tcp.py new file mode 100644 index 00000000..9fb2e01b --- /dev/null +++ b/libmproxy/protocol/tcp.py @@ -0,0 +1,57 @@ +from . import ProtocolHandler +import select, socket +from cStringIO import StringIO + + +class TCPHandler(ProtocolHandler): + """ + TCPHandler acts as a generic TCP forwarder. + Data will be .log()ed, but not stored any further. + """ + def handle_messages(self): + conns = [self.c.client_conn.rfile, self.c.server_conn.rfile] + while not self.c.close: + r, _, _ = select.select(conns, [], [], 10) + for rfile in r: + if self.c.client_conn.rfile == rfile: + src, dst = self.c.client_conn, self.c.server_conn + src_str, dst_str = "client", "server" + else: + dst, src = self.c.client_conn, self.c.server_conn + dst_str, src_str = "client", "server" + + data = StringIO() + while range(4096): + # Do non-blocking select() to see if there is further data on in the buffer. + r, _, _ = select.select([rfile], [], [], 0) + if len(r): + d = rfile.read(1) + if d == "": # connection closed + break + data.write(d) + + """ + OpenSSL Connections have an internal buffer that might contain data altough everything is read + from the socket. Thankfully, connection.pending() returns the amount of bytes in this buffer, + so we can read it completely at once. + """ + if src.ssl_established: + data.write(rfile.read(src.connection.pending())) + else: # no data left, but not closed yet + break + data = data.getvalue() + + if data == "": # no data received, rfile is closed + self.c.log("Close writing connection to %s" % dst_str) + conns.remove(rfile) + if dst.ssl_established: + dst.connection.shutdown() + else: + dst.connection.shutdown(socket.SHUT_WR) + if len(conns) == 0: + self.c.close = True + break + + self.c.log("%s -> %s" % (src_str, dst_str), ["\r\n" + data]) + dst.wfile.write(data) + dst.wfile.flush()
\ No newline at end of file |