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