1 /* prot.h -- stdio-like module that handles buffering, SASL, and TLS 2 * details for I/O over sockets 3 * 4 * Copyright (c) 1994-2008 Carnegie Mellon University. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * 3. The name "Carnegie Mellon University" must not be used to 19 * endorse or promote products derived from this software without 20 * prior written permission. For permission or any legal 21 * details, please contact 22 * Carnegie Mellon University 23 * Center for Technology Transfer and Enterprise Creation 24 * 4615 Forbes Avenue 25 * Suite 302 26 * Pittsburgh, PA 15213 27 * (412) 268-7393, fax: (412) 268-7395 28 * innovation@andrew.cmu.edu 29 * 30 * 4. Redistributions of any form whatsoever must retain the following 31 * acknowledgment: 32 * "This product includes software developed by Computing Services 33 * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 34 * 35 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 36 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 37 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 38 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 39 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 40 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 41 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 42 */ 43 44 #ifndef INCLUDED_PROT_H 45 #define INCLUDED_PROT_H 46 47 #include <time.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 51 #include <sasl/sasl.h> 52 #include <config.h> 53 54 #ifdef HAVE_SSL 55 #include <openssl/ssl.h> 56 #endif /* HAVE_SSL */ 57 58 #ifdef HAVE_ZLIB 59 #include <zlib.h> 60 #endif /* HAVE_ZLIB */ 61 62 #include "util.h" 63 64 #define PROT_BUFSIZE 4096 65 /* #define PROT_BUFSIZE 8192 */ 66 67 #define PROT_NO_FD -1 68 69 struct protstream; 70 struct prot_waitevent; 71 72 typedef void prot_readcallback_t(struct protstream *s, void *rock); 73 typedef ssize_t prot_fillcallback_t(unsigned char *buf, size_t len, void *rock); 74 75 struct protstream { 76 /* The Buffer */ 77 unsigned char *buf; 78 unsigned buf_size; 79 unsigned char *ptr; /* The end of data in the buffer */ 80 unsigned cnt; /* Space Remaining in buffer */ 81 82 /* File Descriptors */ 83 int fd; /* The Socket */ 84 int logfd; /* The Telemetry Log (or PROT_NO_FD) */ 85 int big_buffer; /* The Big Buffer (or PROT_NO_FD) */ 86 87 /* SASL / TLS */ 88 sasl_conn_t *conn; 89 int saslssf; 90 int maxplain; 91 92 #ifdef HAVE_SSL 93 SSL *tls_conn; 94 #endif /* HAVE_SSL */ 95 96 #ifdef HAVE_ZLIB 97 /* (De)compress stream */ 98 z_stream *zstrm; 99 /* (De)compress buffer */ 100 unsigned char *zbuf; 101 unsigned int zbuf_size; 102 /* Compress parameters */ 103 int zlevel; 104 int zflush; 105 #endif /* HAVE_ZLIB */ 106 107 /* Big Buffer Information */ 108 const char *bigbuf_base; /* Base Pointer */ 109 size_t bigbuf_siz; /* Overall Size of Buffer */ 110 size_t bigbuf_len; /* Length of mapped file */ 111 size_t bigbuf_pos; /* Current Position */ 112 113 /* Callback-fill information */ 114 prot_fillcallback_t *fillcallback_proc; 115 void *fillcallback_rock; 116 117 /* Status Flags */ 118 int eof; 119 int boundary; /* Type of data is about to change */ 120 int fixedsize; 121 char *error; 122 123 /* Parameters */ 124 int write; 125 int dontblock; /* Application requested nonblocking */ 126 int dontblock_isset; /* write only, we've fcntl(O_NONBLOCK)'d */ 127 int read_timeout; 128 time_t timeout_mark; 129 struct protstream *flushonread; 130 /* hack to write to an in-memory-string */ 131 struct buf *writetobuf; 132 133 int can_unget; 134 int bytes_in; 135 int bytes_out; 136 int isclient; 137 138 /* Events */ 139 prot_readcallback_t *readcallback_proc; 140 void *readcallback_rock; 141 struct prot_waitevent *waitevent; 142 143 /* For use by applications */ 144 void *userdata; 145 }; 146 147 typedef struct prot_waitevent *prot_waiteventcallback_t(struct protstream *s, 148 struct prot_waitevent *ev, 149 void *rock); 150 151 struct prot_waitevent { 152 time_t mark; 153 prot_waiteventcallback_t *proc; 154 void *rock; 155 struct prot_waitevent *next; 156 }; 157 158 /* Not for use by applications directly, but needed by the macros. */ 159 int prot_flush_internal(struct protstream *s, int force); 160 161 #define PROT_EOF_STRING "end of file reached" 162 #define PROTGROUP_SIZE_DEFAULT 32 163 struct protgroup; /* Opaque protgroup structure */ 164 165 extern int prot_getc(struct protstream *s); 166 extern int prot_ungetc(int c, struct protstream *s); 167 extern int prot_putc(int c, struct protstream *s); 168 169 /* The following two macros control the blocking nature of 170 * the protstream. 171 * 172 * For a read stream, the non-blocking behavior is that for the 173 * reading functions (prot_read, prot_getc, etc) we will return EOF and 174 * set errno = EAGAIN if no data was pending. 175 * 176 * For a write stream, it's a bit more complicated. When a nonblocking 177 * write stream is flushed, a nonblocking write to the network is attempted. 178 * if it cannot write all of its data, the remaining data is flushed to a 179 * "bigbuffer" temporary file. (When the next flush occurs, this temporary 180 * buffer is flushed first, and additional data is appended to it if necessary) 181 * Note that this means that in the telemetry logs, only the time of the 182 * first prot_flush_internal() call is logged, not the call for when the data 183 * actually is flushed to the network successfully. 184 */ 185 186 #define prot_BLOCK(s) ((s)->dontblock = 0) 187 #define prot_NONBLOCK(s) ((s)->dontblock = 1) 188 #define prot_IS_BLOCKING(s) ((s)->dontblock == 0) 189 #define prot_IS_EOF(s) ((s)->eof != 0) 190 #define prot_IS_ERROR(s) ((s)->error != NULL) 191 192 /* Allocate/free the protstream structure */ 193 extern struct protstream *prot_new(int fd, int write); 194 extern struct protstream *prot_writebuf(struct buf *buf); 195 extern struct protstream *prot_readmap(const char *base, uint32_t len); 196 extern struct protstream *prot_readcb(prot_fillcallback_t *proc, void *rock); 197 extern int prot_free(struct protstream *s); 198 199 /* Set the telemetry logfile for a given protstream */ 200 extern int prot_setlog(struct protstream *s, int fd); 201 202 /* Get traffic counts */ 203 extern int prot_bytes_in(struct protstream *s); 204 extern int prot_bytes_out(struct protstream *s); 205 #define prot_bytes_in(s) ((s)->bytes_in) 206 #define prot_bytes_out(s) ((s)->bytes_out) 207 208 /* Set the SASL options for a protstream (requires authentication to 209 * be complete for the given sasl_conn_t */ 210 extern int prot_setsasl(struct protstream *s, sasl_conn_t *conn); 211 extern void prot_unsetsasl(struct protstream *s); 212 213 #ifdef HAVE_SSL 214 /* Set TLS options for a given protstream (requires a completed tls 215 * negotiation */ 216 extern int prot_settls(struct protstream *s, SSL *tlsconn); 217 #endif /* HAVE_SSL */ 218 219 /* Mark this protstream as a "client" for the purpose of generating 220 * or consuming literals (thanks LITERAL+) */ 221 int prot_setisclient(struct protstream *s, int val); 222 223 #ifdef HAVE_ZLIB 224 /* Enable (de)compression for a given protstream */ 225 int prot_setcompress(struct protstream *s); 226 #endif /* HAVE_ZLIB */ 227 228 /* Tell the protstream that the type of data is about to change. */ 229 int prot_data_boundary(struct protstream *s); 230 231 /* Set a timeout for the connection (in seconds) */ 232 extern int prot_settimeout(struct protstream *s, int timeout); 233 234 /* Reset the timeout timer for the connection (in seconds) */ 235 extern int prot_resettimeout(struct protstream *s); 236 237 /* Connect two streams so that when you block on reading s, the layer 238 * will automaticly flush flushs */ 239 extern int prot_setflushonread(struct protstream *s, 240 struct protstream *flushs); 241 242 243 int prot_setreadcallback(struct protstream *s, 244 prot_readcallback_t *proc, void *rock); 245 extern struct prot_waitevent *prot_addwaitevent(struct protstream *s, 246 time_t mark, 247 prot_waiteventcallback_t *proc, 248 void *rock); 249 extern void prot_removewaitevent(struct protstream *s, 250 struct prot_waitevent *event); 251 252 extern const char *prot_error(struct protstream *s); 253 extern int prot_rewind(struct protstream *s); 254 255 /* Fill the buffer for a read stream with waiting data (may block) */ 256 extern int prot_fill(struct protstream *s); 257 258 /* Force a flush of an output stream */ 259 extern int prot_flush(struct protstream *s); 260 261 /* These are protlayer versions of the specified functions */ 262 extern int prot_write(struct protstream *s, const char *buf, unsigned len); 263 extern int prot_putbuf(struct protstream *s, struct buf *buf); 264 extern int prot_puts(struct protstream *s, const char *str); 265 extern int prot_vprintf(struct protstream *, const char *, va_list); 266 extern int prot_printf(struct protstream *, const char *, ...) 267 #ifdef __GNUC__ 268 __attribute__ ((format (printf, 2, 3))); 269 #else 270 ; 271 #endif 272 extern int prot_printliteral(struct protstream *out, const char *s, 273 size_t size); 274 extern int prot_printstring(struct protstream *out, const char *s); 275 extern int prot_printmap(struct protstream *out, const char *s, size_t n); 276 extern int prot_printamap(struct protstream *out, const char *s, size_t n); 277 extern int prot_printastring(struct protstream *out, const char *s); 278 extern int prot_read(struct protstream *s, char *buf, unsigned size); 279 extern int prot_readbuf(struct protstream *s, struct buf *buf, unsigned size); 280 extern char *prot_fgets(char *buf, unsigned size, struct protstream *s); 281 282 /* select() for protstreams */ 283 extern int prot_select(struct protgroup *readstreams, int extra_read_fd, 284 struct protgroup **out, int *extra_read_flag, 285 struct timeval *timeout); 286 287 /* Protgroup manipulations */ 288 /* Create a new protgroup of a certain size or as a copy of another 289 * protgroup */ 290 struct protgroup *protgroup_new(size_t size); 291 struct protgroup *protgroup_copy(struct protgroup *src); 292 293 /* Cleanup a protgroup but don't release the allocated memory (so it can 294 * be reused) */ 295 void protgroup_reset(struct protgroup *group); 296 297 /* Release memory for a protgroup */ 298 void protgroup_free(struct protgroup *group); 299 300 /* Insert an element into a protgroup */ 301 void protgroup_insert(struct protgroup *group, struct protstream *item); 302 303 /* Delete an element from a protgroup */ 304 void protgroup_delete(struct protgroup *group, struct protstream *item); 305 306 /* Returns the protstream at that position in the protgroup, or NULL if 307 * an invalid element is requested */ 308 struct protstream *protgroup_getelement(struct protgroup *group, 309 size_t element); 310 311 #endif /* INCLUDED_PROT_H */ 312