ESP8266: LWS_POSIX fixes for basic auth and deprecated context
[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 || info->port == CONTEXT_PORT_NO_LISTEN_SERVER)
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 #if 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 #if 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 #if LWS_POSIX
1096 transaction_result_n:
1097         lws_return_http_status(wsi, n, NULL);
1098
1099         return lws_http_transaction_completed(wsi);
1100 #endif
1101 }
1102
1103 int
1104 lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p)
1105 {
1106 //      if (wsi->protocol == p)
1107 //              return 0;
1108
1109         if (wsi->protocol)
1110                 wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_DROP_PROTOCOL,
1111                                         wsi->user_space, NULL, 0);
1112         if (!wsi->user_space_externally_allocated)
1113                 lws_free_set_NULL(wsi->user_space);
1114
1115         wsi->protocol = p;
1116         if (!p)
1117                 return 0;
1118
1119         if (lws_ensure_user_space(wsi))
1120                 return 1;
1121
1122         if (wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_BIND_PROTOCOL,
1123                                     wsi->user_space, NULL, 0))
1124                 return 1;
1125
1126         return 0;
1127 }
1128
1129
1130 int
1131 lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
1132 {
1133         struct lws_context *context = lws_get_context(wsi);
1134         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
1135         struct _lws_header_related hdr;
1136         struct allocated_headers *ah;
1137         int protocol_len, n = 0, hit;
1138         char protocol_list[128];
1139         char protocol_name[64];
1140         char *p;
1141
1142         if (len >= 10000000) {
1143                 lwsl_err("%s: assert: len %ld\n", __func__, (long)len);
1144                 assert(0);
1145         }
1146
1147         if (!wsi->u.hdr.ah) {
1148                 lwsl_err("%s: assert: NULL ah\n", __func__);
1149                 assert(0);
1150         }
1151
1152         while (len--) {
1153                 wsi->more_rx_waiting = !!len;
1154
1155                 if (wsi->mode != LWSCM_HTTP_SERVING &&
1156                     wsi->mode != LWSCM_HTTP_SERVING_ACCEPTED) {
1157                         lwsl_err("%s: bad wsi mode %d\n", __func__, wsi->mode);
1158                         goto bail_nuke_ah;
1159                 }
1160
1161                 if (lws_parse(wsi, *(*buf)++)) {
1162                         lwsl_info("lws_parse failed\n");
1163                         goto bail_nuke_ah;
1164                 }
1165
1166                 if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
1167                         continue;
1168
1169                 lwsl_parser("%s: lws_parse sees parsing complete\n", __func__);
1170                 lwsl_debug("%s: wsi->more_rx_waiting=%d\n", __func__,
1171                                 wsi->more_rx_waiting);
1172
1173                 /* check for unwelcome guests */
1174
1175                 if (wsi->context->reject_service_keywords) {
1176                         const struct lws_protocol_vhost_options *rej =
1177                                         wsi->context->reject_service_keywords;
1178                         char ua[384], *msg = NULL;
1179
1180                         if (lws_hdr_copy(wsi, ua, sizeof(ua) - 1,
1181                                           WSI_TOKEN_HTTP_USER_AGENT) > 0) {
1182                                 ua[sizeof(ua) - 1] = '\0';
1183                                 while (rej) {
1184                                         if (strstr(ua, rej->name)) {
1185                                                 msg = strchr(rej->value, ' ');
1186                                                 if (msg)
1187                                                         msg++;
1188                                                 lws_return_http_status(wsi, atoi(rej->value), msg);
1189
1190                                                 wsi->vhost->conn_stats.rejected++;
1191
1192                                                 goto bail_nuke_ah;
1193                                         }
1194                                         rej = rej->next;
1195                                 }
1196                         }
1197                 }
1198
1199                 /* select vhost */
1200
1201                 if (lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) {
1202                         struct lws_vhost *vhost = lws_select_vhost(
1203                                 context, wsi->vhost->listen_port,
1204                                 lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST));
1205
1206                         if (vhost)
1207                                 wsi->vhost = vhost;
1208                 } else
1209                         lwsl_info("no host\n");
1210
1211                 wsi->vhost->conn_stats.trans++;
1212                 if (!wsi->conn_stat_done) {
1213                         wsi->vhost->conn_stats.conn++;
1214                         wsi->conn_stat_done = 1;
1215                 }
1216
1217                 wsi->mode = LWSCM_PRE_WS_SERVING_ACCEPT;
1218                 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1219
1220                 /* is this websocket protocol or normal http 1.0? */
1221
1222                 if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) {
1223                         if (!strcasecmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE),
1224                                         "websocket")) {
1225                                 wsi->vhost->conn_stats.ws_upg++;
1226                                 lwsl_info("Upgrade to ws\n");
1227                                 goto upgrade_ws;
1228                         }
1229 #ifdef LWS_USE_HTTP2
1230                         if (!strcasecmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE),
1231                                         "h2c")) {
1232                                 wsi->vhost->conn_stats.http2_upg++;
1233                                 lwsl_info("Upgrade to h2c\n");
1234                                 goto upgrade_h2c;
1235                         }
1236 #endif
1237                         lwsl_info("Unknown upgrade\n");
1238                         /* dunno what he wanted to upgrade to */
1239                         goto bail_nuke_ah;
1240                 }
1241
1242                 /* no upgrade ack... he remained as HTTP */
1243
1244                 lwsl_info("No upgrade\n");
1245                 ah = wsi->u.hdr.ah;
1246
1247                 lws_union_transition(wsi, LWSCM_HTTP_SERVING_ACCEPTED);
1248                 wsi->state = LWSS_HTTP;
1249                 wsi->u.http.fd = LWS_INVALID_FILE;
1250
1251                 /* expose it at the same offset as u.hdr */
1252                 wsi->u.http.ah = ah;
1253                 lwsl_debug("%s: wsi %p: ah %p\n", __func__, (void *)wsi,
1254                            (void *)wsi->u.hdr.ah);
1255
1256                 n = lws_http_action(wsi);
1257
1258                 return n;
1259
1260 #ifdef LWS_USE_HTTP2
1261 upgrade_h2c:
1262                 if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP2_SETTINGS)) {
1263                         lwsl_info("missing http2_settings\n");
1264                         goto bail_nuke_ah;
1265                 }
1266
1267                 lwsl_info("h2c upgrade...\n");
1268
1269                 p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP2_SETTINGS);
1270                 /* convert the peer's HTTP-Settings */
1271                 n = lws_b64_decode_string(p, protocol_list,
1272                                           sizeof(protocol_list));
1273                 if (n < 0) {
1274                         lwsl_parser("HTTP2_SETTINGS too long\n");
1275                         return 1;
1276                 }
1277
1278                 /* adopt the header info */
1279
1280                 ah = wsi->u.hdr.ah;
1281
1282                 lws_union_transition(wsi, LWSCM_HTTP2_SERVING);
1283
1284                 /* http2 union member has http union struct at start */
1285                 wsi->u.http.ah = ah;
1286
1287                 lws_http2_init(&wsi->u.http2.peer_settings);
1288                 lws_http2_init(&wsi->u.http2.my_settings);
1289
1290                 /* HTTP2 union */
1291
1292                 lws_http2_interpret_settings_payload(&wsi->u.http2.peer_settings,
1293                                 (unsigned char *)protocol_list, n);
1294
1295                 strcpy(protocol_list,
1296                        "HTTP/1.1 101 Switching Protocols\x0d\x0a"
1297                       "Connection: Upgrade\x0d\x0a"
1298                       "Upgrade: h2c\x0d\x0a\x0d\x0a");
1299                 n = lws_issue_raw(wsi, (unsigned char *)protocol_list,
1300                                         strlen(protocol_list));
1301                 if (n != strlen(protocol_list)) {
1302                         lwsl_debug("http2 switch: ERROR writing to socket\n");
1303                         return 1;
1304                 }
1305
1306                 wsi->state = LWSS_HTTP2_AWAIT_CLIENT_PREFACE;
1307
1308                 return 0;
1309 #endif
1310
1311 upgrade_ws:
1312                 if (!wsi->protocol)
1313                         lwsl_err("NULL protocol at lws_read\n");
1314
1315                 /*
1316                  * It's websocket
1317                  *
1318                  * Select the first protocol we support from the list
1319                  * the client sent us.
1320                  *
1321                  * Copy it to remove header fragmentation
1322                  */
1323
1324                 if (lws_hdr_copy(wsi, protocol_list, sizeof(protocol_list) - 1,
1325                                  WSI_TOKEN_PROTOCOL) < 0) {
1326                         lwsl_err("protocol list too long");
1327                         goto bail_nuke_ah;
1328                 }
1329
1330                 protocol_len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
1331                 protocol_list[protocol_len] = '\0';
1332                 p = protocol_list;
1333                 hit = 0;
1334
1335                 while (*p && !hit) {
1336                         n = 0;
1337                         while (n < sizeof(protocol_name) - 1 && *p && *p !=',')
1338                                 protocol_name[n++] = *p++;
1339                         protocol_name[n] = '\0';
1340                         if (*p)
1341                                 p++;
1342
1343                         lwsl_info("checking %s\n", protocol_name);
1344
1345                         n = 0;
1346                         while (wsi->vhost->protocols[n].callback) {
1347                                 lwsl_info("try %s\n", wsi->vhost->protocols[n].name);
1348
1349                                 if (wsi->vhost->protocols[n].name &&
1350                                     !strcmp(wsi->vhost->protocols[n].name,
1351                                             protocol_name)) {
1352                                         wsi->protocol = &wsi->vhost->protocols[n];
1353                                         hit = 1;
1354                                         break;
1355                                 }
1356
1357                                 n++;
1358                         }
1359                 }
1360
1361                 /* we didn't find a protocol he wanted? */
1362
1363                 if (!hit) {
1364                         if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL)) {
1365                                 lwsl_info("No protocol from \"%s\" supported\n",
1366                                          protocol_list);
1367                                 goto bail_nuke_ah;
1368                         }
1369                         /*
1370                          * some clients only have one protocol and
1371                          * do not send the protocol list header...
1372                          * allow it and match to the vhost's default
1373                          * protocol (which itself defaults to zero)
1374                          */
1375                         lwsl_info("defaulting to prot handler %d\n",
1376                                 wsi->vhost->default_protocol_index);
1377                         n = 0;
1378                         wsi->protocol = &wsi->vhost->protocols[
1379                                       (int)wsi->vhost->default_protocol_index];
1380                 }
1381
1382                 /* allocate wsi->user storage */
1383                 if (lws_ensure_user_space(wsi))
1384                         goto bail_nuke_ah;
1385
1386                 /*
1387                  * Give the user code a chance to study the request and
1388                  * have the opportunity to deny it
1389                  */
1390                 if ((wsi->protocol->callback)(wsi,
1391                                 LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
1392                                 wsi->user_space,
1393                               lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL), 0)) {
1394                         lwsl_warn("User code denied connection\n");
1395                         goto bail_nuke_ah;
1396                 }
1397
1398                 /*
1399                  * Perform the handshake according to the protocol version the
1400                  * client announced
1401                  */
1402
1403                 switch (wsi->ietf_spec_revision) {
1404                 case 13:
1405                         lwsl_parser("lws_parse calling handshake_04\n");
1406                         if (handshake_0405(context, wsi)) {
1407                                 lwsl_info("hs0405 has failed the connection\n");
1408                                 goto bail_nuke_ah;
1409                         }
1410                         break;
1411
1412                 default:
1413                         lwsl_info("Unknown client spec version %d\n",
1414                                   wsi->ietf_spec_revision);
1415                         goto bail_nuke_ah;
1416                 }
1417
1418                 /*
1419                  * stitch protocol choice into the vh protocol linked list
1420                  * We always insert ourselves at the start of the list
1421                  *
1422                  * X <-> B
1423                  * X <-> pAn <-> pB
1424                  */
1425                 //lwsl_err("%s: pre insert vhost start wsi %p, that wsi prev == %p\n",
1426                 //              __func__,
1427                 //              wsi->vhost->same_vh_protocol_list[n],
1428                 //              wsi->same_vh_protocol_prev);
1429                 wsi->same_vh_protocol_prev = /* guy who points to us */
1430                         &wsi->vhost->same_vh_protocol_list[n];
1431                 wsi->same_vh_protocol_next = /* old first guy is our next */
1432                                 wsi->vhost->same_vh_protocol_list[n];
1433                 /* we become the new first guy */
1434                 wsi->vhost->same_vh_protocol_list[n] = wsi;
1435
1436                 if (wsi->same_vh_protocol_next)
1437                         /* old first guy points back to us now */
1438                         wsi->same_vh_protocol_next->same_vh_protocol_prev =
1439                                         &wsi->same_vh_protocol_next;
1440
1441
1442
1443                 /* we are upgrading to ws, so http/1.1 and keepalive +
1444                  * pipelined header considerations about keeping the ah around
1445                  * no longer apply.  However it's common for the first ws
1446                  * protocol data to have been coalesced with the browser
1447                  * upgrade request and to already be in the ah rx buffer.
1448                  */
1449
1450                 lwsl_info("%s: %p: inheriting ah in ws mode (rxpos:%d, rxlen:%d)\n",
1451                           __func__, wsi, wsi->u.hdr.ah->rxpos,
1452                           wsi->u.hdr.ah->rxlen);
1453                 lws_pt_lock(pt);
1454                 hdr = wsi->u.hdr;
1455
1456                 lws_union_transition(wsi, LWSCM_WS_SERVING);
1457                 /*
1458                  * first service is WS mode will notice this, use the RX and
1459                  * then detach the ah (caution: we are not in u.hdr union
1460                  * mode any more then... ah_temp member is at start the same
1461                  * though)
1462                  *
1463                  * Because rxpos/rxlen shows something in the ah, we will get
1464                  * service guaranteed next time around the event loop
1465                  *
1466                  * All union members begin with hdr, so we can use it even
1467                  * though we transitioned to ws union mode (the ah detach
1468                  * code uses it anyway).
1469                  */
1470                 wsi->u.hdr = hdr;
1471                 lws_pt_unlock(pt);
1472
1473                 lws_restart_ws_ping_pong_timer(wsi);
1474
1475                 /*
1476                  * create the frame buffer for this connection according to the
1477                  * size mentioned in the protocol definition.  If 0 there, use
1478                  * a big default for compatibility
1479                  */
1480
1481                 n = wsi->protocol->rx_buffer_size;
1482                 if (!n)
1483                         n = context->pt_serv_buf_size;
1484                 n += LWS_PRE;
1485                 wsi->u.ws.rx_ubuf = lws_malloc(n + 4 /* 0x0000ffff zlib */);
1486                 if (!wsi->u.ws.rx_ubuf) {
1487                         lwsl_err("Out of Mem allocating rx buffer %d\n", n);
1488                         return 1;
1489                 }
1490                 wsi->u.ws.rx_ubuf_alloc = n;
1491                 lwsl_debug("Allocating RX buffer %d\n", n);
1492 #if LWS_POSIX
1493                 if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF,
1494                                (const char *)&n, sizeof n)) {
1495                         lwsl_warn("Failed to set SNDBUF to %d", n);
1496                         return 1;
1497                 }
1498 #endif
1499
1500                 lwsl_parser("accepted v%02d connection\n",
1501                             wsi->ietf_spec_revision);
1502
1503                 /* notify user code that we're ready to roll */
1504
1505                 if (wsi->protocol->callback)
1506                         if (wsi->protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED,
1507                                                     wsi->user_space,
1508 #ifdef LWS_OPENSSL_SUPPORT
1509                                                     wsi->ssl,
1510 #else
1511                                                     NULL,
1512 #endif
1513                                                     0))
1514                                 return 1;
1515
1516                 /* !!! drop ah unreservedly after ESTABLISHED */
1517                 if (!wsi->more_rx_waiting) {
1518                         wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
1519
1520                         //lwsl_notice("%p: dropping ah EST\n", wsi);
1521                         lws_header_table_detach(wsi, 1);
1522                 }
1523
1524                 return 0;
1525         } /* while all chars are handled */
1526
1527         return 0;
1528
1529 bail_nuke_ah:
1530         /* drop the header info */
1531         /* we're closing, losing some rx is OK */
1532         wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
1533         //lwsl_notice("%s: drop2\n", __func__);
1534         lws_header_table_detach(wsi, 1);
1535
1536         return 1;
1537 }
1538
1539 static int
1540 lws_get_idlest_tsi(struct lws_context *context)
1541 {
1542         unsigned int lowest = ~0;
1543         int n = 0, hit = -1;
1544
1545         for (; n < context->count_threads; n++) {
1546                 if ((unsigned int)context->pt[n].fds_count !=
1547                     context->fd_limit_per_thread - 1 &&
1548                     (unsigned int)context->pt[n].fds_count < lowest) {
1549                         lowest = context->pt[n].fds_count;
1550                         hit = n;
1551                 }
1552         }
1553
1554         return hit;
1555 }
1556
1557 struct lws *
1558 lws_create_new_server_wsi(struct lws_vhost *vhost)
1559 {
1560         struct lws *new_wsi;
1561         int n = lws_get_idlest_tsi(vhost->context);
1562
1563         if (n < 0) {
1564                 lwsl_err("no space for new conn\n");
1565                 return NULL;
1566         }
1567
1568         new_wsi = lws_zalloc(sizeof(struct lws));
1569         if (new_wsi == NULL) {
1570                 lwsl_err("Out of memory for new connection\n");
1571                 return NULL;
1572         }
1573
1574         new_wsi->tsi = n;
1575         lwsl_notice("Accepted wsi %p to context %p, tsi %d\n", new_wsi,
1576                     vhost->context, new_wsi->tsi);
1577
1578         new_wsi->vhost = vhost;
1579         new_wsi->context = vhost->context;
1580         new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
1581         new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
1582
1583         /* initialize the instance struct */
1584
1585         new_wsi->state = LWSS_HTTP;
1586         new_wsi->mode = LWSCM_HTTP_SERVING;
1587         new_wsi->hdr_parsing_completed = 0;
1588
1589 #ifdef LWS_OPENSSL_SUPPORT
1590         new_wsi->use_ssl = LWS_SSL_ENABLED(vhost);
1591 #endif
1592
1593         /*
1594          * these can only be set once the protocol is known
1595          * we set an unestablished connection's protocol pointer
1596          * to the start of the supported list, so it can look
1597          * for matching ones during the handshake
1598          */
1599         new_wsi->protocol = vhost->protocols;
1600         new_wsi->user_space = NULL;
1601         new_wsi->ietf_spec_revision = 0;
1602         new_wsi->sock = LWS_SOCK_INVALID;
1603         vhost->context->count_wsi_allocated++;
1604
1605         /*
1606          * outermost create notification for wsi
1607          * no user_space because no protocol selection
1608          */
1609         vhost->protocols[0].callback(new_wsi, LWS_CALLBACK_WSI_CREATE,
1610                                        NULL, NULL, 0);
1611
1612         return new_wsi;
1613 }
1614
1615 LWS_VISIBLE int LWS_WARN_UNUSED_RESULT
1616 lws_http_transaction_completed(struct lws *wsi)
1617 {
1618         int n = NO_PENDING_TIMEOUT;
1619
1620         lws_access_log(wsi);
1621
1622         lwsl_info("%s: wsi %p\n", __func__, wsi);
1623         /* if we can't go back to accept new headers, drop the connection */
1624         if (wsi->u.http.connection_type != HTTP_CONNECTION_KEEP_ALIVE) {
1625                 lwsl_info("%s: %p: close connection\n", __func__, wsi);
1626                 return 1;
1627         }
1628
1629         if (lws_bind_protocol(wsi, &wsi->vhost->protocols[0]))
1630                 return 1;
1631
1632         /* otherwise set ourselves up ready to go again */
1633         wsi->state = LWSS_HTTP;
1634         wsi->mode = LWSCM_HTTP_SERVING;
1635         wsi->u.http.content_length = 0;
1636         wsi->u.http.content_remain = 0;
1637         wsi->hdr_parsing_completed = 0;
1638 #ifdef LWS_WITH_ACCESS_LOG
1639         wsi->access_log.sent = 0;
1640 #endif
1641
1642         if (wsi->vhost->keepalive_timeout)
1643                 n = PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE;
1644         lws_set_timeout(wsi, n, wsi->vhost->keepalive_timeout);
1645
1646         /*
1647          * We already know we are on http1.1 / keepalive and the next thing
1648          * coming will be another header set.
1649          *
1650          * If there is no pending rx and we still have the ah, drop it and
1651          * reacquire a new ah when the new headers start to arrive.  (Otherwise
1652          * we needlessly hog an ah indefinitely.)
1653          *
1654          * However if there is pending rx and we know from the keepalive state
1655          * that is already at least the start of another header set, simply
1656          * reset the existing header table and keep it.
1657          */
1658         if (wsi->u.hdr.ah) {
1659                 lwsl_info("%s: wsi->more_rx_waiting=%d\n", __func__,
1660                                 wsi->more_rx_waiting);
1661
1662                 if (!wsi->more_rx_waiting) {
1663                         wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
1664                         lws_header_table_detach(wsi, 1);
1665                 } else
1666                         lws_header_table_reset(wsi, 1);
1667         }
1668
1669         /* If we're (re)starting on headers, need other implied init */
1670         wsi->u.hdr.ues = URIES_IDLE;
1671
1672         lwsl_info("%s: %p: keep-alive await new transaction\n", __func__, wsi);
1673
1674         return 0;
1675 }
1676
1677 LWS_VISIBLE struct lws *
1678 lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd)
1679 {
1680         struct lws_context *context = vh->context;
1681         struct lws *new_wsi = lws_create_new_server_wsi(vh);
1682
1683         if (!new_wsi) {
1684                 compatible_close(accept_fd);
1685                 return NULL;
1686         }
1687
1688         //lwsl_notice("%s: new wsi %p, sockfd %d, cb %p\n", __func__, new_wsi, accept_fd, context->vhost_list->protocols[0].callback);
1689
1690         new_wsi->sock = accept_fd;
1691
1692         /* the transport is accepted... give him time to negotiate */
1693         lws_set_timeout(new_wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
1694                         context->timeout_secs);
1695
1696 #if LWS_POSIX == 0
1697 #if defined(LWS_WITH_ESP8266)
1698         esp8266_tcp_stream_accept(accept_fd, new_wsi);
1699 #else
1700         mbed3_tcp_stream_accept(accept_fd, new_wsi);
1701 #endif
1702 #endif
1703         /*
1704          * A new connection was accepted. Give the user a chance to
1705          * set properties of the newly created wsi. There's no protocol
1706          * selected yet so we issue this to protocols[0]
1707          */
1708         if ((context->vhost_list->protocols[0].callback)(new_wsi,
1709              LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED, NULL, NULL, 0)) {
1710                 /* force us off the timeout list by hand */
1711                 lws_set_timeout(new_wsi, NO_PENDING_TIMEOUT, 0);
1712                 compatible_close(new_wsi->sock);
1713                 lws_free(new_wsi);
1714                 return NULL;
1715         }
1716
1717         lws_libev_accept(new_wsi, new_wsi->sock);
1718         lws_libuv_accept(new_wsi, new_wsi->sock);
1719
1720         if (!LWS_SSL_ENABLED(new_wsi->vhost)) {
1721                 if (insert_wsi_socket_into_fds(context, new_wsi)) {
1722                         lwsl_err("%s: fail inserting socket\n", __func__);
1723                         goto fail;
1724                 }
1725         } else {
1726                 new_wsi->mode = LWSCM_SSL_INIT;
1727                 if (lws_server_socket_service_ssl(new_wsi, accept_fd)) {
1728                         lwsl_err("%s: fail ssl negotiation\n", __func__);
1729                         goto fail;
1730                 }
1731         }
1732
1733         if (!lws_header_table_attach(new_wsi, 0))
1734                 lwsl_debug("Attached ah immediately\n");
1735
1736         return new_wsi;
1737
1738 fail:
1739         lws_close_free_wsi(new_wsi, LWS_CLOSE_STATUS_NOSTATUS);
1740
1741         return NULL;
1742 }
1743
1744 LWS_VISIBLE struct lws *
1745 lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd)
1746 {
1747         return lws_adopt_socket_vhost(context->vhost_list, accept_fd);
1748 }
1749
1750 /* Common read-buffer adoption for lws_adopt_*_readbuf */
1751 static struct lws*
1752 adopt_socket_readbuf(struct lws *wsi, const char *readbuf, size_t len)
1753 {
1754         struct lws_context_per_thread *pt;
1755         struct allocated_headers *ah;
1756         struct lws_pollfd *pfd;
1757
1758         if (!wsi)
1759                 return NULL;
1760
1761         if (!readbuf || len == 0)
1762                 return wsi;
1763
1764         if (len > sizeof(ah->rx)) {
1765                 lwsl_err("%s: rx in too big\n", __func__);
1766                 goto bail;
1767         }
1768
1769         /*
1770          * we can't process the initial read data until we can attach an ah.
1771          *
1772          * if one is available, get it and place the data in his ah rxbuf...
1773          * wsi with ah that have pending rxbuf get auto-POLLIN service.
1774          *
1775          * no autoservice because we didn't get a chance to attach the
1776          * readbuf data to wsi or ah yet, and we will do it next if we get
1777          * the ah.
1778          */
1779         if (wsi->u.hdr.ah || !lws_header_table_attach(wsi, 0)) {
1780                 ah = wsi->u.hdr.ah;
1781                 memcpy(ah->rx, readbuf, len);
1782                 ah->rxpos = 0;
1783                 ah->rxlen = len;
1784
1785                 lwsl_notice("%s: calling service on readbuf ah\n", __func__);
1786                 pt = &wsi->context->pt[(int)wsi->tsi];
1787
1788                 /* unlike a normal connect, we have the headers already
1789                  * (or the first part of them anyway).
1790                  * libuv won't come back and service us without a network
1791                  * event, so we need to do the header service right here.
1792                  */
1793                 pfd = &pt->fds[wsi->position_in_fds_table];
1794                 pfd->revents |= LWS_POLLIN;
1795                 lwsl_err("%s: calling service\n", __func__);
1796                 if (lws_service_fd_tsi(wsi->context, pfd, wsi->tsi))
1797                         /* service closed us */
1798                         return NULL;
1799
1800                 return wsi;
1801         }
1802         lwsl_err("%s: deferring handling ah\n", __func__);
1803         /*
1804          * hum if no ah came, we are on the wait list and must defer
1805          * dealing with this until the ah arrives.
1806          *
1807          * later successful lws_header_table_attach() will apply the
1808          * below to the rx buffer (via lws_header_table_reset()).
1809          */
1810         wsi->u.hdr.preamble_rx = lws_malloc(len);
1811         if (!wsi->u.hdr.preamble_rx) {
1812                 lwsl_err("OOM\n");
1813                 goto bail;
1814         }
1815         memcpy(wsi->u.hdr.preamble_rx, readbuf, len);
1816         wsi->u.hdr.preamble_rx_len = len;
1817
1818         return wsi;
1819
1820 bail:
1821         lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
1822
1823         return NULL;
1824 }
1825
1826 LWS_VISIBLE struct lws *
1827 lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd,
1828                          const char *readbuf, size_t len)
1829 {
1830         return adopt_socket_readbuf(lws_adopt_socket(context, accept_fd), readbuf, len);
1831 }
1832
1833 LWS_VISIBLE struct lws *
1834 lws_adopt_socket_vhost_readbuf(struct lws_vhost *vhost, lws_sockfd_type accept_fd,
1835                          const char *readbuf, size_t len)
1836 {
1837         return adopt_socket_readbuf(lws_adopt_socket_vhost(vhost, accept_fd), readbuf, len);
1838 }
1839
1840 LWS_VISIBLE int
1841 lws_server_socket_service(struct lws_context *context, struct lws *wsi,
1842                           struct lws_pollfd *pollfd)
1843 {
1844         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
1845         lws_sockfd_type accept_fd = LWS_SOCK_INVALID;
1846         struct allocated_headers *ah;
1847 #if LWS_POSIX
1848         struct sockaddr_in cli_addr;
1849         socklen_t clilen;
1850 #endif
1851         int n, len;
1852         
1853         // lwsl_notice("%s: mode %d\n", __func__, wsi->mode);
1854
1855         switch (wsi->mode) {
1856
1857         case LWSCM_HTTP_SERVING:
1858         case LWSCM_HTTP_SERVING_ACCEPTED:
1859         case LWSCM_HTTP2_SERVING:
1860
1861                 /* handle http headers coming in */
1862
1863                 /* pending truncated sends have uber priority */
1864
1865                 if (wsi->trunc_len) {
1866                         if (!(pollfd->revents & LWS_POLLOUT))
1867                                 break;
1868
1869                         if (lws_issue_raw(wsi, wsi->trunc_alloc +
1870                                                wsi->trunc_offset,
1871                                           wsi->trunc_len) < 0)
1872                                 goto fail;
1873                         /*
1874                          * we can't afford to allow input processing to send
1875                          * something new, so spin around he event loop until
1876                          * he doesn't have any partials
1877                          */
1878                         break;
1879                 }
1880
1881                 /* any incoming data ready? */
1882
1883                 if (!(pollfd->revents & pollfd->events & LWS_POLLIN))
1884                         goto try_pollout;
1885
1886                 /*
1887                  * If we previously just did POLLIN when IN and OUT were
1888                  * signalled (because POLLIN processing may have used up
1889                  * the POLLOUT), don't let that happen twice in a row...
1890                  * next time we see the situation favour POLLOUT
1891                  */
1892 #if !defined(LWS_WITH_ESP8266)
1893                 if (wsi->favoured_pollin &&
1894                     (pollfd->revents & pollfd->events & LWS_POLLOUT)) {
1895                         wsi->favoured_pollin = 0;
1896                         goto try_pollout;
1897                 }
1898 #endif
1899                 /* these states imply we MUST have an ah attached */
1900
1901                 if (wsi->state == LWSS_HTTP ||
1902                     wsi->state == LWSS_HTTP_ISSUING_FILE ||
1903                     wsi->state == LWSS_HTTP_HEADERS) {
1904                         if (!wsi->u.hdr.ah) {
1905                                 
1906                                 //lwsl_err("wsi %p: missing ah\n", wsi);
1907                                 /* no autoservice beacuse we will do it next */
1908                                 if (lws_header_table_attach(wsi, 0)) {
1909                                         lwsl_err("wsi %p: failed to acquire ah\n", wsi);
1910                                         goto try_pollout;
1911                                 }
1912                         }
1913                         ah = wsi->u.hdr.ah;
1914
1915                         //lwsl_notice("%s: %p: rxpos:%d rxlen:%d\n", __func__, wsi,
1916                         //         ah->rxpos, ah->rxlen);
1917
1918                         /* if nothing in ah rx buffer, get some fresh rx */
1919                         if (ah->rxpos == ah->rxlen) {
1920                                 ah->rxlen = lws_ssl_capable_read(wsi, ah->rx,
1921                                                    sizeof(ah->rx));
1922                                 ah->rxpos = 0;
1923                                 //lwsl_notice("%s: wsi %p, ah->rxlen = %d\r\n",
1924                                 //         __func__, wsi, ah->rxlen);
1925                                 switch (ah->rxlen) {
1926                                 case 0:
1927                                         lwsl_info("%s: read 0 len\n", __func__);
1928                                         /* lwsl_info("   state=%d\n", wsi->state); */
1929 //                                      if (!wsi->hdr_parsing_completed)
1930 //                                              lws_header_table_detach(wsi);
1931                                         /* fallthru */
1932                                 case LWS_SSL_CAPABLE_ERROR:
1933                                         goto fail;
1934                                 case LWS_SSL_CAPABLE_MORE_SERVICE:
1935                                         ah->rxlen = ah->rxpos = 0;
1936                                         goto try_pollout;
1937                                 }
1938                         }
1939
1940                         if (!(ah->rxpos != ah->rxlen && ah->rxlen)) {
1941                                 lwsl_err("%s: assert: rxpos %d, rxlen %d\n",
1942                                          __func__, ah->rxpos, ah->rxlen);
1943
1944                                 assert(0);
1945                         }
1946                         
1947                         /* just ignore incoming if waiting for close */
1948                         if (wsi->state != LWSS_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
1949                                 n = lws_read(wsi, ah->rx + ah->rxpos,
1950                                              ah->rxlen - ah->rxpos);
1951                                 if (n < 0) /* we closed wsi */
1952                                         return 1;
1953                                 if (wsi->u.hdr.ah) {
1954                                         if ( wsi->u.hdr.ah->rxlen)
1955                                                  wsi->u.hdr.ah->rxpos += n;
1956
1957                                         lwsl_debug("%s: wsi %p: ah read rxpos %d, rxlen %d\n", __func__, wsi, wsi->u.hdr.ah->rxpos, wsi->u.hdr.ah->rxlen);
1958
1959                                         if (wsi->u.hdr.ah->rxpos == wsi->u.hdr.ah->rxlen &&
1960                                             (wsi->mode != LWSCM_HTTP_SERVING &&
1961                                              wsi->mode != LWSCM_HTTP_SERVING_ACCEPTED &&
1962                                              wsi->mode != LWSCM_HTTP2_SERVING))
1963                                                 lws_header_table_detach(wsi, 1);
1964                                 }
1965                                 break;
1966                         }
1967
1968                         goto try_pollout;
1969                 }
1970
1971                 len = lws_ssl_capable_read(wsi, pt->serv_buf,
1972                                            context->pt_serv_buf_size);
1973                 lwsl_notice("%s: wsi %p read %d\r\n", __func__, wsi, len);
1974                 switch (len) {
1975                 case 0:
1976                         lwsl_info("%s: read 0 len\n", __func__);
1977                         /* lwsl_info("   state=%d\n", wsi->state); */
1978 //                      if (!wsi->hdr_parsing_completed)
1979 //                              lws_header_table_detach(wsi);
1980                         /* fallthru */
1981                 case LWS_SSL_CAPABLE_ERROR:
1982                         goto fail;
1983                 case LWS_SSL_CAPABLE_MORE_SERVICE:
1984                         goto try_pollout;
1985                 }
1986                 
1987                 /* just ignore incoming if waiting for close */
1988                 if (wsi->state != LWSS_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
1989                         /*
1990                          * this may want to send
1991                          * (via HTTP callback for example)
1992                          */
1993                         n = lws_read(wsi, pt->serv_buf, len);
1994                         if (n < 0) /* we closed wsi */
1995                                 return 1;
1996                         /*
1997                          *  he may have used up the
1998                          * writability above, if we will defer POLLOUT
1999                          * processing in favour of POLLIN, note it
2000                          */
2001                         if (pollfd->revents & LWS_POLLOUT)
2002                                 wsi->favoured_pollin = 1;
2003                         break;
2004                 }
2005
2006 try_pollout:
2007                 
2008                 /* this handles POLLOUT for http serving fragments */
2009
2010                 if (!(pollfd->revents & LWS_POLLOUT))
2011                         break;
2012
2013                 /* one shot */
2014                 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
2015                         lwsl_notice("%s a\n", __func__);
2016                         goto fail;
2017                 }
2018
2019                 if (!wsi->hdr_parsing_completed)
2020                         break;
2021
2022                 if (wsi->state != LWSS_HTTP_ISSUING_FILE) {
2023                         n = user_callback_handle_rxflow(wsi->protocol->callback,
2024                                         wsi, LWS_CALLBACK_HTTP_WRITEABLE,
2025                                         wsi->user_space, NULL, 0);
2026                         if (n < 0) {
2027                                 lwsl_info("writeable_fail\n");
2028                                 goto fail;
2029                         }
2030                         break;
2031                 }
2032
2033                 /* >0 == completion, <0 == error */
2034                 n = lws_serve_http_file_fragment(wsi);
2035                 if (n < 0 || (n > 0 && lws_http_transaction_completed(wsi))) {
2036                         lwsl_info("completed\n");
2037                         goto fail;
2038                 }
2039
2040                 break;
2041
2042         case LWSCM_SERVER_LISTENER:
2043
2044 #if LWS_POSIX
2045                 /* pollin means a client has connected to us then */
2046
2047                 do {
2048                         if (!(pollfd->revents & LWS_POLLIN) || !(pollfd->events & LWS_POLLIN))
2049                                 break;
2050
2051                         /* listen socket got an unencrypted connection... */
2052
2053                         clilen = sizeof(cli_addr);
2054                         lws_latency_pre(context, wsi);
2055                         accept_fd  = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
2056                                             &clilen);
2057                         lws_latency(context, wsi, "listener accept", accept_fd,
2058                                     accept_fd >= 0);
2059                         if (accept_fd < 0) {
2060                                 if (LWS_ERRNO == LWS_EAGAIN ||
2061                                     LWS_ERRNO == LWS_EWOULDBLOCK) {
2062                                         lwsl_err("accept asks to try again\n");
2063                                         break;
2064                                 }
2065                                 lwsl_err("ERROR on accept: %s\n", strerror(LWS_ERRNO));
2066                                 break;
2067                         }
2068
2069                         lws_plat_set_socket_options(wsi->vhost, accept_fd);
2070
2071                         lwsl_debug("accepted new conn  port %u on fd=%d\n",
2072                                           ntohs(cli_addr.sin_port), accept_fd);
2073
2074 #else
2075                         /* not very beautiful... */
2076                         accept_fd = (lws_sockfd_type)pollfd;
2077 #endif
2078                         /*
2079                          * look at who we connected to and give user code a chance
2080                          * to reject based on client IP.  There's no protocol selected
2081                          * yet so we issue this to protocols[0]
2082                          */
2083                         if ((wsi->vhost->protocols[0].callback)(wsi,
2084                                         LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
2085                                         NULL, (void *)(long)accept_fd, 0)) {
2086                                 lwsl_debug("Callback denied network connection\n");
2087                                 compatible_close(accept_fd);
2088                                 break;
2089                         }
2090
2091                         if (!lws_adopt_socket_vhost(wsi->vhost, accept_fd))
2092                                 /* already closed cleanly as necessary */
2093                                 return 1;
2094
2095 #if LWS_POSIX
2096                 } while (pt->fds_count < context->fd_limit_per_thread - 1 &&
2097                          lws_poll_listen_fd(&pt->fds[wsi->position_in_fds_table]) > 0);
2098 #endif
2099                 return 0;
2100
2101         default:
2102                 break;
2103         }
2104
2105         if (!lws_server_socket_service_ssl(wsi, accept_fd))
2106                 return 0;
2107
2108 fail:
2109         lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
2110
2111         return 1;
2112 }
2113
2114 LWS_VISIBLE int
2115 lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type,
2116                     const char *other_headers, int other_headers_len)
2117 {
2118         static const char * const intermediates[] = { "private", "public" };
2119         struct lws_context *context = lws_get_context(wsi);
2120         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
2121 #if defined(LWS_WITH_RANGES)
2122         struct lws_range_parsing *rp = &wsi->u.http.range;
2123 #endif
2124         char cache_control[50], *cc = "no-store";
2125         unsigned char *response = pt->serv_buf + LWS_PRE;
2126         unsigned char *p = response;
2127         unsigned char *end = p + context->pt_serv_buf_size - LWS_PRE;
2128         unsigned long computed_total_content_length;
2129         int ret = 0, cclen = 8, n = HTTP_STATUS_OK;
2130 #if defined(LWS_WITH_RANGES)
2131         int ranges;
2132 #endif
2133
2134         wsi->u.http.fd = lws_plat_file_open(wsi, file, &wsi->u.http.filelen,
2135                                             O_RDONLY);
2136
2137         if (wsi->u.http.fd == LWS_INVALID_FILE) {
2138                 lwsl_err("Unable to open '%s'\n", file);
2139
2140                 return -1;
2141         }
2142         computed_total_content_length = wsi->u.http.filelen;
2143
2144 #if defined(LWS_WITH_RANGES)
2145         ranges = lws_ranges_init(wsi, rp, wsi->u.http.filelen);
2146
2147         lwsl_debug("Range count %d\n", ranges);
2148         /*
2149          * no ranges -> 200;
2150          *  1 range  -> 206 + Content-Type: normal; Content-Range;
2151          *  more     -> 206 + Content-Type: multipart/byteranges
2152          *              Repeat the true Content-Type in each multipart header
2153          *              along with Content-Range
2154          */
2155         if (ranges < 0) {
2156                 /* it means he expressed a range in Range:, but it was illegal */
2157                 lws_return_http_status(wsi, HTTP_STATUS_REQ_RANGE_NOT_SATISFIABLE, NULL);
2158                 if (lws_http_transaction_completed(wsi))
2159                         return -1; /* <0 means just hang up */
2160
2161                 return 0; /* == 0 means we dealt with the transaction complete */
2162         }
2163         if (ranges)
2164                 n = HTTP_STATUS_PARTIAL_CONTENT;
2165 #endif
2166
2167         if (lws_add_http_header_status(wsi, n, &p, end))
2168                 return -1;
2169
2170 #if defined(LWS_WITH_RANGES)
2171         if (ranges < 2 && content_type && content_type[0])
2172                 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
2173                                                  (unsigned char *)content_type,
2174                                                  strlen(content_type), &p, end))
2175                         return -1;
2176
2177         if (ranges >= 2) { /* multipart byteranges */
2178                 strncpy(wsi->u.http.multipart_content_type, content_type,
2179                         sizeof(wsi->u.http.multipart_content_type) - 1);
2180                 wsi->u.http.multipart_content_type[
2181                          sizeof(wsi->u.http.multipart_content_type) - 1] = '\0';
2182                 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
2183                                                  (unsigned char *)"multipart/byteranges; boundary=_lws",
2184                                                  20, &p, end))
2185                         return -1;
2186
2187                 /*
2188                  *  our overall content length has to include
2189                  *
2190                  *  - (n + 1) x "_lws\r\n"
2191                  *  - n x Content-Type: xxx/xxx\r\n
2192                  *  - n x Content-Range: bytes xxx-yyy/zzz\r\n
2193                  *  - n x /r/n
2194                  *  - the actual payloads (aggregated in rp->agg)
2195                  *
2196                  *  Precompute it for the main response header
2197                  */
2198
2199                 computed_total_content_length = (unsigned long)rp->agg +
2200                                                 6 /* final _lws\r\n */;
2201
2202                 lws_ranges_reset(rp);
2203                 while (lws_ranges_next(rp)) {
2204                         n = lws_snprintf(cache_control, sizeof(cache_control),
2205                                         "bytes %llu-%llu/%llu",
2206                                         rp->start, rp->end, rp->extent);
2207
2208                         computed_total_content_length +=
2209                                         6 /* header _lws\r\n */ +
2210                                         14 + strlen(content_type) + 2 + /* Content-Type: xxx/xxx\r\n */
2211                                         15 + n + 2 + /* Content-Range: xxxx\r\n */
2212                                         2; /* /r/n */
2213                 }
2214
2215                 lws_ranges_reset(rp);
2216                 lws_ranges_next(rp);
2217         }
2218
2219         if (ranges == 1) {
2220                 computed_total_content_length = (unsigned long)rp->agg;
2221                 n = lws_snprintf(cache_control, sizeof(cache_control), "bytes %llu-%llu/%llu",
2222                                 rp->start, rp->end, rp->extent);
2223
2224                 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_RANGE,
2225                                                  (unsigned char *)cache_control,
2226                                                  n, &p, end))
2227                         return -1;
2228         }
2229
2230         wsi->u.http.range.inside = 0;
2231
2232         if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_ACCEPT_RANGES,
2233                                          (unsigned char *)"bytes", 5, &p, end))
2234                 return -1;
2235 #endif
2236
2237         if (!wsi->sending_chunked) {
2238                 if (lws_add_http_header_content_length(wsi,
2239                                                        computed_total_content_length,
2240                                                        &p, end))
2241                         return -1;
2242         } else {
2243                 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_TRANSFER_ENCODING,
2244                                                  (unsigned char *)"chunked",
2245                                                  7, &p, end))
2246                         return -1;
2247         }
2248
2249         if (wsi->cache_secs && wsi->cache_reuse) {
2250                 if (wsi->cache_revalidate) {
2251                         cc = cache_control;
2252                         cclen = sprintf(cache_control, "%s max-age: %u",
2253                                     intermediates[wsi->cache_intermediaries],
2254                                     wsi->cache_secs);
2255                 } else {
2256                         cc = "no-cache";
2257                         cclen = 8;
2258                 }
2259         }
2260
2261         if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CACHE_CONTROL,
2262                         (unsigned char *)cc, cclen, &p, end))
2263                 return -1;
2264
2265         if (wsi->u.http.connection_type == HTTP_CONNECTION_KEEP_ALIVE)
2266                 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION,
2267                                 (unsigned char *)"keep-alive", 10, &p, end))
2268                         return -1;
2269
2270         if (other_headers) {
2271                 if ((end - p) < other_headers_len)
2272                         return -1;
2273                 memcpy(p, other_headers, other_headers_len);
2274                 p += other_headers_len;
2275         }
2276
2277         if (lws_finalize_http_header(wsi, &p, end))
2278                 return -1;
2279
2280         ret = lws_write(wsi, response, p - response, LWS_WRITE_HTTP_HEADERS);
2281         if (ret != (p - response)) {
2282                 lwsl_err("_write returned %d from %d\n", ret, (p - response));
2283                 return -1;
2284         }
2285
2286         wsi->u.http.filepos = 0;
2287         wsi->state = LWSS_HTTP_ISSUING_FILE;
2288
2289         return lws_serve_http_file_fragment(wsi);
2290 }
2291
2292 int
2293 lws_interpret_incoming_packet(struct lws *wsi, unsigned char **buf, size_t len)
2294 {
2295         int m;
2296
2297         lwsl_parser("%s: received %d byte packet\n", __func__, (int)len);
2298 #if 0
2299         lwsl_hexdump(*buf, len);
2300 #endif
2301
2302         /* let the rx protocol state machine have as much as it needs */
2303
2304         while (len) {
2305                 /*
2306                  * we were accepting input but now we stopped doing so
2307                  */
2308                 if (!(wsi->rxflow_change_to & LWS_RXFLOW_ALLOW)) {
2309                         lws_rxflow_cache(wsi, *buf, 0, len);
2310                         lwsl_parser("%s: cached %d\n", __func__, len);
2311                         return 1;
2312                 }
2313
2314                 if (wsi->u.ws.rx_draining_ext) {
2315                         m = lws_rx_sm(wsi, 0);
2316                         if (m < 0)
2317                                 return -1;
2318                         continue;
2319                 }
2320
2321                 /* account for what we're using in rxflow buffer */
2322                 if (wsi->rxflow_buffer)
2323                         wsi->rxflow_pos++;
2324
2325                 /* consume payload bytes efficiently */
2326                 if (wsi->lws_rx_parse_state ==
2327                     LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED) {
2328                         m = lws_payload_until_length_exhausted(wsi, buf, &len);
2329                         if (wsi->rxflow_buffer)
2330                                 wsi->rxflow_pos += m;
2331                 }
2332
2333                 /* process the byte */
2334                 m = lws_rx_sm(wsi, *(*buf)++);
2335                 if (m < 0)
2336                         return -1;
2337                 len--;
2338         }
2339
2340         lwsl_parser("%s: exit with %d unused\n", __func__, (int)len);
2341
2342         return 0;
2343 }
2344
2345 LWS_VISIBLE void
2346 lws_server_get_canonical_hostname(struct lws_context *context,
2347                                   struct lws_context_creation_info *info)
2348 {
2349         if (lws_check_opt(info->options, LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME))
2350                 return;
2351 #if LWS_POSIX
2352         /* find canonical hostname */
2353         gethostname((char *)context->canonical_hostname,
2354                     sizeof(context->canonical_hostname) - 1);
2355
2356         lwsl_notice(" canonical_hostname = %s\n", context->canonical_hostname);
2357 #else
2358         (void)context;
2359 #endif
2360 }
2361
2362 #define LWS_MAX_ELEM_NAME 32
2363
2364 enum urldecode_stateful {
2365         US_NAME,
2366         US_IDLE,
2367         US_PC1,
2368         US_PC2,
2369
2370         MT_LOOK_BOUND_IN,
2371         MT_HNAME,
2372         MT_DISP,
2373         MT_TYPE,
2374         MT_IGNORE1,
2375         MT_IGNORE2,
2376 };
2377
2378 static const char * const mp_hdr[] = {
2379         "content-disposition: ",
2380         "content-type: ",
2381         "\x0d\x0a"
2382 };
2383
2384 typedef int (*lws_urldecode_stateful_cb)(void *data,
2385                 const char *name, char **buf, int len, int final);
2386
2387 struct lws_urldecode_stateful {
2388         char *out;
2389         void *data;
2390         char name[LWS_MAX_ELEM_NAME];
2391         char temp[LWS_MAX_ELEM_NAME];
2392         char content_type[32];
2393         char content_disp[32];
2394         char content_disp_filename[256];
2395         char mime_boundary[128];
2396         int out_len;
2397         int pos;
2398         int hdr_idx;
2399         int mp;
2400
2401         unsigned int multipart_form_data:1;
2402         unsigned int inside_quote:1;
2403         unsigned int subname:1;
2404         unsigned int boundary_real_crlf:1;
2405
2406         enum urldecode_stateful state;
2407
2408         lws_urldecode_stateful_cb output;
2409 };
2410
2411 static struct lws_urldecode_stateful *
2412 lws_urldecode_s_create(struct lws *wsi, char *out, int out_len, void *data,
2413                        lws_urldecode_stateful_cb output)
2414 {
2415         struct lws_urldecode_stateful *s = lws_zalloc(sizeof(*s));
2416         char buf[200], *p;
2417         int m = 0;
2418
2419         if (!s)
2420                 return NULL;
2421
2422         s->out = out;
2423         s->out_len  = out_len;
2424         s->output = output;
2425         s->pos = 0;
2426         s->mp = 0;
2427         s->state = US_NAME;
2428         s->name[0] = '\0';
2429         s->data = data;
2430
2431         if (lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_CONTENT_TYPE) > 0) {
2432                 /* multipart/form-data; boundary=----WebKitFormBoundarycc7YgAPEIHvgE9Bf */
2433
2434                 if (!strncmp(buf, "multipart/form-data", 19)) {
2435                         s->multipart_form_data = 1;
2436                         s->state = MT_LOOK_BOUND_IN;
2437                         s->mp = 2;
2438                         p = strstr(buf, "boundary=");
2439                         if (p) {
2440                                 p += 9;
2441                                 s->mime_boundary[m++] = '\x0d';
2442                                 s->mime_boundary[m++] = '\x0a';
2443                                 s->mime_boundary[m++] = '-';
2444                                 s->mime_boundary[m++] = '-';
2445                                 while (m < sizeof(s->mime_boundary) - 1 &&
2446                                        *p && *p != ' ')
2447                                         s->mime_boundary[m++] = *p++;
2448
2449                                 s->mime_boundary[m] = '\0';
2450
2451                                 lwsl_notice("boundary '%s'\n", s->mime_boundary);
2452                         }
2453                 }
2454         }
2455
2456         return s;
2457 }
2458
2459 static int
2460 lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in, int len)
2461 {
2462         int n, m, hit = 0;
2463         char sum = 0, c, was_end = 0;
2464
2465         while (len--) {
2466                 if (s->pos == s->out_len - s->mp - 1) {
2467                         if (s->output(s->data, s->name, &s->out, s->pos, 0))
2468                                 return -1;
2469
2470                         was_end = s->pos;
2471                         s->pos = 0;
2472                 }
2473                 switch (s->state) {
2474
2475                 /* states for url arg style */
2476
2477                 case US_NAME:
2478                         s->inside_quote = 0;
2479                         if (*in == '=') {
2480                                 s->name[s->pos] = '\0';
2481                                 s->pos = 0;
2482                                 s->state = US_IDLE;
2483                                 in++;
2484                                 continue;
2485                         }
2486                         if (*in == '&') {
2487                                 s->name[s->pos] = '\0';
2488                                 if (s->output(s->data, s->name, &s->out, s->pos, 1))
2489                                         return -1;
2490                                 s->pos = 0;
2491                                 s->state = US_IDLE;
2492                                 in++;
2493                                 continue;
2494                         }
2495                         if (s->pos >= sizeof(s->name) - 1) {
2496                                 lwsl_notice("Name too long\n");
2497                                 return -1;
2498                         }
2499                         s->name[s->pos++] = *in++;
2500                         break;
2501                 case US_IDLE:
2502                         if (*in == '%') {
2503                                 s->state++;
2504                                 in++;
2505                                 continue;
2506                         }
2507                         if (*in == '&') {
2508                                 s->out[s->pos] = '\0';
2509                                 if (s->output(s->data, s->name, &s->out, s->pos, 1))
2510                                         return -1;
2511                                 s->pos = 0;
2512                                 s->state = US_NAME;
2513                                 in++;
2514                                 continue;
2515                         }
2516                         if (*in == '+') {
2517                                 in++;
2518                                 s->out[s->pos++] = ' ';
2519                                 continue;
2520                         }
2521                         s->out[s->pos++] = *in++;
2522                         break;
2523                 case US_PC1:
2524                         n = char_to_hex(*in);
2525                         if (n < 0)
2526                                 return -1;
2527
2528                         in++;
2529                         sum = n << 4;
2530                         s->state++;
2531                         break;
2532
2533                 case US_PC2:
2534                         n = char_to_hex(*in);
2535                         if (n < 0)
2536                                 return -1;
2537
2538                         in++;
2539                         s->out[s->pos++] = sum | n;
2540                         s->state = US_IDLE;
2541                         break;
2542
2543
2544                 /* states for multipart / mime style */
2545
2546                 case MT_LOOK_BOUND_IN:
2547 retry_as_first:
2548                         if (*in == s->mime_boundary[s->mp] &&
2549                             s->mime_boundary[s->mp]) {
2550                                 in++;
2551                                 s->mp++;
2552                                 if (!s->mime_boundary[s->mp]) {
2553                                         s->mp = 0;
2554                                         s->state = MT_IGNORE1;
2555
2556                                         if (s->pos || was_end)
2557                                                 if (s->output(s->data, s->name,
2558                                                       &s->out, s->pos, 1))
2559                                                         return -1;
2560
2561                                         s->pos = 0;
2562
2563                                         s->content_disp[0] = '\0';
2564                                         s->name[0] = '\0';
2565                                         s->content_disp_filename[0] = '\0';
2566                                         s->boundary_real_crlf = 1;
2567                                 }
2568                                 continue;
2569                         }
2570                         if (s->mp) {
2571                                 n = 0;
2572                                 if (!s->boundary_real_crlf)
2573                                         n = 2;
2574
2575                                 memcpy(s->out + s->pos, s->mime_boundary + n, s->mp - n);
2576                                 s->pos += s->mp;
2577                                 s->mp = 0;
2578                                 goto retry_as_first;
2579                         }
2580
2581                         s->out[s->pos++] = *in;
2582                         in++;
2583                         s->mp = 0;
2584                         break;
2585
2586                 case MT_HNAME:
2587                         m = 0;
2588                         c =*in;
2589                         if (c >= 'A' && c <= 'Z')
2590                                 c += 'a' - 'A';
2591                         for (n = 0; n < ARRAY_SIZE(mp_hdr); n++)
2592                                 if (c == mp_hdr[n][s->mp]) {
2593                                         m++;
2594                                         hit = n;
2595                                 }
2596                         in++;
2597                         if (!m) {
2598                                 s->mp = 0;
2599                                 continue;
2600                         }
2601
2602                         s->mp++;
2603                         if (m != 1)
2604                                 continue;
2605
2606                         if (mp_hdr[hit][s->mp])
2607                                 continue;
2608
2609                         s->mp = 0;
2610                         s->temp[0] = '\0';
2611                         s->subname = 0;
2612
2613                         if (hit == 2)
2614                                 s->state = MT_LOOK_BOUND_IN;
2615                         else
2616                                 s->state += hit + 1;
2617                         break;
2618
2619                 case MT_DISP:
2620                         /* form-data; name="file"; filename="t.txt" */
2621
2622                         if (*in == '\x0d') {
2623 //                              lwsl_notice("disp: '%s', '%s', '%s'\n",
2624 //                                 s->content_disp, s->name,
2625 //                                 s->content_disp_filename);
2626
2627                                 if (s->content_disp_filename[0])
2628                                         if (s->output(s->data, s->name,
2629                                                       &s->out, s->pos, LWS_UFS_OPEN))
2630                                                 return -1;
2631                                 s->state = MT_IGNORE2;
2632                                 goto done;
2633                         }
2634                         if (*in == ';') {
2635                                 s->subname = 1;
2636                                 s->temp[0] = '\0';
2637                                 s->mp = 0;
2638                                 goto done;
2639                         }
2640
2641                         if (*in == '\"') {
2642                                 s->inside_quote ^= 1;
2643                                 goto done;
2644                         }
2645
2646                         if (s->subname) {
2647                                 if (*in == '=') {
2648                                         s->temp[s->mp] = '\0';
2649                                         s->subname = 0;
2650                                         s->mp = 0;
2651                                         goto done;
2652                                 }
2653                                 if (s->mp < sizeof(s->temp) - 1 &&
2654                                     (*in != ' ' || s->inside_quote))
2655                                         s->temp[s->mp++] = *in;
2656                                 goto done;
2657                         }
2658
2659                         if (!s->temp[0]) {
2660                                 if (s->mp < sizeof(s->content_disp) - 1)
2661                                         s->content_disp[s->mp++] = *in;
2662                                 s->content_disp[s->mp] = '\0';
2663                                 goto done;
2664                         }
2665
2666                         if (!strcmp(s->temp, "name")) {
2667                                 if (s->mp < sizeof(s->name) - 1)
2668                                         s->name[s->mp++] = *in;
2669                                 s->name[s->mp] = '\0';
2670                                 goto done;
2671                         }
2672
2673                         if (!strcmp(s->temp, "filename")) {
2674                                 if (s->mp < sizeof(s->content_disp_filename) - 1)
2675                                         s->content_disp_filename[s->mp++] = *in;
2676                                 s->content_disp_filename[s->mp] = '\0';
2677                                 goto done;
2678                         }
2679 done:
2680                         in++;
2681                         break;
2682
2683                 case MT_TYPE:
2684                         if (*in == '\x0d')
2685                                 s->state = MT_IGNORE2;
2686                         else {
2687                                 if (s->mp < sizeof(s->content_type) - 1)
2688                                         s->content_type[s->mp++] = *in;
2689                                 s->content_type[s->mp] = '\0';
2690                         }
2691                         in++;
2692                         break;
2693
2694                 case MT_IGNORE1:
2695                         if (*in == '\x0d')
2696                                 s->state = MT_IGNORE2;
2697                         in++;
2698                         break;
2699
2700                 case MT_IGNORE2:
2701                         s->mp = 0;
2702                         if (*in == '\x0a')
2703                                 s->state = MT_HNAME;
2704                         in++;
2705                         break;
2706                 }
2707         }
2708
2709         return 0;
2710 }
2711
2712 static int
2713 lws_urldecode_s_destroy(struct lws_urldecode_stateful *s)
2714 {
2715         int ret = 0;
2716
2717         if (s->state != US_IDLE)
2718                 ret = -1;
2719
2720         if (!ret)
2721                 if (s->output(s->data, s->name, &s->out, s->pos, 1))
2722                         ret = -1;
2723
2724         lws_free(s);
2725
2726         return ret;
2727 }
2728
2729 struct lws_spa {
2730         struct lws_urldecode_stateful *s;
2731         lws_spa_fileupload_cb opt_cb;
2732         const char * const *param_names;
2733         int count_params;
2734         char **params;
2735         int *param_length;
2736         void *opt_data;
2737
2738         char *storage;
2739         char *end;
2740         int max_storage;
2741 };
2742
2743 static int
2744 lws_urldecode_spa_lookup(struct lws_spa *spa,
2745                          const char *name)
2746 {
2747         int n;
2748
2749         for (n = 0; n < spa->count_params; n++)
2750                 if (!strcmp(spa->param_names[n], name))
2751                         return n;
2752
2753         return -1;
2754 }
2755
2756 static int
2757 lws_urldecode_spa_cb(void *data, const char *name, char **buf, int len,
2758                      int final)
2759 {
2760         struct lws_spa *spa =
2761                         (struct lws_spa *)data;
2762         int n;
2763
2764         if (spa->s->content_disp_filename[0]) {
2765                 if (spa->opt_cb) {
2766                         n = spa->opt_cb(spa->opt_data, name,
2767                                         spa->s->content_disp_filename,
2768                                         *buf, len, final);
2769
2770                         if (n < 0)
2771                                 return -1;
2772                 }
2773                 return 0;
2774         }
2775         n = lws_urldecode_spa_lookup(spa, name);
2776
2777         if (n == -1 || !len) /* unrecognized */
2778                 return 0;
2779
2780         if (!spa->params[n])
2781                 spa->params[n] = *buf;
2782
2783         if ((*buf) + len >= spa->end) {
2784                 lwsl_notice("%s: exceeded storage\n", __func__);
2785                 return -1;
2786         }
2787
2788         spa->param_length[n] += len;
2789
2790         /* move it on inside storage */
2791         (*buf) += len;
2792         *((*buf)++) = '\0';
2793
2794         spa->s->out_len -= len + 1;
2795
2796         return 0;
2797 }
2798
2799 LWS_VISIBLE LWS_EXTERN struct lws_spa *
2800 lws_spa_create(struct lws *wsi, const char * const *param_names,
2801                          int count_params, int max_storage,
2802                          lws_spa_fileupload_cb opt_cb, void *opt_data)
2803 {
2804         struct lws_spa *spa = lws_zalloc(sizeof(*spa));
2805
2806         if (!spa)
2807                 return NULL;
2808
2809         spa->param_names = param_names;
2810         spa->count_params = count_params;
2811         spa->max_storage = max_storage;
2812         spa->opt_cb = opt_cb;
2813         spa->opt_data = opt_data;
2814
2815         spa->storage = lws_malloc(max_storage);
2816         if (!spa->storage)
2817                 goto bail2;
2818         spa->end = spa->storage + max_storage - 1;
2819
2820         spa->params = lws_zalloc(sizeof(char *) * count_params);
2821         if (!spa->params)
2822                 goto bail3;
2823
2824         spa->s = lws_urldecode_s_create(wsi, spa->storage, max_storage, spa,
2825                                         lws_urldecode_spa_cb);
2826         if (!spa->s)
2827                 goto bail4;
2828
2829         spa->param_length = lws_zalloc(sizeof(int) * count_params);
2830         if (!spa->param_length)
2831                 goto bail5;
2832
2833         lwsl_notice("%s: Created SPA %p\n", __func__, spa);
2834
2835         return spa;
2836
2837 bail5:
2838         lws_urldecode_s_destroy(spa->s);
2839 bail4:
2840         lws_free(spa->params);
2841 bail3:
2842         lws_free(spa->storage);
2843 bail2:
2844         lws_free(spa);
2845
2846         return NULL;
2847 }
2848
2849 LWS_VISIBLE LWS_EXTERN int
2850 lws_spa_process(struct lws_spa *ludspa, const char *in, int len)
2851 {
2852         if (!ludspa) {
2853                 lwsl_err("%s: NULL spa\n");
2854                 return -1;
2855         }
2856         return lws_urldecode_s_process(ludspa->s, in, len);
2857 }
2858
2859 LWS_VISIBLE LWS_EXTERN int
2860 lws_spa_get_length(struct lws_spa *ludspa, int n)
2861 {
2862         if (n >= ludspa->count_params)
2863                 return 0;
2864
2865         return ludspa->param_length[n];
2866 }
2867
2868 LWS_VISIBLE LWS_EXTERN const char *
2869 lws_spa_get_string(struct lws_spa *ludspa, int n)
2870 {
2871         if (n >= ludspa->count_params)
2872                 return NULL;
2873
2874         return ludspa->params[n];
2875 }
2876
2877 LWS_VISIBLE LWS_EXTERN int
2878 lws_spa_finalize(struct lws_spa *spa)
2879 {
2880         if (spa->s) {
2881                 lws_urldecode_s_destroy(spa->s);
2882                 spa->s = NULL;
2883         }
2884
2885         return 0;
2886 }
2887
2888 LWS_VISIBLE LWS_EXTERN int
2889 lws_spa_destroy(struct lws_spa *spa)
2890 {
2891         int n = 0;
2892
2893         lwsl_notice("%s: destroy spa %p\n", __func__, spa);
2894
2895         if (spa->s)
2896                 lws_urldecode_s_destroy(spa->s);
2897
2898         lwsl_debug("%s\n", __func__);
2899
2900         lws_free(spa->param_length);
2901         lws_free(spa->params);
2902         lws_free(spa->storage);
2903         lws_free(spa);
2904
2905         return n;
2906 }
2907
2908 LWS_VISIBLE LWS_EXTERN int
2909 lws_chunked_html_process(struct lws_process_html_args *args,
2910                          struct lws_process_html_state *s)
2911 {
2912         char *sp, buffer[32];
2913         const char *pc;
2914         int old_len, n;
2915
2916         /* do replacements */
2917         sp = args->p;
2918         old_len = args->len;
2919         args->len = 0;
2920         s->start = sp;
2921         while (sp < args->p + old_len) {
2922
2923                 if (args->len + 7 >= args->max_len) {
2924                         lwsl_err("Used up interpret padding\n");
2925                         return -1;
2926                 }
2927
2928                 if ((!s->pos && *sp == '$') || s->pos) {
2929                         int hits = 0, hit = 0;
2930
2931                         if (!s->pos)
2932                                 s->start = sp;
2933                         s->swallow[s->pos++] = *sp;
2934                         if (s->pos == sizeof(s->swallow) - 1)
2935                                 goto skip;
2936                         for (n = 0; n < s->count_vars; n++)
2937                                 if (!strncmp(s->swallow, s->vars[n], s->pos)) {
2938                                         hits++;
2939                                         hit = n;
2940                                 }
2941                         if (!hits) {
2942 skip:
2943                                 s->swallow[s->pos] = '\0';
2944                                 memcpy(s->start, s->swallow, s->pos);
2945                                 args->len++;
2946                                 s->pos = 0;
2947                                 sp = s->start + 1;
2948                                 continue;
2949                         }
2950                         if (hits == 1 && s->pos == strlen(s->vars[hit])) {
2951                                 pc = s->replace(s->data, hit);
2952                                 if (!pc)
2953                                         pc = "NULL";
2954                                 n = strlen(pc);
2955                                 s->swallow[s->pos] = '\0';
2956                                 if (n != s->pos) {
2957                                         memmove(s->start + n,
2958                                                 s->start + s->pos,
2959                                                 old_len - (sp - args->p));
2960                                         old_len += (n - s->pos) + 1;
2961                                 }
2962                                 memcpy(s->start, pc, n);
2963                                 args->len++;
2964                                 sp = s->start + 1;
2965
2966                                 s->pos = 0;
2967                         }
2968                         sp++;
2969                         continue;
2970                 }
2971
2972                 args->len++;
2973                 sp++;
2974         }
2975
2976         /* no space left for final chunk trailer */
2977         if (args->final && args->len + 7 >= args->max_len)
2978                 return -1;
2979
2980         n = sprintf(buffer, "%X\x0d\x0a", args->len);
2981
2982         args->p -= n;
2983         memcpy(args->p, buffer, n);
2984         args->len += n;
2985
2986         if (args->final) {
2987                 sp = args->p + args->len;
2988                 *sp++ = '\x0d';
2989                 *sp++ = '\x0a';
2990                 *sp++ = '0';
2991                 *sp++ = '\x0d';
2992                 *sp++ = '\x0a';
2993                 *sp++ = '\x0d';
2994                 *sp++ = '\x0a';
2995                 args->len += 7;
2996         } else {
2997                 sp = args->p + args->len;
2998                 *sp++ = '\x0d';
2999                 *sp++ = '\x0a';
3000                 args->len += 2;
3001         }
3002
3003         return 0;
3004 }