context deprecation
[platform/upstream/libwebsockets.git] / lib / server.c
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation:
9  *  version 2.1 of the License.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *  MA  02110-1301  USA
20  */
21
22
23 #include "private-libwebsockets.h"
24
25 #if defined (LWS_WITH_ESP8266)
26 #undef memcpy
27 void *memcpy(void *dest, const void *src, size_t n)
28 {
29         return ets_memcpy(dest, src, n);
30 }
31 #endif
32
33 int
34 lws_context_init_server(struct lws_context_creation_info *info,
35                         struct lws_vhost *vhost)
36 {
37 #if LWS_POSIX
38         int n, opt = 1, limit = 1;
39 #endif
40         lws_sockfd_type sockfd;
41         struct lws_vhost *vh;
42         struct lws *wsi;
43         int m = 0;
44
45         /* set up our external listening socket we serve on */
46
47         if (info->port == CONTEXT_PORT_NO_LISTEN)
48                 return 0;
49
50         vh = vhost->context->vhost_list;
51         while (vh) {
52                 if (vh->listen_port == info->port) {
53                         if ((!info->iface && !vh->iface) ||
54                             (info->iface && vh->iface &&
55                             !strcmp(info->iface, vh->iface))) {
56                                 vhost->listen_port = info->port;
57                                 vhost->iface = info->iface;
58                                 lwsl_notice(" using listen skt from vhost %s\n",
59                                             vh->name);
60                                 return 0;
61                         }
62                 }
63                 vh = vh->vhost_next;
64         }
65
66 #if LWS_POSIX
67 #if defined(__linux__)
68         limit = vhost->context->count_threads;
69 #endif
70
71         for (m = 0; m < limit; m++) {
72 #ifdef LWS_USE_UNIX_SOCK
73         if (LWS_UNIX_SOCK_ENABLED(vhost))
74                 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
75         else
76 #endif
77 #ifdef LWS_USE_IPV6
78         if (LWS_IPV6_ENABLED(vhost))
79                 sockfd = socket(AF_INET6, SOCK_STREAM, 0);
80         else
81 #endif
82                 sockfd = socket(AF_INET, SOCK_STREAM, 0);
83
84         if (sockfd == -1) {
85 #else
86 #if defined(LWS_WITH_ESP8266)
87         sockfd = esp8266_create_tcp_listen_socket(vhost);
88         if (!lws_sockfd_valid(sockfd)) {
89
90 #else
91         sockfd = mbed3_create_tcp_stream_socket();
92         if (!lws_sockfd_valid(sockfd)) {
93 #endif
94 #endif
95                 lwsl_err("ERROR opening socket\n");
96                 return 1;
97         }
98
99 #if LWS_POSIX
100         /*
101          * allow us to restart even if old sockets in TIME_WAIT
102          */
103         if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
104                        (const void *)&opt, sizeof(opt)) < 0) {
105                 compatible_close(sockfd);
106                 return 1;
107         }
108
109 #if defined(LWS_USE_IPV6) && defined(IPV6_V6ONLY)
110         if (LWS_IPV6_ENABLED(vhost)) {
111                 if (vhost->options & LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY) {
112                         int value = (vhost->options & LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE) ? 1 : 0;
113                         if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
114                                         (const void*)&value, sizeof(value)) < 0) {
115                                 compatible_close(sockfd);
116                                 return 1;
117                         }
118                 }
119         }
120 #endif
121
122 #if defined(__linux__) && defined(SO_REUSEPORT) && LWS_MAX_SMP > 1
123         if (vhost->context->count_threads > 1)
124                 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT,
125                                 (const void *)&opt, sizeof(opt)) < 0) {
126                         compatible_close(sockfd);
127                         return 1;
128                 }
129 #endif
130 #endif
131         lws_plat_set_socket_options(vhost, sockfd);
132
133 #if LWS_POSIX
134         n = lws_socket_bind(vhost, sockfd, info->port, info->iface);
135         if (n < 0)
136                 goto bail;
137         info->port = n;
138 #endif
139         vhost->listen_port = info->port;
140         vhost->iface = info->iface;
141
142         wsi = lws_zalloc(sizeof(struct lws));
143         if (wsi == NULL) {
144                 lwsl_err("Out of mem\n");
145                 goto bail;
146         }
147         wsi->context = vhost->context;
148         wsi->sock = sockfd;
149         wsi->mode = LWSCM_SERVER_LISTENER;
150         wsi->protocol = vhost->protocols;
151         wsi->tsi = m;
152         wsi->vhost = vhost;
153         wsi->listener = 1;
154
155 #ifdef LWS_USE_LIBUV
156         if (LWS_LIBUV_ENABLED(vhost->context))
157                 lws_uv_initvhost(vhost, wsi);
158 #endif
159
160         if (insert_wsi_socket_into_fds(vhost->context, wsi))
161                 goto bail;
162
163         vhost->context->count_wsi_allocated++;
164         vhost->lserv_wsi = wsi;
165
166 #if LWS_POSIX
167         listen(wsi->sock, LWS_SOMAXCONN);
168         } /* for each thread able to independently listen */
169 #else
170 #if defined(LWS_WITH_ESP8266)
171         esp8266_tcp_stream_bind(wsi->sock, info->port, wsi);
172 #else
173         mbed3_tcp_stream_bind(wsi->sock, info->port, wsi);
174 #endif
175 #endif
176         if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) {
177 #ifdef LWS_USE_UNIX_SOCK
178                 if (LWS_UNIX_SOCK_ENABLED(vhost))
179                         lwsl_notice(" Listening on \"%s\"\n", info->iface);
180                 else
181 #endif
182                         lwsl_notice(" Listening on port %d\n", info->port);
183         }
184
185         return 0;
186
187 bail:
188         compatible_close(sockfd);
189
190         return 1;
191 }
192
193 #if defined(LWS_WITH_ESP8266)
194 #undef strchr
195 #define strchr ets_strchr
196 #endif
197
198 struct lws_vhost *
199 lws_select_vhost(struct lws_context *context, int port, const char *servername)
200 {
201         struct lws_vhost *vhost = context->vhost_list;
202         const char *p;
203         int n, m, colon;
204
205         n = strlen(servername);
206         colon = n;
207         p = strchr(servername, ':');
208         if (p)
209                 colon = p - servername;
210
211         /* first try exact matches */
212
213         while (vhost) {
214                 if (port == vhost->listen_port &&
215                     !strncmp(vhost->name, servername, colon)) {
216                         lwsl_info("SNI: Found: %s\n", servername);
217                         return vhost;
218                 }
219                 vhost = vhost->vhost_next;
220         }
221
222         /*
223          * if no exact matches, try matching *.vhost-name
224          * unintentional matches are possible but resolve to x.com for *.x.com
225          * which is reasonable.  If exact match exists we already chose it and
226          * never reach here.  SSL will still fail it if the cert doesn't allow
227          * *.x.com.
228          */
229
230         vhost = context->vhost_list;
231         while (vhost) {
232                 m = strlen(vhost->name);
233                 if (port == vhost->listen_port &&
234                     m <= (colon - 2) &&
235                     servername[colon - m - 1] == '.' &&
236                     !strncmp(vhost->name, servername + colon - m, m)) {
237                         lwsl_info("SNI: Found %s on wildcard: %s\n",
238                                     servername, vhost->name);
239                         return vhost;
240                 }
241                 vhost = vhost->vhost_next;
242         }
243
244         return NULL;
245 }
246
247 LWS_VISIBLE LWS_EXTERN const struct lws_protocols *
248 lws_vhost_name_to_protocol(struct lws_vhost *vh, const char *name)
249 {
250         int n;
251
252         for (n = 0; n < vh->count_protocols; n++)
253                 if (!strcmp(name, vh->protocols[n].name))
254                         return &vh->protocols[n];
255
256         return NULL;
257 }
258
259 LWS_VISIBLE LWS_EXTERN const char *
260 lws_get_mimetype(const char *file, const struct lws_http_mount *m)
261 {
262         int n = strlen(file);
263         const struct lws_protocol_vhost_options *pvo = NULL;
264
265         if (m)
266                 pvo = m->extra_mimetypes;
267
268         if (n < 5)
269                 return NULL;
270
271         if (!strcmp(&file[n - 4], ".ico"))
272                 return "image/x-icon";
273
274         if (!strcmp(&file[n - 4], ".gif"))
275                 return "image/gif";
276
277         if (!strcmp(&file[n - 3], ".js"))
278                 return "text/javascript";
279
280         if (!strcmp(&file[n - 4], ".png"))
281                 return "image/png";
282
283         if (!strcmp(&file[n - 4], ".jpg"))
284                 return "image/jpeg";
285
286         if (!strcmp(&file[n - 3], ".gz"))
287                 return "application/gzip";
288
289         if (!strcmp(&file[n - 4], ".JPG"))
290                 return "image/jpeg";
291
292         if (!strcmp(&file[n - 5], ".html"))
293                 return "text/html";
294
295         if (!strcmp(&file[n - 4], ".css"))
296                 return "text/css";
297
298         if (!strcmp(&file[n - 4], ".txt"))
299                 return "text/plain";
300
301         if (!strcmp(&file[n - 4], ".svg"))
302                 return "image/svg+xml";
303
304         if (!strcmp(&file[n - 4], ".ttf"))
305                 return "application/x-font-ttf";
306
307         if (!strcmp(&file[n - 5], ".woff"))
308                 return "application/font-woff";
309
310         if (!strcmp(&file[n - 4], ".xml"))
311                 return "application/xml";
312
313         while (pvo) {
314                 if (pvo->name[0] == '*') /* ie, match anything */
315                         return pvo->value;
316
317                 if (!strcmp(&file[n - strlen(pvo->name)], pvo->name))
318                         return pvo->value;
319
320                 pvo = pvo->next;
321         }
322
323         return NULL;
324 }
325
326 static int
327 lws_http_serve(struct lws *wsi, char *uri, const char *origin,
328                const struct lws_http_mount *m)
329 {
330         const struct lws_protocol_vhost_options *pvo = m->interpret;
331         struct lws_process_html_args args;
332         const char *mimetype;
333 #if !defined(_WIN32_WCE) && !defined(LWS_WITH_ESP8266)
334         struct stat st;
335         int spin = 0;
336 #endif
337         char path[256], sym[512];
338         unsigned char *p = (unsigned char *)sym + 32 + LWS_PRE, *start = p;
339         unsigned char *end = p + sizeof(sym) - 32 - LWS_PRE;
340 #if !defined(WIN32) && LWS_POSIX
341         size_t len;
342 #endif
343         int n;
344
345         lws_snprintf(path, sizeof(path) - 1, "%s/%s", origin, uri);
346
347 #if !defined(_WIN32_WCE) && !defined(LWS_WITH_ESP8266)
348         do {
349                 spin++;
350
351                 if (stat(path, &st)) {
352                         lwsl_info("unable to stat %s\n", path);
353                         goto bail;
354                 }
355
356                 lwsl_debug(" %s mode %d\n", path, S_IFMT & st.st_mode);
357 #if !defined(WIN32) && LWS_POSIX
358                 if ((S_IFMT & st.st_mode) == S_IFLNK) {
359                         len = readlink(path, sym, sizeof(sym) - 1);
360                         if (len) {
361                                 lwsl_err("Failed to read link %s\n", path);
362                                 goto bail;
363                         }
364                         sym[len] = '\0';
365                         lwsl_debug("symlink %s -> %s\n", path, sym);
366                         lws_snprintf(path, sizeof(path) - 1, "%s", sym);
367                 }
368 #endif
369                 if ((S_IFMT & st.st_mode) == S_IFDIR) {
370                         lwsl_debug("default filename append to dir\n");
371                         lws_snprintf(path, sizeof(path) - 1, "%s/%s/index.html",
372                                  origin, uri);
373                 }
374
375         } while ((S_IFMT & st.st_mode) != S_IFREG && spin < 5);
376
377         if (spin == 5)
378                 lwsl_err("symlink loop %s \n", path);
379
380         n = sprintf(sym, "%08lX%08lX", (unsigned long)st.st_size,
381                                    (unsigned long)st.st_mtime);
382
383         /* disable ranges if IF_RANGE token invalid */
384
385         if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_IF_RANGE))
386                 if (strcmp(sym, lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_IF_RANGE)))
387                         /* differs - defeat Range: */
388                         wsi->u.http.ah->frag_index[WSI_TOKEN_HTTP_RANGE] = 0;
389
390         if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_IF_NONE_MATCH)) {
391                 /*
392                  * he thinks he has some version of it already,
393                  * check if the tag matches
394                  */
395                 if (!strcmp(sym, lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_IF_NONE_MATCH))) {
396
397                         lwsl_debug("%s: ETAG match %s %s\n", __func__,
398                                    uri, origin);
399
400                         /* we don't need to send the payload */
401                         if (lws_add_http_header_status(wsi, 304, &p, end))
402                                 return -1;
403
404                         if (lws_add_http_header_by_token(wsi,
405                                         WSI_TOKEN_HTTP_ETAG,
406                                         (unsigned char *)sym, n, &p, end))
407                                 return -1;
408
409                         if (lws_finalize_http_header(wsi, &p, end))
410                                 return -1;
411
412                         n = lws_write(wsi, start, p - start,
413                                       LWS_WRITE_HTTP_HEADERS);
414                         if (n != (p - start)) {
415                                 lwsl_err("_write returned %d from %d\n", n, p - start);
416                                 return -1;
417                         }
418
419                         return lws_http_transaction_completed(wsi);
420                 }
421         }
422
423         if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_ETAG,
424                         (unsigned char *)sym, n, &p, end))
425                 return -1;
426 #endif
427
428         mimetype = lws_get_mimetype(path, m);
429         if (!mimetype) {
430                 lwsl_err("unknown mimetype for %s\n", path);
431                goto bail;
432         }
433         if (!mimetype[0])
434                 lwsl_debug("sending no mimetype for %s\n", path);
435
436         wsi->sending_chunked = 0;
437
438         /*
439          * check if this is in the list of file suffixes to be interpreted by
440          * a protocol
441          */
442         while (pvo) {
443                 n = strlen(path);
444                 if (n > (int)strlen(pvo->name) &&
445                     !strcmp(&path[n - strlen(pvo->name)], pvo->name)) {
446                         wsi->sending_chunked = 1;
447                         wsi->protocol_interpret_idx = (char)(long)pvo->value;
448                         lwsl_info("want %s interpreted by %s\n", path,
449                                     wsi->vhost->protocols[(int)(long)(pvo->value)].name);
450                         wsi->protocol = &wsi->vhost->protocols[(int)(long)(pvo->value)];
451                         if (lws_ensure_user_space(wsi))
452                                 return -1;
453                         break;
454                 }
455                 pvo = pvo->next;
456         }
457
458         if (m->protocol) {
459                 const struct lws_protocols *pp = lws_vhost_name_to_protocol(
460                                                         wsi->vhost, m->protocol);
461
462                 if (lws_bind_protocol(wsi, pp))
463                         return 1;
464                 args.p = (char *)p;
465                 args.max_len = end - p;
466                 if (pp->callback(wsi, LWS_CALLBACK_ADD_HEADERS,
467                                           wsi->user_space, &args, 0))
468                         return -1;
469                 p = (unsigned char *)args.p;
470         }
471
472         n = lws_serve_http_file(wsi, path, mimetype, (char *)start, p - start);
473
474         if (n < 0 || ((n > 0) && lws_http_transaction_completed(wsi)))
475                 return -1; /* error or can't reuse connection: close the socket */
476
477         return 0;
478 bail:
479
480         return -1;
481 }
482
483 const struct lws_http_mount *
484 lws_find_mount(struct lws *wsi, const char *uri_ptr, int uri_len)
485 {
486         const struct lws_http_mount *hm, *hit = NULL;
487         int best = 0;
488
489         hm = wsi->vhost->mount_list;
490         while (hm) {
491                 if (uri_len >= hm->mountpoint_len &&
492                     !strncmp(uri_ptr, hm->mountpoint, hm->mountpoint_len) &&
493                     (uri_ptr[hm->mountpoint_len] == '\0' ||
494                      uri_ptr[hm->mountpoint_len] == '/' ||
495                      hm->mountpoint_len == 1)
496                     ) {
497                         if (hm->origin_protocol == LWSMPRO_CALLBACK ||
498                             ((hm->origin_protocol == LWSMPRO_CGI ||
499                              lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) ||
500                              hm->protocol) &&
501                             hm->mountpoint_len > best)) {
502                                 best = hm->mountpoint_len;
503                                 hit = hm;
504                         }
505                 }
506                 hm = hm->mount_next;
507         }
508
509         return hit;
510 }
511
512 #ifdef LWS_POSIX
513
514 static int
515 lws_find_string_in_file(const char *filename, const char *string, int stringlen)
516 {
517         char buf[128];
518         int fd, match = 0, pos = 0, n = 0, hit = 0;
519
520         fd = open(filename, O_RDONLY);
521         if (fd < 0) {
522                 lwsl_err("can't open auth file: %s\n", filename);
523                 return 1;
524         }
525
526         while (1) {
527                 if (pos == n) {
528                         n = read(fd, buf, sizeof(buf));
529                         if (n <= 0) {
530                                 if (match == stringlen)
531                                         hit = 1;
532                                 break;
533                         }
534                         pos = 0;
535                 }
536
537                 if (match == stringlen) {
538                         if (buf[pos] == '\r' || buf[pos] == '\n') {
539                                 hit = 1;
540                                 break;
541                         }
542                         match = 0;
543                 }
544
545                 if (buf[pos] == string[match])
546                         match++;
547                 else
548                         match = 0;
549
550                 pos++;
551         }
552
553         close(fd);
554
555         return hit;
556 }
557
558 static int
559 lws_unauthorised_basic_auth(struct lws *wsi)
560 {
561         struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
562         unsigned char *start = pt->serv_buf + LWS_PRE,
563                       *p = start, *end = p + 512;
564         char buf[64];
565         int n;
566
567         /* no auth... tell him it is required */
568
569         if (lws_add_http_header_status(wsi, HTTP_STATUS_UNAUTHORIZED, &p, end))
570                 return -1;
571
572         n = lws_snprintf(buf, sizeof(buf), "Basic realm=\"lwsws\"");
573         if (lws_add_http_header_by_token(wsi,
574                         WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
575                         (unsigned char *)buf, n, &p, end))
576                 return -1;
577
578         if (lws_finalize_http_header(wsi, &p, end))
579                 return -1;
580
581         n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
582         if (n < 0)
583                 return -1;
584
585         return lws_http_transaction_completed(wsi);
586
587 }
588
589 #endif
590
591 int
592 lws_http_action(struct lws *wsi)
593 {
594         struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
595         enum http_connection_type connection_type;
596         enum http_version request_version;
597         char content_length_str[32];
598         struct lws_process_html_args args;
599         const struct lws_http_mount *hit = NULL;
600         unsigned int n, count = 0;
601         char http_version_str[10];
602         char http_conn_str[20];
603         int http_version_len;
604         char *uri_ptr = NULL, *s;
605         int uri_len = 0;
606         int meth = -1;
607
608         static const unsigned char methods[] = {
609                 WSI_TOKEN_GET_URI,
610                 WSI_TOKEN_POST_URI,
611                 WSI_TOKEN_OPTIONS_URI,
612                 WSI_TOKEN_PUT_URI,
613                 WSI_TOKEN_PATCH_URI,
614                 WSI_TOKEN_DELETE_URI,
615 #ifdef LWS_USE_HTTP2
616                 WSI_TOKEN_HTTP_COLON_PATH,
617 #endif
618         };
619 #if defined(_DEBUG) || defined(LWS_WITH_ACCESS_LOG)
620         static const char * const method_names[] = {
621                 "GET", "POST", "OPTIONS", "PUT", "PATCH", "DELETE",
622 #ifdef LWS_USE_HTTP2
623                 ":path",
624 #endif
625         };
626 #endif
627         static const char * const oprot[] = {
628                 "http://", "https://"
629         };
630
631         /* it's not websocket.... shall we accept it as http? */
632
633         for (n = 0; n < ARRAY_SIZE(methods); n++)
634                 if (lws_hdr_total_length(wsi, methods[n]))
635                         count++;
636         if (!count) {
637                 lwsl_warn("Missing URI in HTTP request\n");
638                 goto bail_nuke_ah;
639         }
640
641         if (count != 1) {
642                 lwsl_warn("multiple methods?\n");
643                 goto bail_nuke_ah;
644         }
645
646         if (lws_ensure_user_space(wsi))
647                 goto bail_nuke_ah;
648
649         for (n = 0; n < ARRAY_SIZE(methods); n++)
650                 if (lws_hdr_total_length(wsi, methods[n])) {
651                         uri_ptr = lws_hdr_simple_ptr(wsi, methods[n]);
652                         uri_len = lws_hdr_total_length(wsi, methods[n]);
653                         lwsl_info("Method: %s request for '%s'\n",
654                                         method_names[n], uri_ptr);
655                         meth = n;
656                         break;
657                 }
658
659         (void)meth;
660
661         /* we insist on absolute paths */
662
663         if (uri_ptr[0] != '/') {
664                 lws_return_http_status(wsi, HTTP_STATUS_FORBIDDEN, NULL);
665
666                 goto bail_nuke_ah;
667         }
668
669         /* HTTP header had a content length? */
670
671         wsi->u.http.content_length = 0;
672         if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI) ||
673                 lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI) ||
674                 lws_hdr_total_length(wsi, WSI_TOKEN_PUT_URI))
675                 wsi->u.http.content_length = 100 * 1024 * 1024;
676
677         if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
678                 lws_hdr_copy(wsi, content_length_str,
679                              sizeof(content_length_str) - 1,
680                              WSI_TOKEN_HTTP_CONTENT_LENGTH);
681                 wsi->u.http.content_length = atoi(content_length_str);
682         }
683
684         if (wsi->http2_substream) {
685                 wsi->u.http.request_version = HTTP_VERSION_2;
686         } else {
687                 /* http_version? Default to 1.0, override with token: */
688                 request_version = HTTP_VERSION_1_0;
689
690                 /* Works for single digit HTTP versions. : */
691                 http_version_len = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP);
692                 if (http_version_len > 7) {
693                         lws_hdr_copy(wsi, http_version_str,
694                                         sizeof(http_version_str) - 1, WSI_TOKEN_HTTP);
695                         if (http_version_str[5] == '1' && http_version_str[7] == '1')
696                                 request_version = HTTP_VERSION_1_1;
697                 }
698                 wsi->u.http.request_version = request_version;
699
700                 /* HTTP/1.1 defaults to "keep-alive", 1.0 to "close" */
701                 if (request_version == HTTP_VERSION_1_1)
702                         connection_type = HTTP_CONNECTION_KEEP_ALIVE;
703                 else
704                         connection_type = HTTP_CONNECTION_CLOSE;
705
706                 /* Override default if http "Connection:" header: */
707                 if (lws_hdr_total_length(wsi, WSI_TOKEN_CONNECTION)) {
708                         lws_hdr_copy(wsi, http_conn_str, sizeof(http_conn_str) - 1,
709                                      WSI_TOKEN_CONNECTION);
710                         http_conn_str[sizeof(http_conn_str) - 1] = '\0';
711                         if (!strcasecmp(http_conn_str, "keep-alive"))
712                                 connection_type = HTTP_CONNECTION_KEEP_ALIVE;
713                         else
714                                 if (!strcasecmp(http_conn_str, "close"))
715                                         connection_type = HTTP_CONNECTION_CLOSE;
716                 }
717                 wsi->u.http.connection_type = connection_type;
718         }
719
720         n = wsi->protocol->callback(wsi, LWS_CALLBACK_FILTER_HTTP_CONNECTION,
721                                     wsi->user_space, uri_ptr, uri_len);
722         if (n) {
723                 lwsl_info("LWS_CALLBACK_HTTP closing\n");
724
725                 return 1;
726         }
727         /*
728          * if there is content supposed to be coming,
729          * put a timeout on it having arrived
730          */
731         lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
732                         wsi->context->timeout_secs);
733 #ifdef LWS_OPENSSL_SUPPORT
734         if (wsi->redirect_to_https) {
735                 /*
736                  * we accepted http:// only so we could redirect to
737                  * https://, so issue the redirect.  Create the redirection
738                  * URI from the host: header and ignore the path part
739                  */
740                 unsigned char *start = pt->serv_buf + LWS_PRE, *p = start,
741                               *end = p + 512;
742
743                 if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST))
744                         goto bail_nuke_ah;
745
746                 n = sprintf((char *)end, "https://%s/",
747                             lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST));
748
749                 n = lws_http_redirect(wsi, HTTP_STATUS_MOVED_PERMANENTLY,
750                                       end, n, &p, end);
751                 if ((int)n < 0)
752                         goto bail_nuke_ah;
753
754                 return lws_http_transaction_completed(wsi);
755         }
756 #endif
757
758 #ifdef LWS_WITH_ACCESS_LOG
759         /*
760          * Produce Apache-compatible log string for wsi, like this:
761          *
762          * 2.31.234.19 - - [27/Mar/2016:03:22:44 +0800]
763          * "GET /aep-screen.png HTTP/1.1"
764          * 200 152987 "https://libwebsockets.org/index.html"
765          * "Mozilla/5.0 (Macint... Chrome/49.0.2623.87 Safari/537.36"
766          *
767          */
768         {
769                 static const char * const hver[] = {
770                         "http/1.0", "http/1.1", "http/2"
771                 };
772 #ifdef LWS_USE_IPV6
773                 char ads[INET6_ADDRSTRLEN];
774 #else
775                 char ads[INET_ADDRSTRLEN];
776 #endif
777                 char da[64];
778                 const char *pa, *me;
779                 struct tm *tmp;
780                 time_t t = time(NULL);
781                 int l = 256;
782
783                 if (wsi->access_log_pending)
784                         lws_access_log(wsi);
785
786                 wsi->access_log.header_log = lws_malloc(l);
787                 if (wsi->access_log.header_log) {
788
789                         tmp = localtime(&t);
790                         if (tmp)
791                                 strftime(da, sizeof(da), "%d/%b/%Y:%H:%M:%S %z", tmp);
792                         else
793                                 strcpy(da, "01/Jan/1970:00:00:00 +0000");
794
795                         pa = lws_get_peer_simple(wsi, ads, sizeof(ads));
796                         if (!pa)
797                                 pa = "(unknown)";
798
799                         if (meth >= 0)
800                                 me = method_names[meth];
801                         else
802                                 me = "unknown";
803
804                         lws_snprintf(wsi->access_log.header_log, l,
805                                  "%s - - [%s] \"%s %s %s\"",
806                                  pa, da, me, uri_ptr,
807                                  hver[wsi->u.http.request_version]);
808
809                         l = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_USER_AGENT);
810                         if (l) {
811                                 wsi->access_log.user_agent = lws_malloc(l + 2);
812                                 if (wsi->access_log.user_agent)
813                                         lws_hdr_copy(wsi, wsi->access_log.user_agent,
814                                                         l + 1, WSI_TOKEN_HTTP_USER_AGENT);
815                                 else
816                                         lwsl_err("OOM getting user agent\n");
817                         }
818                         wsi->access_log_pending = 1;
819                 }
820         }
821 #endif
822
823         /* can we serve it from the mount list? */
824
825         hit = lws_find_mount(wsi, uri_ptr, uri_len);
826         if (!hit) {
827                 /* deferred cleanup and reset to protocols[0] */
828
829                 lwsl_info("no hit\n");
830
831                 if (lws_bind_protocol(wsi, &wsi->vhost->protocols[0]))
832                         return 1;
833
834                 n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
835                                     wsi->user_space, uri_ptr, uri_len);
836
837                 goto after;
838         }
839
840         s = uri_ptr + hit->mountpoint_len;
841
842         /*
843          * if we have a mountpoint like https://xxx.com/yyy
844          * there is an implied / at the end for our purposes since
845          * we can only mount on a "directory".
846          *
847          * But if we just go with that, the browser cannot understand
848          * that he is actually looking down one "directory level", so
849          * even though we give him /yyy/abc.html he acts like the
850          * current directory level is /.  So relative urls like "x.png"
851          * wrongly look outside the mountpoint.
852          *
853          * Therefore if we didn't come in on a url with an explicit
854          * / at the end, we must redirect to add it so the browser
855          * understands he is one "directory level" down.
856          */
857         if ((hit->mountpoint_len > 1 ||
858              (hit->origin_protocol == LWSMPRO_REDIR_HTTP ||
859               hit->origin_protocol == LWSMPRO_REDIR_HTTPS)) &&
860             (*s != '/' ||
861              (hit->origin_protocol == LWSMPRO_REDIR_HTTP ||
862               hit->origin_protocol == LWSMPRO_REDIR_HTTPS)) &&
863             (hit->origin_protocol != LWSMPRO_CGI &&
864              hit->origin_protocol != LWSMPRO_CALLBACK //&&
865              //hit->protocol == NULL
866              )) {
867                 unsigned char *start = pt->serv_buf + LWS_PRE,
868                               *p = start, *end = p + 512;
869
870                 lwsl_debug("Doing 301 '%s' org %s\n", s, hit->origin);
871
872                 if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST))
873                         goto bail_nuke_ah;
874
875                 /* > at start indicates deal with by redirect */
876                 if (hit->origin_protocol == LWSMPRO_REDIR_HTTP ||
877                     hit->origin_protocol == LWSMPRO_REDIR_HTTPS)
878                         n = lws_snprintf((char *)end, 256, "%s%s",
879                                     oprot[hit->origin_protocol & 1],
880                                     hit->origin);
881                 else
882                         n = lws_snprintf((char *)end, 256,
883                             "%s%s%s/", oprot[lws_is_ssl(wsi)],
884                             lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST),
885                             uri_ptr);
886
887                 n = lws_http_redirect(wsi, HTTP_STATUS_MOVED_PERMANENTLY,
888                                       end, n, &p, end);
889                 if ((int)n < 0)
890                         goto bail_nuke_ah;
891
892                 return lws_http_transaction_completed(wsi);
893         }
894
895 #ifdef LWS_POSIX
896         /* basic auth? */
897
898         if (hit->basic_auth_login_file) {
899                 char b64[160], plain[(sizeof(b64) * 3) / 4];
900                 int m;
901
902                 /* Did he send auth? */
903                 if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_AUTHORIZATION))
904                         return lws_unauthorised_basic_auth(wsi);
905
906                 n = HTTP_STATUS_FORBIDDEN;
907
908                 m = lws_hdr_copy(wsi, b64, sizeof(b64), WSI_TOKEN_HTTP_AUTHORIZATION);
909                 if (m < 7) {
910                         lwsl_err("b64 auth too long\n");
911                         goto transaction_result_n;
912                 }
913
914                 b64[5] = '\0';
915                 if (strcasecmp(b64, "Basic")) {
916                         lwsl_err("auth missing basic: %s\n", b64);
917                         goto transaction_result_n;
918                 }
919
920                 /* It'll be like Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l */
921
922                 m = lws_b64_decode_string(b64 + 6, plain, sizeof(plain));
923                 if (m < 0) {
924                         lwsl_err("plain auth too long\n");
925                         goto transaction_result_n;
926                 }
927
928 //              lwsl_notice(plain);
929
930                 if (!lws_find_string_in_file(hit->basic_auth_login_file, plain, m)) {
931                         lwsl_err("basic auth lookup failed\n");
932                         return lws_unauthorised_basic_auth(wsi);
933                 }
934
935                 lwsl_notice("basic auth accepted\n");
936
937                 /* accept the auth */
938         }
939 #endif
940
941         /*
942          * A particular protocol callback is mounted here?
943          *
944          * For the duration of this http transaction, bind us to the
945          * associated protocol
946          */
947         if (hit->origin_protocol == LWSMPRO_CALLBACK || hit->protocol) {
948                 const struct lws_protocols *pp;
949                 const char *name = hit->origin;
950                 if (hit->protocol)
951                         name = hit->protocol;
952
953                 pp = lws_vhost_name_to_protocol(wsi->vhost, name);
954                 if (!pp) {
955                         n = -1;
956                         lwsl_err("Unable to find plugin '%s'\n",
957                                  hit->origin);
958                         return 1;
959                 }
960
961                 if (lws_bind_protocol(wsi, pp))
962                         return 1;
963
964                 args.p = uri_ptr;
965                 args.len = uri_len;
966                 args.max_len = hit->auth_mask;
967                 args.final = 0; /* used to signal callback dealt with it */
968
969                 n = wsi->protocol->callback(wsi, LWS_CALLBACK_CHECK_ACCESS_RIGHTS,
970                                             wsi->user_space, &args, 0);
971                 if (n) {
972                         lws_return_http_status(wsi, HTTP_STATUS_UNAUTHORIZED,
973                                                NULL);
974                         goto bail_nuke_ah;
975                 }
976                 if (args.final) /* callback completely handled it well */
977                         return 0;
978
979                 if (hit->cgienv && wsi->protocol->callback(wsi,
980                                 LWS_CALLBACK_HTTP_PMO,
981                                 wsi->user_space, (void *)hit->cgienv, 0))
982                         return 1;
983
984                 if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
985                         n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
986                                             wsi->user_space,
987                                             uri_ptr + hit->mountpoint_len,
988                                             uri_len - hit->mountpoint_len);
989                         goto after;
990                 }
991         }
992
993 #ifdef LWS_WITH_CGI
994         /* did we hit something with a cgi:// origin? */
995         if (hit->origin_protocol == LWSMPRO_CGI) {
996                 const char *cmd[] = {
997                         NULL, /* replace with cgi path */
998                         NULL
999                 };
1000                 unsigned char *p, *end, buffer[1024];
1001
1002                 lwsl_debug("%s: cgi\n", __func__);
1003                 cmd[0] = hit->origin;
1004
1005                 n = 5;
1006                 if (hit->cgi_timeout)
1007                         n = hit->cgi_timeout;
1008
1009                 n = lws_cgi(wsi, cmd, hit->mountpoint_len, n,
1010                             hit->cgienv);
1011                 if (n) {
1012                         lwsl_err("%s: cgi failed\n");
1013                         return -1;
1014                 }
1015                 p = buffer + LWS_PRE;
1016                 end = p + sizeof(buffer) - LWS_PRE;
1017
1018                 if (lws_add_http_header_status(wsi, 200, &p, end))
1019                         return 1;
1020                 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION,
1021                                 (unsigned char *)"close", 5, &p, end))
1022                         return 1;
1023                 n = lws_write(wsi, buffer + LWS_PRE,
1024                               p - (buffer + LWS_PRE),
1025                               LWS_WRITE_HTTP_HEADERS);
1026
1027                 goto deal_body;
1028         }
1029 #endif
1030
1031         n = strlen(s);
1032         if (s[0] == '\0' || (n == 1 && s[n - 1] == '/'))
1033                 s = (char *)hit->def;
1034         if (!s)
1035                 s = "index.html";
1036
1037         wsi->cache_secs = hit->cache_max_age;
1038         wsi->cache_reuse = hit->cache_reusable;
1039         wsi->cache_revalidate = hit->cache_revalidate;
1040         wsi->cache_intermediaries = hit->cache_intermediaries;
1041
1042         n = lws_http_serve(wsi, s, hit->origin, hit);
1043         if (n) {
1044                 /*
1045                  *      lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
1046                  */
1047                 if (hit->protocol) {
1048                         const struct lws_protocols *pp = lws_vhost_name_to_protocol(
1049                                         wsi->vhost, hit->protocol);
1050
1051                         if (lws_bind_protocol(wsi, pp))
1052                                 return 1;
1053
1054                         n = pp->callback(wsi, LWS_CALLBACK_HTTP,
1055                                          wsi->user_space,
1056                                          uri_ptr + hit->mountpoint_len,
1057                                          uri_len - hit->mountpoint_len);
1058                 } else
1059                         n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
1060                                     wsi->user_space, uri_ptr, uri_len);
1061         }
1062
1063 after:
1064         if (n) {
1065                 lwsl_info("LWS_CALLBACK_HTTP closing\n");
1066
1067                 return 1;
1068         }
1069
1070 #ifdef LWS_WITH_CGI
1071 deal_body:
1072 #endif
1073         /*
1074          * If we're not issuing a file, check for content_length or
1075          * HTTP keep-alive. No keep-alive header allocation for
1076          * ISSUING_FILE, as this uses HTTP/1.0.
1077          *
1078          * In any case, return 0 and let lws_read decide how to
1079          * proceed based on state
1080          */
1081         if (wsi->state != LWSS_HTTP_ISSUING_FILE)
1082                 /* Prepare to read body if we have a content length: */
1083                 if (wsi->u.http.content_length > 0)
1084                         wsi->state = LWSS_HTTP_BODY;
1085
1086         return 0;
1087
1088 bail_nuke_ah:
1089         /* we're closing, losing some rx is OK */
1090         wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
1091         // lwsl_notice("%s: drop1\n", __func__);
1092         lws_header_table_detach(wsi, 1);
1093
1094         return 1;
1095
1096 transaction_result_n:
1097         lws_return_http_status(wsi, n, NULL);
1098         return lws_http_transaction_completed(wsi);
1099 }
1100
1101 int
1102 lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p)
1103 {
1104 //      if (wsi->protocol == p)
1105 //              return 0;
1106
1107         if (wsi->protocol)
1108                 wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_DROP_PROTOCOL,
1109                                         wsi->user_space, NULL, 0);
1110         if (!wsi->user_space_externally_allocated)
1111                 lws_free_set_NULL(wsi->user_space);
1112
1113         wsi->protocol = p;
1114         if (!p)
1115                 return 0;
1116
1117         if (lws_ensure_user_space(wsi))
1118                 return 1;
1119
1120         if (wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_BIND_PROTOCOL,
1121                                     wsi->user_space, NULL, 0))
1122                 return 1;
1123
1124         return 0;
1125 }
1126
1127
1128 int
1129 lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
1130 {
1131         struct lws_context *context = lws_get_context(wsi);
1132         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
1133         struct _lws_header_related hdr;
1134         struct allocated_headers *ah;
1135         int protocol_len, n = 0, hit;
1136         char protocol_list[128];
1137         char protocol_name[64];
1138         char *p;
1139
1140         if (len >= 10000000) {
1141                 lwsl_err("%s: assert: len %ld\n", __func__, (long)len);
1142                 assert(0);
1143         }
1144
1145         if (!wsi->u.hdr.ah) {
1146                 lwsl_err("%s: assert: NULL ah\n", __func__);
1147                 assert(0);
1148         }
1149
1150         while (len--) {
1151                 wsi->more_rx_waiting = !!len;
1152
1153                 if (wsi->mode != LWSCM_HTTP_SERVING &&
1154                     wsi->mode != LWSCM_HTTP_SERVING_ACCEPTED) {
1155                         lwsl_err("%s: bad wsi mode %d\n", __func__, wsi->mode);
1156                         goto bail_nuke_ah;
1157                 }
1158
1159                 if (lws_parse(wsi, *(*buf)++)) {
1160                         lwsl_info("lws_parse failed\n");
1161                         goto bail_nuke_ah;
1162                 }
1163
1164                 if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
1165                         continue;
1166
1167                 lwsl_parser("%s: lws_parse sees parsing complete\n", __func__);
1168                 lwsl_debug("%s: wsi->more_rx_waiting=%d\n", __func__,
1169                                 wsi->more_rx_waiting);
1170
1171                 /* check for unwelcome guests */
1172
1173                 if (wsi->context->reject_service_keywords) {
1174                         const struct lws_protocol_vhost_options *rej =
1175                                         wsi->context->reject_service_keywords;
1176                         char ua[384], *msg = NULL;
1177
1178                         if (lws_hdr_copy(wsi, ua, sizeof(ua) - 1,
1179                                           WSI_TOKEN_HTTP_USER_AGENT) > 0) {
1180                                 ua[sizeof(ua) - 1] = '\0';
1181                                 while (rej) {
1182                                         if (strstr(ua, rej->name)) {
1183                                                 msg = strchr(rej->value, ' ');
1184                                                 if (msg)
1185                                                         msg++;
1186                                                 lws_return_http_status(wsi, atoi(rej->value), msg);
1187
1188                                                 wsi->vhost->conn_stats.rejected++;
1189
1190                                                 goto bail_nuke_ah;
1191                                         }
1192                                         rej = rej->next;
1193                                 }
1194                         }
1195                 }
1196
1197                 /* select vhost */
1198
1199                 if (lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) {
1200                         struct lws_vhost *vhost = lws_select_vhost(
1201                                 context, wsi->vhost->listen_port,
1202                                 lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST));
1203
1204                         if (vhost)
1205                                 wsi->vhost = vhost;
1206                 } else
1207                         lwsl_info("no host\n");
1208
1209                 wsi->vhost->conn_stats.trans++;
1210                 if (!wsi->conn_stat_done) {
1211                         wsi->vhost->conn_stats.conn++;
1212                         wsi->conn_stat_done = 1;
1213                 }
1214
1215                 wsi->mode = LWSCM_PRE_WS_SERVING_ACCEPT;
1216                 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1217
1218                 /* is this websocket protocol or normal http 1.0? */
1219
1220                 if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) {
1221                         if (!strcasecmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE),
1222                                         "websocket")) {
1223                                 wsi->vhost->conn_stats.ws_upg++;
1224                                 lwsl_info("Upgrade to ws\n");
1225                                 goto upgrade_ws;
1226                         }
1227 #ifdef LWS_USE_HTTP2
1228                         if (!strcasecmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE),
1229                                         "h2c")) {
1230                                 wsi->vhost->conn_stats.http2_upg++;
1231                                 lwsl_info("Upgrade to h2c\n");
1232                                 goto upgrade_h2c;
1233                         }
1234 #endif
1235                         lwsl_info("Unknown upgrade\n");
1236                         /* dunno what he wanted to upgrade to */
1237                         goto bail_nuke_ah;
1238                 }
1239
1240                 /* no upgrade ack... he remained as HTTP */
1241
1242                 lwsl_info("No upgrade\n");
1243                 ah = wsi->u.hdr.ah;
1244
1245                 lws_union_transition(wsi, LWSCM_HTTP_SERVING_ACCEPTED);
1246                 wsi->state = LWSS_HTTP;
1247                 wsi->u.http.fd = LWS_INVALID_FILE;
1248
1249                 /* expose it at the same offset as u.hdr */
1250                 wsi->u.http.ah = ah;
1251                 lwsl_debug("%s: wsi %p: ah %p\n", __func__, (void *)wsi,
1252                            (void *)wsi->u.hdr.ah);
1253
1254                 n = lws_http_action(wsi);
1255
1256                 return n;
1257
1258 #ifdef LWS_USE_HTTP2
1259 upgrade_h2c:
1260                 if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP2_SETTINGS)) {
1261                         lwsl_info("missing http2_settings\n");
1262                         goto bail_nuke_ah;
1263                 }
1264
1265                 lwsl_info("h2c upgrade...\n");
1266
1267                 p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP2_SETTINGS);
1268                 /* convert the peer's HTTP-Settings */
1269                 n = lws_b64_decode_string(p, protocol_list,
1270                                           sizeof(protocol_list));
1271                 if (n < 0) {
1272                         lwsl_parser("HTTP2_SETTINGS too long\n");
1273                         return 1;
1274                 }
1275
1276                 /* adopt the header info */
1277
1278                 ah = wsi->u.hdr.ah;
1279
1280                 lws_union_transition(wsi, LWSCM_HTTP2_SERVING);
1281
1282                 /* http2 union member has http union struct at start */
1283                 wsi->u.http.ah = ah;
1284
1285                 lws_http2_init(&wsi->u.http2.peer_settings);
1286                 lws_http2_init(&wsi->u.http2.my_settings);
1287
1288                 /* HTTP2 union */
1289
1290                 lws_http2_interpret_settings_payload(&wsi->u.http2.peer_settings,
1291                                 (unsigned char *)protocol_list, n);
1292
1293                 strcpy(protocol_list,
1294                        "HTTP/1.1 101 Switching Protocols\x0d\x0a"
1295                       "Connection: Upgrade\x0d\x0a"
1296                       "Upgrade: h2c\x0d\x0a\x0d\x0a");
1297                 n = lws_issue_raw(wsi, (unsigned char *)protocol_list,
1298                                         strlen(protocol_list));
1299                 if (n != strlen(protocol_list)) {
1300                         lwsl_debug("http2 switch: ERROR writing to socket\n");
1301                         return 1;
1302                 }
1303
1304                 wsi->state = LWSS_HTTP2_AWAIT_CLIENT_PREFACE;
1305
1306                 return 0;
1307 #endif
1308
1309 upgrade_ws:
1310                 if (!wsi->protocol)
1311                         lwsl_err("NULL protocol at lws_read\n");
1312
1313                 /*
1314                  * It's websocket
1315                  *
1316                  * Select the first protocol we support from the list
1317                  * the client sent us.
1318                  *
1319                  * Copy it to remove header fragmentation
1320                  */
1321
1322                 if (lws_hdr_copy(wsi, protocol_list, sizeof(protocol_list) - 1,
1323                                  WSI_TOKEN_PROTOCOL) < 0) {
1324                         lwsl_err("protocol list too long");
1325                         goto bail_nuke_ah;
1326                 }
1327
1328                 protocol_len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
1329                 protocol_list[protocol_len] = '\0';
1330                 p = protocol_list;
1331                 hit = 0;
1332
1333                 while (*p && !hit) {
1334                         n = 0;
1335                         while (n < sizeof(protocol_name) - 1 && *p && *p !=',')
1336                                 protocol_name[n++] = *p++;
1337                         protocol_name[n] = '\0';
1338                         if (*p)
1339                                 p++;
1340
1341                         lwsl_info("checking %s\n", protocol_name);
1342
1343                         n = 0;
1344                         while (wsi->vhost->protocols[n].callback) {
1345                                 lwsl_info("try %s\n", wsi->vhost->protocols[n].name);
1346
1347                                 if (wsi->vhost->protocols[n].name &&
1348                                     !strcmp(wsi->vhost->protocols[n].name,
1349                                             protocol_name)) {
1350                                         wsi->protocol = &wsi->vhost->protocols[n];
1351                                         hit = 1;
1352                                         break;
1353                                 }
1354
1355                                 n++;
1356                         }
1357                 }
1358
1359                 /* we didn't find a protocol he wanted? */
1360
1361                 if (!hit) {
1362                         if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL)) {
1363                                 lwsl_info("No protocol from \"%s\" supported\n",
1364                                          protocol_list);
1365                                 goto bail_nuke_ah;
1366                         }
1367                         /*
1368                          * some clients only have one protocol and
1369                          * do not send the protocol list header...
1370                          * allow it and match to the vhost's default
1371                          * protocol (which itself defaults to zero)
1372                          */
1373                         lwsl_info("defaulting to prot handler %d\n",
1374                                 wsi->vhost->default_protocol_index);
1375                         n = 0;
1376                         wsi->protocol = &wsi->vhost->protocols[
1377                                       (int)wsi->vhost->default_protocol_index];
1378                 }
1379
1380                 /* allocate wsi->user storage */
1381                 if (lws_ensure_user_space(wsi))
1382                         goto bail_nuke_ah;
1383
1384                 /*
1385                  * Give the user code a chance to study the request and
1386                  * have the opportunity to deny it
1387                  */
1388                 if ((wsi->protocol->callback)(wsi,
1389                                 LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
1390                                 wsi->user_space,
1391                               lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL), 0)) {
1392                         lwsl_warn("User code denied connection\n");
1393                         goto bail_nuke_ah;
1394                 }
1395
1396                 /*
1397                  * Perform the handshake according to the protocol version the
1398                  * client announced
1399                  */
1400
1401                 switch (wsi->ietf_spec_revision) {
1402                 case 13:
1403                         lwsl_parser("lws_parse calling handshake_04\n");
1404                         if (handshake_0405(context, wsi)) {
1405                                 lwsl_info("hs0405 has failed the connection\n");
1406                                 goto bail_nuke_ah;
1407                         }
1408                         break;
1409
1410                 default:
1411                         lwsl_info("Unknown client spec version %d\n",
1412                                   wsi->ietf_spec_revision);
1413                         goto bail_nuke_ah;
1414                 }
1415
1416                 /*
1417                  * stitch protocol choice into the vh protocol linked list
1418                  * We always insert ourselves at the start of the list
1419                  *
1420                  * X <-> B
1421                  * X <-> pAn <-> pB
1422                  */
1423                 //lwsl_err("%s: pre insert vhost start wsi %p, that wsi prev == %p\n",
1424                 //              __func__,
1425                 //              wsi->vhost->same_vh_protocol_list[n],
1426                 //              wsi->same_vh_protocol_prev);
1427                 wsi->same_vh_protocol_prev = /* guy who points to us */
1428                         &wsi->vhost->same_vh_protocol_list[n];
1429                 wsi->same_vh_protocol_next = /* old first guy is our next */
1430                                 wsi->vhost->same_vh_protocol_list[n];
1431                 /* we become the new first guy */
1432                 wsi->vhost->same_vh_protocol_list[n] = wsi;
1433
1434                 if (wsi->same_vh_protocol_next)
1435                         /* old first guy points back to us now */
1436                         wsi->same_vh_protocol_next->same_vh_protocol_prev =
1437                                         &wsi->same_vh_protocol_next;
1438
1439
1440
1441                 /* we are upgrading to ws, so http/1.1 and keepalive +
1442                  * pipelined header considerations about keeping the ah around
1443                  * no longer apply.  However it's common for the first ws
1444                  * protocol data to have been coalesced with the browser
1445                  * upgrade request and to already be in the ah rx buffer.
1446                  */
1447
1448                 lwsl_info("%s: %p: inheriting ah in ws mode (rxpos:%d, rxlen:%d)\n",
1449                           __func__, wsi, wsi->u.hdr.ah->rxpos,
1450                           wsi->u.hdr.ah->rxlen);
1451                 lws_pt_lock(pt);
1452                 hdr = wsi->u.hdr;
1453
1454                 lws_union_transition(wsi, LWSCM_WS_SERVING);
1455                 /*
1456                  * first service is WS mode will notice this, use the RX and
1457                  * then detach the ah (caution: we are not in u.hdr union
1458                  * mode any more then... ah_temp member is at start the same
1459                  * though)
1460                  *
1461                  * Because rxpos/rxlen shows something in the ah, we will get
1462                  * service guaranteed next time around the event loop
1463                  *
1464                  * All union members begin with hdr, so we can use it even
1465                  * though we transitioned to ws union mode (the ah detach
1466                  * code uses it anyway).
1467                  */
1468                 wsi->u.hdr = hdr;
1469                 lws_pt_unlock(pt);
1470
1471                 lws_restart_ws_ping_pong_timer(wsi);
1472
1473                 /*
1474                  * create the frame buffer for this connection according to the
1475                  * size mentioned in the protocol definition.  If 0 there, use
1476                  * a big default for compatibility
1477                  */
1478
1479                 n = wsi->protocol->rx_buffer_size;
1480                 if (!n)
1481                         n = context->pt_serv_buf_size;
1482                 n += LWS_PRE;
1483                 wsi->u.ws.rx_ubuf = lws_malloc(n + 4 /* 0x0000ffff zlib */);
1484                 if (!wsi->u.ws.rx_ubuf) {
1485                         lwsl_err("Out of Mem allocating rx buffer %d\n", n);
1486                         return 1;
1487                 }
1488                 wsi->u.ws.rx_ubuf_alloc = n;
1489                 lwsl_debug("Allocating RX buffer %d\n", n);
1490 #if LWS_POSIX
1491                 if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF,
1492                                (const char *)&n, sizeof n)) {
1493                         lwsl_warn("Failed to set SNDBUF to %d", n);
1494                         return 1;
1495                 }
1496 #endif
1497
1498                 lwsl_parser("accepted v%02d connection\n",
1499                             wsi->ietf_spec_revision);
1500
1501                 /* notify user code that we're ready to roll */
1502
1503                 if (wsi->protocol->callback)
1504                         if (wsi->protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED,
1505                                                     wsi->user_space,
1506 #ifdef LWS_OPENSSL_SUPPORT
1507                                                     wsi->ssl,
1508 #else
1509                                                     NULL,
1510 #endif
1511                                                     0))
1512                                 return 1;
1513
1514                 /* !!! drop ah unreservedly after ESTABLISHED */
1515                 if (!wsi->more_rx_waiting) {
1516                         wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
1517
1518                         //lwsl_notice("%p: dropping ah EST\n", wsi);
1519                         lws_header_table_detach(wsi, 1);
1520                 }
1521
1522                 return 0;
1523         } /* while all chars are handled */
1524
1525         return 0;
1526
1527 bail_nuke_ah:
1528         /* drop the header info */
1529         /* we're closing, losing some rx is OK */
1530         wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
1531         //lwsl_notice("%s: drop2\n", __func__);
1532         lws_header_table_detach(wsi, 1);
1533
1534         return 1;
1535 }
1536
1537 static int
1538 lws_get_idlest_tsi(struct lws_context *context)
1539 {
1540         unsigned int lowest = ~0;
1541         int n = 0, hit = -1;
1542
1543         for (; n < context->count_threads; n++) {
1544                 if ((unsigned int)context->pt[n].fds_count !=
1545                     context->fd_limit_per_thread - 1 &&
1546                     (unsigned int)context->pt[n].fds_count < lowest) {
1547                         lowest = context->pt[n].fds_count;
1548                         hit = n;
1549                 }
1550         }
1551
1552         return hit;
1553 }
1554
1555 struct lws *
1556 lws_create_new_server_wsi(struct lws_vhost *vhost)
1557 {
1558         struct lws *new_wsi;
1559         int n = lws_get_idlest_tsi(vhost->context);
1560
1561         if (n < 0) {
1562                 lwsl_err("no space for new conn\n");
1563                 return NULL;
1564         }
1565
1566         new_wsi = lws_zalloc(sizeof(struct lws));
1567         if (new_wsi == NULL) {
1568                 lwsl_err("Out of memory for new connection\n");
1569                 return NULL;
1570         }
1571
1572         new_wsi->tsi = n;
1573         lwsl_notice("Accepted wsi %p to context %p, tsi %d\n", new_wsi,
1574                     vhost->context, new_wsi->tsi);
1575
1576         new_wsi->vhost = vhost;
1577         new_wsi->context = vhost->context;
1578         new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
1579         new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
1580
1581         /* initialize the instance struct */
1582
1583         new_wsi->state = LWSS_HTTP;
1584         new_wsi->mode = LWSCM_HTTP_SERVING;
1585         new_wsi->hdr_parsing_completed = 0;
1586
1587 #ifdef LWS_OPENSSL_SUPPORT
1588         new_wsi->use_ssl = LWS_SSL_ENABLED(vhost);
1589 #endif
1590
1591         /*
1592          * these can only be set once the protocol is known
1593          * we set an unestablished connection's protocol pointer
1594          * to the start of the supported list, so it can look
1595          * for matching ones during the handshake
1596          */
1597         new_wsi->protocol = vhost->protocols;
1598         new_wsi->user_space = NULL;
1599         new_wsi->ietf_spec_revision = 0;
1600         new_wsi->sock = LWS_SOCK_INVALID;
1601         vhost->context->count_wsi_allocated++;
1602
1603         /*
1604          * outermost create notification for wsi
1605          * no user_space because no protocol selection
1606          */
1607         vhost->protocols[0].callback(new_wsi, LWS_CALLBACK_WSI_CREATE,
1608                                        NULL, NULL, 0);
1609
1610         return new_wsi;
1611 }
1612
1613 LWS_VISIBLE int LWS_WARN_UNUSED_RESULT
1614 lws_http_transaction_completed(struct lws *wsi)
1615 {
1616         int n = NO_PENDING_TIMEOUT;
1617
1618         lws_access_log(wsi);
1619
1620         lwsl_info("%s: wsi %p\n", __func__, wsi);
1621         /* if we can't go back to accept new headers, drop the connection */
1622         if (wsi->u.http.connection_type != HTTP_CONNECTION_KEEP_ALIVE) {
1623                 lwsl_info("%s: %p: close connection\n", __func__, wsi);
1624                 return 1;
1625         }
1626
1627         if (lws_bind_protocol(wsi, &wsi->vhost->protocols[0]))
1628                 return 1;
1629
1630         /* otherwise set ourselves up ready to go again */
1631         wsi->state = LWSS_HTTP;
1632         wsi->mode = LWSCM_HTTP_SERVING;
1633         wsi->u.http.content_length = 0;
1634         wsi->u.http.content_remain = 0;
1635         wsi->hdr_parsing_completed = 0;
1636 #ifdef LWS_WITH_ACCESS_LOG
1637         wsi->access_log.sent = 0;
1638 #endif
1639
1640         if (wsi->vhost->keepalive_timeout)
1641                 n = PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE;
1642         lws_set_timeout(wsi, n, wsi->vhost->keepalive_timeout);
1643
1644         /*
1645          * We already know we are on http1.1 / keepalive and the next thing
1646          * coming will be another header set.
1647          *
1648          * If there is no pending rx and we still have the ah, drop it and
1649          * reacquire a new ah when the new headers start to arrive.  (Otherwise
1650          * we needlessly hog an ah indefinitely.)
1651          *
1652          * However if there is pending rx and we know from the keepalive state
1653          * that is already at least the start of another header set, simply
1654          * reset the existing header table and keep it.
1655          */
1656         if (wsi->u.hdr.ah) {
1657                 lwsl_info("%s: wsi->more_rx_waiting=%d\n", __func__,
1658                                 wsi->more_rx_waiting);
1659
1660                 if (!wsi->more_rx_waiting) {
1661                         wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
1662                         lws_header_table_detach(wsi, 1);
1663                 } else
1664                         lws_header_table_reset(wsi, 1);
1665         }
1666
1667         /* If we're (re)starting on headers, need other implied init */
1668         wsi->u.hdr.ues = URIES_IDLE;
1669
1670         lwsl_info("%s: %p: keep-alive await new transaction\n", __func__, wsi);
1671
1672         return 0;
1673 }
1674
1675 struct lws *
1676 lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd)
1677 {
1678         struct lws_context *context = vh->context;
1679         struct lws *new_wsi = lws_create_new_server_wsi(vh);
1680
1681         if (!new_wsi) {
1682                 compatible_close(accept_fd);
1683                 return NULL;
1684         }
1685
1686         //lwsl_notice("%s: new wsi %p, sockfd %d, cb %p\n", __func__, new_wsi, accept_fd, context->vhost_list->protocols[0].callback);
1687
1688         new_wsi->sock = accept_fd;
1689
1690         /* the transport is accepted... give him time to negotiate */
1691         lws_set_timeout(new_wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
1692                         context->timeout_secs);
1693
1694 #if LWS_POSIX == 0
1695 #if defined(LWS_WITH_ESP8266)
1696         esp8266_tcp_stream_accept(accept_fd, new_wsi);
1697 #else
1698         mbed3_tcp_stream_accept(accept_fd, new_wsi);
1699 #endif
1700 #endif
1701         /*
1702          * A new connection was accepted. Give the user a chance to
1703          * set properties of the newly created wsi. There's no protocol
1704          * selected yet so we issue this to protocols[0]
1705          */
1706         if ((context->vhost_list->protocols[0].callback)(new_wsi,
1707              LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED, NULL, NULL, 0)) {
1708                 /* force us off the timeout list by hand */
1709                 lws_set_timeout(new_wsi, NO_PENDING_TIMEOUT, 0);
1710                 compatible_close(new_wsi->sock);
1711                 lws_free(new_wsi);
1712                 return NULL;
1713         }
1714
1715         lws_libev_accept(new_wsi, new_wsi->sock);
1716         lws_libuv_accept(new_wsi, new_wsi->sock);
1717
1718         if (!LWS_SSL_ENABLED(new_wsi->vhost)) {
1719                 if (insert_wsi_socket_into_fds(context, new_wsi)) {
1720                         lwsl_err("%s: fail inserting socket\n", __func__);
1721                         goto fail;
1722                 }
1723         } else {
1724                 new_wsi->mode = LWSCM_SSL_INIT;
1725                 if (lws_server_socket_service_ssl(new_wsi, accept_fd)) {
1726                         lwsl_err("%s: fail ssl negotiation\n", __func__);
1727                         goto fail;
1728                 }
1729         }
1730
1731         if (!lws_header_table_attach(new_wsi, 0))
1732                 lwsl_debug("Attached ah immediately\n");
1733
1734         return new_wsi;
1735
1736 fail:
1737         lws_close_free_wsi(new_wsi, LWS_CLOSE_STATUS_NOSTATUS);
1738
1739         return NULL;
1740 }
1741
1742 LWS_VISIBLE struct lws *
1743 lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd)
1744 {
1745         return lws_adopt_socket_vhost(context->vhost_list, accept_fd);
1746 }
1747
1748 LWS_VISIBLE LWS_EXTERN struct lws *
1749 lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd,
1750                          const char *readbuf, size_t len)
1751 {
1752         struct lws *wsi = lws_adopt_socket(context, accept_fd);
1753         struct lws_context_per_thread *pt;
1754         struct allocated_headers *ah;
1755         struct lws_pollfd *pfd;
1756
1757         if (!wsi)
1758                 return NULL;
1759
1760         if (!readbuf)
1761                 return wsi;
1762
1763         if (len > sizeof(ah->rx)) {
1764                 lwsl_err("%s: rx in too big\n", __func__);
1765                 goto bail;
1766         }
1767
1768         /*
1769          * we can't process the initial read data until we can attach an ah.
1770          *
1771          * if one is available, get it and place the data in his ah rxbuf...
1772          * wsi with ah that have pending rxbuf get auto-POLLIN service.
1773          *
1774          * no autoservice because we didn't get a chance to attach the
1775          * readbuf data to wsi or ah yet, and we will do it next if we get
1776          * the ah.
1777          */
1778         if (wsi->u.hdr.ah || !lws_header_table_attach(wsi, 0)) {
1779                 ah = wsi->u.hdr.ah;
1780                 memcpy(ah->rx, readbuf, len);
1781                 ah->rxpos = 0;
1782                 ah->rxlen = len;
1783
1784                 lwsl_notice("%s: calling service on readbuf ah\n", __func__);
1785                 pt = &context->pt[(int)wsi->tsi];
1786
1787                 /* unlike a normal connect, we have the headers already
1788                  * (or the first part of them anyway).
1789                  * libuv won't come back and service us without a network
1790                  * event, so we need to do the header service right here.
1791                  */
1792                 pfd = &pt->fds[wsi->position_in_fds_table];
1793                 pfd->revents |= LWS_POLLIN;
1794                 lwsl_err("%s: calling service\n", __func__);
1795                 if (lws_service_fd_tsi(context, pfd, wsi->tsi))
1796                         /* service closed us */
1797                         return NULL;
1798
1799                 return wsi;
1800         }
1801         lwsl_err("%s: deferring handling ah\n", __func__);
1802         /*
1803          * hum if no ah came, we are on the wait list and must defer
1804          * dealing with this until the ah arrives.
1805          *
1806          * later successful lws_header_table_attach() will apply the
1807          * below to the rx buffer (via lws_header_table_reset()).
1808          */
1809         wsi->u.hdr.preamble_rx = lws_malloc(len);
1810         if (!wsi->u.hdr.preamble_rx) {
1811                 lwsl_err("OOM\n");
1812                 goto bail;
1813         }
1814         memcpy(wsi->u.hdr.preamble_rx, readbuf, len);
1815         wsi->u.hdr.preamble_rx_len = len;
1816
1817         return wsi;
1818
1819 bail:
1820         lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
1821
1822         return NULL;
1823 }
1824
1825 LWS_VISIBLE int
1826 lws_server_socket_service(struct lws_context *context, struct lws *wsi,
1827                           struct lws_pollfd *pollfd)
1828 {
1829         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
1830         lws_sockfd_type accept_fd = LWS_SOCK_INVALID;
1831         struct allocated_headers *ah;
1832 #if LWS_POSIX
1833         struct sockaddr_in cli_addr;
1834         socklen_t clilen;
1835 #endif
1836         int n, len;
1837         
1838         // lwsl_notice("%s: mode %d\n", __func__, wsi->mode);
1839
1840         switch (wsi->mode) {
1841
1842         case LWSCM_HTTP_SERVING:
1843         case LWSCM_HTTP_SERVING_ACCEPTED:
1844         case LWSCM_HTTP2_SERVING:
1845
1846                 /* handle http headers coming in */
1847
1848                 /* pending truncated sends have uber priority */
1849
1850                 if (wsi->trunc_len) {
1851                         if (!(pollfd->revents & LWS_POLLOUT))
1852                                 break;
1853
1854                         if (lws_issue_raw(wsi, wsi->trunc_alloc +
1855                                                wsi->trunc_offset,
1856                                           wsi->trunc_len) < 0)
1857                                 goto fail;
1858                         /*
1859                          * we can't afford to allow input processing to send
1860                          * something new, so spin around he event loop until
1861                          * he doesn't have any partials
1862                          */
1863                         break;
1864                 }
1865
1866                 /* any incoming data ready? */
1867
1868                 if (!(pollfd->revents & pollfd->events & LWS_POLLIN))
1869                         goto try_pollout;
1870
1871                 /*
1872                  * If we previously just did POLLIN when IN and OUT were
1873                  * signalled (because POLLIN processing may have used up
1874                  * the POLLOUT), don't let that happen twice in a row...
1875                  * next time we see the situation favour POLLOUT
1876                  */
1877 #if !defined(LWS_WITH_ESP8266)
1878                 if (wsi->favoured_pollin &&
1879                     (pollfd->revents & pollfd->events & LWS_POLLOUT)) {
1880                         wsi->favoured_pollin = 0;
1881                         goto try_pollout;
1882                 }
1883 #endif
1884                 /* these states imply we MUST have an ah attached */
1885
1886                 if (wsi->state == LWSS_HTTP ||
1887                     wsi->state == LWSS_HTTP_ISSUING_FILE ||
1888                     wsi->state == LWSS_HTTP_HEADERS) {
1889                         if (!wsi->u.hdr.ah) {
1890                                 
1891                                 //lwsl_err("wsi %p: missing ah\n", wsi);
1892                                 /* no autoservice beacuse we will do it next */
1893                                 if (lws_header_table_attach(wsi, 0)) {
1894                                         lwsl_err("wsi %p: failed to acquire ah\n", wsi);
1895                                         goto try_pollout;
1896                                 }
1897                         }
1898                         ah = wsi->u.hdr.ah;
1899
1900                         //lwsl_notice("%s: %p: rxpos:%d rxlen:%d\n", __func__, wsi,
1901                         //         ah->rxpos, ah->rxlen);
1902
1903                         /* if nothing in ah rx buffer, get some fresh rx */
1904                         if (ah->rxpos == ah->rxlen) {
1905                                 ah->rxlen = lws_ssl_capable_read(wsi, ah->rx,
1906                                                    sizeof(ah->rx));
1907                                 ah->rxpos = 0;
1908                                 //lwsl_notice("%s: wsi %p, ah->rxlen = %d\r\n",
1909                                 //         __func__, wsi, ah->rxlen);
1910                                 switch (ah->rxlen) {
1911                                 case 0:
1912                                         lwsl_info("%s: read 0 len\n", __func__);
1913                                         /* lwsl_info("   state=%d\n", wsi->state); */
1914 //                                      if (!wsi->hdr_parsing_completed)
1915 //                                              lws_header_table_detach(wsi);
1916                                         /* fallthru */
1917                                 case LWS_SSL_CAPABLE_ERROR:
1918                                         goto fail;
1919                                 case LWS_SSL_CAPABLE_MORE_SERVICE:
1920                                         ah->rxlen = ah->rxpos = 0;
1921                                         goto try_pollout;
1922                                 }
1923                         }
1924
1925                         if (!(ah->rxpos != ah->rxlen && ah->rxlen)) {
1926                                 lwsl_err("%s: assert: rxpos %d, rxlen %d\n",
1927                                          __func__, ah->rxpos, ah->rxlen);
1928
1929                                 assert(0);
1930                         }
1931                         
1932                         /* just ignore incoming if waiting for close */
1933                         if (wsi->state != LWSS_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
1934                                 n = lws_read(wsi, ah->rx + ah->rxpos,
1935                                              ah->rxlen - ah->rxpos);
1936                                 if (n < 0) /* we closed wsi */
1937                                         return 1;
1938                                 if (wsi->u.hdr.ah) {
1939                                         if ( wsi->u.hdr.ah->rxlen)
1940                                                  wsi->u.hdr.ah->rxpos += n;
1941
1942                                         lwsl_debug("%s: wsi %p: ah read rxpos %d, rxlen %d\n", __func__, wsi, wsi->u.hdr.ah->rxpos, wsi->u.hdr.ah->rxlen);
1943
1944                                         if (wsi->u.hdr.ah->rxpos == wsi->u.hdr.ah->rxlen &&
1945                                             (wsi->mode != LWSCM_HTTP_SERVING &&
1946                                              wsi->mode != LWSCM_HTTP_SERVING_ACCEPTED &&
1947                                              wsi->mode != LWSCM_HTTP2_SERVING))
1948                                                 lws_header_table_detach(wsi, 1);
1949                                 }
1950                                 break;
1951                         }
1952
1953                         goto try_pollout;
1954                 }
1955
1956                 len = lws_ssl_capable_read(wsi, pt->serv_buf,
1957                                            context->pt_serv_buf_size);
1958                 lwsl_notice("%s: wsi %p read %d\r\n", __func__, wsi, len);
1959                 switch (len) {
1960                 case 0:
1961                         lwsl_info("%s: read 0 len\n", __func__);
1962                         /* lwsl_info("   state=%d\n", wsi->state); */
1963 //                      if (!wsi->hdr_parsing_completed)
1964 //                              lws_header_table_detach(wsi);
1965                         /* fallthru */
1966                 case LWS_SSL_CAPABLE_ERROR:
1967                         goto fail;
1968                 case LWS_SSL_CAPABLE_MORE_SERVICE:
1969                         goto try_pollout;
1970                 }
1971                 
1972                 /* just ignore incoming if waiting for close */
1973                 if (wsi->state != LWSS_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
1974                         /*
1975                          * this may want to send
1976                          * (via HTTP callback for example)
1977                          */
1978                         n = lws_read(wsi, pt->serv_buf, len);
1979                         if (n < 0) /* we closed wsi */
1980                                 return 1;
1981                         /*
1982                          *  he may have used up the
1983                          * writability above, if we will defer POLLOUT
1984                          * processing in favour of POLLIN, note it
1985                          */
1986                         if (pollfd->revents & LWS_POLLOUT)
1987                                 wsi->favoured_pollin = 1;
1988                         break;
1989                 }
1990
1991 try_pollout:
1992                 
1993                 /* this handles POLLOUT for http serving fragments */
1994
1995                 if (!(pollfd->revents & LWS_POLLOUT))
1996                         break;
1997
1998                 /* one shot */
1999                 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
2000                         lwsl_notice("%s a\n", __func__);
2001                         goto fail;
2002                 }
2003
2004                 if (!wsi->hdr_parsing_completed)
2005                         break;
2006
2007                 if (wsi->state != LWSS_HTTP_ISSUING_FILE) {
2008                         n = user_callback_handle_rxflow(wsi->protocol->callback,
2009                                         wsi, LWS_CALLBACK_HTTP_WRITEABLE,
2010                                         wsi->user_space, NULL, 0);
2011                         if (n < 0) {
2012                                 lwsl_info("writeable_fail\n");
2013                                 goto fail;
2014                         }
2015                         break;
2016                 }
2017
2018                 /* >0 == completion, <0 == error */
2019                 n = lws_serve_http_file_fragment(wsi);
2020                 if (n < 0 || (n > 0 && lws_http_transaction_completed(wsi))) {
2021                         lwsl_info("completed\n");
2022                         goto fail;
2023                 }
2024
2025                 break;
2026
2027         case LWSCM_SERVER_LISTENER:
2028
2029 #if LWS_POSIX
2030                 /* pollin means a client has connected to us then */
2031
2032                 do {
2033                         if (!(pollfd->revents & LWS_POLLIN) || !(pollfd->events & LWS_POLLIN))
2034                                 break;
2035
2036                         /* listen socket got an unencrypted connection... */
2037
2038                         clilen = sizeof(cli_addr);
2039                         lws_latency_pre(context, wsi);
2040                         accept_fd  = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
2041                                             &clilen);
2042                         lws_latency(context, wsi, "listener accept", accept_fd,
2043                                     accept_fd >= 0);
2044                         if (accept_fd < 0) {
2045                                 if (LWS_ERRNO == LWS_EAGAIN ||
2046                                     LWS_ERRNO == LWS_EWOULDBLOCK) {
2047                                         lwsl_err("accept asks to try again\n");
2048                                         break;
2049                                 }
2050                                 lwsl_err("ERROR on accept: %s\n", strerror(LWS_ERRNO));
2051                                 break;
2052                         }
2053
2054                         lws_plat_set_socket_options(wsi->vhost, accept_fd);
2055
2056                         lwsl_debug("accepted new conn  port %u on fd=%d\n",
2057                                           ntohs(cli_addr.sin_port), accept_fd);
2058
2059 #else
2060                         /* not very beautiful... */
2061                         accept_fd = (lws_sockfd_type)pollfd;
2062 #endif
2063                         /*
2064                          * look at who we connected to and give user code a chance
2065                          * to reject based on client IP.  There's no protocol selected
2066                          * yet so we issue this to protocols[0]
2067                          */
2068                         if ((wsi->vhost->protocols[0].callback)(wsi,
2069                                         LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
2070                                         NULL, (void *)(long)accept_fd, 0)) {
2071                                 lwsl_debug("Callback denied network connection\n");
2072                                 compatible_close(accept_fd);
2073                                 break;
2074                         }
2075
2076                         if (!lws_adopt_socket_vhost(wsi->vhost, accept_fd))
2077                                 /* already closed cleanly as necessary */
2078                                 return 1;
2079
2080 #if LWS_POSIX
2081                 } while (pt->fds_count < context->fd_limit_per_thread - 1 &&
2082                          lws_poll_listen_fd(&pt->fds[wsi->position_in_fds_table]) > 0);
2083 #endif
2084                 return 0;
2085
2086         default:
2087                 break;
2088         }
2089
2090         if (!lws_server_socket_service_ssl(wsi, accept_fd))
2091                 return 0;
2092
2093 fail:
2094         lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
2095
2096         return 1;
2097 }
2098
2099 LWS_VISIBLE int
2100 lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type,
2101                     const char *other_headers, int other_headers_len)
2102 {
2103         static const char * const intermediates[] = { "private", "public" };
2104         struct lws_context *context = lws_get_context(wsi);
2105         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
2106 #if defined(LWS_WITH_RANGES)
2107         struct lws_range_parsing *rp = &wsi->u.http.range;
2108 #endif
2109         char cache_control[50], *cc = "no-store";
2110         unsigned char *response = pt->serv_buf + LWS_PRE;
2111         unsigned char *p = response;
2112         unsigned char *end = p + context->pt_serv_buf_size - LWS_PRE;
2113         unsigned long computed_total_content_length;
2114         int ret = 0, cclen = 8, n = HTTP_STATUS_OK;
2115 #if defined(LWS_WITH_RANGES)
2116         int ranges;
2117 #endif
2118
2119         wsi->u.http.fd = lws_plat_file_open(wsi, file, &wsi->u.http.filelen,
2120                                             O_RDONLY);
2121
2122         if (wsi->u.http.fd == LWS_INVALID_FILE) {
2123                 lwsl_err("Unable to open '%s'\n", file);
2124
2125                 return -1;
2126         }
2127         computed_total_content_length = wsi->u.http.filelen;
2128
2129 #if defined(LWS_WITH_RANGES)
2130         ranges = lws_ranges_init(wsi, rp, wsi->u.http.filelen);
2131
2132         lwsl_debug("Range count %d\n", ranges);
2133         /*
2134          * no ranges -> 200;
2135          *  1 range  -> 206 + Content-Type: normal; Content-Range;
2136          *  more     -> 206 + Content-Type: multipart/byteranges
2137          *              Repeat the true Content-Type in each multipart header
2138          *              along with Content-Range
2139          */
2140         if (ranges < 0) {
2141                 /* it means he expressed a range in Range:, but it was illegal */
2142                 lws_return_http_status(wsi, HTTP_STATUS_REQ_RANGE_NOT_SATISFIABLE, NULL);
2143                 if (lws_http_transaction_completed(wsi))
2144                         return -1; /* <0 means just hang up */
2145
2146                 return 0; /* == 0 means we dealt with the transaction complete */
2147         }
2148         if (ranges)
2149                 n = HTTP_STATUS_PARTIAL_CONTENT;
2150 #endif
2151
2152         if (lws_add_http_header_status(wsi, n, &p, end))
2153                 return -1;
2154
2155 #if defined(LWS_WITH_RANGES)
2156         if (ranges < 2 && content_type && content_type[0])
2157                 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
2158                                                  (unsigned char *)content_type,
2159                                                  strlen(content_type), &p, end))
2160                         return -1;
2161
2162         if (ranges >= 2) { /* multipart byteranges */
2163                 strncpy(wsi->u.http.multipart_content_type, content_type,
2164                         sizeof(wsi->u.http.multipart_content_type) - 1);
2165                 wsi->u.http.multipart_content_type[
2166                          sizeof(wsi->u.http.multipart_content_type) - 1] = '\0';
2167                 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
2168                                                  (unsigned char *)"multipart/byteranges; boundary=_lws",
2169                                                  20, &p, end))
2170                         return -1;
2171
2172                 /*
2173                  *  our overall content length has to include
2174                  *
2175                  *  - (n + 1) x "_lws\r\n"
2176                  *  - n x Content-Type: xxx/xxx\r\n
2177                  *  - n x Content-Range: bytes xxx-yyy/zzz\r\n
2178                  *  - n x /r/n
2179                  *  - the actual payloads (aggregated in rp->agg)
2180                  *
2181                  *  Precompute it for the main response header
2182                  */
2183
2184                 computed_total_content_length = (unsigned long)rp->agg +
2185                                                 6 /* final _lws\r\n */;
2186
2187                 lws_ranges_reset(rp);
2188                 while (lws_ranges_next(rp)) {
2189                         n = lws_snprintf(cache_control, sizeof(cache_control),
2190                                         "bytes %llu-%llu/%llu",
2191                                         rp->start, rp->end, rp->extent);
2192
2193                         computed_total_content_length +=
2194                                         6 /* header _lws\r\n */ +
2195                                         14 + strlen(content_type) + 2 + /* Content-Type: xxx/xxx\r\n */
2196                                         15 + n + 2 + /* Content-Range: xxxx\r\n */
2197                                         2; /* /r/n */
2198                 }
2199
2200                 lws_ranges_reset(rp);
2201                 lws_ranges_next(rp);
2202         }
2203
2204         if (ranges == 1) {
2205                 computed_total_content_length = (unsigned long)rp->agg;
2206                 n = lws_snprintf(cache_control, sizeof(cache_control), "bytes %llu-%llu/%llu",
2207                                 rp->start, rp->end, rp->extent);
2208
2209                 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_RANGE,
2210                                                  (unsigned char *)cache_control,
2211                                                  n, &p, end))
2212                         return -1;
2213         }
2214
2215         wsi->u.http.range.inside = 0;
2216
2217         if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_ACCEPT_RANGES,
2218                                          (unsigned char *)"bytes", 5, &p, end))
2219                 return -1;
2220 #endif
2221
2222         if (!wsi->sending_chunked) {
2223                 if (lws_add_http_header_content_length(wsi,
2224                                                        computed_total_content_length,
2225                                                        &p, end))
2226                         return -1;
2227         } else {
2228                 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_TRANSFER_ENCODING,
2229                                                  (unsigned char *)"chunked",
2230                                                  7, &p, end))
2231                         return -1;
2232         }
2233
2234         if (wsi->cache_secs && wsi->cache_reuse) {
2235                 if (wsi->cache_revalidate) {
2236                         cc = cache_control;
2237                         cclen = sprintf(cache_control, "%s max-age: %u",
2238                                     intermediates[wsi->cache_intermediaries],
2239                                     wsi->cache_secs);
2240                 } else {
2241                         cc = "no-cache";
2242                         cclen = 8;
2243                 }
2244         }
2245
2246         if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CACHE_CONTROL,
2247                         (unsigned char *)cc, cclen, &p, end))
2248                 return -1;
2249
2250         if (wsi->u.http.connection_type == HTTP_CONNECTION_KEEP_ALIVE)
2251                 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION,
2252                                 (unsigned char *)"keep-alive", 10, &p, end))
2253                         return -1;
2254
2255         if (other_headers) {
2256                 if ((end - p) < other_headers_len)
2257                         return -1;
2258                 memcpy(p, other_headers, other_headers_len);
2259                 p += other_headers_len;
2260         }
2261
2262         if (lws_finalize_http_header(wsi, &p, end))
2263                 return -1;
2264
2265         ret = lws_write(wsi, response, p - response, LWS_WRITE_HTTP_HEADERS);
2266         if (ret != (p - response)) {
2267                 lwsl_err("_write returned %d from %d\n", ret, (p - response));
2268                 return -1;
2269         }
2270
2271         wsi->u.http.filepos = 0;
2272         wsi->state = LWSS_HTTP_ISSUING_FILE;
2273
2274         return lws_serve_http_file_fragment(wsi);
2275 }
2276
2277 int
2278 lws_interpret_incoming_packet(struct lws *wsi, unsigned char **buf, size_t len)
2279 {
2280         int m;
2281
2282         lwsl_parser("%s: received %d byte packet\n", __func__, (int)len);
2283 #if 0
2284         lwsl_hexdump(*buf, len);
2285 #endif
2286
2287         /* let the rx protocol state machine have as much as it needs */
2288
2289         while (len) {
2290                 /*
2291                  * we were accepting input but now we stopped doing so
2292                  */
2293                 if (!(wsi->rxflow_change_to & LWS_RXFLOW_ALLOW)) {
2294                         lws_rxflow_cache(wsi, *buf, 0, len);
2295                         lwsl_parser("%s: cached %d\n", __func__, len);
2296                         return 1;
2297                 }
2298
2299                 if (wsi->u.ws.rx_draining_ext) {
2300                         m = lws_rx_sm(wsi, 0);
2301                         if (m < 0)
2302                                 return -1;
2303                         continue;
2304                 }
2305
2306                 /* account for what we're using in rxflow buffer */
2307                 if (wsi->rxflow_buffer)
2308                         wsi->rxflow_pos++;
2309
2310                 /* consume payload bytes efficiently */
2311                 if (wsi->lws_rx_parse_state ==
2312                     LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED) {
2313                         m = lws_payload_until_length_exhausted(wsi, buf, &len);
2314                         if (wsi->rxflow_buffer)
2315                                 wsi->rxflow_pos += m;
2316                 }
2317
2318                 /* process the byte */
2319                 m = lws_rx_sm(wsi, *(*buf)++);
2320                 if (m < 0)
2321                         return -1;
2322                 len--;
2323         }
2324
2325         lwsl_parser("%s: exit with %d unused\n", __func__, (int)len);
2326
2327         return 0;
2328 }
2329
2330 LWS_VISIBLE void
2331 lws_server_get_canonical_hostname(struct lws_context *context,
2332                                   struct lws_context_creation_info *info)
2333 {
2334         if (lws_check_opt(info->options, LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME))
2335                 return;
2336 #if LWS_POSIX
2337         /* find canonical hostname */
2338         gethostname((char *)context->canonical_hostname,
2339                     sizeof(context->canonical_hostname) - 1);
2340
2341         lwsl_notice(" canonical_hostname = %s\n", context->canonical_hostname);
2342 #else
2343         (void)context;
2344 #endif
2345 }
2346
2347 #define LWS_MAX_ELEM_NAME 32
2348
2349 enum urldecode_stateful {
2350         US_NAME,
2351         US_IDLE,
2352         US_PC1,
2353         US_PC2,
2354
2355         MT_LOOK_BOUND_IN,
2356         MT_HNAME,
2357         MT_DISP,
2358         MT_TYPE,
2359         MT_IGNORE1,
2360         MT_IGNORE2,
2361 };
2362
2363 static const char * const mp_hdr[] = {
2364         "content-disposition: ",
2365         "content-type: ",
2366         "\x0d\x0a"
2367 };
2368
2369 typedef int (*lws_urldecode_stateful_cb)(void *data,
2370                 const char *name, char **buf, int len, int final);
2371
2372 struct lws_urldecode_stateful {
2373         char *out;
2374         void *data;
2375         char name[LWS_MAX_ELEM_NAME];
2376         char temp[LWS_MAX_ELEM_NAME];
2377         char content_type[32];
2378         char content_disp[32];
2379         char content_disp_filename[256];
2380         char mime_boundary[128];
2381         int out_len;
2382         int pos;
2383         int hdr_idx;
2384         int mp;
2385
2386         unsigned int multipart_form_data:1;
2387         unsigned int inside_quote:1;
2388         unsigned int subname:1;
2389         unsigned int boundary_real_crlf:1;
2390
2391         enum urldecode_stateful state;
2392
2393         lws_urldecode_stateful_cb output;
2394 };
2395
2396 static struct lws_urldecode_stateful *
2397 lws_urldecode_s_create(struct lws *wsi, char *out, int out_len, void *data,
2398                        lws_urldecode_stateful_cb output)
2399 {
2400         struct lws_urldecode_stateful *s = lws_zalloc(sizeof(*s));
2401         char buf[200], *p;
2402         int m = 0;
2403
2404         if (!s)
2405                 return NULL;
2406
2407         s->out = out;
2408         s->out_len  = out_len;
2409         s->output = output;
2410         s->pos = 0;
2411         s->mp = 0;
2412         s->state = US_NAME;
2413         s->name[0] = '\0';
2414         s->data = data;
2415
2416         if (lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_CONTENT_TYPE) > 0) {
2417                 /* multipart/form-data; boundary=----WebKitFormBoundarycc7YgAPEIHvgE9Bf */
2418
2419                 if (!strncmp(buf, "multipart/form-data", 19)) {
2420                         s->multipart_form_data = 1;
2421                         s->state = MT_LOOK_BOUND_IN;
2422                         s->mp = 2;
2423                         p = strstr(buf, "boundary=");
2424                         if (p) {
2425                                 p += 9;
2426                                 s->mime_boundary[m++] = '\x0d';
2427                                 s->mime_boundary[m++] = '\x0a';
2428                                 s->mime_boundary[m++] = '-';
2429                                 s->mime_boundary[m++] = '-';
2430                                 while (m < sizeof(s->mime_boundary) - 1 &&
2431                                        *p && *p != ' ')
2432                                         s->mime_boundary[m++] = *p++;
2433
2434                                 s->mime_boundary[m] = '\0';
2435
2436                                 lwsl_notice("boundary '%s'\n", s->mime_boundary);
2437                         }
2438                 }
2439         }
2440
2441         return s;
2442 }
2443
2444 static int
2445 lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in, int len)
2446 {
2447         int n, m, hit = 0;
2448         char sum = 0, c, was_end = 0;
2449
2450         while (len--) {
2451                 if (s->pos == s->out_len - s->mp - 1) {
2452                         if (s->output(s->data, s->name, &s->out, s->pos, 0))
2453                                 return -1;
2454
2455                         was_end = s->pos;
2456                         s->pos = 0;
2457                 }
2458                 switch (s->state) {
2459
2460                 /* states for url arg style */
2461
2462                 case US_NAME:
2463                         s->inside_quote = 0;
2464                         if (*in == '=') {
2465                                 s->name[s->pos] = '\0';
2466                                 s->pos = 0;
2467                                 s->state = US_IDLE;
2468                                 in++;
2469                                 continue;
2470                         }
2471                         if (*in == '&') {
2472                                 s->name[s->pos] = '\0';
2473                                 if (s->output(s->data, s->name, &s->out, s->pos, 1))
2474                                         return -1;
2475                                 s->pos = 0;
2476                                 s->state = US_IDLE;
2477                                 in++;
2478                                 continue;
2479                         }
2480                         if (s->pos >= sizeof(s->name) - 1) {
2481                                 lwsl_notice("Name too long\n");
2482                                 return -1;
2483                         }
2484                         s->name[s->pos++] = *in++;
2485                         break;
2486                 case US_IDLE:
2487                         if (*in == '%') {
2488                                 s->state++;
2489                                 in++;
2490                                 continue;
2491                         }
2492                         if (*in == '&') {
2493                                 s->out[s->pos] = '\0';
2494                                 if (s->output(s->data, s->name, &s->out, s->pos, 1))
2495                                         return -1;
2496                                 s->pos = 0;
2497                                 s->state = US_NAME;
2498                                 in++;
2499                                 continue;
2500                         }
2501                         if (*in == '+') {
2502                                 in++;
2503                                 s->out[s->pos++] = ' ';
2504                                 continue;
2505                         }
2506                         s->out[s->pos++] = *in++;
2507                         break;
2508                 case US_PC1:
2509                         n = char_to_hex(*in);
2510                         if (n < 0)
2511                                 return -1;
2512
2513                         in++;
2514                         sum = n << 4;
2515                         s->state++;
2516                         break;
2517
2518                 case US_PC2:
2519                         n = char_to_hex(*in);
2520                         if (n < 0)
2521                                 return -1;
2522
2523                         in++;
2524                         s->out[s->pos++] = sum | n;
2525                         s->state = US_IDLE;
2526                         break;
2527
2528
2529                 /* states for multipart / mime style */
2530
2531                 case MT_LOOK_BOUND_IN:
2532 retry_as_first:
2533                         if (*in == s->mime_boundary[s->mp] &&
2534                             s->mime_boundary[s->mp]) {
2535                                 in++;
2536                                 s->mp++;
2537                                 if (!s->mime_boundary[s->mp]) {
2538                                         s->mp = 0;
2539                                         s->state = MT_IGNORE1;
2540
2541                                         if (s->pos || was_end)
2542                                                 if (s->output(s->data, s->name,
2543                                                       &s->out, s->pos, 1))
2544                                                         return -1;
2545
2546                                         s->pos = 0;
2547
2548                                         s->content_disp[0] = '\0';
2549                                         s->name[0] = '\0';
2550                                         s->content_disp_filename[0] = '\0';
2551                                         s->boundary_real_crlf = 1;
2552                                 }
2553                                 continue;
2554                         }
2555                         if (s->mp) {
2556                                 n = 0;
2557                                 if (!s->boundary_real_crlf)
2558                                         n = 2;
2559
2560                                 memcpy(s->out + s->pos, s->mime_boundary + n, s->mp - n);
2561                                 s->pos += s->mp;
2562                                 s->mp = 0;
2563                                 goto retry_as_first;
2564                         }
2565
2566                         s->out[s->pos++] = *in;
2567                         in++;
2568                         s->mp = 0;
2569                         break;
2570
2571                 case MT_HNAME:
2572                         m = 0;
2573                         c =*in;
2574                         if (c >= 'A' && c <= 'Z')
2575                                 c += 'a' - 'A';
2576                         for (n = 0; n < ARRAY_SIZE(mp_hdr); n++)
2577                                 if (c == mp_hdr[n][s->mp]) {
2578                                         m++;
2579                                         hit = n;
2580                                 }
2581                         in++;
2582                         if (!m) {
2583                                 s->mp = 0;
2584                                 continue;
2585                         }
2586
2587                         s->mp++;
2588                         if (m != 1)
2589                                 continue;
2590
2591                         if (mp_hdr[hit][s->mp])
2592                                 continue;
2593
2594                         s->mp = 0;
2595                         s->temp[0] = '\0';
2596                         s->subname = 0;
2597
2598                         if (hit == 2)
2599                                 s->state = MT_LOOK_BOUND_IN;
2600                         else
2601                                 s->state += hit + 1;
2602                         break;
2603
2604                 case MT_DISP:
2605                         /* form-data; name="file"; filename="t.txt" */
2606
2607                         if (*in == '\x0d') {
2608 //                              lwsl_notice("disp: '%s', '%s', '%s'\n",
2609 //                                 s->content_disp, s->name,
2610 //                                 s->content_disp_filename);
2611
2612                                 if (s->content_disp_filename[0])
2613                                         if (s->output(s->data, s->name,
2614                                                       &s->out, s->pos, LWS_UFS_OPEN))
2615                                                 return -1;
2616                                 s->state = MT_IGNORE2;
2617                                 goto done;
2618                         }
2619                         if (*in == ';') {
2620                                 s->subname = 1;
2621                                 s->temp[0] = '\0';
2622                                 s->mp = 0;
2623                                 goto done;
2624                         }
2625
2626                         if (*in == '\"') {
2627                                 s->inside_quote ^= 1;
2628                                 goto done;
2629                         }
2630
2631                         if (s->subname) {
2632                                 if (*in == '=') {
2633                                         s->temp[s->mp] = '\0';
2634                                         s->subname = 0;
2635                                         s->mp = 0;
2636                                         goto done;
2637                                 }
2638                                 if (s->mp < sizeof(s->temp) - 1 &&
2639                                     (*in != ' ' || s->inside_quote))
2640                                         s->temp[s->mp++] = *in;
2641                                 goto done;
2642                         }
2643
2644                         if (!s->temp[0]) {
2645                                 if (s->mp < sizeof(s->content_disp) - 1)
2646                                         s->content_disp[s->mp++] = *in;
2647                                 s->content_disp[s->mp] = '\0';
2648                                 goto done;
2649                         }
2650
2651                         if (!strcmp(s->temp, "name")) {
2652                                 if (s->mp < sizeof(s->name) - 1)
2653                                         s->name[s->mp++] = *in;
2654                                 s->name[s->mp] = '\0';
2655                                 goto done;
2656                         }
2657
2658                         if (!strcmp(s->temp, "filename")) {
2659                                 if (s->mp < sizeof(s->content_disp_filename) - 1)
2660                                         s->content_disp_filename[s->mp++] = *in;
2661                                 s->content_disp_filename[s->mp] = '\0';
2662                                 goto done;
2663                         }
2664 done:
2665                         in++;
2666                         break;
2667
2668                 case MT_TYPE:
2669                         if (*in == '\x0d')
2670                                 s->state = MT_IGNORE2;
2671                         else {
2672                                 if (s->mp < sizeof(s->content_type) - 1)
2673                                         s->content_type[s->mp++] = *in;
2674                                 s->content_type[s->mp] = '\0';
2675                         }
2676                         in++;
2677                         break;
2678
2679                 case MT_IGNORE1:
2680                         if (*in == '\x0d')
2681                                 s->state = MT_IGNORE2;
2682                         in++;
2683                         break;
2684
2685                 case MT_IGNORE2:
2686                         s->mp = 0;
2687                         if (*in == '\x0a')
2688                                 s->state = MT_HNAME;
2689                         in++;
2690                         break;
2691                 }
2692         }
2693
2694         return 0;
2695 }
2696
2697 static int
2698 lws_urldecode_s_destroy(struct lws_urldecode_stateful *s)
2699 {
2700         int ret = 0;
2701
2702         if (s->state != US_IDLE)
2703                 ret = -1;
2704
2705         if (!ret)
2706                 if (s->output(s->data, s->name, &s->out, s->pos, 1))
2707                         ret = -1;
2708
2709         lws_free(s);
2710
2711         return ret;
2712 }
2713
2714 struct lws_spa {
2715         struct lws_urldecode_stateful *s;
2716         lws_spa_fileupload_cb opt_cb;
2717         const char * const *param_names;
2718         int count_params;
2719         char **params;
2720         int *param_length;
2721         void *opt_data;
2722
2723         char *storage;
2724         char *end;
2725         int max_storage;
2726 };
2727
2728 static int
2729 lws_urldecode_spa_lookup(struct lws_spa *spa,
2730                          const char *name)
2731 {
2732         int n;
2733
2734         for (n = 0; n < spa->count_params; n++)
2735                 if (!strcmp(spa->param_names[n], name))
2736                         return n;
2737
2738         return -1;
2739 }
2740
2741 static int
2742 lws_urldecode_spa_cb(void *data, const char *name, char **buf, int len,
2743                      int final)
2744 {
2745         struct lws_spa *spa =
2746                         (struct lws_spa *)data;
2747         int n;
2748
2749         if (spa->s->content_disp_filename[0]) {
2750                 if (spa->opt_cb) {
2751                         n = spa->opt_cb(spa->opt_data, name,
2752                                         spa->s->content_disp_filename,
2753                                         *buf, len, final);
2754
2755                         if (n < 0)
2756                                 return -1;
2757                 }
2758                 return 0;
2759         }
2760         n = lws_urldecode_spa_lookup(spa, name);
2761
2762         if (n == -1 || !len) /* unrecognized */
2763                 return 0;
2764
2765         if (!spa->params[n])
2766                 spa->params[n] = *buf;
2767
2768         if ((*buf) + len >= spa->end) {
2769                 lwsl_notice("%s: exceeded storage\n", __func__);
2770                 return -1;
2771         }
2772
2773         spa->param_length[n] += len;
2774
2775         /* move it on inside storage */
2776         (*buf) += len;
2777         *((*buf)++) = '\0';
2778
2779         spa->s->out_len -= len + 1;
2780
2781         return 0;
2782 }
2783
2784 LWS_VISIBLE LWS_EXTERN struct lws_spa *
2785 lws_spa_create(struct lws *wsi, const char * const *param_names,
2786                          int count_params, int max_storage,
2787                          lws_spa_fileupload_cb opt_cb, void *opt_data)
2788 {
2789         struct lws_spa *spa = lws_zalloc(sizeof(*spa));
2790
2791         if (!spa)
2792                 return NULL;
2793
2794         spa->param_names = param_names;
2795         spa->count_params = count_params;
2796         spa->max_storage = max_storage;
2797         spa->opt_cb = opt_cb;
2798         spa->opt_data = opt_data;
2799
2800         spa->storage = lws_malloc(max_storage);
2801         if (!spa->storage)
2802                 goto bail2;
2803         spa->end = spa->storage + max_storage - 1;
2804
2805         spa->params = lws_zalloc(sizeof(char *) * count_params);
2806         if (!spa->params)
2807                 goto bail3;
2808
2809         spa->s = lws_urldecode_s_create(wsi, spa->storage, max_storage, spa,
2810                                         lws_urldecode_spa_cb);
2811         if (!spa->s)
2812                 goto bail4;
2813
2814         spa->param_length = lws_zalloc(sizeof(int) * count_params);
2815         if (!spa->param_length)
2816                 goto bail5;
2817
2818         lwsl_notice("%s: Created SPA %p\n", __func__, spa);
2819
2820         return spa;
2821
2822 bail5:
2823         lws_urldecode_s_destroy(spa->s);
2824 bail4:
2825         lws_free(spa->params);
2826 bail3:
2827         lws_free(spa->storage);
2828 bail2:
2829         lws_free(spa);
2830
2831         return NULL;
2832 }
2833
2834 LWS_VISIBLE LWS_EXTERN int
2835 lws_spa_process(struct lws_spa *ludspa, const char *in, int len)
2836 {
2837         if (!ludspa) {
2838                 lwsl_err("%s: NULL spa\n");
2839                 return -1;
2840         }
2841         return lws_urldecode_s_process(ludspa->s, in, len);
2842 }
2843
2844 LWS_VISIBLE LWS_EXTERN int
2845 lws_spa_get_length(struct lws_spa *ludspa, int n)
2846 {
2847         if (n >= ludspa->count_params)
2848                 return 0;
2849
2850         return ludspa->param_length[n];
2851 }
2852
2853 LWS_VISIBLE LWS_EXTERN const char *
2854 lws_spa_get_string(struct lws_spa *ludspa, int n)
2855 {
2856         if (n >= ludspa->count_params)
2857                 return NULL;
2858
2859         return ludspa->params[n];
2860 }
2861
2862 LWS_VISIBLE LWS_EXTERN int
2863 lws_spa_finalize(struct lws_spa *spa)
2864 {
2865         if (spa->s) {
2866                 lws_urldecode_s_destroy(spa->s);
2867                 spa->s = NULL;
2868         }
2869
2870         return 0;
2871 }
2872
2873 LWS_VISIBLE LWS_EXTERN int
2874 lws_spa_destroy(struct lws_spa *spa)
2875 {
2876         int n = 0;
2877
2878         lwsl_notice("%s: destroy spa %p\n", __func__, spa);
2879
2880         if (spa->s)
2881                 lws_urldecode_s_destroy(spa->s);
2882
2883         lwsl_debug("%s\n", __func__);
2884
2885         lws_free(spa->param_length);
2886         lws_free(spa->params);
2887         lws_free(spa->storage);
2888         lws_free(spa);
2889
2890         return n;
2891 }
2892
2893 LWS_VISIBLE LWS_EXTERN int
2894 lws_chunked_html_process(struct lws_process_html_args *args,
2895                          struct lws_process_html_state *s)
2896 {
2897         char *sp, buffer[32];
2898         const char *pc;
2899         int old_len, n;
2900
2901         /* do replacements */
2902         sp = args->p;
2903         old_len = args->len;
2904         args->len = 0;
2905         s->start = sp;
2906         while (sp < args->p + old_len) {
2907
2908                 if (args->len + 7 >= args->max_len) {
2909                         lwsl_err("Used up interpret padding\n");
2910                         return -1;
2911                 }
2912
2913                 if ((!s->pos && *sp == '$') || s->pos) {
2914                         int hits = 0, hit = 0;
2915
2916                         if (!s->pos)
2917                                 s->start = sp;
2918                         s->swallow[s->pos++] = *sp;
2919                         if (s->pos == sizeof(s->swallow) - 1)
2920                                 goto skip;
2921                         for (n = 0; n < s->count_vars; n++)
2922                                 if (!strncmp(s->swallow, s->vars[n], s->pos)) {
2923                                         hits++;
2924                                         hit = n;
2925                                 }
2926                         if (!hits) {
2927 skip:
2928                                 s->swallow[s->pos] = '\0';
2929                                 memcpy(s->start, s->swallow, s->pos);
2930                                 args->len++;
2931                                 s->pos = 0;
2932                                 sp = s->start + 1;
2933                                 continue;
2934                         }
2935                         if (hits == 1 && s->pos == strlen(s->vars[hit])) {
2936                                 pc = s->replace(s->data, hit);
2937                                 if (!pc)
2938                                         pc = "NULL";
2939                                 n = strlen(pc);
2940                                 s->swallow[s->pos] = '\0';
2941                                 if (n != s->pos) {
2942                                         memmove(s->start + n,
2943                                                 s->start + s->pos,
2944                                                 old_len - (sp - args->p));
2945                                         old_len += (n - s->pos) + 1;
2946                                 }
2947                                 memcpy(s->start, pc, n);
2948                                 args->len++;
2949                                 sp = s->start + 1;
2950
2951                                 s->pos = 0;
2952                         }
2953                         sp++;
2954                         continue;
2955                 }
2956
2957                 args->len++;
2958                 sp++;
2959         }
2960
2961         /* no space left for final chunk trailer */
2962         if (args->final && args->len + 7 >= args->max_len)
2963                 return -1;
2964
2965         n = sprintf(buffer, "%X\x0d\x0a", args->len);
2966
2967         args->p -= n;
2968         memcpy(args->p, buffer, n);
2969         args->len += n;
2970
2971         if (args->final) {
2972                 sp = args->p + args->len;
2973                 *sp++ = '\x0d';
2974                 *sp++ = '\x0a';
2975                 *sp++ = '0';
2976                 *sp++ = '\x0d';
2977                 *sp++ = '\x0a';
2978                 *sp++ = '\x0d';
2979                 *sp++ = '\x0a';
2980                 args->len += 7;
2981         } else {
2982                 sp = args->p + args->len;
2983                 *sp++ = '\x0d';
2984                 *sp++ = '\x0a';
2985                 args->len += 2;
2986         }
2987
2988         return 0;
2989 }