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