win32: enable 64-bit file lengths
[platform/upstream/libwebsockets.git] / lib / handshake.c
index 00b543a..98e75b3 100644 (file)
  * into multiple fragments.  They may contain unknown headers with arbitrary
  * argument lengths.  So, we parse using a single-character at a time state
  * machine that is completely independent of packet size.
+ *
+ * Returns <0 for error or length of chars consumed from buf (up to len)
  */
 
 LWS_VISIBLE int
-lws_read(struct lws *wsi, unsigned char *buf, size_t len)
+lws_read(struct lws *wsi, unsigned char *buf, lws_filepos_t len)
 {
-       unsigned char *last_char;
-       int body_chunk_len;
+       unsigned char *last_char, *oldbuf = buf;
+       lws_filepos_t body_chunk_len;
        size_t n;
 
+       lwsl_debug("%s: incoming len %d  state %d\n", __func__, (int)len, wsi->state);
+
        switch (wsi->state) {
 #ifdef LWS_USE_HTTP2
        case LWSS_HTTP2_AWAIT_CLIENT_PREFACE:
@@ -83,12 +87,17 @@ lws_read(struct lws *wsi, unsigned char *buf, size_t len)
                        /* account for what we're using in rxflow buffer */
                        if (wsi->rxflow_buffer)
                                wsi->rxflow_pos++;
-                       if (lws_http2_parser(wsi, buf[n++]))
+                       if (lws_http2_parser(wsi, buf[n++])) {
+                               lwsl_debug("%s: http2_parser bailed\n", __func__);
                                goto bail;
+                       }
                }
                break;
 #endif
-http_new:
+
+       case LWSS_CLIENT_HTTP_ESTABLISHED:
+               break;
+
        case LWSS_HTTP:
                wsi->hdr_parsing_completed = 0;
                /* fallthru */
@@ -98,16 +107,25 @@ http_new:
                wsi->u.hdr.lextable_pos = 0;
                /* fallthru */
        case LWSS_HTTP_HEADERS:
+               if (!wsi->u.hdr.ah) {
+                       lwsl_err("%s: LWSS_HTTP_HEADERS: NULL ah\n", __func__);
+                       assert(0);
+               }
                lwsl_parser("issuing %d bytes to parser\n", (int)len);
 
-               if (lws_handshake_client(wsi, &buf, len))
+               if (lws_handshake_client(wsi, &buf, (size_t)len))
                        goto bail;
 
                last_char = buf;
-               if (lws_handshake_server(wsi, &buf, len))
+               if (lws_handshake_server(wsi, &buf, (size_t)len))
                        /* Handshake indicates this session is done. */
                        goto bail;
 
+               /* we might have transitioned to RAW */
+               if (wsi->mode == LWSCM_RAW)
+                        /* we gave the read buffer to RAW handler already */
+                       goto read_ok;
+
                /*
                 * It's possible that we've exhausted our data already, or
                 * rx flow control has stopped us dealing with this early,
@@ -116,7 +134,7 @@ http_new:
                 * appropriately:
                 */
                len -= (buf - last_char);
-               lwsl_debug("%s: thinks we have used %d\n", __func__, len);
+               lwsl_debug("%s: thinks we have used %ld\n", __func__, (long)len);
 
                if (!wsi->hdr_parsing_completed)
                        /* More header content on the way */
@@ -125,7 +143,7 @@ http_new:
                switch (wsi->state) {
                        case LWSS_HTTP:
                        case LWSS_HTTP_HEADERS:
-                               goto http_complete;
+                               goto read_ok;
                        case LWSS_HTTP_ISSUING_FILE:
                                goto read_ok;
                        case LWSS_HTTP_BODY:
@@ -151,41 +169,74 @@ http_postbody:
                        body_chunk_len = min(wsi->u.http.content_remain,len);
                        wsi->u.http.content_remain -= body_chunk_len;
                        len -= body_chunk_len;
+#ifdef LWS_WITH_CGI
+                       if (wsi->cgi) {
+                               struct lws_cgi_args args;
 
-                       n = wsi->protocol->callback(wsi,
-                               LWS_CALLBACK_HTTP_BODY, wsi->user_space,
-                               buf, body_chunk_len);
-                       if (n)
-                               goto bail;
+                               args.ch = LWS_STDIN;
+                               args.stdwsi = &wsi->cgi->stdwsi[0];
+                               args.data = buf;
+                               args.len = body_chunk_len;
 
-                       buf += body_chunk_len;
+                               /* returns how much used */
+                               n = user_callback_handle_rxflow(
+                                       wsi->protocol->callback,
+                                       wsi, LWS_CALLBACK_CGI_STDIN_DATA,
+                                       wsi->user_space,
+                                       (void *)&args, 0);
+                               if ((int)n < 0)
+                                       goto bail;
+                       } else {
+#endif
+                               n = wsi->protocol->callback(wsi,
+                                       LWS_CALLBACK_HTTP_BODY, wsi->user_space,
+                                       buf, (size_t)body_chunk_len);
+                               if (n)
+                                       goto bail;
+                               n = (size_t)body_chunk_len;
+#ifdef LWS_WITH_CGI
+                       }
+#endif
+                       buf += n;
 
                        if (wsi->u.http.content_remain)  {
                                lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
-                                               AWAITING_TIMEOUT);
+                                               wsi->context->timeout_secs);
                                break;
                        }
                        /* he sent all the content in time */
 postbody_completion:
