annotate mercurial/wireprotoserver.py @ 39641:aa7e312375cf

wireprotov2: let clients drive delta behavior Previously, the "manifestdata" and "filedata" commands assumed the receiver had all parent revisions for requested nodes. Unless the revision had no parents, they emitted a delta instead of a fulltext. This strategy isn't appropriate for shallow clones and for clients that only want to access fulltext revision data for a single node without fetching their parent revisions. This commit adds an "haveparents" argument to the "manifestdata" and "filedata" commands that controls delta generation behavior. Unless "haveparents" is set, the server assumes that the client doesn't have parent revisions unless they were previously sent as part of the current group of revisions. This change allows the fulltext revision data of any individual revision to be obtained. This will facilitate shallow clones and other data retrieval strategies that don't require all previous revisions of an entity to be fetched. Differential Revision: https://phab.mercurial-scm.org/D4492
author Gregory Szorc <gregory.szorc@gmail.com>
date Thu, 30 Aug 2018 14:55:34 -0700
parents 5f4a9ada5ab5
children a9f56e4501c1
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
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>
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
2 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
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
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
11 import sys
36523
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
12 import threading
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 20903
diff changeset
13
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
14 from .i18n import _
35856
ef3a24a023ec wireprotoserver: rename hgweb.protocol to wireprotoserver (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35750
diff changeset
15 from . import (
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
16 encoding,
34509
e21f274cccea hgweb: in protocol adapter, avoid control reaching end of non-void function
Augie Fackler <augie@google.com>
parents: 33821
diff changeset
17 error,
34742
5a9cad0dfddb hgweb: when unpacking args from request form, convert to bytes
Augie Fackler <augie@google.com>
parents: 34740
diff changeset
18 pycompat,
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 20903
diff changeset
19 util,
36073
cd6ab329c5c7 wireprototypes: move wire protocol response types to new module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36072
diff changeset
20 wireprototypes,
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
21 wireprotov1server,
37545
93397c4633f6 wireproto: extract HTTP version 2 code to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37535
diff changeset
22 wireprotov2server,
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 20903
diff changeset
23 )
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,
37810
856f381ad74b interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37785
diff changeset
26 interfaceutil,
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37061
diff changeset
27 procutil,
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
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
37 HGTYPE = 'application/mercurial-0.1'
30764
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
38 HGTYPE2 = 'application/mercurial-0.2'
15017
f4522df38c65 wireproto: add out-of-band error class to allow remote repo to report errors
Andrew Pritchard <andrewp@fogcreek.com>
parents: 14614
diff changeset
39 HGERRTYPE = '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
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
44 def decodevaluefromheaders(req, headerprefix):
34744
0a2ef612ad50 hgweb: fix decodevaluefromheaders to always return a bytes value
Augie Fackler <augie@google.com>
parents: 34743
diff changeset
45 """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
46
0a2ef612ad50 hgweb: fix decodevaluefromheaders to always return a bytes value
Augie Fackler <augie@google.com>
parents: 34743
diff changeset
47 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
48 """
30759
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
49 chunks = []
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
50 i = 1
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
51 while True:
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
52 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
53 if v is None:
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
54 break
34744
0a2ef612ad50 hgweb: fix decodevaluefromheaders to always return a bytes value
Augie Fackler <augie@google.com>
parents: 34743
diff changeset
55 chunks.append(pycompat.bytesurl(v))
30759
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
56 i += 1
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
57
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
58 return ''.join(chunks)
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
59
37810
856f381ad74b interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37785
diff changeset
60 @interfaceutil.implementer(wireprototypes.baseprotocolhandler)
37296
78103e4138b1 wireproto: port protocol handler to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37295
diff changeset
61 class httpv1protocolhandler(object):
36867
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
62 def __init__(self, req, ui, checkperm):
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
63 self._req = req
35866
d747cf39cf70 wireprotoserver: make attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35865
diff changeset
64 self._ui = ui
36801
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
65 self._checkperm = checkperm
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
66 self._protocaps = None
35873
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
67
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
68 @property
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
69 def name(self):
36223
2e07dc514073 wireprotoserver: add version to HTTP protocol name (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36222
diff changeset
70 return 'http-v1'
30562
b3a9ef3d30e8 protocol: declare transport protocol name
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30466
diff changeset
71
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
72 def getargs(self, args):
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
73 knownargs = self._args()
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
74 data = {}
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
75 keys = args.split()
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
76 for k in keys:
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
77 if k == '*':
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
78 star = {}
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
79 for key in knownargs.keys():
13721
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 12704
diff changeset
80 if key != 'cmd' and key not in keys:
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
81 star[key] = knownargs[key][0]
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
82 data['*'] = star
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
83 else:
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
84 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
85 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
86
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
87 def _args(self):
36862
ec0af9c59270 hgweb: use a multidict for holding query string parameters
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36861
diff changeset
88 args = self._req.qsparams.asdictoflists()
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
89 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
90 if postlen:
36077
a3d42d1865f1 wireprotoserver: define and use parse_qs from urllib
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36075
diff changeset
91 args.update(urlreq.parseqs(
36857
da4e2f87167d hgweb: expose input stream on parsed WSGI request object
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36855
diff changeset
92 self._req.bodyfh.read(postlen), keep_blank_values=True))
28530
fd2acc5046f6 http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents: 27046
diff changeset
93 return args
30759
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
94
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
95 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
96 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
97 return args
35863
49426bb4476c wireprotoserver: add some blank lines between methods
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35860
diff changeset
98
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
99 def getprotocaps(self):
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
100 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
101 value = decodevaluefromheaders(self._req, b'X-HgProto')
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
102 self._protocaps = set(value.split(' '))
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
103 return self._protocaps
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
104
37414
2d965bfeb8f6 wireproto: allow direct stream processing for unbundle
Joerg Sonnenberger <joerg@bec.de>
parents: 37393
diff changeset
105 def getpayload(self):
36847
ed0456fde625 hgweb: handle CONTENT_LENGTH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36846
diff changeset
106 # Existing clients *always* send Content-Length.
ed0456fde625 hgweb: handle CONTENT_LENGTH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36846
diff changeset
107 length = int(self._req.headers[b'Content-Length'])
ed0456fde625 hgweb: handle CONTENT_LENGTH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36846
diff changeset
108
33821
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33228
diff changeset
109 # 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
110 # 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
111 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
112 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
113
36066
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
114 @contextlib.contextmanager
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
115 def mayberedirectstdio(self):
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
116 oldout = self._ui.fout
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
117 olderr = self._ui.ferr
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
118
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
119 out = util.stringio()
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
120
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
121 try:
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
122 self._ui.fout = out
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
123 self._ui.ferr = out
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
124 yield out
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
125 finally:
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
126 self._ui.fout = oldout
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
127 self._ui.ferr = olderr
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
128
36069
957e773614d0 wireprotoserver: rename _client to client (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36068
diff changeset
129 def client(self):
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
130 return 'remote:%s:%s:%s' % (
36867
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
131 self._req.urlscheme,
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
132 urlreq.quote(self._req.remotehost or ''),
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
133 urlreq.quote(self._req.remoteuser or ''))
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
134
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
135 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
136 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
137
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
138 caps.append('httpheader=%d' %
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
139 repo.ui.configint('server', 'maxhttpheaderlen'))
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
140 if repo.ui.configbool('experimental', 'httppostargs'):
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
141 caps.append('httppostargs')
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
142
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
143 # 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
144 # FUTURE advertise minrx and mintx after consulting config option
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
145 caps.append('httpmediatype=0.1rx,0.1tx,0.2tx')
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
146
37783
9d818539abfa wireproto: move supportedcompengines out of wireproto
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37644
diff changeset
147 compengines = wireprototypes.supportedcompengines(repo.ui,
9d818539abfa wireproto: move supportedcompengines out of wireproto
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37644
diff changeset
148 util.SERVERROLE)
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
149 if compengines:
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
150 comptypes = ','.join(urlreq.quote(e.wireprotosupport().name)
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
151 for e in compengines)
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
152 caps.append('compression=%s' % comptypes)
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
153
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
154 return caps
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
155
36801
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
156 def checkperm(self, perm):
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
157 return self._checkperm(perm)
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
158
36231
72812ad205d1 wireprotoserver: return to using iscmd() method
Augie Fackler <augie@google.com>
parents: 36223
diff changeset
159 # 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
160 # 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
161 # 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
162 # 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
163 def iscmd(cmd):
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
164 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
165
36877
02bea04b4c54 hgweb: transition permissions hooks to modern request type (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36867
diff changeset
166 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
167 """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
168
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
169 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
170 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
171
36810
886fba199022 hgweb: only recognize wire protocol commands from query string (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36804
diff changeset
172 ``req`` is a ``parsedrequest`` instance.
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
173 ``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
174
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
175 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
176 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
177 """
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
178 # 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
179 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
180
36801
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
181 repo = rctx.repo
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
182
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
183 # 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
184 # 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
185 # request.
36862
ec0af9c59270 hgweb: use a multidict for holding query string parameters
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36861
diff changeset
186 if 'cmd' not in req.qsparams:
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
187 return False
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
188
36862
ec0af9c59270 hgweb: use a multidict for holding query string parameters
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36861
diff changeset
189 cmd = req.qsparams['cmd']
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
190
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
191 # 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
192 # 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
193 # 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
194 # 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
195 # 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
196 # 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
197 # clients.
36231
72812ad205d1 wireprotoserver: return to using iscmd() method
Augie Fackler <augie@google.com>
parents: 36223
diff changeset
198 if not iscmd(cmd):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
199 return False
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
200
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
201 # 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
202 # 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
203 # 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
204 # 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
205 if req.dispatchpath:
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
206 res.status = hgwebcommon.statusmessage(404)
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
207 res.headers['Content-Type'] = HGTYPE
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
208 # 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
209 # is mostly for BC for now.
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
210 res.setbodybytes('0\n%s\n' % b'Not Found')
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
211 return True
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
212
36867
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
213 proto = httpv1protocolhandler(req, repo.ui,
36877
02bea04b4c54 hgweb: transition permissions hooks to modern request type (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36867
diff changeset
214 lambda perm: checkperm(rctx, req, perm))
30764
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
215
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
216 # 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
217 # 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
218 # 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
219 # 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
220 try:
36867
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
221 _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
222 except hgwebcommon.ErrorResponse as e:
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
223 for k, v in e.headers:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
224 res.headers[k] = v
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
225 res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
226 # 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
227 # "unbundle." That assumption is not always valid.
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
228 res.setbodybytes('0\n%s\n' % pycompat.bytestr(e))
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
229
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
230 return True
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
231
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
232 def _availableapis(repo):
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
233 apis = set()
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
234
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
235 # 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
236 # the protocol.
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
237 for k, v in API_HANDLERS.items():
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
238 section, option = v['config']
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
239 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
240 apis.add(k)
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
241
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
242 return apis
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
243
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
244 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
245 """Handle requests to /api/*."""
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
246 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
247
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
248 repo = rctx.repo
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
249
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
250 # 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
251 # reserve the URL space. So, 404 all URLs if the feature isn't enabled.
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
252 if not repo.ui.configbool('experimental', 'web.apiserver'):
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
253 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
254 res.headers[b'Content-Type'] = b'text/plain'
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
255 res.setbodybytes(_('Experimental API server endpoint not enabled'))
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
256 return
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
257
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
258 # 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
259 # by <protocol>.
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
260
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
261 availableapis = _availableapis(repo)
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
262
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
263 # 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
264 if req.dispatchparts == [b'api']:
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
265 res.status = b'200 OK'
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
266 res.headers[b'Content-Type'] = b'text/plain'
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
267 lines = [_('APIs can be accessed at /api/<name>, where <name> can be '
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
268 'one of the following:\n')]
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
269 if availableapis:
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
270 lines.extend(sorted(availableapis))
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
271 else:
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
272 lines.append(_('(no available APIs)\n'))
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
273 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
274 return
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
275
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
276 proto = req.dispatchparts[1]
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
277
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
278 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
279 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
280 res.headers[b'Content-Type'] = b'text/plain'
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
281 res.setbodybytes(_('Unknown API: %s\nKnown APIs: %s') % (
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
282 proto, b', '.join(sorted(availableapis))))
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
283 return
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
284
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
285 if proto not in availableapis:
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
286 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
287 res.headers[b'Content-Type'] = b'text/plain'
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
288 res.setbodybytes(_('API %s not enabled\n') % proto)
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
289 return
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
290
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
291 API_HANDLERS[proto]['handler'](rctx, req, res, checkperm,
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
292 req.dispatchparts[2:])
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
293
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
294 # 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
295 # Keys are:
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
296 #
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
297 # config
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
298 # 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
299 # handler
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
300 # 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
301 # 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
302 # apidescriptor
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
303 # 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
304 # 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
305 API_HANDLERS = {
37644
77c9ee77687c wireproto: rename HTTPV2 so it less like HTTP/2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37590
diff changeset
306 wireprotov2server.HTTP_WIREPROTO_V2: {
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
307 'config': ('experimental', 'web.api.http-v2'),
37545
93397c4633f6 wireproto: extract HTTP version 2 code to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37535
diff changeset
308 'handler': wireprotov2server.handlehttpv2request,
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
309 'apidescriptor': wireprotov2server.httpv2apidescriptor,
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
310 },
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
311 }
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
312
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
313 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
314 """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
315
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
316 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
317 """
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
318 # 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
319 # on the request parameters.
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
320
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
321 if '0.2' in proto.getprotocaps():
36072
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
322 # 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
323 if prefer_uncompressed:
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
324 return HGTYPE2, util._noopengine(), {}
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
325
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
326 # 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
327 compformats = wireprotov1server.clientcompressionsupport(proto)
37783
9d818539abfa wireproto: move supportedcompengines out of wireproto
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37644
diff changeset
328 for engine in wireprototypes.supportedcompengines(ui, util.SERVERROLE):
36072
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
329 if engine.wireprotosupport().name in compformats:
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
330 opts = {}
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
331 level = ui.configint('server', '%slevel' % engine.name())
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
332 if level is not None:
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
333 opts['level'] = level
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
334
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
335 return HGTYPE2, engine, opts
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
336
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
337 # 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
338 # legacy protocol.
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
339
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
340 # 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
341 # 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
342 # the server's network or CPU.
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
343 opts = {'level': ui.configint('server', 'zliblevel')}
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
344 return HGTYPE, util.compengines['zlib'], opts
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
345
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
346 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
347 """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
348
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
349 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
350 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
351 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
352 """
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
353 # Fall back to old behavior unless the API server is enabled.
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
354 if not repo.ui.configbool('experimental', 'web.apiserver'):
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
355 return False
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
356
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
357 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
358 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
359 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
360 return False
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
361
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
362 # We currently only support CBOR responses.
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
363 protocaps = set(protocaps.split(' '))
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
364 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
365 return False
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
366
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
367 descriptors = {}
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
368
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
369 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
370 handler = API_HANDLERS[api]
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
371
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
372 descriptorfn = handler.get('apidescriptor')
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
373 if not descriptorfn:
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
374 continue
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
375
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
376 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
377
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
378 v1caps = wireprotov1server.dispatch(repo, proto, 'capabilities')
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
379 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
380
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
381 m = {
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
382 # TODO allow this to be configurable.
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
383 'apibase': 'api/',
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
384 'apis': descriptors,
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
385 'v1capabilities': v1caps.data,
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
386 }
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
387
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
388 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
389 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
390 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
391
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
392 return True
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
393
36867
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
394 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
395 # Avoid cycle involving hg module.
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
396 from .hgweb import common as hgwebcommon
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
397
35750
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
398 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
399 # 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
400 # 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
401 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
402 assert 0 < len(name) < 256
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
403 yield struct.pack('B', len(name))
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
404 yield name
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
405
35750
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
406 for chunk in gen:
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
407 yield chunk
30764
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
408
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
409 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
410 if code == HTTP_OK:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
411 res.status = '200 Script output follows'
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
412 else:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
413 res.status = hgwebcommon.statusmessage(code)
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
414
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
415 res.headers['Content-Type'] = contenttype
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
416
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
417 if bodybytes is not None:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
418 res.setbodybytes(bodybytes)
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
419 if bodygen is not None:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
420 res.setbodygen(bodygen)
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
421
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
422 if not wireprotov1server.commands.commandavailable(cmd, proto):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
423 setresponse(HTTP_OK, HGERRTYPE,
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
424 _('requested wire protocol command is not available over '
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
425 'HTTP'))
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
426 return
35982
5a56bf4180ad wireproto: function for testing if wire protocol command is available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35976
diff changeset
427
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
428 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
429
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
430 # Possibly handle a modern client wanting to switch protocols.
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
431 if (cmd == 'capabilities' and
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
432 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
433
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
434 return
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
435
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
436 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
437
34510
c23fa3103925 hgweb: in protocol adapter, look for bytes instances, not str
Augie Fackler <augie@google.com>
parents: 34509
diff changeset
438 if isinstance(rsp, bytes):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
439 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
440 elif isinstance(rsp, wireprototypes.bytesresponse):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
441 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
442 elif isinstance(rsp, wireprototypes.streamreslegacy):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
443 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
444 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
445 gen = rsp.gen
30466
2add671bf55b wireproto: perform chunking and compression at protocol layer (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30366
diff changeset
446
30764
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
447 # 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
448 # 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
449 mediatype, engine, engineopts = _httpresponsetype(
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
450 repo.ui, proto, rsp.prefer_uncompressed)
35750
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
451 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
452
35750
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
453 if mediatype == HGTYPE2:
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
454 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
455
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
456 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
457 elif isinstance(rsp, wireprototypes.pushres):
36067
caca3ac2ac04 wireproto: use maybecapturestdio() for push responses (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36066
diff changeset
458 rsp = '%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
459 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
460 elif isinstance(rsp, wireprototypes.pusherr):
12703
40bb5853fc4b wireproto: introduce pusherr() to deal with "unsynced changes" error
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 11626
diff changeset
461 rsp = '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
462 res.drain = True
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
463 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
464 elif isinstance(rsp, wireprototypes.ooberror):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
465 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
466 else:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
467 raise error.ProgrammingError('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
468
36064
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
469 def _sshv1respondbytes(fout, value):
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
470 """Send a bytes response for protocol version 1."""
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
471 fout.write('%d\n' % len(value))
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
472 fout.write(value)
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
473 fout.flush()
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
474
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
475 def _sshv1respondstream(fout, source):
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
476 write = fout.write
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
477 for chunk in source.gen:
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
478 write(chunk)
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
479 fout.flush()
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
480
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
481 def _sshv1respondooberror(fout, ferr, rsp):
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
482 ferr.write(b'%s\n-\n' % rsp)
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
483 ferr.flush()
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
484 fout.write(b'\n')
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
485 fout.flush()
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
486
37810
856f381ad74b interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37785
diff changeset
487 @interfaceutil.implementer(wireprototypes.baseprotocolhandler)
37296
78103e4138b1 wireproto: port protocol handler to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37295
diff changeset
488 class sshv1protocolhandler(object):
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
489 """Handler for requests services via version 1 of SSH protocol."""
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
490 def __init__(self, ui, fin, fout):
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
491 self._ui = ui
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
492 self._fin = fin
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
493 self._fout = fout
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
494 self._protocaps = set()
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
495
35873
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
496 @property
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
497 def name(self):
36536
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36526
diff changeset
498 return wireprototypes.SSHV1
35873
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
499
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
500 def getargs(self, args):
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
501 data = {}
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
502 keys = args.split()
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37945
diff changeset
503 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
504 argline = self._fin.readline()[:-1]
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
505 arg, l = argline.split()
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
506 if arg not in keys:
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
507 raise error.Abort(_("unexpected parameter %r") % arg)
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
508 if arg == '*':
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
509 star = {}
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37945
diff changeset
510 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
511 argline = self._fin.readline()[:-1]
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
512 arg, l = argline.split()
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
513 val = self._fin.read(int(l))
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
514 star[arg] = val
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
515 data['*'] = star
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
516 else:
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
517 val = self._fin.read(int(l))
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
518 data[arg] = val
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
519 return [data[k] for k in keys]
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
520
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
521 def getprotocaps(self):
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
522 return self._protocaps
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
523
37414
2d965bfeb8f6 wireproto: allow direct stream processing for unbundle
Joerg Sonnenberger <joerg@bec.de>
parents: 37393
diff changeset
524 def getpayload(self):
36372
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36371
diff changeset
525 # 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
526 # 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
527 # interprets it as an error.
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36371
diff changeset
528 _sshv1respondbytes(self._fout, b'')
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36371
diff changeset
529
36070
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
530 # The file is in the form:
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
531 #
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
532 # <chunk size>\n<chunk>
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
533 # ...
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
534 # 0\n
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
535 count = int(self._fin.readline())
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
536 while count:
37414
2d965bfeb8f6 wireproto: allow direct stream processing for unbundle
Joerg Sonnenberger <joerg@bec.de>
parents: 37393
diff changeset
537 yield self._fin.read(count)
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
538 count = int(self._fin.readline())
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
539
36066
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
540 @contextlib.contextmanager
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
541 def mayberedirectstdio(self):
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
542 yield None
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
543
36069
957e773614d0 wireprotoserver: rename _client to client (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36068
diff changeset
544 def client(self):
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
545 client = encoding.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
546 return 'remote:ssh:' + client
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
547
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
548 def addcapabilities(self, repo, caps):
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
549 if self.name == wireprototypes.SSHV1:
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
550 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
551 caps.append(b'batch')
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
552 return caps
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
553
36801
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
554 def checkperm(self, perm):
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
555 pass
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
556
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
557 class sshv2protocolhandler(sshv1protocolhandler):
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
558 """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
559
36610
af0d38f015bb wireprotoserver: identify requests via version 2 of SSH protocol as such
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36536
diff changeset
560 @property
af0d38f015bb wireprotoserver: identify requests via version 2 of SSH protocol as such
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36536
diff changeset
561 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
562 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
563
37533
df4985497986 wireproto: implement capabilities for wire protocol v2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37485
diff changeset
564 def addcapabilities(self, repo, caps):
df4985497986 wireproto: implement capabilities for wire protocol v2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37485
diff changeset
565 return caps
df4985497986 wireproto: implement capabilities for wire protocol v2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37485
diff changeset
566
36523
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
567 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
568 # 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
569 # states are defined:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
570 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
571 # protov1-serving
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
572 # 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
573 # 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
574 # after the other.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
575 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
576 # protov2-serving
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
577 # 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
578 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
579 # upgrade-initial
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
580 # 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
581 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
582 # upgrade-v2-filter-legacy-handshake
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
583 # 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
584 # 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
585 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
586 # upgrade-v2-finish
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
587 # 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
588 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
589 # shutdown
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
590 # 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
591 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
592 # And here are their transitions:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
593 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
594 # protov1-serving -> shutdown
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
595 # 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
596 # error.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
597 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
598 # protov1-serving -> upgrade-initial
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
599 # 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
600 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
601 # 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
602 # 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
603 # process a legacy handshake.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
604 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
605 # 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
606 # 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
607 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
608 # 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
609 # 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
610 # upgrade.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
611 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
612 # upgrade-v2-finish -> protov2-serving
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
613 # 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
614 # version 2.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
615 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
616 # protov2-serving -> protov1-serving
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
617 # 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
618 # 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
619
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
620 state = 'protov1-serving'
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
621 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
622 protoswitched = False
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
623
36523
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
624 while not ev.is_set():
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
625 if state == 'protov1-serving':
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
626 # 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
627 request = fin.readline()[:-1]
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
628
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
629 # 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
630 if not request:
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
631 state = 'shutdown'
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
632 continue
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
633
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
634 # 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
635 # handle it.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
636 if request.startswith(b'upgrade '):
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
637 if protoswitched:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
638 _sshv1respondooberror(fout, ui.ferr,
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
639 b'cannot upgrade protocols multiple '
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
640 b'times')
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
641 state = 'shutdown'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
642 continue
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 state = 'upgrade-initial'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
645 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
646
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
647 available = wireprotov1server.commands.commandavailable(
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
648 request, proto)
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
649
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
650 # 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
651 # 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
652 if not available:
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
653 _sshv1respondbytes(fout, b'')
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
654 continue
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
655
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
656 rsp = wireprotov1server.dispatch(repo, proto, request)
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
657
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
658 if isinstance(rsp, bytes):
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
659 _sshv1respondbytes(fout, rsp)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
660 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
661 _sshv1respondbytes(fout, rsp.data)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
662 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
663 _sshv1respondstream(fout, rsp)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
664 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
665 _sshv1respondstream(fout, rsp)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
666 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
667 _sshv1respondbytes(fout, b'')
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
668 _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
669 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
670 _sshv1respondbytes(fout, rsp.res)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
671 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
672 _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
673 else:
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
674 raise error.ProgrammingError('unhandled response type from '
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
675 'wire protocol command: %s' % rsp)
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 # For now, protocol version 2 serving just goes back to version 1.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
678 elif state == 'protov2-serving':
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
679 state = 'protov1-serving'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
680 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
681
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
682 elif state == 'upgrade-initial':
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
683 # 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
684 # protocols.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
685 assert not protoswitched
36536
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36526
diff changeset
686 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
687
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
688 # Expected: upgrade <token> <capabilities>
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
689 # 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
690 # 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
691 # 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
692 try:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
693 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
694 except ValueError:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
695 _sshv1respondbytes(fout, b'')
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
696 state = 'protov1-serving'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
697 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
698
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
699 # Send empty response if we don't support upgrading protocols.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
700 if not ui.configbool('experimental', 'sshserver.support-v2'):
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
701 _sshv1respondbytes(fout, b'')
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
702 state = 'protov1-serving'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
703 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
704
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
705 try:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
706 caps = urlreq.parseqs(caps)
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
707 except ValueError:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
708 _sshv1respondbytes(fout, b'')
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
709 state = 'protov1-serving'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
710 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
711
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
712 # 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
713 # the upgrade request.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
714 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
715 if SSHV2 not in wantedprotos:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
716 _sshv1respondbytes(fout, b'')
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
717 state = 'protov1-serving'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
718 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
719
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
720 # 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
721 # Filter the rest of the handshake protocol request lines.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
722 state = 'upgrade-v2-filter-legacy-handshake'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
723 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
724
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
725 elif state == 'upgrade-v2-filter-legacy-handshake':
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
726 # 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
727 # request. Expected lines:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
728 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
729 # hello
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
730 # between
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
731 # pairs 81
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
732 # 0000...-0000...
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
733
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
734 ok = True
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
735 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
736 request = fin.readline()[:-1]
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 if request != line:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
739 _sshv1respondooberror(fout, ui.ferr,
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
740 b'malformed handshake protocol: '
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
741 b'missing %s' % line)
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
742 ok = False
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
743 state = 'shutdown'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
744 break
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
745
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
746 if not ok:
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 request = fin.read(81)
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
750 if request != b'%s-%s' % (b'0' * 40, b'0' * 40):
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
751 _sshv1respondooberror(fout, ui.ferr,
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
752 b'malformed handshake protocol: '
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
753 b'missing between argument value')
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
754 state = 'shutdown'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
755 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
756
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
757 state = 'upgrade-v2-finish'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
758 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
759
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
760 elif state == 'upgrade-v2-finish':
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
761 # Send the upgrade response.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
762 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
763 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
764 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
765 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
766 fout.flush()
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
767
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
768 proto = sshv2protocolhandler(ui, fin, fout)
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
769 protoswitched = True
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
770
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
771 state = 'protov2-serving'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
772 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
773
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
774 elif state == 'shutdown':
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
775 break
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
776
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
777 else:
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
778 raise error.ProgrammingError('unhandled ssh server state: %s' %
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
779 state)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
780
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
781 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
782 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
783 self._ui = ui
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
784 self._repo = repo
37945
bfe8ef6e370e sshserver: redirect stdin/stdout early and use duplicated streams
Yuya Nishihara <yuya@tcha.org>
parents: 37944
diff changeset
785 self._fin, self._fout = procutil.protectstdio(ui.fin, ui.fout)
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
786
36526
7cc4a9b9732a wireprotoserver: support logging SSH server I/O to a file descriptor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36523
diff changeset
787 # 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
788 if logfh:
7cc4a9b9732a wireprotoserver: support logging SSH server I/O to a file descriptor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36523
diff changeset
789 self._fout = util.makeloggingfileobject(
7cc4a9b9732a wireprotoserver: support logging SSH server I/O to a file descriptor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36523
diff changeset
790 logfh, self._fout, 'o', logdata=True)
7cc4a9b9732a wireprotoserver: support logging SSH server I/O to a file descriptor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36523
diff changeset
791 ui.ferr = util.makeloggingfileobject(
7cc4a9b9732a wireprotoserver: support logging SSH server I/O to a file descriptor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36523
diff changeset
792 logfh, ui.ferr, 'e', logdata=True)
7cc4a9b9732a wireprotoserver: support logging SSH server I/O to a file descriptor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36523
diff changeset
793
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
794 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
795 self.serveuntil(threading.Event())
37945
bfe8ef6e370e sshserver: redirect stdin/stdout early and use duplicated streams
Yuya Nishihara <yuya@tcha.org>
parents: 37944
diff changeset
796 procutil.restorestdio(self._ui.fin, self._ui.fout,
bfe8ef6e370e sshserver: redirect stdin/stdout early and use duplicated streams
Yuya Nishihara <yuya@tcha.org>
parents: 37944
diff changeset
797 self._fin, self._fout)
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
798 sys.exit(0)
36523
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
799
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
800 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
801 """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
802 _runsshserver(self._ui, self._repo, self._fin, self._fout, ev)