BRL-CAD
Loading...
Searching...
No Matches
pkg.h
Go to the documentation of this file.
1/* P K G . H
2 * BRL-CAD
3 *
4 * Copyright (c) 2004-2025 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
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 */
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 */
122#define PKC_NULL ((struct pkg_conn *)0)
123#define PKC_ERROR ((struct pkg_conn *)(-1L))
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 */
138PKG_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);
140/**
141 * Close a network connection.
142 *
143 * Gracefully release the connection block and close the connection.
144 */
145PKG_EXPORT extern void pkg_close(struct pkg_conn* pc);
147PKG_EXPORT extern int pkg_process(struct pkg_conn *);
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 */
175PKG_EXPORT extern int pkg_suckin(struct pkg_conn *);
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 */
190PKG_EXPORT extern int pkg_send(int type, const char *buf, size_t len, struct pkg_conn* pc);
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 */
198PKG_EXPORT extern int pkg_2send(int type, const char *buf1, size_t len1, const char *buf2, size_t len2, struct pkg_conn* pc);
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 */
212PKG_EXPORT extern int pkg_stream(int type, const char *buf, size_t len, struct pkg_conn* pc);
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 */
221PKG_EXPORT extern int pkg_flush(struct pkg_conn* pc);
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 */
233PKG_EXPORT extern int pkg_waitfor(int type, char *buf, size_t len, struct pkg_conn* pc);
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 */
248PKG_EXPORT extern char *pkg_bwaitfor(int type, struct pkg_conn* pc);
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 */
266PKG_EXPORT extern int pkg_block(struct pkg_conn* pc);
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 */
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 */
289PKG_EXPORT extern int pkg_permserver(const char *service, const char *protocol, int backlog, pkg_errlog);
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 */
300PKG_EXPORT extern int pkg_permserver_ip(const char *ipOrHostname, const char *service, const char *protocol, int backlog, pkg_errlog errlog);
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 */
314PKG_EXPORT extern struct pkg_conn *pkg_getclient(int fd, const struct pkg_switch *switchp, pkg_errlog errlog, int nodelay);
316
317/****************************
318 * Data conversion routines *
319 ****************************/
320
321/**
322 * Get a 16-bit short from a char[2] array
323 */
324PKG_EXPORT extern unsigned short pkg_gshort(char *buf);
326/**
327 * Get a 32-bit long from a char[4] array
328 */
329PKG_EXPORT extern unsigned long pkg_glong(char *buf);
331/**
332 * Put a 16-bit short into a char[2] array
333 */
334PKG_EXPORT extern char *pkg_pshort(char *buf, unsigned short s);
336/**
337 * Put a 32-bit long into a char[4] array
338 */
339PKG_EXPORT extern char *pkg_plong(char *buf, unsigned long l);
341/**
342 * returns a human-readable string describing this version of the
343 * LIBPKG library.
344 */
345PKG_EXPORT extern const char *pkg_version(void);
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 */
Definition dvec.h:74
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)
#define PKG_STDIO_MODE
Definition pkg.h:54
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: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
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
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