2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 2008-2012 Zmanda, Inc. All Rights Reserved.
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.
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
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
19 * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
20 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
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.
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.
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:
45 * +--------|--------|--------|--------+
47 * +--------|--------|--------|--------+
49 * +-----------------|-----------------+
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
60 * +--------|--------|--------|--------+
62 * +--------|--------|--------|--------+
64 * +-----------------------------------+
66 * +-----------------------------------+
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: */
79 MY_PROTO_HOSTNAME = 1,
82 MY_PROTO_FILENAMES = 4,
88 static ipc_binary_proto_t *proto = NULL;
90 ipc_binary_cmd_t *cmd;
92 proto = ipc_binary_proto_new(0xFACE);
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);
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);
108 /* Invoke my_proto in a thread-safe manner if necessary.
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.
117 * Creating a new protocol
121 typedef struct ipc_binary_proto_t ipc_binary_proto_t;
122 typedef struct ipc_binary_cmd_t ipc_binary_cmd_t;
124 /* Create a new, empty protocol object
126 * @param magic: magic number used to identify this protocol
127 * @returns: proto object
129 ipc_binary_proto_t *ipc_binary_proto_new(
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.
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
139 ipc_binary_cmd_t *ipc_binary_proto_add_cmd(
140 ipc_binary_proto_t *proto,
143 /* Flags for arguments */
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)
151 /* This argument may be omitted */
152 #define IPC_BINARY_OPTIONAL (1 << 1)
154 /* Add an argument to a command
156 * @param cmd: the command object
157 * @param id: the argument identifier
158 * @param flags: bit flags for the command (see above)
160 void ipc_binary_cmd_add_arg(
161 ipc_binary_cmd_t *cmd,
169 typedef struct ipc_binary_buf_t {
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
179 typedef struct ipc_binary_channel_t {
180 /* protocol for this channel */
181 ipc_binary_proto_t *proto;
183 /* buffers for incoming and outgoing data */
184 ipc_binary_buf_t in, out;
185 } ipc_binary_channel_t;
187 /* Create a new channel, ready to send and receive messages.
189 * @param proto: protocol to use on this channel
190 * @returns: a new channel object
192 ipc_binary_channel_t *ipc_binary_new_channel(
193 ipc_binary_proto_t *proto);
195 /* Free a channel completely.
197 * @param channel: the channel to free
199 void ipc_binary_free_channel(
200 ipc_binary_channel_t *channel);
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. */
205 typedef struct ipc_binary_message_t {
206 ipc_binary_channel_t *chan;
208 ipc_binary_cmd_t *cmd;
215 } ipc_binary_message_t;
217 /* Create a new, blank message which will later be sent.
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
223 ipc_binary_message_t *ipc_binary_new_message(
224 ipc_binary_channel_t *chan,
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
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
239 void ipc_binary_add_arg(
240 ipc_binary_message_t *msg,
244 gboolean take_memory);
246 /* Free a message structure (including all associated memory)
248 * @param msg: message to free
250 void ipc_binary_free_message(
251 ipc_binary_message_t *msg);
253 /* Synchronous interface
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).
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.
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
268 ipc_binary_message_t *ipc_binary_read_message(
269 ipc_binary_channel_t *chan,
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.
276 * @param chan: channel on which to send the message
277 * @param fd: file descriptor to write to
278 * @param msg: message to send
280 int ipc_binary_write_message(
281 ipc_binary_channel_t *chan,
283 ipc_binary_message_t *msg);
285 /* Asynchronous interface
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
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
295 * @param chan: channel into which to feed data
296 * @param size: size of DATA
297 * @param data: the new data
299 void ipc_binary_feed_data(
300 ipc_binary_channel_t *chan,
304 /* Signal that some bytes have been transmitted and need not be kept in the
305 * outgoing buffer any longer
307 * @param chan: channel from which bytes were sent
308 * @param size: number of bytes transmitted
310 void ipc_binary_data_transmitted(
311 ipc_binary_channel_t *chan,
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.
318 * @param chan: channel to poll
319 * @returns: message or NULL
321 ipc_binary_message_t *ipc_binary_poll_message(
322 ipc_binary_channel_t *chan);
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
328 * @param chan: the channel to feed
329 * @param msg: the message to send
331 void ipc_binary_queue_message(
332 ipc_binary_channel_t *chan,
333 ipc_binary_message_t *msg);
335 #endif /* IPC_BINARY_H */