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