Mercurial > public > mercurial-scm > hg
comparison mercurial/wireprotoframing.py @ 43077:687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Done with
python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py')
black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**')
# skip-blame mass-reformatting only
Differential Revision: https://phab.mercurial-scm.org/D6972
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:48:39 -0400 |
parents | 2372284d9457 |
children | c59eb1560c44 |
comparison
equal
deleted
inserted
replaced
43076:2372284d9457 | 43077:687b865b95ad |
---|---|
125 namemap = {v: k for k, v in mapping.iteritems()} | 125 namemap = {v: k for k, v in mapping.iteritems()} |
126 flags = [] | 126 flags = [] |
127 val = 1 | 127 val = 1 |
128 while value >= val: | 128 while value >= val: |
129 if value & val: | 129 if value & val: |
130 flags.append(namemap.get(val, '<unknown 0x%02x>' % val)) | 130 flags.append(namemap.get(val, b'<unknown 0x%02x>' % val)) |
131 val <<= 1 | 131 val <<= 1 |
132 | 132 |
133 return b'|'.join(flags) | 133 return b'|'.join(flags) |
134 | 134 |
135 | 135 |
156 flags = attr.ib() | 156 flags = attr.ib() |
157 payload = attr.ib() | 157 payload = attr.ib() |
158 | 158 |
159 @encoding.strmethod | 159 @encoding.strmethod |
160 def __repr__(self): | 160 def __repr__(self): |
161 typename = '<unknown 0x%02x>' % self.typeid | 161 typename = b'<unknown 0x%02x>' % self.typeid |
162 for name, value in FRAME_TYPES.iteritems(): | 162 for name, value in FRAME_TYPES.iteritems(): |
163 if value == self.typeid: | 163 if value == self.typeid: |
164 typename = name | 164 typename = name |
165 break | 165 break |
166 | 166 |
167 return ( | 167 return ( |
168 'frame(size=%d; request=%d; stream=%d; streamflags=%s; ' | 168 b'frame(size=%d; request=%d; stream=%d; streamflags=%s; ' |
169 'type=%s; flags=%s)' | 169 b'type=%s; flags=%s)' |
170 % ( | 170 % ( |
171 len(self.payload), | 171 len(self.payload), |
172 self.requestid, | 172 self.requestid, |
173 self.streamid, | 173 self.streamid, |
174 humanflags(STREAM_FLAGS, self.streamflags), | 174 humanflags(STREAM_FLAGS, self.streamflags), |
304 if readcount == 0: | 304 if readcount == 0: |
305 return None | 305 return None |
306 | 306 |
307 if readcount != FRAME_HEADER_SIZE: | 307 if readcount != FRAME_HEADER_SIZE: |
308 raise error.Abort( | 308 raise error.Abort( |
309 _('received incomplete frame: got %d bytes: %s') | 309 _(b'received incomplete frame: got %d bytes: %s') |
310 % (readcount, header) | 310 % (readcount, header) |
311 ) | 311 ) |
312 | 312 |
313 h = parseheader(header) | 313 h = parseheader(header) |
314 | 314 |
315 payload = fh.read(h.length) | 315 payload = fh.read(h.length) |
316 if len(payload) != h.length: | 316 if len(payload) != h.length: |
317 raise error.Abort( | 317 raise error.Abort( |
318 _('frame length error: expected %d; got %d') | 318 _(b'frame length error: expected %d; got %d') |
319 % (h.length, len(payload)) | 319 % (h.length, len(payload)) |
320 ) | 320 ) |
321 | 321 |
322 return frame( | 322 return frame( |
323 h.requestid, h.streamid, h.streamflags, h.typeid, h.flags, payload | 323 h.requestid, h.streamid, h.streamflags, h.typeid, h.flags, payload |
536 | 536 |
537 for (formatting, args, labels) in atoms: | 537 for (formatting, args, labels) in atoms: |
538 # TODO look for localstr, other types here? | 538 # TODO look for localstr, other types here? |
539 | 539 |
540 if not isinstance(formatting, bytes): | 540 if not isinstance(formatting, bytes): |
541 raise ValueError('must use bytes formatting strings') | 541 raise ValueError(b'must use bytes formatting strings') |
542 for arg in args: | 542 for arg in args: |
543 if not isinstance(arg, bytes): | 543 if not isinstance(arg, bytes): |
544 raise ValueError('must use bytes for arguments') | 544 raise ValueError(b'must use bytes for arguments') |
545 for label in labels: | 545 for label in labels: |
546 if not isinstance(label, bytes): | 546 if not isinstance(label, bytes): |
547 raise ValueError('must use bytes for labels') | 547 raise ValueError(b'must use bytes for labels') |
548 | 548 |
549 # Formatting string must be ASCII. | 549 # Formatting string must be ASCII. |
550 formatting = formatting.decode(r'ascii', r'replace').encode(r'ascii') | 550 formatting = formatting.decode(r'ascii', r'replace').encode(r'ascii') |
551 | 551 |
552 # Arguments must be UTF-8. | 552 # Arguments must be UTF-8. |
566 atomdicts.append(atom) | 566 atomdicts.append(atom) |
567 | 567 |
568 payload = b''.join(cborutil.streamencode(atomdicts)) | 568 payload = b''.join(cborutil.streamencode(atomdicts)) |
569 | 569 |
570 if len(payload) > maxframesize: | 570 if len(payload) > maxframesize: |
571 raise ValueError('cannot encode data in a single frame') | 571 raise ValueError(b'cannot encode data in a single frame') |
572 | 572 |
573 yield stream.makeframe( | 573 yield stream.makeframe( |
574 requestid=requestid, | 574 requestid=requestid, |
575 typeid=FRAME_TYPE_TEXT_OUTPUT, | 575 typeid=FRAME_TYPE_TEXT_OUTPUT, |
576 flags=0, | 576 flags=0, |
708 """Decoder for the "identity" stream encoding profile.""" | 708 """Decoder for the "identity" stream encoding profile.""" |
709 | 709 |
710 def __init__(self, ui, extraobjs): | 710 def __init__(self, ui, extraobjs): |
711 if extraobjs: | 711 if extraobjs: |
712 raise error.Abort( | 712 raise error.Abort( |
713 _('identity decoder received unexpected ' 'additional values') | 713 _(b'identity decoder received unexpected ' b'additional values') |
714 ) | 714 ) |
715 | 715 |
716 def decode(self, data): | 716 def decode(self, data): |
717 return data | 717 return data |
718 | 718 |
742 def __init__(self, ui, extraobjs): | 742 def __init__(self, ui, extraobjs): |
743 import zlib | 743 import zlib |
744 | 744 |
745 if extraobjs: | 745 if extraobjs: |
746 raise error.Abort( | 746 raise error.Abort( |
747 _('zlib decoder received unexpected ' 'additional values') | 747 _(b'zlib decoder received unexpected ' b'additional values') |
748 ) | 748 ) |
749 | 749 |
750 self._decompressor = zlib.decompressobj() | 750 self._decompressor = zlib.decompressobj() |
751 | 751 |
752 def decode(self, data): | 752 def decode(self, data): |
799 | 799 |
800 class zstd8mbdecoder(zstdbasedecoder): | 800 class zstd8mbdecoder(zstdbasedecoder): |
801 def __init__(self, ui, extraobjs): | 801 def __init__(self, ui, extraobjs): |
802 if extraobjs: | 802 if extraobjs: |
803 raise error.Abort( | 803 raise error.Abort( |
804 _('zstd8mb decoder received unexpected ' 'additional values') | 804 _(b'zstd8mb decoder received unexpected ' b'additional values') |
805 ) | 805 ) |
806 | 806 |
807 super(zstd8mbdecoder, self).__init__(maxwindowsize=8 * 1048576) | 807 super(zstd8mbdecoder, self).__init__(maxwindowsize=8 * 1048576) |
808 | 808 |
809 | 809 |
870 | 870 |
871 Receives the stream profile name and any additional CBOR objects | 871 Receives the stream profile name and any additional CBOR objects |
872 decoded from the stream encoding settings frame payloads. | 872 decoded from the stream encoding settings frame payloads. |
873 """ | 873 """ |
874 if name not in STREAM_ENCODERS: | 874 if name not in STREAM_ENCODERS: |
875 raise error.Abort(_('unknown stream decoder: %s') % name) | 875 raise error.Abort(_(b'unknown stream decoder: %s') % name) |
876 | 876 |
877 self._decoder = STREAM_ENCODERS[name][1](ui, extraobjs) | 877 self._decoder = STREAM_ENCODERS[name][1](ui, extraobjs) |
878 | 878 |
879 def decode(self, data): | 879 def decode(self, data): |
880 # Default is identity decoder. We don't bother instantiating one | 880 # Default is identity decoder. We don't bother instantiating one |
904 """Set the encoder for this stream. | 904 """Set the encoder for this stream. |
905 | 905 |
906 Receives the stream profile name. | 906 Receives the stream profile name. |
907 """ | 907 """ |
908 if name not in STREAM_ENCODERS: | 908 if name not in STREAM_ENCODERS: |
909 raise error.Abort(_('unknown stream encoder: %s') % name) | 909 raise error.Abort(_(b'unknown stream encoder: %s') % name) |
910 | 910 |
911 self._encoder = STREAM_ENCODERS[name][0](ui) | 911 self._encoder = STREAM_ENCODERS[name][0](ui) |
912 self._encodername = name | 912 self._encodername = name |
913 | 913 |
914 def encode(self, data): | 914 def encode(self, data): |
977 | 977 |
978 | 978 |
979 def ensureserverstream(stream): | 979 def ensureserverstream(stream): |
980 if stream.streamid % 2: | 980 if stream.streamid % 2: |
981 raise error.ProgrammingError( | 981 raise error.ProgrammingError( |
982 'server should only write to even ' | 982 b'server should only write to even ' |
983 'numbered streams; %d is not even' % stream.streamid | 983 b'numbered streams; %d is not even' % stream.streamid |
984 ) | 984 ) |
985 | 985 |
986 | 986 |
987 DEFAULT_PROTOCOL_SETTINGS = { | 987 DEFAULT_PROTOCOL_SETTINGS = { |
988 'contentencodings': [b'identity'], | 988 b'contentencodings': [b'identity'], |
989 } | 989 } |
990 | 990 |
991 | 991 |
992 class serverreactor(object): | 992 class serverreactor(object): |
993 """Holds state of a server handling frame-based protocol requests. | 993 """Holds state of a server handling frame-based protocol requests. |
1064 send those frames. This is useful for half-duplex transports where the | 1064 send those frames. This is useful for half-duplex transports where the |
1065 sender cannot receive until all data has been transmitted. | 1065 sender cannot receive until all data has been transmitted. |
1066 """ | 1066 """ |
1067 self._ui = ui | 1067 self._ui = ui |
1068 self._deferoutput = deferoutput | 1068 self._deferoutput = deferoutput |
1069 self._state = 'initial' | 1069 self._state = b'initial' |
1070 self._nextoutgoingstreamid = 2 | 1070 self._nextoutgoingstreamid = 2 |
1071 self._bufferedframegens = [] | 1071 self._bufferedframegens = [] |
1072 # stream id -> stream instance for all active streams from the client. | 1072 # stream id -> stream instance for all active streams from the client. |
1073 self._incomingstreams = {} | 1073 self._incomingstreams = {} |
1074 self._outgoingstreams = {} | 1074 self._outgoingstreams = {} |
1091 | 1091 |
1092 Returns a dict with an ``action`` key that details what action, | 1092 Returns a dict with an ``action`` key that details what action, |
1093 if any, the consumer should take next. | 1093 if any, the consumer should take next. |
1094 """ | 1094 """ |
1095 if not frame.streamid % 2: | 1095 if not frame.streamid % 2: |
1096 self._state = 'errored' | 1096 self._state = b'errored' |
1097 return self._makeerrorresult( | 1097 return self._makeerrorresult( |
1098 _('received frame with even numbered stream ID: %d') | 1098 _(b'received frame with even numbered stream ID: %d') |
1099 % frame.streamid | 1099 % frame.streamid |
1100 ) | 1100 ) |
1101 | 1101 |
1102 if frame.streamid not in self._incomingstreams: | 1102 if frame.streamid not in self._incomingstreams: |
1103 if not frame.streamflags & STREAM_FLAG_BEGIN_STREAM: | 1103 if not frame.streamflags & STREAM_FLAG_BEGIN_STREAM: |
1104 self._state = 'errored' | 1104 self._state = b'errored' |
1105 return self._makeerrorresult( | 1105 return self._makeerrorresult( |
1106 _( | 1106 _( |
1107 'received frame on unknown inactive stream without ' | 1107 b'received frame on unknown inactive stream without ' |
1108 'beginning of stream flag set' | 1108 b'beginning of stream flag set' |
1109 ) | 1109 ) |
1110 ) | 1110 ) |
1111 | 1111 |
1112 self._incomingstreams[frame.streamid] = inputstream(frame.streamid) | 1112 self._incomingstreams[frame.streamid] = inputstream(frame.streamid) |
1113 | 1113 |
1114 if frame.streamflags & STREAM_FLAG_ENCODING_APPLIED: | 1114 if frame.streamflags & STREAM_FLAG_ENCODING_APPLIED: |
1115 # TODO handle decoding frames | 1115 # TODO handle decoding frames |
1116 self._state = 'errored' | 1116 self._state = b'errored' |
1117 raise error.ProgrammingError( | 1117 raise error.ProgrammingError( |
1118 'support for decoding stream payloads ' 'not yet implemented' | 1118 b'support for decoding stream payloads ' b'not yet implemented' |
1119 ) | 1119 ) |
1120 | 1120 |
1121 if frame.streamflags & STREAM_FLAG_END_STREAM: | 1121 if frame.streamflags & STREAM_FLAG_END_STREAM: |
1122 del self._incomingstreams[frame.streamid] | 1122 del self._incomingstreams[frame.streamid] |
1123 | 1123 |
1124 handlers = { | 1124 handlers = { |
1125 'initial': self._onframeinitial, | 1125 b'initial': self._onframeinitial, |
1126 'protocol-settings-receiving': self._onframeprotocolsettings, | 1126 b'protocol-settings-receiving': self._onframeprotocolsettings, |
1127 'idle': self._onframeidle, | 1127 b'idle': self._onframeidle, |
1128 'command-receiving': self._onframecommandreceiving, | 1128 b'command-receiving': self._onframecommandreceiving, |
1129 'errored': self._onframeerrored, | 1129 b'errored': self._onframeerrored, |
1130 } | 1130 } |
1131 | 1131 |
1132 meth = handlers.get(self._state) | 1132 meth = handlers.get(self._state) |
1133 if not meth: | 1133 if not meth: |
1134 raise error.ProgrammingError('unhandled state: %s' % self._state) | 1134 raise error.ProgrammingError(b'unhandled state: %s' % self._state) |
1135 | 1135 |
1136 return meth(frame) | 1136 return meth(frame) |
1137 | 1137 |
1138 def oncommandresponsereadyobjects(self, stream, requestid, objs): | 1138 def oncommandresponsereadyobjects(self, stream, requestid, objs): |
1139 """Signal that objects are ready to be sent to the client. | 1139 """Signal that objects are ready to be sent to the client. |
1188 | 1188 |
1189 except Exception as e: | 1189 except Exception as e: |
1190 for frame in createerrorframe( | 1190 for frame in createerrorframe( |
1191 stream, | 1191 stream, |
1192 requestid, | 1192 requestid, |
1193 '%s' % stringutil.forcebytestr(e), | 1193 b'%s' % stringutil.forcebytestr(e), |
1194 errtype='server', | 1194 errtype=b'server', |
1195 ): | 1195 ): |
1196 | 1196 |
1197 yield frame | 1197 yield frame |
1198 | 1198 |
1199 break | 1199 break |
1202 # Alternate location responses can only be the first and | 1202 # Alternate location responses can only be the first and |
1203 # only object in the output stream. | 1203 # only object in the output stream. |
1204 if isinstance(o, wireprototypes.alternatelocationresponse): | 1204 if isinstance(o, wireprototypes.alternatelocationresponse): |
1205 if emitted: | 1205 if emitted: |
1206 raise error.ProgrammingError( | 1206 raise error.ProgrammingError( |
1207 'alternatelocationresponse seen after initial ' | 1207 b'alternatelocationresponse seen after initial ' |
1208 'output object' | 1208 b'output object' |
1209 ) | 1209 ) |
1210 | 1210 |
1211 frame = stream.makestreamsettingsframe(requestid) | 1211 frame = stream.makestreamsettingsframe(requestid) |
1212 if frame: | 1212 if frame: |
1213 yield frame | 1213 yield frame |
1220 emitted = True | 1220 emitted = True |
1221 continue | 1221 continue |
1222 | 1222 |
1223 if alternatelocationsent: | 1223 if alternatelocationsent: |
1224 raise error.ProgrammingError( | 1224 raise error.ProgrammingError( |
1225 'object follows alternatelocationresponse' | 1225 b'object follows alternatelocationresponse' |
1226 ) | 1226 ) |
1227 | 1227 |
1228 if not emitted: | 1228 if not emitted: |
1229 # Frame is optional. | 1229 # Frame is optional. |
1230 frame = stream.makestreamsettingsframe(requestid) | 1230 frame = stream.makestreamsettingsframe(requestid) |
1264 for frame in emitter.send(chunk): | 1264 for frame in emitter.send(chunk): |
1265 yield frame | 1265 yield frame |
1266 | 1266 |
1267 except Exception as e: | 1267 except Exception as e: |
1268 for frame in createerrorframe( | 1268 for frame in createerrorframe( |
1269 stream, requestid, '%s' % e, errtype='server' | 1269 stream, requestid, b'%s' % e, errtype=b'server' |
1270 ): | 1270 ): |
1271 yield frame | 1271 yield frame |
1272 | 1272 |
1273 break | 1273 break |
1274 | 1274 |
1283 completed. | 1283 completed. |
1284 """ | 1284 """ |
1285 # TODO should we do anything about in-flight commands? | 1285 # TODO should we do anything about in-flight commands? |
1286 | 1286 |
1287 if not self._deferoutput or not self._bufferedframegens: | 1287 if not self._deferoutput or not self._bufferedframegens: |
1288 return 'noop', {} | 1288 return b'noop', {} |
1289 | 1289 |
1290 # If we buffered all our responses, emit those. | 1290 # If we buffered all our responses, emit those. |
1291 def makegen(): | 1291 def makegen(): |
1292 for gen in self._bufferedframegens: | 1292 for gen in self._bufferedframegens: |
1293 for frame in gen: | 1293 for frame in gen: |
1294 yield frame | 1294 yield frame |
1295 | 1295 |
1296 return 'sendframes', {'framegen': makegen(),} | 1296 return b'sendframes', {b'framegen': makegen(),} |
1297 | 1297 |
1298 def _handlesendframes(self, framegen): | 1298 def _handlesendframes(self, framegen): |
1299 if self._deferoutput: | 1299 if self._deferoutput: |
1300 self._bufferedframegens.append(framegen) | 1300 self._bufferedframegens.append(framegen) |
1301 return 'noop', {} | 1301 return b'noop', {} |
1302 else: | 1302 else: |
1303 return 'sendframes', {'framegen': framegen,} | 1303 return b'sendframes', {b'framegen': framegen,} |
1304 | 1304 |
1305 def onservererror(self, stream, requestid, msg): | 1305 def onservererror(self, stream, requestid, msg): |
1306 ensureserverstream(stream) | 1306 ensureserverstream(stream) |
1307 | 1307 |
1308 def sendframes(): | 1308 def sendframes(): |
1309 for frame in createerrorframe( | 1309 for frame in createerrorframe( |
1310 stream, requestid, msg, errtype='server' | 1310 stream, requestid, msg, errtype=b'server' |
1311 ): | 1311 ): |
1312 yield frame | 1312 yield frame |
1313 | 1313 |
1314 self._activecommands.remove(requestid) | 1314 self._activecommands.remove(requestid) |
1315 | 1315 |
1343 self._outgoingstreams[streamid] = s | 1343 self._outgoingstreams[streamid] = s |
1344 | 1344 |
1345 # Always use the *server's* preferred encoder over the client's, | 1345 # Always use the *server's* preferred encoder over the client's, |
1346 # as servers have more to lose from sub-optimal encoders being used. | 1346 # as servers have more to lose from sub-optimal encoders being used. |
1347 for name in STREAM_ENCODERS_ORDER: | 1347 for name in STREAM_ENCODERS_ORDER: |
1348 if name in self._sendersettings['contentencodings']: | 1348 if name in self._sendersettings[b'contentencodings']: |
1349 s.setencoder(self._ui, name) | 1349 s.setencoder(self._ui, name) |
1350 break | 1350 break |
1351 | 1351 |
1352 return s | 1352 return s |
1353 | 1353 |
1354 def _makeerrorresult(self, msg): | 1354 def _makeerrorresult(self, msg): |
1355 return 'error', {'message': msg,} | 1355 return b'error', {b'message': msg,} |
1356 | 1356 |
1357 def _makeruncommandresult(self, requestid): | 1357 def _makeruncommandresult(self, requestid): |
1358 entry = self._receivingcommands[requestid] | 1358 entry = self._receivingcommands[requestid] |
1359 | 1359 |
1360 if not entry['requestdone']: | 1360 if not entry[b'requestdone']: |
1361 self._state = 'errored' | 1361 self._state = b'errored' |
1362 raise error.ProgrammingError( | 1362 raise error.ProgrammingError( |
1363 'should not be called without ' 'requestdone set' | 1363 b'should not be called without ' b'requestdone set' |
1364 ) | 1364 ) |
1365 | 1365 |
1366 del self._receivingcommands[requestid] | 1366 del self._receivingcommands[requestid] |
1367 | 1367 |
1368 if self._receivingcommands: | 1368 if self._receivingcommands: |
1369 self._state = 'command-receiving' | 1369 self._state = b'command-receiving' |
1370 else: | 1370 else: |
1371 self._state = 'idle' | 1371 self._state = b'idle' |
1372 | 1372 |
1373 # Decode the payloads as CBOR. | 1373 # Decode the payloads as CBOR. |
1374 entry['payload'].seek(0) | 1374 entry[b'payload'].seek(0) |
1375 request = cborutil.decodeall(entry['payload'].getvalue())[0] | 1375 request = cborutil.decodeall(entry[b'payload'].getvalue())[0] |
1376 | 1376 |
1377 if b'name' not in request: | 1377 if b'name' not in request: |
1378 self._state = 'errored' | 1378 self._state = b'errored' |
1379 return self._makeerrorresult( | 1379 return self._makeerrorresult( |
1380 _('command request missing "name" field') | 1380 _(b'command request missing "name" field') |
1381 ) | 1381 ) |
1382 | 1382 |
1383 if b'args' not in request: | 1383 if b'args' not in request: |
1384 request[b'args'] = {} | 1384 request[b'args'] = {} |
1385 | 1385 |
1386 assert requestid not in self._activecommands | 1386 assert requestid not in self._activecommands |
1387 self._activecommands.add(requestid) | 1387 self._activecommands.add(requestid) |
1388 | 1388 |
1389 return ( | 1389 return ( |
1390 'runcommand', | 1390 b'runcommand', |
1391 { | 1391 { |
1392 'requestid': requestid, | 1392 b'requestid': requestid, |
1393 'command': request[b'name'], | 1393 b'command': request[b'name'], |
1394 'args': request[b'args'], | 1394 b'args': request[b'args'], |
1395 'redirect': request.get(b'redirect'), | 1395 b'redirect': request.get(b'redirect'), |
1396 'data': entry['data'].getvalue() if entry['data'] else None, | 1396 b'data': entry[b'data'].getvalue() if entry[b'data'] else None, |
1397 }, | 1397 }, |
1398 ) | 1398 ) |
1399 | 1399 |
1400 def _makewantframeresult(self): | 1400 def _makewantframeresult(self): |
1401 return 'wantframe', {'state': self._state,} | 1401 return b'wantframe', {b'state': self._state,} |
1402 | 1402 |
1403 def _validatecommandrequestframe(self, frame): | 1403 def _validatecommandrequestframe(self, frame): |
1404 new = frame.flags & FLAG_COMMAND_REQUEST_NEW | 1404 new = frame.flags & FLAG_COMMAND_REQUEST_NEW |
1405 continuation = frame.flags & FLAG_COMMAND_REQUEST_CONTINUATION | 1405 continuation = frame.flags & FLAG_COMMAND_REQUEST_CONTINUATION |
1406 | 1406 |
1407 if new and continuation: | 1407 if new and continuation: |
1408 self._state = 'errored' | 1408 self._state = b'errored' |
1409 return self._makeerrorresult( | 1409 return self._makeerrorresult( |
1410 _( | 1410 _( |
1411 'received command request frame with both new and ' | 1411 b'received command request frame with both new and ' |
1412 'continuation flags set' | 1412 b'continuation flags set' |
1413 ) | 1413 ) |
1414 ) | 1414 ) |
1415 | 1415 |
1416 if not new and not continuation: | 1416 if not new and not continuation: |
1417 self._state = 'errored' | 1417 self._state = b'errored' |
1418 return self._makeerrorresult( | 1418 return self._makeerrorresult( |
1419 _( | 1419 _( |
1420 'received command request frame with neither new nor ' | 1420 b'received command request frame with neither new nor ' |
1421 'continuation flags set' | 1421 b'continuation flags set' |
1422 ) | 1422 ) |
1423 ) | 1423 ) |
1424 | 1424 |
1425 def _onframeinitial(self, frame): | 1425 def _onframeinitial(self, frame): |
1426 # Called when we receive a frame when in the "initial" state. | 1426 # Called when we receive a frame when in the "initial" state. |
1427 if frame.typeid == FRAME_TYPE_SENDER_PROTOCOL_SETTINGS: | 1427 if frame.typeid == FRAME_TYPE_SENDER_PROTOCOL_SETTINGS: |
1428 self._state = 'protocol-settings-receiving' | 1428 self._state = b'protocol-settings-receiving' |
1429 self._protocolsettingsdecoder = cborutil.bufferingdecoder() | 1429 self._protocolsettingsdecoder = cborutil.bufferingdecoder() |
1430 return self._onframeprotocolsettings(frame) | 1430 return self._onframeprotocolsettings(frame) |
1431 | 1431 |
1432 elif frame.typeid == FRAME_TYPE_COMMAND_REQUEST: | 1432 elif frame.typeid == FRAME_TYPE_COMMAND_REQUEST: |
1433 self._state = 'idle' | 1433 self._state = b'idle' |
1434 return self._onframeidle(frame) | 1434 return self._onframeidle(frame) |
1435 | 1435 |
1436 else: | 1436 else: |
1437 self._state = 'errored' | 1437 self._state = b'errored' |
1438 return self._makeerrorresult( | 1438 return self._makeerrorresult( |
1439 _( | 1439 _( |
1440 'expected sender protocol settings or command request ' | 1440 b'expected sender protocol settings or command request ' |
1441 'frame; got %d' | 1441 b'frame; got %d' |
1442 ) | 1442 ) |
1443 % frame.typeid | 1443 % frame.typeid |
1444 ) | 1444 ) |
1445 | 1445 |
1446 def _onframeprotocolsettings(self, frame): | 1446 def _onframeprotocolsettings(self, frame): |
1447 assert self._state == 'protocol-settings-receiving' | 1447 assert self._state == b'protocol-settings-receiving' |
1448 assert self._protocolsettingsdecoder is not None | 1448 assert self._protocolsettingsdecoder is not None |
1449 | 1449 |
1450 if frame.typeid != FRAME_TYPE_SENDER_PROTOCOL_SETTINGS: | 1450 if frame.typeid != FRAME_TYPE_SENDER_PROTOCOL_SETTINGS: |
1451 self._state = 'errored' | 1451 self._state = b'errored' |
1452 return self._makeerrorresult( | 1452 return self._makeerrorresult( |
1453 _('expected sender protocol settings frame; got %d') | 1453 _(b'expected sender protocol settings frame; got %d') |
1454 % frame.typeid | 1454 % frame.typeid |
1455 ) | 1455 ) |
1456 | 1456 |
1457 more = frame.flags & FLAG_SENDER_PROTOCOL_SETTINGS_CONTINUATION | 1457 more = frame.flags & FLAG_SENDER_PROTOCOL_SETTINGS_CONTINUATION |
1458 eos = frame.flags & FLAG_SENDER_PROTOCOL_SETTINGS_EOS | 1458 eos = frame.flags & FLAG_SENDER_PROTOCOL_SETTINGS_EOS |
1459 | 1459 |
1460 if more and eos: | 1460 if more and eos: |
1461 self._state = 'errored' | 1461 self._state = b'errored' |
1462 return self._makeerrorresult( | 1462 return self._makeerrorresult( |
1463 _( | 1463 _( |
1464 'sender protocol settings frame cannot have both ' | 1464 b'sender protocol settings frame cannot have both ' |
1465 'continuation and end of stream flags set' | 1465 b'continuation and end of stream flags set' |
1466 ) | 1466 ) |
1467 ) | 1467 ) |
1468 | 1468 |
1469 if not more and not eos: | 1469 if not more and not eos: |
1470 self._state = 'errored' | 1470 self._state = b'errored' |
1471 return self._makeerrorresult( | 1471 return self._makeerrorresult( |
1472 _( | 1472 _( |
1473 'sender protocol settings frame must have continuation or ' | 1473 b'sender protocol settings frame must have continuation or ' |
1474 'end of stream flag set' | 1474 b'end of stream flag set' |
1475 ) | 1475 ) |
1476 ) | 1476 ) |
1477 | 1477 |
1478 # TODO establish limits for maximum amount of data that can be | 1478 # TODO establish limits for maximum amount of data that can be |
1479 # buffered. | 1479 # buffered. |
1480 try: | 1480 try: |
1481 self._protocolsettingsdecoder.decode(frame.payload) | 1481 self._protocolsettingsdecoder.decode(frame.payload) |
1482 except Exception as e: | 1482 except Exception as e: |
1483 self._state = 'errored' | 1483 self._state = b'errored' |
1484 return self._makeerrorresult( | 1484 return self._makeerrorresult( |
1485 _('error decoding CBOR from sender protocol settings frame: %s') | 1485 _( |
1486 b'error decoding CBOR from sender protocol settings frame: %s' | |
1487 ) | |
1486 % stringutil.forcebytestr(e) | 1488 % stringutil.forcebytestr(e) |
1487 ) | 1489 ) |
1488 | 1490 |
1489 if more: | 1491 if more: |
1490 return self._makewantframeresult() | 1492 return self._makewantframeresult() |
1493 | 1495 |
1494 decoded = self._protocolsettingsdecoder.getavailable() | 1496 decoded = self._protocolsettingsdecoder.getavailable() |
1495 self._protocolsettingsdecoder = None | 1497 self._protocolsettingsdecoder = None |
1496 | 1498 |
1497 if not decoded: | 1499 if not decoded: |
1498 self._state = 'errored' | 1500 self._state = b'errored' |
1499 return self._makeerrorresult( | 1501 return self._makeerrorresult( |
1500 _('sender protocol settings frame did not contain CBOR data') | 1502 _(b'sender protocol settings frame did not contain CBOR data') |
1501 ) | 1503 ) |
1502 elif len(decoded) > 1: | 1504 elif len(decoded) > 1: |
1503 self._state = 'errored' | 1505 self._state = b'errored' |
1504 return self._makeerrorresult( | 1506 return self._makeerrorresult( |
1505 _( | 1507 _( |
1506 'sender protocol settings frame contained multiple CBOR ' | 1508 b'sender protocol settings frame contained multiple CBOR ' |
1507 'values' | 1509 b'values' |
1508 ) | 1510 ) |
1509 ) | 1511 ) |
1510 | 1512 |
1511 d = decoded[0] | 1513 d = decoded[0] |
1512 | 1514 |
1513 if b'contentencodings' in d: | 1515 if b'contentencodings' in d: |
1514 self._sendersettings['contentencodings'] = d[b'contentencodings'] | 1516 self._sendersettings[b'contentencodings'] = d[b'contentencodings'] |
1515 | 1517 |
1516 self._state = 'idle' | 1518 self._state = b'idle' |
1517 | 1519 |
1518 return self._makewantframeresult() | 1520 return self._makewantframeresult() |
1519 | 1521 |
1520 def _onframeidle(self, frame): | 1522 def _onframeidle(self, frame): |
1521 # The only frame type that should be received in this state is a | 1523 # The only frame type that should be received in this state is a |
1522 # command request. | 1524 # command request. |
1523 if frame.typeid != FRAME_TYPE_COMMAND_REQUEST: | 1525 if frame.typeid != FRAME_TYPE_COMMAND_REQUEST: |
1524 self._state = 'errored' | 1526 self._state = b'errored' |
1525 return self._makeerrorresult( | 1527 return self._makeerrorresult( |
1526 _('expected command request frame; got %d') % frame.typeid | 1528 _(b'expected command request frame; got %d') % frame.typeid |
1527 ) | 1529 ) |
1528 | 1530 |
1529 res = self._validatecommandrequestframe(frame) | 1531 res = self._validatecommandrequestframe(frame) |
1530 if res: | 1532 if res: |
1531 return res | 1533 return res |
1532 | 1534 |
1533 if frame.requestid in self._receivingcommands: | 1535 if frame.requestid in self._receivingcommands: |
1534 self._state = 'errored' | 1536 self._state = b'errored' |
1535 return self._makeerrorresult( | 1537 return self._makeerrorresult( |
1536 _('request with ID %d already received') % frame.requestid | 1538 _(b'request with ID %d already received') % frame.requestid |
1537 ) | 1539 ) |
1538 | 1540 |
1539 if frame.requestid in self._activecommands: | 1541 if frame.requestid in self._activecommands: |
1540 self._state = 'errored' | 1542 self._state = b'errored' |
1541 return self._makeerrorresult( | 1543 return self._makeerrorresult( |
1542 _('request with ID %d is already active') % frame.requestid | 1544 _(b'request with ID %d is already active') % frame.requestid |
1543 ) | 1545 ) |
1544 | 1546 |
1545 new = frame.flags & FLAG_COMMAND_REQUEST_NEW | 1547 new = frame.flags & FLAG_COMMAND_REQUEST_NEW |
1546 moreframes = frame.flags & FLAG_COMMAND_REQUEST_MORE_FRAMES | 1548 moreframes = frame.flags & FLAG_COMMAND_REQUEST_MORE_FRAMES |
1547 expectingdata = frame.flags & FLAG_COMMAND_REQUEST_EXPECT_DATA | 1549 expectingdata = frame.flags & FLAG_COMMAND_REQUEST_EXPECT_DATA |
1548 | 1550 |
1549 if not new: | 1551 if not new: |
1550 self._state = 'errored' | 1552 self._state = b'errored' |
1551 return self._makeerrorresult( | 1553 return self._makeerrorresult( |
1552 _('received command request frame without new flag set') | 1554 _(b'received command request frame without new flag set') |
1553 ) | 1555 ) |
1554 | 1556 |
1555 payload = util.bytesio() | 1557 payload = util.bytesio() |
1556 payload.write(frame.payload) | 1558 payload.write(frame.payload) |
1557 | 1559 |
1558 self._receivingcommands[frame.requestid] = { | 1560 self._receivingcommands[frame.requestid] = { |
1559 'payload': payload, | 1561 b'payload': payload, |
1560 'data': None, | 1562 b'data': None, |
1561 'requestdone': not moreframes, | 1563 b'requestdone': not moreframes, |
1562 'expectingdata': bool(expectingdata), | 1564 b'expectingdata': bool(expectingdata), |
1563 } | 1565 } |
1564 | 1566 |
1565 # This is the final frame for this request. Dispatch it. | 1567 # This is the final frame for this request. Dispatch it. |
1566 if not moreframes and not expectingdata: | 1568 if not moreframes and not expectingdata: |
1567 return self._makeruncommandresult(frame.requestid) | 1569 return self._makeruncommandresult(frame.requestid) |
1568 | 1570 |
1569 assert moreframes or expectingdata | 1571 assert moreframes or expectingdata |
1570 self._state = 'command-receiving' | 1572 self._state = b'command-receiving' |
1571 return self._makewantframeresult() | 1573 return self._makewantframeresult() |
1572 | 1574 |
1573 def _onframecommandreceiving(self, frame): | 1575 def _onframecommandreceiving(self, frame): |
1574 if frame.typeid == FRAME_TYPE_COMMAND_REQUEST: | 1576 if frame.typeid == FRAME_TYPE_COMMAND_REQUEST: |
1575 # Process new command requests as such. | 1577 # Process new command requests as such. |
1581 return res | 1583 return res |
1582 | 1584 |
1583 # All other frames should be related to a command that is currently | 1585 # All other frames should be related to a command that is currently |
1584 # receiving but is not active. | 1586 # receiving but is not active. |
1585 if frame.requestid in self._activecommands: | 1587 if frame.requestid in self._activecommands: |
1586 self._state = 'errored' | 1588 self._state = b'errored' |
1587 return self._makeerrorresult( | 1589 return self._makeerrorresult( |
1588 _('received frame for request that is still active: %d') | 1590 _(b'received frame for request that is still active: %d') |
1589 % frame.requestid | 1591 % frame.requestid |
1590 ) | 1592 ) |
1591 | 1593 |
1592 if frame.requestid not in self._receivingcommands: | 1594 if frame.requestid not in self._receivingcommands: |
1593 self._state = 'errored' | 1595 self._state = b'errored' |
1594 return self._makeerrorresult( | 1596 return self._makeerrorresult( |
1595 _('received frame for request that is not receiving: %d') | 1597 _(b'received frame for request that is not receiving: %d') |
1596 % frame.requestid | 1598 % frame.requestid |
1597 ) | 1599 ) |
1598 | 1600 |
1599 entry = self._receivingcommands[frame.requestid] | 1601 entry = self._receivingcommands[frame.requestid] |
1600 | 1602 |
1601 if frame.typeid == FRAME_TYPE_COMMAND_REQUEST: | 1603 if frame.typeid == FRAME_TYPE_COMMAND_REQUEST: |
1602 moreframes = frame.flags & FLAG_COMMAND_REQUEST_MORE_FRAMES | 1604 moreframes = frame.flags & FLAG_COMMAND_REQUEST_MORE_FRAMES |
1603 expectingdata = bool(frame.flags & FLAG_COMMAND_REQUEST_EXPECT_DATA) | 1605 expectingdata = bool(frame.flags & FLAG_COMMAND_REQUEST_EXPECT_DATA) |
1604 | 1606 |
1605 if entry['requestdone']: | 1607 if entry[b'requestdone']: |
1606 self._state = 'errored' | 1608 self._state = b'errored' |
1607 return self._makeerrorresult( | 1609 return self._makeerrorresult( |
1608 _( | 1610 _( |
1609 'received command request frame when request frames ' | 1611 b'received command request frame when request frames ' |
1610 'were supposedly done' | 1612 b'were supposedly done' |
1611 ) | 1613 ) |
1612 ) | 1614 ) |
1613 | 1615 |
1614 if expectingdata != entry['expectingdata']: | 1616 if expectingdata != entry[b'expectingdata']: |
1615 self._state = 'errored' | 1617 self._state = b'errored' |
1616 return self._makeerrorresult( | 1618 return self._makeerrorresult( |
1617 _('mismatch between expect data flag and previous frame') | 1619 _(b'mismatch between expect data flag and previous frame') |
1618 ) | 1620 ) |
1619 | 1621 |
1620 entry['payload'].write(frame.payload) | 1622 entry[b'payload'].write(frame.payload) |
1621 | 1623 |
1622 if not moreframes: | 1624 if not moreframes: |
1623 entry['requestdone'] = True | 1625 entry[b'requestdone'] = True |
1624 | 1626 |
1625 if not moreframes and not expectingdata: | 1627 if not moreframes and not expectingdata: |
1626 return self._makeruncommandresult(frame.requestid) | 1628 return self._makeruncommandresult(frame.requestid) |
1627 | 1629 |
1628 return self._makewantframeresult() | 1630 return self._makewantframeresult() |
1629 | 1631 |
1630 elif frame.typeid == FRAME_TYPE_COMMAND_DATA: | 1632 elif frame.typeid == FRAME_TYPE_COMMAND_DATA: |
1631 if not entry['expectingdata']: | 1633 if not entry[b'expectingdata']: |
1632 self._state = 'errored' | 1634 self._state = b'errored' |
1633 return self._makeerrorresult( | 1635 return self._makeerrorresult( |
1634 _( | 1636 _( |
1635 'received command data frame for request that is not ' | 1637 b'received command data frame for request that is not ' |
1636 'expecting data: %d' | 1638 b'expecting data: %d' |
1637 ) | 1639 ) |
1638 % frame.requestid | 1640 % frame.requestid |
1639 ) | 1641 ) |
1640 | 1642 |
1641 if entry['data'] is None: | 1643 if entry[b'data'] is None: |
1642 entry['data'] = util.bytesio() | 1644 entry[b'data'] = util.bytesio() |
1643 | 1645 |
1644 return self._handlecommanddataframe(frame, entry) | 1646 return self._handlecommanddataframe(frame, entry) |
1645 else: | 1647 else: |
1646 self._state = 'errored' | 1648 self._state = b'errored' |
1647 return self._makeerrorresult( | 1649 return self._makeerrorresult( |
1648 _('received unexpected frame type: %d') % frame.typeid | 1650 _(b'received unexpected frame type: %d') % frame.typeid |
1649 ) | 1651 ) |
1650 | 1652 |
1651 def _handlecommanddataframe(self, frame, entry): | 1653 def _handlecommanddataframe(self, frame, entry): |
1652 assert frame.typeid == FRAME_TYPE_COMMAND_DATA | 1654 assert frame.typeid == FRAME_TYPE_COMMAND_DATA |
1653 | 1655 |
1654 # TODO support streaming data instead of buffering it. | 1656 # TODO support streaming data instead of buffering it. |
1655 entry['data'].write(frame.payload) | 1657 entry[b'data'].write(frame.payload) |
1656 | 1658 |
1657 if frame.flags & FLAG_COMMAND_DATA_CONTINUATION: | 1659 if frame.flags & FLAG_COMMAND_DATA_CONTINUATION: |
1658 return self._makewantframeresult() | 1660 return self._makewantframeresult() |
1659 elif frame.flags & FLAG_COMMAND_DATA_EOS: | 1661 elif frame.flags & FLAG_COMMAND_DATA_EOS: |
1660 entry['data'].seek(0) | 1662 entry[b'data'].seek(0) |
1661 return self._makeruncommandresult(frame.requestid) | 1663 return self._makeruncommandresult(frame.requestid) |
1662 else: | 1664 else: |
1663 self._state = 'errored' | 1665 self._state = b'errored' |
1664 return self._makeerrorresult( | 1666 return self._makeerrorresult( |
1665 _('command data frame without ' 'flags') | 1667 _(b'command data frame without ' b'flags') |
1666 ) | 1668 ) |
1667 | 1669 |
1668 def _onframeerrored(self, frame): | 1670 def _onframeerrored(self, frame): |
1669 return self._makeerrorresult(_('server already errored')) | 1671 return self._makeerrorresult(_(b'server already errored')) |
1670 | 1672 |
1671 | 1673 |
1672 class commandrequest(object): | 1674 class commandrequest(object): |
1673 """Represents a request to run a command.""" | 1675 """Represents a request to run a command.""" |
1674 | 1676 |
1676 self.requestid = requestid | 1678 self.requestid = requestid |
1677 self.name = name | 1679 self.name = name |
1678 self.args = args | 1680 self.args = args |
1679 self.datafh = datafh | 1681 self.datafh = datafh |
1680 self.redirect = redirect | 1682 self.redirect = redirect |
1681 self.state = 'pending' | 1683 self.state = b'pending' |
1682 | 1684 |
1683 | 1685 |
1684 class clientreactor(object): | 1686 class clientreactor(object): |
1685 """Holds state of a client issuing frame-based protocol requests. | 1687 """Holds state of a client issuing frame-based protocol requests. |
1686 | 1688 |
1776 and an optional file object containing the raw data for the command. | 1778 and an optional file object containing the raw data for the command. |
1777 | 1779 |
1778 Returns a 3-tuple of (request, action, action data). | 1780 Returns a 3-tuple of (request, action, action data). |
1779 """ | 1781 """ |
1780 if not self._canissuecommands: | 1782 if not self._canissuecommands: |
1781 raise error.ProgrammingError('cannot issue new commands') | 1783 raise error.ProgrammingError(b'cannot issue new commands') |
1782 | 1784 |
1783 requestid = self._nextrequestid | 1785 requestid = self._nextrequestid |
1784 self._nextrequestid += 2 | 1786 self._nextrequestid += 2 |
1785 | 1787 |
1786 request = commandrequest( | 1788 request = commandrequest( |
1787 requestid, name, args, datafh=datafh, redirect=redirect | 1789 requestid, name, args, datafh=datafh, redirect=redirect |
1788 ) | 1790 ) |
1789 | 1791 |
1790 if self._buffersends: | 1792 if self._buffersends: |
1791 self._pendingrequests.append(request) | 1793 self._pendingrequests.append(request) |
1792 return request, 'noop', {} | 1794 return request, b'noop', {} |
1793 else: | 1795 else: |
1794 if not self._cansend: | 1796 if not self._cansend: |
1795 raise error.ProgrammingError( | 1797 raise error.ProgrammingError( |
1796 'sends cannot be performed on ' 'this instance' | 1798 b'sends cannot be performed on ' b'this instance' |
1797 ) | 1799 ) |
1798 | 1800 |
1799 if not self._hasmultiplesend: | 1801 if not self._hasmultiplesend: |
1800 self._cansend = False | 1802 self._cansend = False |
1801 self._canissuecommands = False | 1803 self._canissuecommands = False |
1802 | 1804 |
1803 return ( | 1805 return ( |
1804 request, | 1806 request, |
1805 'sendframes', | 1807 b'sendframes', |
1806 {'framegen': self._makecommandframes(request),}, | 1808 {b'framegen': self._makecommandframes(request),}, |
1807 ) | 1809 ) |
1808 | 1810 |
1809 def flushcommands(self): | 1811 def flushcommands(self): |
1810 """Request that all queued commands be sent. | 1812 """Request that all queued commands be sent. |
1811 | 1813 |
1815 | 1817 |
1816 If instances aren't configured for multiple sends, no new command | 1818 If instances aren't configured for multiple sends, no new command |
1817 requests are allowed after this is called. | 1819 requests are allowed after this is called. |
1818 """ | 1820 """ |
1819 if not self._pendingrequests: | 1821 if not self._pendingrequests: |
1820 return 'noop', {} | 1822 return b'noop', {} |
1821 | 1823 |
1822 if not self._cansend: | 1824 if not self._cansend: |
1823 raise error.ProgrammingError( | 1825 raise error.ProgrammingError( |
1824 'sends cannot be performed on this ' 'instance' | 1826 b'sends cannot be performed on this ' b'instance' |
1825 ) | 1827 ) |
1826 | 1828 |
1827 # If the instance only allows sending once, mark that we have fired | 1829 # If the instance only allows sending once, mark that we have fired |
1828 # our one shot. | 1830 # our one shot. |
1829 if not self._hasmultiplesend: | 1831 if not self._hasmultiplesend: |
1834 while self._pendingrequests: | 1836 while self._pendingrequests: |
1835 request = self._pendingrequests.popleft() | 1837 request = self._pendingrequests.popleft() |
1836 for frame in self._makecommandframes(request): | 1838 for frame in self._makecommandframes(request): |
1837 yield frame | 1839 yield frame |
1838 | 1840 |
1839 return 'sendframes', {'framegen': makeframes(),} | 1841 return b'sendframes', {b'framegen': makeframes(),} |
1840 | 1842 |
1841 def _makecommandframes(self, request): | 1843 def _makecommandframes(self, request): |
1842 """Emit frames to issue a command request. | 1844 """Emit frames to issue a command request. |
1843 | 1845 |
1844 As a side-effect, update request accounting to reflect its changed | 1846 As a side-effect, update request accounting to reflect its changed |
1845 state. | 1847 state. |
1846 """ | 1848 """ |
1847 self._activerequests[request.requestid] = request | 1849 self._activerequests[request.requestid] = request |
1848 request.state = 'sending' | 1850 request.state = b'sending' |
1849 | 1851 |
1850 if not self._protocolsettingssent and self._clientcontentencoders: | 1852 if not self._protocolsettingssent and self._clientcontentencoders: |
1851 self._protocolsettingssent = True | 1853 self._protocolsettingssent = True |
1852 | 1854 |
1853 payload = b''.join( | 1855 payload = b''.join( |
1873 ) | 1875 ) |
1874 | 1876 |
1875 for frame in res: | 1877 for frame in res: |
1876 yield frame | 1878 yield frame |
1877 | 1879 |
1878 request.state = 'sent' | 1880 request.state = b'sent' |
1879 | 1881 |
1880 def onframerecv(self, frame): | 1882 def onframerecv(self, frame): |
1881 """Process a frame that has been received off the wire. | 1883 """Process a frame that has been received off the wire. |
1882 | 1884 |
1883 Returns a 2-tuple of (action, meta) describing further action the | 1885 Returns a 2-tuple of (action, meta) describing further action the |
1884 caller needs to take as a result of receiving this frame. | 1886 caller needs to take as a result of receiving this frame. |
1885 """ | 1887 """ |
1886 if frame.streamid % 2: | 1888 if frame.streamid % 2: |
1887 return ( | 1889 return ( |
1888 'error', | 1890 b'error', |
1889 { | 1891 { |
1890 'message': ( | 1892 b'message': ( |
1891 _('received frame with odd numbered stream ID: %d') | 1893 _(b'received frame with odd numbered stream ID: %d') |
1892 % frame.streamid | 1894 % frame.streamid |
1893 ), | 1895 ), |
1894 }, | 1896 }, |
1895 ) | 1897 ) |
1896 | 1898 |
1897 if frame.streamid not in self._incomingstreams: | 1899 if frame.streamid not in self._incomingstreams: |
1898 if not frame.streamflags & STREAM_FLAG_BEGIN_STREAM: | 1900 if not frame.streamflags & STREAM_FLAG_BEGIN_STREAM: |
1899 return ( | 1901 return ( |
1900 'error', | 1902 b'error', |
1901 { | 1903 { |
1902 'message': _( | 1904 b'message': _( |
1903 'received frame on unknown stream ' | 1905 b'received frame on unknown stream ' |
1904 'without beginning of stream flag set' | 1906 b'without beginning of stream flag set' |
1905 ), | 1907 ), |
1906 }, | 1908 }, |
1907 ) | 1909 ) |
1908 | 1910 |
1909 self._incomingstreams[frame.streamid] = inputstream(frame.streamid) | 1911 self._incomingstreams[frame.streamid] = inputstream(frame.streamid) |
1922 if frame.typeid == FRAME_TYPE_STREAM_SETTINGS: | 1924 if frame.typeid == FRAME_TYPE_STREAM_SETTINGS: |
1923 return self._onstreamsettingsframe(frame) | 1925 return self._onstreamsettingsframe(frame) |
1924 | 1926 |
1925 if frame.requestid not in self._activerequests: | 1927 if frame.requestid not in self._activerequests: |
1926 return ( | 1928 return ( |
1927 'error', | 1929 b'error', |
1928 { | 1930 { |
1929 'message': ( | 1931 b'message': ( |
1930 _('received frame for inactive request ID: %d') | 1932 _(b'received frame for inactive request ID: %d') |
1931 % frame.requestid | 1933 % frame.requestid |
1932 ), | 1934 ), |
1933 }, | 1935 }, |
1934 ) | 1936 ) |
1935 | 1937 |
1936 request = self._activerequests[frame.requestid] | 1938 request = self._activerequests[frame.requestid] |
1937 request.state = 'receiving' | 1939 request.state = b'receiving' |
1938 | 1940 |
1939 handlers = { | 1941 handlers = { |
1940 FRAME_TYPE_COMMAND_RESPONSE: self._oncommandresponseframe, | 1942 FRAME_TYPE_COMMAND_RESPONSE: self._oncommandresponseframe, |
1941 FRAME_TYPE_ERROR_RESPONSE: self._onerrorresponseframe, | 1943 FRAME_TYPE_ERROR_RESPONSE: self._onerrorresponseframe, |
1942 } | 1944 } |
1943 | 1945 |
1944 meth = handlers.get(frame.typeid) | 1946 meth = handlers.get(frame.typeid) |
1945 if not meth: | 1947 if not meth: |
1946 raise error.ProgrammingError( | 1948 raise error.ProgrammingError( |
1947 'unhandled frame type: %d' % frame.typeid | 1949 b'unhandled frame type: %d' % frame.typeid |
1948 ) | 1950 ) |
1949 | 1951 |
1950 return meth(request, frame) | 1952 return meth(request, frame) |
1951 | 1953 |
1952 def _onstreamsettingsframe(self, frame): | 1954 def _onstreamsettingsframe(self, frame): |
1955 more = frame.flags & FLAG_STREAM_ENCODING_SETTINGS_CONTINUATION | 1957 more = frame.flags & FLAG_STREAM_ENCODING_SETTINGS_CONTINUATION |
1956 eos = frame.flags & FLAG_STREAM_ENCODING_SETTINGS_EOS | 1958 eos = frame.flags & FLAG_STREAM_ENCODING_SETTINGS_EOS |
1957 | 1959 |
1958 if more and eos: | 1960 if more and eos: |
1959 return ( | 1961 return ( |
1960 'error', | 1962 b'error', |
1961 { | 1963 { |
1962 'message': ( | 1964 b'message': ( |
1963 _( | 1965 _( |
1964 'stream encoding settings frame cannot have both ' | 1966 b'stream encoding settings frame cannot have both ' |
1965 'continuation and end of stream flags set' | 1967 b'continuation and end of stream flags set' |
1966 ) | 1968 ) |
1967 ), | 1969 ), |
1968 }, | 1970 }, |
1969 ) | 1971 ) |
1970 | 1972 |
1971 if not more and not eos: | 1973 if not more and not eos: |
1972 return ( | 1974 return ( |
1973 'error', | 1975 b'error', |
1974 { | 1976 { |
1975 'message': _( | 1977 b'message': _( |
1976 'stream encoding settings frame must have ' | 1978 b'stream encoding settings frame must have ' |
1977 'continuation or end of stream flag set' | 1979 b'continuation or end of stream flag set' |
1978 ), | 1980 ), |
1979 }, | 1981 }, |
1980 ) | 1982 ) |
1981 | 1983 |
1982 if frame.streamid not in self._streamsettingsdecoders: | 1984 if frame.streamid not in self._streamsettingsdecoders: |
1987 | 1989 |
1988 try: | 1990 try: |
1989 decoder.decode(frame.payload) | 1991 decoder.decode(frame.payload) |
1990 except Exception as e: | 1992 except Exception as e: |
1991 return ( | 1993 return ( |
1992 'error', | 1994 b'error', |
1993 { | 1995 { |
1994 'message': ( | 1996 b'message': ( |
1995 _( | 1997 _( |
1996 'error decoding CBOR from stream encoding ' | 1998 b'error decoding CBOR from stream encoding ' |
1997 'settings frame: %s' | 1999 b'settings frame: %s' |
1998 ) | 2000 ) |
1999 % stringutil.forcebytestr(e) | 2001 % stringutil.forcebytestr(e) |
2000 ), | 2002 ), |
2001 }, | 2003 }, |
2002 ) | 2004 ) |
2003 | 2005 |
2004 if more: | 2006 if more: |
2005 return 'noop', {} | 2007 return b'noop', {} |
2006 | 2008 |
2007 assert eos | 2009 assert eos |
2008 | 2010 |
2009 decoded = decoder.getavailable() | 2011 decoded = decoder.getavailable() |
2010 del self._streamsettingsdecoders[frame.streamid] | 2012 del self._streamsettingsdecoders[frame.streamid] |
2011 | 2013 |
2012 if not decoded: | 2014 if not decoded: |
2013 return ( | 2015 return ( |
2014 'error', | 2016 b'error', |
2015 { | 2017 { |
2016 'message': _( | 2018 b'message': _( |
2017 'stream encoding settings frame did not contain ' | 2019 b'stream encoding settings frame did not contain ' |
2018 'CBOR data' | 2020 b'CBOR data' |
2019 ), | 2021 ), |
2020 }, | 2022 }, |
2021 ) | 2023 ) |
2022 | 2024 |
2023 try: | 2025 try: |
2024 self._incomingstreams[frame.streamid].setdecoder( | 2026 self._incomingstreams[frame.streamid].setdecoder( |
2025 self._ui, decoded[0], decoded[1:] | 2027 self._ui, decoded[0], decoded[1:] |
2026 ) | 2028 ) |
2027 except Exception as e: | 2029 except Exception as e: |
2028 return ( | 2030 return ( |
2029 'error', | 2031 b'error', |
2030 { | 2032 { |
2031 'message': ( | 2033 b'message': ( |
2032 _('error setting stream decoder: %s') | 2034 _(b'error setting stream decoder: %s') |
2033 % stringutil.forcebytestr(e) | 2035 % stringutil.forcebytestr(e) |
2034 ), | 2036 ), |
2035 }, | 2037 }, |
2036 ) | 2038 ) |
2037 | 2039 |
2038 return 'noop', {} | 2040 return b'noop', {} |
2039 | 2041 |
2040 def _oncommandresponseframe(self, request, frame): | 2042 def _oncommandresponseframe(self, request, frame): |
2041 if frame.flags & FLAG_COMMAND_RESPONSE_EOS: | 2043 if frame.flags & FLAG_COMMAND_RESPONSE_EOS: |
2042 request.state = 'received' | 2044 request.state = b'received' |
2043 del self._activerequests[request.requestid] | 2045 del self._activerequests[request.requestid] |
2044 | 2046 |
2045 return ( | 2047 return ( |
2046 'responsedata', | 2048 b'responsedata', |
2047 { | 2049 { |
2048 'request': request, | 2050 b'request': request, |
2049 'expectmore': frame.flags & FLAG_COMMAND_RESPONSE_CONTINUATION, | 2051 b'expectmore': frame.flags & FLAG_COMMAND_RESPONSE_CONTINUATION, |
2050 'eos': frame.flags & FLAG_COMMAND_RESPONSE_EOS, | 2052 b'eos': frame.flags & FLAG_COMMAND_RESPONSE_EOS, |
2051 'data': frame.payload, | 2053 b'data': frame.payload, |
2052 }, | 2054 }, |
2053 ) | 2055 ) |
2054 | 2056 |
2055 def _onerrorresponseframe(self, request, frame): | 2057 def _onerrorresponseframe(self, request, frame): |
2056 request.state = 'errored' | 2058 request.state = b'errored' |
2057 del self._activerequests[request.requestid] | 2059 del self._activerequests[request.requestid] |
2058 | 2060 |
2059 # The payload should be a CBOR map. | 2061 # The payload should be a CBOR map. |
2060 m = cborutil.decodeall(frame.payload)[0] | 2062 m = cborutil.decodeall(frame.payload)[0] |
2061 | 2063 |
2062 return ( | 2064 return ( |
2063 'error', | 2065 b'error', |
2064 {'request': request, 'type': m['type'], 'message': m['message'],}, | 2066 { |
2067 b'request': request, | |
2068 b'type': m[b'type'], | |
2069 b'message': m[b'message'], | |
2070 }, | |
2065 ) | 2071 ) |