]> andersk Git - test.git/blob - libhttp/httpconnection.c
The server could sometimes end up listening for events even though it
[test.git] / libhttp / httpconnection.c
1 // httpconnection.c -- Manage state machine for HTTP connections
2 // Copyright (C) 2008-2010 Markus Gutschke <markus@shellinabox.com>
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License version 2 as
6 // published by the Free Software Foundation.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License along
14 // with this program; if not, write to the Free Software Foundation, Inc.,
15 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 //
17 // In addition to these license terms, the author grants the following
18 // additional rights:
19 //
20 // If you modify this program, or any covered work, by linking or
21 // combining it with the OpenSSL project's OpenSSL library (or a
22 // modified version of that library), containing parts covered by the
23 // terms of the OpenSSL or SSLeay licenses, the author
24 // grants you additional permission to convey the resulting work.
25 // Corresponding Source for a non-source form of such a combination
26 // shall include the source code for the parts of OpenSSL used as well
27 // as that of the covered work.
28 //
29 // You may at your option choose to remove this additional permission from
30 // the work, or from any part of it.
31 //
32 // It is possible to build this program in a way that it loads OpenSSL
33 // libraries at run-time. If doing so, the following notices are required
34 // by the OpenSSL and SSLeay licenses:
35 //
36 // This product includes software developed by the OpenSSL Project
37 // for use in the OpenSSL Toolkit. (http://www.openssl.org/)
38 //
39 // This product includes cryptographic software written by Eric Young
40 // (eay@cryptsoft.com)
41 //
42 //
43 // The most up-to-date version of this program is always available from
44 // http://shellinabox.com
45
46 #define _GNU_SOURCE
47 #include "config.h"
48
49 #include <errno.h>
50 #include <arpa/inet.h>
51 #include <math.h>
52 #include <netdb.h>
53 #include <netinet/in.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <sys/poll.h>
58 #include <sys/socket.h>
59 #include <sys/types.h>
60 #include <unistd.h>
61
62 #ifdef HAVE_ZLIB
63 #include <zlib.h>
64 #endif
65
66 #ifdef HAVE_STRLCAT
67 #define strncat(a,b,c) ({ char *_a = (a); strlcat(_a, (b), (c)+1); _a; })
68 #endif
69 #ifndef HAVE_ISNAN
70 #define isnan(x) ({ typeof(x) _x = (x); _x != _x; })
71 #endif
72 #define max(a, b) ({ typeof(a) _a = (a); typeof(b) _b = (b);                  \
73                      _a > _b ? _a : _b; })
74 #ifdef HAVE_UNUSED
75 #defined ATTR_UNUSED __attribute__((unused))
76 #defined UNUSED(x)   do { } while (0)
77 #else
78 #define ATTR_UNUSED
79 #define UNUSED(x)    do { (void)(x); } while (0)
80 #endif
81
82 #include "libhttp/httpconnection.h"
83 #include "logging/logging.h"
84
85 #define MAX_HEADER_LENGTH   (64<<10)
86 #define CONNECTION_TIMEOUT  (10*60)
87
88 static int httpPromoteToSSL(struct HttpConnection *http, const char *buf,
89                             int len) {
90   if (http->ssl->enabled && !http->sslHndl) {
91     debug("Switching to SSL (replaying %d+%d bytes)",
92           http->partialLength, len);
93     if (http->partial && len > 0) {
94       check(http->partial  = realloc(http->partial,
95                                      http->partialLength + len));
96       memcpy(http->partial + http->partialLength, buf, len);
97       http->partialLength += len;
98     }
99     int rc                 = sslPromoteToSSL(
100                                     http->ssl, &http->sslHndl, http->fd,
101                                     http->partial ? http->partial : buf,
102                                     http->partial ? http->partialLength : len);
103     if (http->sslHndl) {
104       check(!rc);
105       SSL_set_app_data(http->sslHndl, http);
106     }
107     free(http->partial);
108     http->partialLength    = 0;
109     return rc;
110   } else {
111     errno                  = EINVAL;
112     return -1;
113   }
114 }
115
116 static ssize_t httpRead(struct HttpConnection *http, char *buf, ssize_t len) {
117   sslBlockSigPipe();
118   int rc;
119   if (http->sslHndl) {
120     dcheck(!ERR_peek_error());
121     rc                        = SSL_read(http->sslHndl, buf, len);
122     switch (rc) {
123     case 0:
124     case -1:
125       switch (http->lastError = SSL_get_error(http->sslHndl, rc)) {
126       case SSL_ERROR_WANT_READ:
127       case SSL_ERROR_WANT_WRITE:
128         errno                 = EAGAIN;
129         rc                    = -1;
130         break;
131       default:
132         errno                 = EINVAL;
133         break;
134       }
135       ERR_clear_error();
136       break;
137     default:
138       break;
139     }
140     dcheck(!ERR_peek_error());
141   } else {
142     rc = NOINTR(read(http->fd, buf, len));
143   }
144   sslUnblockSigPipe();
145   if (rc > 0) {
146     serverSetTimeout(httpGetServerConnection(http), CONNECTION_TIMEOUT);
147   }
148   return rc;
149 }
150
151 static ssize_t httpWrite(struct HttpConnection *http, const char *buf,
152                          ssize_t len) {
153   sslBlockSigPipe();
154   int rc;
155   if (http->sslHndl) {
156     dcheck(!ERR_peek_error());
157     rc                        = SSL_write(http->sslHndl, buf, len);
158     switch (rc) {
159     case 0:
160     case -1:
161       switch (http->lastError = SSL_get_error(http->sslHndl, rc)) {
162       case SSL_ERROR_WANT_READ:
163       case SSL_ERROR_WANT_WRITE:
164         errno                 = EAGAIN;
165         rc                    = -1;
166         break;
167       default:
168         errno                 = EINVAL;
169         break;
170       }
171       ERR_clear_error();
172       break;
173     default:
174       break;
175     }
176     dcheck(!ERR_peek_error());
177   } else {
178     rc = NOINTR(write(http->fd, buf, len));
179   }
180   sslUnblockSigPipe();
181   return rc;
182 }
183
184 static int httpShutdown(struct HttpConnection *http, int how) {
185   if (http->sslHndl) {
186     int rc        = 0;
187     if (how != SHUT_RD) {
188       dcheck(!ERR_peek_error());
189       for (int i = 0; i < 10; i++) {
190         sslBlockSigPipe();
191         rc        = SSL_shutdown(http->sslHndl);
192         int sPipe = sslUnblockSigPipe();
193         if (rc > 0) {
194           rc      = 0;
195           break;
196         } else {
197           rc      = -1;
198           // Retry a few times in order to prefer a clean bidirectional
199           // shutdown. But don't bother if the other side already closed
200           // the connection.
201           if (sPipe) {
202             break;
203           }
204         }
205       }
206       sslFreeHndl(&http->sslHndl);
207     }
208   }
209   return shutdown(http->fd, how);
210 }
211
212 static void httpCloseRead(struct HttpConnection *http) {
213   if (!http->closed) {
214     httpShutdown(http, SHUT_RD);
215     http->closed = 1;
216   }
217 }
218
219 #ifndef HAVE_STRCASESTR
220 static char *strcasestr(const char *haystack, const char *needle) {
221   // This algorithm is O(len(haystack)*len(needle)). Much better algorithms
222   // are available, but this code is much simpler and performance is not
223   // critical for our workloads.
224   int len = strlen(needle);
225   do {
226     if (!strncasecmp(haystack, needle, len)) {
227       return haystack;
228     }
229   } while (*haystack++);
230   return NULL;
231 }
232 #endif
233
234 static int httpFinishCommand(struct HttpConnection *http) {
235   int rc            = HTTP_DONE;
236   if ((http->callback || http->websocketHandler) && !http->done) {
237     rc              = http->callback ? http->callback(http, http->arg, NULL, 0)
238        : http->websocketHandler(http, http->arg, WS_CONNECTION_CLOSED, NULL,0);
239     check(rc != HTTP_SUSPEND);
240     check(rc != HTTP_PARTIAL_REPLY);
241     http->callback  = NULL;
242     http->arg       = NULL;
243     if (rc == HTTP_ERROR) {
244       httpCloseRead(http);
245     }
246   }
247   if (!http->closed) {
248     const char *con = getFromHashMap(&http->header, "connection");
249     if ((con && strcasestr(con, "close")) ||
250         !http->version || strcmp(http->version, "HTTP/1.1") < 0) {
251       httpCloseRead(http);
252     }
253   }
254   if (logIsInfo()) {
255     check(http->method);
256     check(http->path);
257     check(http->version);
258     if (http->peerName) {
259       time_t t      = currentTime;
260       struct tm *ltime;
261       check (ltime  = localtime(&t));
262       char timeBuf[80];
263       char lengthBuf[40];
264       check(strftime(timeBuf, sizeof(timeBuf),
265                      "[%d/%b/%Y:%H:%M:%S %z]", ltime));
266       if (http->totalWritten > 0) {
267         snprintf(lengthBuf, sizeof(lengthBuf), "%d", http->totalWritten);
268       } else {
269         *lengthBuf  = '\000';
270         strncat(lengthBuf, "-", sizeof(lengthBuf)-1);
271       }
272       info("%s - - %s \"%s %s %s\" %d %s",
273            http->peerName, timeBuf, http->method, http->path, http->version,
274            http->code, lengthBuf);
275     }
276   }
277   return rc;
278 }
279
280 static void httpDestroyHeaders(void *arg ATTR_UNUSED, char *key, char *value) {
281   UNUSED(arg);
282   free(key);
283   free(value);
284 }
285
286 static char *getPeerName(int fd, int *port, int numericHosts) {
287   struct sockaddr peerAddr;
288   socklen_t sockLen = sizeof(peerAddr);
289   if (getpeername(fd, &peerAddr, &sockLen)) {
290     if (port) {
291       *port         = -1;
292     }
293     return NULL;
294   }
295   char host[256];
296   if (numericHosts ||
297       getnameinfo(&peerAddr, sockLen, host, sizeof(host), NULL, 0, NI_NOFQDN)){
298     check(inet_ntop(peerAddr.sa_family,
299                     &((struct sockaddr_in *)&peerAddr)->sin_addr,
300                     host, sizeof(host)));
301   }
302   if (port) {
303     *port           = ntohs(((struct sockaddr_in *)&peerAddr)->sin_port);
304   }
305   char *ret;
306   check(ret         = strdup(host));
307   return ret;
308 }
309
310 static void httpSetState(struct HttpConnection *http, int state) {
311   if (state == (int)http->state) {
312     return;
313   }
314
315   if (state == COMMAND) {
316     if (http->state != SNIFFING_SSL) {
317       int rc                 = httpFinishCommand(http);
318       check(rc != HTTP_SUSPEND);
319       check(rc != HTTP_PARTIAL_REPLY);
320     }
321     check(!http->private);
322     free(http->url);
323     free(http->method);
324     free(http->path);
325     free(http->matchedPath);
326     free(http->pathInfo);
327     free(http->query);
328     free(http->version);
329     http->done               = 0;
330     http->url                = NULL;
331     http->method             = NULL;
332     http->path               = NULL;
333     http->matchedPath        = NULL;
334     http->pathInfo           = NULL;
335     http->query              = NULL;
336     http->version            = NULL;
337     destroyHashMap(&http->header);
338     initHashMap(&http->header, httpDestroyHeaders, NULL);
339     http->headerLength       = 0;
340     http->callback           = NULL;
341     http->arg                = NULL;
342     http->totalWritten       = 0;
343     http->code               = 200;
344   }
345   http->state                = state;
346 }
347
348 struct HttpConnection *newHttpConnection(struct Server *server, int fd,
349                                          int port, struct SSLSupport *ssl,
350                                          int numericHosts) {
351   struct HttpConnection *http;
352   check(http = malloc(sizeof(struct HttpConnection)));
353   initHttpConnection(http, server, fd, port, ssl, numericHosts);
354   return http;
355 }
356
357 void initHttpConnection(struct HttpConnection *http, struct Server *server,
358                         int fd, int port, struct SSLSupport *ssl,
359                         int numericHosts) {
360   http->server             = server;
361   http->connection         = NULL;
362   http->fd                 = fd;
363   http->port               = port;
364   http->closed             = 0;
365   http->isSuspended        = 0;
366   http->isPartialReply     = 0;
367   http->done               = 0;
368   http->state              = ssl ? SNIFFING_SSL : COMMAND;
369   http->peerName           = getPeerName(fd, &http->peerPort, numericHosts);
370   http->url                = NULL;
371   http->method             = NULL;
372   http->path               = NULL;
373   http->matchedPath        = NULL;
374   http->pathInfo           = NULL;
375   http->query              = NULL;
376   http->version            = NULL;
377   initHashMap(&http->header, httpDestroyHeaders, NULL);
378   http->headerLength       = 0;
379   http->key                = NULL;
380   http->partial            = NULL;
381   http->partialLength      = 0;
382   http->msg                = NULL;
383   http->msgLength          = 0;
384   http->msgOffset          = 0;
385   http->totalWritten       = 0;
386   http->expecting          = 0;
387   http->websocketType      = WS_UNDEFINED;
388   http->callback           = NULL;
389   http->websocketHandler   = NULL;
390   http->arg                = NULL;
391   http->private            = NULL;
392   http->code               = 200;
393   http->ssl                = ssl;
394   http->sslHndl            = NULL;
395   http->lastError          = 0;
396   if (logIsInfo()) {
397     debug("Accepted connection from %s:%d",
398           http->peerName ? http->peerName : "???", http->peerPort);
399   }
400 }
401
402 void destroyHttpConnection(struct HttpConnection *http) {
403   if (http) {
404     if (http->isSuspended || http->isPartialReply) {
405       if (!http->done) {
406         if (http->callback) {
407           http->callback(http, http->arg, NULL, 0);
408         } else if (http->websocketHandler) {
409           http->websocketHandler(http, http->arg, WS_CONNECTION_CLOSED,NULL,0);
410         }
411       }
412       http->callback       = NULL;
413       http->isSuspended    = 0;
414       http->isPartialReply = 0;
415     }
416     httpSetState(http, COMMAND);
417     if (logIsInfo()) {
418       debug("Closing connection to %s:%d",
419             http->peerName ? http->peerName : "???", http->peerPort);
420     }
421     httpShutdown(http, http->closed ? SHUT_WR : SHUT_RDWR);
422     dcheck(!close(http->fd));
423     free(http->peerName);
424     free(http->url);
425     free(http->method);
426     free(http->path);
427     free(http->matchedPath);
428     free(http->pathInfo);
429     free(http->query);
430     free(http->version);
431     destroyHashMap(&http->header);
432     free(http->partial);
433     free(http->msg);
434   }
435 }
436
437 void deleteHttpConnection(struct HttpConnection *http) {
438   destroyHttpConnection(http);
439   free(http);
440 }
441
442 #ifdef HAVE_ZLIB
443 static int httpAcceptsEncoding(struct HttpConnection *http,
444                                const char *encoding) {
445   int encodingLength  = strlen(encoding);
446   const char *accepts = getFromHashMap(&http->header, "accept-encoding");
447   if (!accepts) {
448     return 0;
449   }
450   double all          = -1.0;
451   double match        = -1.0;
452   while (*accepts) {
453     while (*accepts == ' ' || *accepts == '\t' ||
454            *accepts == '\r' || *accepts == '\n') {
455       accepts++;
456     }
457     const char *ptr   = accepts;
458     while (*ptr && *ptr != ',' && *ptr != ';' &&
459            *ptr != ' ' && *ptr != '\t' &&
460            *ptr != '\r' && *ptr != '\n') {
461       ptr++;
462     }
463     int isAll         = ptr - accepts == 1 && *accepts == '*';
464     int isMatch       = ptr - accepts == encodingLength &&
465                         !strncasecmp(accepts, encoding, encodingLength);
466     while (*ptr && *ptr != ';' && *ptr != ',') {
467       ptr++;
468     }
469     double val        = 1.0;
470     if (*ptr == ';') {
471       ptr++;
472       while (*ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == '\n') {
473         ptr++;
474       }
475       if ((*ptr | 0x20) == 'q') {
476         ptr++;
477         while (*ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == '\n') {
478           ptr++;
479         }
480         if (*ptr == '=') {
481           val         = strtod(ptr + 1, (char **)&ptr);
482         }
483       }
484     }
485     if (isnan(val) || val == -HUGE_VAL || val < 0) {
486       val             = 0;
487     } else if (val == HUGE_VAL || val > 1.0) {
488       val             = 1.0;
489     }
490     if (isAll) {
491       all             = val;
492     } else if (isMatch) {
493       match           = val;
494     }
495     while (*ptr && *ptr != ',') {
496       ptr++;
497     }
498     while (*ptr == ',') {
499       ptr++;
500     }
501     accepts           = ptr;
502   }
503   if (match >= 0.0) {
504     return match > 0.0;
505   } else {
506     return all > 0.0;
507   }
508 }
509 #endif
510
511 static void removeHeader(char *header, int *headerLength, const char *id) {
512   check(header);
513   check(headerLength);
514   check(*headerLength >= 0);
515   check(id);
516   check(strchr(id, ':'));
517   int idLength       = strlen(id);
518   if (idLength <= 0) {
519     return;
520   }
521   for (char *ptr = header; header + *headerLength - ptr >= idLength; ) {
522     char *end        = ptr;
523     do {
524       end            = memchr(end, '\n', header + *headerLength - end);
525       if (end == NULL) {
526         end          = header + *headerLength;
527       } else {
528         ++end;
529       }
530     } while (end < header + *headerLength && *end == ' ');
531     if (!strncasecmp(ptr, id, idLength)) {
532       memmove(ptr, end, header + *headerLength - end);
533       *headerLength -= end - ptr;
534     } else {
535       ptr            = end;
536     }
537   }
538 }
539
540 static void addHeader(char **header, int *headerLength, const char *fmt, ...) {
541   check(header);
542   check(headerLength);
543   check(*headerLength >= 0);
544   check(strstr(fmt, "\r\n"));
545
546   va_list ap;
547   va_start(ap, fmt);
548   char *tmp        = vStringPrintf(NULL, fmt, ap);
549   va_end(ap);
550   int tmpLength    = strlen(tmp);
551
552   if (*headerLength >= 2 && !memcmp(*header + *headerLength - 2, "\r\n", 2)) {
553     *headerLength -= 2;
554   }
555   check(*header    = realloc(*header, *headerLength + tmpLength + 2));
556
557   memcpy(*header + *headerLength, tmp, tmpLength);
558   memcpy(*header + *headerLength + tmpLength, "\r\n", 2);
559   *headerLength   += tmpLength + 2;
560   free(tmp);
561 }
562
563 void httpTransfer(struct HttpConnection *http, char *msg, int len) {
564   check(msg);
565   check(len >= 0);
566
567   // Internet Explorer seems to have difficulties with compressed data. It
568   // also has difficulties with SSL connections that are being proxied.
569   int ieBug                 = 0;
570   const char *userAgent     = getFromHashMap(&http->header, "user-agent");
571   const char *msie          = userAgent ? strstr(userAgent, "MSIE ") : NULL;
572   if (msie) {
573     ieBug++;
574   }
575
576   char *header              = NULL;
577   int headerLength          = 0;
578   int bodyOffset            = 0;
579
580   int compress              = 0;
581   if (!http->totalWritten) {
582     // Perform some basic sanity checks. This does not necessarily catch all
583     // possible problems, though.
584     int l                   = len;
585     char *line              = msg;
586     for (char *eol, *lastLine = NULL;
587          l > 0 && (eol = memchr(line, '\n', l)) != NULL; ) {
588       // All lines end in CR LF
589       check(eol[-1] == '\r');
590       if (!lastLine) {
591         // The first line looks like "HTTP/1.x STATUS\r\n"
592         check(eol - line > 11);
593         check(!memcmp(line, "HTTP/1.", 7));
594         check(line[7] >= '0' && line[7] <= '9' &&
595               (line[8] == ' ' || line[8] == '\t'));
596         int i               = eol - line - 9;
597         for (char *ptr = line + 9; i-- > 0; ) {
598           char ch           = *ptr++;
599           if (ch < '0' || ch > '9') {
600             check(ptr > line + 10);
601             check(ch == ' ' || ch == '\t');
602             break;
603           }
604         }
605         check(i > 1);
606       } else if (line + 1 == eol) {
607         // Found the end of the headers.
608
609         // Check that we don't send any data with HEAD requests
610         int isHead          = !strcmp(http->method, "HEAD");
611         check(l == 2 || !isHead);
612
613         #ifdef HAVE_ZLIB
614         // Compress replies that might exceed the size of a single IP packet
615         compress            = !ieBug && !isHead &&
616                               !http->isPartialReply &&
617                               len > 1400 &&
618                               httpAcceptsEncoding(http, "deflate");
619         #endif
620         break;
621       } else {
622         // Header lines either contain a colon, or they are continuation
623         // lines
624         if (*line != ' ' && *line != '\t') {
625           check(memchr(line, ':', eol - line));
626         }
627       }
628       lastLine              = line;
629       l                    -= eol - line + 1;
630       line                  = eol + 1;
631     }
632
633     if (ieBug || compress) {
634       if (l >= 2 && !memcmp(line, "\r\n", 2)) {
635         line               += 2;
636         l                  -= 2;
637       }
638       headerLength          = line - msg;
639       bodyOffset            = headerLength;
640       check(header          = malloc(headerLength));
641       memcpy(header, msg, headerLength);
642     }
643     if (ieBug) {
644       removeHeader(header, &headerLength, "connection:");
645       addHeader(&header, &headerLength, "Connection: close\r\n");
646     }
647
648     if (compress) {
649       #ifdef HAVE_ZLIB
650       // Compress the message
651       char *compressed;
652       check(compressed      = malloc(len));
653       check(len >= bodyOffset + 2);
654       z_stream strm         = { .zalloc    = Z_NULL,
655                                 .zfree     = Z_NULL,
656                                 .opaque    = Z_NULL,
657                                 .avail_in  = l,
658                                 .next_in   = (unsigned char *)line,
659                                 .avail_out = len,
660                                 .next_out  = (unsigned char *)compressed
661                               };
662       if (deflateInit(&strm, Z_DEFAULT_COMPRESSION) == Z_OK) {
663         if (deflate(&strm, Z_FINISH) == Z_STREAM_END) {
664           // Compression was successful and resulted in reduction in size
665           debug("Compressed response from %d to %d", len, len-strm.avail_out);
666           free(msg);
667           msg               = compressed;
668           len              -= strm.avail_out;
669           bodyOffset        = 0;
670           removeHeader(header, &headerLength, "content-length:");
671           removeHeader(header, &headerLength, "content-encoding:");
672           addHeader(&header, &headerLength, "Content-Length: %d\r\n", len);
673           addHeader(&header, &headerLength, "Content-Encoding: deflate\r\n");
674         } else {
675           free(compressed);
676         }
677         deflateEnd(&strm);
678       } else {
679         free(compressed);
680       }
681       #endif
682     }
683   }
684
685   http->totalWritten       += headerLength + (len - bodyOffset);
686   if (!headerLength) {
687     free(header);
688   } else if (http->msg) {
689     check(http->msg         = realloc(http->msg,
690                                       http->msgLength - http->msgOffset +
691                                       max(http->msgOffset, headerLength)));
692     if (http->msgOffset) {
693       memmove(http->msg, http->msg + http->msgOffset,
694               http->msgLength - http->msgOffset);
695       http->msgLength      -= http->msgOffset;
696       http->msgOffset       = 0;
697     }
698     memcpy(http->msg + http->msgLength, header, headerLength);
699     http->msgLength        += headerLength;
700     free(header);
701   } else {
702     check(!http->msgOffset);
703     http->msg               = header;
704     http->msgLength         = headerLength;
705   }
706
707   if (len <= bodyOffset) {
708     free(msg);
709   } else if (http->msg) {
710     check(http->msg         = realloc(http->msg,
711                                       http->msgLength - http->msgOffset +
712                                       max(http->msgOffset, len - bodyOffset)));
713     if (http->msgOffset) {
714       memmove(http->msg, http->msg + http->msgOffset,
715               http->msgLength - http->msgOffset);
716       http->msgLength      -= http->msgOffset;
717       http->msgOffset       = 0;
718     }
719     memcpy(http->msg + http->msgLength, msg + bodyOffset, len - bodyOffset);
720     http->msgLength        += len - bodyOffset;
721     free(msg);
722   } else {
723     check(!http->msgOffset);
724     if (bodyOffset) {
725       memmove(msg, msg + bodyOffset, len - bodyOffset);
726     }
727     http->msg               = msg;
728     http->msgLength         = len - bodyOffset;
729   }
730
731   // The caller can suspend the connection, so that it can send an
732   // asynchronous reply. Once the reply has been sent, the connection
733   // gets reactivated. Normally, this means it would go back to listening
734   // for commands.
735   // Similarly, the caller can indicate that this is a partial message and
736   // return additional data in subsequent calls to the callback handler.
737   if (http->isSuspended || http->isPartialReply) {
738     if (http->msg && http->msgLength > 0) {
739       int wrote             = httpWrite(http, http->msg, http->msgLength);
740       if (wrote < 0 && errno != EAGAIN) {
741         httpCloseRead(http);
742         free(http->msg);
743         http->msgLength     = 0;
744         http->msg           = NULL;
745       } else if (wrote > 0) {
746         if (wrote == http->msgLength) {
747           free(http->msg);
748           http->msgLength   = 0;
749           http->msg         = NULL;
750         } else {
751           memmove(http->msg, http->msg + wrote, http->msgLength - wrote);
752           http->msgLength  -= wrote;
753         }
754       }
755     }
756
757     check(http->state == PAYLOAD || http->state == DISCARD_PAYLOAD);
758     if (!http->isPartialReply) {
759       if (http->expecting < 0) {
760         // If we do not know the length of the content, close the connection.
761         debug("Closing previously suspended connection");
762         httpCloseRead(http);
763         httpSetState(http, DISCARD_PAYLOAD);
764       } else if (http->expecting == 0) {
765         httpSetState(http, COMMAND);
766         http->isSuspended  = 0;
767         struct ServerConnection *connection = httpGetServerConnection(http);
768         if (!serverGetTimeout(connection)) {
769           serverSetTimeout(connection, CONNECTION_TIMEOUT);
770         }
771         serverConnectionSetEvents(http->server, connection, http->fd,
772                                   http->msgLength ? POLLIN|POLLOUT : POLLIN);
773       }
774     }
775   }
776
777   if (ieBug) {
778     httpCloseRead(http);
779   }
780 }
781
782 void httpTransferPartialReply(struct HttpConnection *http, char *msg, int len){
783   check(!http->isSuspended);
784   http->isPartialReply = 1;
785   if (http->state != PAYLOAD && http->state != DISCARD_PAYLOAD) {
786     check(http->state == HEADERS);
787     httpSetState(http, PAYLOAD);
788   }
789   httpTransfer(http, msg, len);
790 }
791
792 static int httpHandleCommand(struct HttpConnection *http,
793                              const struct Trie *handlers) {
794   debug("Handling \"%s\" \"%s\"", http->method, http->path);
795   const char *contentLength                  = getFromHashMap(&http->header,
796                                                              "content-length");
797   if (contentLength != NULL && *contentLength) {
798     char *endptr;
799     http->expecting                          = strtol(contentLength,
800                                                       &endptr, 10);
801     if (*endptr) {
802       // Invalid length. Read until end of stream and then close
803       // connection.
804       http->expecting                        = -1;
805     }
806   } else {
807       // Unknown length. Read until end of stream and then close
808       // connection.
809     http->expecting                          = -1;
810   }
811   if (!strcmp(http->method, "OPTIONS")) {
812     char *response                           = stringPrintf(NULL,
813                                                 "HTTP/1.1 200 OK\r\n"
814                                                 "Content-Length: 0\r\n"
815                                                 "Allow: GET, POST, OPTIONS\r\n"
816                                                 "\r\n");
817     httpTransfer(http, response, strlen(response));
818     if (http->expecting < 0) {
819       http->expecting                        = 0;
820     }
821     return HTTP_READ_MORE;
822   } else if (!strcmp(http->method, "GET")) {
823     if (http->expecting < 0) {
824       http->expecting                        = 0;
825     }
826   } else if (!strcmp(http->method, "POST")) {
827   } else if (!strcmp(http->method, "HEAD")) {
828     if (http->expecting < 0) {
829       http->expecting                        = 0;
830     }
831   } else if (!strcmp(http->method, "PUT")    ||
832              !strcmp(http->method, "DELETE") ||
833              !strcmp(http->method, "TRACE")  ||
834              !strcmp(http->method, "CONNECT")) {
835     httpSendReply(http, 405, "Method Not Allowed", NO_MSG);
836     return HTTP_DONE;
837   } else {
838     httpSendReply(http, 501, "Method Not Implemented", NO_MSG);
839     return HTTP_DONE;
840   }
841   const char *host                           = getFromHashMap(&http->header,
842                                                               "host");
843   if (host) {
844     for (char ch, *ptr = (char *)host; (ch = *ptr) != '\000'; ptr++) {
845       if (ch == ':') {
846         *ptr                                 = '\000';
847         break;
848       }
849       if (ch != '-' && ch != '.' &&
850           (ch < '0' ||(ch > '9' && ch < 'A') ||
851           (ch > 'Z' && ch < 'a')||(ch > 'z' && ch <= 0x7E))) {
852         httpSendReply(http, 400, "Bad Request", NO_MSG);
853         return HTTP_DONE;
854       }
855     }
856   }
857
858   char *diff;
859   struct HttpHandler *h = (struct HttpHandler *)getFromTrie(handlers,
860                                                             http->path, &diff);
861
862   if (h) {
863     if (h->websocketHandler) {
864       // Check for WebSocket handshake
865       const char *upgrade                    = getFromHashMap(&http->header,
866                                                               "upgrade");
867       if (upgrade && !strcmp(upgrade, "WebSocket")) {
868         const char *connection               = getFromHashMap(&http->header,
869                                                               "connection");
870         if (connection && !strcmp(connection, "Upgrade")) {
871           const char *origin                 = getFromHashMap(&http->header,
872                                                               "origin");
873           if (origin) {
874             for (const char *ptr = origin; *ptr; ptr++) {
875               if ((unsigned char)*ptr < ' ') {
876                 goto bad_ws_upgrade;
877               }
878             }
879
880             const char *protocol             = getFromHashMap(&http->header,
881                                                          "websocket-protocol");
882             if (protocol) {
883               for (const char *ptr = protocol; *ptr; ptr++) {
884                 if ((unsigned char)*ptr < ' ') {
885                   goto bad_ws_upgrade;
886                 }
887               }
888             }
889             char *port                       = NULL;
890             if (http->port != (http->sslHndl ? 443 : 80)) {
891               port                           = stringPrintf(NULL,
892                                                             ":%d", http->port);
893             }
894             char *response                   = stringPrintf(NULL,
895               "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
896               "Upgrade: WebSocket\r\n"
897               "Connection: Upgrade\r\n"
898               "WebSocket-Origin: %s\r\n"
899               "WebSocket-Location: %s://%s%s%s\r\n"
900               "%s%s%s"
901               "\r\n",
902               origin,
903               http->sslHndl ? "wss" : "ws", host && *host ? host : "localhost",
904               port ? port : "", http->path,
905               protocol ? "WebSocket-Protocol: " : "",
906               protocol ? protocol : "",
907               protocol ? "\r\n" : "");
908             free(port);
909             debug("Switching to WebSockets");
910             httpTransfer(http, response, strlen(response));
911             if (http->expecting < 0) {
912               http->expecting                = 0;
913             }
914             http->websocketHandler           = h->websocketHandler;
915             httpSetState(http, WEBSOCKET);
916             return HTTP_READ_MORE;
917           }
918         }
919       }
920     }
921   bad_ws_upgrade:;
922
923     if (h->handler) {
924       check(diff);
925       while (diff > http->path && diff[-1] == '/') {
926         diff--;
927       }
928       if (!*diff || *diff == '/' || *diff == '?' || *diff == '#') {
929         check(!http->matchedPath);
930         check(!http->pathInfo);
931         check(!http->query);
932
933         check(http->matchedPath              = malloc(diff - http->path + 1));
934         memcpy(http->matchedPath, http->path, diff - http->path);
935         http->matchedPath[diff - http->path] = '\000';
936
937         const char *query = strchr(diff, '?');
938         if (*diff && *diff != '?') {
939           const char *endOfInfo              = query
940                                                ? query : strrchr(diff, '\000');
941           check(http->pathInfo               = malloc(endOfInfo - diff + 1));
942           memcpy(http->pathInfo, diff, endOfInfo - diff);
943           http->pathInfo[endOfInfo - diff]   = '\000';
944         }
945
946         if (query) {
947           check(http->query                  = strdup(query + 1));
948         }
949         return h->handler(http, h->arg);
950       }
951     }
952   }
953   httpSendReply(http, 404, "File Not Found", NO_MSG);
954   return HTTP_DONE;
955 }
956
957 static int httpGetChar(struct HttpConnection *http, const char *buf,
958                        int size, int *offset) {
959   if (*offset < 0) {
960     return (unsigned char)http->partial[http->partialLength + (*offset)++];
961   } else if (*offset < size) {
962     return (unsigned char)buf[(*offset)++];
963   } else {
964     return -1;
965   }
966 }
967
968 static int httpParseCommand(struct HttpConnection *http, int offset,
969                             const char *buf, int bytes, int firstSpace,
970                             int lastSpace, int lineLength) {
971   if (firstSpace < 1 || lastSpace < 0) {
972   bad_request:
973     if (!http->method) {
974       check(http->method  = strdup(""));
975     }
976     if (!http->path) {
977       check(http->path    = strdup(""));
978     }
979     if (!http->version) {
980       check(http->version = strdup(""));
981     }
982     httpSendReply(http, 400, "Bad Request", NO_MSG);
983     httpSetState(http, COMMAND);
984     return 0;
985   }
986   check(!http->method);
987   check(http->method      = malloc(firstSpace + 1));
988   int i                   = offset;
989   int j                   = 0;
990   for (; j < firstSpace; j++) {
991     int ch                = httpGetChar(http, buf, bytes, &i);
992     if (ch >= 'a' && ch <= 'z') {
993       ch                 &= ~0x20;
994     }
995     http->method[j]       = ch;
996   }
997   http->method[j]         = '\000';
998   check(!http->path);
999   check(http->path        = malloc(lastSpace - firstSpace));
1000   j                       = 0;
1001   while (i < offset + lastSpace) {
1002     int ch                = httpGetChar(http, buf, bytes, &i);
1003     if ((ch != ' ' && ch != '\t') || j) {
1004       http->path[j++]     = ch;
1005     }
1006   }
1007   http->path[j]           = '\000';
1008   if (*http->path != '/' &&
1009       (strcmp(http->method, "OPTIONS") || strcmp(http->path, "*"))) {
1010     goto bad_request;
1011   }
1012   check(!http->version);
1013   check(http->version     = malloc(lineLength - lastSpace + 1));
1014   j                       = 0;
1015   while (i < offset + lineLength) {
1016     int ch                = httpGetChar(http, buf, bytes, &i);
1017     if (ch == '\r') {
1018       break;
1019     }
1020     if (ch >= 'a' && ch <= 'z') {
1021       ch                 &= ~0x20;
1022     }
1023     if ((ch != ' ' && ch != '\t') || j) {
1024       http->version[j]    = ch;
1025       j++;
1026     }
1027   }
1028   http->version[j]        = '\000';
1029   if (memcmp(http->version, "HTTP/", 5) ||
1030       (http->version[5] < '1' || http->version[5] > '9')) {
1031     goto bad_request;
1032   }
1033   httpSetState(http, HEADERS);
1034   return 1;
1035 }
1036
1037 static int httpParseHeaders(struct HttpConnection *http,
1038                             const struct Trie *handlers, int offset,
1039                             const char *buf, int bytes, int colon,
1040                             int lineLength) {
1041   int i                    = offset;
1042   int ch                   = httpGetChar(http, buf, bytes, &i);
1043   if (ch == ' ' || ch == '\t') {
1044     if (http->key) {
1045       char **oldValue      = getRefFromHashMap(&http->header, http->key);
1046       check(oldValue);
1047       int oldLength        = strlen(*oldValue);
1048       check(*oldValue      = realloc(*oldValue,
1049                                     oldLength + lineLength + 1));
1050       int j                = oldLength;
1051       int end              = oldLength + lineLength;
1052       (*oldValue)[j++]     = ' ';
1053       for (; j < end; j++) {
1054         ch                 = httpGetChar(http, buf, bytes, &i);
1055         if (ch == ' ' || ch == '\t') {
1056           end--;
1057           j--;
1058           continue;
1059         } else if (ch == '\r' && j == end - 1) {
1060           break;
1061         }
1062         (*oldValue)[j]     = ch;
1063       }
1064       (*oldValue)[j]       = '\000';
1065     }
1066   } else if ((ch == '\r' &&
1067               httpGetChar(http, buf, bytes, &i) == '\n') ||
1068              ch == '\n' || ch == -1) {
1069     check(!http->expecting);
1070     http->callback         = NULL;
1071     http->arg              = NULL;
1072     int rc                 = httpHandleCommand(http, handlers);
1073   retry:;
1074     struct ServerConnection *connection = httpGetServerConnection(http);
1075     switch (rc) {
1076     case HTTP_DONE:
1077     case HTTP_ERROR: {
1078       if (http->expecting < 0 || rc == HTTP_ERROR) {
1079         httpCloseRead(http);
1080       }
1081       http->done           = 1;
1082       http->isSuspended    = 0;
1083       http->isPartialReply = 0;
1084       if (!serverGetTimeout(connection)) {
1085         serverSetTimeout(connection, CONNECTION_TIMEOUT);
1086       }
1087       httpSetState(http, http->expecting ? DISCARD_PAYLOAD : COMMAND);
1088       break; }
1089     case HTTP_READ_MORE:
1090       http->isSuspended    = 0;
1091       http->isPartialReply = 0;
1092       if (!serverGetTimeout(connection)) {
1093         serverSetTimeout(connection, CONNECTION_TIMEOUT);
1094       }
1095       check(!http->done);
1096       if (!http->expecting) {
1097         if (http->callback) {
1098           rc                 = http->callback(http, http->arg, "", 0);
1099           if (rc != HTTP_READ_MORE) {
1100             goto retry;
1101           }
1102         } else if (http->websocketHandler) {
1103           http->websocketHandler(http, http->arg, WS_CONNECTION_OPENED,
1104                                  NULL, 0);
1105         }
1106       }
1107       if (http->state != WEBSOCKET) {
1108         httpSetState(http, http->expecting ? PAYLOAD : COMMAND);
1109       }
1110       break;
1111     case HTTP_SUSPEND:
1112       http->isSuspended    = 1;
1113       http->isPartialReply = 0;
1114       serverSetTimeout(connection, 0);
1115       if (http->state != PAYLOAD && http->state != DISCARD_PAYLOAD) {
1116         check(http->state == HEADERS);
1117         httpSetState(http, PAYLOAD);
1118       }
1119       break;
1120     case HTTP_PARTIAL_REPLY:
1121       http->isSuspended    = 0;
1122       http->isPartialReply = 1;
1123       if (http->state != PAYLOAD && http->state != DISCARD_PAYLOAD) {
1124         check(http->state == HEADERS);
1125         httpSetState(http, PAYLOAD);
1126       }
1127       break;
1128     default:
1129       check(0);
1130     }
1131     if (ch == -1) {
1132       httpCloseRead(http);
1133     }
1134   } else {
1135     if (colon <= 0) {
1136       httpSendReply(http, 400, "Bad Request", NO_MSG);
1137       return 0;
1138     }
1139     check(colon < lineLength);
1140     check(http->key        = malloc(colon + 1));
1141     int i                  = offset;
1142     for (int j = 0; j < colon; j++) {
1143       ch                   = httpGetChar(http, buf, bytes, &i);
1144       if (ch >= 'A' && ch <= 'Z') {
1145         ch                |= 0x20;
1146       }
1147       http->key[j]         = ch;
1148     }
1149     http->key[colon]       = '\000';
1150     char *value;
1151     check(value            = malloc(lineLength - colon));
1152     i++;
1153     int j                  = 0;
1154     for (int k = 0; k < lineLength - colon - 1; j++, k++) {
1155       int ch           = httpGetChar(http, buf, bytes, &i);
1156       if ((ch == ' ' || ch == '\t') && j == 0) {
1157         j--;
1158       } else if (ch == '\r' && k == lineLength - colon - 2) {
1159         break;
1160       } else {
1161         value[j]           = ch;
1162       }
1163     }
1164     value[j]               = '\000';
1165     if (getRefFromHashMap(&http->header, http->key)) {
1166       debug("Dropping duplicate header \"%s\"", http->key);
1167       free(http->key);
1168       free(value);
1169       http->key            = NULL;
1170     } else {
1171       addToHashMap(&http->header, http->key, value);
1172     }
1173   }
1174   return 1;
1175 }
1176
1177 static int httpConsumePayload(struct HttpConnection *http, const char *buf,
1178                               int len) {
1179   if (http->expecting >= 0) {
1180     // If positive, we know the expected length of payload and
1181     // can keep the connection open.
1182     // If negative, allow unlimited payload, but close connection
1183     // when done.
1184     if (len > http->expecting) {
1185       len                  = http->expecting;
1186     }
1187     http->expecting       -= len;
1188   }
1189   if (http->callback) {
1190     check(!http->done);
1191     int rc                 = http->callback(http, http->arg, buf, len);
1192     struct ServerConnection *connection = httpGetServerConnection(http);
1193     switch (rc) {
1194     case HTTP_DONE:
1195     case HTTP_ERROR:
1196       if (http->expecting < 0 || rc == HTTP_ERROR) {
1197         httpCloseRead(http);
1198       }
1199       http->done           = 1;
1200       http->isSuspended    = 0;
1201       http->isPartialReply = 0;
1202       if (!serverGetTimeout(connection)) {
1203         serverSetTimeout(connection, CONNECTION_TIMEOUT);
1204       }
1205       httpSetState(http, http->expecting ? DISCARD_PAYLOAD : COMMAND);
1206       break;
1207     case HTTP_READ_MORE:
1208       http->isSuspended    = 0;
1209       http->isPartialReply = 0;
1210       if (!serverGetTimeout(connection)) {
1211         serverSetTimeout(connection, CONNECTION_TIMEOUT);
1212       }
1213       if (!http->expecting) {
1214         httpSetState(http, COMMAND);
1215       }
1216       break;
1217     case HTTP_SUSPEND:
1218       http->isSuspended    = 1;
1219       http->isPartialReply = 0;
1220       serverSetTimeout(connection, 0);
1221       if (http->state != PAYLOAD && http->state != DISCARD_PAYLOAD) {
1222         check(http->state == HEADERS);
1223         httpSetState(http, PAYLOAD);
1224       }
1225       break;
1226     case HTTP_PARTIAL_REPLY:
1227       http->isSuspended    = 0;
1228       http->isPartialReply = 1;
1229       if (http->state != PAYLOAD && http->state != DISCARD_PAYLOAD) {
1230         check(http->state == HEADERS);
1231         httpSetState(http, PAYLOAD);
1232       }
1233       break;
1234     default:
1235       check(0);
1236     }
1237   } else {
1238     // If we do not have a callback for handling the payload, and we also do
1239     // not know how long the payload is (because there was not Content-Length),
1240     // we now close the connection.
1241     if (http->expecting < 0) {
1242       http->expecting      = 0;
1243       httpCloseRead(http);
1244       httpSetState(http, COMMAND);
1245     }
1246   }
1247   return len;
1248 }
1249
1250 static int httpParsePayload(struct HttpConnection *http, int offset,
1251                             const char *buf, int bytes) {
1252   int consumed               = 0;
1253   if (offset < 0) {
1254     check(-offset <= http->partialLength);
1255     if (http->expecting) {
1256       consumed               = httpConsumePayload(http,
1257                                   http->partial + http->partialLength + offset,
1258                                   -offset);
1259       if (consumed == http->partialLength) {
1260         free(http->partial);
1261         http->partial        = NULL;
1262         http->partialLength  = 0;
1263       } else {
1264         memmove(http->partial, http->partial + consumed,
1265                 http->partialLength - consumed);
1266         http->partialLength -= consumed;
1267       }
1268       offset                += consumed;
1269     }
1270   }
1271   if (http->expecting && bytes - offset > 0) {
1272     check(offset >= 0);
1273     consumed                += httpConsumePayload(http, buf + offset,
1274                                                   bytes - offset);
1275   }
1276   return consumed;
1277 }
1278
1279 static int httpHandleWebSocket(struct HttpConnection *http, int offset,
1280                                const char *buf, int bytes) {
1281   check(http->websocketHandler);
1282   int ch                          = 0x00;
1283   while (bytes > offset) {
1284     if (http->websocketType & WS_UNDEFINED) {
1285       ch                          = httpGetChar(http, buf, bytes, &offset);
1286       check(ch >= 0);
1287       if (http->websocketType & 0xFF) {
1288         // Reading another byte of length information.
1289         if (http->expecting > 0xFFFFFF) {
1290           return 0;
1291         }
1292         http->expecting           = (128 * http->expecting) + (ch & 0x7F);
1293         if ((ch & 0x80) == 0) {
1294           // Done reading length information.
1295           http->websocketType    &= ~WS_UNDEFINED;
1296
1297           // ch is used to detect when we read the terminating byte in text
1298           // mode. In binary mode, it must be set to something other than 0xFF.
1299           ch                      = 0x00;
1300         }
1301       } else {
1302         // Reading first byte of frame.
1303         http->websocketType       = (ch & 0xFF) | WS_START_OF_FRAME;
1304         if (ch & 0x80) {
1305           // For binary data, we have to read the length before we can start
1306           // processing payload.
1307           http->websocketType    |= WS_UNDEFINED;
1308           http->expecting         = 0;
1309         }
1310       }
1311     } else if (http->websocketType & 0x80) {
1312       // Binary data
1313       if (http->expecting) {
1314         if (offset < 0) {
1315         handle_partial:
1316           check(-offset <= http->partialLength);
1317           int len                 = -offset;
1318           if (len >= http->expecting) {
1319             len                   = http->expecting;
1320             http->websocketType  |= WS_END_OF_FRAME;
1321           }
1322           if (len &&
1323               http->websocketHandler(http, http->arg, http->websocketType,
1324                                   http->partial + http->partialLength + offset,
1325                                   len) != HTTP_DONE) {
1326             return 0;
1327           }
1328
1329           if (ch == 0xFF) {
1330             // In text mode, we jump to handle_partial, when we find the
1331             // terminating 0xFF byte. If so, we should try to consume it now.
1332             if (len < http->partialLength) {
1333               len++;
1334               http->websocketType = WS_UNDEFINED;
1335             }
1336           }
1337
1338           if (len == http->partialLength) {
1339             free(http->partial);
1340             http->partial         = NULL;
1341             http->partialLength   = 0;
1342           } else {
1343             memmove(http->partial, http->partial + len,
1344                     http->partialLength - len);
1345             http->partialLength  -= len;
1346           }
1347           offset                 += len;
1348           http->expecting        -= len;
1349         } else {
1350         handle_buffered:;
1351           int len                 = bytes - offset;
1352           if (len >= http->expecting) {
1353             len                   = http->expecting;
1354             http->websocketType  |= WS_END_OF_FRAME;
1355           }
1356           if (len &&
1357               http->websocketHandler(http, http->arg, http->websocketType,
1358                                      buf + offset, len) != HTTP_DONE) {
1359             return 0;
1360           }
1361
1362           if (ch == 0xFF) {
1363             // In text mode, we jump to handle_buffered, when we find the
1364             // terminating 0xFF byte. If so, we should consume it now.
1365             check(offset + len < bytes);
1366             len++;
1367             http->websocketType   = WS_UNDEFINED;
1368           }
1369           offset                 += len;
1370           http->expecting        -= len;
1371         }
1372         http->websocketType      &= ~(WS_START_OF_FRAME | WS_END_OF_FRAME);
1373       } else {
1374         // Read all data. Go back to looking for a new frame header.
1375         http->websocketType       = WS_UNDEFINED;
1376       }
1377     } else {
1378       // Process text data until we find a 0xFF bytes.
1379       int i                       = offset;
1380
1381       // If we have partial data, process that first.
1382       while (i < 0) {
1383         ch                        = httpGetChar(http, buf, bytes, &i);
1384         check(ch != -1);
1385
1386         // Terminate when we either find the 0xFF, or we have reached the end
1387         // of partial data.
1388         if (ch == 0xFF || !i) {
1389           // Set WS_END_OF_FRAME, iff we have found the 0xFF marker.
1390           http->expecting         = i - offset - (ch == 0xFF);
1391           goto handle_partial;
1392         }
1393       }
1394
1395       // Read all remaining buffered bytes (i.e. positive offset).
1396       while (bytes > i) {
1397         ch                        = httpGetChar(http, buf, bytes, &i);
1398         check(ch != -1);
1399
1400         // Terminate when we either find the 0xFF, or we have reached the end
1401         // of buffered data.
1402         if (ch == 0xFF || bytes == i) {
1403           // Set WS_END_OF_FRAME, iff we have found the 0xFF marker.
1404           http->expecting         = i - offset - (ch == 0xFF);
1405           goto handle_buffered;
1406         }
1407       }
1408     }
1409   }
1410   return 1;
1411 }
1412
1413 int httpHandleConnection(struct ServerConnection *connection, void *http_,
1414                          short *events, short revents) {
1415   struct HttpConnection *http        = (struct HttpConnection *)http_;
1416   struct Trie *handlers              = serverGetHttpHandlers(http->server);
1417   http->connection                   = connection;
1418   int  bytes;
1419   do {
1420     bytes                            = 0;
1421     *events                          = 0;
1422     char buf[4096];
1423     int  eof                         = http->closed;
1424     if ((revents & POLLIN) && !http->closed) {
1425       bytes                          = httpRead(http, buf, sizeof(buf));
1426       if (bytes > 0) {
1427         http->headerLength          += bytes;
1428         if (http->headerLength > MAX_HEADER_LENGTH) {
1429           httpSendReply(http, 413, "Header too big", NO_MSG);
1430           bytes                      = 0;
1431           eof                        = 1;
1432         }
1433       } else {
1434         if (bytes == 0 || errno != EAGAIN) {
1435           httpCloseRead(http);
1436           eof                        = 1;
1437         } else {
1438           if (http->sslHndl && http->lastError == SSL_ERROR_WANT_WRITE) {
1439             *events                 |= POLLOUT;
1440           }
1441         }
1442         bytes                        = 0;
1443       }
1444     }
1445
1446     if (bytes > 0 && http->state == SNIFFING_SSL) {
1447       // Assume that all legitimate HTTP commands start with a sequence of
1448       // letters followed by a space character. If we don't see this pattern,
1449       // or if the method does not match one of the known methods, we try
1450       // switching to SSL, instead.
1451       int isSSL                      = 0;
1452       char method[12]                = { 0 };
1453       for (int i = -http->partialLength, j = 0, ch;
1454            (ch = httpGetChar(http, buf, bytes, &i)) != -1;
1455            j++) {
1456         if ((j > 0 && (ch == ' ' || ch == '\t')) ||
1457             ch == '\r' || ch == '\n') {
1458           isSSL                      = strcmp(method, "OPTIONS") &&
1459                                        strcmp(method, "GET") &&
1460                                        strcmp(method, "HEAD") &&
1461                                        strcmp(method, "POST") &&
1462                                        strcmp(method, "PUT") &&
1463                                        strcmp(method, "DELETE") &&
1464                                        strcmp(method, "TRACE") &&
1465                                        strcmp(method, "CONNECT");
1466           http->state                = COMMAND;
1467           break;
1468         } else if (j >= (int)sizeof(method)-1 ||
1469                    ch < 'A' || (ch > 'Z' && ch < 'a') || ch > 'z') {
1470           isSSL                      = 1;
1471           http->state                = COMMAND;
1472           break;
1473         } else {
1474           method[j]                  = ch & ~0x20;
1475         }
1476       }
1477       if (isSSL) {
1478         if (httpPromoteToSSL(http, buf, bytes) < 0) {
1479           httpCloseRead(http);
1480           bytes                      = 0;
1481           eof                        = 1;
1482         } else {
1483           http->headerLength         = 0;
1484           *events                   |= POLLIN;
1485           continue;
1486         }
1487       }
1488     }
1489
1490     if (bytes > 0 || (eof && http->partial)) {
1491       check(!!http->partial == !!http->partialLength);
1492       int  offset                    = -http->partialLength;
1493       int  eob                       = 0;
1494       do {
1495         int pushBack                 = 0;
1496         int consumed                 = 0;
1497         if (http->state == SNIFFING_SSL || http->state == COMMAND ||
1498             http->state == HEADERS) {
1499           check(!http->expecting);
1500           int  lineLength            = 0;
1501           int  colon                 = -1;
1502           int  firstSpace            = -1;
1503           int  lastSpace             = -1;
1504           int  fullLine              = 1;
1505           for (int i = offset; ; lineLength++) {
1506             int ch                   = httpGetChar(http, buf, bytes, &i);
1507             if (ch == ':') {
1508               if (colon < 0) {
1509                 colon                = lineLength;
1510               }
1511             } else if (ch == ' ' || ch == '\t') {
1512               if (firstSpace < 0) {
1513                 firstSpace           = lineLength;
1514               } else {
1515                 lastSpace            = lineLength;
1516               }
1517             } else if (ch == '\n') {
1518               break;
1519             } else if (ch == -1) {
1520               fullLine               = 0;
1521               eob                    = 1;
1522               break;
1523             }
1524           }
1525           if (fullLine || eof) {
1526             consumed                 = lineLength + 1;
1527             if (lineLength) {
1528               if (http->state == SNIFFING_SSL || http->state == COMMAND) {
1529                 if (!httpParseCommand(http, offset, buf, bytes, firstSpace,
1530                                       lastSpace, lineLength)) {
1531                   break;
1532                 }
1533               } else {
1534                 check(http->state == HEADERS);
1535                 if (!httpParseHeaders(http, handlers, offset, buf, bytes,
1536                                       colon, lineLength)) {
1537                   break;
1538                 }
1539               }
1540             }
1541           } else {
1542             pushBack                 = lineLength;
1543           }
1544         } else if (http->state == PAYLOAD ||
1545                    http->state == DISCARD_PAYLOAD) {
1546           if (http->expecting) {
1547             int len                  = bytes - offset;
1548             if (http->expecting > 0 &&
1549                 len > http->expecting) {
1550               len                    = http->expecting;
1551             }
1552             if (http->state == PAYLOAD) {
1553               len                    = httpParsePayload(http, offset, buf,
1554                                                         len + offset);
1555             }
1556             consumed                 = len;
1557             pushBack                 = bytes - offset - len;
1558           }
1559         } else if (http->state == WEBSOCKET) {
1560           if (!httpHandleWebSocket(http, offset, buf, bytes)) {
1561             httpCloseRead(http);
1562             break;
1563           }
1564           consumed                  += bytes - offset;
1565         } else {
1566           check(0);
1567         }
1568
1569         offset                      += consumed;
1570         if (pushBack) {
1571           check(offset + pushBack == bytes);
1572           if (offset >= 0) {
1573             check(http->partial      = realloc(http->partial, pushBack));
1574             memcpy(http->partial, buf + offset, pushBack);
1575           } else if (pushBack != http->partialLength) {
1576             char *partial;
1577             check(partial            = malloc(pushBack));
1578             for (int i = offset, j = 0; j < pushBack; j++) {
1579               partial[j]             = httpGetChar(http, buf, bytes, &i);
1580             }
1581             free(http->partial);
1582             http->partial            = partial;
1583           }
1584           http->partialLength        = pushBack;
1585           offset                     = -pushBack;
1586           break;
1587         } else {
1588           eob                       |= offset >= bytes;
1589         }
1590       } while (!eob && !http->closed);
1591       if (http->closed || offset >= 0) {
1592         free(http->partial);
1593         http->partial                = NULL;
1594         http->partialLength          = 0;
1595       } else if (-offset != http->partialLength) {
1596         check(-offset < http->partialLength);
1597         memmove(http->partial, http->partial + http->partialLength + offset,
1598                 -offset);
1599         http->partialLength          = -offset;
1600       }
1601     }
1602
1603     // If the peer closed the connection, clean up now.
1604     if (eof) {
1605       check(!http->partial);
1606       switch (http->state) {
1607       case SNIFFING_SSL:
1608       case COMMAND:
1609         break;
1610       case HEADERS:
1611         check(!http->expecting);
1612         http->callback               = NULL;
1613         http->arg                    = NULL;
1614         httpHandleCommand(http, handlers);
1615         httpCloseRead(http);
1616         httpSetState(http, COMMAND);
1617         break;
1618       case PAYLOAD:
1619       case DISCARD_PAYLOAD:
1620       case WEBSOCKET:
1621         http->expecting              = 0;
1622         httpCloseRead(http);
1623         httpSetState(http, COMMAND);
1624         break;
1625       }
1626     }
1627
1628     for (;;) {
1629       // Try to write any pending outgoing data
1630       if (http->msg && http->msgLength > 0) {
1631         int wrote                    = httpWrite(http, http->msg,
1632                                                  http->msgLength);
1633         if (wrote < 0 && errno != EAGAIN) {
1634           httpCloseRead(http);
1635           free(http->msg);
1636           http->msgLength            = 0;
1637           http->msg                  = NULL;
1638           break;
1639         } else if (wrote > 0) {
1640           if (wrote == http->msgLength) {
1641             free(http->msg);
1642             http->msgLength          = 0;
1643             http->msg                = NULL;
1644           } else {
1645             memmove(http->msg, http->msg + wrote, http->msgLength - wrote);
1646             http->msgLength         -= wrote;
1647           }
1648         }
1649         // SSL might require reading in order to write
1650         else if (wrote < 0 && errno == EAGAIN && http->sslHndl) {
1651           if (http->lastError == SSL_ERROR_WANT_READ && !http->closed) {
1652             *events                 |= POLLIN;
1653           }
1654         }
1655       }
1656   
1657       // If the callback only provided partial data, refill the outgoing
1658       // buffer whenever it runs low.
1659       if (http->isPartialReply && (!http->msg || http->msgLength <= 0)) {
1660         httpConsumePayload(http, "", 0);
1661       } else {
1662         break;
1663       }
1664     }
1665
1666     *events                         |=
1667       (*events & ~(POLLIN|POLLOUT)) |
1668       (!http->closed && ((http->state != PAYLOAD &&
1669                           http->state != DISCARD_PAYLOAD) ||
1670                          http->expecting) ? POLLIN : 0) |
1671       (http->msg || http->isPartialReply ? POLLOUT : 0);
1672
1673     connection                       = httpGetServerConnection(http);
1674     int timedOut                     = serverGetTimeout(connection) < 0;
1675     if (timedOut) {
1676       free(http->partial);
1677       http->partial                  = NULL;
1678       http->partialLength            = 0;
1679       free(http->msg);
1680       http->msg                      = NULL;
1681       http->msgLength                = 0;
1682     }
1683   
1684     if ((!(*events || http->isSuspended) || timedOut) && http->sslHndl) {
1685       *events                        = 0;
1686       serverSetTimeout(connection, 1);
1687       int wasAlreadyClosed           = http->closed;
1688       httpCloseRead(http);
1689       dcheck(!ERR_peek_error());
1690       sslBlockSigPipe();
1691       int rc                         = SSL_shutdown(http->sslHndl);
1692       switch (rc) {
1693       case 1:
1694         sslFreeHndl(&http->sslHndl);
1695         break;
1696       case 0:
1697         if (!wasAlreadyClosed) {
1698           *events                   |= POLLIN;
1699         }
1700         break;
1701       case -1:
1702         switch (SSL_get_error(http->sslHndl, rc)) {
1703         case SSL_ERROR_WANT_READ:
1704           if (!wasAlreadyClosed) {
1705             *events                 |= POLLIN;
1706           }
1707           break;
1708         case SSL_ERROR_WANT_WRITE:
1709           *events                   |= POLLOUT;
1710           break;
1711         }
1712         break;
1713       }
1714       ERR_clear_error();
1715       dcheck(!ERR_peek_error());
1716       if (sslUnblockSigPipe()) {
1717         *events                      = 0;
1718         sslFreeHndl(&http->sslHndl);
1719       }
1720     } else if (!http->sslHndl && timedOut) {
1721       *events                        = 0;
1722       serverSetTimeout(connection, 0);
1723       httpCloseRead(http);
1724     }
1725     revents                          = POLLIN | POLLOUT;
1726   } while (bytes > 0 && *events & POLLIN && !http->closed);
1727   return (*events & (POLLIN|POLLOUT)) ||
1728          (!http->closed && http->isSuspended);
1729 }
1730
1731 void httpSetCallback(struct HttpConnection *http,
1732                      int (*callback)(struct HttpConnection *, void *,
1733                                      const char *, int), void *arg) {
1734   http->callback = callback;
1735   http->arg      = arg;
1736 }
1737
1738 void *httpGetPrivate(struct HttpConnection *http) {
1739   return http->private;
1740 }
1741
1742 void *httpSetPrivate(struct HttpConnection *http, void *private) {
1743   void *old     = http->private;
1744   http->private = private;
1745   return old;
1746 }
1747
1748 void httpSendReply(struct HttpConnection *http, int code,
1749                    const char *msg, const char *fmt, ...) {
1750   http->code     = code;
1751   char *body;
1752   char *title    = code != 200 ? stringPrintf(NULL, "%d %s", code, msg) : NULL;
1753   char *details  = NULL;
1754   if (fmt != NULL && strcmp(fmt, NO_MSG)) {
1755     va_list ap;
1756     va_start(ap, fmt);
1757     details      = vStringPrintf(NULL, fmt, ap);
1758     va_end(ap);
1759   }
1760   body           = stringPrintf(NULL,
1761      "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
1762      "<!DOCTYPE html PUBLIC "
1763                "\"-//W3C//DTD XHTML 1.0 Transitional//EN\" "
1764                "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
1765      "<html xmlns=\"http://www.w3.org/1999/xhtml\" "
1766      "xmlns:v=\"urn:schemas-microsoft-com:vml\" "
1767      "xml:lang=\"en\" lang=\"en\">\n"
1768      "<head>\n"
1769      "<title>%s</title>\n"
1770      "</head>\n"
1771      "<body>\n"
1772      "%s\n"
1773      "</body>\n"
1774      "</html>\n",
1775      title ? title : msg, fmt && strcmp(fmt, NO_MSG) ? details : msg);
1776   free(details);
1777   free(title);
1778   char *response = NULL;
1779   if (code) {
1780     response     = stringPrintf(NULL,
1781                                 "HTTP/1.1 %d %s\r\n"
1782                                 "%s"
1783                                 "Content-Type: text/html; charset=utf-8\r\n"
1784                                 "Content-Length: %ld\r\n"
1785                                 "\r\n",
1786                                 code, msg,
1787                                 code != 200 ? "Connection: close\r\n" : "",
1788                                 (long)strlen(body));
1789   }
1790   int isHead     = !strcmp(http->method, "HEAD");
1791   if (!isHead) {
1792     response     = stringPrintf(response, "%s", body);
1793   }
1794   free(body);
1795   httpTransfer(http, response, strlen(response));
1796   if (code != 200 || isHead) {
1797     httpCloseRead(http);
1798   }
1799 }
1800
1801 void httpSendWebSocketTextMsg(struct HttpConnection *http, int type,
1802                               const char *fmt, ...) {
1803   check(type >= 0 && type <= 0x7F);
1804   va_list ap;
1805   va_start(ap, fmt);
1806   char *buf;
1807   int len;
1808   if (strcmp(fmt, BINARY_MSG)) {
1809     // Send a printf() style text message
1810     buf              = vStringPrintf(NULL, fmt, ap);
1811     len              = strlen(buf);
1812   } else {
1813     // Send a binary message
1814     len              = va_arg(ap, int);
1815     buf              = va_arg(ap, char *);
1816   }
1817   va_end(ap);
1818   check(len >= 0 && len < 0x60000000);
1819
1820   // We assume that all input data is directly mapped in the range 0..255
1821   // (e.g. ISO-8859-1). In order to transparently send it over a web socket,
1822   // we have to encode it in UTF-8.
1823   int utf8Len        = len + 2;
1824   for (int i = 0; i < len; ++i) {
1825     if (buf[i] & 0x80) {
1826       ++utf8Len;
1827     }
1828   }
1829   char *utf8;
1830   check(utf8         = malloc(utf8Len));
1831   utf8[0]            = type;
1832   for (int i = 0, j = 1; i < len; ++i) {
1833     unsigned char ch = buf[i];
1834     if (ch & 0x80) {
1835       utf8[j++]      = 0xC0 + (ch >> 6);
1836       utf8[j++]      = 0x80 + (ch & 0x3F);
1837     } else {
1838       utf8[j++]      = ch;
1839     }
1840     check(j < utf8Len);
1841   }
1842   utf8[utf8Len-1]    = '\xFF';
1843
1844   // Free our temporary buffer, if we actually did allocate one.
1845   if (strcmp(fmt, BINARY_MSG)) {
1846     free(buf);
1847   }
1848
1849   // Send to browser.
1850   httpTransfer(http, utf8, utf8Len);
1851 }
1852
1853 void httpSendWebSocketBinaryMsg(struct HttpConnection *http, int type,
1854                                 const void *buf, int len) {
1855   check(type >= 0x80 && type <= 0xFF);
1856   check(len > 0 && len < 0x7FFFFFF0);
1857
1858   // Allocate buffer for header and payload.
1859   char *data;
1860   check(data  = malloc(len + 6));
1861   data[0]     = type;
1862
1863   // Convert length to base-128.
1864   int i       = 0;
1865   int l       = len;
1866   do {
1867     data[++i] = 0x80 + (l & 0x7F);
1868     l        /= 128;
1869   } while (l);
1870   data[i]    &= 0x7F;
1871
1872   // Reverse digits, so that they are big-endian.
1873   for (int j = 0; j < i/2; ++j) {
1874     char ch   = data[1+j];
1875     data[1+j] = data[i-j];
1876     data[i-j] = ch;
1877   }
1878
1879   // Transmit header and payload.
1880   memmove(data + i + 1, buf, len);
1881   httpTransfer(http, data, len + i + 1);
1882 }
1883
1884 void httpExitLoop(struct HttpConnection *http, int exitAll) {
1885   serverExitLoop(http->server, exitAll);
1886 }
1887
1888 struct Server *httpGetServer(const struct HttpConnection *http) {
1889   return http->server;
1890 }
1891
1892 struct ServerConnection *httpGetServerConnection(const struct HttpConnection *
1893                                                  http) {
1894   struct HttpConnection *httpW = (struct HttpConnection *)http;
1895   httpW->connection = serverGetConnection(http->server, http->connection,
1896                                           http->fd);
1897   return http->connection;
1898 }
1899
1900 int httpGetFd(const HttpConnection *http) {
1901   return http->fd;
1902 }
1903
1904 const char *httpGetPeerName(const struct HttpConnection *http) {
1905   return http->peerName;
1906 }
1907
1908 const char *httpGetMethod(const struct HttpConnection *http) {
1909   return http->method;
1910 }
1911
1912 const char *httpGetProtocol(const struct HttpConnection *http) {
1913   return http->sslHndl ? "https" : "http";
1914 }
1915
1916 const char *httpGetHost(const struct HttpConnection *http) {
1917   const char *host = getFromHashMap(&http->header, "host");
1918   if (!host || !*host) {
1919     host           = "localhost";
1920   }
1921   return host;
1922 }
1923
1924 int httpGetPort(const struct HttpConnection *http) {
1925   return http->port;
1926 }
1927
1928 const char *httpGetPath(const struct HttpConnection *http) {
1929   return http->matchedPath;
1930 }
1931
1932 const char *httpGetPathInfo(const struct HttpConnection *http) {
1933   return http->pathInfo ? http->pathInfo : "";
1934 }
1935
1936 const char *httpGetQuery(const struct HttpConnection *http) {
1937   return http->query ? http->query : "";
1938 }
1939
1940 const char *httpGetURL(const struct HttpConnection *http) {
1941   if (!http->url) {
1942     const char *host           = httpGetHost(http);
1943     int s_size                 = 8 + strlen(host) + 25 + strlen(http->path);
1944     check(*(char **)&http->url = malloc(s_size + 1));
1945     *http->url                 = '\000';
1946     strncat(http->url, http->sslHndl ? "https://" : "http://", s_size);
1947     strncat(http->url, host, s_size);
1948     if (http->port != (http->sslHndl ? 443 : 80)) {
1949       snprintf(strrchr(http->url, '\000'), 25, ":%d", http->port);
1950     }
1951     strncat(http->url, http->path, s_size);
1952   }
1953   return http->url;
1954 }
1955
1956 const char *httpGetVersion(const struct HttpConnection *http) {
1957   return http->version;
1958 }
1959
1960 const struct HashMap *httpGetHeaders(const struct HttpConnection *http) {
1961   return &http->header;
1962 }
This page took 1.949472 seconds and 5 git commands to generate.