libafdt
 All Data Structures Files Functions Variables Typedefs Enumerations Macros Groups
afdt.h
Go to the documentation of this file.
1 /**
2  @mainpage
3 
4  @section intro Introduction
5 
6  libafdt is a library for "a"synchronous "f"ile "d"escriptor "t"ransfers.
7  It provides a simple interface that allows libevent-based programs to
8  set up a Unix domain socket to accept connections and transfer file
9  descriptors to clients, or to be a client and request a file descriptor
10  from a libafdt server. Low-level and synchronous interfaces are also
11  provided for programs that do not use libevent.
12 
13  See <em>Advanced Programming in the UNIX(R) Environment</em> for more
14  information about transferring file descriptors between processes using
15  Unix domain sockets.
16 
17  @section structure Structure
18 
19  libafdt's has two high-level interfaces: an \link async Asynchronous
20  Interface \endlink and a \link sync Synchronous Interface \endlink .
21  The former is best for clients or servers that are based on libevent.
22  It uses callbacks to allow the program to process high-level events.
23  The latter is for clients that don't use libevent and are willing to
24  block while waiting to receive a response. It does not require
25  libevent, and is much more convenient when blocking is acceptable.
26 
27  There is also a \link lowlevel Low-level Interface \endlink . It does
28  not require libevent, but can still be used without blocking. It can
29  also be used to change the simple protocol used by the high-level
30  interfaces. It requires a bit more bookkeeping to use.
31 
32  @section examples Examples
33 
34  The test programs are good examples of how to use the high-level
35  interfaces.
36 
37  The high-level interfaces are good examples of how to use the low-level
38  interface.
39  */
40 
41 /**
42  @file
43  @brief The main header file for libafdt
44 
45  This file contains all of the types and functions available in
46  the libafdt API. All other files are for internal use only.
47  */
48 
49 #ifndef _AFDT_H
50 #define _AFDT_H
51 
52 // Put this in an ifndef so it doesn't go into the generated man page.
53 #ifndef DOXYGEN
54 #include <stdint.h>
55 #endif
56 
57 #ifdef __cplusplus
58 extern "C" {
59 #endif
60 
61 
62 /**
63  * @brief Maximum request or response message length, including the header.
64  *
65  * This is relatively small so that we can consider short reads writes to be
66  * exceptional circumstances, rather than business as usual.
67  */
68 #define AFDT_FULL_MSGLEN 0x200
69 
70 /**
71  * @brief Maximum request or response message length, excluding the header.
72  */
73 #define AFDT_MSGLEN (AFDT_FULL_MSGLEN - sizeof(uint32_t))
74 
75 
76 // Declare these as incomplete types.
77 // The appropriate headers need to be included in order to use them.
78 struct event_base;
79 struct timeval;
80 
81 
82 /**
83  @defgroup errors Error Handling
84 
85  Types, values, and functions used for reporting errors.
86  */
87 
88 /**
89  * @ingroup errors
90  * @brief Phase of the AFDT process during which an error occurred.
91  *
92  * These error codes are used by the asynchronous interface to indicate
93  * the high-level operation that triggered an error.
94  */
95 enum afdt_phase {
96  AFDT_NO_PHASE,
97  AFDT_CREATE_SERVER,
98  AFDT_ACCEPT_CLIENT,
99  AFDT_HANDLE_REQUEST,
100  AFDT_CREATE_CLIENT,
101  AFDT_HANDLE_RESPONSE,
102 };
103 
104 /**
105  * @ingroup errors
106  * @brief Operation that resulted in an error.
107  *
108  * These error codes are used by the all interfaces to indicate the low-level
109  * operation that triggered an error. These are mostly system calls.
110  */
112  AFDT_NO_OPERATION,
113  AFDT_MALLOC,
114  AFDT_SOCKET,
115  AFDT_PATHNAME,
116  AFDT_BIND,
117  AFDT_LISTEN,
118  AFDT_ACCEPT,
119  AFDT_CONNECT,
120  AFDT_FORMAT,
121  AFDT_SENDMSG,
122  AFDT_RECVMSG,
123  AFDT_EVENT_BASE_SET,
124  AFDT_EVENT_ADD,
125  AFDT_POLL,
126  AFDT_TIMEOUT,
127 };
128 
129 /**
130  * @ingroup errors
131  * @brief Detailed information about an error.
132  */
133 struct afdt_error_t {
134  /// @brief High-level phase during which the error occurred.
136  /// @brief Low-level operation that caused the error.
138  /// @brief Additional human-readable information, or "".
139  const char* message;
140 };
141 
142 /**
143  * @ingroup errors
144  * @brief Initializer for error information.
145  *
146  * All \c afdt_error_t objects passed to functions in the low-level interface
147  * should be initialized with this value.
148  */
149 extern const struct afdt_error_t AFDT_ERROR_T_INIT;
150 
151 /**
152  * @ingroup errors
153  * @brief Convert \c afdt_phase into a textual description.
154  */
155 const char* afdt_phase_str(enum afdt_phase phase);
156 
157 /**
158  * @ingroup errors
159  * @brief Convert \c afdt_operation into a textual description.
160  */
162 
163 
164 /**
165  @defgroup lowlevel Low-level Interface
166 
167  The low-level interface provides a thin abstraction over the
168  primitives used for transferring file descriptors over Unix domain
169  sockets. The higher-level interfaces are implemented in terms of
170  these functions, which can also be used to implement a high-level
171  interface on top of a different event loop API or a high-level
172  interface obeying a different protocol (for example: the client
173  sending the file descriptor to the server).
174 
175  This layer imposes very few restrictions on usage. Messages must
176  be at most AFDT_MSGLEN bytes, and are automatically prefixed with
177  a 32-bit host-byte-order header equal to the message length.
178  At most one one file descriptor can be passed per message.
179 
180  The most interesting operation provided by this interface is
181  send/recv fd_msg, which is a short message and an optional
182  file descriptor. Functions are also provided for sending and
183  receiving "plain" messages, which do not include file descriptors.
184 
185  All functions in this interface report errors by returning a negative
186  value and populating detailed information into their \a err parameter.
187  (\a err should be initialized to \c AFDT_ERROR_T_INIT.) errno will
188  be set to an appropriate code, or 0 if no error code is applicable.
189  */
190 
191 /**
192  * @ingroup lowlevel
193  * @brief Create a socket that listens for connections.
194  *
195  * Higher level code should call \c accept(2) on the returned socket
196  * to accept a connection from a client.
197  *
198  * @param fname File to bind PF_LOCAL socket to.
199  * @param err Structure to populate with error information.
200  *
201  * @return socket fd (>=0) if successful, <0 on failure.
202  */
203 int afdt_listen(const char* fname, struct afdt_error_t* err);
204 
205 /**
206  * @ingroup lowlevel
207  * @brief Create a socket and connect to a listening socket.
208  *
209  * @param fname File to connect PF_LOCAL socket to.
210  * @param err Structure to populate with error information.
211  *
212  * @return socket fd (>=0) if successful, <0 on failure.
213  */
214 int afdt_connect(const char* fname, struct afdt_error_t* err);
215 
216 /**
217  * @ingroup lowlevel
218  * @brief Send a message with an optional file descriptor.
219  *
220  * @param connfd Descriptor from \c accept or \c afdt_connect.
221  * @param content Message content.
222  * @param content_len Message length.
223  * @param fd_to_send File descriptor to send, or <0 for none.
224  * @param err Structure to populate with error information.
225  *
226  * @return >=0 if successful, <0 on failure.
227  */
228 int afdt_send_fd_msg(
229  int connfd,
230  const uint8_t* content,
231  uint32_t content_len,
232  int fd_to_send,
233  struct afdt_error_t* err);
234 
235 /**
236  * @ingroup lowlevel
237  * @brief Send a message with no file descriptor.
238  * @see afdt_send_fd_msg
239  */
241  int connfd,
242  const uint8_t* content,
243  uint32_t content_len,
244  struct afdt_error_t* err);
245 
246 /**
247  * @ingroup lowlevel
248  * @brief Receive a message with an optional file descriptor.
249  *
250  * @param connfd Descriptor from \c accept or \c afdt_connect.
251  * @param content Buffer for message content.
252  * @param content_len Pointer to buffer length, returns with actual length.
253  * @param received_fd Returns with received fd, or <0 if none.
254  * @param err Structure to populate with error information.
255  *
256  * @return >=0 if successful, <0 on failure.
257  */
258 int afdt_recv_fd_msg(
259  int connfd,
260  uint8_t* content,
261  uint32_t* content_len,
262  int *received_fd,
263  struct afdt_error_t* err);
264 
265 /**
266  * @ingroup lowlevel
267  * @brief Receive a message with no file descriptor.
268  * @see afdt_recv_fd_msg
269  */
271  int connfd,
272  uint8_t* content,
273  uint32_t* content_len,
274  struct afdt_error_t* err);
275 
276 
277 /**
278  @defgroup async Asynchronous Interface (libevent-based)
279 
280  The asynchronous interface provides functions for setting up clients
281  and servers that use event-driven I/O to avoid blocking a thread.
282  libevent is used to make the interface work with many different
283  event APIs.
284 
285  The asynchronous interface is adds more restrictions than the
286  low-level API. Interactions are always composed of two messages:
287  a plain message from the client to the server (the request) followed
288  by an fd message from the server to the client(the response).
289  There is currently no support for a client sending a file descriptor
290  to the server. (In most cases, it is not too hard to invert the
291  "client" and "server" roles to get around this. The server is simply
292  the program that listens on the Unix domain socket.)
293 
294  Most functions in this interface report errors by calling an error
295  callback and passing error information to it. errno will be set to
296  an appropriate code, or 0 if no error code is applicable.
297  */
298 
299 /**
300  * @ingroup async
301  * @brief Callback type for processing an AFDT request.
302  *
303  * For example, a callback could check some authentication information
304  * in the request, look in the request for the name of some resource,
305  * then return the appropriate fd or send an error message in the response.
306  * Remember to set *\a response_length to 0 if you are sending an empty
307  * response.
308  *
309  * @param request Request buffer sent by the client.
310  * @param request_length Length of \a request.
311  * @param response Buffer into which to write the response.
312  * @param response_length IN/OUT: \a response buffer/content size.
313  * @param userdata Extra parameter passed to \c create_server.
314  * @return File descriptor to send, or <0 for none.
315  */
316 typedef int (*afdt_request_handler_t)(
317  const uint8_t* request,
318  uint32_t request_length,
319  uint8_t* response,
320  uint32_t* response_length,
321  void *userdata);
322 
323 /**
324  * @ingroup async
325  * @brief Callback type for processing an AFDT response.
326  *
327  * For example, a callback could pass the file descriptor to
328  * \e evhttp_accept_socket and start serving requests, or send another
329  * request if the response indicates that the transfer was not authorized.
330  *
331  * @param response Response buffer sent by the server.
332  * @param response_length Length of \a response.
333  * @param received_fd File descriptor received, or <0 for none.
334  * @param userdata Extra parameter passed to \c create_client.
335  */
336 typedef void (*afdt_response_handler_t)(
337  const uint8_t* response,
338  uint32_t response_length,
339  int received_fd,
340  void *userdata);
341 
342 /**
343  * @ingroup async
344  * @brief Callback type for after a response is sent.
345  *
346  * For example, a callback could close \a sent_fd if the recipient is
347  * going to take over all operations.
348  *
349  * The post handler is called before the server returns to the event loop.
350  *
351  * @param request Request buffer sent by the client.
352  * @param request_length Length of \a request.
353  * @param response Response buffer sent by the server.
354  * @param response_length Length of \a response.
355  * @param received_fd File descriptor sent (by \a request_handler).
356  * @param userdata Extra parameter passed to \c create_server.
357  */
358 typedef void (*afdt_post_handler_t)(
359  const uint8_t* request,
360  uint32_t request_length,
361  const uint8_t* response,
362  uint32_t response_length,
363  int sent_fd,
364  void *userdata);
365 
366 /**
367  * @ingroup async
368  * @brief Callback type for processing errors during AFDT operations.
369  *
370  * For example, a callback could log an error message, then try some
371  * other means of acquiring the resources it needs.
372  *
373  * @param phase AFDT phase during which the error occurred.
374  * @param operation Operation that resulted in the error.
375  * @param message Extra information message (often empty).
376  * @param userdata Extra parameter passed to
377  * \c create_client or \c create_server.
378  */
379 typedef void (*afdt_error_handler_t)(
380  const struct afdt_error_t* err,
381  void *userdata);
382 
383 /**
384  * @ingroup async
385  * @brief No-op function that can be used as a post_handler.
386  */
387 void afdt_no_post(
388  const uint8_t* request,
389  uint32_t request_length,
390  const uint8_t* response,
391  uint32_t response_length,
392  int sent_fd,
393  void *userdata);
394 
395 /**
396  * @ingroup async
397  * @brief Create a server to make file descriptors available.
398  *
399  * \a request_handler and \a error_handler may both be called
400  * multiple times.
401  *
402  * @param fname File to bind PF_LOCAL socket to.
403  * Must not exist.
404  * @param eb struct event_base to manage this server.
405  * @param request_handler Callback to handle requests.
406  * @param post_handler Callback called after sending a response.
407  * @param error_handler Callback to handle errors.
408  * @param out_close_handle If non-\c NULL, set to a handle for
409  * \c afdt_close_server.
410  * @param userdata Arbitrary value to pass to callbacks.
411  * @return >=0 if successful, <0 on failure.
412  * \a error_handler will also be called on failure.
413  */
415  const char* fname,
416  struct event_base* eb,
417  afdt_request_handler_t request_handler,
418  afdt_post_handler_t post_handler,
419  afdt_error_handler_t error_handler,
420  void** out_close_handle,
421  void* userdata);
422 
423 /**
424  * @ingroup async
425  * @brief Shut down a server created by \c afdt_create_server.
426  *
427  * Any client connections that have already been created
428  * will continue to exist.
429  *
430  * @param close_handle Handle provided by \c afdt_create_server.
431  * @return >=0 if successful, <0 on failure.
432  */
433 int afdt_close_server(void* close_handle);
434 
435 /**
436  * @ingroup async
437  * @brief Request a file descriptor from a server.
438  *
439  * Exactly one of \a response_handler and \a error_handler will be called,
440  * unless timeout is \c NULL and the server never responds.
441  *
442  * \note This function currently does a blocking connect and send.
443  *
444  * @param fname File to connect PF_LOCAL socket to.
445  * @param eb struct event_base to manage this client.
446  * @param request Request buffer to send.
447  * @param request_length Length of \a request.
448  * @param response_handler Callback to handle response.
449  * @param error_handler Callback to handle errors.
450  * @param timeout Timeout when waiting for response, or \c NULL.
451  * @param userdata Arbitrary value to pass to callbacks.
452  * @return >=0 if connection and request successful, <0 on failure.
453  * \a error_handler will also be called on failure.
454  */
456  const char* fname,
457  struct event_base* eb,
458  const uint8_t* request,
459  uint32_t request_length,
460  afdt_response_handler_t response_handler,
461  afdt_error_handler_t error_handler,
462  const struct timeval* timeout,
463  void* userdata);
464 
465 
466 /**
467  @defgroup sync Synchronous Client Interface
468 
469  The synchronous interface provides a very simple function allowing
470  clients to communicate with servers using the asynchronous interface.
471  The function is blocking, but supports an optional timeout.
472  */
473 
474 /**
475  * @ingroup sync
476  * @brief Request a file descriptor from a server.
477  *
478  * @param fname File to connect PF_LOCAL socket to.
479  * @param request Request buffer to send.
480  * @param request_length Length of \a request.
481  * @param response Buffer for response.
482  * @param response_length Pointer to \a response length,
483  * returns with actual length.
484  * @param received_fd Returns with received fd, or <0 if none.
485  * @param timeout Timeout when waiting for response, or \c NULL.
486  * @param err Structure to populate with error information.
487  * @return >=0 if successful, <0 on failure.
488  */
489 int afdt_sync_client(
490  const char* fname,
491  const uint8_t* request,
492  uint32_t request_length,
493  uint8_t* response,
494  uint32_t* response_length,
495  int* received_fd,
496  const struct timeval* timeout,
497  struct afdt_error_t* err);
498 
499 #ifdef __cplusplus
500 }
501 #endif
502 
503 #endif // _AFDT_H
Detailed information about an error.
Definition: afdt.h:133
int afdt_sync_client(const char *fname, const uint8_t *request, uint32_t request_length, uint8_t *response, uint32_t *response_length, int *received_fd, const struct timeval *timeout, struct afdt_error_t *err)
Request a file descriptor from a server.
int(* afdt_request_handler_t)(const uint8_t *request, uint32_t request_length, uint8_t *response, uint32_t *response_length, void *userdata)
Callback type for processing an AFDT request.
Definition: afdt.h:316
int afdt_listen(const char *fname, struct afdt_error_t *err)
Create a socket that listens for connections.
void(* afdt_error_handler_t)(const struct afdt_error_t *err, void *userdata)
Callback type for processing errors during AFDT operations.
Definition: afdt.h:379
int afdt_send_plain_msg(int connfd, const uint8_t *content, uint32_t content_len, struct afdt_error_t *err)
Send a message with no file descriptor.
void(* afdt_post_handler_t)(const uint8_t *request, uint32_t request_length, const uint8_t *response, uint32_t response_length, int sent_fd, void *userdata)
Callback type for after a response is sent.
Definition: afdt.h:358
int afdt_create_client(const char *fname, struct event_base *eb, const uint8_t *request, uint32_t request_length, afdt_response_handler_t response_handler, afdt_error_handler_t error_handler, const struct timeval *timeout, void *userdata)
Request a file descriptor from a server.
enum afdt_operation operation
Low-level operation that caused the error.
Definition: afdt.h:137
const char * message
Additional human-readable information, or "".
Definition: afdt.h:139
int afdt_connect(const char *fname, struct afdt_error_t *err)
Create a socket and connect to a listening socket.
void afdt_no_post(const uint8_t *request, uint32_t request_length, const uint8_t *response, uint32_t response_length, int sent_fd, void *userdata)
No-op function that can be used as a post_handler.
afdt_phase
Phase of the AFDT process during which an error occurred.
Definition: afdt.h:95
int afdt_send_fd_msg(int connfd, const uint8_t *content, uint32_t content_len, int fd_to_send, struct afdt_error_t *err)
Send a message with an optional file descriptor.
enum afdt_phase phase
High-level phase during which the error occurred.
Definition: afdt.h:135
const char * afdt_phase_str(enum afdt_phase phase)
Convert afdt_phase into a textual description.
void(* afdt_response_handler_t)(const uint8_t *response, uint32_t response_length, int received_fd, void *userdata)
Callback type for processing an AFDT response.
Definition: afdt.h:336
int afdt_recv_plain_msg(int connfd, uint8_t *content, uint32_t *content_len, struct afdt_error_t *err)
Receive a message with no file descriptor.
int afdt_create_server(const char *fname, struct event_base *eb, afdt_request_handler_t request_handler, afdt_post_handler_t post_handler, afdt_error_handler_t error_handler, void **out_close_handle, void *userdata)
Create a server to make file descriptors available.
int afdt_close_server(void *close_handle)
Shut down a server created by afdt_create_server.
const struct afdt_error_t AFDT_ERROR_T_INIT
Initializer for error information.
int afdt_recv_fd_msg(int connfd, uint8_t *content, uint32_t *content_len, int *received_fd, struct afdt_error_t *err)
Receive a message with an optional file descriptor.
const char * afdt_operation_str(enum afdt_operation operation)
Convert afdt_operation into a textual description.
afdt_operation
Operation that resulted in an error.
Definition: afdt.h:111