aboutsummaryrefslogtreecommitdiffstats
path: root/libmproxy/protocol/primitives.py
diff options
context:
space:
mode:
Diffstat (limited to 'libmproxy/protocol/primitives.py')
-rw-r--r--libmproxy/protocol/primitives.py89
1 files changed, 52 insertions, 37 deletions
diff --git a/libmproxy/protocol/primitives.py b/libmproxy/protocol/primitives.py
index 160c50c7..1bf7f832 100644
--- a/libmproxy/protocol/primitives.py
+++ b/libmproxy/protocol/primitives.py
@@ -1,5 +1,6 @@
from __future__ import absolute_import
import copy
+import uuid
import netlib.tcp
from .. import stateobject, utils, version
from ..proxy.connection import ClientConnection, ServerConnection
@@ -8,14 +9,14 @@ from ..proxy.connection import ClientConnection, ServerConnection
KILL = 0 # const for killed requests
-class Error(stateobject.SimpleStateObject):
+class Error(stateobject.StateObject):
"""
An Error.
- This is distinct from an protocol error response (say, a HTTP code 500), which
- is represented by a normal HTTPResponse object. This class is responsible
- for indicating errors that fall outside of normal protocol communications,
- like interrupted connections, timeouts, protocol errors.
+ This is distinct from an protocol error response (say, a HTTP code 500),
+ which is represented by a normal HTTPResponse object. This class is
+ responsible for indicating errors that fall outside of normal protocol
+ communications, like interrupted connections, timeouts, protocol errors.
Exposes the following attributes:
@@ -41,9 +42,11 @@ class Error(stateobject.SimpleStateObject):
return self.msg
@classmethod
- def _from_state(cls, state):
- f = cls(None) # the default implementation assumes an empty constructor. Override accordingly.
- f._load_state(state)
+ def from_state(cls, state):
+ # the default implementation assumes an empty constructor. Override
+ # accordingly.
+ f = cls(None)
+ f.load_state(state)
return f
def copy(self):
@@ -51,13 +54,14 @@ class Error(stateobject.SimpleStateObject):
return c
-class Flow(stateobject.SimpleStateObject):
+class Flow(stateobject.StateObject):
"""
A Flow is a collection of objects representing a single transaction.
This class is usually subclassed for each protocol, e.g. HTTPFlow.
"""
- def __init__(self, conntype, client_conn, server_conn, live=None):
- self.conntype = conntype
+ def __init__(self, type, client_conn, server_conn, live=None):
+ self.type = type
+ self.id = str(uuid.uuid4())
self.client_conn = client_conn
"""@type: ClientConnection"""
self.server_conn = server_conn
@@ -70,14 +74,15 @@ class Flow(stateobject.SimpleStateObject):
self._backup = None
_stateobject_attributes = dict(
+ id=str,
error=Error,
client_conn=ClientConnection,
server_conn=ServerConnection,
- conntype=str
+ type=str
)
- def _get_state(self):
- d = super(Flow, self)._get_state()
+ def get_state(self, short=False):
+ d = super(Flow, self).get_state(short)
d.update(version=version.IVERSION)
return d
@@ -99,7 +104,7 @@ class Flow(stateobject.SimpleStateObject):
Has this Flow been modified?
"""
if self._backup:
- return self._backup != self._get_state()
+ return self._backup != self.get_state()
else:
return False
@@ -109,14 +114,14 @@ class Flow(stateobject.SimpleStateObject):
call to .revert().
"""
if not self._backup:
- self._backup = self._get_state()
+ self._backup = self.get_state()
def revert(self):
"""
Revert to the last backed up state.
"""
if self._backup:
- self._load_state(self._backup)
+ self.load_state(self._backup)
self._backup = None
@@ -133,31 +138,35 @@ class ProtocolHandler(object):
def handle_messages(self):
"""
- This method gets called if a client connection has been made. Depending on the proxy settings,
- a server connection might already exist as well.
+ This method gets called if a client connection has been made. Depending
+ on the proxy settings, a server connection might already exist as well.
"""
raise NotImplementedError # pragma: nocover
def handle_server_reconnect(self, state):
"""
- This method gets called if a server connection needs to reconnect and there's a state associated
- with the server connection (e.g. a previously-sent CONNECT request or a SOCKS proxy request).
- This method gets called after the connection has been restablished but before SSL is established.
+ This method gets called if a server connection needs to reconnect and
+ there's a state associated with the server connection (e.g. a
+ previously-sent CONNECT request or a SOCKS proxy request). This method
+ gets called after the connection has been restablished but before SSL is
+ established.
"""
raise NotImplementedError # pragma: nocover
def handle_error(self, error):
"""
- This method gets called should there be an uncaught exception during the connection.
- This might happen outside of handle_messages, e.g. if the initial SSL handshake fails in transparent mode.
+ This method gets called should there be an uncaught exception during the
+ connection. This might happen outside of handle_messages, e.g. if the
+ initial SSL handshake fails in transparent mode.
"""
raise error # pragma: nocover
class LiveConnection(object):
"""
- This facade allows interested parties (FlowMaster, inline scripts) to interface with a live connection,
- without requiring to expose the internals of the ConnectionHandler.
+ This facade allows interested parties (FlowMaster, inline scripts) to
+ interface with a live connection, without exposing the internals
+ of the ConnectionHandler.
"""
def __init__(self, c):
self.c = c
@@ -182,18 +191,23 @@ class LiveConnection(object):
if ssl_mismatch or address_mismatch or force:
- self.c.log("Change server connection: %s:%s -> %s:%s [persistent: %s]" % (
- self.c.server_conn.address.host,
- self.c.server_conn.address.port,
- address.host,
- address.port,
- persistent_change
- ), "debug")
+ self.c.log(
+ "Change server connection: %s:%s -> %s:%s [persistent: %s]" % (
+ self.c.server_conn.address.host,
+ self.c.server_conn.address.port,
+ address.host,
+ address.port,
+ persistent_change
+ ),
+ "debug"
+ )
if not self._backup_server_conn and not persistent_change:
self._backup_server_conn = self.c.server_conn
self.c.server_conn = None
- else: # This is at least the second temporary change. We can kill the current connection.
+ else:
+ # This is at least the second temporary change. We can kill the
+ # current connection.
self.c.del_server_connection()
self.c.set_server_address(address)
@@ -204,8 +218,9 @@ class LiveConnection(object):
return False
def restore_server(self):
- # TODO: Similar to _backup_server_conn, introduce _cache_server_conn, which keeps the changed connection open
- # This may be beneficial if a user is rewriting all requests from http to https or similar.
+ # TODO: Similar to _backup_server_conn, introduce _cache_server_conn,
+ # which keeps the changed connection open This may be beneficial if a
+ # user is rewriting all requests from http to https or similar.
if not self._backup_server_conn:
return
@@ -218,4 +233,4 @@ class LiveConnection(object):
self.c.del_server_connection()
self.c.server_conn = self._backup_server_conn
- self._backup_server_conn = None \ No newline at end of file
+ self._backup_server_conn = None