BRL-CAD
pkg.h
Go to the documentation of this file.
1 /* P K G . H
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @addtogroup libpkg */
21 /** @{ */
22 /** @file pkg.h
23  *
24  * LIBPKG provides routines to manage multiplexing and de-multiplexing
25  * synchronous and asynchronous messages across stream connections.
26  *
27  */
28 
29 #ifndef PKG_H
30 #define PKG_H
31 
32 /* for size_t */
33 #include <stddef.h>
34 
35 #ifndef PKG_EXPORT
36 # if defined(PKG_DLL_EXPORTS) && defined(PKG_DLL_IMPORTS)
37 # error "Only PKG_DLL_EXPORTS or PKG_DLL_IMPORTS can be defined, not both."
38 # elif defined(PKG_DLL_EXPORTS)
39 # define PKG_EXPORT __declspec(dllexport)
40 # elif defined(PKG_DLL_IMPORTS)
41 # define PKG_EXPORT __declspec(dllimport)
42 # else
43 # define PKG_EXPORT
44 # endif
45 #endif
46 
47 
48 #ifdef __cplusplus
49 extern "C" {
50 #endif
51 
52 struct pkg_conn;
53 
54 typedef void (*pkg_callback)(struct pkg_conn*, char*);
55 typedef void (*pkg_errlog)(const char *msg);
56 
57 struct pkg_switch {
58  unsigned short pks_type; /**< @brief Type code */
59  pkg_callback pks_handler; /**< @brief Message Handler */
60  const char *pks_title; /**< @brief Description of message type */
61  void *pks_user_data; /**< @brief User defined pointer to data */
62 };
63 
64 /**
65  * Format of the message header as it is transmitted over the network
66  * connection. Internet network order is used.
67  * User Code should access pkc_len and pkc_type rather than
68  * looking into the header directly.
69  * Users should never need to know what this header looks like.
70  */
71 #define PKG_MAGIC 0x41FE
72 struct pkg_header {
73  unsigned char pkh_magic[2]; /**< @brief Ident */
74  unsigned char pkh_type[2]; /**< @brief Message Type */
75  unsigned char pkh_len[4]; /**< @brief Byte count of remainder */
76 };
77 
78 #define PKG_STREAMLEN (32*1024)
79 struct pkg_conn {
80  int pkc_fd; /**< @brief TCP connection fd */
81  const struct pkg_switch *pkc_switch; /**< @brief Array of message handlers */
82  pkg_errlog pkc_errlog; /**< @brief Error message logger */
83  struct pkg_header pkc_hdr; /**< @brief hdr of cur msg */
84  size_t pkc_len; /**< @brief pkg_len, in host order */
85  unsigned short pkc_type; /**< @brief pkg_type, in host order */
86  void *pkc_user_data; /**< @brief User defined pointer to data for the current pkg_type */
87  /* OUTPUT BUFFER */
88  char pkc_stream[PKG_STREAMLEN]; /**< @brief output stream */
89  unsigned int pkc_magic; /**< @brief for validating pointers */
90  int pkc_strpos; /**< @brief index into stream buffer */
91  /* FIRST LEVEL INPUT BUFFER */
92  char *pkc_inbuf; /**< @brief input stream buffer */
93  int pkc_incur; /**< @brief current pos in inbuf */
94  int pkc_inend; /**< @brief first unused pos in inbuf */
95  int pkc_inlen; /**< @brief length of pkc_inbuf */
96  /* DYNAMIC BUFFER FOR USER */
97  int pkc_left; /**< @brief # bytes pkg_get expects */
98  /* neg->read new hdr, 0->all here, >0 ->more to come */
99  char *pkc_buf; /**< @brief start of dynamic buf */
100  char *pkc_curpos; /**< @brief current position in pkg_buf */
101  void *pkc_server_data; /**< @brief used to hold server data for callbacks */
102 };
103 #define PKC_NULL ((struct pkg_conn *)0)
104 #define PKC_ERROR ((struct pkg_conn *)(-1L))
105 
106 
107 /**
108  * Sends a VLS as a given message type across a pkg connection.
109  */
110 #define pkg_send_vls(type, vlsp, pkg) \
111  pkg_send( (type), bu_vls_addr((vlsp)), bu_vls_strlen((vlsp))+1, (pkg) )
112 
113 
114 /**
115  * Open a network connection to a host/server.
116  *
117  * Returns PKC_ERROR on error.
118  */
119 PKG_EXPORT extern struct pkg_conn *pkg_open(const char *host, const char *service, const char *protocol, const char *username, const char *passwd, const struct pkg_switch* switchp, pkg_errlog errlog);
120 
121 /**
122  * Close a network connection.
123  *
124  * Gracefully release the connection block and close the connection.
125  */
126 PKG_EXPORT extern void pkg_close(struct pkg_conn* pc);
127 
128 PKG_EXPORT extern int pkg_process(struct pkg_conn *);
129 
130 /**
131  * Suck all data from the operating system into the internal buffer.
132  *
133  * This is done with large buffers, to maximize the efficiency of the
134  * data transfer from kernel to user.
135  *
136  * It is expected that the read() system call will return as much data
137  * as the kernel has, UP TO the size indicated. The only time the
138  * read() may be expected to block is when the kernel does not have
139  * any data at all. Thus, it is wise to call call this routine only
140  * if:
141  *
142  * a) select() has indicated the presence of data, or
143  * b) blocking is acceptable.
144  *
145  * This routine is the only place where data is taken off the network.
146  * All input is appended to the internal buffer for later processing.
147  *
148  * Subscripting was used for pkc_incur/pkc_inend to avoid having to
149  * recompute pointers after a realloc().
150  *
151  * Returns -
152  * -1 on error
153  * 0 on EOF
154  * 1 success
155  */
156 PKG_EXPORT extern int pkg_suckin(struct pkg_conn *);
157 
158 /**
159  * Send a message on the connection.
160  *
161  * Send the user's data, prefaced with an identifying header which
162  * contains a message type value. All header fields are exchanged in
163  * "network order".
164  *
165  * Note that the whole message (header + data) should be transmitted
166  * by TCP with only one TCP_PUSH at the end, due to the use of
167  * writev().
168  *
169  * Returns number of bytes of user data actually sent.
170  */
171 PKG_EXPORT extern int pkg_send(int type, const char *buf, size_t len, struct pkg_conn* pc);
172 
173 /**
174  * Send a two part message on the connection.
175  *
176  * Exactly like pkg_send, except user's data is located in two
177  * disjoint buffers, rather than one. Fiendishly useful!
178  */
179 PKG_EXPORT extern int pkg_2send(int type, const char *buf1, size_t len1, const char *buf2, size_t len2, struct pkg_conn* pc);
180 
181 /**
182  * Send a message that doesn't need a push.
183  *
184  * Exactly like pkg_send except no "push" is necessary here. If the
185  * packet is sufficiently small (MAXQLEN) it will be placed in the
186  * pkc_stream buffer (after flushing this buffer if there insufficient
187  * room). If it is larger than this limit, it is sent via pkg_send
188  * (who will do a pkg_flush if there is already data in the stream
189  * queue).
190  *
191  * Returns number of bytes of user data actually sent (or queued).
192  */
193 PKG_EXPORT extern int pkg_stream(int type, const char *buf, size_t len, struct pkg_conn* pc);
194 
195 /**
196  * Empty the stream buffer of any queued messages.
197  *
198  * Flush any pending data in the pkc_stream buffer.
199  *
200  * Returns < 0 on failure, else number of bytes sent.
201  */
202 PKG_EXPORT extern int pkg_flush(struct pkg_conn* pc);
203 
204 /**
205  * Wait for a specific msg, user buf, processing others.
206  *
207  * This routine implements a blocking read on the network connection
208  * until a message of 'type' type is received. This can be useful for
209  * implementing the synchronous portions of a query/reply exchange.
210  * All messages of any other type are processed by pkg_block().
211  *
212  * Returns the length of the message actually received, or -1 on error.
213  */
214 PKG_EXPORT extern int pkg_waitfor(int type, char *buf, size_t len, struct pkg_conn* pc);
215 
216 /**
217  * Wait for specific msg, malloc buf, processing others.
218  *
219  * This routine implements a blocking read on the network connection
220  * until a message of 'type' type is received. This can be useful for
221  * implementing the synchronous portions of a query/reply exchange.
222  * All messages of any other type are processed by pkg_block().
223  *
224  * The buffer to contain the actual message is acquired via malloc(),
225  * and the caller must free it.
226  *
227  * Returns pointer to message buffer, or NULL.
228  */
229 PKG_EXPORT extern char *pkg_bwaitfor(int type, struct pkg_conn* pc);
230 
231 /**
232  * Wait until a full message has been read.
233  *
234  * This routine blocks, waiting for one complete message to arrive
235  * from the network. The actual handling of the message is done with
236  * _pkg_dispatch(), which invokes the user-supplied message handler.
237  *
238  * This routine can be used in a loop to pass the time while waiting
239  * for a flag to be changed by the arrival of an asynchronous message,
240  * or for the arrival of a message of uncertain type.
241  *
242  * The companion routine is pkg_process(), which does not block.
243  *
244  * Control returns to the caller after one full message is processed.
245  * Returns -1 on error, etc.
246  */
247 PKG_EXPORT extern int pkg_block(struct pkg_conn* pc);
248 
249 /**
250  * Become a transient network server
251  *
252  * Become a one-time server on a given open connection. A client has
253  * already called and we have already answered. This will be a
254  * servers starting condition if he was created by a process like the
255  * UNIX inetd.
256  *
257  * Returns PKC_ERROR or a pointer to a pkg_conn structure.
258  */
259 PKG_EXPORT extern struct pkg_conn *pkg_transerver(const struct pkg_switch* switchp, pkg_errlog errlog);
260 
261 /**
262  * Create a network server, and listen for connection.
263  *
264  * We are now going to be a server for the indicated service. Hang a
265  * LISTEN, and return the fd to select() on waiting for new
266  * connections.
267  *
268  * Returns fd to listen on (>=0), -1 on error.
269  */
270 PKG_EXPORT extern int pkg_permserver(const char *service, const char *protocol, int backlog, pkg_errlog);
271 
272 /**
273  * Create network server from IP address, and listen for connection.
274  *
275  * We are now going to be a server for the indicated service. Hang a
276  * LISTEN, and return the fd to select() on waiting for new
277  * connections.
278  *
279  * Returns fd to listen on (>=0), -1 on error.
280  */
281 PKG_EXPORT extern int pkg_permserver_ip(const char *ipOrHostname, const char *service, const char *protocol, int backlog, pkg_errlog errlog);
282 
283 /**
284  * As permanent network server, accept a new connection
285  *
286  * Given an fd with a listen outstanding, accept the connection. When
287  * poll == 0, accept is allowed to block. When poll != 0, accept will
288  * not block.
289  *
290  * Returns -
291  * >0 ptr to pkg_conn block of new connection
292  * PKC_NULL accept would block, try again later
293  * PKC_ERROR fatal error
294  */
295 PKG_EXPORT extern struct pkg_conn *pkg_getclient(int fd, const struct pkg_switch *switchp, pkg_errlog errlog, int nodelay);
296 
297 
298 /****************************
299  * Data conversion routines *
300  ****************************/
301 
302 /**
303  * Get a 16-bit short from a char[2] array
304  */
305 PKG_EXPORT extern unsigned short pkg_gshort(char *buf);
306 
307 /**
308  * Get a 32-bit long from a char[4] array
309  */
310 PKG_EXPORT extern unsigned long pkg_glong(char *buf);
311 
312 /**
313  * Put a 16-bit short into a char[2] array
314  */
315 PKG_EXPORT extern char *pkg_pshort(char *buf, unsigned short s);
316 
317 /**
318  * Put a 32-bit long into a char[4] array
319  */
320 PKG_EXPORT extern char *pkg_plong(char *buf, unsigned long l);
321 
322 /**
323  * returns a human-readable string describing this version of the
324  * LIBPKG library.
325  */
326 PKG_EXPORT extern const char *pkg_version(void);
327 
328 #ifdef __cplusplus
329 }
330 #endif
331 
332 #endif /* PKG_H */
333 
334 /** @} */
335 /*
336  * Local Variables:
337  * mode: C
338  * tab-width: 8
339  * indent-tabs-mode: t
340  * c-file-style: "stroustrup"
341  * End:
342  * ex: shiftwidth=4 tabstop=8
343  */
const struct pkg_switch * pkc_switch
Array of message handlers.
Definition: pkg.h:81
char * pkc_inbuf
input stream buffer
Definition: pkg.h:92
int pkc_incur
current pos in inbuf
Definition: pkg.h:93
char * pkg_plong(char *buf, unsigned long l)
Definition: pkg.c:190
void pkg_close(struct pkg_conn *pc)
Definition: pkg.c:800
struct pkg_header pkc_hdr
hdr of cur msg
Definition: pkg.h:83
unsigned short pks_type
Type code.
Definition: pkg.h:58
if lu s
Definition: nmg_mod.c:3860
unsigned char pkh_len[4]
Byte count of remainder.
Definition: pkg.h:75
pkg_errlog pkc_errlog
Error message logger.
Definition: pkg.h:82
int pkc_inend
first unused pos in inbuf
Definition: pkg.h:94
int pkg_process(struct pkg_conn *)
Definition: pkg.c:1560
int pkc_fd
TCP connection fd.
Definition: pkg.h:80
struct pkg_conn * pkg_open(const char *host, const char *service, const char *protocol, const char *username, const char *passwd, const struct pkg_switch *switchp, pkg_errlog errlog)
unsigned short pkc_type
pkg_type, in host order
Definition: pkg.h:85
void(* pkg_errlog)(const char *msg)
Definition: pkg.h:55
int pkg_flush(struct pkg_conn *pc)
Definition: pkg.c:1243
int pkg_send(int type, const char *buf, size_t len, struct pkg_conn *pc)
Definition: pkg.c:934
void * pks_user_data
User defined pointer to data.
Definition: pkg.h:61
unsigned int pkc_magic
for validating pointers
Definition: pkg.h:89
int pkc_left
bytes pkg_get expects
Definition: pkg.h:97
int pkg_permserver_ip(const char *ipOrHostname, const char *service, const char *protocol, int backlog, pkg_errlog errlog)
struct pkg_conn * pkg_transerver(const struct pkg_switch *switchp, pkg_errlog errlog)
char * pkg_pshort(char *buf, unsigned short s)
Definition: pkg.c:181
unsigned char pkh_magic[2]
Ident.
Definition: pkg.h:73
Definition: pkg.h:72
int pkc_inlen
length of pkc_inbuf
Definition: pkg.h:95
unsigned char pkh_type[2]
Message Type.
Definition: pkg.h:74
int pkc_strpos
index into stream buffer
Definition: pkg.h:90
int pkg_waitfor(int type, char *buf, size_t len, struct pkg_conn *pc)
Definition: pkg.c:1355
#define PKG_STREAMLEN
Definition: pkg.h:78
Definition: pkg.h:57
const char * pkg_version(void)
Definition: vers.c:31
char * pkc_curpos
current position in pkg_buf
Definition: pkg.h:100
size_t pkc_len
pkg_len, in host order
Definition: pkg.h:84
char * pkg_bwaitfor(int type, struct pkg_conn *pc)
Definition: pkg.c:1448
unsigned short pkg_gshort(char *buf)
Definition: pkg.c:157
void * pkc_user_data
User defined pointer to data for the current pkg_type.
Definition: pkg.h:86
unsigned long pkg_glong(char *buf)
Definition: pkg.c:168
const char * pks_title
Description of message type.
Definition: pkg.h:60
int pkg_permserver(const char *service, const char *protocol, int backlog, pkg_errlog)
Definition: pkg.h:79
int pkg_block(struct pkg_conn *pc)
Definition: pkg.c:1682
void(* pkg_callback)(struct pkg_conn *, char *)
Definition: pkg.h:54
int pkg_suckin(struct pkg_conn *)
Definition: pkg.c:1715
void * pkc_server_data
used to hold server data for callbacks
Definition: pkg.h:101
int pkg_2send(int type, const char *buf1, size_t len1, const char *buf2, size_t len2, struct pkg_conn *pc)
Definition: pkg.c:1061
pkg_callback pks_handler
Message Handler.
Definition: pkg.h:59
char * pkc_buf
start of dynamic buf
Definition: pkg.h:99
struct pkg_conn * pkg_getclient(int fd, const struct pkg_switch *switchp, pkg_errlog errlog, int nodelay)
int pkg_stream(int type, const char *buf, size_t len, struct pkg_conn *pc)
Definition: pkg.c:1210
char pkc_stream[PKG_STREAMLEN]
output stream
Definition: pkg.h:88