summaryrefslogtreecommitdiffstats
blob: 2e7041156378587d164f9bc7129976273bf14d5d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
/*
 * util/tube.h - pipe service
 *
 * Copyright (c) 2008, NLnet Labs. All rights reserved.
 *
 * This software is open source.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * 
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * 
 * Neither the name of the NLNET LABS nor the names of its contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * \file
 *
 * This file contains pipe service functions.
 */

#ifndef UTIL_TUBE_H
#define UTIL_TUBE_H
struct comm_reply;
struct comm_point;
struct comm_base;
struct tube;
struct tube_res_list;
#ifdef USE_WINSOCK
#include "util/locks.h"
#include "util/winsock_event.h"
#endif

/**
 * Callback from pipe listen function
 * void mycallback(tube, msg, len, error, user_argument);
 * if error is true (NETEVENT_*), msg is probably NULL.
 */
typedef void tube_callback_t(struct tube*, uint8_t*, size_t, int, void*);

/**
 * A pipe
 */
struct tube {
#ifndef USE_WINSOCK
	/** pipe end to read from */
	int sr;
	/** pipe end to write on */
	int sw;

	/** listen commpoint */
	struct comm_point* listen_com;
	/** listen callback */
	tube_callback_t* listen_cb;
	/** listen callback user arg */
	void* listen_arg;
	/** are we currently reading a command, 0 if not, else bytecount */
	size_t cmd_read;
	/** size of current read command, may be partially read */
	uint32_t cmd_len;
	/** the current read command content, malloced, can be partially read*/
	uint8_t* cmd_msg;

	/** background write queue, commpoint to write results back */
	struct comm_point* res_com;
	/** are we curently writing a result, 0 if not, else bytecount into
	 * the res_list first entry. */
	size_t res_write;
	/** list of outstanding results to be written back */
	struct tube_res_list* res_list;
	/** last in list */
	struct tube_res_list* res_last;

#else /* USE_WINSOCK */
	/** listen callback */
	tube_callback_t* listen_cb;
	/** listen callback user arg */
	void* listen_arg;
	/** the windows sockets event (signaled if items in pipe) */
	WSAEVENT event;
	/** winsock event storage when registered with event base */
	struct event ev_listen;

	/** lock on the list of outstanding items */
	lock_basic_t res_lock;
	/** list of outstanding results on pipe */
	struct tube_res_list* res_list;
	/** last in list */
	struct tube_res_list* res_last;
#endif /* USE_WINSOCK */
};

/**
 * List of results (arbitrary command serializations) to write back
 */
struct tube_res_list {
	/** next in list */
	struct tube_res_list* next;
	/** serialized buffer to write */
	uint8_t* buf;
	/** length to write */
	uint32_t len;
};

/**
 * Create a pipe
 * @return: new tube struct or NULL on error.
 */
struct tube* tube_create(void);

/**
 * Delete and destroy a pipe
 * @param tube: to delete
 */
void tube_delete(struct tube* tube);

/**
 * Write length bytes followed by message.
 * @param tube: the tube to write on.
 *     If that tube is a pipe, its write fd is used as
 *     the socket to write on. Is nonblocking.
 *      Set to blocking by the function,
 *      and back to non-blocking at exit of function.
 * @param buf: the message.
 * @param len: length of message.
 * @param nonblock: if set to true, the first write is nonblocking.
 *      If the first write fails the function returns -1.
 *      If set false, the first write is blocking.
 * @return: all remainder writes are nonblocking.
 *      return 0 on error, in that case blocking/nonblocking of socket is
 *              unknown.
 *      return 1 if all OK.
 */
int tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len, 
	int nonblock);

/**
 * Read length bytes followed by message.
 * @param tube: The tube to read on.
 *     If that tube is a pipe, its read fd is used as
 *     the socket to read on. Is nonblocking.
 *      Set to blocking by the function,
 *      and back to non-blocking at exit of function.
 * @param buf: the message, malloced.
 * @param len: length of message, returned.
 * @param nonblock: if set to true, the first read is nonblocking.
 *      If the first read fails the function returns -1.
 *      If set false, the first read is blocking.
 * @return: all remainder reads are nonblocking.
 *      return 0 on error, in that case blocking/nonblocking of socket is 
 *              unknown. On EOF 0 is returned.
 *      return 1 if all OK.
 */
int tube_read_msg(struct tube* tube, uint8_t** buf, uint32_t* len, 
	int nonblock);

/**
 * Close read part of the pipe.
 * The tube can no longer be read from.
 * @param tube: tube to operate on.
 */
void tube_close_read(struct tube* tube);

/**
 * Close write part of the pipe.
 * The tube can no longer be written to.
 * @param tube: tube to operate on.
 */
void tube_close_write(struct tube* tube);

/**
 * See if data is ready for reading on the tube without blocking.
 * @param tube: tube to check for readable items
 * @return true if readable items are present. False if not (or error).
 *     true on pipe_closed.
 */
int tube_poll(struct tube* tube);

/**
 * Wait for data to be ready for reading on the tube. is blocking.
 * No timeout.
 * @param tube: the tube to wait on.
 * @return: if there was something to read (false on error).
 *     true on pipe_closed.
 */
int tube_wait(struct tube* tube);

/**
 * Get FD that is readable when new information arrives.
 * @param tube
 * @return file descriptor.
 */
int tube_read_fd(struct tube* tube);

/**
 * Start listening for information over the pipe.
 * Background registration of a read listener, callback when read completed.
 * Do not mix with tube_read_msg style direct reads from the pipe.
 * @param tube: tube to listen on
 * @param base: what base to register event callback.
 * @param cb: callback routine.
 * @param arg: user argument for callback routine.
 * @return true if successful, false on error.
 */
int tube_setup_bg_listen(struct tube* tube, struct comm_base* base,
	tube_callback_t* cb, void* arg);

/**
 * Remove bg listen setup from event base.
 * @param tube: what tube to cleanup
 */
void tube_remove_bg_listen(struct tube* tube);

/**
 * Start background write handler for the pipe.
 * Do not mix with tube_write_msg style direct writes to the pipe.
 * @param tube: tube to write on
 * @param base: what base to register event handler on.
 * @return true if successful, false on error.
 */
int tube_setup_bg_write(struct tube* tube, struct comm_base* base);

/**
 * Remove bg write setup from event base.
 * @param tube: what tube to cleanup
 */
void tube_remove_bg_write(struct tube* tube);


/**
 * Append data item to background list of writes.
 * Mallocs a list entry behind the scenes.
 * Not locked behind the scenes, call from one thread or lock on outside.
 * @param tube: what tube to queue on.
 * @param msg: memory message to send. Is free()d after use.
 * 	Put at the end of the to-send queue.
 * @param len: length of item.
 * @return 0 on failure (msg freed).
 */
int tube_queue_item(struct tube* tube, uint8_t* msg, size_t len);

/** for fptr wlist, callback function */
int tube_handle_listen(struct comm_point* c, void* arg, int error, 
	struct comm_reply* reply_info);

/** for fptr wlist, callback function */
int tube_handle_write(struct comm_point* c, void* arg, int error, 
	struct comm_reply* reply_info);

/** for fptr wlist, winsock signal event callback function */
void tube_handle_signal(int fd, short events, void* arg);

#endif /* UTIL_TUBE_H */