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