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