aboutsummaryrefslogtreecommitdiffstats
path: root/libmproxy/protocol
diff options
context:
space:
mode:
Diffstat (limited to 'libmproxy/protocol')
-rw-r--r--libmproxy/protocol/__init__.py11
-rw-r--r--libmproxy/protocol/http.py26
-rw-r--r--libmproxy/protocol/tcp.py57
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