From patchwork Mon Feb 5 17:15:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: D2035: sshpeer: document the handshake mechanism From: phabricator X-Patchwork-Id: 27334 Message-Id: To: mercurial-devel@mercurial-scm.org Date: Mon, 5 Feb 2018 17:15:51 +0000 indygreg updated this revision to Diff 5230. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2035?vs=5193&id=5230 REVISION DETAIL https://phab.mercurial-scm.org/D2035 AFFECTED FILES mercurial/sshpeer.py CHANGE DETAILS To: indygreg, #hg-reviewers, lothiraldan Cc: mercurial-devel diff --git a/mercurial/sshpeer.py b/mercurial/sshpeer.py --- a/mercurial/sshpeer.py +++ b/mercurial/sshpeer.py @@ -163,6 +163,37 @@ hint = ui.config('ui', 'ssherrorhint') raise error.RepoError(msg, hint=hint) + # The handshake consists of sending 2 wire protocol commands: + # ``hello`` and ``between``. + # + # The ``hello`` command (which was introduced in Mercurial 0.9.1) + # instructs the server to advertise its capabilities. + # + # The ``between`` command (which has existed in all Mercurial servers + # for as long as SSH support has existed), asks for the set of revisions + # between a pair of revisions. + # + # The ``between`` command is issued with a request for the null + # range. If the remote is a Mercurial server, this request will + # generate a specific response: ``1\n\n``. This represents the + # wire protocol encoded value for ``\n``. We look for ``1\n\n`` + # in the output stream and know this is the response to ``between`` + # and we're at the end of our handshake reply. + # + # The response to the ``hello`` command will be a line with the + # length of the value returned by that command followed by that + # value. If the server doesn't support ``hello`` (which should be + # rare), that line will be ``0\n``. Otherwise, the value will contain + # RFC 822 like lines. Of these, the ``capabilities:`` line contains + # the capabilities of the server. + # + # In addition to the responses to our command requests, the server + # may emit "banner" output on stdout. SSH servers are allowed to + # print messages to stdout on login. Issuing commands on connection + # allows us to flush this banner output from the server by scanning + # for output to our well-known ``between`` command. Of course, if + # the banner contains ``1\n\n``, this will throw off our detection. + requestlog = ui.configbool('devel', 'debug.peer-request') try: @@ -206,6 +237,8 @@ caps = set() for l in reversed(lines): + # Look for response to ``hello`` command. Scan from the back so + # we don't misinterpret banner output as the command reply. if l.startswith('capabilities:'): caps.update(l[:-1].split(':')[1].split()) break