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 #define prot_peek(s) (prot_ungetc(prot_getc(s), s))
170 
171 /* prot_lookahead checks whether the next several buffered bytes match
172  * the string str (of length len).
173  *
174  * If there are enough buffered bytes available, and they match, then
175  * sep will be set to the first byte following str, and the return
176  * value will be equal to len+1.
177  *
178  * If there are not enough buffered bytes available, but those that
179  * are there match, then sep will remain unset, and the return value
180  * will be within 0 < x <= len, depending on how many matching bytes
181  * were available.
182  *
183  * If there is no match, sep will remain unset and the return value
184  * will be zero, regardless of how many bytes were available.
185  *
186  * The internal buffer will ONLY be filled if it is currently empty.
187  */
188 extern size_t prot_lookahead(struct protstream *s,
189                              const char *str,
190                              size_t len,
191                              int *sep);
192 
193 /* The following two macros control the blocking nature of
194  * the protstream.
195  *
196  * For a read stream, the non-blocking behavior is that for the
197  * reading functions (prot_read, prot_getc, etc) we will return EOF and
198  * set errno = EAGAIN if no data was pending.
199  *
200  * For a write stream, it's a bit more complicated.  When a nonblocking
201  * write stream is flushed, a nonblocking write to the network is attempted.
202  * if it cannot write all of its data, the remaining data is flushed to a
203  * "bigbuffer" temporary file.  (When the next flush occurs, this temporary
204  * buffer is flushed first, and additional data is appended to it if necessary)
205  * Note that this means that in the telemetry logs, only the time of the
206  * first prot_flush_internal() call is logged, not the call for when the data
207  * actually is flushed to the network successfully.
208  */
209 
210 #define prot_BLOCK(s) ((s)->dontblock = 0)
211 #define prot_NONBLOCK(s) ((s)->dontblock = 1)
212 #define prot_IS_BLOCKING(s) ((s)->dontblock == 0)
213 #define prot_IS_EOF(s) ((s)->eof != 0)
214 #define prot_IS_ERROR(s) ((s)->error != NULL)
215 
216 /* Allocate/free the protstream structure */
217 extern struct protstream *prot_new(int fd, int write);
218 extern struct protstream *prot_writebuf(struct buf *buf);
219 extern struct protstream *prot_readmap(const char *base, uint32_t len);
220 extern struct protstream *prot_readcb(prot_fillcallback_t *proc, void *rock);
221 extern int prot_free(struct protstream *s);
222 
223 /* Set the telemetry logfile for a given protstream */
224 extern int prot_setlog(struct protstream *s, int fd);
225 
226 /* Get traffic counts */
227 extern int prot_bytes_in(struct protstream *s);
228 extern int prot_bytes_out(struct protstream *s);
229 #define prot_bytes_in(s) ((s)->bytes_in)
230 #define prot_bytes_out(s) ((s)->bytes_out)
231 
232 /* Set the SASL options for a protstream (requires authentication to
233  * be complete for the given sasl_conn_t */
234 extern int prot_setsasl(struct protstream *s, sasl_conn_t *conn);
235 extern void prot_unsetsasl(struct protstream *s);
236 
237 #ifdef HAVE_SSL
238 /* Set TLS options for a given protstream (requires a completed tls
239  * negotiation */
240 extern int prot_settls(struct protstream *s, SSL *tlsconn);
241 #endif /* HAVE_SSL */
242 
243 /* Mark this protstream as a "client" for the purpose of generating
244  * or consuming literals (thanks LITERAL+) */
245 int prot_setisclient(struct protstream *s, int val);
246 
247 #ifdef HAVE_ZLIB
248 /* Enable (de)compression for a given protstream */
249 int prot_setcompress(struct protstream *s);
250 
251 /* Disable (de)compression for a given protstream */
252 void prot_unsetcompress(struct protstream *s);
253 #endif /* HAVE_ZLIB */
254 
255 /* Tell the protstream that the type of data is about to change. */
256 int prot_data_boundary(struct protstream *s);
257 
258 /* Set a timeout for the connection (in seconds) */
259 extern int prot_settimeout(struct protstream *s, int timeout);
260 
261 /* Reset the timeout timer for the connection (in seconds) */
262 extern int prot_resettimeout(struct protstream *s);
263 
264 /* Connect two streams so that when you block on reading s, the layer
265  * will automatically flush flushs */
266 extern int prot_setflushonread(struct protstream *s,
267                                struct protstream *flushs);
268 
269 
270 int prot_setreadcallback(struct protstream *s,
271                                 prot_readcallback_t *proc, void *rock);
272 extern struct prot_waitevent *prot_addwaitevent(struct protstream *s,
273                                                 time_t mark,
274                                                 prot_waiteventcallback_t *proc,
275                                                 void *rock);
276 extern void prot_removewaitevent(struct protstream *s,
277                                  struct prot_waitevent *event);
278 
279 extern const char *prot_error(struct protstream *s);
280 extern int prot_rewind(struct protstream *s);
281 
282 /* Fill the buffer for a read stream with waiting data (may block) */
283 extern int prot_fill(struct protstream *s);
284 
285 /* Force a flush of an output stream */
286 extern int prot_flush(struct protstream *s);
287 
288 /* These are protlayer versions of the specified functions */
289 extern int prot_write(struct protstream *s, const char *buf, unsigned len);
290 extern int prot_putbuf(struct protstream *s, struct buf *buf);
291 extern int prot_puts(struct protstream *s, const char *str);
292 extern int prot_vprintf(struct protstream *, const char *, va_list)
293     __attribute__((format(printf, 2, 0)));
294 extern int prot_printf(struct protstream *, const char *, ...)
295     __attribute__((format(printf, 2, 3)));
296 extern int prot_printliteral(struct protstream *out, const char *s,
297                              size_t size);
298 extern int prot_printstring(struct protstream *out, const char *s);
299 extern int prot_printmap(struct protstream *out, const char *s, size_t n);
300 extern int prot_printamap(struct protstream *out, const char *s, size_t n);
301 extern int prot_printastring(struct protstream *out, const char *s);
302 extern int prot_read(struct protstream *s, char *buf, unsigned size);
303 extern int prot_readbuf(struct protstream *s, struct buf *buf, unsigned size);
304 extern char *prot_fgets(char *buf, unsigned size, struct protstream *s);
305 
306 /* select() for protstreams */
307 extern int prot_select(struct protgroup *readstreams, int extra_read_fd,
308                        struct protgroup **out, int *extra_read_flag,
309                        struct timeval *timeout);
310 
311 /* Protgroup manipulations */
312 /* Create a new protgroup of a certain size or as a copy of another
313  * protgroup */
314 struct protgroup *protgroup_new(size_t size);
315 struct protgroup *protgroup_copy(struct protgroup *src);
316 
317 /* Cleanup a protgroup but don't release the allocated memory (so it can
318  * be reused) */
319 void protgroup_reset(struct protgroup *group);
320 
321 /* Release memory for a protgroup */
322 void protgroup_free(struct protgroup *group);
323 
324 /* Insert an element into a protgroup */
325 void protgroup_insert(struct protgroup *group, struct protstream *item);
326 
327 /* Delete an element from a protgroup */
328 void protgroup_delete(struct protgroup *group, struct protstream *item);
329 
330 /* Returns the protstream at that position in the protgroup, or NULL if
331  * an invalid element is requested */
332 struct protstream *protgroup_getelement(struct protgroup *group,
333                                         size_t element);
334 
335 #endif /* INCLUDED_PROT_H */
336