mercurial/wireprotov2peer.py
author Gregory Szorc <gregory.szorc@gmail.com>
Sat, 14 Apr 2018 11:49:06 -0700
changeset 37721 f7673845b167
parent 37720 d715a85003c8
child 37722 89a16704114c
permissions -rw-r--r--
wireprotov2: decode responses to their expected types Callers of established wire protocol commands expect the response from that command to be decoded into a data structure. It's not very useful if callers get back a stream of bytes and don't know how they should be interpreted - especially since that stream of bytes varies by wire protocol and even the transport within that protocol version. This commit establishes decoding functions for various command responses so callers of those commands get the response type they expect. In theory, this should make the version 2 HTTP peer usable for various operations. But I haven't tested to confirm. Differential Revision: https://phab.mercurial-scm.org/D3381
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     1
# wireprotov2peer.py - client side code for wire protocol version 2
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     2
#
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     3
# Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com>
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     4
#
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     7
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     8
from __future__ import absolute_import
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     9
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    10
from .i18n import _
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    11
from .thirdparty import (
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    12
    cbor,
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    13
)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    14
from . import (
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
    15
    encoding,
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    16
    error,
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    17
    util,
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    18
    wireprotoframing,
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    19
)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    20
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    21
class commandresponse(object):
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    22
    """Represents the response to a command request."""
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    23
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    24
    def __init__(self, requestid, command):
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    25
        self.requestid = requestid
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    26
        self.command = command
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    27
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    28
        self.cbor = False
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    29
        self.b = util.bytesio()
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    30
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    31
    def cborobjects(self):
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    32
        """Obtain decoded CBOR objects from this response."""
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    33
        size = self.b.tell()
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    34
        self.b.seek(0)
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    35
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    36
        decoder = cbor.CBORDecoder(self.b)
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    37
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    38
        while self.b.tell() < size:
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    39
            yield decoder.decode()
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    40
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    41
class clienthandler(object):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    42
    """Object to handle higher-level client activities.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    43
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    44
    The ``clientreactor`` is used to hold low-level state about the frame-based
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    45
    protocol, such as which requests and streams are active. This type is used
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    46
    for higher-level operations, such as reading frames from a socket, exposing
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    47
    and managing a higher-level primitive for representing command responses,
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    48
    etc. This class is what peers should probably use to bridge wire activity
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    49
    with the higher-level peer API.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    50
    """
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    51
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    52
    def __init__(self, ui, clientreactor):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    53
        self._ui = ui
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    54
        self._reactor = clientreactor
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    55
        self._requests = {}
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    56
        self._futures = {}
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    57
        self._responses = {}
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    58
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    59
    def callcommand(self, command, args, f):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    60
        """Register a request to call a command.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    61
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    62
        Returns an iterable of frames that should be sent over the wire.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    63
        """
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    64
        request, action, meta = self._reactor.callcommand(command, args)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    65
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    66
        if action != 'noop':
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    67
            raise error.ProgrammingError('%s not yet supported' % action)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    68
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    69
        rid = request.requestid
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    70
        self._requests[rid] = request
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    71
        self._futures[rid] = f
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
    72
        self._responses[rid] = commandresponse(rid, command)
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    73
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    74
        return iter(())
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    75
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    76
    def flushcommands(self):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    77
        """Flush all queued commands.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    78
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    79
        Returns an iterable of frames that should be sent over the wire.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    80
        """
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    81
        action, meta = self._reactor.flushcommands()
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    82
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    83
        if action != 'sendframes':
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    84
            raise error.ProgrammingError('%s not yet supported' % action)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    85
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    86
        return meta['framegen']
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    87
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    88
    def readframe(self, fh):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    89
        """Attempt to read and process a frame.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    90
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    91
        Returns None if no frame was read. Presumably this means EOF.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    92
        """
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    93
        frame = wireprotoframing.readframe(fh)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    94
        if frame is None:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    95
            # TODO tell reactor?
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    96
            return
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    97
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    98
        self._ui.note(_('received %r\n') % frame)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    99
        self._processframe(frame)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   100
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   101
        return True
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   102
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   103
    def _processframe(self, frame):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   104
        """Process a single read frame."""
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   105
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   106
        action, meta = self._reactor.onframerecv(frame)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   107
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   108
        if action == 'error':
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   109
            e = error.RepoError(meta['message'])
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   110
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   111
            if frame.requestid in self._futures:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   112
                self._futures[frame.requestid].set_exception(e)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   113
            else:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   114
                raise e
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   115
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   116
        if frame.requestid not in self._requests:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   117
            raise error.ProgrammingError(
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   118
                'received frame for unknown request; this is either a bug in '
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   119
                'the clientreactor not screening for this or this instance was '
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   120
                'never told about this request: %r' % frame)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   121
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   122
        response = self._responses[frame.requestid]
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   123
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   124
        if action == 'responsedata':
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
   125
            response.b.write(meta['data'])
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   126
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   127
            if meta['cbor']:
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
   128
                response.cbor = True
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   129
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   130
            if meta['eos']:
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   131
                # If the command has a decoder, resolve the future to the
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   132
                # decoded value. Otherwise resolve to the rich response object.
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   133
                decoder = COMMAND_DECODERS.get(response.command)
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   134
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   135
                result = decoder(response) if decoder else response
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   136
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   137
                self._futures[frame.requestid].set_result(result)
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   138
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   139
                del self._requests[frame.requestid]
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   140
                del self._futures[frame.requestid]
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   141
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   142
        else:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   143
            raise error.ProgrammingError(
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   144
                'unhandled action from clientreactor: %s' % action)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   145
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   146
def decodebranchmap(resp):
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   147
    # Response should be a single CBOR map of branch name to array of nodes.
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   148
    bm = next(resp.cborobjects())
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   149
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   150
    return {encoding.tolocal(k): v for k, v in bm.items()}
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   151
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   152
def decodeheads(resp):
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   153
    # Array of node bytestrings.
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   154
    return next(resp.cborobjects())
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   155
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   156
def decodeknown(resp):
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   157
    # Bytestring where each byte is a 0 or 1.
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   158
    raw = next(resp.cborobjects())
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   159
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   160
    return [True if c == '1' else False for c in raw]
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   161
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   162
def decodelistkeys(resp):
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   163
    # Map with bytestring keys and values.
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   164
    return next(resp.cborobjects())
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   165
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   166
def decodelookup(resp):
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   167
    return next(resp.cborobjects())
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   168
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   169
def decodepushkey(resp):
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   170
    return next(resp.cborobjects())
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   171
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   172
COMMAND_DECODERS = {
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   173
    'branchmap': decodebranchmap,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   174
    'heads': decodeheads,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   175
    'known': decodeknown,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   176
    'listkeys': decodelistkeys,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   177
    'lookup': decodelookup,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   178
    'pushkey': decodepushkey,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   179
}