1238106Sdes/*
2238106Sdes * util/tube.h - pipe service
3238106Sdes *
4238106Sdes * Copyright (c) 2008, NLnet Labs. All rights reserved.
5238106Sdes *
6238106Sdes * This software is open source.
7238106Sdes *
8238106Sdes * Redistribution and use in source and binary forms, with or without
9238106Sdes * modification, are permitted provided that the following conditions
10238106Sdes * are met:
11238106Sdes *
12238106Sdes * Redistributions of source code must retain the above copyright notice,
13238106Sdes * this list of conditions and the following disclaimer.
14238106Sdes *
15238106Sdes * Redistributions in binary form must reproduce the above copyright notice,
16238106Sdes * this list of conditions and the following disclaimer in the documentation
17238106Sdes * and/or other materials provided with the distribution.
18238106Sdes *
19238106Sdes * Neither the name of the NLNET LABS nor the names of its contributors may
20238106Sdes * be used to endorse or promote products derived from this software without
21238106Sdes * specific prior written permission.
22238106Sdes *
23238106Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24269257Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25269257Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26269257Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27269257Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28269257Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29269257Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30269257Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31269257Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32269257Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33269257Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34238106Sdes */
35238106Sdes
36238106Sdes/**
37238106Sdes * \file
38238106Sdes *
39238106Sdes * This file contains pipe service functions.
40238106Sdes */
41238106Sdes
42238106Sdes#ifndef UTIL_TUBE_H
43238106Sdes#define UTIL_TUBE_H
44238106Sdesstruct comm_reply;
45238106Sdesstruct comm_point;
46238106Sdesstruct comm_base;
47238106Sdesstruct tube;
48238106Sdesstruct tube_res_list;
49238106Sdes#ifdef USE_WINSOCK
50238106Sdes#include "util/locks.h"
51238106Sdes#include "util/winsock_event.h"
52238106Sdes#endif
53238106Sdes
54238106Sdes/**
55238106Sdes * Callback from pipe listen function
56238106Sdes * void mycallback(tube, msg, len, error, user_argument);
57238106Sdes * if error is true (NETEVENT_*), msg is probably NULL.
58238106Sdes */
59238106Sdestypedef void tube_callback_t(struct tube*, uint8_t*, size_t, int, void*);
60238106Sdes
61238106Sdes/**
62238106Sdes * A pipe
63238106Sdes */
64238106Sdesstruct tube {
65238106Sdes#ifndef USE_WINSOCK
66238106Sdes	/** pipe end to read from */
67238106Sdes	int sr;
68238106Sdes	/** pipe end to write on */
69238106Sdes	int sw;
70238106Sdes
71238106Sdes	/** listen commpoint */
72238106Sdes	struct comm_point* listen_com;
73238106Sdes	/** listen callback */
74238106Sdes	tube_callback_t* listen_cb;
75238106Sdes	/** listen callback user arg */
76238106Sdes	void* listen_arg;
77238106Sdes	/** are we currently reading a command, 0 if not, else bytecount */
78238106Sdes	size_t cmd_read;
79238106Sdes	/** size of current read command, may be partially read */
80238106Sdes	uint32_t cmd_len;
81238106Sdes	/** the current read command content, malloced, can be partially read*/
82238106Sdes	uint8_t* cmd_msg;
83238106Sdes
84238106Sdes	/** background write queue, commpoint to write results back */
85238106Sdes	struct comm_point* res_com;
86294190Sdes	/** are we currently writing a result, 0 if not, else bytecount into
87238106Sdes	 * the res_list first entry. */
88238106Sdes	size_t res_write;
89238106Sdes	/** list of outstanding results to be written back */
90238106Sdes	struct tube_res_list* res_list;
91238106Sdes	/** last in list */
92238106Sdes	struct tube_res_list* res_last;
93238106Sdes
94238106Sdes#else /* USE_WINSOCK */
95238106Sdes	/** listen callback */
96238106Sdes	tube_callback_t* listen_cb;
97238106Sdes	/** listen callback user arg */
98238106Sdes	void* listen_arg;
99238106Sdes	/** the windows sockets event (signaled if items in pipe) */
100238106Sdes	WSAEVENT event;
101238106Sdes	/** winsock event storage when registered with event base */
102238106Sdes	struct event ev_listen;
103238106Sdes
104238106Sdes	/** lock on the list of outstanding items */
105238106Sdes	lock_basic_t res_lock;
106238106Sdes	/** list of outstanding results on pipe */
107238106Sdes	struct tube_res_list* res_list;
108238106Sdes	/** last in list */
109238106Sdes	struct tube_res_list* res_last;
110238106Sdes#endif /* USE_WINSOCK */
111238106Sdes};
112238106Sdes
113238106Sdes/**
114238106Sdes * List of results (arbitrary command serializations) to write back
115238106Sdes */
116238106Sdesstruct tube_res_list {
117238106Sdes	/** next in list */
118238106Sdes	struct tube_res_list* next;
119238106Sdes	/** serialized buffer to write */
120238106Sdes	uint8_t* buf;
121238106Sdes	/** length to write */
122238106Sdes	uint32_t len;
123238106Sdes};
124238106Sdes
125238106Sdes/**
126238106Sdes * Create a pipe
127238106Sdes * @return: new tube struct or NULL on error.
128238106Sdes */
129238106Sdesstruct tube* tube_create(void);
130238106Sdes
131238106Sdes/**
132238106Sdes * Delete and destroy a pipe
133238106Sdes * @param tube: to delete
134238106Sdes */
135238106Sdesvoid tube_delete(struct tube* tube);
136238106Sdes
137238106Sdes/**
138238106Sdes * Write length bytes followed by message.
139238106Sdes * @param tube: the tube to write on.
140238106Sdes *     If that tube is a pipe, its write fd is used as
141238106Sdes *     the socket to write on. Is nonblocking.
142238106Sdes *      Set to blocking by the function,
143238106Sdes *      and back to non-blocking at exit of function.
144238106Sdes * @param buf: the message.
145238106Sdes * @param len: length of message.
146238106Sdes * @param nonblock: if set to true, the first write is nonblocking.
147238106Sdes *      If the first write fails the function returns -1.
148238106Sdes *      If set false, the first write is blocking.
149238106Sdes * @return: all remainder writes are nonblocking.
150238106Sdes *      return 0 on error, in that case blocking/nonblocking of socket is
151238106Sdes *              unknown.
152238106Sdes *      return 1 if all OK.
153238106Sdes */
154238106Sdesint tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len,
155238106Sdes	int nonblock);
156238106Sdes
157238106Sdes/**
158238106Sdes * Read length bytes followed by message.
159238106Sdes * @param tube: The tube to read on.
160238106Sdes *     If that tube is a pipe, its read fd is used as
161238106Sdes *     the socket to read on. Is nonblocking.
162238106Sdes *      Set to blocking by the function,
163238106Sdes *      and back to non-blocking at exit of function.
164238106Sdes * @param buf: the message, malloced.
165238106Sdes * @param len: length of message, returned.
166238106Sdes * @param nonblock: if set to true, the first read is nonblocking.
167238106Sdes *      If the first read fails the function returns -1.
168238106Sdes *      If set false, the first read is blocking.
169238106Sdes * @return: all remainder reads are nonblocking.
170238106Sdes *      return 0 on error, in that case blocking/nonblocking of socket is
171238106Sdes *              unknown. On EOF 0 is returned.
172238106Sdes *      return 1 if all OK.
173238106Sdes */
174238106Sdesint tube_read_msg(struct tube* tube, uint8_t** buf, uint32_t* len,
175238106Sdes	int nonblock);
176238106Sdes
177238106Sdes/**
178238106Sdes * Close read part of the pipe.
179238106Sdes * The tube can no longer be read from.
180238106Sdes * @param tube: tube to operate on.
181238106Sdes */
182238106Sdesvoid tube_close_read(struct tube* tube);
183238106Sdes
184238106Sdes/**
185238106Sdes * Close write part of the pipe.
186238106Sdes * The tube can no longer be written to.
187238106Sdes * @param tube: tube to operate on.
188238106Sdes */
189238106Sdesvoid tube_close_write(struct tube* tube);
190238106Sdes
191238106Sdes/**
192238106Sdes * See if data is ready for reading on the tube without blocking.
193238106Sdes * @param tube: tube to check for readable items
194238106Sdes * @return true if readable items are present. False if not (or error).
195238106Sdes *     true on pipe_closed.
196238106Sdes */
197238106Sdesint tube_poll(struct tube* tube);
198238106Sdes
199238106Sdes/**
200238106Sdes * Wait for data to be ready for reading on the tube. is blocking.
201238106Sdes * No timeout.
202238106Sdes * @param tube: the tube to wait on.
203238106Sdes * @return: if there was something to read (false on error).
204238106Sdes *     true on pipe_closed.
205238106Sdes */
206238106Sdesint tube_wait(struct tube* tube);
207238106Sdes
208238106Sdes/**
209238106Sdes * Get FD that is readable when new information arrives.
210238106Sdes * @param tube
211238106Sdes * @return file descriptor.
212238106Sdes */
213238106Sdesint tube_read_fd(struct tube* tube);
214238106Sdes
215238106Sdes/**
216238106Sdes * Start listening for information over the pipe.
217238106Sdes * Background registration of a read listener, callback when read completed.
218238106Sdes * Do not mix with tube_read_msg style direct reads from the pipe.
219238106Sdes * @param tube: tube to listen on
220238106Sdes * @param base: what base to register event callback.
221238106Sdes * @param cb: callback routine.
222238106Sdes * @param arg: user argument for callback routine.
223238106Sdes * @return true if successful, false on error.
224238106Sdes */
225238106Sdesint tube_setup_bg_listen(struct tube* tube, struct comm_base* base,
226238106Sdes	tube_callback_t* cb, void* arg);
227238106Sdes
228238106Sdes/**
229238106Sdes * Remove bg listen setup from event base.
230238106Sdes * @param tube: what tube to cleanup
231238106Sdes */
232238106Sdesvoid tube_remove_bg_listen(struct tube* tube);
233238106Sdes
234238106Sdes/**
235238106Sdes * Start background write handler for the pipe.
236238106Sdes * Do not mix with tube_write_msg style direct writes to the pipe.
237238106Sdes * @param tube: tube to write on
238238106Sdes * @param base: what base to register event handler on.
239238106Sdes * @return true if successful, false on error.
240238106Sdes */
241238106Sdesint tube_setup_bg_write(struct tube* tube, struct comm_base* base);
242238106Sdes
243238106Sdes/**
244238106Sdes * Remove bg write setup from event base.
245238106Sdes * @param tube: what tube to cleanup
246238106Sdes */
247238106Sdesvoid tube_remove_bg_write(struct tube* tube);
248238106Sdes
249238106Sdes
250238106Sdes/**
251238106Sdes * Append data item to background list of writes.
252238106Sdes * Mallocs a list entry behind the scenes.
253238106Sdes * Not locked behind the scenes, call from one thread or lock on outside.
254238106Sdes * @param tube: what tube to queue on.
255238106Sdes * @param msg: memory message to send. Is free()d after use.
256238106Sdes * 	Put at the end of the to-send queue.
257238106Sdes * @param len: length of item.
258238106Sdes * @return 0 on failure (msg freed).
259238106Sdes */
260238106Sdesint tube_queue_item(struct tube* tube, uint8_t* msg, size_t len);
261238106Sdes
262238106Sdes/** for fptr wlist, callback function */
263238106Sdesint tube_handle_listen(struct comm_point* c, void* arg, int error,
264238106Sdes	struct comm_reply* reply_info);
265238106Sdes
266238106Sdes/** for fptr wlist, callback function */
267238106Sdesint tube_handle_write(struct comm_point* c, void* arg, int error,
268238106Sdes	struct comm_reply* reply_info);
269238106Sdes
270238106Sdes/** for fptr wlist, winsock signal event callback function */
271238106Sdesvoid tube_handle_signal(int fd, short events, void* arg);
272238106Sdes
273238106Sdes#endif /* UTIL_TUBE_H */
274