diff options
Diffstat (limited to 'libmproxy')
-rw-r--r-- | libmproxy/cmdline.py | 4 | ||||
-rw-r--r-- | libmproxy/console/__init__.py | 45 | ||||
-rw-r--r-- | libmproxy/dump.py | 15 | ||||
-rw-r--r-- | libmproxy/flow.py | 19 | ||||
-rw-r--r-- | libmproxy/protocol/http.py | 6 | ||||
-rw-r--r-- | libmproxy/protocol/tcp.py | 6 |
6 files changed, 57 insertions, 38 deletions
diff --git a/libmproxy/cmdline.py b/libmproxy/cmdline.py index 185944da..e45cc54c 100644 --- a/libmproxy/cmdline.py +++ b/libmproxy/cmdline.py @@ -418,14 +418,14 @@ def common_options(parser): group = parser.add_argument_group("Client Replay") group.add_argument( "-c", "--client-replay", - action="store", dest="client_replay", default=None, metavar="PATH", + action="append", dest="client_replay", default=None, metavar="PATH", help="Replay client requests from a saved file." ) group = parser.add_argument_group("Server Replay") group.add_argument( "-S", "--server-replay", - action="store", dest="server_replay", default=None, metavar="PATH", + action="append", dest="server_replay", default=None, metavar="PATH", help="Replay server responses from a saved file." ) group.add_argument( diff --git a/libmproxy/console/__init__.py b/libmproxy/console/__init__.py index dc20d21f..0db06832 100644 --- a/libmproxy/console/__init__.py +++ b/libmproxy/console/__init__.py @@ -498,37 +498,34 @@ class ConsoleMaster(flow.FlowMaster): self.eventlog = not self.eventlog self.view_flowlist() - def _readflow(self, path): - path = os.path.expanduser(path) + def _readflow(self, paths): + """ + Utitility function that reads a list of flows + or prints an error to the UI if that fails. + Returns + - None, if there was an error. + - a list of flows, otherwise. + """ try: - f = file(path, "rb") - flows = list(flow.FlowReader(f).stream()) - except (IOError, flow.FlowReadError), v: - return True, v.strerror - return False, flows - - def client_playback_path(self, path): - err, ret = self._readflow(path) - if err: + return flow.read_flows_from_paths(paths) + except flow.FlowReadError as e: if not self.statusbar: - print >> sys.stderr, ret + print >> sys.stderr, e.strerror sys.exit(1) else: - self.statusbar.message(ret) - else: - self.start_client_playback(ret, False) + self.statusbar.message(e.strerror) + return None + + def client_playback_path(self, path): + flows = self._readflow(path) + if flows: + self.start_client_playback(flows, False) def server_playback_path(self, path): - err, ret = self._readflow(path) - if err: - if not self.statusbar: - print >> sys.stderr, ret - sys.exit(1) - else: - self.statusbar.message(ret) - else: + flows = self._readflow(path) + if flows: self.start_server_playback( - ret, + flows, self.killextra, self.rheaders, False, self.nopop, self.options.replay_ignore_params, self.options.replay_ignore_content, self.options.replay_ignore_payload_params diff --git a/libmproxy/dump.py b/libmproxy/dump.py index 91ccb42b..59ddcf5f 100644 --- a/libmproxy/dump.py +++ b/libmproxy/dump.py @@ -143,14 +143,15 @@ class DumpMaster(flow.FlowMaster): if self.o.app: self.start_app(self.o.app_host, self.o.app_port) - def _readflow(self, path): - path = os.path.expanduser(path) + def _readflow(self, paths): + """ + Utitility function that reads a list of flows + or raises a DumpError if that fails. + """ try: - f = file(path, "rb") - flows = list(flow.FlowReader(f).stream()) - except (IOError, flow.FlowReadError), v: - raise DumpError(v.strerror) - return flows + return flow.read_flows_from_paths(paths) + except flow.FlowReadError as e: + raise DumpError(e.strerror) def add_event(self, e, level="info"): needed = dict(error=0, info=1, debug=2).get(level, 1) diff --git a/libmproxy/flow.py b/libmproxy/flow.py index 97ebc572..f9e2b94d 100644 --- a/libmproxy/flow.py +++ b/libmproxy/flow.py @@ -945,6 +945,25 @@ class FlowMaster(controller.Master): self.stream = None +def read_flows_from_paths(paths): + """ + Given a list of filepaths, read all flows and return a list of them. + From a performance perspective, streaming would be advisable - + however, if there's an error with one of the files, we want it to be raised immediately. + + If an error occurs, a FlowReadError will be raised. + """ + try: + flows = [] + for path in paths: + path = os.path.expanduser(path) + with file(path, "rb") as f: + flows.extend(FlowReader(f).stream()) + except IOError as e: + raise FlowReadError(e.strerror) + return flows + + class FlowWriter: def __init__(self, fo): self.fo = fo diff --git a/libmproxy/protocol/http.py b/libmproxy/protocol/http.py index 50691ea2..284731b0 100644 --- a/libmproxy/protocol/http.py +++ b/libmproxy/protocol/http.py @@ -995,7 +995,7 @@ class HTTPHandler(ProtocolHandler): include_body=False ) break - except (tcp.NetLibDisconnect, http.HttpErrorConnClosed), v: + except (tcp.NetLibError, http.HttpErrorConnClosed), v: self.c.log( "error in server communication: %s" % repr(v), level="debug" @@ -1042,7 +1042,7 @@ class HTTPHandler(ProtocolHandler): self.c.client_conn.rfile, body_size_limit=self.c.config.body_size_limit ) - except tcp.NetLibDisconnect: + except tcp.NetLibError: # don't throw an error for disconnects that happen # before/between requests. return False @@ -1140,7 +1140,7 @@ class HTTPHandler(ProtocolHandler): message = repr(error) message_debug = None - if isinstance(error, tcp.NetLibDisconnect): + if isinstance(error, tcp.NetLibError): message = None message_debug = "TCP connection closed unexpectedly." elif "tlsv1 alert unknown ca" in message: diff --git a/libmproxy/protocol/tcp.py b/libmproxy/protocol/tcp.py index da0c9087..d2d21829 100644 --- a/libmproxy/protocol/tcp.py +++ b/libmproxy/protocol/tcp.py @@ -3,6 +3,7 @@ import select import socket from .primitives import ProtocolHandler from netlib.utils import cleanBin +from netlib.tcp import NetLibError class TCPHandler(ProtocolHandler): @@ -76,7 +77,8 @@ class TCPHandler(ProtocolHandler): ), "info" ) - dst.connection.send(contents) + # Do not use dst.connection.send here, which may raise OpenSSL-specific errors. + dst.send(contents) else: # socket.socket.send supports raw bytearrays/memoryviews if self.log: @@ -87,6 +89,6 @@ class TCPHandler(ProtocolHandler): "info" ) dst.connection.send(buf[:size]) - except socket.error as e: + except (socket.error, NetLibError) as e: self.c.log("TCP connection closed unexpectedly.", "debug") return |