This function is used by both version 1 and version 2. It belongs in
a common module.
"wireprototypes" may not be the best module name. I may rename it...
| durin42 |
| hg-reviewers |
This function is used by both version 1 and version 2. It belongs in
a common module.
"wireprototypes" may not be the best module name. I may rename it...
| Automatic diff as part of commit; lint not applicable. |
| Automatic diff as part of commit; unit tests not applicable. |
| Path | Packages | |||
|---|---|---|---|---|
| M | mercurial/wireproto.py (49 lines) | |||
| M | mercurial/wireprotoserver.py (5 lines) | |||
| M | mercurial/wireprototypes.py (54 lines) | |||
| M | mercurial/wireprotov2server.py (2 lines) |
| if gd: | if gd: | ||||
| v = ui.configbool('server', 'bundle1gd') | v = ui.configbool('server', 'bundle1gd') | ||||
| if v is not None: | if v is not None: | ||||
| return v | return v | ||||
| return ui.configbool('server', 'bundle1') | return ui.configbool('server', 'bundle1') | ||||
| def supportedcompengines(ui, role): | |||||
| """Obtain the list of supported compression engines for a request.""" | |||||
| assert role in (util.CLIENTROLE, util.SERVERROLE) | |||||
| compengines = util.compengines.supportedwireengines(role) | |||||
| # Allow config to override default list and ordering. | |||||
| if role == util.SERVERROLE: | |||||
| configengines = ui.configlist('server', 'compressionengines') | |||||
| config = 'server.compressionengines' | |||||
| else: | |||||
| # This is currently implemented mainly to facilitate testing. In most | |||||
| # cases, the server should be in charge of choosing a compression engine | |||||
| # because a server has the most to lose from a sub-optimal choice. (e.g. | |||||
| # CPU DoS due to an expensive engine or a network DoS due to poor | |||||
| # compression ratio). | |||||
| configengines = ui.configlist('experimental', | |||||
| 'clientcompressionengines') | |||||
| config = 'experimental.clientcompressionengines' | |||||
| # No explicit config. Filter out the ones that aren't supposed to be | |||||
| # advertised and return default ordering. | |||||
| if not configengines: | |||||
| attr = 'serverpriority' if role == util.SERVERROLE else 'clientpriority' | |||||
| return [e for e in compengines | |||||
| if getattr(e.wireprotosupport(), attr) > 0] | |||||
| # If compression engines are listed in the config, assume there is a good | |||||
| # reason for it (like server operators wanting to achieve specific | |||||
| # performance characteristics). So fail fast if the config references | |||||
| # unusable compression engines. | |||||
| validnames = set(e.name() for e in compengines) | |||||
| invalidnames = set(e for e in configengines if e not in validnames) | |||||
| if invalidnames: | |||||
| raise error.Abort(_('invalid compression engine defined in %s: %s') % | |||||
| (config, ', '.join(sorted(invalidnames)))) | |||||
| compengines = [e for e in compengines if e.name() in configengines] | |||||
| compengines = sorted(compengines, | |||||
| key=lambda e: configengines.index(e.name())) | |||||
| if not compengines: | |||||
| raise error.Abort(_('%s config option does not specify any known ' | |||||
| 'compression engines') % config, | |||||
| hint=_('usable compression engines: %s') % | |||||
| ', '.sorted(validnames)) | |||||
| return compengines | |||||
| # For version 1 transports. | # For version 1 transports. | ||||
| commands = wireprototypes.commanddict() | commands = wireprototypes.commanddict() | ||||
| # For version 2 transports. | # For version 2 transports. | ||||
| commandsv2 = wireprototypes.commanddict() | commandsv2 = wireprototypes.commanddict() | ||||
| def wireprotocommand(name, args=None, permission='push'): | def wireprotocommand(name, args=None, permission='push'): | ||||
| """Decorator to declare a wire protocol command. | """Decorator to declare a wire protocol command. | ||||
| repo.ui.configint('server', 'maxhttpheaderlen')) | repo.ui.configint('server', 'maxhttpheaderlen')) | ||||
| if repo.ui.configbool('experimental', 'httppostargs'): | if repo.ui.configbool('experimental', 'httppostargs'): | ||||
| caps.append('httppostargs') | caps.append('httppostargs') | ||||
| # FUTURE advertise 0.2rx once support is implemented | # FUTURE advertise 0.2rx once support is implemented | ||||
| # FUTURE advertise minrx and mintx after consulting config option | # FUTURE advertise minrx and mintx after consulting config option | ||||
| caps.append('httpmediatype=0.1rx,0.1tx,0.2tx') | caps.append('httpmediatype=0.1rx,0.1tx,0.2tx') | ||||
| compengines = wireproto.supportedcompengines(repo.ui, util.SERVERROLE) | compengines = wireprototypes.supportedcompengines(repo.ui, | ||||
| util.SERVERROLE) | |||||
| if compengines: | if compengines: | ||||
| comptypes = ','.join(urlreq.quote(e.wireprotosupport().name) | comptypes = ','.join(urlreq.quote(e.wireprotosupport().name) | ||||
| for e in compengines) | for e in compengines) | ||||
| caps.append('compression=%s' % comptypes) | caps.append('compression=%s' % comptypes) | ||||
| return caps | return caps | ||||
| def checkperm(self, perm): | def checkperm(self, perm): | ||||
| if '0.2' in proto.getprotocaps(): | if '0.2' in proto.getprotocaps(): | ||||
| # All clients are expected to support uncompressed data. | # All clients are expected to support uncompressed data. | ||||
| if prefer_uncompressed: | if prefer_uncompressed: | ||||
| return HGTYPE2, util._noopengine(), {} | return HGTYPE2, util._noopengine(), {} | ||||
| # Now find an agreed upon compression format. | # Now find an agreed upon compression format. | ||||
| compformats = wireproto.clientcompressionsupport(proto) | compformats = wireproto.clientcompressionsupport(proto) | ||||
| for engine in wireproto.supportedcompengines(ui, util.SERVERROLE): | for engine in wireprototypes.supportedcompengines(ui, util.SERVERROLE): | ||||
| if engine.wireprotosupport().name in compformats: | if engine.wireprotosupport().name in compformats: | ||||
| opts = {} | opts = {} | ||||
| level = ui.configint('server', '%slevel' % engine.name()) | level = ui.configint('server', '%slevel' % engine.name()) | ||||
| if level is not None: | if level is not None: | ||||
| opts['level'] = level | opts['level'] = level | ||||
| return HGTYPE2, engine, opts | return HGTYPE2, engine, opts | ||||
| # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com> | # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com> | ||||
| # | # | ||||
| # This software may be used and distributed according to the terms of the | # This software may be used and distributed according to the terms of the | ||||
| # GNU General Public License version 2 or any later version. | # GNU General Public License version 2 or any later version. | ||||
| from __future__ import absolute_import | from __future__ import absolute_import | ||||
| from .node import ( | from .node import ( | ||||
| bin, | bin, | ||||
| hex, | hex, | ||||
| ) | ) | ||||
| from .thirdparty.zope import ( | from .thirdparty.zope import ( | ||||
| interface as zi, | interface as zi, | ||||
| ) | ) | ||||
| from .i18n import _ | |||||
| from . import ( | |||||
| error, | |||||
| util, | |||||
| ) | |||||
| # Names of the SSH protocol implementations. | # Names of the SSH protocol implementations. | ||||
| SSHV1 = 'ssh-v1' | SSHV1 = 'ssh-v1' | ||||
| # These are advertised over the wire. Increment the counters at the end | # These are advertised over the wire. Increment the counters at the end | ||||
| # to reflect BC breakages. | # to reflect BC breakages. | ||||
| SSHV2 = 'exp-ssh-v2-0001' | SSHV2 = 'exp-ssh-v2-0001' | ||||
| HTTP_WIREPROTO_V2 = 'exp-http-v2-0001' | HTTP_WIREPROTO_V2 = 'exp-http-v2-0001' | ||||
| if not entry: | if not entry: | ||||
| return False | return False | ||||
| if proto.name not in entry.transports: | if proto.name not in entry.transports: | ||||
| return False | return False | ||||
| return True | return True | ||||
| def supportedcompengines(ui, role): | |||||
| """Obtain the list of supported compression engines for a request.""" | |||||
| assert role in (util.CLIENTROLE, util.SERVERROLE) | |||||
| compengines = util.compengines.supportedwireengines(role) | |||||
| # Allow config to override default list and ordering. | |||||
| if role == util.SERVERROLE: | |||||
| configengines = ui.configlist('server', 'compressionengines') | |||||
| config = 'server.compressionengines' | |||||
| else: | |||||
| # This is currently implemented mainly to facilitate testing. In most | |||||
| # cases, the server should be in charge of choosing a compression engine | |||||
| # because a server has the most to lose from a sub-optimal choice. (e.g. | |||||
| # CPU DoS due to an expensive engine or a network DoS due to poor | |||||
| # compression ratio). | |||||
| configengines = ui.configlist('experimental', | |||||
| 'clientcompressionengines') | |||||
| config = 'experimental.clientcompressionengines' | |||||
| # No explicit config. Filter out the ones that aren't supposed to be | |||||
| # advertised and return default ordering. | |||||
| if not configengines: | |||||
| attr = 'serverpriority' if role == util.SERVERROLE else 'clientpriority' | |||||
| return [e for e in compengines | |||||
| if getattr(e.wireprotosupport(), attr) > 0] | |||||
| # If compression engines are listed in the config, assume there is a good | |||||
| # reason for it (like server operators wanting to achieve specific | |||||
| # performance characteristics). So fail fast if the config references | |||||
| # unusable compression engines. | |||||
| validnames = set(e.name() for e in compengines) | |||||
| invalidnames = set(e for e in configengines if e not in validnames) | |||||
| if invalidnames: | |||||
| raise error.Abort(_('invalid compression engine defined in %s: %s') % | |||||
| (config, ', '.join(sorted(invalidnames)))) | |||||
| compengines = [e for e in compengines if e.name() in configengines] | |||||
| compengines = sorted(compengines, | |||||
| key=lambda e: configengines.index(e.name())) | |||||
| if not compengines: | |||||
| raise error.Abort(_('%s config option does not specify any known ' | |||||
| 'compression engines') % config, | |||||
| hint=_('usable compression engines: %s') % | |||||
| ', '.sorted(validnames)) | |||||
| return compengines | |||||
| def _capabilitiesv2(repo, proto): | def _capabilitiesv2(repo, proto): | ||||
| """Obtain the set of capabilities for version 2 transports. | """Obtain the set of capabilities for version 2 transports. | ||||
| These capabilities are distinct from the capabilities for version 1 | These capabilities are distinct from the capabilities for version 1 | ||||
| transports. | transports. | ||||
| """ | """ | ||||
| compression = [] | compression = [] | ||||
| for engine in wireproto.supportedcompengines(repo.ui, util.SERVERROLE): | for engine in wireprototypes.supportedcompengines(repo.ui, util.SERVERROLE): | ||||
| compression.append({ | compression.append({ | ||||
| b'name': engine.wireprotosupport().name, | b'name': engine.wireprotosupport().name, | ||||
| }) | }) | ||||
| caps = { | caps = { | ||||
| 'commands': {}, | 'commands': {}, | ||||
| 'compression': compression, | 'compression': compression, | ||||
| 'framingmediatypes': [FRAMINGTYPE], | 'framingmediatypes': [FRAMINGTYPE], | ||||