summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Jones <rjones@redhat.com>2009-04-19 14:33:46 +0100
committerRichard Jones <rjones@redhat.com>2009-04-19 14:33:46 +0100
commit08c333a73893a0fc413e7619c8e64bebaebc741a (patch)
treeadd3fe0958ad5d45f0bd898426f672ea42a6dd5b
parentd73a4f097f96e7246718671b0a85cb94f0d3a88f (diff)
downloadlibguestfs-08c333a73893a0fc413e7619c8e64bebaebc741a.tar.gz
libguestfs-08c333a73893a0fc413e7619c8e64bebaebc741a.tar.xz
libguestfs-08c333a73893a0fc413e7619c8e64bebaebc741a.zip
Document the internal protocol.
-rw-r--r--guestfs.pod124
-rwxr-xr-xsrc/generator.ml38
2 files changed, 132 insertions, 30 deletions
diff --git a/guestfs.pod b/guestfs.pod
index cce7b90d..a4624312 100644
--- a/guestfs.pod
+++ b/guestfs.pod
@@ -491,6 +491,130 @@ C<guestfs_create_main_loop>.
This isn't documented. Please see the libguestfs-select and
libguestfs-glib implementations.
+=head1 INTERNALS
+
+=head2 COMMUNICATION PROTOCOL
+
+Don't rely on using this protocol directly. This section documents
+how it currently works, but it may change at any time.
+
+The protocol used to talk between the library and the daemon running
+inside the qemu virtual machine is a simple RPC mechanism built on top
+of XDR (RFC 1014, RFC 1832, RFC 4506).
+
+The detailed format of structures is in C<src/guestfs_protocol.x>
+(note: this file is automatically generated).
+
+There are two broad cases, ordinary functions that don't have any
+C<FileIn> and C<FileOut> parameters, which are handled with very
+simple request/reply messages. Then there are functions that have any
+C<FileIn> or C<FileOut> parameters, which use the same request and
+reply messages, but they may also be followed by files sent using a
+chunked encoding.
+
+=head3 ORDINARY FUNCTIONS (NO FILEIN/FILEOUT PARAMS)
+
+For ordinary functions, the request message is:
+
+ total length (header + arguments,
+ but not including the length word itself)
+ struct guestfs_message_header
+ struct guestfs_<foo>_args
+
+The total length field allows the daemon to allocate a fixed size
+buffer into which it slurps the rest of the message. As a result, the
+total length is limited to C<GUESTFS_MESSAGE_MAX> bytes (currently
+4MB), which means the effective size of any request is limited to
+somewhere under this size.
+
+Note also that many functions don't take any arguments, in which case
+the C<guestfs_I<foo>_args> is completely omitted.
+
+The header contains the procedure number (C<guestfs_proc>) which is
+how the receiver knows what type of args structure to expect, or none
+at all.
+
+The reply message for ordinary functions is:
+
+ total length (header + ret,
+ but not including the length word itself)
+ struct guestfs_message_header
+ struct guestfs_<foo>_ret
+
+As above the C<guestfs_I<foo>_ret> structure may be completely omitted
+for functions that return no formal return values.
+
+As above the total length of the reply is limited to
+C<GUESTFS_MESSAGE_MAX>.
+
+In the case of an error, a flag is set in the header, and the reply
+message is slightly changed:
+
+ total length (header + error,
+ but not including the length word itself)
+ struct guestfs_message_header
+ struct guestfs_message_error
+
+The C<guestfs_message_error> structure contains the error message as a
+string.
+
+=head3 FUNCTIONS THAT HAVE FILEIN PARAMETERS
+
+A C<FileIn> parameter indicates that we transfer a file I<into> the
+guest. The normal request message is sent (see above). However this
+is followed by a sequence of file chunks.
+
+ total length (header + arguments,
+ but not including the length word itself,
+ and not including the chunks)
+ struct guestfs_message_header
+ struct guestfs_<foo>_args
+ sequence of chunks for FileIn param #0
+ sequence of chunks for FileIn param #1 etc.
+
+The sequence of chunks is a sequence of C<struct guestfs_chunk>. A
+flag is set in the final chunk to indicate either successful
+completion or early cancellation.
+
+At time of writing there are no functions that have more than one
+FileIn parameter. However this is (theoretically) supported, by
+sending the chunks for each FileIn parameter one after another (from
+left to right).
+
+Both the library (sender) I<and> the daemon (receiver) may cancel the
+transfer. The library does this by sending a chunk with a special
+flag set to indicate cancellation. When the daemon sees this, it
+cancels the whole RPC, does I<not> send any reply, and goes back to
+reading the next request.
+
+The daemon may also cancel. It does this by writing a special word
+C<GUESTFS_CANCEL_FLAG> to the socket. The library listens for this
+during the transfer, and if it gets it, it will cancel the transfer
+(it sends a cancel chunk). The special word is chosen so that even if
+cancellation happens right at the end of the transfer (after the
+library has finished writing and has started listening for the reply),
+the "spurious" cancel flag will not be confused with the reply
+message.
+
+This protocol allows the transfer of arbitrary sized files (no 32 bit
+limit), and also files where the size is not known in advance
+(eg. from pipes or sockets). However the chunks are rather small
+(C<GUESTFS_MAX_CHUNK_SIZE>), so that neither the library nor the
+daemon need to keep much in memory.
+
+=head3 FUNCTIONS THAT HAVE FILEOUT PARAMETERS
+
+The protocol for FileOut parameters is exactly the same as for FileIn
+parameters, but with the roles of daemon and library reversed.
+
+ total length (header + ret,
+ but not including the length word itself,
+ and not including the chunks)
+ struct guestfs_message_header
+ struct guestfs_<foo>_ret
+ sequence of chunks for FileOut param #0
+ sequence of chunks for FileOut param #1 etc.
+
=head1 ENVIRONMENT VARIABLES
=over 4
diff --git a/src/generator.ml b/src/generator.ml
index cf5db876..8c75b933 100755
--- a/src/generator.ml
+++ b/src/generator.ml
@@ -1924,9 +1924,17 @@ and generate_xdr () =
(* Message header, etc. *)
pr "\
+/* The communication protocol is now documented in the guestfs(3)
+ * manpage.
+ */
+
const GUESTFS_PROGRAM = 0x2000F5F5;
const GUESTFS_PROTOCOL_VERSION = 1;
+/* These constants must be larger than any possible message length. */
+const GUESTFS_LAUNCH_FLAG = 0xf5f55f5f;
+const GUESTFS_CANCEL_FLAG = 0xffffeeee;
+
enum guestfs_message_direction {
GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
@@ -1943,19 +1951,6 @@ struct guestfs_message_error {
string error_message<GUESTFS_ERROR_LEN>;
};
-/* For normal requests and replies (not involving any FileIn or
- * FileOut parameters), the protocol is:
- *
- * For requests:
- * total length (header + args, but not including length word itself)
- * header
- * guestfs_foo_args struct
- * For replies:
- * total length (as above)
- * header
- * guestfs_foo_ret struct
- */
-
struct guestfs_message_header {
unsigned prog; /* GUESTFS_PROGRAM */
unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
@@ -1965,23 +1960,6 @@ struct guestfs_message_header {
guestfs_message_status status;
};
-/* Chunked encoding used to transfer files, for FileIn and FileOut
- * parameters.
- *
- * For requests which have >= 1 FileIn parameter:
- * length of header + args (but not length word itself, and not chunks)
- * header
- * guestfs_foo_args struct
- * sequence of chunks for FileIn param #0
- * sequence of chunks for FileIn param #1 etc
- *
- * For replies which have >= 1 FileOut parameter:
- * length of header + ret (but not length word itself, and not chunks)
- * header
- * guestfs_foo_ret struct
- * sequence of chunks for FileOut param #0
- * sequence of chunks for FileOut param #1 etc
- */
const GUESTFS_MAX_CHUNK_SIZE = 8192;
struct guestfs_chunk {