To avoid a cycle between modules in an upcoming commit.
Details
Details
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Lint
Automatic diff as part of commit; lint not applicable. - Unit
Automatic diff as part of commit; unit tests not applicable.
To avoid a cycle between modules in an upcoming commit.
Automatic diff as part of commit; lint not applicable. |
Automatic diff as part of commit; unit tests not applicable. |
Path | Packages | |||
---|---|---|---|---|
M | mercurial/sshpeer.py (9 lines) | |||
M | mercurial/wireprotoserver.py (11 lines) | |||
M | mercurial/wireprototypes.py (6 lines) |
Status | Author | Revision | |
---|---|---|---|
Abandoned | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Abandoned | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg |
from .i18n import _ | from .i18n import _ | ||||
from . import ( | from . import ( | ||||
error, | error, | ||||
pycompat, | pycompat, | ||||
util, | util, | ||||
wireproto, | wireproto, | ||||
wireprotoserver, | wireprotoserver, | ||||
wireprototypes, | |||||
) | ) | ||||
def _serverquote(s): | def _serverquote(s): | ||||
"""quote a string for the remote shell ... which we assume is sh""" | """quote a string for the remote shell ... which we assume is sh""" | ||||
if not s: | if not s: | ||||
return s | return s | ||||
if re.match('[a-zA-Z0-9@%_+=:,./-]*$', s): | if re.match('[a-zA-Z0-9@%_+=:,./-]*$', s): | ||||
return s | return s | ||||
ui.debug('sending between command\n') | ui.debug('sending between command\n') | ||||
stdin.write(''.join(handshake)) | stdin.write(''.join(handshake)) | ||||
stdin.flush() | stdin.flush() | ||||
except IOError: | except IOError: | ||||
badresponse() | badresponse() | ||||
# Assume version 1 of wire protocol by default. | # Assume version 1 of wire protocol by default. | ||||
protoname = wireprotoserver.SSHV1 | protoname = wireprototypes.SSHV1 | ||||
reupgraded = re.compile(b'^upgraded %s (.*)$' % re.escape(token)) | reupgraded = re.compile(b'^upgraded %s (.*)$' % re.escape(token)) | ||||
lines = ['', 'dummy'] | lines = ['', 'dummy'] | ||||
max_noise = 500 | max_noise = 500 | ||||
while lines[-1] and max_noise: | while lines[-1] and max_noise: | ||||
try: | try: | ||||
l = stdout.readline() | l = stdout.readline() | ||||
_forwardoutput(ui, stderr) | _forwardoutput(ui, stderr) | ||||
badresponse() | badresponse() | ||||
else: | else: | ||||
badresponse() | badresponse() | ||||
caps = set() | caps = set() | ||||
# For version 1, we should see a ``capabilities`` line in response to the | # For version 1, we should see a ``capabilities`` line in response to the | ||||
# ``hello`` command. | # ``hello`` command. | ||||
if protoname == wireprotoserver.SSHV1: | if protoname == wireprototypes.SSHV1: | ||||
for l in reversed(lines): | for l in reversed(lines): | ||||
# Look for response to ``hello`` command. Scan from the back so | # Look for response to ``hello`` command. Scan from the back so | ||||
# we don't misinterpret banner output as the command reply. | # we don't misinterpret banner output as the command reply. | ||||
if l.startswith('capabilities:'): | if l.startswith('capabilities:'): | ||||
caps.update(l[:-1].split(':')[1].split()) | caps.update(l[:-1].split(':')[1].split()) | ||||
break | break | ||||
elif protoname == wireprotoserver.SSHV2: | elif protoname == wireprotoserver.SSHV2: | ||||
# We see a line with number of bytes to follow and then a value | # We see a line with number of bytes to follow and then a value | ||||
testing. | testing. | ||||
""" | """ | ||||
try: | try: | ||||
protoname, caps = _performhandshake(ui, stdin, stdout, stderr) | protoname, caps = _performhandshake(ui, stdin, stdout, stderr) | ||||
except Exception: | except Exception: | ||||
_cleanuppipes(ui, stdout, stdin, stderr) | _cleanuppipes(ui, stdout, stdin, stderr) | ||||
raise | raise | ||||
if protoname == wireprotoserver.SSHV1: | if protoname == wireprototypes.SSHV1: | ||||
return sshv1peer(ui, path, proc, stdin, stdout, stderr, caps, | return sshv1peer(ui, path, proc, stdin, stdout, stderr, caps, | ||||
autoreadstderr=autoreadstderr) | autoreadstderr=autoreadstderr) | ||||
elif protoname == wireprotoserver.SSHV2: | elif protoname == wireprototypes.SSHV2: | ||||
return sshv2peer(ui, path, proc, stdin, stdout, stderr, caps, | return sshv2peer(ui, path, proc, stdin, stdout, stderr, caps, | ||||
autoreadstderr=autoreadstderr) | autoreadstderr=autoreadstderr) | ||||
else: | else: | ||||
_cleanuppipes(ui, stdout, stdin, stderr) | _cleanuppipes(ui, stdout, stdin, stderr) | ||||
raise error.RepoError(_('unknown version of SSH protocol: %s') % | raise error.RepoError(_('unknown version of SSH protocol: %s') % | ||||
protoname) | protoname) | ||||
def instance(ui, path, create): | def instance(ui, path, create): |
urlreq = util.urlreq | urlreq = util.urlreq | ||||
HTTP_OK = 200 | HTTP_OK = 200 | ||||
HGTYPE = 'application/mercurial-0.1' | HGTYPE = 'application/mercurial-0.1' | ||||
HGTYPE2 = 'application/mercurial-0.2' | HGTYPE2 = 'application/mercurial-0.2' | ||||
HGERRTYPE = 'application/hg-error' | HGERRTYPE = 'application/hg-error' | ||||
# Names of the SSH protocol implementations. | SSHV1 = wireprototypes.SSHV1 | ||||
SSHV1 = 'ssh-v1' | SSHV2 = wireprototypes.SSHV2 | ||||
# This is advertised over the wire. Incremental the counter at the end | |||||
# to reflect BC breakages. | |||||
SSHV2 = 'exp-ssh-v2-0001' | |||||
def decodevaluefromheaders(req, headerprefix): | def decodevaluefromheaders(req, headerprefix): | ||||
"""Decode a long value from multiple HTTP request headers. | """Decode a long value from multiple HTTP request headers. | ||||
Returns the value as a bytes, not a str. | Returns the value as a bytes, not a str. | ||||
""" | """ | ||||
chunks = [] | chunks = [] | ||||
i = 1 | i = 1 | ||||
"""Handler for requests services via version 1 of SSH protocol.""" | """Handler for requests services via version 1 of SSH protocol.""" | ||||
def __init__(self, ui, fin, fout): | def __init__(self, ui, fin, fout): | ||||
self._ui = ui | self._ui = ui | ||||
self._fin = fin | self._fin = fin | ||||
self._fout = fout | self._fout = fout | ||||
@property | @property | ||||
def name(self): | def name(self): | ||||
return SSHV1 | return wireprototypes.SSHV1 | ||||
def getargs(self, args): | def getargs(self, args): | ||||
data = {} | data = {} | ||||
keys = args.split() | keys = args.split() | ||||
for n in xrange(len(keys)): | for n in xrange(len(keys)): | ||||
argline = self._fin.readline()[:-1] | argline = self._fin.readline()[:-1] | ||||
arg, l = argline.split() | arg, l = argline.split() | ||||
if arg not in keys: | if arg not in keys: | ||||
elif state == 'protov2-serving': | elif state == 'protov2-serving': | ||||
state = 'protov1-serving' | state = 'protov1-serving' | ||||
continue | continue | ||||
elif state == 'upgrade-initial': | elif state == 'upgrade-initial': | ||||
# We should never transition into this state if we've switched | # We should never transition into this state if we've switched | ||||
# protocols. | # protocols. | ||||
assert not protoswitched | assert not protoswitched | ||||
assert proto.name == SSHV1 | assert proto.name == wireprototypes.SSHV1 | ||||
# Expected: upgrade <token> <capabilities> | # Expected: upgrade <token> <capabilities> | ||||
# If we get something else, the request is malformed. It could be | # If we get something else, the request is malformed. It could be | ||||
# from a future client that has altered the upgrade line content. | # from a future client that has altered the upgrade line content. | ||||
# We treat this as an unknown command. | # We treat this as an unknown command. | ||||
try: | try: | ||||
token, caps = request.split(b' ')[1:] | token, caps = request.split(b' ')[1:] | ||||
except ValueError: | except ValueError: |
# 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 | ||||
import abc | import abc | ||||
# Names of the SSH protocol implementations. | |||||
SSHV1 = 'ssh-v1' | |||||
# This is advertised over the wire. Incremental the counter at the end | |||||
# to reflect BC breakages. | |||||
SSHV2 = 'exp-ssh-v2-0001' | |||||
class bytesresponse(object): | class bytesresponse(object): | ||||
"""A wire protocol response consisting of raw bytes.""" | """A wire protocol response consisting of raw bytes.""" | ||||
def __init__(self, data): | def __init__(self, data): | ||||
self.data = data | self.data = data | ||||
class ooberror(object): | class ooberror(object): | ||||
"""wireproto reply: failure of a batch of operation | """wireproto reply: failure of a batch of operation | ||||