annotate mercurial/sshpeer.py @ 37813:58bbd14b0c62 stable

sshpeer: reflect actual command activity one handshake The output from devel-peer-request is expected to give data about request and roundtrip done to the server. Changeset a9cffd14aa04 changed some of that by grouping hello and between commands call. However, the old sequence of command was "emulated" in sshpeer. Update the sshpeer to reflect this grouping of commands and update the tests that use it.
author Boris Feld <boris.feld@octobus.net>
date Mon, 23 Apr 2018 19:23:18 +0100
parents b4d85bc122bd
children 67dc32d4e790
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
17192
1ac628cd7113 peer: introduce real peer classes
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 16688
diff changeset
1 # sshpeer.py - ssh repository proxy class for mercurial
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
2 #
2859
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2740
diff changeset
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
4 #
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8210
diff changeset
5 # 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: 9878
diff changeset
6 # GNU General Public License version 2 or any later version.
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
7
25975
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
8 from __future__ import absolute_import
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
9
15622
86fc364ca5f8 sshrepo: don't quote obviously safe strings (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents: 15581
diff changeset
10 import re
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
11 import uuid
25975
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
12
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
13 from .i18n import _
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
14 from . import (
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
15 error,
33112
05906b8e1d23 py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32062
diff changeset
16 pycompat,
25975
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
17 util,
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
18 wireprotoserver,
36565
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36562
diff changeset
19 wireprototypes,
37614
a81d02ea65db wireproto: move version 1 peer functionality to standalone module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37498
diff changeset
20 wireprotov1peer,
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37717
diff changeset
21 wireprotov1server,
25975
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
22 )
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
23 from .utils import (
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
24 procutil,
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
25 )
60
e32fdbd97839 Add hg:// protocol
mpm@selenic.com
parents: 56
diff changeset
26
15581
d8fa35c28335 ssh: quote remote paths (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents: 15017
diff changeset
27 def _serverquote(s):
35463
b520c8f98e1e sshpeer: move docstring to top
Yuya Nishihara <yuya@tcha.org>
parents: 35440
diff changeset
28 """quote a string for the remote shell ... which we assume is sh"""
23671
e3f30068d2eb sshpeer: more thorough shell quoting
Matt Mackall <mpm@selenic.com>
parents: 22935
diff changeset
29 if not s:
e3f30068d2eb sshpeer: more thorough shell quoting
Matt Mackall <mpm@selenic.com>
parents: 22935
diff changeset
30 return s
15624
be43234a6d60 sshrepo: add more safe characters (issue2983)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 15622
diff changeset
31 if re.match('[a-zA-Z0-9@%_+=:,./-]*$', s):
15622
86fc364ca5f8 sshrepo: don't quote obviously safe strings (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents: 15581
diff changeset
32 return s
15581
d8fa35c28335 ssh: quote remote paths (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents: 15017
diff changeset
33 return "'%s'" % s.replace("'", "'\\''")
d8fa35c28335 ssh: quote remote paths (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents: 15017
diff changeset
34
25244
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
35 def _forwardoutput(ui, pipe):
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
36 """display all data currently available on pipe as remote output.
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
37
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
38 This is non blocking."""
36841
46f4d71ed505 sshpeer: check pipe validity before forwarding output from it
Matt Harbison <matt_harbison@yahoo.com>
parents: 36657
diff changeset
39 if pipe:
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
40 s = procutil.readpipe(pipe)
36841
46f4d71ed505 sshpeer: check pipe validity before forwarding output from it
Matt Harbison <matt_harbison@yahoo.com>
parents: 36657
diff changeset
41 if s:
46f4d71ed505 sshpeer: check pipe validity before forwarding output from it
Matt Harbison <matt_harbison@yahoo.com>
parents: 36657
diff changeset
42 for l in s.splitlines():
46f4d71ed505 sshpeer: check pipe validity before forwarding output from it
Matt Harbison <matt_harbison@yahoo.com>
parents: 36657
diff changeset
43 ui.status(_("remote: "), l, '\n')
25244
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
44
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
45 class doublepipe(object):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
46 """Operate a side-channel pipe in addition of a main one
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
47
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
48 The side-channel pipe contains server output to be forwarded to the user
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
49 input. The double pipe will behave as the "main" pipe, but will ensure the
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
50 content of the "side" pipe is properly processed while we wait for blocking
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
51 call on the "main" pipe.
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
52
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
53 If large amounts of data are read from "main", the forward will cease after
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
54 the first bytes start to appear. This simplifies the implementation
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
55 without affecting actual output of sshpeer too much as we rarely issue
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
56 large read for data not yet emitted by the server.
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
57
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
58 The main pipe is expected to be a 'bufferedinputpipe' from the util module
31953
cc2382b60007 sshpeer: fix docstring typo
Augie Fackler <augie@google.com>
parents: 31207
diff changeset
59 that handle all the os specific bits. This class lives in this module
26781
1aee2ab0f902 spelling: trivial spell checking
Mads Kiilerich <madski@unity3d.com>
parents: 26587
diff changeset
60 because it focus on behavior specific to the ssh protocol."""
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
61
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
62 def __init__(self, ui, main, side):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
63 self._ui = ui
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
64 self._main = main
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
65 self._side = side
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
66
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
67 def _wait(self):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
68 """wait until some data are available on main or side
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
69
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
70 return a pair of boolean (ismainready, issideready)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
71
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
72 (This will only wait for data if the setup is supported by `util.poll`)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
73 """
36400
066e6a9d52bb sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36398
diff changeset
74 if (isinstance(self._main, util.bufferedinputpipe) and
066e6a9d52bb sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36398
diff changeset
75 self._main.hasbuffer):
066e6a9d52bb sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36398
diff changeset
76 # Main has data. Assume side is worth poking at.
066e6a9d52bb sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36398
diff changeset
77 return True, True
066e6a9d52bb sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36398
diff changeset
78
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
79 fds = [self._main.fileno(), self._side.fileno()]
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
80 try:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
81 act = util.poll(fds)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
82 except NotImplementedError:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
83 # non supported yet case, assume all have data.
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
84 act = fds
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
85 return (self._main.fileno() in act, self._side.fileno() in act)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
86
25456
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
87 def write(self, data):
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
88 return self._call('write', data)
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
89
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
90 def read(self, size):
32062
ad6c5497cd15 sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents: 31953
diff changeset
91 r = self._call('read', size)
ad6c5497cd15 sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents: 31953
diff changeset
92 if size != 0 and not r:
ad6c5497cd15 sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents: 31953
diff changeset
93 # We've observed a condition that indicates the
ad6c5497cd15 sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents: 31953
diff changeset
94 # stdout closed unexpectedly. Check stderr one
ad6c5497cd15 sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents: 31953
diff changeset
95 # more time and snag anything that's there before
ad6c5497cd15 sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents: 31953
diff changeset
96 # letting anyone know the main part of the pipe
ad6c5497cd15 sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents: 31953
diff changeset
97 # closed prematurely.
ad6c5497cd15 sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents: 31953
diff changeset
98 _forwardoutput(self._ui, self._side)
ad6c5497cd15 sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents: 31953
diff changeset
99 return r
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
100
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
101 def readline(self):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
102 return self._call('readline')
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
103
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
104 def _call(self, methname, data=None):
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
105 """call <methname> on "main", forward output of "side" while blocking
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
106 """
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
107 # data can be '' or 0
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
108 if (data is not None and not data) or self._main.closed:
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
109 _forwardoutput(self._ui, self._side)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
110 return ''
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
111 while True:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
112 mainready, sideready = self._wait()
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
113 if sideready:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
114 _forwardoutput(self._ui, self._side)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
115 if mainready:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
116 meth = getattr(self._main, methname)
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
117 if data is None:
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
118 return meth()
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
119 else:
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
120 return meth(data)
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
121
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
122 def close(self):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
123 return self._main.close()
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
124
25456
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
125 def flush(self):
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
126 return self._main.flush()
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
127
35973
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
128 def _cleanuppipes(ui, pipei, pipeo, pipee):
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
129 """Clean up pipes used by an SSH connection."""
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
130 if pipeo:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
131 pipeo.close()
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
132 if pipei:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
133 pipei.close()
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
134
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
135 if pipee:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
136 # Try to read from the err descriptor until EOF.
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
137 try:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
138 for l in pipee:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
139 ui.status(_('remote: '), l)
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
140 except (IOError, ValueError):
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
141 pass
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
142
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
143 pipee.close()
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
144
35975
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
145 def _makeconnection(ui, sshcmd, args, remotecmd, path, sshenv=None):
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
146 """Create an SSH connection to a server.
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
147
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
148 Returns a tuple of (process, stdin, stdout, stderr) for the
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
149 spawned process.
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
150 """
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
151 cmd = '%s %s %s' % (
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
152 sshcmd,
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
153 args,
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
154 procutil.shellquote('%s -R %s serve --stdio' % (
35975
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
155 _serverquote(remotecmd), _serverquote(path))))
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
156
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
157 ui.debug('running %s\n' % cmd)
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
158 cmd = procutil.quotecommand(cmd)
35975
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
159
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
160 # no buffer allow the use of 'select'
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
161 # feel free to remove buffering and select usage when we ultimately
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
162 # move to threading.
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
163 stdin, stdout, stderr, proc = procutil.popen4(cmd, bufsize=0, env=sshenv)
35975
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
164
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
165 return proc, stdin, stdout, stderr
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
166
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
167 def _clientcapabilities():
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
168 """Return list of capabilities of this client.
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
169
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
170 Returns a list of capabilities that are supported by this client.
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
171 """
37498
aacfca6f9767 wireproto: support for pullbundles
Joerg Sonnenberger <joerg@bec.de>
parents: 37411
diff changeset
172 protoparams = {'partial-pull'}
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
173 comps = [e.wireprotosupport().name for e in
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
174 util.compengines.supportedwireengines(util.CLIENTROLE)]
37411
3e1688711efd wireproto: turn client capabilities into sets, sorted on the wire
Joerg Sonnenberger <joerg@bec.de>
parents: 37393
diff changeset
175 protoparams.add('comp=%s' % ','.join(comps))
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
176 return protoparams
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
177
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
178 def _performhandshake(ui, stdin, stdout, stderr):
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
179 def badresponse():
36401
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
180 # Flush any output on stderr.
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
181 _forwardoutput(ui, stderr)
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
182
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
183 msg = _('no suitable response from remote hg')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
184 hint = ui.config('ui', 'ssherrorhint')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
185 raise error.RepoError(msg, hint=hint)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
186
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
187 # The handshake consists of sending wire protocol commands in reverse
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
188 # order of protocol implementation and then sniffing for a response
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
189 # to one of them.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
190 #
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
191 # Those commands (from oldest to newest) are:
35979
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
192 #
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
193 # ``between``
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
194 # Asks for the set of revisions between a pair of revisions. Command
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
195 # present in all Mercurial server implementations.
35979
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
196 #
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
197 # ``hello``
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
198 # Instructs the server to advertise its capabilities. Introduced in
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
199 # Mercurial 0.9.1.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
200 #
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
201 # ``upgrade``
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
202 # Requests upgrade from default transport protocol version 1 to
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
203 # a newer version. Introduced in Mercurial 4.6 as an experimental
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
204 # feature.
35979
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
205 #
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
206 # The ``between`` command is issued with a request for the null
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
207 # range. If the remote is a Mercurial server, this request will
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
208 # generate a specific response: ``1\n\n``. This represents the
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
209 # wire protocol encoded value for ``\n``. We look for ``1\n\n``
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
210 # in the output stream and know this is the response to ``between``
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
211 # and we're at the end of our handshake reply.
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
212 #
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
213 # The response to the ``hello`` command will be a line with the
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
214 # length of the value returned by that command followed by that
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
215 # value. If the server doesn't support ``hello`` (which should be
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
216 # rare), that line will be ``0\n``. Otherwise, the value will contain
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
217 # RFC 822 like lines. Of these, the ``capabilities:`` line contains
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
218 # the capabilities of the server.
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
219 #
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
220 # The ``upgrade`` command isn't really a command in the traditional
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
221 # sense of version 1 of the transport because it isn't using the
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
222 # proper mechanism for formatting insteads: instead, it just encodes
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
223 # arguments on the line, delimited by spaces.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
224 #
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
225 # The ``upgrade`` line looks like ``upgrade <token> <capabilities>``.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
226 # If the server doesn't support protocol upgrades, it will reply to
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
227 # this line with ``0\n``. Otherwise, it emits an
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
228 # ``upgraded <token> <protocol>`` line to both stdout and stderr.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
229 # Content immediately following this line describes additional
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
230 # protocol and server state.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
231 #
35979
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
232 # In addition to the responses to our command requests, the server
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
233 # may emit "banner" output on stdout. SSH servers are allowed to
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
234 # print messages to stdout on login. Issuing commands on connection
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
235 # allows us to flush this banner output from the server by scanning
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
236 # for output to our well-known ``between`` command. Of course, if
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
237 # the banner contains ``1\n\n``, this will throw off our detection.
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
238
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
239 requestlog = ui.configbool('devel', 'debug.peer-request')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
240
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
241 # Generate a random token to help identify responses to version 2
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
242 # upgrade request.
36081
223ed0b53f08 py3: more robustly cast UUID to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36017
diff changeset
243 token = pycompat.sysbytes(str(uuid.uuid4()))
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
244 upgradecaps = [
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
245 ('proto', wireprotoserver.SSHV2),
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
246 ]
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
247 upgradecaps = util.urlreq.urlencode(upgradecaps)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
248
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
249 try:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
250 pairsarg = '%s-%s' % ('0' * 40, '0' * 40)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
251 handshake = [
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
252 'hello\n',
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
253 'between\n',
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
254 'pairs %d\n' % len(pairsarg),
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
255 pairsarg,
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
256 ]
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
257
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
258 # Request upgrade to version 2 if configured.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
259 if ui.configbool('experimental', 'sshpeer.advertise-v2'):
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
260 ui.debug('sending upgrade request: %s %s\n' % (token, upgradecaps))
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
261 handshake.insert(0, 'upgrade %s %s\n' % (token, upgradecaps))
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
262
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
263 if requestlog:
37813
58bbd14b0c62 sshpeer: reflect actual command activity one handshake
Boris Feld <boris.feld@octobus.net>
parents: 37785
diff changeset
264 ui.debug('devel-peer-request: hello+between\n')
58bbd14b0c62 sshpeer: reflect actual command activity one handshake
Boris Feld <boris.feld@octobus.net>
parents: 37785
diff changeset
265 ui.debug('devel-peer-request: pairs: %d bytes\n' % len(pairsarg))
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
266 ui.debug('sending hello command\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
267 ui.debug('sending between command\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
268
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
269 stdin.write(''.join(handshake))
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
270 stdin.flush()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
271 except IOError:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
272 badresponse()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
273
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
274 # Assume version 1 of wire protocol by default.
36565
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36562
diff changeset
275 protoname = wireprototypes.SSHV1
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
276 reupgraded = re.compile(b'^upgraded %s (.*)$' % re.escape(token))
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
277
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
278 lines = ['', 'dummy']
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
279 max_noise = 500
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
280 while lines[-1] and max_noise:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
281 try:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
282 l = stdout.readline()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
283 _forwardoutput(ui, stderr)
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
284
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
285 # Look for reply to protocol upgrade request. It has a token
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
286 # in it, so there should be no false positives.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
287 m = reupgraded.match(l)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
288 if m:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
289 protoname = m.group(1)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
290 ui.debug('protocol upgraded to %s\n' % protoname)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
291 # If an upgrade was handled, the ``hello`` and ``between``
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
292 # requests are ignored. The next output belongs to the
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
293 # protocol, so stop scanning lines.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
294 break
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
295
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
296 # Otherwise it could be a banner, ``0\n`` response if server
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
297 # doesn't support upgrade.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
298
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
299 if lines[-1] == '1\n' and l == '\n':
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
300 break
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
301 if l:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
302 ui.debug('remote: ', l)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
303 lines.append(l)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
304 max_noise -= 1
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
305 except IOError:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
306 badresponse()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
307 else:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
308 badresponse()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
309
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
310 caps = set()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
311
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
312 # For version 1, we should see a ``capabilities`` line in response to the
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
313 # ``hello`` command.
36565
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36562
diff changeset
314 if protoname == wireprototypes.SSHV1:
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
315 for l in reversed(lines):
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
316 # Look for response to ``hello`` command. Scan from the back so
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
317 # we don't misinterpret banner output as the command reply.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
318 if l.startswith('capabilities:'):
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
319 caps.update(l[:-1].split(':')[1].split())
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
320 break
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
321 elif protoname == wireprotoserver.SSHV2:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
322 # We see a line with number of bytes to follow and then a value
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
323 # looking like ``capabilities: *``.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
324 line = stdout.readline()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
325 try:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
326 valuelen = int(line)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
327 except ValueError:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
328 badresponse()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
329
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
330 capsline = stdout.read(valuelen)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
331 if not capsline.startswith('capabilities: '):
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
332 badresponse()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
333
36254
7218e93ade47 sshpeer: log remote capabilities after protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36081
diff changeset
334 ui.debug('remote: %s\n' % capsline)
7218e93ade47 sshpeer: log remote capabilities after protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36081
diff changeset
335
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
336 caps.update(capsline.split(':')[1].split())
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
337 # Trailing newline.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
338 stdout.read(1)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
339
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
340 # Error if we couldn't find capabilities, this means:
35980
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35979
diff changeset
341 #
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35979
diff changeset
342 # 1. Remote isn't a Mercurial server
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35979
diff changeset
343 # 2. Remote is a <0.9.1 Mercurial server
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35979
diff changeset
344 # 3. Remote is a future Mercurial server that dropped ``hello``
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
345 # and other attempted handshake mechanisms.
35980
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35979
diff changeset
346 if not caps:
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35979
diff changeset
347 badresponse()
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35979
diff changeset
348
36401
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
349 # Flush any output on stderr before proceeding.
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
350 _forwardoutput(ui, stderr)
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
351
36017
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36016
diff changeset
352 return protoname, caps
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
353
37614
a81d02ea65db wireproto: move version 1 peer functionality to standalone module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37498
diff changeset
354 class sshv1peer(wireprotov1peer.wirepeer):
36562
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
355 def __init__(self, ui, url, proc, stdin, stdout, stderr, caps,
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
356 autoreadstderr=True):
35976
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
357 """Create a peer from an existing SSH connection.
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
358
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
359 ``proc`` is a handle on the underlying SSH process.
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
360 ``stdin``, ``stdout``, and ``stderr`` are handles on the stdio
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
361 pipes for that process.
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
362 ``caps`` is a set of capabilities supported by the remote.
36562
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
363 ``autoreadstderr`` denotes whether to automatically read from
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
364 stderr and to forward its output.
35976
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
365 """
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
366 self._url = url
37321
e826fe7a08c7 peer: make ui an attribute
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37320
diff changeset
367 self.ui = ui
35975
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
368 # self._subprocess is unused. Keeping a handle on the process
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
369 # holds a reference and prevents it from being garbage collected.
35976
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
370 self._subprocess = proc
36401
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
371
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
372 # And we hook up our "doublepipe" wrapper to allow querying
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
373 # stderr any time we perform I/O.
36562
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
374 if autoreadstderr:
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
375 stdout = doublepipe(ui, util.bufferedinputpipe(stdout), stderr)
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
376 stdin = doublepipe(ui, stdin, stderr)
36401
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
377
35976
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
378 self._pipeo = stdin
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
379 self._pipei = stdout
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
380 self._pipee = stderr
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
381 self._caps = caps
36637
1151c731686e sshpeer: don't read from stderr when that behavior is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36565
diff changeset
382 self._autoreadstderr = autoreadstderr
2549
e1831f06eef1 Added ability to clone from a local repository to a (new) remote one.
Sean Meiners <sean.meiners@linspire.com>
parents: 2484
diff changeset
383
36398
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
384 # Commands that have a "framed" response where the first line of the
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
385 # response contains the length of that response.
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
386 _FRAMED_COMMANDS = {
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
387 'batch',
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
388 }
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
389
37320
39f7d4ee8bcd repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37123
diff changeset
390 # Begin of ipeerconnection interface.
33825
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
391
2673
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
392 def url(self):
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
393 return self._url
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
394
33825
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
395 def local(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
396 return None
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
397
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
398 def peer(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
399 return self
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
400
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
401 def canpush(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
402 return True
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
403
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
404 def close(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
405 pass
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
406
37320
39f7d4ee8bcd repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37123
diff changeset
407 # End of ipeerconnection interface.
33825
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
408
37320
39f7d4ee8bcd repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37123
diff changeset
409 # Begin of ipeercommands interface.
33825
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
410
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
411 def capabilities(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
412 return self._caps
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
413
37320
39f7d4ee8bcd repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37123
diff changeset
414 # End of ipeercommands interface.
33825
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
415
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
416 def _readerr(self):
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
417 _forwardoutput(self.ui, self._pipee)
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
418
11586
ddaaaa23bb8f protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents: 11369
diff changeset
419 def _abort(self, exception):
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
420 self._cleanup()
11586
ddaaaa23bb8f protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents: 11369
diff changeset
421 raise exception
ddaaaa23bb8f protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents: 11369
diff changeset
422
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
423 def _cleanup(self):
35973
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
424 _cleanuppipes(self.ui, self._pipei, self._pipeo, self._pipee)
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
425
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
426 __del__ = _cleanup
3034
2b0bc36a48d8 sshrepo: flush stderr before connecting to the hg server
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2859
diff changeset
427
36398
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
428 def _sendrequest(self, cmd, args, framed=False):
35699
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
429 if (self.ui.debugflag
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
430 and self.ui.configbool('devel', 'debug.peer-request')):
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
431 dbg = self.ui.debug
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
432 line = 'devel-peer-request: %s\n'
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
433 dbg(line % cmd)
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
434 for key, value in sorted(args.items()):
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
435 if not isinstance(value, dict):
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
436 dbg(line % ' %s: %d bytes' % (key, len(value)))
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
437 else:
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
438 for dk, dv in sorted(value.items()):
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
439 dbg(line % ' %s-%s: %d' % (key, dk, len(dv)))
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 8563
diff changeset
440 self.ui.debug("sending %s command\n" % cmd)
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
441 self._pipeo.write("%s\n" % cmd)
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37717
diff changeset
442 _func, names = wireprotov1server.commands[cmd]
13721
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
443 keys = names.split()
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
444 wireargs = {}
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
445 for k in keys:
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
446 if k == '*':
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
447 wireargs['*'] = args
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
448 break
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
449 else:
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
450 wireargs[k] = args[k]
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
451 del args[k]
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
452 for k, v in sorted(wireargs.iteritems()):
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
453 self._pipeo.write("%s %d\n" % (k, len(v)))
13721
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
454 if isinstance(v, dict):
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
455 for dk, dv in v.iteritems():
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
456 self._pipeo.write("%s %d\n" % (dk, len(dv)))
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
457 self._pipeo.write(dv)
13721
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
458 else:
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
459 self._pipeo.write(v)
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
460 self._pipeo.flush()
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
461
36398
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
462 # We know exactly how many bytes are in the response. So return a proxy
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
463 # around the raw output stream that allows reading exactly this many
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
464 # bytes. Callers then can read() without fear of overrunning the
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
465 # response.
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
466 if framed:
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
467 amount = self._getamount()
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
468 return util.cappedreader(self._pipei, amount)
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
469
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
470 return self._pipei
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
471
36397
a34d5ef53c2e sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36396
diff changeset
472 def _callstream(self, cmd, **args):
a34d5ef53c2e sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36396
diff changeset
473 args = pycompat.byteskwargs(args)
36398
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
474 return self._sendrequest(cmd, args, framed=cmd in self._FRAMED_COMMANDS)
36397
a34d5ef53c2e sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36396
diff changeset
475
20905
167047ba3cfa wireproto: drop the _decompress method in favor a new call type
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20794
diff changeset
476 def _callcompressable(self, cmd, **args):
36397
a34d5ef53c2e sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36396
diff changeset
477 args = pycompat.byteskwargs(args)
36398
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
478 return self._sendrequest(cmd, args, framed=cmd in self._FRAMED_COMMANDS)
20905
167047ba3cfa wireproto: drop the _decompress method in favor a new call type
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20794
diff changeset
479
11589
e8d22fe2ddab protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents: 11588
diff changeset
480 def _call(self, cmd, **args):
36397
a34d5ef53c2e sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36396
diff changeset
481 args = pycompat.byteskwargs(args)
36398
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
482 return self._sendrequest(cmd, args, framed=True).read()
5978
7939c71f3132 sshrepo: be more careful while reading data
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5293
diff changeset
483
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
484 def _callpush(self, cmd, fp, **args):
36403
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
485 # The server responds with an empty frame if the client should
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
486 # continue submitting the payload.
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
487 r = self._call(cmd, **args)
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
488 if r:
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
489 return '', r
36403
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
490
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
491 # The payload consists of frames with content followed by an empty
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
492 # frame.
29739
0dbd788a2dfd sshpeer: use `iter(callable, sentinel)` instead of while True
Augie Fackler <augie@google.com>
parents: 29389
diff changeset
493 for d in iter(lambda: fp.read(4096), ''):
36396
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36254
diff changeset
494 self._writeframed(d)
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36254
diff changeset
495 self._writeframed("", flush=True)
36403
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
496
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
497 # In case of success, there is an empty frame and a frame containing
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
498 # the integer result (as a string).
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
499 # In case of error, there is a non-empty frame containing the error.
36396
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36254
diff changeset
500 r = self._readframed()
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
501 if r:
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
502 return '', r
36396
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36254
diff changeset
503 return self._readframed(), ''
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
504
21073
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
505 def _calltwowaystream(self, cmd, fp, **args):
36403
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
506 # The server responds with an empty frame if the client should
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
507 # continue submitting the payload.
21073
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
508 r = self._call(cmd, **args)
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
509 if r:
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
510 # XXX needs to be made better
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 28438
diff changeset
511 raise error.Abort(_('unexpected remote reply: %s') % r)
36403
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
512
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
513 # The payload consists of frames with content followed by an empty
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
514 # frame.
29739
0dbd788a2dfd sshpeer: use `iter(callable, sentinel)` instead of while True
Augie Fackler <augie@google.com>
parents: 29389
diff changeset
515 for d in iter(lambda: fp.read(4096), ''):
36396
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36254
diff changeset
516 self._writeframed(d)
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36254
diff changeset
517 self._writeframed("", flush=True)
36403
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
518
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
519 return self._pipei
11591
0d9cb3f3b0a1 protocol: unify client changegroup methods
Matt Mackall <mpm@selenic.com>
parents: 11590
diff changeset
520
28438
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
521 def _getamount(self):
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
522 l = self._pipei.readline()
15017
f4522df38c65 wireproto: add out-of-band error class to allow remote repo to report errors
Andrew Pritchard <andrewp@fogcreek.com>
parents: 14537
diff changeset
523 if l == '\n':
36637
1151c731686e sshpeer: don't read from stderr when that behavior is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36565
diff changeset
524 if self._autoreadstderr:
1151c731686e sshpeer: don't read from stderr when that behavior is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36565
diff changeset
525 self._readerr()
25243
d65243d28749 sshpeer: break "OutOfBandError" feature for ssh (BC)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23684
diff changeset
526 msg = _('check previous remote output')
d65243d28749 sshpeer: break "OutOfBandError" feature for ssh (BC)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23684
diff changeset
527 self._abort(error.OutOfBandError(hint=msg))
36637
1151c731686e sshpeer: don't read from stderr when that behavior is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36565
diff changeset
528 if self._autoreadstderr:
1151c731686e sshpeer: don't read from stderr when that behavior is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36565
diff changeset
529 self._readerr()
646
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
530 try:
28438
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
531 return int(l)
14004
97ed99d1f419 eliminate various naked except clauses
Idan Kamara <idankk86@gmail.com>
parents: 13827
diff changeset
532 except ValueError:
11590
0b15aee0a306 protocol: convert some ssh abort calls
Matt Mackall <mpm@selenic.com>
parents: 11589
diff changeset
533 self._abort(error.ResponseError(_("unexpected response:"), l))
28438
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
534
36396
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36254
diff changeset
535 def _readframed(self):
36657
70415568ea65 sshpeer: don't read(0)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36637
diff changeset
536 size = self._getamount()
70415568ea65 sshpeer: don't read(0)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36637
diff changeset
537 if not size:
70415568ea65 sshpeer: don't read(0)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36637
diff changeset
538 return b''
70415568ea65 sshpeer: don't read(0)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36637
diff changeset
539
70415568ea65 sshpeer: don't read(0)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36637
diff changeset
540 return self._pipei.read(size)
5978
7939c71f3132 sshrepo: be more careful while reading data
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5293
diff changeset
541
36396
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36254
diff changeset
542 def _writeframed(self, data, flush=False):
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
543 self._pipeo.write("%d\n" % len(data))
5978
7939c71f3132 sshrepo: be more careful while reading data
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5293
diff changeset
544 if data:
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
545 self._pipeo.write(data)
5978
7939c71f3132 sshrepo: be more careful while reading data
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5293
diff changeset
546 if flush:
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
547 self._pipeo.flush()
36637
1151c731686e sshpeer: don't read from stderr when that behavior is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36565
diff changeset
548 if self._autoreadstderr:
1151c731686e sshpeer: don't read from stderr when that behavior is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36565
diff changeset
549 self._readerr()
2612
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2549
diff changeset
550
36017
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36016
diff changeset
551 class sshv2peer(sshv1peer):
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36016
diff changeset
552 """A peer that speakers version 2 of the transport protocol."""
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36016
diff changeset
553 # Currently version 2 is identical to version 1 post handshake.
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36016
diff changeset
554 # And handshake is performed before the peer is instantiated. So
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36016
diff changeset
555 # we need no custom code.
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36016
diff changeset
556
36562
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
557 def makepeer(ui, path, proc, stdin, stdout, stderr, autoreadstderr=True):
36517
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
558 """Make a peer instance from existing pipes.
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
559
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
560 ``path`` and ``proc`` are stored on the eventual peer instance and may
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
561 not be used for anything meaningful.
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
562
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
563 ``stdin``, ``stdout``, and ``stderr`` are the pipes connected to the
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
564 SSH server's stdio handles.
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
565
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
566 This function is factored out to allow creating peers that don't
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
567 actually spawn a new process. It is useful for starting SSH protocol
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
568 servers and clients via non-standard means, which can be useful for
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
569 testing.
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
570 """
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
571 try:
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
572 protoname, caps = _performhandshake(ui, stdin, stdout, stderr)
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
573 except Exception:
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
574 _cleanuppipes(ui, stdout, stdin, stderr)
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
575 raise
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
576
36565
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36562
diff changeset
577 if protoname == wireprototypes.SSHV1:
36562
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
578 return sshv1peer(ui, path, proc, stdin, stdout, stderr, caps,
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
579 autoreadstderr=autoreadstderr)
36565
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36562
diff changeset
580 elif protoname == wireprototypes.SSHV2:
36562
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
581 return sshv2peer(ui, path, proc, stdin, stdout, stderr, caps,
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
582 autoreadstderr=autoreadstderr)
36517
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
583 else:
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
584 _cleanuppipes(ui, stdout, stdin, stderr)
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
585 raise error.RepoError(_('unknown version of SSH protocol: %s') %
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
586 protoname)
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
587
37717
0664be4f0c1f hg: pass command intents to repo/peer creation (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37614
diff changeset
588 def instance(ui, path, create, intents=None):
35971
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
589 """Create an SSH peer.
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
590
37614
a81d02ea65db wireproto: move version 1 peer functionality to standalone module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37498
diff changeset
591 The returned object conforms to the ``wireprotov1peer.wirepeer`` interface.
35971
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
592 """
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
593 u = util.url(path, parsequery=False, parsefragment=False)
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
594 if u.scheme != 'ssh' or not u.host or u.path is None:
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
595 raise error.RepoError(_("couldn't parse location %s") % path)
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
596
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
597 util.checksafessh(path)
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
598
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
599 if u.passwd is not None:
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
600 raise error.RepoError(_('password in URL not supported'))
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
601
35972
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
602 sshcmd = ui.config('ui', 'ssh')
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
603 remotecmd = ui.config('ui', 'remotecmd')
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
604 sshaddenv = dict(ui.configitems('sshenv'))
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
605 sshenv = procutil.shellenviron(sshaddenv)
35972
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
606 remotepath = u.path or '.'
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
607
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
608 args = procutil.sshargs(sshcmd, u.host, u.user, u.port)
35972
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
609
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
610 if create:
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
611 cmd = '%s %s %s' % (sshcmd, args,
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
612 procutil.shellquote('%s init %s' %
35972
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
613 (_serverquote(remotecmd), _serverquote(remotepath))))
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
614 ui.debug('running %s\n' % cmd)
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
615 res = ui.system(cmd, blockedtag='sshpeer', environ=sshenv)
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
616 if res != 0:
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
617 raise error.RepoError(_('could not create remote repo'))
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
618
35975
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
619 proc, stdin, stdout, stderr = _makeconnection(ui, sshcmd, args, remotecmd,
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
620 remotepath, sshenv)
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
621
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
622 peer = makepeer(ui, path, proc, stdin, stdout, stderr)
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
623
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
624 # Finally, if supported by the server, notify it about our own
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
625 # capabilities.
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
626 if 'protocaps' in peer.capabilities():
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
627 try:
37411
3e1688711efd wireproto: turn client capabilities into sets, sorted on the wire
Joerg Sonnenberger <joerg@bec.de>
parents: 37393
diff changeset
628 peer._call("protocaps",
3e1688711efd wireproto: turn client capabilities into sets, sorted on the wire
Joerg Sonnenberger <joerg@bec.de>
parents: 37393
diff changeset
629 caps=' '.join(sorted(_clientcapabilities())))
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
630 except IOError:
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
631 peer._cleanup()
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
632 raise error.RepoError(_('capability exchange failed'))
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
633
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
634 return peer