1 /* this header file comes from libowfat, http://www.fefe.de/libowfat/ */ 2 #ifndef IO_H 3 #define IO_H 4 5 /* http://cr.yp.to/lib/io.html */ 6 7 #include "uint64.h" 8 #include "taia.h" 9 10 #ifdef __cplusplus 11 extern "C" { 12 #endif 13 14 /* like open(s,O_RDONLY) */ 15 /* return 1 if ok, 0 on error */ 16 int io_readfile(int64* d,const char* s); 17 /* like open(s,O_WRONLY|O_CREAT|O_TRUNC,0600) */ 18 /* return 1 if ok, 0 on error */ 19 int io_createfile(int64* d,const char* s); 20 /* like open(s,O_RDWR) */ 21 /* return 1 if ok, 0 on error */ 22 int io_readwritefile(int64* d,const char* s); 23 /* like open(s,O_WRONLY|O_APPEND|O_CREAT,0600) */ 24 /* return 1 if ok, 0 on error */ 25 int io_appendfile(int64* d,const char* s); 26 /* like pipe(d) */ 27 /* return 1 if ok, 0 on error */ 28 int io_pipe(int64* d); 29 /* like socketpair() */ 30 /* return 1 if ok, 0 on error */ 31 int io_socketpair(int64* d); 32 33 /* non-blocking read(), -1 for EAGAIN and -3+errno for other errors */ 34 int64 io_tryread(int64 d,char* buf,int64 len); 35 36 /* blocking read(), with -3 instead of -1 for errors */ 37 int64 io_waitread(int64 d,char* buf,int64 len); 38 39 /* non-blocking write(), -1 for EAGAIN and -3+errno for other errors */ 40 int64 io_trywrite(int64 d,const char* buf,int64 len); 41 42 /* blocking write(), with -3 instead of -1 for errors */ 43 int64 io_waitwrite(int64 d,const char* buf,int64 len); 44 45 /* modify timeout attribute of file descriptor */ 46 void io_timeout(int64 d,tai6464 t); 47 48 /* like io_tryread but will return -2,errno=ETIMEDOUT if d has a timeout 49 * associated and it is passed without input being there */ 50 int64 io_tryreadtimeout(int64 d,char* buf,int64 len); 51 52 /* like io_trywrite but will return -2,errno=ETIMEDOUT if d has a timeout 53 * associated and it is passed without being able to write */ 54 int64 io_trywritetimeout(int64 d,const char* buf,int64 len); 55 56 void io_wantread(int64 d); 57 void io_wantwrite(int64 d); 58 void io_dontwantread(int64 d); 59 void io_dontwantwrite(int64 d); 60 61 void io_wait(); 62 void io_waituntil(tai6464 t); 63 int64 io_waituntil2(int64 milliseconds); 64 void io_check(); 65 66 /* signal that read/accept/whatever returned EAGAIN */ 67 /* needed for SIGIO and epoll */ 68 void io_eagain(int64 d); /* do not use, API was a bad idea */ 69 #define HAVE_EAGAIN_READWRITE 70 void io_eagain_read(int64 d); /* use these ones */ 71 void io_eagain_write(int64 d); 72 73 /* return next descriptor from io_wait that can be read from */ 74 int64 io_canread(); 75 /* return next descriptor from io_wait that can be written to */ 76 int64 io_canwrite(); 77 78 /* return next descriptor with expired timeout */ 79 int64 io_timeouted(); 80 81 /* is this fd over its timeout? */ 82 int io_timedout(int64 d); 83 84 /* 1 means: have IO_FD_CANWRITE, IO_FD_BLOCK and IO_FD_NONBLOCK, 85 * will be incremented if API is extended in the future */ 86 #define HAVE_IO_FD_FLAGS 1 87 enum io_fd_flags { 88 IO_FD_CANWRITE=1, /* new TCP connection, we know it's writable */ 89 IO_FD_BLOCK=2, /* skip the fcntl, assume fd is set to blocking */ 90 IO_FD_NONBLOCK=4, /* skip the fcntl, assume fd is set to non-blocking */ 91 }; 92 93 /* put d on internal data structure, return 1 on success, 0 on error */ 94 int io_fd(int64 d); /* use this for sockets before you called connect() or accept() */ 95 int io_fd_canwrite(int64 d); /* use this for connected sockets (assumes socket is writable) */ 96 int io_fd_flags(int64 d,int flags); /* can be used to tell io_fd to skip one syscall */ 97 98 void io_setcookie(int64 d,void* cookie); 99 void* io_getcookie(int64 d); 100 101 /* put descriptor in non-blocking mode */ 102 void io_nonblock(int64 d); 103 /* put descriptor in blocking mode */ 104 void io_block(int64 d); 105 /* put descriptor in close-on-exec mode */ 106 void io_closeonexec(int64 d); 107 108 void io_close(int64 d); 109 110 /* Free the internal data structures from libio. 111 * This only makes sense if you run your program in a malloc checker and 112 * these produce false alarms. Your OS will free these automatically on 113 * process termination. */ 114 void io_finishandshutdown(void); 115 116 /* send n bytes from file fd starting at offset off to socket s */ 117 /* return number of bytes written */ 118 int64 io_sendfile(int64 s,int64 fd,uint64 off,uint64 n); 119 120 /* Pass fd over sock (must be a unix domain socket) to other process. 121 * Return 0 if ok, -1 on error, setting errno. */ 122 int io_passfd(int64 sock,int64 fd); 123 124 /* Receive fd over sock (must be a unix domain socket) from other 125 * process. Return sock if ok, -1 on error, setting errno. */ 126 int64 io_receivefd(int64 sock); 127 128 int io_starteventloopthread(unsigned int threads); 129 130 #define HAVE_IO_QUEUEFORREAD 131 /* Artificially queue a file descriptor as readable. 132 * The next call to io_canread will return this descriptor. */ 133 int io_queueforread(int64 d); 134 /* Artificially queue a file descriptor as writable. 135 * The next call to io_canread will return this descriptor. */ 136 int io_queueforwrite(int64 d); 137 138 typedef int64 (*io_write_callback)(int64 s,const void* buf,uint64 n); 139 140 /* used internally, but hey, who knows */ 141 int64 io_mmapwritefile(int64 out,int64 in,uint64 off,uint64 bytes,io_write_callback writecb); 142 143 /* only needed for debugging, will print some stats into the buffer to 144 * aid in debugging the state machine if a descriptor loops or so */ 145 unsigned int io_debugstring(int64 s,char* buf,unsigned int bufsize); 146 147 #ifdef __dietlibc__ 148 #include <threads.h> 149 #else 150 #include <pthread.h> 151 #include <semaphore.h> 152 #endif 153 154 enum { SLOTS=128 }; 155 typedef struct iomux { 156 int ctx; 157 int working; /* used to synchronize who is filling the queue */ 158 unsigned int h,l; /* high, low */ 159 struct { 160 int fd, events; 161 } q[SLOTS]; 162 #ifdef __dietlibc__ 163 mtx_t mtx; 164 cnd_t sem; 165 #else 166 sem_t sem; 167 #endif 168 } iomux_t; 169 170 171 /* Init master context */ 172 int iom_init(iomux_t* c); 173 174 /* Add socket to iomux */ 175 enum { 176 IOM_READ=1, 177 IOM_WRITE=2, 178 IOM_ERROR=4 179 }; 180 /* return -1 if error, events can be IOM_READ or IOM_WRITE */ 181 int iom_add(iomux_t* c,int64 s,unsigned int events); 182 183 /* Blocking wait for single event, timeout in milliseconds */ 184 /* return -1 if error, 0 if ok; s set to fd, revents set to known events on that fd */ 185 /* when done with the fd, call iom_add on it again! */ 186 /* This can be called by multiple threads in parallel */ 187 int iom_wait(iomux_t* c,int64* s,unsigned int* revents,unsigned long timeout); 188 189 /* Call this to terminate all threads waiting in iom_wait */ 190 int iom_abort(iomux_t* c); 191 192 #ifdef __cplusplus 193 } 194 #endif 195 196 #endif 197