mercurial/wireprotoframing.py
changeset 39446 36f487a332ad
parent 37728 564a3eec6e63
child 39486 43d92d68ac88
equal deleted inserted replaced
39445:cdb56f295b03 39446:36f487a332ad
    15 import struct
    15 import struct
    16 
    16 
    17 from .i18n import _
    17 from .i18n import _
    18 from .thirdparty import (
    18 from .thirdparty import (
    19     attr,
    19     attr,
    20     cbor,
       
    21 )
    20 )
    22 from . import (
    21 from . import (
    23     encoding,
    22     encoding,
    24     error,
    23     error,
    25     util,
    24     util,
    26 )
    25 )
    27 from .utils import (
    26 from .utils import (
       
    27     cborutil,
    28     stringutil,
    28     stringutil,
    29 )
    29 )
    30 
    30 
    31 FRAME_HEADER_SIZE = 8
    31 FRAME_HEADER_SIZE = 8
    32 DEFAULT_MAX_FRAME_SIZE = 32768
    32 DEFAULT_MAX_FRAME_SIZE = 32768
   215             finalflags |= validflags[flag]
   215             finalflags |= validflags[flag]
   216         else:
   216         else:
   217             finalflags |= int(flag)
   217             finalflags |= int(flag)
   218 
   218 
   219     if payload.startswith(b'cbor:'):
   219     if payload.startswith(b'cbor:'):
   220         payload = cbor.dumps(stringutil.evalpythonliteral(payload[5:]),
   220         payload = b''.join(cborutil.streamencode(
   221                              canonical=True)
   221             stringutil.evalpythonliteral(payload[5:])))
   222 
   222 
   223     else:
   223     else:
   224         payload = stringutil.unescapestr(payload)
   224         payload = stringutil.unescapestr(payload)
   225 
   225 
   226     return makeframe(requestid=requestid, streamid=streamid,
   226     return makeframe(requestid=requestid, streamid=streamid,
   287     """
   287     """
   288     data = {b'name': cmd}
   288     data = {b'name': cmd}
   289     if args:
   289     if args:
   290         data[b'args'] = args
   290         data[b'args'] = args
   291 
   291 
   292     data = cbor.dumps(data, canonical=True)
   292     data = b''.join(cborutil.streamencode(data))
   293 
   293 
   294     offset = 0
   294     offset = 0
   295 
   295 
   296     while True:
   296     while True:
   297         flags = 0
   297         flags = 0
   345     """Create a raw frame to send a bytes response from static bytes input.
   345     """Create a raw frame to send a bytes response from static bytes input.
   346 
   346 
   347     Returns a generator of bytearrays.
   347     Returns a generator of bytearrays.
   348     """
   348     """
   349     # Automatically send the overall CBOR response map.
   349     # Automatically send the overall CBOR response map.
   350     overall = cbor.dumps({b'status': b'ok'}, canonical=True)
   350     overall = b''.join(cborutil.streamencode({b'status': b'ok'}))
   351     if len(overall) > maxframesize:
   351     if len(overall) > maxframesize:
   352         raise error.ProgrammingError('not yet implemented')
   352         raise error.ProgrammingError('not yet implemented')
   353 
   353 
   354     # Simple case where we can fit the full response in a single frame.
   354     # Simple case where we can fit the full response in a single frame.
   355     if len(overall) + len(data) <= maxframesize:
   355     if len(overall) + len(data) <= maxframesize:
   386         if done:
   386         if done:
   387             break
   387             break
   388 
   388 
   389 def createbytesresponseframesfromgen(stream, requestid, gen,
   389 def createbytesresponseframesfromgen(stream, requestid, gen,
   390                                      maxframesize=DEFAULT_MAX_FRAME_SIZE):
   390                                      maxframesize=DEFAULT_MAX_FRAME_SIZE):
   391     overall = cbor.dumps({b'status': b'ok'}, canonical=True)
   391     overall = b''.join(cborutil.streamencode({b'status': b'ok'}))
   392 
   392 
   393     yield stream.makeframe(requestid=requestid,
   393     yield stream.makeframe(requestid=requestid,
   394                            typeid=FRAME_TYPE_COMMAND_RESPONSE,
   394                            typeid=FRAME_TYPE_COMMAND_RESPONSE,
   395                            flags=FLAG_COMMAND_RESPONSE_CONTINUATION,
   395                            flags=FLAG_COMMAND_RESPONSE_CONTINUATION,
   396                            payload=overall)
   396                            payload=overall)
   427     }
   427     }
   428 
   428 
   429     if args:
   429     if args:
   430         m[b'error'][b'args'] = args
   430         m[b'error'][b'args'] = args
   431 
   431 
   432     overall = cbor.dumps(m, canonical=True)
   432     overall = b''.join(cborutil.streamencode(m))
   433 
   433 
   434     yield stream.makeframe(requestid=requestid,
   434     yield stream.makeframe(requestid=requestid,
   435                            typeid=FRAME_TYPE_COMMAND_RESPONSE,
   435                            typeid=FRAME_TYPE_COMMAND_RESPONSE,
   436                            flags=FLAG_COMMAND_RESPONSE_EOS,
   436                            flags=FLAG_COMMAND_RESPONSE_EOS,
   437                            payload=overall)
   437                            payload=overall)
   438 
   438 
   439 def createerrorframe(stream, requestid, msg, errtype):
   439 def createerrorframe(stream, requestid, msg, errtype):
   440     # TODO properly handle frame size limits.
   440     # TODO properly handle frame size limits.
   441     assert len(msg) <= DEFAULT_MAX_FRAME_SIZE
   441     assert len(msg) <= DEFAULT_MAX_FRAME_SIZE
   442 
   442 
   443     payload = cbor.dumps({
   443     payload = b''.join(cborutil.streamencode({
   444         b'type': errtype,
   444         b'type': errtype,
   445         b'message': [{b'msg': msg}],
   445         b'message': [{b'msg': msg}],
   446     }, canonical=True)
   446     }))
   447 
   447 
   448     yield stream.makeframe(requestid=requestid,
   448     yield stream.makeframe(requestid=requestid,
   449                            typeid=FRAME_TYPE_ERROR_RESPONSE,
   449                            typeid=FRAME_TYPE_ERROR_RESPONSE,
   450                            flags=0,
   450                            flags=0,
   451                            payload=payload)
   451                            payload=payload)
   491         if labels:
   491         if labels:
   492             atom[b'labels'] = labels
   492             atom[b'labels'] = labels
   493 
   493 
   494         atomdicts.append(atom)
   494         atomdicts.append(atom)
   495 
   495 
   496     payload = cbor.dumps(atomdicts, canonical=True)
   496     payload = b''.join(cborutil.streamencode(atomdicts))
   497 
   497 
   498     if len(payload) > maxframesize:
   498     if len(payload) > maxframesize:
   499         raise ValueError('cannot encode data in a single frame')
   499         raise ValueError('cannot encode data in a single frame')
   500 
   500 
   501     yield stream.makeframe(requestid=requestid,
   501     yield stream.makeframe(requestid=requestid,
   782         else:
   782         else:
   783             self._state = 'idle'
   783             self._state = 'idle'
   784 
   784 
   785         # Decode the payloads as CBOR.
   785         # Decode the payloads as CBOR.
   786         entry['payload'].seek(0)
   786         entry['payload'].seek(0)
   787         request = cbor.load(entry['payload'])
   787         request = cborutil.decodeall(entry['payload'].getvalue())[0]
   788 
   788 
   789         if b'name' not in request:
   789         if b'name' not in request:
   790             self._state = 'errored'
   790             self._state = 'errored'
   791             return self._makeerrorresult(
   791             return self._makeerrorresult(
   792                 _('command request missing "name" field'))
   792                 _('command request missing "name" field'))
  1156     def _onerrorresponseframe(self, request, frame):
  1156     def _onerrorresponseframe(self, request, frame):
  1157         request.state = 'errored'
  1157         request.state = 'errored'
  1158         del self._activerequests[request.requestid]
  1158         del self._activerequests[request.requestid]
  1159 
  1159 
  1160         # The payload should be a CBOR map.
  1160         # The payload should be a CBOR map.
  1161         m = cbor.loads(frame.payload)
  1161         m = cborutil.decodeall(frame.payload)[0]
  1162 
  1162 
  1163         return 'error', {
  1163         return 'error', {
  1164             'request': request,
  1164             'request': request,
  1165             'type': m['type'],
  1165             'type': m['type'],
  1166             'message': m['message'],
  1166             'message': m['message'],