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