[MERGE][RFC] Add doc/developers/network-protocol.txt to describe the HPSS protocol; streaming body extension to HPSS protocol.

Andrew Bennetts andrew at canonical.com
Mon Sep 3 06:22:37 BST 2007


This bundle adds a doc/developers/network-protocol.txt file.  It is basically
what used to be in the docstring of bzrlib/smart/__init__.py, but this seems
like a more useful location for it.

I've also rearranged it slightly from the version in the docstring to have what
I hope is a slightly better structure.

The other big part is I've extended it to describe the streamed body protocol
I've been working on.  This will allow sending large results over the protocol
without knowing the full length in advance, which for some operations is very
difficult to do without buffering everything in memory.  It's somewhat backwards
compatible with the existing version 2 protocol, in that new request methods
only known to new clients and servers with streaming support will work without
breaking anything, i.e. old clients won't see streaming bodies, because they
never send requests that trigger them, so they won't be affected.

Comments welcome.

-Andrew.

-------------- next part --------------
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: andrew.bennetts at canonical.com-20070903051138-\
#   ikak86wb238gk1da
# target_branch: http://bazaar-vcs.org/bzr/bzr.dev
# testament_sha1: 19cdaab8a58d50a8b5eae8318e2ec990fef007a7
# timestamp: 2007-09-03 15:15:27 +1000
# source_branch: http://people.ubuntu.com/~andrew/bzr/hpss-protocol-\
#   docs
# base_revision_id: pqm at pqm.ubuntu.com-20070902233606-wb062d366w5c83uc
# 
# Begin patch
=== added file 'doc/developers/network-protocol.txt'
--- doc/developers/network-protocol.txt	1970-01-01 00:00:00 +0000
+++ doc/developers/network-protocol.txt	2007-09-03 05:11:38 +0000
@@ -0,0 +1,223 @@
+================
+Network Protocol
+================
+
+:Date: 2007-09-03
+
+
+.. contents::
+
+
+Overview
+========
+
+The smart protocol provides a way to send a requests and corresponding
+responses to communicate with a remote bzr process.
+
+Layering
+========
+
+Medium
+------
+
+At the bottom level there is either a socket, pipes, or an HTTP
+request/response.  We call this layer the *medium*.  It is responsible for
+carrying bytes between a client and server.  For sockets, we have the idea
+that you have multiple requests and get a read error because the other
+side did shutdown.  For pipes we have read pipe which will have a zero
+read which marks end-of-file.  For HTTP server environment there is no
+end-of-stream because each request coming into the server is independent.
+
+So we need a wrapper around pipes and sockets to seperate out requests
+from substrate and this will give us a single model which is consistent
+for HTTP, sockets and pipes.
+
+Protocol
+--------
+
+On top of the medium is the *protocol*.  This is the layer that
+deserialises bytes into the structured data that requests and responses
+consist of.
+
+Request/Response processing
+---------------------------
+
+On top of the protocol is the logic for processing requests (on the
+server) or responses (on the client).
+
+Server-side
+-----------
+
+Sketch::
+
+ MEDIUM  (factory for protocol, reads bytes & pushes to protocol,
+          uses protocol to detect end-of-request, sends written
+          bytes to client) e.g. socket, pipe, HTTP request handler.
+  ^
+  | bytes.
+  v
+
+ PROTOCOL(serialization, deserialization)  accepts bytes for one
+          request, decodes according to internal state, pushes
+          structured data to handler.  accepts structured data from
+          handler and encodes and writes to the medium.  factory for
+          handler.
+  ^
+  | structured data
+  v
+
+ HANDLER  (domain logic) accepts structured data, operates state
+          machine until the request can be satisfied,
+          sends structured data to the protocol.
+
+Request handlers are registered in the `bzrlib.smart.request` module.
+
+
+Client-side
+-----------
+
+Sketch::
+
+ CLIENT   domain logic, accepts domain requests, generated structured
+          data, reads structured data from responses and turns into
+          domain data.  Sends structured data to the protocol.
+          Operates state machines until the request can be delivered
+          (e.g. reading from a bundle generated in bzrlib to deliver a
+          complete request).
+
+          Possibly this should just be RemoteBzrDir, RemoteTransport,
+          ...
+  ^
+  | structured data
+  v
+
+ PROTOCOL  (serialization, deserialization)  accepts structured data for one
+          request, encodes and writes to the medium.  Reads bytes from the
+          medium, decodes and allows the client to read structured data.
+  ^
+  | bytes.
+  v
+
+ MEDIUM  (accepts bytes from the protocol & delivers to the remote server.
+          Allows the potocol to read bytes e.g. socket, pipe, HTTP request.
+
+The domain logic is in `bzrlib.remote`: `RemoteBzrDir`, `RemoteBranch`,
+and so on.
+
+There is also an plain file-level transport that calls remote methods to
+manipulate files on the server in `bzrlib.transport.remote`.
+
+Protocol description
+====================
+
+Version one
+-----------
+
+Version one of the protocol (for requests and responses) is described by::
+
+  REQUEST := MESSAGE_V1
+  RESPONSE := MESSAGE_V1
+  MESSAGE_V1 := ARGS BODY
+
+  ARGS := ARG [MORE_ARGS] NEWLINE
+  MORE_ARGS := SEP ARG [MORE_ARGS]
+  SEP := 0x01
+
+  BODY := LENGTH NEWLINE BODY_BYTES TRAILER
+  LENGTH := decimal integer
+  TRAILER := "done" NEWLINE
+
+That is, a tuple of arguments separated by Ctrl-A and terminated with a
+newline, followed by length prefixed body with a constant trailer.  Note
+that although arguments are not 8-bit safe (they cannot include 0x01 or
+0x0a bytes without breaking the protocol encoding), the body is.
+
+Version two
+-----------
+
+Version two of the request protocol is::
+
+  REQUEST_V2 := "bzr request 2" NEWLINE MESSAGE_V2
+
+Version two of the response protocol is::
+
+  RESPONSE_V2 := "bzr request 2" NEWLINE MESSAGE_V2
+
+Future versions should follow this structure, like version two does::
+
+  FUTURE_MESSAGE := VERSION_STRING NEWLINE REST_OF_MESSAGE
+
+This is so that clients and servers can read bytes up to the first newline
+byte to determine what version a message is.
+
+For compatibility will all versions (past and future) of bzr clients,
+servers that receive a request in an unknown protocol version should
+respond with a single-line error terminated with 0x0a (NEWLINE), rather
+than structured response prefixed with a version string.
+
+Version two of the message protocol is::
+
+  MESSAGE_V2 := ARGS BODY
+  BODY_V2 := BODY | STREAMED_BODY
+
+That is, a version one length-prefixed body, or a version two streamed
+body.
+
+A streamed body looks a lot like HTTP's chunked encoding::
+ 
+  STREAMED_BODY := "chunked" NEWLINE CHUNKS TERMINATOR
+  CHUNKS := CHUNK [CHUNKS]
+  CHUNK := CHUNK_LENGTH CHUNK_CONTENT
+  CHUNK_LENGTH := HEX_DIGITS NEWLINE
+  CHUNK_CONTENT := bytes
+  
+  TERMINATOR := SUCCESS_TERMINATOR | ERROR_TERMINATOR
+  SUCCESS_TERMINATOR := 'END' NEWLINE
+  ERROR_TERMINATOR := 'ERR' NEWLINE CHUNKS SUCCESS_TERMINATOR
+
+That is, the body consists of a series of chunks.  Each chunk starts with
+a length prefix in hexadecimal digits, followed by an ASCII newline byte.
+The end of the body is signaled by 'END\\n', or by 'ERR\\n' followed by
+error args, one per chunk.  Note that this allows an 8-bit clean error
+response.
+
+A streamed body starts with the string "chunked" so that legacy clients
+and servers will not mistake the first chunk as the start of a version one
+body.
+
+Software versions
+-----------------
+
+Version 1 of the protocol was introduced in Bazaar 0.11.
+
+Version 2 was introduced in Bazaar 0.16.
+
+
+Paths
+=====
+
+Paths are passed across the network.  The client needs to see a namespace
+that includes any repository that might need to be referenced, and the
+client needs to know about a root directory beyond which it cannot ascend.
+
+Servers run over ssh will typically want to be able to access any path the
+user can access.  Public servers on the other hand (which might be over
+http, ssh or tcp) will typically want to restrict access to only a
+particular directory and its children, so will want to do a software
+virtual root at that level.  In other words they'll want to rewrite
+incoming paths to be under that level (and prevent escaping using ../
+tricks.)
+
+URLs that include ~ should probably be passed across to the server
+verbatim and the server can expand them.  This will proably not be
+meaningful when limited to a directory?
+
+
+Requests
+========
+
+The available request methods are registered in `bzrlib.smart.request`.
+
+..
+   vim: ft=rst tw=74 ai
+

=== modified file 'bzrlib/smart/__init__.py'
--- bzrlib/smart/__init__.py	2007-04-26 04:32:44 +0000
+++ bzrlib/smart/__init__.py	2007-09-03 04:43:27 +0000
@@ -20,160 +20,17 @@
 rather than being a single large module.  Refer to the individual module
 docstrings for details.
 
-Overview
-========
-
-The smart protocol provides a way to send a requests and corresponding
-responses to communicate with a remote bzr process.
-
-Layering
-========
-
-Medium
-------
-
-At the bottom level there is either a socket, pipes, or an HTTP
-request/response.  We call this layer the *medium*.  It is responsible for
-carrying bytes between a client and server.  For sockets, we have the
-idea that you have multiple requests and get a read error because the other side
-did shutdown.  For pipes we have read pipe which will have a zero read which
-marks end-of-file.  For HTTP server environment there is no end-of-stream
-because each request coming into the server is independent.
-
-So we need a wrapper around pipes and sockets to seperate out requests from
-substrate and this will give us a single model which is consistent for HTTP,
-sockets and pipes.
-
-Protocol
---------
-
-On top of the medium is the *protocol*.  This is the layer that deserialises
-bytes into the structured data that requests and responses consist of.
-
-Version one of the protocol (for requests and responses) is described by::
-
-  REQUEST := MESSAGE_V1
-  RESPONSE := MESSAGE_V1
-  MESSAGE_V1 := ARGS BODY
-
-  ARGS := ARG [MORE_ARGS] NEWLINE
-  MORE_ARGS := SEP ARG [MORE_ARGS]
-  SEP := 0x01
-
-  BODY := LENGTH NEWLINE BODY_BYTES TRAILER
-  LENGTH := decimal integer
-  TRAILER := "done" NEWLINE
-
-That is, a tuple of arguments separated by Ctrl-A and terminated with a newline,
-followed by length prefixed body with a constant trailer.  Note that although
-arguments are not 8-bit safe (they cannot include 0x01 or 0x0a bytes without
-breaking the protocol encoding), the body is.
-
-Version two of the request protocol is::
-
-  REQUEST_V2 := "bzr request 2" NEWLINE MESSAGE_V1
-
-Version two of the response protocol is::
-
-  RESPONSE_V2 := "bzr request 2" NEWLINE MESSAGE_V1
-
-Future versions should follow this structure, like version two does::
-
-  FUTURE_MESSAGE := VERSION_STRING NEWLINE REST_OF_MESSAGE
-
-This is that clients and servers can read bytes up to the first newline byte to
-determine what version a message is.
-
-For compatibility will all versions (past and future) of bzr clients, servers
-that receive a request in an unknown protocol version should respond with a
-single-line error terminated with 0x0a (NEWLINE), rather than structured
-response prefixed with a version string.
-
-Request/Response processing
----------------------------
-
-On top of the protocol is the logic for processing requests (on the server) or
-responses (on the client).
-
-Server-side
------------
-
-Sketch::
-
- MEDIUM  (factory for protocol, reads bytes & pushes to protocol,
-          uses protocol to detect end-of-request, sends written
-          bytes to client) e.g. socket, pipe, HTTP request handler.
-  ^
-  | bytes.
-  v
-
- PROTOCOL(serialization, deserialization)  accepts bytes for one
-          request, decodes according to internal state, pushes
-          structured data to handler.  accepts structured data from
-          handler and encodes and writes to the medium.  factory for
-          handler.
-  ^
-  | structured data
-  v
-
- HANDLER  (domain logic) accepts structured data, operates state
-          machine until the request can be satisfied,
-          sends structured data to the protocol.
-
-Request handlers are registered in `bzrlib.smart.request`.
-
-
-Client-side
------------
-
-Sketch::
-
- CLIENT   domain logic, accepts domain requests, generated structured
-          data, reads structured data from responses and turns into
-          domain data.  Sends structured data to the protocol.
-          Operates state machines until the request can be delivered
-          (e.g. reading from a bundle generated in bzrlib to deliver a
-          complete request).
-
-          Possibly this should just be RemoteBzrDir, RemoteTransport,
-          ...
-  ^
-  | structured data
-  v
-
-PROTOCOL  (serialization, deserialization)  accepts structured data for one
-          request, encodes and writes to the medium.  Reads bytes from the
-          medium, decodes and allows the client to read structured data.
-  ^
-  | bytes.
-  v
-
- MEDIUM  (accepts bytes from the protocol & delivers to the remote server.
-          Allows the potocol to read bytes e.g. socket, pipe, HTTP request.
-
-The domain logic is in `bzrlib.remote`: `RemoteBzrDir`, `RemoteBranch`, and so
-on.
+Server-side request handlers are registered in the `bzrlib.smart.request`
+module.
+
+The domain logic is in `bzrlib.remote`: `RemoteBzrDir`, `RemoteBranch`,
+and so on.
 
 There is also an plain file-level transport that calls remote methods to
 manipulate files on the server in `bzrlib.transport.remote`.
 
-Paths
-=====
-
-Paths are passed across the network.  The client needs to see a namespace that
-includes any repository that might need to be referenced, and the client needs
-to know about a root directory beyond which it cannot ascend.
-
-Servers run over ssh will typically want to be able to access any path the user
-can access.  Public servers on the other hand (which might be over http, ssh
-or tcp) will typically want to restrict access to only a particular directory
-and its children, so will want to do a software virtual root at that level.
-In other words they'll want to rewrite incoming paths to be under that level
-(and prevent escaping using ../ tricks.)
-
-URLs that include ~ should probably be passed across to the server verbatim
-and the server can expand them.  This will proably not be meaningful when
-limited to a directory?
+The protocol is described in doc/developers/network-protocol.txt.
+
 """
 
 # TODO: _translate_error should be on the client, not the transport because

=== modified file 'doc/developers/index.txt'
--- doc/developers/index.txt	2007-08-13 10:20:11 +0000
+++ doc/developers/index.txt	2007-09-03 05:11:38 +0000
@@ -31,5 +31,6 @@
 
 * `Repositories <repository.html>`_ |--| What repositories do and are used for.
 
+* `Network protocol <network-protocol.html>`_ |--| Custom network protocol.
 
 .. |--| unicode:: U+2014

# Begin bundle
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
cKEhSP63rg==


More information about the bazaar mailing list