xref: /freebsd/contrib/unbound/util/tube.h (revision 865f46b255599c4a645e84a4cbb5ea7abdc0e207)
1b7579f77SDag-Erling Smørgrav /*
2b7579f77SDag-Erling Smørgrav  * util/tube.h - pipe service
3b7579f77SDag-Erling Smørgrav  *
4b7579f77SDag-Erling Smørgrav  * Copyright (c) 2008, NLnet Labs. All rights reserved.
5b7579f77SDag-Erling Smørgrav  *
6b7579f77SDag-Erling Smørgrav  * This software is open source.
7b7579f77SDag-Erling Smørgrav  *
8b7579f77SDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
9b7579f77SDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
10b7579f77SDag-Erling Smørgrav  * are met:
11b7579f77SDag-Erling Smørgrav  *
12b7579f77SDag-Erling Smørgrav  * Redistributions of source code must retain the above copyright notice,
13b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer.
14b7579f77SDag-Erling Smørgrav  *
15b7579f77SDag-Erling Smørgrav  * Redistributions in binary form must reproduce the above copyright notice,
16b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer in the documentation
17b7579f77SDag-Erling Smørgrav  * and/or other materials provided with the distribution.
18b7579f77SDag-Erling Smørgrav  *
19b7579f77SDag-Erling Smørgrav  * Neither the name of the NLNET LABS nor the names of its contributors may
20b7579f77SDag-Erling Smørgrav  * be used to endorse or promote products derived from this software without
21b7579f77SDag-Erling Smørgrav  * specific prior written permission.
22b7579f77SDag-Erling Smørgrav  *
23b7579f77SDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2417d15b25SDag-Erling Smørgrav  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2517d15b25SDag-Erling Smørgrav  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2617d15b25SDag-Erling Smørgrav  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2717d15b25SDag-Erling Smørgrav  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2817d15b25SDag-Erling Smørgrav  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2917d15b25SDag-Erling Smørgrav  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3017d15b25SDag-Erling Smørgrav  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3117d15b25SDag-Erling Smørgrav  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3217d15b25SDag-Erling Smørgrav  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3317d15b25SDag-Erling Smørgrav  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34b7579f77SDag-Erling Smørgrav  */
35b7579f77SDag-Erling Smørgrav 
36b7579f77SDag-Erling Smørgrav /**
37b7579f77SDag-Erling Smørgrav  * \file
38b7579f77SDag-Erling Smørgrav  *
39b7579f77SDag-Erling Smørgrav  * This file contains pipe service functions.
40b7579f77SDag-Erling Smørgrav  */
41b7579f77SDag-Erling Smørgrav 
42b7579f77SDag-Erling Smørgrav #ifndef UTIL_TUBE_H
43b7579f77SDag-Erling Smørgrav #define UTIL_TUBE_H
44b7579f77SDag-Erling Smørgrav struct comm_reply;
45b7579f77SDag-Erling Smørgrav struct comm_point;
46b7579f77SDag-Erling Smørgrav struct comm_base;
47b7579f77SDag-Erling Smørgrav struct tube;
48b7579f77SDag-Erling Smørgrav struct tube_res_list;
49b7579f77SDag-Erling Smørgrav #ifdef USE_WINSOCK
50b7579f77SDag-Erling Smørgrav #include "util/locks.h"
51b7579f77SDag-Erling Smørgrav #endif
52b7579f77SDag-Erling Smørgrav 
53b7579f77SDag-Erling Smørgrav /**
54b7579f77SDag-Erling Smørgrav  * Callback from pipe listen function
55b7579f77SDag-Erling Smørgrav  * void mycallback(tube, msg, len, error, user_argument);
56b7579f77SDag-Erling Smørgrav  * if error is true (NETEVENT_*), msg is probably NULL.
57b7579f77SDag-Erling Smørgrav  */
583005e0a3SDag-Erling Smørgrav typedef void tube_callback_type(struct tube*, uint8_t*, size_t, int, void*);
59b7579f77SDag-Erling Smørgrav 
60b7579f77SDag-Erling Smørgrav /**
61b7579f77SDag-Erling Smørgrav  * A pipe
62b7579f77SDag-Erling Smørgrav  */
63b7579f77SDag-Erling Smørgrav struct tube {
64b7579f77SDag-Erling Smørgrav #ifndef USE_WINSOCK
65b7579f77SDag-Erling Smørgrav 	/** pipe end to read from */
66b7579f77SDag-Erling Smørgrav 	int sr;
67b7579f77SDag-Erling Smørgrav 	/** pipe end to write on */
68b7579f77SDag-Erling Smørgrav 	int sw;
69b7579f77SDag-Erling Smørgrav 
70b7579f77SDag-Erling Smørgrav 	/** listen commpoint */
71b7579f77SDag-Erling Smørgrav 	struct comm_point* listen_com;
72b7579f77SDag-Erling Smørgrav 	/** listen callback */
733005e0a3SDag-Erling Smørgrav 	tube_callback_type* listen_cb;
74b7579f77SDag-Erling Smørgrav 	/** listen callback user arg */
75b7579f77SDag-Erling Smørgrav 	void* listen_arg;
76b7579f77SDag-Erling Smørgrav 	/** are we currently reading a command, 0 if not, else bytecount */
77b7579f77SDag-Erling Smørgrav 	size_t cmd_read;
78b7579f77SDag-Erling Smørgrav 	/** size of current read command, may be partially read */
79b7579f77SDag-Erling Smørgrav 	uint32_t cmd_len;
80b7579f77SDag-Erling Smørgrav 	/** the current read command content, malloced, can be partially read*/
81b7579f77SDag-Erling Smørgrav 	uint8_t* cmd_msg;
82b7579f77SDag-Erling Smørgrav 
83b7579f77SDag-Erling Smørgrav 	/** background write queue, commpoint to write results back */
84b7579f77SDag-Erling Smørgrav 	struct comm_point* res_com;
8505ab2901SDag-Erling Smørgrav 	/** are we currently writing a result, 0 if not, else bytecount into
86b7579f77SDag-Erling Smørgrav 	 * the res_list first entry. */
87b7579f77SDag-Erling Smørgrav 	size_t res_write;
88b7579f77SDag-Erling Smørgrav 	/** list of outstanding results to be written back */
89b7579f77SDag-Erling Smørgrav 	struct tube_res_list* res_list;
90b7579f77SDag-Erling Smørgrav 	/** last in list */
91b7579f77SDag-Erling Smørgrav 	struct tube_res_list* res_last;
92b7579f77SDag-Erling Smørgrav 
93b7579f77SDag-Erling Smørgrav #else /* USE_WINSOCK */
94b7579f77SDag-Erling Smørgrav 	/** listen callback */
953005e0a3SDag-Erling Smørgrav 	tube_callback_type* listen_cb;
96b7579f77SDag-Erling Smørgrav 	/** listen callback user arg */
97b7579f77SDag-Erling Smørgrav 	void* listen_arg;
98b7579f77SDag-Erling Smørgrav 	/** the windows sockets event (signaled if items in pipe) */
99b7579f77SDag-Erling Smørgrav 	WSAEVENT event;
100b7579f77SDag-Erling Smørgrav 	/** winsock event storage when registered with event base */
101e2d15004SDag-Erling Smørgrav 	struct ub_event* ev_listen;
102b7579f77SDag-Erling Smørgrav 
103b7579f77SDag-Erling Smørgrav 	/** lock on the list of outstanding items */
1043005e0a3SDag-Erling Smørgrav 	lock_basic_type res_lock;
105b7579f77SDag-Erling Smørgrav 	/** list of outstanding results on pipe */
106b7579f77SDag-Erling Smørgrav 	struct tube_res_list* res_list;
107b7579f77SDag-Erling Smørgrav 	/** last in list */
108b7579f77SDag-Erling Smørgrav 	struct tube_res_list* res_last;
109b7579f77SDag-Erling Smørgrav #endif /* USE_WINSOCK */
110b7579f77SDag-Erling Smørgrav };
111b7579f77SDag-Erling Smørgrav 
112b7579f77SDag-Erling Smørgrav /**
113b7579f77SDag-Erling Smørgrav  * List of results (arbitrary command serializations) to write back
114b7579f77SDag-Erling Smørgrav  */
115b7579f77SDag-Erling Smørgrav struct tube_res_list {
116b7579f77SDag-Erling Smørgrav 	/** next in list */
117b7579f77SDag-Erling Smørgrav 	struct tube_res_list* next;
118b7579f77SDag-Erling Smørgrav 	/** serialized buffer to write */
119b7579f77SDag-Erling Smørgrav 	uint8_t* buf;
120b7579f77SDag-Erling Smørgrav 	/** length to write */
121b7579f77SDag-Erling Smørgrav 	uint32_t len;
122b7579f77SDag-Erling Smørgrav };
123b7579f77SDag-Erling Smørgrav 
124b7579f77SDag-Erling Smørgrav /**
125b7579f77SDag-Erling Smørgrav  * Create a pipe
126b7579f77SDag-Erling Smørgrav  * @return: new tube struct or NULL on error.
127b7579f77SDag-Erling Smørgrav  */
128b7579f77SDag-Erling Smørgrav struct tube* tube_create(void);
129b7579f77SDag-Erling Smørgrav 
130b7579f77SDag-Erling Smørgrav /**
131b7579f77SDag-Erling Smørgrav  * Delete and destroy a pipe
132b7579f77SDag-Erling Smørgrav  * @param tube: to delete
133b7579f77SDag-Erling Smørgrav  */
134b7579f77SDag-Erling Smørgrav void tube_delete(struct tube* tube);
135b7579f77SDag-Erling Smørgrav 
136b7579f77SDag-Erling Smørgrav /**
137b7579f77SDag-Erling Smørgrav  * Write length bytes followed by message.
138b7579f77SDag-Erling Smørgrav  * @param tube: the tube to write on.
139b7579f77SDag-Erling Smørgrav  *     If that tube is a pipe, its write fd is used as
140b7579f77SDag-Erling Smørgrav  *     the socket to write on. Is nonblocking.
141b7579f77SDag-Erling Smørgrav  *      Set to blocking by the function,
142b7579f77SDag-Erling Smørgrav  *      and back to non-blocking at exit of function.
143b7579f77SDag-Erling Smørgrav  * @param buf: the message.
144b7579f77SDag-Erling Smørgrav  * @param len: length of message.
145b7579f77SDag-Erling Smørgrav  * @param nonblock: if set to true, the first write is nonblocking.
146b7579f77SDag-Erling Smørgrav  *      If the first write fails the function returns -1.
147b7579f77SDag-Erling Smørgrav  *      If set false, the first write is blocking.
148b7579f77SDag-Erling Smørgrav  * @return: all remainder writes are nonblocking.
149b7579f77SDag-Erling Smørgrav  *      return 0 on error, in that case blocking/nonblocking of socket is
150b7579f77SDag-Erling Smørgrav  *              unknown.
151b7579f77SDag-Erling Smørgrav  *      return 1 if all OK.
152b7579f77SDag-Erling Smørgrav  */
153b7579f77SDag-Erling Smørgrav int tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len,
154b7579f77SDag-Erling Smørgrav 	int nonblock);
155b7579f77SDag-Erling Smørgrav 
156b7579f77SDag-Erling Smørgrav /**
157b7579f77SDag-Erling Smørgrav  * Read length bytes followed by message.
158b7579f77SDag-Erling Smørgrav  * @param tube: The tube to read on.
159b7579f77SDag-Erling Smørgrav  *     If that tube is a pipe, its read fd is used as
160b7579f77SDag-Erling Smørgrav  *     the socket to read on. Is nonblocking.
161b7579f77SDag-Erling Smørgrav  *      Set to blocking by the function,
162b7579f77SDag-Erling Smørgrav  *      and back to non-blocking at exit of function.
163b7579f77SDag-Erling Smørgrav  * @param buf: the message, malloced.
164b7579f77SDag-Erling Smørgrav  * @param len: length of message, returned.
165b7579f77SDag-Erling Smørgrav  * @param nonblock: if set to true, the first read is nonblocking.
166b7579f77SDag-Erling Smørgrav  *      If the first read fails the function returns -1.
167b7579f77SDag-Erling Smørgrav  *      If set false, the first read is blocking.
168b7579f77SDag-Erling Smørgrav  * @return: all remainder reads are nonblocking.
169b7579f77SDag-Erling Smørgrav  *      return 0 on error, in that case blocking/nonblocking of socket is
170b7579f77SDag-Erling Smørgrav  *              unknown. On EOF 0 is returned.
171b7579f77SDag-Erling Smørgrav  *      return 1 if all OK.
172b7579f77SDag-Erling Smørgrav  */
173b7579f77SDag-Erling Smørgrav int tube_read_msg(struct tube* tube, uint8_t** buf, uint32_t* len,
174b7579f77SDag-Erling Smørgrav 	int nonblock);
175b7579f77SDag-Erling Smørgrav 
176b7579f77SDag-Erling Smørgrav /**
177b7579f77SDag-Erling Smørgrav  * Close read part of the pipe.
178b7579f77SDag-Erling Smørgrav  * The tube can no longer be read from.
179b7579f77SDag-Erling Smørgrav  * @param tube: tube to operate on.
180b7579f77SDag-Erling Smørgrav  */
181b7579f77SDag-Erling Smørgrav void tube_close_read(struct tube* tube);
182b7579f77SDag-Erling Smørgrav 
183b7579f77SDag-Erling Smørgrav /**
184b7579f77SDag-Erling Smørgrav  * Close write part of the pipe.
185b7579f77SDag-Erling Smørgrav  * The tube can no longer be written to.
186b7579f77SDag-Erling Smørgrav  * @param tube: tube to operate on.
187b7579f77SDag-Erling Smørgrav  */
188b7579f77SDag-Erling Smørgrav void tube_close_write(struct tube* tube);
189b7579f77SDag-Erling Smørgrav 
190b7579f77SDag-Erling Smørgrav /**
191b7579f77SDag-Erling Smørgrav  * See if data is ready for reading on the tube without blocking.
192b7579f77SDag-Erling Smørgrav  * @param tube: tube to check for readable items
193b7579f77SDag-Erling Smørgrav  * @return true if readable items are present. False if not (or error).
194b7579f77SDag-Erling Smørgrav  *     true on pipe_closed.
195b7579f77SDag-Erling Smørgrav  */
196b7579f77SDag-Erling Smørgrav int tube_poll(struct tube* tube);
197b7579f77SDag-Erling Smørgrav 
198b7579f77SDag-Erling Smørgrav /**
199b7579f77SDag-Erling Smørgrav  * Wait for data to be ready for reading on the tube. is blocking.
200b7579f77SDag-Erling Smørgrav  * No timeout.
201b7579f77SDag-Erling Smørgrav  * @param tube: the tube to wait on.
202b7579f77SDag-Erling Smørgrav  * @return: if there was something to read (false on error).
203b7579f77SDag-Erling Smørgrav  *     true on pipe_closed.
204b7579f77SDag-Erling Smørgrav  */
205b7579f77SDag-Erling Smørgrav int tube_wait(struct tube* tube);
206b7579f77SDag-Erling Smørgrav 
207b7579f77SDag-Erling Smørgrav /**
208*865f46b2SCy Schubert  * Wait for data to be ready with a timeout.
209*865f46b2SCy Schubert  * @param tube: the tube to wait on.
210*865f46b2SCy Schubert  * @param msec: timeout in milliseconds.
211*865f46b2SCy Schubert  * @return 1 if there is something to read within timeout, readability.
212*865f46b2SCy Schubert  * 	0 on a timeout. On failures -1, like errors. */
213*865f46b2SCy Schubert int tube_wait_timeout(struct tube* tube, int msec);
214*865f46b2SCy Schubert 
215*865f46b2SCy Schubert /**
216b7579f77SDag-Erling Smørgrav  * Get FD that is readable when new information arrives.
217b7579f77SDag-Erling Smørgrav  * @param tube
218b7579f77SDag-Erling Smørgrav  * @return file descriptor.
219b7579f77SDag-Erling Smørgrav  */
220b7579f77SDag-Erling Smørgrav int tube_read_fd(struct tube* tube);
221b7579f77SDag-Erling Smørgrav 
222b7579f77SDag-Erling Smørgrav /**
223b7579f77SDag-Erling Smørgrav  * Start listening for information over the pipe.
224b7579f77SDag-Erling Smørgrav  * Background registration of a read listener, callback when read completed.
225b7579f77SDag-Erling Smørgrav  * Do not mix with tube_read_msg style direct reads from the pipe.
226b7579f77SDag-Erling Smørgrav  * @param tube: tube to listen on
227b7579f77SDag-Erling Smørgrav  * @param base: what base to register event callback.
228b7579f77SDag-Erling Smørgrav  * @param cb: callback routine.
229b7579f77SDag-Erling Smørgrav  * @param arg: user argument for callback routine.
230b7579f77SDag-Erling Smørgrav  * @return true if successful, false on error.
231b7579f77SDag-Erling Smørgrav  */
232b7579f77SDag-Erling Smørgrav int tube_setup_bg_listen(struct tube* tube, struct comm_base* base,
2333005e0a3SDag-Erling Smørgrav 	tube_callback_type* cb, void* arg);
234b7579f77SDag-Erling Smørgrav 
235b7579f77SDag-Erling Smørgrav /**
236b7579f77SDag-Erling Smørgrav  * Remove bg listen setup from event base.
237b7579f77SDag-Erling Smørgrav  * @param tube: what tube to cleanup
238b7579f77SDag-Erling Smørgrav  */
239b7579f77SDag-Erling Smørgrav void tube_remove_bg_listen(struct tube* tube);
240b7579f77SDag-Erling Smørgrav 
241b7579f77SDag-Erling Smørgrav /**
242b7579f77SDag-Erling Smørgrav  * Start background write handler for the pipe.
243b7579f77SDag-Erling Smørgrav  * Do not mix with tube_write_msg style direct writes to the pipe.
244b7579f77SDag-Erling Smørgrav  * @param tube: tube to write on
245b7579f77SDag-Erling Smørgrav  * @param base: what base to register event handler on.
246b7579f77SDag-Erling Smørgrav  * @return true if successful, false on error.
247b7579f77SDag-Erling Smørgrav  */
248b7579f77SDag-Erling Smørgrav int tube_setup_bg_write(struct tube* tube, struct comm_base* base);
249b7579f77SDag-Erling Smørgrav 
250b7579f77SDag-Erling Smørgrav /**
251b7579f77SDag-Erling Smørgrav  * Remove bg write setup from event base.
252b7579f77SDag-Erling Smørgrav  * @param tube: what tube to cleanup
253b7579f77SDag-Erling Smørgrav  */
254b7579f77SDag-Erling Smørgrav void tube_remove_bg_write(struct tube* tube);
255b7579f77SDag-Erling Smørgrav 
256b7579f77SDag-Erling Smørgrav 
257b7579f77SDag-Erling Smørgrav /**
258b7579f77SDag-Erling Smørgrav  * Append data item to background list of writes.
259b7579f77SDag-Erling Smørgrav  * Mallocs a list entry behind the scenes.
260b7579f77SDag-Erling Smørgrav  * Not locked behind the scenes, call from one thread or lock on outside.
261b7579f77SDag-Erling Smørgrav  * @param tube: what tube to queue on.
262b7579f77SDag-Erling Smørgrav  * @param msg: memory message to send. Is free()d after use.
263b7579f77SDag-Erling Smørgrav  * 	Put at the end of the to-send queue.
264b7579f77SDag-Erling Smørgrav  * @param len: length of item.
265b7579f77SDag-Erling Smørgrav  * @return 0 on failure (msg freed).
266b7579f77SDag-Erling Smørgrav  */
267b7579f77SDag-Erling Smørgrav int tube_queue_item(struct tube* tube, uint8_t* msg, size_t len);
268b7579f77SDag-Erling Smørgrav 
269b7579f77SDag-Erling Smørgrav /** for fptr wlist, callback function */
270b7579f77SDag-Erling Smørgrav int tube_handle_listen(struct comm_point* c, void* arg, int error,
271b7579f77SDag-Erling Smørgrav 	struct comm_reply* reply_info);
272b7579f77SDag-Erling Smørgrav 
273b7579f77SDag-Erling Smørgrav /** for fptr wlist, callback function */
274b7579f77SDag-Erling Smørgrav int tube_handle_write(struct comm_point* c, void* arg, int error,
275b7579f77SDag-Erling Smørgrav 	struct comm_reply* reply_info);
276b7579f77SDag-Erling Smørgrav 
277b7579f77SDag-Erling Smørgrav /** for fptr wlist, winsock signal event callback function */
278b7579f77SDag-Erling Smørgrav void tube_handle_signal(int fd, short events, void* arg);
279b7579f77SDag-Erling Smørgrav 
280b7579f77SDag-Erling Smørgrav #endif /* UTIL_TUBE_H */
281