36372d22da59190b4d25b501edacf81f988de718
[fms.git] / libs / shttpd / shttpd.c
1 /*
2  * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
3  * All rights reserved
4  *
5  * "THE BEER-WARE LICENSE" (Revision 42):
6  * Sergey Lyubka wrote this file.  As long as you retain this notice you
7  * can do whatever you want with this stuff. If we meet some day, and you think
8  * this stuff is worth it, you can buy me a beer in return.
9  */
10
11 /*
12  * Small and portable HTTP server, http://shttpd.sourceforge.net
13  * $Id: shttpd.c,v 1.10 2007/06/01 17:59:32 drozd Exp $
14  */
15
16 #include "defs.h"
17
18 time_t          current_time;   /* Current UTC time             */
19 int             tz_offset;      /* Time zone offset from UTC    */
20
21 static LL_HEAD(listeners);      /* List of listening sockets    */
22
23 const struct vec known_http_methods[] = {
24         {"GET",         3},
25         {"POST",        4},
26         {"PUT",         3},
27         {"DELETE",      6},
28         {"HEAD",        4},
29         {NULL,          0}
30 };
31
32 struct listener {
33         struct llhead   link;
34         struct shttpd_ctx *ctx;         /* Context that socket belongs  */
35         int             sock;           /* Listening socket             */
36         int             is_ssl;         /* Should be SSL-ed             */
37 };
38
39 /*
40  * This structure tells how HTTP headers must be parsed.
41  * Used by parse_headers() function.
42  */
43 #define OFFSET(x)       offsetof(struct headers, x)
44 static const struct http_header http_headers[] = {
45         {16, HDR_INT,    OFFSET(cl),            "Content-Length: "      },
46         {14, HDR_STRING, OFFSET(ct),            "Content-Type: "        },
47         {12, HDR_STRING, OFFSET(useragent),     "User-Agent: "          },
48         {19, HDR_DATE,   OFFSET(ims),           "If-Modified-Since: "   },
49         {15, HDR_STRING, OFFSET(auth),          "Authorization: "       },
50         {9,  HDR_STRING, OFFSET(referer),       "Referer: "             },
51         {8,  HDR_STRING, OFFSET(cookie),        "Cookie: "              },
52         {10, HDR_STRING, OFFSET(location),      "Location: "            },
53         {8,  HDR_INT,    OFFSET(status),        "Status: "              },
54         {7,  HDR_STRING, OFFSET(range),         "Range: "               },
55         {12, HDR_STRING, OFFSET(connection),    "Connection: "          },
56         {19, HDR_STRING, OFFSET(transenc),      "Transfer-Encoding: "   },
57         {0,  HDR_INT,    0,                     NULL                    }
58 };
59
60 struct shttpd_ctx *init_ctx(const char *config_file, int argc, char *argv[]);
61
62 int
63 url_decode(const char *src, int src_len, char *dst, int dst_len)
64 {
65         int     i, j, a, b;
66 #define HEXTOI(x)  (isdigit(x) ? x - '0' : x - 'W')
67
68         for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++)
69                 switch (src[i]) {
70                 case '%':
71                         if (isxdigit(((unsigned char *) src)[i + 1]) &&
72                             isxdigit(((unsigned char *) src)[i + 2])) {
73                                 a = tolower(((unsigned char *)src)[i + 1]);
74                                 b = tolower(((unsigned char *)src)[i + 2]);
75                                 dst[j] = (HEXTOI(a) << 4) | HEXTOI(b);
76                                 i += 2;
77                         } else {
78                                 dst[j] = '%';
79                         }
80                         break;
81                 case '+':
82                         dst[j] = ' ';
83                         break;
84                 default:
85                         dst[j] = src[i];
86                         break;
87                 }
88
89         dst[j] = '\0';  /* Null-terminate the destination */
90
91         return (j);
92 }
93
94 void
95 shttpd_add_mime_type(struct shttpd_ctx *ctx, const char *ext, const char *mime)
96 {
97         struct mime_type_link   *e;
98         const char              *error_msg = "shttpd_add_mime_type: no memory";
99
100         if ((e = malloc(sizeof(*e))) == NULL) {
101                 elog(E_FATAL, 0, error_msg);
102         } else if ((e->ext= my_strdup(ext)) == NULL) {
103                 elog(E_FATAL, 0, error_msg);
104         } else if ((e->mime = my_strdup(mime)) == NULL) {
105                 elog(E_FATAL, 0, error_msg);
106         } else {
107                 e->ext_len = strlen(ext);
108                 LL_TAIL(&ctx->mime_types, &e->link);
109         }
110 }
111
112
113 static const char *
114 is_alias(struct shttpd_ctx *ctx, const char *uri,
115                 struct vec *a_uri, struct vec *a_path)
116 {
117         const char      *p, *s = ctx->aliases;
118         size_t          len;
119
120         DBG(("is_alias: aliases [%s]", s == NULL ? "" : s));
121
122         FOR_EACH_WORD_IN_LIST(s, len) {
123                 if ((p = memchr(s, '=', len)) != NULL &&
124                     memcmp(uri, s, p - s) == 0) {
125                         a_uri->ptr = s;
126                         a_uri->len = p - s;
127                         a_path->ptr = ++p;
128                         a_path->len = (s + len) - p;
129                         return (s);
130                 }
131         }
132
133         return (NULL);
134 }
135
136 void
137 stop_stream(struct stream *stream)
138 {
139         if (stream->io_class != NULL && stream->io_class->close != NULL)
140                 stream->io_class->close(stream);
141
142         stream->io_class= NULL;
143         stream->flags |= FLAG_CLOSED;
144         stream->flags &= ~(FLAG_R | FLAG_W | FLAG_ALWAYS_READY);
145
146         DBG(("%d %s stopped. %lu of content data, %d now in a buffer",
147             stream->conn->rem.chan.sock, 
148             stream->io_class ? stream->io_class->name : "(null)",
149             (unsigned long) stream->io.total, io_data_len(&stream->io)));
150 }
151
152 /*
153  * Setup listening socket on given port, return socket
154  */
155 static int
156 open_listening_port(int port)
157 {
158         int             sock, on = 1;
159         struct usa      sa;
160
161 #ifdef _WIN32
162         {WSADATA data;  WSAStartup(MAKEWORD(2,2), &data);}
163 #endif /* _WIN32 */
164
165         sa.len                          = sizeof(sa.u.sin);
166         sa.u.sin.sin_family             = AF_INET;
167         sa.u.sin.sin_port               = htons((uint16_t) port);
168         sa.u.sin.sin_addr.s_addr        = htonl(INADDR_ANY);
169
170         if ((sock = socket(PF_INET, SOCK_STREAM, 6)) == -1)
171                 goto fail;
172         if (set_non_blocking_mode(sock) != 0)
173                 goto fail;
174         if (setsockopt(sock, SOL_SOCKET,
175             SO_REUSEADDR,(char *) &on, sizeof(on)) != 0)
176                 goto fail;
177         if (bind(sock, &sa.u.sa, sa.len) < 0)
178                 goto fail;
179         if (listen(sock, 128) != 0)
180                 goto fail;
181
182 #ifndef _WIN32
183         (void) fcntl(sock, F_SETFD, FD_CLOEXEC);
184 #endif /* !_WIN32 */
185
186         return (sock);
187 fail:
188         if (sock != -1)
189                 (void) closesocket(sock);
190         elog(E_LOG, NULL, "open_listening_port(%d): %s", port, strerror(errno));
191         return (-1);
192 }
193
194 /*
195  * Check whether full request is buffered Return headers length, or 0
196  */
197 int
198 get_headers_len(const char *buf, size_t buflen)
199 {
200         const char      *s, *e;
201         int             len = 0;
202
203         for (s = buf, e = s + buflen - 1; len == 0 && s < e; s++)
204                 /* Control characters are not allowed but >=128 is. */
205                 if (!isprint(*(unsigned char *)s) && *s != '\r' && *s != '\n' && *(unsigned char *)s < 128)
206                         len = -1;
207                 else if (s[0] == '\n' && s[1] == '\n')
208                         len = s - buf + 2;
209                 else if (s[0] == '\n' && &s[1] < e &&
210                     s[1] == '\r' && s[2] == '\n')
211                         len = s - buf + 3;
212
213         return (len);
214 }
215
216 /*
217  * Send error message back to a client.
218  */
219 void
220 send_server_error(struct conn *c, int status, const char *reason)
221 {
222 #ifdef EMBEDDED
223         struct llhead           *lp;
224         struct error_handler    *e;
225
226         LL_FOREACH(&c->ctx->error_handlers, lp) {
227                 e = LL_ENTRY(lp, struct error_handler, link);
228
229                 if (e->code == status) {
230                         if (c->loc.io_class != NULL &&
231                             c->loc.io_class->close != NULL)
232                                 c->loc.io_class->close(&c->loc);
233                         io_clear(&c->loc.io);
234                         setup_embedded_stream(c, e->callback, NULL);
235                         return;
236                 }
237         }
238 #endif /* EMBEDDED */
239
240         io_clear(&c->loc.io);
241         c->loc.headers_len = c->loc.io.head = my_snprintf(c->loc.io.buf,
242             c->loc.io.size, "HTTP/1.1 %d %s\r\n\r\n%d %s",
243             status, reason, status, reason);
244         c->status = status;
245         stop_stream(&c->loc);
246 }
247
248 /*
249  * Convert month to the month number. Return -1 on error, or month number
250  */
251 static int
252 montoi(const char *s)
253 {
254         static const char *ar[] = {
255                 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
256                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
257         };
258         size_t  i;
259
260         for (i = 0; i < sizeof(ar) / sizeof(ar[0]); i++)
261                 if (!strcmp(s, ar[i]))
262                         return (i);
263
264         return (-1);
265 }
266
267 /*
268  * Parse date-time string, and return the corresponding time_t value
269  */
270 static time_t
271 date_to_epoch(const char *s)
272 {
273         struct tm       tm, *tmp;
274         char            mon[32];
275         int             sec, min, hour, mday, month, year;
276
277         (void) memset(&tm, 0, sizeof(tm));
278         sec = min = hour = mday = month = year = 0;
279
280         if (((sscanf(s, "%d/%3s/%d %d:%d:%d",
281             &mday, mon, &year, &hour, &min, &sec) == 6) ||
282             (sscanf(s, "%d %3s %d %d:%d:%d",
283             &mday, mon, &year, &hour, &min, &sec) == 6) ||
284             (sscanf(s, "%*3s, %d %3s %d %d:%d:%d",
285             &mday, mon, &year, &hour, &min, &sec) == 6) ||
286             (sscanf(s, "%d-%3s-%d %d:%d:%d",
287             &mday, mon, &year, &hour, &min, &sec) == 6)) &&
288             (month = montoi(mon)) != -1) {
289                 tm.tm_mday      = mday;
290                 tm.tm_mon       = month;
291                 tm.tm_year      = year;
292                 tm.tm_hour      = hour;
293                 tm.tm_min       = min;
294                 tm.tm_sec       = sec;
295         }
296
297         if (tm.tm_year > 1900)
298                 tm.tm_year -= 1900;
299         else if (tm.tm_year < 70)
300                 tm.tm_year += 100;
301
302         /* Set Daylight Saving Time field */
303         tmp = localtime(&current_time);
304         tm.tm_isdst = tmp->tm_isdst;
305
306         return (mktime(&tm));
307 }
308
309 static void
310 remove_double_dots(char *s)
311 {
312         char    *p = s;
313
314         while (*s != '\0') {
315                 *p++ = *s++;
316                 if (s[-1] == '/')
317                         while (*s == '.' || *s == '/')
318                                 s++;
319         }
320         *p = '\0';
321 }
322
323 void
324 parse_headers(const char *s, int len, struct headers *parsed)
325 {
326         const struct http_header        *h;
327         union variant                   *v;
328         const char                      *p, *e = s + len;
329
330         DBG(("parsing headers (len %d): [%.*s]", len, len, s));
331
332         /* Loop through all headers in the request */
333         while (s < e) {
334
335                 /* Find where this header ends */
336                 for (p = s; p < e && *p != '\n'; ) p++;
337
338                 /* Is this header known to us ? */
339                 for (h = http_headers; h->len != 0; h++)
340                         if (e - s > h->len &&
341                             !my_strncasecmp(s, h->name, h->len))
342                                 break;
343
344                 /* If the header is known to us, store its value */
345                 if (h->len != 0) {
346
347                         /* Shift to where value starts */
348                         s += h->len;
349
350                         /* Find place to store the value */
351                         v = (union variant *) ((char *) parsed + h->offset);
352
353                         /* Fetch header value into the connection structure */
354                         if (h->type == HDR_STRING) {
355                                 v->v_vec.ptr = s;
356                                 v->v_vec.len = p - s;
357                                 if (p[-1] == '\r' && v->v_vec.len > 0)
358                                         v->v_vec.len--;
359                         } else if (h->type == HDR_INT) {
360                                 v->v_big_int = strtoul(s, NULL, 10);
361                         } else if (h->type == HDR_DATE) {
362                                 v->v_time = date_to_epoch(s);
363                         }
364                 }
365
366                 s = p + 1;      /* Shift to the next header */
367         }
368 }
369
370 /*
371  * For given directory path, substitute it to valid index file.
372  * Return 0 if index file has been found, -1 if not found
373  */
374 static int
375 find_index_file(struct conn *c, char *path, size_t maxpath, struct stat *stp)
376 {
377         char            buf[FILENAME_MAX];
378         const char      *s = c->ctx->index_files;
379         size_t          len;
380
381         FOR_EACH_WORD_IN_LIST(s, len) {
382                 my_snprintf(buf, sizeof(buf), "%s%c%.*s",path, DIRSEP, len, s);
383                 if (my_stat(buf, stp) == 0) {
384                         my_strlcpy(path, buf, maxpath);
385                         c->mime_type = get_mime_type(c->ctx, s, len);
386                         return (0);
387                 }
388         }
389
390         return (-1);
391 }
392
393 /*
394  * Try to open requested file, return 0 if OK, -1 if error.
395  * If the file is given arguments using PATH_INFO mechanism,
396  * initialize pathinfo pointer.
397  */
398 static int
399 get_path_info(struct conn *c, char *path, struct stat *stp)
400 {
401         char    *p, *e;
402
403         if (my_stat(path, stp) == 0)
404                 return (0);
405
406         p = path + strlen(path);
407         e = path + strlen(c->ctx->document_root) + 2;
408         
409         /* Strip directory parts of the path one by one */
410         for (; p > e; p--)
411                 if (*p == '/') {
412                         *p = '\0';
413                         if (!my_stat(path, stp) && !S_ISDIR(stp->st_mode)) {
414                                 c->path_info = p + 1;
415                                 return (0);
416                         } else {
417                                 *p = '/';
418                         }
419                 }
420
421         return (-1);
422 }
423
424
425 static void
426 decide_what_to_do(struct conn *c)
427 {
428         char            path[URI_MAX], buf[1024];
429         struct vec      alias_uri, alias_path;
430         struct stat     st;
431         int             rc;
432 #ifdef EMBEDDED
433         struct registered_uri   *ruri;
434 #endif /* EMBEDDED */
435
436         DBG(("decide_what_to_do: [%s]", c->uri));
437
438         if ((c->query = strchr(c->uri, '?')) != NULL)
439                 *c->query++ = '\0';
440
441         url_decode(c->uri, strlen(c->uri), c->uri, strlen(c->uri) + 1);
442         remove_double_dots(c->uri);
443         
444         if (strlen(c->uri) + strlen(c->ctx->document_root) >= sizeof(path)) {
445                 send_server_error(c, 400, "URI is too long");
446                 return;
447         }
448
449         (void) my_snprintf(path, sizeof(path), "%s%s",
450             c->ctx->document_root, c->uri);
451
452         /* User may use the aliases - check URI for mount point */
453         if (is_alias(c->ctx, c->uri, &alias_uri, &alias_path) != NULL) {
454                 (void) my_snprintf(path, sizeof(path), "%.*s%s",
455                     alias_path.len, alias_path.ptr, c->uri + alias_uri.len);
456                 DBG(("using alias %.*s -> %.*s", alias_uri.len, alias_uri.ptr,
457                     alias_path.len, alias_path.ptr));
458         }
459
460 #if !defined(NO_AUTH)
461         if (check_authorization(c, path) != 1) {
462                 send_authorization_request(c);
463         } else
464 #endif /* NO_AUTH */
465 #ifdef EMBEDDED
466         if ((ruri = is_registered_uri(c->ctx, c->uri)) != NULL) {
467                 setup_embedded_stream(c, ruri->callback, ruri->callback_data);
468         } else
469 #endif /* EMBEDDED */
470         if (strstr(path, HTPASSWD)) {
471                 /* Do not allow to view passwords files */
472                 send_server_error(c, 403, "Forbidden");
473         } else
474 #if !defined(NO_AUTH)
475         if ((c->method == METHOD_PUT || c->method == METHOD_DELETE) &&
476             (c->ctx->put_auth_file == NULL || !is_authorized_for_put(c))) {
477                 send_authorization_request(c);
478         } else
479 #endif /* NO_AUTH */
480         if (c->method == METHOD_PUT) {
481                 c->status = my_stat(path, &st) == 0 ? 200 : 201;
482
483                 if (c->ch.range.v_vec.len > 0) {
484                         send_server_error(c, 501, "PUT Range Not Implemented");
485                 } else if ((rc = put_dir(path)) == 0) {
486                         send_server_error(c, 200, "OK");
487                 } else if (rc == -1) {
488                         send_server_error(c, 500, "PUT Directory Error");
489                 } else if (c->rem.content_len == 0) {
490                         send_server_error(c, 411, "Length Required");
491                 } else if ((c->loc.chan.fd = my_open(path, O_WRONLY | O_BINARY |
492                     O_CREAT | O_NONBLOCK | O_TRUNC, 0644)) == -1) {
493                         send_server_error(c, 500, "PUT Error");
494                 } else {
495                         DBG(("PUT file [%s]", c->uri));
496                         c->loc.io_class = &io_file;
497                         c->loc.flags |= FLAG_W | FLAG_ALWAYS_READY ;
498                 }
499         } else if (c->method == METHOD_DELETE) {
500                 DBG(("DELETE [%s]", c->uri));
501                 if (my_remove(path) == 0)
502                         send_server_error(c, 200, "OK");
503                 else
504                         send_server_error(c, 500, "DELETE Error");
505         } else if (get_path_info(c, path, &st) != 0) {
506                 send_server_error(c, 404, "Not Found");
507         } else if (S_ISDIR(st.st_mode) && path[strlen(path) - 1] != '/') {
508                 (void) my_snprintf(buf, sizeof(buf),
509                         "Moved Permanently\r\nLocation: %s/", c->uri);
510                 send_server_error(c, 301, buf);
511         } else if (S_ISDIR(st.st_mode) &&
512             find_index_file(c, path, sizeof(path) - 1, &st) == -1 &&
513             c->ctx->dirlist == 0) {
514                 send_server_error(c, 403, "Directory Listing Denied");
515         } else if (S_ISDIR(st.st_mode) && c->ctx->dirlist) {
516                 if ((c->loc.chan.dir.path = my_strdup(path)) != NULL)
517                         get_dir(c);
518                 else
519                         send_server_error(c, 500, "GET Directory Error");
520         } else if (S_ISDIR(st.st_mode) && c->ctx->dirlist == 0) {
521                 send_server_error(c, 403, "Directory listing denied");
522 #if !defined(NO_CGI)
523         } else if (match_extension(path, c->ctx->cgi_extensions)) {
524                 if (c->method != METHOD_POST && c->method != METHOD_GET) {
525                         send_server_error(c, 501, "Bad method ");
526                 } else if ((run_cgi(c, path)) == -1) {
527                         send_server_error(c, 500, "Cannot exec CGI");
528                 } else {
529                         do_cgi(c);
530                 }
531 #endif /* NO_CGI */
532 #if !defined(NO_SSI)
533         } else if (match_extension(path, c->ctx->ssi_extensions)) {
534                 if ((c->loc.chan.fd = my_open(path,
535                     O_RDONLY | O_BINARY, 0644)) == -1) {
536                         send_server_error(c, 500, "SSI open error");
537                 } else {
538                         do_ssi(c);
539                 }
540 #endif /* NO_CGI */
541         } else if (c->ch.ims.v_time && st.st_mtime <= c->ch.ims.v_time) {
542                 send_server_error(c, 304, "Not Modified");
543         } else if ((c->loc.chan.fd = my_open(path,
544             O_RDONLY | O_BINARY, 0644)) != -1) {
545                 get_file(c, &st);
546         } else {
547                 send_server_error(c, 500, "Internal Error");
548         }
549 }
550
551 static int
552 set_request_method(struct conn *c)
553 {
554         const struct vec        *v;
555
556         assert(c->rem.io.head >= MIN_REQ_LEN);
557
558         /* Set the request method */
559         for (v = known_http_methods; v->ptr != NULL; v++)
560                 if (!memcmp(c->rem.io.buf, v->ptr, v->len)) {
561                         c->method = v - known_http_methods;
562                         break;
563                 }
564
565         return (v->ptr == NULL);
566 }
567
568 static void
569 parse_http_request(struct conn *c)
570 {
571         char    *s, *e, *p, *start;
572         char    *end_number;
573         int     uri_len, req_len;
574
575         s = c->rem.io.buf;
576         req_len = c->rem.headers_len = get_headers_len(s, c->rem.io.head);
577
578         if (req_len == 0 && io_space_len(&c->rem.io) == 0)
579                 send_server_error(c, 400, "Request is too big");
580
581         if (req_len == 0)
582                 return;
583         else if (req_len < MIN_REQ_LEN)
584                 send_server_error(c, 400, "Bad request");
585         else if (set_request_method(c))
586                 send_server_error(c, 501, "Method Not Implemented");
587         else if ((c->request = my_strndup(s, req_len)) == NULL)
588                 send_server_error(c, 500, "Cannot allocate request");
589
590         if (c->loc.flags & FLAG_CLOSED)
591                 return;
592
593         DBG(("Conn %d: parsing request: [%.*s]", c->rem.chan.sock, req_len, s));
594         c->rem.flags |= FLAG_HEADERS_PARSED;
595
596         /* Set headers pointer. Headers follow the request line */
597         c->headers = memchr(c->request, '\n', req_len);
598         assert(c->headers != NULL);
599         assert(c->headers < c->request + req_len);
600         if (c->headers > c->request && c->headers[-1] == '\r')
601                 c->headers[-1] = '\0';
602         *c->headers++ = '\0';
603
604         /*
605          * Now make a copy of the URI, because it will be URL-decoded,
606          * and we need a copy of unmodified URI for the access log.
607          * First, we skip the REQUEST_METHOD and shift to the URI.
608          */
609         for (p = c->request, e = p + req_len; *p != ' ' && p < e; p++);
610         while (p < e && *p == ' ') p++;
611
612         /* Now remember where URI starts, and shift to the end of URI */
613         for (start = p; p < e && !isspace((unsigned char)*p); ) p++;
614         uri_len = p - start;
615         /* Skip space following the URI */
616         while (p < e && *p == ' ') p++;
617
618         /* Now comes the HTTP-Version in the form HTTP/<major>.<minor> */
619         if (strncmp(p, "HTTP/", 5) != 0) {
620                 send_server_error(c, 400, "Bad HTTP version");
621                 return;
622         }
623         p += 5;
624         /* Parse the HTTP major version number */
625         c->major_version = strtoul(p, &end_number, 10);
626         if (end_number == p || *end_number != '.') {
627                 send_server_error(c, 400, "Bad HTTP major version");
628                 return;
629         }
630         p = end_number + 1;
631         /* Parse the minor version number */
632         c->minor_version = strtoul(p, &end_number, 10);
633         if (end_number == p || *end_number != '\0') {
634                 send_server_error(c, 400, "Bad HTTP minor version");
635                 return;
636         }
637         /* Version must be <=1.1 */
638         if (c->major_version > 1 ||
639             (c->major_version == 1 && c->minor_version > 1)) {
640                 send_server_error(c, 505, "HTTP version not supported");
641                 return;
642         }
643
644         if (uri_len <= 0) {
645                 send_server_error(c, 400, "Bad URI");
646         } else if ((c->uri = malloc(uri_len + 1)) == NULL) {
647                 send_server_error(c, 500, "Cannot allocate URI");
648         } else {
649                 my_strlcpy(c->uri, (char *) start, uri_len + 1);
650                 parse_headers(c->headers,
651                     (c->request + req_len) - c->headers, &c->ch);
652
653                 /* Remove the length of request from total, count only data */
654                 assert(c->rem.io.total >= (big_int_t) req_len);
655                 c->rem.io.total -= req_len;
656
657                 c->rem.content_len = c->ch.cl.v_big_int;
658                 io_inc_tail(&c->rem.io, req_len);
659
660                 decide_what_to_do(c);
661         }
662 }
663
664 void
665 shttpd_add_socket(struct shttpd_ctx *ctx, int sock)
666 {
667         struct conn     *c;
668         struct usa      sa;
669         int             l = ctx->inetd_mode ? E_FATAL : E_LOG;
670 #if !defined(NO_SSL)
671         SSL             *ssl = NULL;
672 #endif /* NO_SSL */
673
674         sa.len = sizeof(sa.u.sin);
675         (void) set_non_blocking_mode(sock);
676
677         if (getpeername(sock, &sa.u.sa, &sa.len)) {
678                 elog(l, NULL, "add_socket: %s", strerror(errno));
679 #if !defined(NO_SSL)
680         } else if (ctx->ssl_ctx && (ssl = SSL_new(ctx->ssl_ctx)) == NULL) {
681                 elog(l, NULL, "add_socket: SSL_new: %s", strerror(ERRNO));
682                 (void) closesocket(sock);
683         } else if (ctx->ssl_ctx && SSL_set_fd(ssl, sock) == 0) {
684                 elog(l, NULL, "add_socket: SSL_set_fd: %s", strerror(ERRNO));
685                 (void) closesocket(sock);
686                 SSL_free(ssl);
687 #endif /* NO_SSL */
688         } else if ((c = calloc(1, sizeof(*c) + 2 * ctx->io_buf_size)) == NULL) {
689
690 #if !defined(NO_SSL)
691                 if (ssl)
692                         SSL_free(ssl);
693 #endif /* NO_SSL */
694                 (void) closesocket(sock);
695                 elog(l, NULL, "add_socket: calloc: %s", strerror(ERRNO));
696         } else {
697                 ctx->nrequests++;
698                 c->rem.conn = c->loc.conn = c;
699                 c->ctx          = ctx;
700                 c->sa           = sa;
701                 c->birth_time   = current_time;
702                 c->expire_time  = current_time + EXPIRE_TIME;
703
704                 (void) getsockname(sock, &sa.u.sa, &sa.len);
705                 c->loc_port = sa.u.sin.sin_port;
706
707                 set_close_on_exec(sock);
708
709                 c->loc.io_class = NULL;
710         
711                 c->rem.io_class = &io_socket;
712                 c->rem.chan.sock = sock;
713
714                 /* Set IO buffers */
715                 c->loc.io.buf   = (char *) (c + 1);
716                 c->rem.io.buf   = c->loc.io.buf + ctx->io_buf_size;
717                 c->loc.io.size  = c->rem.io.size = ctx->io_buf_size;
718
719 #if !defined(NO_SSL)
720                 if (ssl) {
721                         c->rem.io_class = &io_ssl;
722                         c->rem.chan.ssl.sock = sock;
723                         c->rem.chan.ssl.ssl = ssl;
724                         ssl_handshake(&c->rem);
725                 }
726 #endif /* NO_SSL */
727
728                 EnterCriticalSection(&ctx->mutex);
729                 LL_TAIL(&ctx->connections, &c->link);
730                 ctx->nactive++;
731                 LeaveCriticalSection(&ctx->mutex);
732                 
733                 DBG(("%s:%hu connected (socket %d)",
734                     inet_ntoa(* (struct in_addr *) &sa.u.sin.sin_addr.s_addr),
735                     ntohs(sa.u.sin.sin_port), sock));
736         }
737 }
738
739 int
740 shttpd_active(struct shttpd_ctx *ctx)
741 {
742         return (ctx->nactive);
743 }
744
745 /*
746  * Setup a listening socket on given port. Return opened socket or -1
747  */
748 int
749 shttpd_listen(struct shttpd_ctx *ctx, int port, int is_ssl)
750 {
751         struct listener *l;
752         int             sock;
753
754         if ((sock = open_listening_port(port)) == -1) {
755                 elog(E_FATAL, NULL, "cannot open port %d", port);
756         } else if ((l = calloc(1, sizeof(*l))) == NULL) {
757                 (void) closesocket(sock);
758                 elog(E_FATAL, NULL, "cannot allocate listener");
759         } else if (is_ssl && ctx->ssl_ctx == NULL) {
760                 (void) closesocket(sock);
761                 elog(E_FATAL, NULL, "cannot add SSL socket, "
762                     "please specify certificate file");
763         } else {
764                 l->is_ssl = is_ssl;
765                 l->sock = sock;
766                 l->ctx  = ctx;
767                 LL_TAIL(&listeners, &l->link);
768                 DBG(("shttpd_listen: added socket %d", sock));
769         }
770
771         return (sock);
772 }
773
774 int
775 shttpd_accept(int lsn_sock, int milliseconds)
776 {
777         struct timeval  tv;
778         struct usa      sa;
779         fd_set          read_set;
780         int             sock = -1;
781         
782         tv.tv_sec       = milliseconds / 1000;
783         tv.tv_usec      = milliseconds % 1000;
784         sa.len          = sizeof(sa.u.sin);
785         FD_ZERO(&read_set);
786         FD_SET(lsn_sock, &read_set);
787         
788         if (select(lsn_sock + 1, &read_set, NULL, NULL, &tv) == 1)
789                 sock = accept(lsn_sock, &sa.u.sa, &sa.len);
790
791         return (sock);
792 }
793
794 static void
795 read_stream(struct stream *stream)
796 {
797         int     n, len;
798
799         len = io_space_len(&stream->io);
800         assert(len > 0);
801
802         /* Do not read more that needed */
803         if (stream->content_len > 0 &&
804             stream->io.total + len > stream->content_len)
805                 len = stream->content_len - stream->io.total;
806
807         /* Read from underlying channel */
808         n = stream->nread_last = stream->io_class->read(stream,
809             io_space(&stream->io), len);
810
811         if (n > 0)
812                 io_inc_head(&stream->io, n);
813         else if (n == -1 && (ERRNO == EINTR || ERRNO == EWOULDBLOCK))
814                 n = n;  /* Ignore EINTR and EAGAIN */
815         else if (!(stream->flags & FLAG_DONT_CLOSE))
816                 stop_stream(stream);
817
818         DBG(("read_stream (%d %s): read %d/%d/%lu bytes (errno %d)",
819             stream->conn->rem.chan.sock,
820             stream->io_class ? stream->io_class->name : "(null)",
821             n, len, (unsigned long) stream->io.total, ERRNO));
822
823         /*
824          * Close the local stream if everything was read
825          * XXX We do not close the remote stream though! It may be
826          * a POST data completed transfer, we do not want the socket
827          * to be closed.
828          */
829         if (stream->content_len > 0 && stream == &stream->conn->loc) {
830                 assert(stream->io.total <= stream->content_len);
831                 if (stream->io.total == stream->content_len)
832                         stop_stream(stream);
833         }
834
835         stream->conn->expire_time = current_time + EXPIRE_TIME;
836 }
837
838 static void
839 write_stream(struct stream *from, struct stream *to)
840 {
841         int     n, len;
842
843         len = io_data_len(&from->io);
844         assert(len > 0);
845
846         /* TODO: should be assert on CAN_WRITE flag */
847         n = to->io_class->write(to, io_data(&from->io), len);
848         to->conn->expire_time = current_time + EXPIRE_TIME;
849         DBG(("write_stream (%d %s): written %d/%d bytes (errno %d)",
850             to->conn->rem.chan.sock,
851             to->io_class ? to->io_class->name : "(null)", n, len, ERRNO));
852
853         if (n > 0)
854                 io_inc_tail(&from->io, n);
855         else if (n == -1 && (ERRNO == EINTR || ERRNO == EWOULDBLOCK))
856                 n = n;  /* Ignore EINTR and EAGAIN */
857         else if (!(to->flags & FLAG_DONT_CLOSE))
858                 stop_stream(to);
859 }
860
861
862 static void
863 disconnect(struct conn *c)
864 {
865         static const struct vec ka = {"keep-alive", 10};
866         int                     dont_close;
867
868         DBG(("Disconnecting %d (%.*s)", c->rem.chan.sock,
869             c->ch.connection.v_vec.len, c->ch.connection.v_vec.ptr));
870
871 #if !defined(_WIN32) || defined(NO_GUI)
872         if (c->ctx->access_log != NULL)
873 #endif /* _WIN32 */
874                         log_access(c->ctx->access_log, c);
875
876         /* In inetd mode, exit if request is finished. */
877         if (c->ctx->inetd_mode)
878                 exit(0);
879
880         if (c->loc.io_class != NULL && c->loc.io_class->close != NULL)
881                 c->loc.io_class->close(&c->loc);
882
883         /*
884          * Check the "Connection: " header before we free c->request
885          * If it its 'keep-alive', then do not close the connection
886          */
887         dont_close =  c->ch.connection.v_vec.len >= ka.len &&
888             !my_strncasecmp(ka.ptr, c->ch.connection.v_vec.ptr, ka.len);
889
890         if (c->request)
891                 free(c->request);
892         if (c->uri)
893                 free(c->uri);
894
895         /* Handle Keep-Alive */
896         dont_close = 0;
897         if (dont_close) {
898                 c->loc.io_class = NULL;
899                 c->loc.flags = c->rem.flags = 0;
900                 c->query = c->request = c->uri = c->path_info = NULL;
901                 c->mime_type = NULL;
902                 (void) memset(&c->ch, 0, sizeof(c->ch));
903                 io_clear(&c->rem.io);
904                 io_clear(&c->loc.io);
905                 c->rem.io.total = c->loc.io.total = 0;
906         } else {
907                 if (c->rem.io_class != NULL)
908                         c->rem.io_class->close(&c->rem);
909
910                 EnterCriticalSection(&c->ctx->mutex);
911                 LL_DEL(&c->link);
912                 c->ctx->nactive--;
913                 assert(c->ctx->nactive >= 0);
914                 LeaveCriticalSection(&c->ctx->mutex);
915
916                 free(c);
917         }
918 }
919
920 static void
921 add_to_set(int fd, fd_set *set, int *max_fd)
922 {
923         FD_SET(fd, set);
924         if (fd > *max_fd)
925                 *max_fd = fd;
926 }
927
928 /*
929  * One iteration of server loop. This is the core of the data exchange.
930  */
931 void
932 shttpd_poll(struct shttpd_ctx *ctx, int milliseconds)
933 {
934         struct llhead   *lp, *tmp;
935         struct listener *l;
936         struct conn     *c;
937         struct timeval  tv;                     /* Timeout for select() */
938         fd_set          read_set, write_set;
939         int             sock, max_fd = -1, msec = milliseconds;
940         struct usa      sa;
941
942         current_time = time(0);
943         FD_ZERO(&read_set);
944         FD_ZERO(&write_set);
945
946         /* Add listening sockets to the read set */
947         LL_FOREACH(&listeners, lp) {
948                 l = LL_ENTRY(lp, struct listener, link);
949                 FD_SET(l->sock, &read_set);
950                 if (l->sock > max_fd)
951                         max_fd = l->sock;
952                 DBG(("FD_SET(%d) (listening)", l->sock));
953         }
954
955         /* Multiplex streams */
956         LL_FOREACH(&ctx->connections, lp) {
957                 c = LL_ENTRY(lp, struct conn, link);
958                 
959                 /* If there is a space in remote IO, check remote socket */
960                 if (io_space_len(&c->rem.io))
961                         add_to_set(c->rem.chan.fd, &read_set, &max_fd);
962
963 #if !defined(NO_CGI)
964                 /*
965                  * If there is a space in local IO, and local endpoint is
966                  * CGI, check local socket for read availability
967                  */
968                 if (io_space_len(&c->loc.io) && (c->loc.flags & FLAG_R) &&
969                     c->loc.io_class == &io_cgi)
970                         add_to_set(c->loc.chan.fd, &read_set, &max_fd);
971
972                 /*
973                  * If there is some data read from remote socket, and
974                  * local endpoint is CGI, check local for write availability
975                  */
976                 if (io_data_len(&c->rem.io) && (c->loc.flags & FLAG_W) &&
977                     c->loc.io_class == &io_cgi)
978                         add_to_set(c->loc.chan.fd, &write_set, &max_fd);
979 #endif /* NO_CGI */
980
981                 /*
982                  * If there is some data read from local endpoint, check the
983                  * remote socket for write availability
984                  */
985                 if (io_data_len(&c->loc.io))
986                         add_to_set(c->rem.chan.fd, &write_set, &max_fd);
987
988                 if (io_space_len(&c->loc.io) && (c->loc.flags & FLAG_R) &&
989                     (c->loc.flags & FLAG_ALWAYS_READY))
990                         msec = 0;
991                 
992                 if (io_data_len(&c->rem.io) && (c->loc.flags & FLAG_W) &&
993                     (c->loc.flags & FLAG_ALWAYS_READY))
994                         msec = 0;
995         }
996
997         tv.tv_sec = msec / 1000;
998         tv.tv_usec = msec % 1000;
999
1000         /* Check IO readiness */
1001         if (select(max_fd + 1, &read_set, &write_set, NULL, &tv) < 0) {
1002 #ifdef _WIN32
1003                 /*
1004                  * On windows, if read_set and write_set are empty,
1005                  * select() returns "Invalid parameter" error
1006                  * (at least on my Windows XP Pro). So in this case,
1007                  * we sleep here.
1008                  */
1009                 Sleep(milliseconds);
1010 #endif /* _WIN32 */
1011                 DBG(("select: %d", ERRNO));
1012                 return;
1013         }
1014
1015         /* Check for incoming connections on listener sockets */
1016         LL_FOREACH(&listeners, lp) {
1017                 l = LL_ENTRY(lp, struct listener, link);
1018                 if (!FD_ISSET(l->sock, &read_set))
1019                         continue;
1020                 do {
1021                         sa.len = sizeof(sa.u.sin);
1022                         if ((sock = accept(l->sock, &sa.u.sa, &sa.len)) != -1) {
1023 #if defined(_WIN32)
1024                                 shttpd_add_socket(ctx, sock);
1025 #else
1026                                 if (sock < (int) FD_SETSIZE) {
1027                                         shttpd_add_socket(ctx, sock);
1028                                 } else {
1029                                         elog(E_LOG, NULL,
1030                                            "shttpd_poll: ctx %p: disarding "
1031                                            "socket %d, too busy", ctx, sock);
1032                                         (void) closesocket(sock);
1033                                 }
1034 #endif /* _WIN32 */
1035                         }
1036                 } while (sock != -1);
1037         }
1038
1039         /* Process all connections */
1040         LL_FOREACH_SAFE(&ctx->connections, lp, tmp) {
1041                 c = LL_ENTRY(lp, struct conn, link);
1042
1043                 /* Read from remote end if it is ready */
1044                 if (FD_ISSET(c->rem.chan.fd, &read_set) &&
1045                     io_space_len(&c->rem.io))
1046                         read_stream(&c->rem);
1047
1048                 /* If the request is not parsed yet, do so */
1049                 if (!(c->rem.flags & FLAG_HEADERS_PARSED))
1050                         parse_http_request(c);
1051
1052                 DBG(("loc: %u [%.*s]", io_data_len(&c->loc.io),
1053                     io_data_len(&c->loc.io), io_data(&c->loc.io)));
1054                 DBG(("rem: %u [%.*s]", io_data_len(&c->rem.io),
1055                     io_data_len(&c->rem.io), io_data(&c->rem.io)));
1056
1057                 /* Read from the local end if it is ready */
1058                 if (io_space_len(&c->loc.io) &&
1059                     ((c->loc.flags & FLAG_ALWAYS_READY)
1060                     
1061 #if !defined(NO_CGI)
1062                     ||(c->loc.io_class == &io_cgi &&
1063                      FD_ISSET(c->loc.chan.fd, &read_set))
1064 #endif /* NO_CGI */
1065                     ))
1066                         read_stream(&c->loc);
1067
1068                 if (io_data_len(&c->rem.io) > 0 && (c->loc.flags & FLAG_W) &&
1069                     c->loc.io_class != NULL && c->loc.io_class->write != NULL)
1070                         write_stream(&c->rem, &c->loc);
1071
1072                 if (io_data_len(&c->loc.io) > 0 && c->rem.io_class != NULL)
1073                         write_stream(&c->loc, &c->rem); 
1074
1075                 if (c->rem.nread_last > 0)
1076                         c->ctx->in += c->rem.nread_last;
1077                 if (c->loc.nread_last > 0)
1078                         c->ctx->out += c->loc.nread_last;
1079
1080                 /* Check whether we should close this connection */
1081                 if ((current_time > c->expire_time) ||
1082                     (c->rem.flags & FLAG_CLOSED) ||
1083                     ((c->loc.flags & FLAG_CLOSED) && !io_data_len(&c->loc.io)))
1084                         disconnect(c);
1085         }
1086 }
1087
1088 /*
1089  * Deallocate shttpd object, free up the resources
1090  */
1091 void
1092 shttpd_fini(struct shttpd_ctx *ctx)
1093 {
1094         struct llhead           *lp, *tmp;
1095         struct mime_type_link   *mtl;
1096         struct conn             *c;
1097         struct listener         *l;
1098         struct registered_uri   *ruri;
1099
1100         /* Free configured mime types */
1101         LL_FOREACH_SAFE(&ctx->mime_types, lp, tmp) {
1102                 mtl = LL_ENTRY(lp, struct mime_type_link, link);
1103                 free(mtl->mime);
1104                 free(mtl->ext);
1105                 free(mtl);
1106         }
1107
1108         /* Free all connections */
1109         LL_FOREACH_SAFE(&ctx->connections, lp, tmp) {
1110                 c = LL_ENTRY(lp, struct conn, link);
1111                 disconnect(c);
1112         }
1113
1114         /* Free registered URIs (must be done after disconnect()) */
1115         LL_FOREACH_SAFE(&ctx->registered_uris, lp, tmp) {
1116                 ruri = LL_ENTRY(lp, struct registered_uri, link);
1117                 free((void *)ruri->uri);
1118                 free(ruri);
1119         }
1120
1121         /* Free listener sockets for this context */
1122         LL_FOREACH_SAFE(&listeners, lp, tmp) {
1123                 l = LL_ENTRY(lp, struct listener, link);
1124                 (void) closesocket(l->sock);
1125                 LL_DEL(&l->link);
1126                 free(l);
1127         }
1128
1129 #if !defined(NO_SSI)
1130         free_ssi_funcs(ctx);
1131 #endif /* NO_SSI */
1132
1133         if (ctx->access_log)            (void) fclose(ctx->access_log);
1134         if (ctx->error_log)             (void) fclose(ctx->error_log);
1135         if (ctx->put_auth_file)         free(ctx->put_auth_file);
1136         if (ctx->document_root)         free(ctx->document_root);
1137         if (ctx->index_files)           free(ctx->index_files);
1138         if (ctx->aliases)               free(ctx->aliases);
1139 #if !defined(NO_CGI)
1140         if (ctx->cgi_vars)              free(ctx->cgi_vars);
1141         if (ctx->cgi_extensions)        free(ctx->cgi_extensions);
1142         if (ctx->cgi_interpreter)       free(ctx->cgi_interpreter);
1143 #endif /* NO_CGI */
1144         if (ctx->auth_realm)            free(ctx->auth_realm);
1145         if (ctx->global_passwd_file)    free(ctx->global_passwd_file);
1146         if (ctx->uid)                   free(ctx->uid);
1147
1148         /* TODO: free SSL context */
1149
1150         free(ctx);
1151 }
1152
1153 void
1154 open_listening_ports(struct shttpd_ctx *ctx)
1155 {
1156         const char      *p = ctx->ports;
1157         int             len, is_ssl;
1158         
1159         FOR_EACH_WORD_IN_LIST(p, len) {
1160                 is_ssl = p[len - 1] == 's' ? 1 : 0;
1161                 if (shttpd_listen(ctx, atoi(p), is_ssl) == -1)
1162                         elog(E_FATAL, NULL,
1163                             "Cannot open socket on port %d", atoi(p));
1164         }
1165 }