annotate tests/sshprotoext.py @ 36065:bf676267f64f

wireprotoserver: split ssh protocol handler and server We want to formalize the interface for protocol handlers. Today, server functionality (which is domain specific) is interleaved with protocol handling functionality (which conforms to a generic interface) in the sshserver class. This commit splits the ssh protocol handling code out of the sshserver class. Differential Revision: https://phab.mercurial-scm.org/D2080
author Gregory Szorc <gregory.szorc@gmail.com>
date Wed, 07 Feb 2018 20:17:05 -0800
parents 5767664d39a5
children 2f7290555c96
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
35930
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
1 # sshprotoext.py - Extension to test behavior of SSH protocol
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
2 #
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
3 # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com>
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
4 #
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
5 # This software may be used and distributed according to the terms of the
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
6 # GNU General Public License version 2 or any later version.
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
7
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
8 # This extension replaces the SSH server started via `hg serve --stdio`.
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
9 # The server behaves differently depending on environment variables.
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
10
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
11 from __future__ import absolute_import
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
12
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
13 from mercurial import (
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
14 error,
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
15 extensions,
35930
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
16 registrar,
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
17 sshpeer,
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
18 wireproto,
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
19 wireprotoserver,
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
20 )
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
21
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
22 configtable = {}
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
23 configitem = registrar.configitem(configtable)
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
24
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
25 configitem('sshpeer', 'mode', default=None)
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
26 configitem('sshpeer', 'handshake-mode', default=None)
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
27
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
28 class bannerserver(wireprotoserver.sshserver):
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
29 """Server that sends a banner to stdout."""
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
30 def serve_forever(self):
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
31 for i in range(10):
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
32 self._fout.write(b'banner: line %d\n' % i)
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
33
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
34 super(bannerserver, self).serve_forever()
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
35
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
36 class prehelloserver(wireprotoserver.sshserver):
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
37 """Tests behavior when connecting to <0.9.1 servers.
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
38
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
39 The ``hello`` wire protocol command was introduced in Mercurial
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
40 0.9.1. Modern clients send the ``hello`` command when connecting
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
41 to SSH servers. This mock server tests behavior of the handshake
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
42 when ``hello`` is not supported.
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
43 """
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
44 def serve_forever(self):
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
45 l = self._fin.readline()
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
46 assert l == b'hello\n'
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
47 # Respond to unknown commands with an empty reply.
36064
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35976
diff changeset
48 wireprotoserver._sshv1respondbytes(self._fout, b'')
35930
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
49 l = self._fin.readline()
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
50 assert l == b'between\n'
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
51 rsp = wireproto.dispatch(self._repo, self._proto, b'between')
36064
5767664d39a5 wireprotoserver: extract SSH response handling functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35976
diff changeset
52 wireprotoserver._sshv1respondbytes(self._fout, rsp)
35930
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
53
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
54 super(prehelloserver, self).serve_forever()
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
55
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
56 class upgradev2server(wireprotoserver.sshserver):
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
57 """Tests behavior for clients that issue upgrade to version 2."""
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
58 def serve_forever(self):
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
59 name = wireprotoserver.SSHV2
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
60 l = self._fin.readline()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
61 assert l.startswith(b'upgrade ')
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
62 token, caps = l[:-1].split(b' ')[1:]
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
63 assert caps == b'proto=%s' % name
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
64
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
65 # Filter hello and between requests.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
66 l = self._fin.readline()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
67 assert l == b'hello\n'
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
68 l = self._fin.readline()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
69 assert l == b'between\n'
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
70 l = self._fin.readline()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
71 assert l == 'pairs 81\n'
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
72 self._fin.read(81)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
73
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
74 # Send the upgrade response.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
75 self._fout.write(b'upgraded %s %s\n' % (token, name))
36065
bf676267f64f wireprotoserver: split ssh protocol handler and server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36064
diff changeset
76 servercaps = wireproto.capabilities(self._repo, self._proto)
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
77 rsp = b'capabilities: %s' % servercaps
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
78 self._fout.write(b'%d\n' % len(rsp))
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
79 self._fout.write(rsp)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
80 self._fout.write(b'\n')
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
81 self._fout.flush()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
82
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
83 super(upgradev2server, self).serve_forever()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
84
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
85 def performhandshake(orig, ui, stdin, stdout, stderr):
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
86 """Wrapped version of sshpeer._performhandshake to send extra commands."""
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
87 mode = ui.config(b'sshpeer', b'handshake-mode')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
88 if mode == b'pre-no-args':
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
89 ui.debug(b'sending no-args command\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
90 stdin.write(b'no-args\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
91 stdin.flush()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
92 return orig(ui, stdin, stdout, stderr)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
93 elif mode == b'pre-multiple-no-args':
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
94 ui.debug(b'sending unknown1 command\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
95 stdin.write(b'unknown1\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
96 ui.debug(b'sending unknown2 command\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
97 stdin.write(b'unknown2\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
98 ui.debug(b'sending unknown3 command\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
99 stdin.write(b'unknown3\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
100 stdin.flush()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
101 return orig(ui, stdin, stdout, stderr)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
102 else:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
103 raise error.ProgrammingError(b'unknown HANDSHAKECOMMANDMODE: %s' %
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
104 mode)
35930
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
105
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
106 def extsetup(ui):
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
107 # It's easier for tests to define the server behavior via environment
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
108 # variables than config options. This is because `hg serve --stdio`
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
109 # has to be invoked with a certain form for security reasons and
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
110 # `dummyssh` can't just add `--config` flags to the command line.
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
111 servermode = ui.environ.get(b'SSHSERVERMODE')
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
112
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
113 if servermode == b'banner':
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
114 wireprotoserver.sshserver = bannerserver
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
115 elif servermode == b'no-hello':
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
116 wireprotoserver.sshserver = prehelloserver
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
117 elif servermode == b'upgradev2':
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
118 wireprotoserver.sshserver = upgradev2server
35930
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
119 elif servermode:
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
120 raise error.ProgrammingError(b'unknown server mode: %s' % servermode)
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
121
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
122 peermode = ui.config(b'sshpeer', b'mode')
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
123
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
124 if peermode == b'extra-handshake-commands':
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
125 extensions.wrapfunction(sshpeer, '_performhandshake', performhandshake)
35930
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
126 elif peermode:
83d67257ba90 tests: add low-level SSH protocol tests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
127 raise error.ProgrammingError(b'unknown peer mode: %s' % peermode)