bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
|
2018.5.19
by Andrew Bennetts
Add docstrings to all the new modules, and a few other places. |
1 |
# Copyright (C) 2006 Canonical Ltd
|
2 |
#
|
|
3 |
# This program is free software; you can redistribute it and/or modify
|
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
5 |
# the Free Software Foundation; either version 2 of the License, or
|
|
6 |
# (at your option) any later version.
|
|
7 |
#
|
|
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
#
|
|
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
15 |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
16 |
||
17 |
"""Smart-server protocol, client and server.
|
|
18 |
||
19 |
This code is fairly complex, so it has been split up into a package of modules,
|
|
20 |
rather than being a single large module. Refer to the individual module
|
|
21 |
docstrings for details.
|
|
22 |
||
23 |
Overview
|
|
24 |
========
|
|
25 |
||
|
2432.2.8
by Andrew Bennetts
NEWS entry, greatly improved docstring in bzrlib.smart. |
26 |
The smart protocol provides a way to send a requests and corresponding
|
27 |
responses to communicate with a remote bzr process.
|
|
28 |
||
29 |
Layering
|
|
30 |
========
|
|
31 |
||
32 |
Medium
|
|
33 |
------
|
|
34 |
||
35 |
At the bottom level there is either a socket, pipes, or an HTTP
|
|
36 |
request/response. We call this layer the *medium*. It is responsible for
|
|
37 |
carrying bytes between a client and server. For sockets, we have the
|
|
38 |
idea that you have multiple requests and get a read error because the other side
|
|
39 |
did shutdown. For pipes we have read pipe which will have a zero read which
|
|
40 |
marks end-of-file. For HTTP server environment there is no end-of-stream
|
|
41 |
because each request coming into the server is independent.
|
|
|
2018.5.19
by Andrew Bennetts
Add docstrings to all the new modules, and a few other places. |
42 |
|
43 |
So we need a wrapper around pipes and sockets to seperate out requests from
|
|
|
2432.2.8
by Andrew Bennetts
NEWS entry, greatly improved docstring in bzrlib.smart. |
44 |
substrate and this will give us a single model which is consistent for HTTP,
|
|
2018.5.19
by Andrew Bennetts
Add docstrings to all the new modules, and a few other places. |
45 |
sockets and pipes.
|
46 |
||
|
2432.2.8
by Andrew Bennetts
NEWS entry, greatly improved docstring in bzrlib.smart. |
47 |
Protocol
|
48 |
--------
|
|
49 |
||
50 |
On top of the medium is the *protocol*. This is the layer that deserialises
|
|
51 |
bytes into the structured data that requests and responses consist of.
|
|
52 |
||
53 |
Version one of the protocol (for requests and responses) is described by::
|
|
54 |
||
55 |
REQUEST := MESSAGE_V1
|
|
56 |
RESPONSE := MESSAGE_V1
|
|
57 |
MESSAGE_V1 := ARGS BODY
|
|
58 |
||
59 |
ARGS := ARG [MORE_ARGS] NEWLINE
|
|
60 |
MORE_ARGS := SEP ARG [MORE_ARGS]
|
|
61 |
SEP := 0x01
|
|
62 |
||
63 |
BODY := LENGTH NEWLINE BODY_BYTES TRAILER
|
|
64 |
LENGTH := decimal integer
|
|
65 |
TRAILER := "done" NEWLINE
|
|
66 |
||
67 |
That is, a tuple of arguments separated by Ctrl-A and terminated with a newline,
|
|
68 |
followed by length prefixed body with a constant trailer. Note that although
|
|
69 |
arguments are not 8-bit safe (they cannot include 0x01 or 0x0a bytes without
|
|
70 |
breaking the protocol encoding), the body is.
|
|
71 |
||
72 |
Version two of the request protocol is::
|
|
73 |
||
74 |
REQUEST_V2 := "bzr request 2" NEWLINE MESSAGE_V1
|
|
75 |
||
76 |
Version two of the response protocol is::
|
|
77 |
||
78 |
RESPONSE_V2 := "bzr request 2" NEWLINE MESSAGE_V1
|
|
79 |
||
80 |
Future versions should follow this structure, like version two does::
|
|
81 |
||
82 |
FUTURE_MESSAGE := VERSION_STRING NEWLINE REST_OF_MESSAGE
|
|
83 |
||
84 |
This is that clients and servers can read bytes up to the first newline byte to
|
|
85 |
determine what version a message is.
|
|
86 |
||
|
2432.2.9
by Andrew Bennetts
Update protocol versioning docs to explain how unknown request versions should be handled. |
87 |
For compatibility will all versions (past and future) of bzr clients, servers
|
88 |
that receive a request in an unknown protocol version should respond with a
|
|
89 |
single-line error terminated with 0x0a (NEWLINE), rather than structured
|
|
90 |
response prefixed with a version string.
|
|
91 |
||
|
2432.2.8
by Andrew Bennetts
NEWS entry, greatly improved docstring in bzrlib.smart. |
92 |
Request/Response processing
|
93 |
---------------------------
|
|
94 |
||
95 |
On top of the protocol is the logic for processing requests (on the server) or
|
|
96 |
responses (on the client).
|
|
97 |
||
|
2018.5.19
by Andrew Bennetts
Add docstrings to all the new modules, and a few other places. |
98 |
Server-side
|
99 |
-----------
|
|
100 |
||
|
2432.2.8
by Andrew Bennetts
NEWS entry, greatly improved docstring in bzrlib.smart. |
101 |
Sketch::
|
102 |
||
|
2018.5.19
by Andrew Bennetts
Add docstrings to all the new modules, and a few other places. |
103 |
MEDIUM (factory for protocol, reads bytes & pushes to protocol,
|
104 |
uses protocol to detect end-of-request, sends written
|
|
105 |
bytes to client) e.g. socket, pipe, HTTP request handler.
|
|
106 |
^
|
|
107 |
| bytes.
|
|
108 |
v
|
|
109 |
||
|
2432.2.8
by Andrew Bennetts
NEWS entry, greatly improved docstring in bzrlib.smart. |
110 |
PROTOCOL(serialization, deserialization) accepts bytes for one
|
|
2018.5.19
by Andrew Bennetts
Add docstrings to all the new modules, and a few other places. |
111 |
request, decodes according to internal state, pushes
|
112 |
structured data to handler. accepts structured data from
|
|
113 |
handler and encodes and writes to the medium. factory for
|
|
114 |
handler.
|
|
115 |
^
|
|
116 |
| structured data
|
|
117 |
v
|
|
118 |
||
|
2432.2.8
by Andrew Bennetts
NEWS entry, greatly improved docstring in bzrlib.smart. |
119 |
HANDLER (domain logic) accepts structured data, operates state
|
|
2018.5.19
by Andrew Bennetts
Add docstrings to all the new modules, and a few other places. |
120 |
machine until the request can be satisfied,
|
121 |
sends structured data to the protocol.
|
|
122 |
||
|
2432.2.8
by Andrew Bennetts
NEWS entry, greatly improved docstring in bzrlib.smart. |
123 |
Request handlers are registered in `bzrlib.smart.request`.
|
124 |
||
|
2018.5.19
by Andrew Bennetts
Add docstrings to all the new modules, and a few other places. |
125 |
|
126 |
Client-side
|
|
127 |
-----------
|
|
128 |
||
|
2432.2.8
by Andrew Bennetts
NEWS entry, greatly improved docstring in bzrlib.smart. |
129 |
Sketch::
|
130 |
||
131 |
CLIENT domain logic, accepts domain requests, generated structured
|
|
132 |
data, reads structured data from responses and turns into
|
|
133 |
domain data. Sends structured data to the protocol.
|
|
134 |
Operates state machines until the request can be delivered
|
|
135 |
(e.g. reading from a bundle generated in bzrlib to deliver a
|
|
136 |
complete request).
|
|
137 |
||
138 |
Possibly this should just be RemoteBzrDir, RemoteTransport,
|
|
139 |
...
|
|
|
2018.5.19
by Andrew Bennetts
Add docstrings to all the new modules, and a few other places. |
140 |
^
|
141 |
| structured data
|
|
142 |
v
|
|
143 |
||
144 |
PROTOCOL (serialization, deserialization) accepts structured data for one
|
|
145 |
request, encodes and writes to the medium. Reads bytes from the
|
|
146 |
medium, decodes and allows the client to read structured data.
|
|
147 |
^
|
|
148 |
| bytes.
|
|
149 |
v
|
|
150 |
||
151 |
MEDIUM (accepts bytes from the protocol & delivers to the remote server.
|
|
152 |
Allows the potocol to read bytes e.g. socket, pipe, HTTP request.
|
|
|
2432.2.8
by Andrew Bennetts
NEWS entry, greatly improved docstring in bzrlib.smart. |
153 |
|
154 |
The domain logic is in `bzrlib.remote`: `RemoteBzrDir`, `RemoteBranch`, and so
|
|
155 |
on.
|
|
156 |
||
157 |
There is also an plain file-level transport that calls remote methods to
|
|
158 |
manipulate files on the server in `bzrlib.transport.remote`.
|
|
159 |
||
160 |
Paths
|
|
161 |
=====
|
|
162 |
||
163 |
Paths are passed across the network. The client needs to see a namespace that
|
|
164 |
includes any repository that might need to be referenced, and the client needs
|
|
165 |
to know about a root directory beyond which it cannot ascend.
|
|
166 |
||
167 |
Servers run over ssh will typically want to be able to access any path the user
|
|
168 |
can access. Public servers on the other hand (which might be over http, ssh
|
|
169 |
or tcp) will typically want to restrict access to only a particular directory
|
|
170 |
and its children, so will want to do a software virtual root at that level.
|
|
171 |
In other words they'll want to rewrite incoming paths to be under that level
|
|
172 |
(and prevent escaping using ../ tricks.)
|
|
173 |
||
174 |
URLs that include ~ should probably be passed across to the server verbatim
|
|
175 |
and the server can expand them. This will proably not be meaningful when
|
|
176 |
limited to a directory?
|
|
|
2018.5.19
by Andrew Bennetts
Add docstrings to all the new modules, and a few other places. |
177 |
"""
|
178 |
||
179 |
# TODO: _translate_error should be on the client, not the transport because
|
|
180 |
# error coding is wire protocol specific.
|
|
181 |
||
182 |
# TODO: A plain integer from query_version is too simple; should give some
|
|
183 |
# capabilities too?
|
|
184 |
||
185 |
# TODO: Server should probably catch exceptions within itself and send them
|
|
186 |
# back across the network. (But shouldn't catch KeyboardInterrupt etc)
|
|
187 |
# Also needs to somehow report protocol errors like bad requests. Need to
|
|
188 |
# consider how we'll handle error reporting, e.g. if we get halfway through a
|
|
189 |
# bulk transfer and then something goes wrong.
|
|
190 |
||
191 |
# TODO: Make each request and response self-validatable, e.g. with checksums.
|
|
192 |
#
|
|
193 |
# TODO: get/put objects could be changed to gradually read back the data as it
|
|
194 |
# comes across the network
|
|
195 |
#
|
|
196 |
# TODO: What should the server do if it hits an error and has to terminate?
|
|
197 |
#
|
|
198 |
# TODO: is it useful to allow multiple chunks in the bulk data?
|
|
199 |
#
|
|
200 |
# TODO: If we get an exception during transmission of bulk data we can't just
|
|
201 |
# emit the exception because it won't be seen.
|
|
202 |
# John proposes: I think it would be worthwhile to have a header on each
|
|
203 |
# chunk, that indicates it is another chunk. Then you can send an 'error'
|
|
204 |
# chunk as long as you finish the previous chunk.
|
|
205 |
#
|
|
206 |
# TODO: Clone method on Transport; should work up towards parent directory;
|
|
207 |
# unclear how this should be stored or communicated to the server... maybe
|
|
208 |
# just pass it on all relevant requests?
|
|
209 |
#
|
|
210 |
# TODO: Better name than clone() for changing between directories. How about
|
|
211 |
# open_dir or change_dir or chdir?
|
|
212 |
#
|
|
213 |
# TODO: Is it really good to have the notion of current directory within the
|
|
214 |
# connection? Perhaps all Transports should factor out a common connection
|
|
215 |
# from the thing that has the directory context?
|
|
216 |
#
|
|
217 |
# TODO: The server that manages a connection should be quite small and retain
|
|
218 |
# minimum state because each of the requests are supposed to be stateless.
|
|
219 |
# Then we can write another implementation that maps to http.
|
|
220 |
#
|
|
221 |
# TODO: What to do when a client connection is garbage collected? Maybe just
|
|
222 |
# abruptly drop the connection?
|
|
223 |
#
|
|
224 |
# TODO: Server in some cases will need to restrict access to files outside of
|
|
225 |
# a particular root directory. LocalTransport doesn't do anything to stop you
|
|
226 |
# ascending above the base directory, so we need to prevent paths
|
|
227 |
# containing '..' in either the server or transport layers. (Also need to
|
|
228 |
# consider what happens if someone creates a symlink pointing outside the
|
|
229 |
# directory tree...)
|
|
230 |
#
|
|
231 |
# TODO: Server should rebase absolute paths coming across the network to put
|
|
232 |
# them under the virtual root, if one is in use. LocalTransport currently
|
|
233 |
# doesn't do that; if you give it an absolute path it just uses it.
|
|
234 |
#
|
|
235 |
# XXX: Arguments can't contain newlines or ascii; possibly we should e.g.
|
|
236 |
# urlescape them instead. Indeed possibly this should just literally be
|
|
237 |
# http-over-ssh.
|
|
238 |
#
|
|
239 |
# TODO: Probably want some way for server commands to gradually produce body
|
|
240 |
# data rather than passing it as a string; they could perhaps pass an
|
|
241 |
# iterator-like callback that will gradually yield data; it probably needs a
|
|
242 |
# close() method that will always be closed to do any necessary cleanup.
|
|
243 |
||
244 |
||
245 |
# Promote some attributes from submodules into this namespace
|
|
|
2018.5.21
by Andrew Bennetts
Move bzrlib.transport.smart to bzrlib.smart |
246 |
from bzrlib.smart.request import SmartServerRequestHandler |
|
2018.5.19
by Andrew Bennetts
Add docstrings to all the new modules, and a few other places. |
247 |
|
|
2018.5.14
by Andrew Bennetts
Move SmartTCPServer to smart/server.py, and SmartServerRequestHandler to smart/request.py. |
248 |