diff options
| author | Maximilian Hils <git@maximilianhils.com> | 2014-09-02 18:13:18 +0200 | 
|---|---|---|
| committer | Maximilian Hils <git@maximilianhils.com> | 2014-09-02 18:13:18 +0200 | 
| commit | 1e4e332ef9040928cb0548097e879d8e9a57f3a2 (patch) | |
| tree | 683623e7801511a561afe521ab4c6b864c387f0a /libmproxy/protocol | |
| parent | 1a41c15c039f871d5da85b6ce17e4f3006c4374a (diff) | |
| download | mitmproxy-1e4e332ef9040928cb0548097e879d8e9a57f3a2.tar.gz mitmproxy-1e4e332ef9040928cb0548097e879d8e9a57f3a2.tar.bz2 mitmproxy-1e4e332ef9040928cb0548097e879d8e9a57f3a2.zip  | |
improve error handling
Diffstat (limited to 'libmproxy/protocol')
| -rw-r--r-- | libmproxy/protocol/http.py | 22 | ||||
| -rw-r--r-- | libmproxy/protocol/tcp.py | 88 | 
2 files changed, 57 insertions, 53 deletions
diff --git a/libmproxy/protocol/http.py b/libmproxy/protocol/http.py index 82ee2b3c..038fde97 100644 --- a/libmproxy/protocol/http.py +++ b/libmproxy/protocol/http.py @@ -22,7 +22,7 @@ def get_line(fp):      if line == "\r\n" or line == "\n":  # Possible leftover from previous message          line = fp.readline()      if line == "": -        raise tcp.NetLibDisconnect +        raise tcp.NetLibDisconnect()      return line @@ -927,7 +927,7 @@ class HTTPHandler(ProtocolHandler):                                                 body_size_limit=self.c.config.body_size_limit, include_body=include_body)                  return res              except (tcp.NetLibDisconnect, http.HttpErrorConnClosed), v: -                self.c.log("error in server communication: %s" % str(v), level="debug") +                self.c.log("error in server communication: %s" % repr(v), level="debug")                  if i < 1:                      # In any case, we try to reconnect at least once.                      # This is necessary because it might be possible that we already initiated an upstream connection @@ -1064,23 +1064,23 @@ class HTTPHandler(ProtocolHandler):      def handle_error(self, error, flow=None):          message = repr(error) -        code = getattr(error, "code", 502) -        headers = getattr(error, "headers", None) -          if "tlsv1 alert unknown ca" in message: -            message = message + " \nThe client does not trust the proxy's certificate." +            message += " The client does not trust the proxy's certificate." -        self.c.log("error: %s" % message, level="info") +        if isinstance(error, tcp.NetLibDisconnect): +            self.c.log("TCP connection closed unexpectedly.", "debug", [repr(error)]) +        else: +            self.c.log("error: %s" % message, level="info")          if flow: -            flow.error = Error(message) -            # FIXME: no flows without request or with both request and response at the moment. +            # TODO: no flows without request or with both request and response at the moment.              if flow.request and not flow.response: +                flow.error = Error(message)                  self.c.channel.ask("error", flow.error) -        else: -            pass          try: +            code = getattr(error, "code", 502) +            headers = getattr(error, "headers", None)              self.send_error(code, message, headers)          except:              pass diff --git a/libmproxy/protocol/tcp.py b/libmproxy/protocol/tcp.py index 00dbf4b3..8411ba6c 100644 --- a/libmproxy/protocol/tcp.py +++ b/libmproxy/protocol/tcp.py @@ -16,51 +16,55 @@ class TCPHandler(ProtocolHandler):          server = "%s:%s" % self.c.server_conn.address()[:2]          buf = memoryview(bytearray(self.chunk_size)) -          conns = [self.c.client_conn.rfile, self.c.server_conn.rfile] -        while True: -            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 -                    direction = "-> tcp ->" -                    src_str, dst_str = "client", server -                else: -                    dst, src = self.c.client_conn, self.c.server_conn -                    direction = "<- tcp <-" -                    dst_str, src_str = "client", server -                closed = False -                if src.ssl_established: -                    # Unfortunately, pyOpenSSL lacks a recv_into function. -                    contents = src.rfile.read(1)  # We need to read a single byte before .pending() becomes usable -                    contents += src.rfile.read(src.connection.pending()) -                    if not contents: -                        closed = True -                else: -                    size = src.connection.recv_into(buf) -                    if not size: -                        closed = True +        try: +            while True: +                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 +                        direction = "-> tcp ->" +                        src_str, dst_str = "client", server +                    else: +                        dst, src = self.c.client_conn, self.c.server_conn +                        direction = "<- tcp <-" +                        dst_str, src_str = "client", server -                if closed: -                    conns.remove(src.rfile) -                    # Shutdown connection to the other peer -                    if dst.ssl_established: -                        dst.connection.shutdown() +                    closed = False +                    if src.ssl_established: +                        # Unfortunately, pyOpenSSL lacks a recv_into function. +                        contents = src.rfile.read(1)  # We need to read a single byte before .pending() becomes usable +                        contents += src.rfile.read(src.connection.pending()) +                        if not contents: +                            closed = True                      else: -                        dst.connection.shutdown(socket.SHUT_WR) +                        size = src.connection.recv_into(buf) +                        if not size: +                            closed = True -                    if len(conns) == 0: -                        return -                    continue +                    if closed: +                        conns.remove(src.rfile) +                        # Shutdown connection to the other peer +                        if dst.ssl_established: +                            dst.connection.shutdown() +                        else: +                            dst.connection.shutdown(socket.SHUT_WR) -                if src.ssl_established or dst.ssl_established: -                    # if one of the peers is over SSL, we need to send bytes/strings -                    if not src.ssl_established:  # only ssl to dst, i.e. we revc'd into buf but need bytes/string now. -                        contents = buf[:size].tobytes() -                    self.c.log("%s %s\r\n%s" % (direction, dst_str, cleanBin(contents)), "debug") -                    dst.connection.send(contents) -                else: -                    # socket.socket.send supports raw bytearrays/memoryviews -                    self.c.log("%s %s\r\n%s" % (direction, dst_str, cleanBin(buf.tobytes())), "debug") -                    dst.connection.send(buf[:size])
\ No newline at end of file +                        if len(conns) == 0: +                            return +                        continue + +                    if src.ssl_established or dst.ssl_established: +                        # if one of the peers is over SSL, we need to send bytes/strings +                        if not src.ssl_established:  # only ssl to dst, i.e. we revc'd into buf but need bytes/string now. +                            contents = buf[:size].tobytes() +                        # self.c.log("%s %s\r\n%s" % (direction, dst_str, cleanBin(contents)), "debug") +                        dst.connection.send(contents) +                    else: +                        # socket.socket.send supports raw bytearrays/memoryviews +                        # self.c.log("%s %s\r\n%s" % (direction, dst_str, cleanBin(buf.tobytes())), "debug") +                        dst.connection.send(buf[:size]) +        except socket.error as e: +            self.c.log("TCP connection closed unexpectedly.", "debug", [repr(e)]) +            return
\ No newline at end of file  | 
