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], |