Document the internal protocol.

This commit is contained in:
Richard Jones
2009-04-19 14:33:46 +01:00
parent d73a4f097f
commit 08c333a738
2 changed files with 132 additions and 30 deletions

View File

@@ -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

View File

@@ -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 {