+#ifdef LWS_WITH_CGI
+                       /* if we're running a cgi, we can't let him off the hook just because he sent his POST data */
+                       if (wsi->cgi)
+                               lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, wsi->context->timeout_secs);
+                       else
+#endif
                        lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
-                       n = wsi->protocol->callback(wsi,
-                               LWS_CALLBACK_HTTP_BODY_COMPLETION,
-                               wsi->user_space, NULL, 0);
-                       if (n)
-                               goto bail;
+#ifdef LWS_WITH_CGI
+                       if (!wsi->cgi)
+#endif
+                       {
+                               n = wsi->protocol->callback(wsi,
+                                       LWS_CALLBACK_HTTP_BODY_COMPLETION,
+                                       wsi->user_space, NULL, 0);
+                               if (n)
+                                       goto bail;
+                       }
 
-                       goto http_complete;
+                       break;
                }
                break;
 
        case LWSS_ESTABLISHED:
        case LWSS_AWAITING_CLOSE_ACK:
-               if (lws_handshake_client(wsi, &buf, len))
+       case LWSS_SHUTDOWN:
+               if (lws_handshake_client(wsi, &buf, (size_t)len))
                        goto bail;
                switch (wsi->mode) {
                case LWSCM_WS_SERVING:
 
-                       if (lws_interpret_incoming_packet(wsi, buf, len) < 0) {
+                       if (lws_interpret_incoming_packet(wsi, &buf, (size_t)len) < 0) {
                                lwsl_info("interpret_incoming_packet has bailed\n");
                                goto bail;
                        }
@@ -193,32 +244,18 @@ postbody_completion:
                }
                break;
        default:
-               lwsl_err("%s: Unhandled state\n", __func__);
+               lwsl_err("%s: Unhandled state %d\n", __func__, wsi->state);
                break;
        }
 
 read_ok:
        /* Nothing more to do for now */
-       lwsl_debug("%s: read_ok\n", __func__);
-
-       return 0;
-
-http_complete:
-       lwsl_debug("%s: http_complete\n", __func__);
-
-#ifndef LWS_NO_SERVER
-       /* Did the client want to keep the HTTP connection going? */
-       if (lws_http_transaction_completed(wsi))
-               goto bail;
-#endif
-       /* If we have more data, loop back around: */
-       if (len)
-               goto http_new;
+       lwsl_info("%s: read_ok, used %ld\n", __func__, (long)(buf - oldbuf));
 
-       return 0;
+       return buf - oldbuf;
 
 bail:
-       lwsl_debug("closing connection at lws_read bail:\n");
+       //lwsl_notice("closing connection at lws_read bail:\n");
        lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
 
        return -1;