2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 2008,2009 Zmanda, Inc. All Rights Reserved.
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.
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
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
18 * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
19 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
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.
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.
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:
44 * +--------|--------|--------|--------+
46 * +--------|--------|--------|--------+
48 * +-----------------|-----------------+
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
59 * +--------|--------|--------|--------+
61 * +--------|--------|--------|--------+
63 * +-----------------------------------+
65 * +-----------------------------------+
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: */
78 MY_PROTO_HOSTNAME = 1,
81 MY_PROTO_FILENAMES = 4,
87 static ipc_binary_proto_t *proto = NULL;
89 ipc_binary_cmd_t *cmd;
91 proto = ipc_binary_proto_new(0xFACE);
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);
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);
107 /* Invoke my_proto in a thread-safe manner if necessary.
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.
116 * Creating a new protocol
120 typedef struct ipc_binary_proto_t ipc_binary_proto_t;
121 typedef struct ipc_binary_cmd_t ipc_binary_cmd_t;
123 /* Create a new, empty protocol object
125 * @param magic: magic number used to identify this protocol
126 * @returns: proto object
128 ipc_binary_proto_t *ipc_binary_proto_new(
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.
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
138 ipc_binary_cmd_t *ipc_binary_proto_add_cmd(
139 ipc_binary_proto_t *proto,
142 /* Flags for arguments */
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)
150 /* This argument may be omitted */
151 #define IPC_BINARY_OPTIONAL (1 << 1)
153 /* Add an argument to a command
155 * @param cmd: the command object
156 * @param id: the argument identifier
157 * @param flags: bit flags for the command (see above)
159 void ipc_binary_cmd_add_arg(
160 ipc_binary_cmd_t *cmd,
168 typedef struct ipc_binary_buf_t {
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
178 typedef struct ipc_binary_channel_t {
179 /* protocol for this channel */
180 ipc_binary_proto_t *proto;
182 /* buffers for incoming and outgoing data */
183 ipc_binary_buf_t in, out;
184 } ipc_binary_channel_t;
186 /* Create a new channel, ready to send and receive messages.
188 * @param proto: protocol to use on this channel
189 * @returns: a new channel object
191 ipc_binary_channel_t *ipc_binary_new_channel(
192 ipc_binary_proto_t *proto);
194 /* Free a channel completely.
196 * @param channel: the channel to free
198 void ipc_binary_free_channel(
199 ipc_binary_channel_t *channel);
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. */
204 typedef struct ipc_binary_message_t {
205 ipc_binary_channel_t *chan;
207 ipc_binary_cmd_t *cmd;
214 } ipc_binary_message_t;
216 /* Create a new, blank message which will later be sent.
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
222 ipc_binary_message_t *ipc_binary_new_message(
223 ipc_binary_channel_t *chan,
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
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
238 void ipc_binary_add_arg(
239 ipc_binary_message_t *msg,
243 gboolean take_memory);
245 /* Free a message structure (including all associated memory)
247 * @param msg: message to free
249 void ipc_binary_free_message(
250 ipc_binary_message_t *msg);
252 /* Synchronous interface
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).
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.
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
267 ipc_binary_message_t *ipc_binary_read_message(
268 ipc_binary_channel_t *chan,
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.
275 * @param chan: channel on which to send the message
276 * @param fd: file descriptor to write to
277 * @param msg: message to send
279 int ipc_binary_write_message(
280 ipc_binary_channel_t *chan,
282 ipc_binary_message_t *msg);
284 /* Asynchronous interface
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
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
294 * @param chan: channel into which to feed data
295 * @param size: size of DATA
296 * @param data: the new data
298 void ipc_binary_feed_data(
299 ipc_binary_channel_t *chan,
303 /* Signal that some bytes have been transmitted and need not be kept in the
304 * outgoing buffer any longer
306 * @param chan: channel from which bytes were sent
307 * @param size: number of bytes transmitted
309 void ipc_binary_data_transmitted(
310 ipc_binary_channel_t *chan,
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.
317 * @param chan: channel to poll
318 * @returns: message or NULL
320 ipc_binary_message_t *ipc_binary_poll_message(
321 ipc_binary_channel_t *chan);
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
327 * @param chan: the channel to feed
328 * @param msg: the message to send
330 void ipc_binary_queue_message(
331 ipc_binary_channel_t *chan,
332 ipc_binary_message_t *msg);
334 #endif /* IPC_BINARY_H */