--- a/mercurial/wireprotoframing.py Wed Mar 14 13:57:52 2018 -0700
+++ b/mercurial/wireprotoframing.py Wed Mar 14 14:01:16 2018 -0700
@@ -308,10 +308,24 @@
wantframe
Indicates that nothing of interest happened and the server is waiting on
more frames from the client before anything interesting can be done.
+
+ noop
+ Indicates no additional action is required.
"""
- def __init__(self):
+ def __init__(self, deferoutput=False):
+ """Construct a new server reactor.
+
+ ``deferoutput`` can be used to indicate that no output frames should be
+ instructed to be sent until input has been exhausted. In this mode,
+ events that would normally generate output frames (such as a command
+ response being ready) will instead defer instructing the consumer to
+ send those frames. This is useful for half-duplex transports where the
+ sender cannot receive until all data has been transmitted.
+ """
+ self._deferoutput = deferoutput
self._state = 'idle'
+ self._bufferedframegens = []
self._activecommand = None
self._activeargs = None
self._activedata = None
@@ -344,8 +358,33 @@
The raw bytes response is passed as an argument.
"""
+ framegen = createbytesresponseframesfrombytes(data)
+
+ if self._deferoutput:
+ self._bufferedframegens.append(framegen)
+ return 'noop', {}
+ else:
+ return 'sendframes', {
+ 'framegen': framegen,
+ }
+
+ def oninputeof(self):
+ """Signals that end of input has been received.
+
+ No more frames will be received. All pending activity should be
+ completed.
+ """
+ if not self._deferoutput or not self._bufferedframegens:
+ return 'noop', {}
+
+ # If we buffered all our responses, emit those.
+ def makegen():
+ for gen in self._bufferedframegens:
+ for frame in gen:
+ yield frame
+
return 'sendframes', {
- 'framegen': createbytesresponseframesfrombytes(data),
+ 'framegen': makegen(),
}
def onapplicationerror(self, msg):