Imported Upstream version 3.3.3
[debian/amanda] / common-src / ipc-binary.h
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 2008-2012 Zmanda, Inc.  All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18  *
19  * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
20  * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
21  */
22
23 #ifndef IPC_BINARY_H
24 #define IPC_BINARY_H
25
26 #include "amanda.h"
27
28 /* This module implements bidirectional message-oriented protocols which use
29  * binary framing, allowing it to transmit significant quantities of binary
30  * data efficiently, at the cost of not being easily human-readable.
31  *
32  * A protocol is a set of messages (identified by distinct small integers),
33  * each of which has a variable number of arguments, identified by other small,
34  * nonzero integers which are unique within a particular message.  Protocols
35  * are assumed to be known completely by both sides of a conversation -- no
36  * allowance is made for communication between different "versions" of a
37  * protocol.  Arguments are limited to 2^32-1 bytes (just under 4 MB), and each
38  * message is similarly limited to a total of 2^32-1 bytes, including all
39  * protocol framing.  Users are advised to choose smaller sizes (e.g., 2MB) for
40  * data blocks transmitted within arguments.
41  *
42  * On the wire, each message consists of a 16-bit magic number, followed by a
43  * 16-bit command id, a 32-bit message length, and a 32-bit argument count:
44  *
45  *   +--------|--------|--------|--------+
46  *   |      magic      |     command     |
47  *   +--------|--------|--------|--------+
48  *   |              length               |
49  *   +-----------------|-----------------+
50  *   |     arg count   | ...
51  *   +-----------------+
52  *
53  * All integers are in network byte order, and the message length includes the
54  * length of the header.  This header is followed by a sequence of argument
55  * records, each of which consists of a 32-bit length followed by a 16-bit
56  * argument id and the corresponding data.  String arguments do not include the
57  * NUL terminator byte.  Note that the argument length does not include the
58  * argument header.
59  *
60  *   +--------|--------|--------|--------+
61  *   |              length               |
62  *   +--------|--------|--------|--------+
63  *   |      argid      |      data       |
64  *   +-----------------------------------+
65  *   |              data...              |
66  *   +-----------------------------------+
67  */
68
69 /* To define a protocol, begin by enumerating the relevant message identifiers
70  * and argument identifiers.  Then write an initialization function on the
71  * following format: */
72 #if 0
73 enum {
74     MY_PROTO_BACKUP = 1,
75     MY_PROTO_RESTORE = 2,
76 };
77
78 enum {
79     MY_PROTO_HOSTNAME = 1,
80     MY_PROTO_DISK = 2,
81     MY_PROTO_LEVEL = 3,
82     MY_PROTO_FILENAMES = 4,
83 };
84
85 ipc_binary_proto_t *
86 my_proto(void)
87 {
88     static ipc_binary_proto_t *proto = NULL;
89     if (!proto) {
90         ipc_binary_cmd_t *cmd;
91
92         proto = ipc_binary_proto_new(0xFACE);
93
94         cmd = ipc_binary_proto_add_cmd(proto, MY_PROTO_BACKUP);
95         ipc_binary_cmd_add_arg(cmd, MY_PROTO_HOSTNAME, IPC_BINARY_STRING);
96         ipc_binary_cmd_add_arg(cmd, MY_PROTO_DISK, IPC_BINARY_STRING);
97         ipc_binary_cmd_add_arg(cmd, MY_PROTO_LEVEL, IPC_BINARY_STRING | IPC_BINARY_OPTIONAL);
98
99         cmd = ipc_binary_proto_add_cmd(proto, MY_PROTO_RESTORE);
100         ipc_binary_cmd_add_arg(cmd, MY_PROTO_HOSTNAME, IPC_BINARY_STRING);
101         ipc_binary_cmd_add_arg(cmd, MY_PROTO_DISK, IPC_BINARY_STRING);
102         ipc_binary_cmd_add_arg(cmd, MY_PROTO_FILENAMES, 0);
103     }
104
105     return proto;
106 }
107 #endif
108 /* Invoke my_proto in a thread-safe manner if necessary.
109  *
110  * Note that all of the constants are one-based.  Internally, the module uses these values as
111  * array indices, so the constants should be assigned sequentially.  Although C specifies that
112  * enumerations will auto-increment, it is best to add explicit values to avoid accidentally
113  * changing protocol values between revisions.
114  */
115
116 /*
117  * Creating a new protocol
118  */
119
120 /* opaque types */
121 typedef struct ipc_binary_proto_t ipc_binary_proto_t;
122 typedef struct ipc_binary_cmd_t ipc_binary_cmd_t;
123
124 /* Create a new, empty protocol object
125  *
126  * @param magic: magic number used to identify this protocol
127  * @returns: proto object
128  */
129 ipc_binary_proto_t *ipc_binary_proto_new(
130     guint16 magic);
131
132 /* Create a new command in a protocol.  The resulting object is only
133  * valid until the next call to this function for this proto.
134  *
135  * @param proto: the ipc_proto_t object to which to add this command
136  * @param id: the nonzero identifier for this command
137  * @returns: a new command object, already linked to PROTO
138  */
139 ipc_binary_cmd_t *ipc_binary_proto_add_cmd(
140     ipc_binary_proto_t *proto,
141     guint16 id);
142
143 /* Flags for arguments */
144
145 /* This argument contains a string of non-null, printable characters and should
146  * be displayed in debugging messages.  Arguments of this type will have a
147  * terminating NUL byte in the ipc_binary_message_t args array, for
148  * convenience, but will not count that byte in the length. */
149 #define IPC_BINARY_STRING               (1 << 0)
150
151 /* This argument may be omitted */
152 #define IPC_BINARY_OPTIONAL             (1 << 1)
153
154 /* Add an argument to a command
155  *
156  * @param cmd: the command object
157  * @param id: the argument identifier
158  * @param flags: bit flags for the command (see above)
159  */
160 void ipc_binary_cmd_add_arg(
161     ipc_binary_cmd_t *cmd,
162     guint16 id,
163     guint8 flags);
164
165 /*
166  * Using a protocol
167  */
168
169 typedef struct ipc_binary_buf_t {
170     gpointer buf;
171     gsize size;
172     gsize offset;
173     gsize length;
174 } ipc_binary_buf_t;
175
176 /* A channel represents a running protocol conversation, and encapsulates
177  * buffers for incoming and outgoing data, as well as a pointer to the protocol
178  * in use. */
179 typedef struct ipc_binary_channel_t {
180     /* protocol for this channel */
181     ipc_binary_proto_t *proto;
182
183     /* buffers for incoming and outgoing data */
184     ipc_binary_buf_t in, out;
185 } ipc_binary_channel_t;
186
187 /* Create a new channel, ready to send and receive messages.
188  *
189  * @param proto: protocol to use on this channel
190  * @returns: a new channel object
191  */
192 ipc_binary_channel_t *ipc_binary_new_channel(
193     ipc_binary_proto_t *proto);
194
195 /* Free a channel completely.
196  *
197  * @param channel: the channel to free
198  */
199 void ipc_binary_free_channel(
200     ipc_binary_channel_t *channel);
201
202 /* message format; use the argument id as an index into the args array.  If
203  * DATA is NULL, then the argument wasn't present. */
204
205 typedef struct ipc_binary_message_t {
206     ipc_binary_channel_t *chan;
207     guint16 cmd_id;
208     ipc_binary_cmd_t *cmd;
209     guint16 n_args;
210
211     struct {
212         gsize len;
213         gpointer data;
214     } *args;
215 } ipc_binary_message_t;
216
217 /* Create a new, blank message which will later be sent.
218  *
219  * @param chan: the channel the message will be sent on
220  * @param cmd: the command id for this message
221  * @returns: new message struct
222  */
223 ipc_binary_message_t *ipc_binary_new_message(
224     ipc_binary_channel_t *chan,
225     guint16 cmd_id);
226
227 /* Add an argument to a message.  If the argument was defined with
228  * IPC_BINARY_STRING, then the size will be calculated using strlen.  If
229  * TAKE_MEMORY is true, then this module takes ownership of the memory and will
230  * free it (with g_free) when the message is freed; otherwise, it will copy the
231  * data.
232  *
233  * @param msg: the message to change
234  * @param arg: the argument ID
235  * @param size: the argument size
236  * @param data: the argument data
237  * @param take_memory: take ownership of memory if TRUE
238  */
239 void ipc_binary_add_arg(
240     ipc_binary_message_t *msg,
241     guint16 arg,
242     gsize size,
243     gpointer data,
244     gboolean take_memory);
245
246 /* Free a message structure (including all associated memory)
247  *
248  * @param msg: message to free
249  */
250 void ipc_binary_free_message(
251     ipc_binary_message_t *msg);
252
253 /* Synchronous interface
254  *
255  * This interface assumes that communication takes place over file
256  * descriptors, and that blocking on network I/O is OK.  It is much
257  * simpler than the asynchronous interface (below).
258  */
259
260 /* Get the next message from the channel, optionally blocking until such a
261  * message is received.  Returns NULL on EOF or on a protcol error.  Errno is
262  * set to 0 for EOF, and contains an appropriate code for any other error.
263  *
264  * @param chan: channel on which to wait for a message
265  * @param fd: file descriptor to read from
266  * @returns: the message or NULL
267  */
268 ipc_binary_message_t *ipc_binary_read_message(
269     ipc_binary_channel_t *chan,
270     int fd);
271
272 /* Send the given message, blocking until it is completely transmitted.
273  * This function automatically frees the message.  Returns -1 on error,
274  * with errno set appropriately, or 0 on success.
275  *
276  * @param chan: channel on which to send the message
277  * @param fd: file descriptor to write to
278  * @param msg: message to send
279  */
280 int ipc_binary_write_message(
281     ipc_binary_channel_t *chan,
282     int fd,
283     ipc_binary_message_t *msg);
284
285 /* Asynchronous interface
286  *
287  * This interface places data into and extracts data out of the buffers
288  * in a channel, but leaves it to the caller to handle sending and receiving
289  * data. */
290
291 /* Feed the given data into the channel.  Call this when new data is
292  * available, and then check ipc_binary_poll_message(..) for any completed
293  * messages.
294  *
295  * @param chan: channel into which to feed data
296  * @param size: size of DATA
297  * @param data: the new data
298  */
299 void ipc_binary_feed_data(
300     ipc_binary_channel_t *chan,
301     gsize size,
302     gpointer data);
303
304 /* Signal that some bytes have been transmitted and need not be kept in the
305  * outgoing buffer any longer
306  *
307  * @param chan: channel from which bytes were sent
308  * @param size: number of bytes transmitted
309  */
310 void ipc_binary_data_transmitted(
311     ipc_binary_channel_t *chan,
312     gsize size);
313
314 /* Return the next complete incoming message in the channel, or NULL if there
315  * are no complete messages available.  This also returns NULL on an invalid
316  * message, with errno set appropriately.
317  *
318  * @param chan: channel to poll
319  * @returns: message or NULL
320  */
321 ipc_binary_message_t *ipc_binary_poll_message(
322     ipc_binary_channel_t *chan);
323
324 /* Queue the given message for later transmission.  This function will free the
325  * message once it is in the outgoing data buffer.  It is up to the caller to
326  * ensure that the
327  *
328  * @param chan: the channel to feed
329  * @param msg: the message to send
330  */
331 void ipc_binary_queue_message(
332     ipc_binary_channel_t *chan,
333     ipc_binary_message_t *msg);
334
335 #endif /* IPC_BINARY_H */