aboutsummaryrefslogtreecommitdiffstats
path: root/mitmproxy/controller.py
diff options
context:
space:
mode:
authorMaximilian Hils <git@maximilianhils.com>2016-08-04 17:03:27 -0700
committerMaximilian Hils <git@maximilianhils.com>2016-08-04 17:03:27 -0700
commita52a1df23c7593daf9979fab56c35e1ebccb6d1f (patch)
treea39116321b3e3fa04c8dd7379b5f4c984f9db8af /mitmproxy/controller.py
parentdcfa7027aed5a8d4aa80aff67fc299298659fb1b (diff)
downloadmitmproxy-a52a1df23c7593daf9979fab56c35e1ebccb6d1f.tar.gz
mitmproxy-a52a1df23c7593daf9979fab56c35e1ebccb6d1f.tar.bz2
mitmproxy-a52a1df23c7593daf9979fab56c35e1ebccb6d1f.zip
fix reply concurrency
Diffstat (limited to 'mitmproxy/controller.py')
-rw-r--r--mitmproxy/controller.py24
1 files changed, 22 insertions, 2 deletions
diff --git a/mitmproxy/controller.py b/mitmproxy/controller.py
index 35817a85..6d7bd773 100644
--- a/mitmproxy/controller.py
+++ b/mitmproxy/controller.py
@@ -222,7 +222,9 @@ def handler(f):
# Reset the handled flag - it's common for us to feed the same object
# through handlers repeatedly, so we don't want this to persist across
# calls.
- if message.reply.handled:
+ if handling:
+ if not message.reply.taken:
+ message.reply.commit()
message.reply.handled = False
return ret
# Mark this function as a handler wrapper
@@ -230,6 +232,9 @@ def handler(f):
return wrapper
+NO_REPLY = object()
+
+
class Reply(object):
"""
Messages sent through a channel are decorated with a "reply" attribute.
@@ -241,6 +246,8 @@ class Reply(object):
self.q = queue.Queue()
# Has this message been acked?
self.acked = False
+ # What's the ack message?
+ self.ack_message = NO_REPLY
# Has the user taken responsibility for ack-ing?
self.taken = False
# Has a handler taken responsibility for ack-ing?
@@ -258,8 +265,21 @@ class Reply(object):
def send(self, msg):
if self.acked:
raise exceptions.ControlException("Message already acked.")
+ if self.ack_message != NO_REPLY:
+ # We may have overrides for this later.
+ raise exceptions.ControlException("Message already has a response.")
self.acked = True
- self.q.put(msg)
+ self.ack_message = msg
+ if self.taken:
+ self.commit()
+
+ def commit(self):
+ """
+ This is called by the handler to actually send the ack message.
+ """
+ if self.ack_message == NO_REPLY:
+ raise exceptions.ControlException("Message has no response.")
+ self.q.put(self.ack_message)
def __del__(self):
if not self.acked: