annotate mercurial/sshpeer.py @ 37318:9954d0e2ad00

py3: use pycompat.bytestr() intsead of str Differential Revision: https://phab.mercurial-scm.org/D3071
author Pulkit Goyal <7895pulkit@gmail.com>
date Mon, 02 Apr 2018 17:06:42 +0530
parents a8a902d7176e
children 39f7d4ee8bcd
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,
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
18 wireproto,
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
19 wireprotoserver,
36565
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36562
diff changeset
20 wireprototypes,
25975
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
21 )
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
22 from .utils import (
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
23 procutil,
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
24 )
60
e32fdbd97839 Add hg:// protocol
mpm@selenic.com
parents: 56
diff changeset
25
15581
d8fa35c28335 ssh: quote remote paths (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents: 15017
diff changeset
26 def _serverquote(s):
35463
b520c8f98e1e sshpeer: move docstring to top
Yuya Nishihara <yuya@tcha.org>
parents: 35440
diff changeset
27 """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
28 if not s:
e3f30068d2eb sshpeer: more thorough shell quoting
Matt Mackall <mpm@selenic.com>
parents: 22935
diff changeset
29 return s
15624
be43234a6d60 sshrepo: add more safe characters (issue2983)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 15622
diff changeset
30 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
31 return s
15581
d8fa35c28335 ssh: quote remote paths (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents: 15017
diff changeset
32 return "'%s'" % s.replace("'", "'\\''")
d8fa35c28335 ssh: quote remote paths (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents: 15017
diff changeset
33
25244
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
34 def _forwardoutput(ui, pipe):
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
35 """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
36
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
37 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
38 if pipe:
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
39 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
40 if s:
46f4d71ed505 sshpeer: check pipe validity before forwarding output from it
Matt Harbison <matt_harbison@yahoo.com>
parents: 36657
diff changeset
41 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
42 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
43
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
44 class doublepipe(object):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
45 """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
46
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
47 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
48 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
49 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
50 call on the "main" pipe.
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
51
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
52 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
53 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
54 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
55 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
56
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
57 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
58 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
59 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
60
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
61 def __init__(self, ui, main, side):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
62 self._ui = ui
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
63 self._main = main
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
64 self._side = side
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
65
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
66 def _wait(self):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
67 """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
68
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
69 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
70
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
71 (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
72 """
36400
066e6a9d52bb sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36398
diff changeset
73 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
74 self._main.hasbuffer):
066e6a9d52bb sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36398
diff changeset
75 # 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
76 return True, True
066e6a9d52bb sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36398
diff changeset
77
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
78 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
79 try:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
80 act = util.poll(fds)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
81 except NotImplementedError:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
82 # 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
83 act = fds
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
84 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
85
25456
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
86 def write(self, data):
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
87 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
88
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
89 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
90 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
91 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
92 # 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
93 # 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
94 # 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
95 # 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
96 # closed prematurely.
ad6c5497cd15 sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents: 31953
diff changeset
97 _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
98 return r
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
99
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
100 def readline(self):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
101 return self._call('readline')
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
102
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
103 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
104 """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
105 """
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
106 # 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
107 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
108 _forwardoutput(self._ui, self._side)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
109 return ''
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
110 while True:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
111 mainready, sideready = self._wait()
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
112 if sideready:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
113 _forwardoutput(self._ui, self._side)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
114 if mainready:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
115 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
116 if data is None:
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
117 return meth()
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
118 else:
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
119 return meth(data)
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
120
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
121 def close(self):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
122 return self._main.close()
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
123
25456
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
124 def flush(self):
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
125 return self._main.flush()
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
126
35973
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
127 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
128 """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
129 if pipeo:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
130 pipeo.close()
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
131 if pipei:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
132 pipei.close()
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
133
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
134 if pipee:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
135 # 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
136 try:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
137 for l in pipee:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
138 ui.status(_('remote: '), l)
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
139 except (IOError, ValueError):
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
140 pass
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
141
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
142 pipee.close()
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
143
35975
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
144 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
145 """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
146
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
147 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
148 spawned process.
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
149 """
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
150 cmd = '%s %s %s' % (
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
151 sshcmd,
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
152 args,
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
153 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
154 _serverquote(remotecmd), _serverquote(path))))
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
155
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
156 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
157 cmd = procutil.quotecommand(cmd)
35975
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
158
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
159 # 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
160 # 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
161 # move to threading.
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
162 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
163
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
164 return proc, stdin, stdout, stderr
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
165
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
166 def _performhandshake(ui, stdin, stdout, stderr):
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
167 def badresponse():
36401
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
168 # Flush any output on stderr.
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
169 _forwardoutput(ui, stderr)
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
170
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
171 msg = _('no suitable response from remote hg')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
172 hint = ui.config('ui', 'ssherrorhint')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
173 raise error.RepoError(msg, hint=hint)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
174
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
175 # 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
176 # 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
177 # to one of them.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
178 #
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
179 # Those commands (from oldest to newest) are:
35979
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
180 #
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
181 # ``between``
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
182 # 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
183 # present in all Mercurial server implementations.
35979
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
184 #
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
185 # ``hello``
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
186 # 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
187 # Mercurial 0.9.1.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
188 #
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
189 # ``upgrade``
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
190 # 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
191 # 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
192 # feature.
35979
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
193 #
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
194 # 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
195 # 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
196 # 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
197 # 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
198 # 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
199 # 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
200 #
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
201 # 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
202 # 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
203 # 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
204 # 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
205 # 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
206 # the capabilities of the server.
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
207 #
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
208 # 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
209 # 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
210 # 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
211 # 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
212 #
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
213 # 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
214 # 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
215 # 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
216 # ``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
217 # 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
218 # protocol and server state.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
219 #
35979
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
220 # 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
221 # 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
222 # 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
223 # 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
224 # 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
225 # 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
226
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
227 requestlog = ui.configbool('devel', 'debug.peer-request')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
228
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
229 # 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
230 # upgrade request.
36081
223ed0b53f08 py3: more robustly cast UUID to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36017
diff changeset
231 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
232 upgradecaps = [
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
233 ('proto', wireprotoserver.SSHV2),
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
234 ]
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
235 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
236
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
237 try:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
238 pairsarg = '%s-%s' % ('0' * 40, '0' * 40)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
239 handshake = [
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
240 'hello\n',
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
241 'between\n',
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
242 'pairs %d\n' % len(pairsarg),
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
243 pairsarg,
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
244 ]
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
245
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
246 # 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
247 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
248 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
249 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
250
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
251 if requestlog:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
252 ui.debug('devel-peer-request: hello\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
253 ui.debug('sending hello command\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
254 if requestlog:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
255 ui.debug('devel-peer-request: between\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
256 ui.debug('devel-peer-request: pairs: %d bytes\n' % len(pairsarg))
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
257 ui.debug('sending between command\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
258
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
259 stdin.write(''.join(handshake))
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
260 stdin.flush()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
261 except IOError:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
262 badresponse()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
263
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
264 # 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
265 protoname = wireprototypes.SSHV1
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
266 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
267
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
268 lines = ['', 'dummy']
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
269 max_noise = 500
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
270 while lines[-1] and max_noise:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
271 try:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
272 l = stdout.readline()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
273 _forwardoutput(ui, stderr)
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
274
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
275 # 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
276 # 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
277 m = reupgraded.match(l)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
278 if m:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
279 protoname = m.group(1)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
280 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
281 # 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
282 # 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
283 # 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
284 break
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
285
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
286 # 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
287 # doesn't support upgrade.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
288
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
289 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
290 break
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
291 if l:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
292 ui.debug('remote: ', l)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
293 lines.append(l)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
294 max_noise -= 1
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
295 except IOError:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
296 badresponse()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
297 else:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
298 badresponse()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
299
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
300 caps = set()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
301
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
302 # 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
303 # ``hello`` command.
36565
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36562
diff changeset
304 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
305 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
306 # 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
307 # 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
308 if l.startswith('capabilities:'):
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
309 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
310 break
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
311 elif protoname == wireprotoserver.SSHV2:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
312 # 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
313 # looking like ``capabilities: *``.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
314 line = stdout.readline()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
315 try:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
316 valuelen = int(line)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
317 except ValueError:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
318 badresponse()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
319
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
320 capsline = stdout.read(valuelen)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
321 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
322 badresponse()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
323
36254
7218e93ade47 sshpeer: log remote capabilities after protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36081
diff changeset
324 ui.debug('remote: %s\n' % capsline)
7218e93ade47 sshpeer: log remote capabilities after protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36081
diff changeset
325
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
326 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
327 # Trailing newline.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
328 stdout.read(1)
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 # 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
331 #
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35979
diff changeset
332 # 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
333 # 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
334 # 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
335 # 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
336 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
337 badresponse()
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35979
diff changeset
338
36401
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
339 # 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
340 _forwardoutput(ui, stderr)
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
341
36017
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36016
diff changeset
342 return protoname, caps
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
343
36016
625038cb4b1d sshpeer: rename sshpeer class to sshv1peer (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36015
diff changeset
344 class sshv1peer(wireproto.wirepeer):
36562
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
345 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
346 autoreadstderr=True):
35976
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
347 """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
348
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
349 ``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
350 ``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
351 pipes for that process.
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
352 ``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
353 ``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
354 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
355 """
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
356 self._url = url
33825
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
357 self._ui = ui
35975
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
358 # 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
359 # 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
360 self._subprocess = proc
36401
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
361
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36400
diff changeset
362 # 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
363 # 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
364 if autoreadstderr:
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
365 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
366 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
367
35976
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
368 self._pipeo = stdin
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
369 self._pipei = stdout
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
370 self._pipee = stderr
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
371 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
372 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
373
36398
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
374 # 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
375 # 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
376 _FRAMED_COMMANDS = {
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
377 'batch',
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
378 }
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
379
33825
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
380 # Begin of _basepeer interface.
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
381
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
382 @util.propertycache
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
383 def ui(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
384 return self._ui
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
385
2673
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
386 def url(self):
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
387 return self._url
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
388
33825
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
389 def local(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
390 return None
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
391
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
392 def peer(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
393 return self
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
394
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
395 def canpush(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
396 return True
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 close(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
399 pass
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 # End of _basepeer interface.
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
402
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
403 # Begin of _basewirecommands interface.
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
404
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
405 def capabilities(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
406 return self._caps
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
407
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
408 # End of _basewirecommands interface.
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
409
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
410 def _readerr(self):
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
411 _forwardoutput(self.ui, self._pipee)
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
412
11586
ddaaaa23bb8f protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents: 11369
diff changeset
413 def _abort(self, exception):
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
414 self._cleanup()
11586
ddaaaa23bb8f protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents: 11369
diff changeset
415 raise exception
ddaaaa23bb8f protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents: 11369
diff changeset
416
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
417 def _cleanup(self):
35973
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
418 _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
419
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
420 __del__ = _cleanup
3034
2b0bc36a48d8 sshrepo: flush stderr before connecting to the hg server
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2859
diff changeset
421
36398
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
422 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
423 if (self.ui.debugflag
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
424 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
425 dbg = self.ui.debug
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
426 line = 'devel-peer-request: %s\n'
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
427 dbg(line % cmd)
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
428 for key, value in sorted(args.items()):
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
429 if not isinstance(value, dict):
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
430 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
431 else:
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
432 for dk, dv in sorted(value.items()):
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
433 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
434 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
435 self._pipeo.write("%s\n" % cmd)
13721
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
436 _func, names = wireproto.commands[cmd]
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
437 keys = names.split()
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
438 wireargs = {}
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
439 for k in keys:
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
440 if k == '*':
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
441 wireargs['*'] = args
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
442 break
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
443 else:
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
444 wireargs[k] = args[k]
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
445 del args[k]
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
446 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
447 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
448 if isinstance(v, dict):
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
449 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
450 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
451 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
452 else:
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
453 self._pipeo.write(v)
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
454 self._pipeo.flush()
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
455
36398
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
456 # 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
457 # 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
458 # 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
459 # response.
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
460 if framed:
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
461 amount = self._getamount()
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
462 return util.cappedreader(self._pipei, amount)
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
463
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
464 return self._pipei
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
465
36397
a34d5ef53c2e sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36396
diff changeset
466 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
467 args = pycompat.byteskwargs(args)
36398
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
468 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
469
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
470 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
471 args = pycompat.byteskwargs(args)
36398
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
472 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
473
11589
e8d22fe2ddab protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents: 11588
diff changeset
474 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
475 args = pycompat.byteskwargs(args)
36398
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36397
diff changeset
476 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
477
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
478 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
479 # 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
480 # continue submitting the payload.
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
481 r = self._call(cmd, **args)
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
482 if r:
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
483 return '', r
36403
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
484
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
485 # 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
486 # frame.
29739
0dbd788a2dfd sshpeer: use `iter(callable, sentinel)` instead of while True
Augie Fackler <augie@google.com>
parents: 29389
diff changeset
487 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
488 self._writeframed(d)
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36254
diff changeset
489 self._writeframed("", flush=True)
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 # 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
492 # 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
493 # 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
494 r = self._readframed()
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
495 if r:
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
496 return '', r
36396
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36254
diff changeset
497 return self._readframed(), ''
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
498
21073
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
499 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
500 # 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
501 # continue submitting the payload.
21073
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
502 r = self._call(cmd, **args)
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
503 if r:
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
504 # XXX needs to be made better
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 28438
diff changeset
505 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
506
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
507 # 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
508 # frame.
29739
0dbd788a2dfd sshpeer: use `iter(callable, sentinel)` instead of while True
Augie Fackler <augie@google.com>
parents: 29389
diff changeset
509 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
510 self._writeframed(d)
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36254
diff changeset
511 self._writeframed("", flush=True)
36403
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36401
diff changeset
512
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
513 return self._pipei
11591
0d9cb3f3b0a1 protocol: unify client changegroup methods
Matt Mackall <mpm@selenic.com>
parents: 11590
diff changeset
514
28438
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
515 def _getamount(self):
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
516 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
517 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
518 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
519 self._readerr()
25243
d65243d28749 sshpeer: break "OutOfBandError" feature for ssh (BC)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23684
diff changeset
520 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
521 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
522 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
523 self._readerr()
646
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
524 try:
28438
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
525 return int(l)
14004
97ed99d1f419 eliminate various naked except clauses
Idan Kamara <idankk86@gmail.com>
parents: 13827
diff changeset
526 except ValueError:
11590
0b15aee0a306 protocol: convert some ssh abort calls
Matt Mackall <mpm@selenic.com>
parents: 11589
diff changeset
527 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
528
36396
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36254
diff changeset
529 def _readframed(self):
36657
70415568ea65 sshpeer: don't read(0)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36637
diff changeset
530 size = self._getamount()
70415568ea65 sshpeer: don't read(0)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36637
diff changeset
531 if not size:
70415568ea65 sshpeer: don't read(0)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36637
diff changeset
532 return b''
70415568ea65 sshpeer: don't read(0)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36637
diff changeset
533
70415568ea65 sshpeer: don't read(0)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36637
diff changeset
534 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
535
36396
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36254
diff changeset
536 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
537 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
538 if data:
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
539 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
540 if flush:
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
541 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
542 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
543 self._readerr()
2612
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2549
diff changeset
544
36017
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36016
diff changeset
545 class sshv2peer(sshv1peer):
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36016
diff changeset
546 """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
547 # 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
548 # 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
549 # 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
550
36562
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
551 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
552 """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
553
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
554 ``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
555 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
556
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
557 ``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
558 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
559
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
560 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
561 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
562 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
563 testing.
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
564 """
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
565 try:
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
566 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
567 except Exception:
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
568 _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
569 raise
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
570
36565
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36562
diff changeset
571 if protoname == wireprototypes.SSHV1:
36562
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
572 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
573 autoreadstderr=autoreadstderr)
36565
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36562
diff changeset
574 elif protoname == wireprototypes.SSHV2:
36562
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36517
diff changeset
575 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
576 autoreadstderr=autoreadstderr)
36517
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
577 else:
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
578 _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
579 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
580 protoname)
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
581
35968
b0d2885c5945 sshpeer: make "instance" a function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35699
diff changeset
582 def instance(ui, path, create):
35971
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
583 """Create an SSH peer.
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
584
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
585 The returned object conforms to the ``wireproto.wirepeer`` interface.
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
586 """
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
587 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
588 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
589 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
590
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
591 util.checksafessh(path)
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 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
594 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
595
35972
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
596 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
597 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
598 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
599 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
600 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
601
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
602 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
603
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
604 if create:
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
605 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
606 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
607 (_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
608 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
609 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
610 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
611 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
612
35975
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
613 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
614 remotepath, sshenv)
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
615
36517
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36403
diff changeset
616 return makepeer(ui, path, proc, stdin, stdout, stderr)