mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
Document the internal protocol.
This commit is contained in:
124
guestfs.pod
124
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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user