Mercurial > public > mercurial-scm > hg-stable
diff mercurial/wireprotoserver.py @ 48561:04688c51f81f
exchangev2: remove it
As discussed on the mailing list, this is incomplete and unused with little
hope of revival.
Differential Revision: https://phab.mercurial-scm.org/D11954
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Tue, 07 Dec 2021 16:44:22 +0100 |
parents | 81805bba11f9 |
children | 6000f5b25c9b |
line wrap: on
line diff
--- a/mercurial/wireprotoserver.py Thu Dec 30 13:25:44 2021 +0100 +++ b/mercurial/wireprotoserver.py Tue Dec 07 16:44:22 2021 +0100 @@ -18,11 +18,9 @@ util, wireprototypes, wireprotov1server, - wireprotov2server, ) from .interfaces import util as interfaceutil from .utils import ( - cborutil, compression, stringutil, ) @@ -39,7 +37,6 @@ HGERRTYPE = b'application/hg-error' SSHV1 = wireprototypes.SSHV1 -SSHV2 = wireprototypes.SSHV2 def decodevaluefromheaders(req, headerprefix): @@ -244,97 +241,6 @@ return True -def _availableapis(repo): - apis = set() - - # Registered APIs are made available via config options of the name of - # the protocol. - for k, v in API_HANDLERS.items(): - section, option = v[b'config'] # pytype: disable=attribute-error - if repo.ui.configbool(section, option): - apis.add(k) - - return apis - - -def handlewsgiapirequest(rctx, req, res, checkperm): - """Handle requests to /api/*.""" - assert req.dispatchparts[0] == b'api' - - repo = rctx.repo - - # This whole URL space is experimental for now. But we want to - # reserve the URL space. So, 404 all URLs if the feature isn't enabled. - if not repo.ui.configbool(b'experimental', b'web.apiserver'): - res.status = b'404 Not Found' - res.headers[b'Content-Type'] = b'text/plain' - res.setbodybytes(_(b'Experimental API server endpoint not enabled')) - return - - # The URL space is /api/<protocol>/*. The structure of URLs under varies - # by <protocol>. - - availableapis = _availableapis(repo) - - # Requests to /api/ list available APIs. - if req.dispatchparts == [b'api']: - res.status = b'200 OK' - res.headers[b'Content-Type'] = b'text/plain' - lines = [ - _( - b'APIs can be accessed at /api/<name>, where <name> can be ' - b'one of the following:\n' - ) - ] - if availableapis: - lines.extend(sorted(availableapis)) - else: - lines.append(_(b'(no available APIs)\n')) - res.setbodybytes(b'\n'.join(lines)) - return - - proto = req.dispatchparts[1] - - if proto not in API_HANDLERS: - res.status = b'404 Not Found' - res.headers[b'Content-Type'] = b'text/plain' - res.setbodybytes( - _(b'Unknown API: %s\nKnown APIs: %s') - % (proto, b', '.join(sorted(availableapis))) - ) - return - - if proto not in availableapis: - res.status = b'404 Not Found' - res.headers[b'Content-Type'] = b'text/plain' - res.setbodybytes(_(b'API %s not enabled\n') % proto) - return - - API_HANDLERS[proto][b'handler']( - rctx, req, res, checkperm, req.dispatchparts[2:] - ) - - -# Maps API name to metadata so custom API can be registered. -# Keys are: -# -# config -# Config option that controls whether service is enabled. -# handler -# Callable receiving (rctx, req, res, checkperm, urlparts) that is called -# when a request to this API is received. -# apidescriptor -# Callable receiving (req, repo) that is called to obtain an API -# descriptor for this service. The response must be serializable to CBOR. -API_HANDLERS = { - wireprotov2server.HTTP_WIREPROTO_V2: { - b'config': (b'experimental', b'web.api.http-v2'), - b'handler': wireprotov2server.handlehttpv2request, - b'apidescriptor': wireprotov2server.httpv2apidescriptor, - }, -} - - def _httpresponsetype(ui, proto, prefer_uncompressed): """Determine the appropriate response type and compression settings. @@ -371,55 +277,6 @@ return HGTYPE, util.compengines[b'zlib'], opts -def processcapabilitieshandshake(repo, req, res, proto): - """Called during a ?cmd=capabilities request. - - If the client is advertising support for a newer protocol, we send - a CBOR response with information about available services. If no - advertised services are available, we don't handle the request. - """ - # Fall back to old behavior unless the API server is enabled. - if not repo.ui.configbool(b'experimental', b'web.apiserver'): - return False - - clientapis = decodevaluefromheaders(req, b'X-HgUpgrade') - protocaps = decodevaluefromheaders(req, b'X-HgProto') - if not clientapis or not protocaps: - return False - - # We currently only support CBOR responses. - protocaps = set(protocaps.split(b' ')) - if b'cbor' not in protocaps: - return False - - descriptors = {} - - for api in sorted(set(clientapis.split()) & _availableapis(repo)): - handler = API_HANDLERS[api] - - descriptorfn = handler.get(b'apidescriptor') - if not descriptorfn: - continue - - descriptors[api] = descriptorfn(req, repo) - - v1caps = wireprotov1server.dispatch(repo, proto, b'capabilities') - assert isinstance(v1caps, wireprototypes.bytesresponse) - - m = { - # TODO allow this to be configurable. - b'apibase': b'api/', - b'apis': descriptors, - b'v1capabilities': v1caps.data, - } - - res.status = b'200 OK' - res.headers[b'Content-Type'] = b'application/mercurial-cbor' - res.setbodybytes(b''.join(cborutil.streamencode(m))) - - return True - - def _callhttp(repo, req, res, proto, cmd): # Avoid cycle involving hg module. from .hgweb import common as hgwebcommon @@ -461,13 +318,6 @@ proto.checkperm(wireprotov1server.commands[cmd].permission) - # Possibly handle a modern client wanting to switch protocols. - if cmd == b'capabilities' and processcapabilitieshandshake( - repo, req, res, proto - ): - - return - rsp = wireprotov1server.dispatch(repo, proto, cmd) if isinstance(rsp, bytes): @@ -596,17 +446,6 @@ pass -class sshv2protocolhandler(sshv1protocolhandler): - """Protocol handler for version 2 of the SSH protocol.""" - - @property - def name(self): - return wireprototypes.SSHV2 - - def addcapabilities(self, repo, caps): - return caps - - def _runsshserver(ui, repo, fin, fout, ev): # This function operates like a state machine of sorts. The following # states are defined: @@ -616,19 +455,6 @@ # new lines. These commands are processed in this state, one command # after the other. # - # protov2-serving - # Server is in protocol version 2 serving mode. - # - # upgrade-initial - # The server is going to process an upgrade request. - # - # upgrade-v2-filter-legacy-handshake - # The protocol is being upgraded to version 2. The server is expecting - # the legacy handshake from version 1. - # - # upgrade-v2-finish - # The upgrade to version 2 of the protocol is imminent. - # # shutdown # The server is shutting down, possibly in reaction to a client event. # @@ -637,32 +463,9 @@ # protov1-serving -> shutdown # When server receives an empty request or encounters another # error. - # - # protov1-serving -> upgrade-initial - # An upgrade request line was seen. - # - # upgrade-initial -> upgrade-v2-filter-legacy-handshake - # Upgrade to version 2 in progress. Server is expecting to - # process a legacy handshake. - # - # upgrade-v2-filter-legacy-handshake -> shutdown - # Client did not fulfill upgrade handshake requirements. - # - # upgrade-v2-filter-legacy-handshake -> upgrade-v2-finish - # Client fulfilled version 2 upgrade requirements. Finishing that - # upgrade. - # - # upgrade-v2-finish -> protov2-serving - # Protocol upgrade to version 2 complete. Server can now speak protocol - # version 2. - # - # protov2-serving -> protov1-serving - # Ths happens by default since protocol version 2 is the same as - # version 1 except for the handshake. state = b'protov1-serving' proto = sshv1protocolhandler(ui, fin, fout) - protoswitched = False while not ev.is_set(): if state == b'protov1-serving': @@ -674,21 +477,6 @@ state = b'shutdown' continue - # It looks like a protocol upgrade request. Transition state to - # handle it. - if request.startswith(b'upgrade '): - if protoswitched: - _sshv1respondooberror( - fout, - ui.ferr, - b'cannot upgrade protocols multiple times', - ) - state = b'shutdown' - continue - - state = b'upgrade-initial' - continue - available = wireprotov1server.commands.commandavailable( request, proto ) @@ -724,108 +512,6 @@ b'wire protocol command: %s' % rsp ) - # For now, protocol version 2 serving just goes back to version 1. - elif state == b'protov2-serving': - state = b'protov1-serving' - continue - - elif state == b'upgrade-initial': - # We should never transition into this state if we've switched - # protocols. - assert not protoswitched - assert proto.name == wireprototypes.SSHV1 - - # Expected: upgrade <token> <capabilities> - # If we get something else, the request is malformed. It could be - # from a future client that has altered the upgrade line content. - # We treat this as an unknown command. - try: - token, caps = request.split(b' ')[1:] - except ValueError: - _sshv1respondbytes(fout, b'') - state = b'protov1-serving' - continue - - # Send empty response if we don't support upgrading protocols. - if not ui.configbool(b'experimental', b'sshserver.support-v2'): - _sshv1respondbytes(fout, b'') - state = b'protov1-serving' - continue - - try: - caps = urlreq.parseqs(caps) - except ValueError: - _sshv1respondbytes(fout, b'') - state = b'protov1-serving' - continue - - # We don't see an upgrade request to protocol version 2. Ignore - # the upgrade request. - wantedprotos = caps.get(b'proto', [b''])[0] - if SSHV2 not in wantedprotos: - _sshv1respondbytes(fout, b'') - state = b'protov1-serving' - continue - - # It looks like we can honor this upgrade request to protocol 2. - # Filter the rest of the handshake protocol request lines. - state = b'upgrade-v2-filter-legacy-handshake' - continue - - elif state == b'upgrade-v2-filter-legacy-handshake': - # Client should have sent legacy handshake after an ``upgrade`` - # request. Expected lines: - # - # hello - # between - # pairs 81 - # 0000...-0000... - - ok = True - for line in (b'hello', b'between', b'pairs 81'): - request = fin.readline()[:-1] - - if request != line: - _sshv1respondooberror( - fout, - ui.ferr, - b'malformed handshake protocol: missing %s' % line, - ) - ok = False - state = b'shutdown' - break - - if not ok: - continue - - request = fin.read(81) - if request != b'%s-%s' % (b'0' * 40, b'0' * 40): - _sshv1respondooberror( - fout, - ui.ferr, - b'malformed handshake protocol: ' - b'missing between argument value', - ) - state = b'shutdown' - continue - - state = b'upgrade-v2-finish' - continue - - elif state == b'upgrade-v2-finish': - # Send the upgrade response. - fout.write(b'upgraded %s %s\n' % (token, SSHV2)) - servercaps = wireprotov1server.capabilities(repo, proto) - rsp = b'capabilities: %s' % servercaps.data - fout.write(b'%d\n%s\n' % (len(rsp), rsp)) - fout.flush() - - proto = sshv2protocolhandler(ui, fin, fout) - protoswitched = True - - state = b'protov2-serving' - continue - elif state == b'shutdown': break