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