annotate mercurial/wireprotoserver.py @ 37061:884a0c1604ad

wireproto: define attr-based classes for representing frames When frames only had 3 attributes, it was reasonable to represent them as a tuple. With them growing more attributes, it will be easier to pass them around as a more formal type. So let's define attr-based classes to represent frame headers and full frames. Differential Revision: https://phab.mercurial-scm.org/D2899
author Gregory Szorc <gregory.szorc@gmail.com>
date Thu, 15 Mar 2018 16:03:14 -0700
parents bbea991635d0
children a8a902d7176e
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,
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
18 hook,
34742
5a9cad0dfddb hgweb: when unpacking args from request form, convert to bytes
Augie Fackler <augie@google.com>
parents: 34740
diff changeset
19 pycompat,
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 20903
diff changeset
20 util,
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 20903
diff changeset
21 wireproto,
37052
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
22 wireprotoframing,
36073
cd6ab329c5c7 wireprototypes: move wire protocol response types to new module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36072
diff changeset
23 wireprototypes,
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 20903
diff changeset
24 )
35856
ef3a24a023ec wireprotoserver: rename hgweb.protocol to wireprotoserver (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35750
diff changeset
25
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28530
diff changeset
26 stringio = util.stringio
5963
5be210afe1b8 hgweb: explicitly check if requested command exists
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5915
diff changeset
27
28883
032c4c2f802a pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents: 28861
diff changeset
28 urlerr = util.urlerr
032c4c2f802a pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents: 28861
diff changeset
29 urlreq = util.urlreq
032c4c2f802a pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents: 28861
diff changeset
30
35858
1b76a9e0a9de wireprotoserver: don't import symbol from hgweb.common
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35857
diff changeset
31 HTTP_OK = 200
1b76a9e0a9de wireprotoserver: don't import symbol from hgweb.common
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35857
diff changeset
32
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
33 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
34 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
35 HGERRTYPE = 'application/hg-error'
37057
2ec1fb9de638 wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
36 FRAMINGTYPE = b'application/mercurial-exp-framing-0002'
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
37
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
38 HTTPV2 = wireprototypes.HTTPV2
36536
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36526
diff changeset
39 SSHV1 = wireprototypes.SSHV1
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36526
diff changeset
40 SSHV2 = wireprototypes.SSHV2
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35900
diff changeset
41
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
42 def decodevaluefromheaders(req, headerprefix):
34744
0a2ef612ad50 hgweb: fix decodevaluefromheaders to always return a bytes value
Augie Fackler <augie@google.com>
parents: 34743
diff changeset
43 """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
44
0a2ef612ad50 hgweb: fix decodevaluefromheaders to always return a bytes value
Augie Fackler <augie@google.com>
parents: 34743
diff changeset
45 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
46 """
30759
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
47 chunks = []
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
48 i = 1
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
49 while True:
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
50 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
51 if v is None:
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
52 break
34744
0a2ef612ad50 hgweb: fix decodevaluefromheaders to always return a bytes value
Augie Fackler <augie@google.com>
parents: 34743
diff changeset
53 chunks.append(pycompat.bytesurl(v))
30759
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
54 i += 1
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
55
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
56 return ''.join(chunks)
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
57
36371
0c231df1ffdc wireprototypes: move baseprotocolhandler from wireprotoserver
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36280
diff changeset
58 class httpv1protocolhandler(wireprototypes.baseprotocolhandler):
36867
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
59 def __init__(self, req, ui, checkperm):
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
60 self._req = req
35866
d747cf39cf70 wireprotoserver: make attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35865
diff changeset
61 self._ui = ui
36801
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
62 self._checkperm = checkperm
35873
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
63
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
64 @property
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
65 def name(self):
36223
2e07dc514073 wireprotoserver: add version to HTTP protocol name (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36222
diff changeset
66 return 'http-v1'
30562
b3a9ef3d30e8 protocol: declare transport protocol name
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30466
diff changeset
67
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
68 def getargs(self, args):
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
69 knownargs = self._args()
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
70 data = {}
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
71 keys = args.split()
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
72 for k in keys:
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
73 if k == '*':
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
74 star = {}
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
75 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
76 if key != 'cmd' and key not in keys:
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
77 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
78 data['*'] = star
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
79 else:
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
80 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
81 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
82
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 13721
diff changeset
83 def _args(self):
36862
ec0af9c59270 hgweb: use a multidict for holding query string parameters
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36861
diff changeset
84 args = self._req.qsparams.asdictoflists()
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
85 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
86 if postlen:
36077
a3d42d1865f1 wireprotoserver: define and use parse_qs from urllib
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36075
diff changeset
87 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
88 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
89 return args
30759
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30562
diff changeset
90
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
91 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
92 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
93 return args
35863
49426bb4476c wireprotoserver: add some blank lines between methods
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35860
diff changeset
94
36070
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
95 def forwardpayload(self, fp):
36847
ed0456fde625 hgweb: handle CONTENT_LENGTH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36846
diff changeset
96 # Existing clients *always* send Content-Length.
ed0456fde625 hgweb: handle CONTENT_LENGTH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36846
diff changeset
97 length = int(self._req.headers[b'Content-Length'])
ed0456fde625 hgweb: handle CONTENT_LENGTH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36846
diff changeset
98
33821
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33228
diff changeset
99 # 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
100 # 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
101 length -= int(self._req.headers.get(b'X-HgArgs-Post', 0))
36857
da4e2f87167d hgweb: expose input stream on parsed WSGI request object
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36855
diff changeset
102 for s in util.filechunkiter(self._req.bodyfh, limit=length):
11621
e46a8b2331a6 protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 11618
diff changeset
103 fp.write(s)
35863
49426bb4476c wireprotoserver: add some blank lines between methods
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35860
diff changeset
104
36066
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
105 @contextlib.contextmanager
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
106 def mayberedirectstdio(self):
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
107 oldout = self._ui.fout
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
108 olderr = self._ui.ferr
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
109
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
110 out = util.stringio()
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
111
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
112 try:
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
113 self._ui.fout = out
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
114 self._ui.ferr = out
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
115 yield out
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
116 finally:
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
117 self._ui.fout = oldout
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
118 self._ui.ferr = olderr
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
119
36069
957e773614d0 wireprotoserver: rename _client to client (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36068
diff changeset
120 def client(self):
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
121 return 'remote:%s:%s:%s' % (
36867
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
122 self._req.urlscheme,
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
123 urlreq.quote(self._req.remotehost or ''),
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
124 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
125
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
126 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
127 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
128
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
129 caps.append('httpheader=%d' %
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
130 repo.ui.configint('server', 'maxhttpheaderlen'))
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
131 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
132 caps.append('httppostargs')
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
133
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
134 # 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
135 # 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
136 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
137
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
138 compengines = wireproto.supportedcompengines(repo.ui, util.SERVERROLE)
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
139 if compengines:
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
140 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
141 for e in compengines)
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
142 caps.append('compression=%s' % comptypes)
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
143
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
144 return caps
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
145
36801
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
146 def checkperm(self, perm):
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
147 return self._checkperm(perm)
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
148
36231
72812ad205d1 wireprotoserver: return to using iscmd() method
Augie Fackler <augie@google.com>
parents: 36223
diff changeset
149 # 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
150 # 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
151 # 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
152 # 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
153 def iscmd(cmd):
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
154 return cmd in wireproto.commands
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
155
36877
02bea04b4c54 hgweb: transition permissions hooks to modern request type (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36867
diff changeset
156 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
157 """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
158
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
159 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
160 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
161
36810
886fba199022 hgweb: only recognize wire protocol commands from query string (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36804
diff changeset
162 ``req`` is a ``parsedrequest`` instance.
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
163 ``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
164
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
165 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
166 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
167 """
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
168 # 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
169 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
170
36801
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
171 repo = rctx.repo
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
172
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
173 # 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
174 # 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
175 # request.
36862
ec0af9c59270 hgweb: use a multidict for holding query string parameters
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36861
diff changeset
176 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
177 return False
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
178
36862
ec0af9c59270 hgweb: use a multidict for holding query string parameters
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36861
diff changeset
179 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
180
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
181 # 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
182 # 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
183 # 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
184 # 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
185 # 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
186 # 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
187 # clients.
36231
72812ad205d1 wireprotoserver: return to using iscmd() method
Augie Fackler <augie@google.com>
parents: 36223
diff changeset
188 if not iscmd(cmd):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
189 return False
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
190
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
191 # 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
192 # 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
193 # 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
194 # 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
195 if req.dispatchpath:
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
196 res.status = hgwebcommon.statusmessage(404)
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
197 res.headers['Content-Type'] = HGTYPE
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
198 # 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
199 # is mostly for BC for now.
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
200 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
201 return True
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
202
36867
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
203 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
204 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
205
36812
158d4ecc03c8 wireprotoserver: move all wire protocol handling logic out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36810
diff changeset
206 # 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
207 # 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
208 # 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
209 # 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
210 try:
36867
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
211 _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
212 except hgwebcommon.ErrorResponse as e:
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
213 for k, v in e.headers:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
214 res.headers[k] = v
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
215 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
216 # 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
217 # "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
218 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
219
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
220 return True
35984
cdc93fe1da77 wireprotoserver: move protocol parsing and dispatch out of hgweb
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35982
diff changeset
221
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
222 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
223 """Handle requests to /api/*."""
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
224 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
225
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
226 repo = rctx.repo
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
227
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
228 # 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
229 # 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
230 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
231 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
232 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
233 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
234 return
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
235
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
236 # 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
237 # by <protocol>.
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
238
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
239 # Registered APIs are made available via config options of the name of
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
240 # the protocol.
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
241 availableapis = set()
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
242 for k, v in API_HANDLERS.items():
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
243 section, option = v['config']
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
244 if repo.ui.configbool(section, option):
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
245 availableapis.add(k)
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
246
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
247 # 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
248 if req.dispatchparts == [b'api']:
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
249 res.status = b'200 OK'
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
250 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
251 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
252 'one of the following:\n')]
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
253 if availableapis:
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
254 lines.extend(sorted(availableapis))
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
255 else:
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
256 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
257 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
258 return
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
259
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
260 proto = req.dispatchparts[1]
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
261
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
262 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
263 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
264 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
265 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
266 proto, b', '.join(sorted(availableapis))))
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
267 return
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
268
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
269 if proto not in availableapis:
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
270 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
271 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
272 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
273 return
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
274
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
275 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
276 req.dispatchparts[2:])
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 def _handlehttpv2request(rctx, req, res, checkperm, urlparts):
37047
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
279 from .hgweb import common as hgwebcommon
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
280
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
281 # URL space looks like: <permissions>/<command>, where <permission> can
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
282 # be ``ro`` or ``rw`` to signal read-only or read-write, respectively.
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
283
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
284 # Root URL does nothing meaningful... yet.
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
285 if not urlparts:
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
286 res.status = b'200 OK'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
287 res.headers[b'Content-Type'] = b'text/plain'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
288 res.setbodybytes(_('HTTP version 2 API handler'))
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
289 return
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
290
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
291 if len(urlparts) == 1:
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
292 res.status = b'404 Not Found'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
293 res.headers[b'Content-Type'] = b'text/plain'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
294 res.setbodybytes(_('do not know how to process %s\n') %
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
295 req.dispatchpath)
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
296 return
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
297
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
298 permission, command = urlparts[0:2]
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
299
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
300 if permission not in (b'ro', b'rw'):
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
301 res.status = b'404 Not Found'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
302 res.headers[b'Content-Type'] = b'text/plain'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
303 res.setbodybytes(_('unknown permission: %s') % permission)
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
304 return
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
305
37048
fc5e261915b9 wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37047
diff changeset
306 if req.method != 'POST':
fc5e261915b9 wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37047
diff changeset
307 res.status = b'405 Method Not Allowed'
fc5e261915b9 wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37047
diff changeset
308 res.headers[b'Allow'] = b'POST'
fc5e261915b9 wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37047
diff changeset
309 res.setbodybytes(_('commands require POST requests'))
fc5e261915b9 wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37047
diff changeset
310 return
fc5e261915b9 wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37047
diff changeset
311
37047
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
312 # At some point we'll want to use our own API instead of recycling the
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
313 # behavior of version 1 of the wire protocol...
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
314 # TODO return reasonable responses - not responses that overload the
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
315 # HTTP status line message for error reporting.
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
316 try:
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
317 checkperm(rctx, req, 'pull' if permission == b'ro' else 'push')
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
318 except hgwebcommon.ErrorResponse as e:
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
319 res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
320 for k, v in e.headers:
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
321 res.headers[k] = v
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
322 res.setbodybytes('permission denied')
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
323 return
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
324
37052
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
325 # We have a special endpoint to reflect the request back at the client.
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
326 if command == b'debugreflect':
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
327 _processhttpv2reflectrequest(rctx.repo.ui, rctx.repo, req, res)
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
328 return
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
329
37059
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
330 # Extra commands that we handle that aren't really wire protocol
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
331 # commands. Think extra hard before making this hackery available to
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
332 # extension.
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
333 extracommands = {'multirequest'}
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
334
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
335 if command not in wireproto.commands and command not in extracommands:
37047
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
336 res.status = b'404 Not Found'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
337 res.headers[b'Content-Type'] = b'text/plain'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
338 res.setbodybytes(_('unknown wire protocol command: %s\n') % command)
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
339 return
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
340
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
341 repo = rctx.repo
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
342 ui = repo.ui
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
343
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
344 proto = httpv2protocolhandler(req, ui)
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
345
37059
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
346 if (not wireproto.commands.commandavailable(command, proto)
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
347 and command not in extracommands):
37047
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
348 res.status = b'404 Not Found'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
349 res.headers[b'Content-Type'] = b'text/plain'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
350 res.setbodybytes(_('invalid wire protocol command: %s') % command)
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
351 return
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
352
37051
40206e227412 wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37050
diff changeset
353 if req.headers.get(b'Accept') != FRAMINGTYPE:
37050
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37048
diff changeset
354 res.status = b'406 Not Acceptable'
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37048
diff changeset
355 res.headers[b'Content-Type'] = b'text/plain'
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37048
diff changeset
356 res.setbodybytes(_('client MUST specify Accept header with value: %s\n')
37051
40206e227412 wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37050
diff changeset
357 % FRAMINGTYPE)
37050
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37048
diff changeset
358 return
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37048
diff changeset
359
37052
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
360 if req.headers.get(b'Content-Type') != FRAMINGTYPE:
37050
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37048
diff changeset
361 res.status = b'415 Unsupported Media Type'
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37048
diff changeset
362 # TODO we should send a response with appropriate media type,
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37048
diff changeset
363 # since client does Accept it.
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37048
diff changeset
364 res.headers[b'Content-Type'] = b'text/plain'
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37048
diff changeset
365 res.setbodybytes(_('client MUST send Content-Type header with '
37051
40206e227412 wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37050
diff changeset
366 'value: %s\n') % FRAMINGTYPE)
37050
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37048
diff changeset
367 return
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37048
diff changeset
368
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
369 _processhttpv2request(ui, repo, req, res, permission, command, proto)
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
370
37052
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
371 def _processhttpv2reflectrequest(ui, repo, req, res):
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
372 """Reads unified frame protocol request and dumps out state to client.
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
373
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
374 This special endpoint can be used to help debug the wire protocol.
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
375
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
376 Instead of routing the request through the normal dispatch mechanism,
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
377 we instead read all frames, decode them, and feed them into our state
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
378 tracker. We then dump the log of all that activity back out to the
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
379 client.
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
380 """
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
381 import json
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
382
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
383 # Reflection APIs have a history of being abused, accidentally disclosing
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
384 # sensitive data, etc. So we have a config knob.
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
385 if not ui.configbool('experimental', 'web.api.debugreflect'):
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
386 res.status = b'404 Not Found'
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
387 res.headers[b'Content-Type'] = b'text/plain'
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
388 res.setbodybytes(_('debugreflect service not available'))
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
389 return
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
390
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
391 # We assume we have a unified framing protocol request body.
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
392
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
393 reactor = wireprotoframing.serverreactor()
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
394 states = []
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
395
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
396 while True:
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
397 frame = wireprotoframing.readframe(req.bodyfh)
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
398
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
399 if not frame:
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
400 states.append(b'received: <no frame>')
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
401 break
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
402
37061
884a0c1604ad wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37059
diff changeset
403 states.append(b'received: %d %d %d %s' % (frame.typeid, frame.flags,
884a0c1604ad wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37059
diff changeset
404 frame.requestid,
884a0c1604ad wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37059
diff changeset
405 frame.payload))
37052
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
406
37061
884a0c1604ad wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37059
diff changeset
407 action, meta = reactor.onframerecv(frame)
37052
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
408 states.append(json.dumps((action, meta), sort_keys=True,
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
409 separators=(', ', ': ')))
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
410
37056
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
411 action, meta = reactor.oninputeof()
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
412 meta['action'] = action
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
413 states.append(json.dumps(meta, sort_keys=True, separators=(', ',': ')))
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
414
37052
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
415 res.status = b'200 OK'
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
416 res.headers[b'Content-Type'] = b'text/plain'
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
417 res.setbodybytes(b'\n'.join(states))
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
418
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
419 def _processhttpv2request(ui, repo, req, res, authedperm, reqcommand, proto):
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
420 """Post-validation handler for HTTPv2 requests.
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
421
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
422 Called when the HTTP request contains unified frame-based protocol
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
423 frames for evaluation.
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
424 """
37056
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
425 # TODO Some HTTP clients are full duplex and can receive data before
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
426 # the entire request is transmitted. Figure out a way to indicate support
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
427 # for that so we can opt into full duplex mode.
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
428 reactor = wireprotoframing.serverreactor(deferoutput=True)
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
429 seencommand = False
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
430
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
431 while True:
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
432 frame = wireprotoframing.readframe(req.bodyfh)
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
433 if not frame:
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
434 break
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
435
37061
884a0c1604ad wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37059
diff changeset
436 action, meta = reactor.onframerecv(frame)
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
437
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
438 if action == 'wantframe':
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
439 # Need more data before we can do anything.
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
440 continue
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
441 elif action == 'runcommand':
37059
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
442 sentoutput = _httpv2runcommand(ui, repo, req, res, authedperm,
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
443 reqcommand, reactor, meta,
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
444 issubsequent=seencommand)
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
445
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
446 if sentoutput:
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
447 return
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
448
37059
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
449 seencommand = True
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
450
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
451 elif action == 'error':
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
452 # TODO define proper error mechanism.
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
453 res.status = b'200 OK'
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
454 res.headers[b'Content-Type'] = b'text/plain'
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
455 res.setbodybytes(meta['message'] + b'\n')
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
456 return
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
457 else:
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
458 raise error.ProgrammingError(
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
459 'unhandled action from frame processor: %s' % action)
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
460
37056
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
461 action, meta = reactor.oninputeof()
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
462 if action == 'sendframes':
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
463 # We assume we haven't started sending the response yet. If we're
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
464 # wrong, the response type will raise an exception.
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
465 res.status = b'200 OK'
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
466 res.headers[b'Content-Type'] = FRAMINGTYPE
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
467 res.setbodygen(meta['framegen'])
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
468 elif action == 'noop':
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
469 pass
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
470 else:
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
471 raise error.ProgrammingError('unhandled action from frame processor: %s'
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
472 % action)
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
473
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
474 def _httpv2runcommand(ui, repo, req, res, authedperm, reqcommand, reactor,
37059
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
475 command, issubsequent):
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
476 """Dispatch a wire protocol command made from HTTPv2 requests.
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
477
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
478 The authenticated permission (``authedperm``) along with the original
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
479 command from the URL (``reqcommand``) are passed in.
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
480 """
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
481 # We already validated that the session has permissions to perform the
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
482 # actions in ``authedperm``. In the unified frame protocol, the canonical
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
483 # command to run is expressed in a frame. However, the URL also requested
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
484 # to run a specific command. We need to be careful that the command we
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
485 # run doesn't have permissions requirements greater than what was granted
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
486 # by ``authedperm``.
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
487 #
37059
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
488 # Our rule for this is we only allow one command per HTTP request and
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
489 # that command must match the command in the URL. However, we make
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
490 # an exception for the ``multirequest`` URL. This URL is allowed to
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
491 # execute multiple commands. We double check permissions of each command
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
492 # as it is invoked to ensure there is no privilege escalation.
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
493 # TODO consider allowing multiple commands to regular command URLs
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
494 # iff each command is the same.
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
495
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
496 proto = httpv2protocolhandler(req, ui, args=command['args'])
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
497
37059
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
498 if reqcommand == b'multirequest':
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
499 if not wireproto.commands.commandavailable(command['command'], proto):
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
500 # TODO proper error mechanism
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
501 res.status = b'200 OK'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
502 res.headers[b'Content-Type'] = b'text/plain'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
503 res.setbodybytes(_('wire protocol command not available: %s') %
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
504 command['command'])
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
505 return True
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
506
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
507 assert authedperm in (b'ro', b'rw')
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
508 wirecommand = wireproto.commands[command['command']]
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
509 assert wirecommand.permission in ('push', 'pull')
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
510
37059
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
511 if authedperm == b'ro' and wirecommand.permission != 'pull':
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
512 # TODO proper error mechanism
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
513 res.status = b'403 Forbidden'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
514 res.headers[b'Content-Type'] = b'text/plain'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
515 res.setbodybytes(_('insufficient permissions to execute '
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
516 'command: %s') % command['command'])
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
517 return True
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
518
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
519 # TODO should we also call checkperm() here? Maybe not if we're going
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
520 # to overhaul that API. The granted scope from the URL check should
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
521 # be good enough.
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
522
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
523 else:
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
524 # Don't allow multiple commands outside of ``multirequest`` URL.
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
525 if issubsequent:
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
526 # TODO proper error mechanism
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
527 res.status = b'200 OK'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
528 res.headers[b'Content-Type'] = b'text/plain'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
529 res.setbodybytes(_('multiple commands cannot be issued to this '
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
530 'URL'))
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
531 return True
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
532
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
533 if reqcommand != command['command']:
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
534 # TODO define proper error mechanism
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
535 res.status = b'200 OK'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
536 res.headers[b'Content-Type'] = b'text/plain'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
537 res.setbodybytes(_('command in frame must match command in URL'))
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
538 return True
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
539
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
540 rsp = wireproto.dispatch(repo, proto, command['command'])
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
541
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
542 res.status = b'200 OK'
37055
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
543 res.headers[b'Content-Type'] = FRAMINGTYPE
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
544
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
545 if isinstance(rsp, wireprototypes.bytesresponse):
37057
2ec1fb9de638 wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
546 action, meta = reactor.onbytesresponseready(command['requestid'],
2ec1fb9de638 wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
547 rsp.data)
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
548 else:
37055
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
549 action, meta = reactor.onapplicationerror(
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
550 _('unhandled response type from wire proto command'))
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
551
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
552 if action == 'sendframes':
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
553 res.setbodygen(meta['framegen'])
37059
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
554 return True
37056
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
555 elif action == 'noop':
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37055
diff changeset
556 pass
37055
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
557 else:
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
558 raise error.ProgrammingError('unhandled event from reactor: %s' %
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
559 action)
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
560
37046
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
561 # Maps API name to metadata so custom API can be registered.
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
562 API_HANDLERS = {
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
563 HTTPV2: {
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
564 'config': ('experimental', 'web.api.http-v2'),
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
565 'handler': _handlehttpv2request,
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
566 },
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
567 }
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36877
diff changeset
568
37047
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
569 class httpv2protocolhandler(wireprototypes.baseprotocolhandler):
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
570 def __init__(self, req, ui, args=None):
37047
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
571 self._req = req
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
572 self._ui = ui
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
573 self._args = args
37047
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
574
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
575 @property
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
576 def name(self):
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
577 return HTTPV2
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
578
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
579 def getargs(self, args):
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
580 data = {}
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
581 for k in args.split():
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
582 if k == '*':
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
583 raise NotImplementedError('do not support * args')
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
584 else:
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
585 data[k] = self._args[k]
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
586
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
587 return [data[k] for k in args.split()]
37047
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
588
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
589 def forwardpayload(self, fp):
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
590 raise NotImplementedError
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
591
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
592 @contextlib.contextmanager
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
593 def mayberedirectstdio(self):
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
594 raise NotImplementedError
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
595
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
596 def client(self):
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
597 raise NotImplementedError
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
598
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
599 def addcapabilities(self, repo, caps):
37054
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
600 return caps
37047
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
601
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
602 def checkperm(self, perm):
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
603 raise NotImplementedError
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37046
diff changeset
604
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
605 def _httpresponsetype(ui, req, prefer_uncompressed):
36072
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
606 """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
607
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
608 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
609 """
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
610 # 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
611 # on the request parameters.
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
612 protocaps = decodevaluefromheaders(req, 'X-HgProto').split(' ')
36072
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
613
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
614 if '0.2' in protocaps:
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
615 # 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
616 if prefer_uncompressed:
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
617 return HGTYPE2, util._noopengine(), {}
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
618
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
619 # Default as defined by wire protocol spec.
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
620 compformats = ['zlib', 'none']
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
621 for cap in protocaps:
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
622 if cap.startswith('comp='):
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
623 compformats = cap[5:].split(',')
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
624 break
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
625
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
626 # Now find an agreed upon compression format.
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
627 for engine in wireproto.supportedcompengines(ui, util.SERVERROLE):
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
628 if engine.wireprotosupport().name in compformats:
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
629 opts = {}
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
630 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
631 if level is not None:
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
632 opts['level'] = level
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
633
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
634 return HGTYPE2, engine, opts
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
635
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
636 # 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
637 # legacy protocol.
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
638
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
639 # 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
640 # 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
641 # the server's network or CPU.
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
642 opts = {'level': ui.configint('server', 'zliblevel')}
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
643 return HGTYPE, util.compengines['zlib'], opts
341c886e411e wireprotoserver: move responsetype() out of http handler
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36071
diff changeset
644
36867
a755fd3b7146 hgweb: expose URL scheme and REMOTE_* attributes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36862
diff changeset
645 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
646 # Avoid cycle involving hg module.
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
647 from .hgweb import common as hgwebcommon
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
648
35750
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
649 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
650 # 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
651 # 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
652 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
653 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
654 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
655 yield name
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
656
35750
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
657 for chunk in gen:
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
658 yield chunk
30764
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
659
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
660 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
661 if code == HTTP_OK:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
662 res.status = '200 Script output follows'
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
663 else:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
664 res.status = hgwebcommon.statusmessage(code)
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
665
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
666 res.headers['Content-Type'] = contenttype
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
667
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
668 if bodybytes is not None:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
669 res.setbodybytes(bodybytes)
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
670 if bodygen is not None:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
671 res.setbodygen(bodygen)
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
672
35982
5a56bf4180ad wireproto: function for testing if wire protocol command is available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35976
diff changeset
673 if not wireproto.commands.commandavailable(cmd, proto):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
674 setresponse(HTTP_OK, HGERRTYPE,
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
675 _('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
676 'HTTP'))
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
677 return
35982
5a56bf4180ad wireproto: function for testing if wire protocol command is available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35976
diff changeset
678
36801
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
679 proto.checkperm(wireproto.commands[cmd].permission)
36799
c638a13093cf wireprotoserver: check permissions in main dispatch function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36798
diff changeset
680
36798
7574c8173d5e wireprotoserver: check if command available before calling it
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36760
diff changeset
681 rsp = wireproto.dispatch(repo, proto, cmd)
7574c8173d5e wireprotoserver: check if command available before calling it
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36760
diff changeset
682
34510
c23fa3103925 hgweb: in protocol adapter, look for bytes instances, not str
Augie Fackler <augie@google.com>
parents: 34509
diff changeset
683 if isinstance(rsp, bytes):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
684 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
685 elif isinstance(rsp, wireprototypes.bytesresponse):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
686 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
687 elif isinstance(rsp, wireprototypes.streamreslegacy):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
688 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
689 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
690 gen = rsp.gen
30466
2add671bf55b wireproto: perform chunking and compression at protocol layer (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30366
diff changeset
691
30764
e75463e3179f protocol: send application/mercurial-0.2 responses to capable clients
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
692 # 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
693 # 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
694 mediatype, engine, engineopts = _httpresponsetype(
36846
14f70c44af6c wireprotoserver: access headers through parsed request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36813
diff changeset
695 repo.ui, req, rsp.prefer_uncompressed)
35750
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
696 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
697
35750
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
698 if mediatype == HGTYPE2:
a39a9df7ecca wireproto: split streamres into legacy and modern case
Joerg Sonnenberger <joerg@bec.de>
parents: 35705
diff changeset
699 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
700
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
701 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
702 elif isinstance(rsp, wireprototypes.pushres):
36067
caca3ac2ac04 wireproto: use maybecapturestdio() for push responses (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36066
diff changeset
703 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
704 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
705 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
706 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
707 res.drain = True
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
708 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
709 elif isinstance(rsp, wireprototypes.ooberror):
36861
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
710 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
711 else:
a88d68dc3ee8 hgweb: create dedicated type for WSGI responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36857
diff changeset
712 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
713
36064
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
714 def _sshv1respondbytes(fout, value):
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
715 """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
716 fout.write('%d\n' % len(value))
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
717 fout.write(value)
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
718 fout.flush()
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
719
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
720 def _sshv1respondstream(fout, source):
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
721 write = fout.write
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
722 for chunk in source.gen:
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
723 write(chunk)
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
724 fout.flush()
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
725
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
726 def _sshv1respondooberror(fout, ferr, rsp):
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
727 ferr.write(b'%s\n-\n' % rsp)
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
728 ferr.flush()
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
729 fout.write(b'\n')
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
730 fout.flush()
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35988
diff changeset
731
36371
0c231df1ffdc wireprototypes: move baseprotocolhandler from wireprotoserver
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36280
diff changeset
732 class sshv1protocolhandler(wireprototypes.baseprotocolhandler):
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
733 """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
734 def __init__(self, ui, fin, fout):
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
735 self._ui = ui
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
736 self._fin = fin
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
737 self._fout = fout
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
738
35873
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
739 @property
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
740 def name(self):
36536
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36526
diff changeset
741 return wireprototypes.SSHV1
35873
29759c46aa1a wireprotoserver: make name part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35872
diff changeset
742
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
743 def getargs(self, args):
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
744 data = {}
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
745 keys = args.split()
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
746 for n in xrange(len(keys)):
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
747 argline = self._fin.readline()[:-1]
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
748 arg, l = argline.split()
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
749 if arg not in keys:
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
750 raise error.Abort(_("unexpected parameter %r") % arg)
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
751 if arg == '*':
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
752 star = {}
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
753 for k in xrange(int(l)):
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
754 argline = self._fin.readline()[:-1]
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
755 arg, l = argline.split()
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
756 val = self._fin.read(int(l))
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
757 star[arg] = val
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
758 data['*'] = star
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
759 else:
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
760 val = self._fin.read(int(l))
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
761 data[arg] = val
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
762 return [data[k] for k in keys]
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
763
36070
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
764 def forwardpayload(self, fpout):
36372
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36371
diff changeset
765 # 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
766 # 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
767 # interprets it as an error.
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36371
diff changeset
768 _sshv1respondbytes(self._fout, b'')
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36371
diff changeset
769
36070
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
770 # The file is in the form:
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
771 #
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
772 # <chunk size>\n<chunk>
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
773 # ...
90ca4986616c wireprotoserver: rename getfile() to forwardpayload() (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36069
diff changeset
774 # 0\n
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
775 count = int(self._fin.readline())
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
776 while count:
35870
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
777 fpout.write(self._fin.read(count))
f1efc0caeab7 wireprotoserver: make some instance attributes private
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35869
diff changeset
778 count = int(self._fin.readline())
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
779
36066
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
780 @contextlib.contextmanager
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
781 def mayberedirectstdio(self):
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
782 yield None
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36065
diff changeset
783
36069
957e773614d0 wireprotoserver: rename _client to client (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36068
diff changeset
784 def client(self):
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
785 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
786 return 'remote:ssh:' + client
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
787
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
788 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
789 caps.append(b'batch')
36613
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
790 return caps
6e585bca962e wireproto: add transport specific capabilities in the transport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36610
diff changeset
791
36801
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
792 def checkperm(self, perm):
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
793 pass
66de4555cefd wireproto: formalize permissions checking as part of protocol interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36800
diff changeset
794
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
795 class sshv2protocolhandler(sshv1protocolhandler):
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
796 """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
797
36610
af0d38f015bb wireprotoserver: identify requests via version 2 of SSH protocol as such
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36536
diff changeset
798 @property
af0d38f015bb wireprotoserver: identify requests via version 2 of SSH protocol as such
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36536
diff changeset
799 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
800 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
801
36523
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
802 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
803 # 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
804 # states are defined:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
805 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
806 # protov1-serving
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
807 # 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
808 # 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
809 # after the other.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
810 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
811 # protov2-serving
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
812 # 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
813 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
814 # upgrade-initial
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
815 # 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
816 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
817 # upgrade-v2-filter-legacy-handshake
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
818 # 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
819 # 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
820 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
821 # upgrade-v2-finish
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
822 # 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
823 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
824 # shutdown
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
825 # 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
826 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
827 # And here are their transitions:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
828 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
829 # protov1-serving -> shutdown
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
830 # 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
831 # error.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
832 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
833 # protov1-serving -> upgrade-initial
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
834 # 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
835 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
836 # 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
837 # 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
838 # process a legacy handshake.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
839 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
840 # 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
841 # 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
842 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
843 # 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
844 # 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
845 # upgrade.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
846 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
847 # upgrade-v2-finish -> protov2-serving
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
848 # 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
849 # version 2.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
850 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
851 # protov2-serving -> protov1-serving
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
852 # 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
853 # 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
854
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
855 state = 'protov1-serving'
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
856 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
857 protoswitched = False
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
858
36523
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
859 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
860 if state == 'protov1-serving':
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
861 # 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
862 request = fin.readline()[:-1]
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
863
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
864 # 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
865 if not request:
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
866 state = 'shutdown'
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
867 continue
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
868
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
869 # 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
870 # handle it.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
871 if request.startswith(b'upgrade '):
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
872 if protoswitched:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
873 _sshv1respondooberror(fout, ui.ferr,
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
874 b'cannot upgrade protocols multiple '
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
875 b'times')
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
876 state = 'shutdown'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
877 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
878
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
879 state = 'upgrade-initial'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
880 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
881
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
882 available = wireproto.commands.commandavailable(request, proto)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
883
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
884 # 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
885 # 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
886 if not available:
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
887 _sshv1respondbytes(fout, b'')
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
888 continue
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
889
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
890 rsp = wireproto.dispatch(repo, proto, request)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
891
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
892 if isinstance(rsp, bytes):
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
893 _sshv1respondbytes(fout, rsp)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
894 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
895 _sshv1respondbytes(fout, rsp.data)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
896 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
897 _sshv1respondstream(fout, rsp)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
898 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
899 _sshv1respondstream(fout, rsp)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
900 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
901 _sshv1respondbytes(fout, b'')
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
902 _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
903 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
904 _sshv1respondbytes(fout, rsp.res)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
905 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
906 _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
907 else:
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
908 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
909 '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
910
36215
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
911 # 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
912 elif state == 'protov2-serving':
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
913 state = 'protov1-serving'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
914 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
915
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
916 elif state == 'upgrade-initial':
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
917 # 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
918 # protocols.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
919 assert not protoswitched
36536
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36526
diff changeset
920 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
921
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
922 # Expected: upgrade <token> <capabilities>
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
923 # 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
924 # 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
925 # 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
926 try:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
927 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
928 except ValueError:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
929 _sshv1respondbytes(fout, b'')
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
930 state = 'protov1-serving'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
931 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
932
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
933 # 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
934 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
935 _sshv1respondbytes(fout, b'')
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
936 state = 'protov1-serving'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
937 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
938
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
939 try:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
940 caps = urlreq.parseqs(caps)
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
941 except ValueError:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
942 _sshv1respondbytes(fout, b'')
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
943 state = 'protov1-serving'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
944 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
945
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
946 # 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
947 # the upgrade request.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
948 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
949 if SSHV2 not in wantedprotos:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
950 _sshv1respondbytes(fout, b'')
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
951 state = 'protov1-serving'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
952 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
953
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
954 # 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
955 # 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
956 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
957 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
958
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
959 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
960 # 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
961 # request. Expected lines:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
962 #
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
963 # hello
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
964 # between
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
965 # pairs 81
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
966 # 0000...-0000...
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
967
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
968 ok = True
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
969 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
970 request = fin.readline()[:-1]
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
971
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
972 if request != line:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
973 _sshv1respondooberror(fout, ui.ferr,
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
974 b'malformed handshake protocol: '
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
975 b'missing %s' % line)
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
976 ok = False
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
977 state = 'shutdown'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
978 break
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
979
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
980 if not ok:
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
981 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
982
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
983 request = fin.read(81)
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
984 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
985 _sshv1respondooberror(fout, ui.ferr,
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
986 b'malformed handshake protocol: '
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
987 b'missing between argument value')
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
988 state = 'shutdown'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
989 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
990
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
991 state = 'upgrade-v2-finish'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
992 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
993
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
994 elif state == 'upgrade-v2-finish':
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
995 # Send the upgrade response.
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
996 fout.write(b'upgraded %s %s\n' % (token, SSHV2))
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
997 servercaps = wireproto.capabilities(repo, proto)
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
998 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
999 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
1000 fout.flush()
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
1001
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
1002 proto = sshv2protocolhandler(ui, fin, fout)
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
1003 protoswitched = True
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
1004
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
1005 state = 'protov2-serving'
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
1006 continue
464bedc0fdb4 wireprotoserver: handle SSH protocol version 2 upgrade requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36214
diff changeset
1007
36214
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
1008 elif state == 'shutdown':
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
1009 break
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
1010
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
1011 else:
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
1012 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
1013 state)
3b3a987bbbaa wireprotoserver: move SSH server operation to a standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36213
diff changeset
1014
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
1015 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
1016 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
1017 self._ui = ui
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
1018 self._repo = repo
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
1019 self._fin = ui.fin
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
1020 self._fout = ui.fout
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
1021
36526
7cc4a9b9732a wireprotoserver: support logging SSH server I/O to a file descriptor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36523
diff changeset
1022 # 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
1023 if logfh:
7cc4a9b9732a wireprotoserver: support logging SSH server I/O to a file descriptor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36523
diff changeset
1024 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
1025 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
1026 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
1027 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
1028
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
1029 hook.redirect(True)
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
1030 ui.fout = repo.ui.fout = ui.ferr
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
1031
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
1032 # Prevent insertion/deletion of CRs
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
1033 util.setbinary(self._fin)
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
1034 util.setbinary(self._fout)
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
1035
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
1036 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
1037 self.serveuntil(threading.Event())
35859
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35858
diff changeset
1038 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
1039
e7411fb7ba7f wireprotoserver: ability to run an SSH server until an event is set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
1040 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
1041 """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
1042 _runsshserver(self._ui, self._repo, self._fin, self._fout, ev)