mercurial/wireprotoserver.py
author Martin von Zweigbergk <martinvonz@google.com>
Tue, 23 Feb 2021 10:28:42 -0800
changeset 47020 ba6881c6a178
parent 46819 d4ba4d51f85f
child 48490 81805bba11f9
permissions -rw-r--r--
rewriteutil: check for divergence This code is adapted from the code in the evolve extension. It seems to be equivalent as far as the evolve extension's test suite can tell (the only impact when making their `precheck()` delegate to our version is that error messages are less detailed). I had to change the error message to work with "change branch of" being inserted as the action. Differential Revision: https://phab.mercurial-scm.org/D10518
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     1
# Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
46819
d4ba4d51f85f contributor: change mentions of mpm to olivia
Raphaël Gomès <rgomes@octobus.net>
parents: 46697
diff changeset
     2
# Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     3
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8109
diff changeset
     4
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9713
diff changeset
     5
# GNU General Public License version 2 or any later version.
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     6
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 20903
diff changeset
     7
from __future__ import absolute_import
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 20903
diff changeset
     8
36066
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
     9
import contextlib
30764
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
    10
import struct
36523
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
    11
import threading
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 20903
diff changeset
    12
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
    13
from .i18n import _
35856
ef3a24a023ec wireprotoserver: rename hgweb.protocol to wireprotoserver (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35750
diff changeset
    14
from . import (
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
    15
    encoding,
34509
e21f274cccea hgweb: in protocol adapter, avoid control reaching end of non-void function
Augie Fackler <augie@google.com>
parents: 33821
diff changeset
    16
    error,
34742
5a9cad0dfddb hgweb: when unpacking args from request form, convert to bytes
Augie Fackler <augie@google.com>
parents: 34740
diff changeset
    17
    pycompat,
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 20903
diff changeset
    18
    util,
36073
cd6ab329c5c7 wireprototypes: move wire protocol response types to new module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36072
diff changeset
    19
    wireprototypes,
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
    20
    wireprotov1server,
37545
93397c4633f6 wireproto: extract HTTP version 2 code to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37535
diff changeset
    21
    wireprotov2server,
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 20903
diff changeset
    22
)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
    23
from .interfaces import util as interfaceutil
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37061
diff changeset
    24
from .utils import (
39447
5f4a9ada5ab5 wireprotoserver: use our CBOR encoder
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38783
diff changeset
    25
    cborutil,
42041
3e47d1ec9da5 util: extract compression code in `mercurial.utils.compression`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 41285
diff changeset
    26
    compression,
46697
71443f742886 wireprotoserver: convert ErrorResponse to bytes
Matt Harbison <matt_harbison@yahoo.com>
parents: 45818
diff changeset
    27
    stringutil,
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37061
diff changeset
    28
)
35856
ef3a24a023ec wireprotoserver: rename hgweb.protocol to wireprotoserver (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35750
diff changeset
    29
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28530
diff changeset
    30
stringio = util.stringio
5963
5be210afe1b8 hgweb: explicitly check if requested command exists
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5915
diff changeset
    31
28883
032c4c2f802a pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents: 28861
diff changeset
    32
urlerr = util.urlerr
032c4c2f802a pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents: 28861
diff changeset
    33
urlreq = util.urlreq
032c4c2f802a pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents: 28861
diff changeset
    34
35858
1b76a9e0a9de wireprotoserver: don't import symbol from hgweb.common
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35857
diff changeset
    35
HTTP_OK = 200
1b76a9e0a9de wireprotoserver: don't import symbol from hgweb.common
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35857
diff changeset
    36
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    37
HGTYPE = b'application/mercurial-0.1'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    38
HGTYPE2 = b'application/mercurial-0.2'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    39
HGERRTYPE = b'application/hg-error'
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
    40
36536
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36526
diff changeset
    41
SSHV1 = wireprototypes.SSHV1
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36526
diff changeset
    42
SSHV2 = wireprototypes.SSHV2
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35900
diff changeset
    43
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
    44
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
    45
def decodevaluefromheaders(req, headerprefix):
34744
0a2ef612ad50 hgweb: fix decodevaluefromheaders to always return a bytes value
Augie Fackler <augie@google.com>
parents: 34743
diff changeset
    46
    """Decode a long value from multiple HTTP request headers.
0a2ef612ad50 hgweb: fix decodevaluefromheaders to always return a bytes value
Augie Fackler <augie@google.com>
parents: 34743
diff changeset
    47
0a2ef612ad50 hgweb: fix decodevaluefromheaders to always return a bytes value
Augie Fackler <augie@google.com>
parents: 34743
diff changeset
    48
    Returns the value as a bytes, not a str.
0a2ef612ad50 hgweb: fix decodevaluefromheaders to always return a bytes value
Augie Fackler <augie@google.com>
parents: 34743
diff changeset
    49
    """
30759
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
    50
    chunks = []
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
    51
    i = 1
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
    52
    while True:
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
    53
        v = req.headers.get(b'%s-%d' % (headerprefix, i))
30759
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
    54
        if v is None:
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
    55
            break
34744
0a2ef612ad50 hgweb: fix decodevaluefromheaders to always return a bytes value
Augie Fackler <augie@google.com>
parents: 34743
diff changeset
    56
        chunks.append(pycompat.bytesurl(v))
30759
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
    57
        i += 1
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
    58
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    59
    return b''.join(chunks)
30759
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
    60
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
    61
37810
856f381ad74b interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37785
diff changeset
    62
@interfaceutil.implementer(wireprototypes.baseprotocolhandler)
37296
78103e4138b1 wireproto: port protocol handler to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37295
diff changeset
    63
class httpv1protocolhandler(object):
36867
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
    64
    def __init__(self, req, ui, checkperm):
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
    65
        self._req = req
35866
d747cf39cf70 wireprotoserver: make attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35865
diff changeset
    66
        self._ui = ui
36801
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
    67
        self._checkperm = checkperm
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
    68
        self._protocaps = None
35873
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
    69
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
    70
    @property
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
    71
    def name(self):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    72
        return b'http-v1'
30562
b3a9ef3d30e8 protocol: declare transport protocol name
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30466
diff changeset
    73
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
    74
    def getargs(self, args):
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
    75
        knownargs = self._args()
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
    76
        data = {}
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
    77
        keys = args.split()
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
    78
        for k in keys:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    79
            if k == b'*':
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
    80
                star = {}
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
    81
                for key in knownargs.keys():
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    82
                    if key != b'cmd' and key not in keys:
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
    83
                        star[key] = knownargs[key][0]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    84
                data[b'*'] = star
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
    85
            else:
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
    86
                data[k] = knownargs[k][0]
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
    87
        return [data[k] for k in keys]
35863
49426bb4476c wireprotoserver: add some blank lines between methods
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35860
diff changeset
    88
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
    89
    def _args(self):
36862
ec0af9c59270 hgweb: use a multidict for holding query string parameters
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36861
diff changeset
    90
        args = self._req.qsparams.asdictoflists()
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
    91
        postlen = int(self._req.headers.get(b'X-HgArgs-Post', 0))
28530
fd2acc5046f6 http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents: 27046
diff changeset
    92
        if postlen:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
    93
            args.update(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
    94
                urlreq.parseqs(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
    95
                    self._req.bodyfh.read(postlen), keep_blank_values=True
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
    96
                )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
    97
            )
28530
fd2acc5046f6 http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents: 27046
diff changeset
    98
            return args
30759
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
    99
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
   100
        argvalue = decodevaluefromheaders(self._req, b'X-HgArg')
36077
a3d42d1865f1 wireprotoserver: define and use parse_qs from urllib
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36075
diff changeset
   101
        args.update(urlreq.parseqs(argvalue, keep_blank_values=True))
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
   102
        return args
35863
49426bb4476c wireprotoserver: add some blank lines between methods
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35860
diff changeset
   103
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
   104
    def getprotocaps(self):
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
   105
        if self._protocaps is None:
37590
9170df9106a8 wireprotoserver: headers are bytes for us internally, use bytes
Augie Fackler <augie@google.com>
parents: 37557
diff changeset
   106
            value = decodevaluefromheaders(self._req, b'X-HgProto')
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   107
            self._protocaps = set(value.split(b' '))
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
   108
        return self._protocaps
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
   109
37414
2d965bfeb8f6 wireproto: allow direct stream processing for unbundle
Joerg Sonnenberger <joerg@bec.de>
parents: 37393
diff changeset
   110
    def getpayload(self):
36847
ed0456fde625 hgweb: handle CONTENT_LENGTH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36846
diff changeset
   111
        # Existing clients *always* send Content-Length.
ed0456fde625 hgweb: handle CONTENT_LENGTH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36846
diff changeset
   112
        length = int(self._req.headers[b'Content-Length'])
ed0456fde625 hgweb: handle CONTENT_LENGTH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36846
diff changeset
   113
33821
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33228
diff changeset
   114
        # If httppostargs is used, we need to read Content-Length
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33228
diff changeset
   115
        # minus the amount that was consumed by args.
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
   116
        length -= int(self._req.headers.get(b'X-HgArgs-Post', 0))
37414
2d965bfeb8f6 wireproto: allow direct stream processing for unbundle
Joerg Sonnenberger <joerg@bec.de>
parents: 37393
diff changeset
   117
        return util.filechunkiter(self._req.bodyfh, limit=length)
35863
49426bb4476c wireprotoserver: add some blank lines between methods
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35860
diff changeset
   118
36066
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   119
    @contextlib.contextmanager
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   120
    def mayberedirectstdio(self):
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   121
        oldout = self._ui.fout
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   122
        olderr = self._ui.ferr
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   123
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   124
        out = util.stringio()
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   125
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   126
        try:
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   127
            self._ui.fout = out
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   128
            self._ui.ferr = out
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   129
            yield out
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   130
        finally:
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   131
            self._ui.fout = oldout
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   132
            self._ui.ferr = olderr
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   133
36069
957e773614d0 wireprotoserver: rename _client to client (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36068
diff changeset
   134
    def client(self):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   135
        return b'remote:%s:%s:%s' % (
36867
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
   136
            self._req.urlscheme,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   137
            urlreq.quote(self._req.remotehost or b''),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   138
            urlreq.quote(self._req.remoteuser or b''),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   139
        )
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
   140
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
   141
    def addcapabilities(self, repo, caps):
37053
cd0ca979a8b8 wireproto: nominally don't expose "batch" to version 2 wire transports
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37052
diff changeset
   142
        caps.append(b'batch')
cd0ca979a8b8 wireproto: nominally don't expose "batch" to version 2 wire transports
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37052
diff changeset
   143
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   144
        caps.append(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   145
            b'httpheader=%d' % repo.ui.configint(b'server', b'maxhttpheaderlen')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   146
        )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   147
        if repo.ui.configbool(b'experimental', b'httppostargs'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   148
            caps.append(b'httppostargs')
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
   149
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
   150
        # FUTURE advertise 0.2rx once support is implemented
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
   151
        # FUTURE advertise minrx and mintx after consulting config option
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   152
        caps.append(b'httpmediatype=0.1rx,0.1tx,0.2tx')
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
   153
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   154
        compengines = wireprototypes.supportedcompengines(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   155
            repo.ui, compression.SERVERROLE
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   156
        )
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
   157
        if compengines:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   158
            comptypes = b','.join(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   159
                urlreq.quote(e.wireprotosupport().name) for e in compengines
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   160
            )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   161
            caps.append(b'compression=%s' % comptypes)
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
   162
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
   163
        return caps
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
   164
36801
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
   165
    def checkperm(self, perm):
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
   166
        return self._checkperm(perm)
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
   167
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   168
36231
72812ad205d1 wireprotoserver: return to using iscmd() method
Augie Fackler <augie@google.com>
parents: 36223
diff changeset
   169
# This method exists mostly so that extensions like remotefilelog can
72812ad205d1 wireprotoserver: return to using iscmd() method
Augie Fackler <augie@google.com>
parents: 36223
diff changeset
   170
# disable a kludgey legacy method only over http. As of early 2018,
72812ad205d1 wireprotoserver: return to using iscmd() method
Augie Fackler <augie@google.com>
parents: 36223
diff changeset
   171
# there are no other known users, so with any luck we can discard this
72812ad205d1 wireprotoserver: return to using iscmd() method
Augie Fackler <augie@google.com>
parents: 36223
diff changeset
   172
# hook if remotefilelog becomes a first-party extension.
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
   173
def iscmd(cmd):
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
   174
    return cmd in wireprotov1server.commands
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
   175
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   176
36877
02bea04b4c54 hgweb: transition permissions hooks to modern request type (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36867
diff changeset
   177
def handlewsgirequest(rctx, req, res, checkperm):
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   178
    """Possibly process a wire protocol request.
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   179
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   180
    If the current request is a wire protocol request, the request is
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   181
    processed by this function.
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   182
36810
886fba199022 hgweb: only recognize wire protocol commands from query string (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36804
diff changeset
   183
    ``req`` is a ``parsedrequest`` instance.
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   184
    ``res`` is a ``wsgiresponse`` instance.
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   185
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   186
    Returns a bool indicating if the request was serviced. If set, the caller
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   187
    should stop processing the request, as a response has already been issued.
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   188
    """
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   189
    # Avoid cycle involving hg module.
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   190
    from .hgweb import common as hgwebcommon
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   191
36801
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
   192
    repo = rctx.repo
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
   193
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   194
    # HTTP version 1 wire protocol requests are denoted by a "cmd" query
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   195
    # string parameter. If it isn't present, this isn't a wire protocol
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   196
    # request.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   197
    if b'cmd' not in req.qsparams:
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   198
        return False
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   199
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   200
    cmd = req.qsparams[b'cmd']
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   201
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   202
    # The "cmd" request parameter is used by both the wire protocol and hgweb.
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   203
    # While not all wire protocol commands are available for all transports,
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   204
    # if we see a "cmd" value that resembles a known wire protocol command, we
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   205
    # route it to a protocol handler. This is better than routing possible
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   206
    # wire protocol requests to hgweb because it prevents hgweb from using
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   207
    # known wire protocol commands and it is less confusing for machine
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   208
    # clients.
36231
72812ad205d1 wireprotoserver: return to using iscmd() method
Augie Fackler <augie@google.com>
parents: 36223
diff changeset
   209
    if not iscmd(cmd):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   210
        return False
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   211
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   212
    # The "cmd" query string argument is only valid on the root path of the
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   213
    # repo. e.g. ``/?cmd=foo``, ``/repo?cmd=foo``. URL paths within the repo
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   214
    # like ``/blah?cmd=foo`` are not allowed. So don't recognize the request
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   215
    # in this case. We send an HTTP 404 for backwards compatibility reasons.
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   216
    if req.dispatchpath:
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   217
        res.status = hgwebcommon.statusmessage(404)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   218
        res.headers[b'Content-Type'] = HGTYPE
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   219
        # TODO This is not a good response to issue for this request. This
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   220
        # is mostly for BC for now.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   221
        res.setbodybytes(b'0\n%s\n' % b'Not Found')
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   222
        return True
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   223
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   224
    proto = httpv1protocolhandler(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   225
        req, repo.ui, lambda perm: checkperm(rctx, req, perm)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   226
    )
30764
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
   227
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   228
    # The permissions checker should be the only thing that can raise an
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   229
    # ErrorResponse. It is kind of a layer violation to catch an hgweb
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   230
    # exception here. So consider refactoring into a exception type that
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   231
    # is associated with the wire protocol.
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   232
    try:
36867
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
   233
        _callhttp(repo, req, res, proto, cmd)
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   234
    except hgwebcommon.ErrorResponse as e:
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   235
        for k, v in e.headers:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   236
            res.headers[k] = v
46697
71443f742886 wireprotoserver: convert ErrorResponse to bytes
Matt Harbison <matt_harbison@yahoo.com>
parents: 45818
diff changeset
   237
        res.status = hgwebcommon.statusmessage(
71443f742886 wireprotoserver: convert ErrorResponse to bytes
Matt Harbison <matt_harbison@yahoo.com>
parents: 45818
diff changeset
   238
            e.code, stringutil.forcebytestr(e)
71443f742886 wireprotoserver: convert ErrorResponse to bytes
Matt Harbison <matt_harbison@yahoo.com>
parents: 45818
diff changeset
   239
        )
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   240
        # TODO This response body assumes the failed command was
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   241
        # "unbundle." That assumption is not always valid.
46697
71443f742886 wireprotoserver: convert ErrorResponse to bytes
Matt Harbison <matt_harbison@yahoo.com>
parents: 45818
diff changeset
   242
        res.setbodybytes(b'0\n%s\n' % stringutil.forcebytestr(e))
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
   243
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   244
    return True
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
   245
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   246
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   247
def _availableapis(repo):
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   248
    apis = set()
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   249
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   250
    # Registered APIs are made available via config options of the name of
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   251
    # the protocol.
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   252
    for k, v in API_HANDLERS.items():
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   253
        section, option = v[b'config']
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   254
        if repo.ui.configbool(section, option):
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   255
            apis.add(k)
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   256
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   257
    return apis
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   258
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   259
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   260
def handlewsgiapirequest(rctx, req, res, checkperm):
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   261
    """Handle requests to /api/*."""
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   262
    assert req.dispatchparts[0] == b'api'
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   263
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   264
    repo = rctx.repo
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   265
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   266
    # This whole URL space is experimental for now. But we want to
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   267
    # reserve the URL space. So, 404 all URLs if the feature isn't enabled.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   268
    if not repo.ui.configbool(b'experimental', b'web.apiserver'):
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   269
        res.status = b'404 Not Found'
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   270
        res.headers[b'Content-Type'] = b'text/plain'
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   271
        res.setbodybytes(_(b'Experimental API server endpoint not enabled'))
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   272
        return
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   273
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   274
    # The URL space is /api/<protocol>/*. The structure of URLs under varies
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   275
    # by <protocol>.
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   276
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   277
    availableapis = _availableapis(repo)
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   278
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   279
    # Requests to /api/ list available APIs.
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   280
    if req.dispatchparts == [b'api']:
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   281
        res.status = b'200 OK'
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   282
        res.headers[b'Content-Type'] = b'text/plain'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   283
        lines = [
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   284
            _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   285
                b'APIs can be accessed at /api/<name>, where <name> can be '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   286
                b'one of the following:\n'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   287
            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   288
        ]
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   289
        if availableapis:
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   290
            lines.extend(sorted(availableapis))
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   291
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   292
            lines.append(_(b'(no available APIs)\n'))
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   293
        res.setbodybytes(b'\n'.join(lines))
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   294
        return
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   295
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   296
    proto = req.dispatchparts[1]
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   297
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   298
    if proto not in API_HANDLERS:
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   299
        res.status = b'404 Not Found'
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   300
        res.headers[b'Content-Type'] = b'text/plain'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   301
        res.setbodybytes(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   302
            _(b'Unknown API: %s\nKnown APIs: %s')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   303
            % (proto, b', '.join(sorted(availableapis)))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   304
        )
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   305
        return
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   306
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   307
    if proto not in availableapis:
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   308
        res.status = b'404 Not Found'
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   309
        res.headers[b'Content-Type'] = b'text/plain'
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   310
        res.setbodybytes(_(b'API %s not enabled\n') % proto)
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   311
        return
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   312
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   313
    API_HANDLERS[proto][b'handler'](
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   314
        rctx, req, res, checkperm, req.dispatchparts[2:]
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   315
    )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   316
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   317
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   318
# Maps API name to metadata so custom API can be registered.
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   319
# Keys are:
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   320
#
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   321
# config
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   322
#    Config option that controls whether service is enabled.
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   323
# handler
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   324
#    Callable receiving (rctx, req, res, checkperm, urlparts) that is called
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   325
#    when a request to this API is received.
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   326
# apidescriptor
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   327
#    Callable receiving (req, repo) that is called to obtain an API
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   328
#    descriptor for this service. The response must be serializable to CBOR.
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   329
API_HANDLERS = {
37644
77c9ee77687c wireproto: rename HTTPV2 so it less like HTTP/2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37590
diff changeset
   330
    wireprotov2server.HTTP_WIREPROTO_V2: {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   331
        b'config': (b'experimental', b'web.api.http-v2'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   332
        b'handler': wireprotov2server.handlehttpv2request,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   333
        b'apidescriptor': wireprotov2server.httpv2apidescriptor,
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   334
    },
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   335
}
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
   336
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   337
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
   338
def _httpresponsetype(ui, proto, prefer_uncompressed):
36072
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   339
    """Determine the appropriate response type and compression settings.
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   340
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   341
    Returns a tuple of (mediatype, compengine, engineopts).
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   342
    """
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   343
    # Determine the response media type and compression engine based
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   344
    # on the request parameters.
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   345
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   346
    if b'0.2' in proto.getprotocaps():
36072
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   347
        # All clients are expected to support uncompressed data.
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   348
        if prefer_uncompressed:
42041
3e47d1ec9da5 util: extract compression code in `mercurial.utils.compression`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 41285
diff changeset
   349
            return HGTYPE2, compression._noopengine(), {}
36072
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   350
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   351
        # Now find an agreed upon compression format.
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
   352
        compformats = wireprotov1server.clientcompressionsupport(proto)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   353
        for engine in wireprototypes.supportedcompengines(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   354
            ui, compression.SERVERROLE
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   355
        ):
36072
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   356
            if engine.wireprotosupport().name in compformats:
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   357
                opts = {}
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   358
                level = ui.configint(b'server', b'%slevel' % engine.name())
36072
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   359
                if level is not None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   360
                    opts[b'level'] = level
36072
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   361
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   362
                return HGTYPE2, engine, opts
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   363
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   364
        # No mutually supported compression format. Fall back to the
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   365
        # legacy protocol.
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   366
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   367
    # Don't allow untrusted settings because disabling compression or
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   368
    # setting a very high compression level could lead to flooding
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   369
    # the server's network or CPU.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   370
    opts = {b'level': ui.configint(b'server', b'zliblevel')}
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   371
    return HGTYPE, util.compengines[b'zlib'], opts
36072
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   372
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   373
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   374
def processcapabilitieshandshake(repo, req, res, proto):
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   375
    """Called during a ?cmd=capabilities request.
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   376
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   377
    If the client is advertising support for a newer protocol, we send
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   378
    a CBOR response with information about available services. If no
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   379
    advertised services are available, we don't handle the request.
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   380
    """
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   381
    # Fall back to old behavior unless the API server is enabled.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   382
    if not repo.ui.configbool(b'experimental', b'web.apiserver'):
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   383
        return False
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   384
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   385
    clientapis = decodevaluefromheaders(req, b'X-HgUpgrade')
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   386
    protocaps = decodevaluefromheaders(req, b'X-HgProto')
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   387
    if not clientapis or not protocaps:
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   388
        return False
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   389
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   390
    # We currently only support CBOR responses.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   391
    protocaps = set(protocaps.split(b' '))
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   392
    if b'cbor' not in protocaps:
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   393
        return False
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   394
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   395
    descriptors = {}
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   396
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   397
    for api in sorted(set(clientapis.split()) & _availableapis(repo)):
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   398
        handler = API_HANDLERS[api]
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   399
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   400
        descriptorfn = handler.get(b'apidescriptor')
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   401
        if not descriptorfn:
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   402
            continue
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   403
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   404
        descriptors[api] = descriptorfn(req, repo)
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   405
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   406
    v1caps = wireprotov1server.dispatch(repo, proto, b'capabilities')
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   407
    assert isinstance(v1caps, wireprototypes.bytesresponse)
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   408
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   409
    m = {
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   410
        # TODO allow this to be configurable.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   411
        b'apibase': b'api/',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   412
        b'apis': descriptors,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   413
        b'v1capabilities': v1caps.data,
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   414
    }
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   415
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   416
    res.status = b'200 OK'
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   417
    res.headers[b'Content-Type'] = b'application/mercurial-cbor'
39447
5f4a9ada5ab5 wireprotoserver: use our CBOR encoder
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38783
diff changeset
   418
    res.setbodybytes(b''.join(cborutil.streamencode(m)))
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   419
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   420
    return True
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   421
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   422
36867
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
   423
def _callhttp(repo, req, res, proto, cmd):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   424
    # Avoid cycle involving hg module.
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   425
    from .hgweb import common as hgwebcommon
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   426
35750
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
   427
    def genversion2(gen, engine, engineopts):
30764
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
   428
        # application/mercurial-0.2 always sends a payload header
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
   429
        # identifying the compression engine.
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
   430
        name = engine.wireprotosupport().name
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
   431
        assert 0 < len(name) < 256
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   432
        yield struct.pack(b'B', len(name))
30764
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
   433
        yield name
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
   434
35750
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
   435
        for chunk in gen:
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
   436
            yield chunk
30764
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
   437
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   438
    def setresponse(code, contenttype, bodybytes=None, bodygen=None):
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   439
        if code == HTTP_OK:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   440
            res.status = b'200 Script output follows'
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   441
        else:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   442
            res.status = hgwebcommon.statusmessage(code)
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   443
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   444
        res.headers[b'Content-Type'] = contenttype
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   445
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   446
        if bodybytes is not None:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   447
            res.setbodybytes(bodybytes)
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   448
        if bodygen is not None:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   449
            res.setbodygen(bodygen)
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   450
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
   451
    if not wireprotov1server.commands.commandavailable(cmd, proto):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   452
        setresponse(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   453
            HTTP_OK,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   454
            HGERRTYPE,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   455
            _(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   456
                b'requested wire protocol command is not available over '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   457
                b'HTTP'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   458
            ),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   459
        )
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   460
        return
35982
5a56bf4180ad wireproto: function for testing if wire protocol command is available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35976
diff changeset
   461
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
   462
    proto.checkperm(wireprotov1server.commands[cmd].permission)
36799
c638a13093cf wireprotoserver: check permissions in main dispatch function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36798
diff changeset
   463
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   464
    # Possibly handle a modern client wanting to switch protocols.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   465
    if cmd == b'capabilities' and processcapabilitieshandshake(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   466
        repo, req, res, proto
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   467
    ):
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   468
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   469
        return
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   470
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
   471
    rsp = wireprotov1server.dispatch(repo, proto, cmd)
36798
7574c8173d5e wireprotoserver: check if command available before calling it
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36760
diff changeset
   472
34510
c23fa3103925 hgweb: in protocol adapter, look for bytes instances, not str
Augie Fackler <augie@google.com>
parents: 34509
diff changeset
   473
    if isinstance(rsp, bytes):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   474
        setresponse(HTTP_OK, HGTYPE, bodybytes=rsp)
36074
2f7290555c96 wireproto: introduce type for raw byte responses (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36073
diff changeset
   475
    elif isinstance(rsp, wireprototypes.bytesresponse):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   476
        setresponse(HTTP_OK, HGTYPE, bodybytes=rsp.data)
36073
cd6ab329c5c7 wireprototypes: move wire protocol response types to new module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36072
diff changeset
   477
    elif isinstance(rsp, wireprototypes.streamreslegacy):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   478
        setresponse(HTTP_OK, HGTYPE, bodygen=rsp.gen)
36073
cd6ab329c5c7 wireprototypes: move wire protocol response types to new module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36072
diff changeset
   479
    elif isinstance(rsp, wireprototypes.streamres):
35705
8cdb671dbd0b wireproto: drop support for reader interface from streamres (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 34744
diff changeset
   480
        gen = rsp.gen
30466
2add671bf55b wireproto: perform chunking and compression at protocol layer (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30366
diff changeset
   481
30764
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
   482
        # This code for compression should not be streamres specific. It
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
   483
        # is here because we only compress streamres at the moment.
36072
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
   484
        mediatype, engine, engineopts = _httpresponsetype(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   485
            repo.ui, proto, rsp.prefer_uncompressed
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   486
        )
35750
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
   487
        gen = engine.compressstream(gen, engineopts)
30466
2add671bf55b wireproto: perform chunking and compression at protocol layer (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30366
diff changeset
   488
35750
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
   489
        if mediatype == HGTYPE2:
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
   490
            gen = genversion2(gen, engine, engineopts)
30764
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
   491
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   492
        setresponse(HTTP_OK, mediatype, bodygen=gen)
36073
cd6ab329c5c7 wireprototypes: move wire protocol response types to new module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36072
diff changeset
   493
    elif isinstance(rsp, wireprototypes.pushres):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   494
        rsp = b'%d\n%s' % (rsp.res, rsp.output)
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   495
        setresponse(HTTP_OK, HGTYPE, bodybytes=rsp)
36073
cd6ab329c5c7 wireprototypes: move wire protocol response types to new module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36072
diff changeset
   496
    elif isinstance(rsp, wireprototypes.pusherr):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   497
        rsp = b'0\n%s\n' % rsp.res
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   498
        res.drain = True
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   499
        setresponse(HTTP_OK, HGTYPE, bodybytes=rsp)
36073
cd6ab329c5c7 wireprototypes: move wire protocol response types to new module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36072
diff changeset
   500
    elif isinstance(rsp, wireprototypes.ooberror):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   501
        setresponse(HTTP_OK, HGERRTYPE, bodybytes=rsp.message)
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
   502
    else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   503
        raise error.ProgrammingError(b'hgweb.protocol internal failure', rsp)
35986
98a00aa0288d wireprotoserver: move error response handling out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35984
diff changeset
   504
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   505
36064
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   506
def _sshv1respondbytes(fout, value):
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   507
    """Send a bytes response for protocol version 1."""
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   508
    fout.write(b'%d\n' % len(value))
36064
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   509
    fout.write(value)
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   510
    fout.flush()
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   511
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   512
36064
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   513
def _sshv1respondstream(fout, source):
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   514
    write = fout.write
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   515
    for chunk in source.gen:
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   516
        write(chunk)
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   517
    fout.flush()
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   518
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   519
36064
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   520
def _sshv1respondooberror(fout, ferr, rsp):
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   521
    ferr.write(b'%s\n-\n' % rsp)
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   522
    ferr.flush()
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   523
    fout.write(b'\n')
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   524
    fout.flush()
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
   525
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   526
37810
856f381ad74b interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37785
diff changeset
   527
@interfaceutil.implementer(wireprototypes.baseprotocolhandler)
37296
78103e4138b1 wireproto: port protocol handler to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37295
diff changeset
   528
class sshv1protocolhandler(object):
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
   529
    """Handler for requests services via version 1 of SSH protocol."""
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   530
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
   531
    def __init__(self, ui, fin, fout):
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
   532
        self._ui = ui
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
   533
        self._fin = fin
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
   534
        self._fout = fout
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
   535
        self._protocaps = set()
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   536
35873
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
   537
    @property
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
   538
    def name(self):
36536
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36526
diff changeset
   539
        return wireprototypes.SSHV1
35873
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
   540
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   541
    def getargs(self, args):
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   542
        data = {}
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   543
        keys = args.split()
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37945
diff changeset
   544
        for n in pycompat.xrange(len(keys)):
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
   545
            argline = self._fin.readline()[:-1]
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   546
            arg, l = argline.split()
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   547
            if arg not in keys:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   548
                raise error.Abort(_(b"unexpected parameter %r") % arg)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   549
            if arg == b'*':
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   550
                star = {}
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37945
diff changeset
   551
                for k in pycompat.xrange(int(l)):
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
   552
                    argline = self._fin.readline()[:-1]
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   553
                    arg, l = argline.split()
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
   554
                    val = self._fin.read(int(l))
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   555
                    star[arg] = val
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   556
                data[b'*'] = star
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   557
            else:
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
   558
                val = self._fin.read(int(l))
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   559
                data[arg] = val
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   560
        return [data[k] for k in keys]
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   561
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
   562
    def getprotocaps(self):
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
   563
        return self._protocaps
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
   564
37414
2d965bfeb8f6 wireproto: allow direct stream processing for unbundle
Joerg Sonnenberger <joerg@bec.de>
parents: 37393
diff changeset
   565
    def getpayload(self):
36372
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36371
diff changeset
   566
        # We initially send an empty response. This tells the client it is
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36371
diff changeset
   567
        # OK to start sending data. If a client sees any other response, it
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36371
diff changeset
   568
        # interprets it as an error.
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36371
diff changeset
   569
        _sshv1respondbytes(self._fout, b'')
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36371
diff changeset
   570
36070
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
   571
        # The file is in the form:
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
   572
        #
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
   573
        # <chunk size>\n<chunk>
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
   574
        # ...
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
   575
        # 0\n
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
   576
        count = int(self._fin.readline())
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   577
        while count:
37414
2d965bfeb8f6 wireproto: allow direct stream processing for unbundle
Joerg Sonnenberger <joerg@bec.de>
parents: 37393
diff changeset
   578
            yield self._fin.read(count)
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
   579
            count = int(self._fin.readline())
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   580
36066
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   581
    @contextlib.contextmanager
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   582
    def mayberedirectstdio(self):
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   583
        yield None
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
   584
36069
957e773614d0 wireprotoserver: rename _client to client (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36068
diff changeset
   585
    def client(self):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   586
        client = encoding.environ.get(b'SSH_CLIENT', b'').split(b' ', 1)[0]
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   587
        return b'remote:ssh:' + client
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
   588
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
   589
    def addcapabilities(self, repo, caps):
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
   590
        if self.name == wireprototypes.SSHV1:
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
   591
            caps.append(b'protocaps')
37053
cd0ca979a8b8 wireproto: nominally don't expose "batch" to version 2 wire transports
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37052
diff changeset
   592
        caps.append(b'batch')
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
   593
        return caps
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
   594
36801
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
   595
    def checkperm(self, perm):
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
   596
        pass
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
   597
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   598
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   599
class sshv2protocolhandler(sshv1protocolhandler):
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   600
    """Protocol handler for version 2 of the SSH protocol."""
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   601
36610
af0d38f015bb wireprotoserver: identify requests via version 2 of SSH protocol as such
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36536
diff changeset
   602
    @property
af0d38f015bb wireprotoserver: identify requests via version 2 of SSH protocol as such
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36536
diff changeset
   603
    def name(self):
af0d38f015bb wireprotoserver: identify requests via version 2 of SSH protocol as such
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36536
diff changeset
   604
        return wireprototypes.SSHV2
af0d38f015bb wireprotoserver: identify requests via version 2 of SSH protocol as such
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36536
diff changeset
   605
37533
df4985497986 wireproto: implement capabilities for wire protocol v2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37485
diff changeset
   606
    def addcapabilities(self, repo, caps):
df4985497986 wireproto: implement capabilities for wire protocol v2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37485
diff changeset
   607
        return caps
df4985497986 wireproto: implement capabilities for wire protocol v2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37485
diff changeset
   608
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   609
36523
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   610
def _runsshserver(ui, repo, fin, fout, ev):
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   611
    # This function operates like a state machine of sorts. The following
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   612
    # states are defined:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   613
    #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   614
    # protov1-serving
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   615
    #    Server is in protocol version 1 serving mode. Commands arrive on
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   616
    #    new lines. These commands are processed in this state, one command
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   617
    #    after the other.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   618
    #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   619
    # protov2-serving
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   620
    #    Server is in protocol version 2 serving mode.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   621
    #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   622
    # upgrade-initial
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   623
    #    The server is going to process an upgrade request.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   624
    #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   625
    # upgrade-v2-filter-legacy-handshake
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   626
    #    The protocol is being upgraded to version 2. The server is expecting
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   627
    #    the legacy handshake from version 1.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   628
    #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   629
    # upgrade-v2-finish
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   630
    #    The upgrade to version 2 of the protocol is imminent.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   631
    #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   632
    # shutdown
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   633
    #    The server is shutting down, possibly in reaction to a client event.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   634
    #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   635
    # And here are their transitions:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   636
    #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   637
    # protov1-serving -> shutdown
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   638
    #    When server receives an empty request or encounters another
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   639
    #    error.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   640
    #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   641
    # protov1-serving -> upgrade-initial
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   642
    #    An upgrade request line was seen.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   643
    #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   644
    # upgrade-initial -> upgrade-v2-filter-legacy-handshake
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   645
    #    Upgrade to version 2 in progress. Server is expecting to
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   646
    #    process a legacy handshake.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   647
    #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   648
    # upgrade-v2-filter-legacy-handshake -> shutdown
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   649
    #    Client did not fulfill upgrade handshake requirements.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   650
    #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   651
    # upgrade-v2-filter-legacy-handshake -> upgrade-v2-finish
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   652
    #    Client fulfilled version 2 upgrade requirements. Finishing that
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   653
    #    upgrade.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   654
    #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   655
    # upgrade-v2-finish -> protov2-serving
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   656
    #    Protocol upgrade to version 2 complete. Server can now speak protocol
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   657
    #    version 2.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   658
    #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   659
    # protov2-serving -> protov1-serving
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   660
    #    Ths happens by default since protocol version 2 is the same as
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   661
    #    version 1 except for the handshake.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   662
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   663
    state = b'protov1-serving'
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   664
    proto = sshv1protocolhandler(ui, fin, fout)
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   665
    protoswitched = False
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   666
36523
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   667
    while not ev.is_set():
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   668
        if state == b'protov1-serving':
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   669
            # Commands are issued on new lines.
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   670
            request = fin.readline()[:-1]
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   671
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   672
            # Empty lines signal to terminate the connection.
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   673
            if not request:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   674
                state = b'shutdown'
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   675
                continue
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   676
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   677
            # It looks like a protocol upgrade request. Transition state to
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   678
            # handle it.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   679
            if request.startswith(b'upgrade '):
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   680
                if protoswitched:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   681
                    _sshv1respondooberror(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   682
                        fout,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   683
                        ui.ferr,
43117
8ff1ecfadcd1 cleanup: join string literals that are already on one line
Martin von Zweigbergk <martinvonz@google.com>
parents: 43077
diff changeset
   684
                        b'cannot upgrade protocols multiple times',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   685
                    )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   686
                    state = b'shutdown'
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   687
                    continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   688
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   689
                state = b'upgrade-initial'
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   690
                continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   691
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
   692
            available = wireprotov1server.commands.commandavailable(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   693
                request, proto
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   694
            )
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   695
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   696
            # This command isn't available. Send an empty response and go
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   697
            # back to waiting for a new command.
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   698
            if not available:
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   699
                _sshv1respondbytes(fout, b'')
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   700
                continue
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   701
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
   702
            rsp = wireprotov1server.dispatch(repo, proto, request)
42896
7e19b640c53e sshserver: flush stream after command dispatch
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42814
diff changeset
   703
            repo.ui.fout.flush()
7e19b640c53e sshserver: flush stream after command dispatch
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42814
diff changeset
   704
            repo.ui.ferr.flush()
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   705
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   706
            if isinstance(rsp, bytes):
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   707
                _sshv1respondbytes(fout, rsp)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   708
            elif isinstance(rsp, wireprototypes.bytesresponse):
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   709
                _sshv1respondbytes(fout, rsp.data)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   710
            elif isinstance(rsp, wireprototypes.streamres):
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   711
                _sshv1respondstream(fout, rsp)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   712
            elif isinstance(rsp, wireprototypes.streamreslegacy):
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   713
                _sshv1respondstream(fout, rsp)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   714
            elif isinstance(rsp, wireprototypes.pushres):
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   715
                _sshv1respondbytes(fout, b'')
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   716
                _sshv1respondbytes(fout, b'%d' % rsp.res)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   717
            elif isinstance(rsp, wireprototypes.pusherr):
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   718
                _sshv1respondbytes(fout, rsp.res)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   719
            elif isinstance(rsp, wireprototypes.ooberror):
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   720
                _sshv1respondooberror(fout, ui.ferr, rsp.message)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   721
            else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   722
                raise error.ProgrammingError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   723
                    b'unhandled response type from '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   724
                    b'wire protocol command: %s' % rsp
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   725
                )
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   726
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   727
        # For now, protocol version 2 serving just goes back to version 1.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   728
        elif state == b'protov2-serving':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   729
            state = b'protov1-serving'
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   730
            continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   731
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   732
        elif state == b'upgrade-initial':
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   733
            # We should never transition into this state if we've switched
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   734
            # protocols.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   735
            assert not protoswitched
36536
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36526
diff changeset
   736
            assert proto.name == wireprototypes.SSHV1
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   737
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   738
            # Expected: upgrade <token> <capabilities>
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   739
            # If we get something else, the request is malformed. It could be
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   740
            # from a future client that has altered the upgrade line content.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   741
            # We treat this as an unknown command.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   742
            try:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   743
                token, caps = request.split(b' ')[1:]
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   744
            except ValueError:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   745
                _sshv1respondbytes(fout, b'')
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   746
                state = b'protov1-serving'
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   747
                continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   748
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   749
            # Send empty response if we don't support upgrading protocols.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   750
            if not ui.configbool(b'experimental', b'sshserver.support-v2'):
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   751
                _sshv1respondbytes(fout, b'')
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   752
                state = b'protov1-serving'
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   753
                continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   754
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   755
            try:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   756
                caps = urlreq.parseqs(caps)
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   757
            except ValueError:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   758
                _sshv1respondbytes(fout, b'')
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   759
                state = b'protov1-serving'
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   760
                continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   761
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   762
            # We don't see an upgrade request to protocol version 2. Ignore
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   763
            # the upgrade request.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   764
            wantedprotos = caps.get(b'proto', [b''])[0]
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   765
            if SSHV2 not in wantedprotos:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   766
                _sshv1respondbytes(fout, b'')
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   767
                state = b'protov1-serving'
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   768
                continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   769
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   770
            # It looks like we can honor this upgrade request to protocol 2.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   771
            # Filter the rest of the handshake protocol request lines.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   772
            state = b'upgrade-v2-filter-legacy-handshake'
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   773
            continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   774
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   775
        elif state == b'upgrade-v2-filter-legacy-handshake':
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   776
            # Client should have sent legacy handshake after an ``upgrade``
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   777
            # request. Expected lines:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   778
            #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   779
            #    hello
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   780
            #    between
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   781
            #    pairs 81
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   782
            #    0000...-0000...
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   783
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   784
            ok = True
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   785
            for line in (b'hello', b'between', b'pairs 81'):
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   786
                request = fin.readline()[:-1]
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   787
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   788
                if request != line:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   789
                    _sshv1respondooberror(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   790
                        fout,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   791
                        ui.ferr,
43117
8ff1ecfadcd1 cleanup: join string literals that are already on one line
Martin von Zweigbergk <martinvonz@google.com>
parents: 43077
diff changeset
   792
                        b'malformed handshake protocol: missing %s' % line,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   793
                    )
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   794
                    ok = False
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   795
                    state = b'shutdown'
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   796
                    break
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   797
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   798
            if not ok:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   799
                continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   800
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   801
            request = fin.read(81)
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   802
            if request != b'%s-%s' % (b'0' * 40, b'0' * 40):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   803
                _sshv1respondooberror(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   804
                    fout,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   805
                    ui.ferr,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   806
                    b'malformed handshake protocol: '
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   807
                    b'missing between argument value',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   808
                )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   809
                state = b'shutdown'
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   810
                continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   811
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   812
            state = b'upgrade-v2-finish'
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   813
            continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   814
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   815
        elif state == b'upgrade-v2-finish':
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   816
            # Send the upgrade response.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   817
            fout.write(b'upgraded %s %s\n' % (token, SSHV2))
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
   818
            servercaps = wireprotov1server.capabilities(repo, proto)
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   819
            rsp = b'capabilities: %s' % servercaps.data
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   820
            fout.write(b'%d\n%s\n' % (len(rsp), rsp))
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   821
            fout.flush()
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   822
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   823
            proto = sshv2protocolhandler(ui, fin, fout)
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   824
            protoswitched = True
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   825
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   826
            state = b'protov2-serving'
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   827
            continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
   828
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   829
        elif state == b'shutdown':
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   830
            break
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   831
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   832
        else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   833
            raise error.ProgrammingError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   834
                b'unhandled ssh server state: %s' % state
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   835
            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   836
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
   837
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
   838
class sshserver(object):
36526
7cc4a9b9732a wireprotoserver: support logging SSH server I/O to a file descriptor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36523
diff changeset
   839
    def __init__(self, ui, repo, logfh=None):
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
   840
        self._ui = ui
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
   841
        self._repo = repo
41285
cf8677cd7286 ui: proxy protect/restorestdio() calls to update internal flag
Yuya Nishihara <yuya@tcha.org>
parents: 40074
diff changeset
   842
        self._fin, self._fout = ui.protectfinout()
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
   843
36526
7cc4a9b9732a wireprotoserver: support logging SSH server I/O to a file descriptor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36523
diff changeset
   844
        # Log write I/O to stdout and stderr if configured.
7cc4a9b9732a wireprotoserver: support logging SSH server I/O to a file descriptor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36523
diff changeset
   845
        if logfh:
7cc4a9b9732a wireprotoserver: support logging SSH server I/O to a file descriptor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36523
diff changeset
   846
            self._fout = util.makeloggingfileobject(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   847
                logfh, self._fout, b'o', logdata=True
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   848
            )
36526
7cc4a9b9732a wireprotoserver: support logging SSH server I/O to a file descriptor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36523
diff changeset
   849
            ui.ferr = util.makeloggingfileobject(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   850
                logfh, ui.ferr, b'e', logdata=True
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42896
diff changeset
   851
            )
36526
7cc4a9b9732a wireprotoserver: support logging SSH server I/O to a file descriptor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36523
diff changeset
   852
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
   853
    def serve_forever(self):
36523
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   854
        self.serveuntil(threading.Event())
41285
cf8677cd7286 ui: proxy protect/restorestdio() calls to update internal flag
Yuya Nishihara <yuya@tcha.org>
parents: 40074
diff changeset
   855
        self._ui.restorefinout(self._fin, self._fout)
36523
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   856
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   857
    def serveuntil(self, ev):
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   858
        """Serve until a threading.Event is set."""
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   859
        _runsshserver(self._ui, self._repo, self._fin, self._fout, ev)