Revert "Imported Upstream version 3.2"
[platform/upstream/libwebsockets.git] / test-server / test-server-http.c
index 32b36ba..070bf7e 100644 (file)
  *                             using this protocol, including the sender
  */
 
-#if defined(LWS_USE_POLARSSL)
-#else
-#if defined(LWS_USE_MBEDTLS)
-#else
 #if defined(LWS_OPENSSL_SUPPORT) && defined(LWS_HAVE_SSL_CTX_set1_param)
 /* location of the certificate revocation list */
 extern char crl_path[1024];
 #endif
-#endif
-#endif
 
 extern int debug_level;
 
@@ -118,9 +112,68 @@ const char * get_mimetype(const char *file)
        if (!strcmp(&file[n - 4], ".css"))
                return "text/css";
 
+       if (!strcmp(&file[n - 3], ".js"))
+               return "text/javascript";
+
        return NULL;
 }
 
+
+static const char * const param_names[] = {
+       "text",
+       "send",
+       "file",
+       "upload",
+};
+
+enum enum_param_names {
+       EPN_TEXT,
+       EPN_SEND,
+       EPN_FILE,
+       EPN_UPLOAD,
+};
+
+static int
+file_upload_cb(void *data, const char *name, const char *filename,
+              char *buf, int len, enum lws_spa_fileupload_states state)
+{
+       struct per_session_data__http *pss =
+                       (struct per_session_data__http *)data;
+       int n;
+
+       (void)n;
+
+       switch (state) {
+       case LWS_UFS_OPEN:
+               strncpy(pss->filename, filename, sizeof(pss->filename) - 1);
+               /* we get the original filename in @filename arg, but for
+                * simple demo use a fixed name so we don't have to deal with
+                * attacks  */
+               pss->post_fd = (lws_filefd_type)open("/tmp/post-file",
+                              O_CREAT | O_TRUNC | O_RDWR, 0600);
+               break;
+       case LWS_UFS_FINAL_CONTENT:
+       case LWS_UFS_CONTENT:
+               if (len) {
+                       pss->file_length += len;
+
+                       /* if the file length is too big, drop it */
+                       if (pss->file_length > 100000)
+                               return 1;
+
+                       n = write((int)pss->post_fd, buf, len);
+                       lwsl_notice("%s: write %d says %d\n", __func__, len, n);
+               }
+               if (state == LWS_UFS_CONTENT)
+                       break;
+               close((int)pss->post_fd);
+               pss->post_fd = LWS_INVALID_FILE;
+               break;
+       }
+
+       return 0;
+}
+
 /* this protocol server (always the first one) handles HTTP,
  *
  * Some misc callbacks that aren't associated with a protocol also turn up only
@@ -133,7 +186,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
        struct per_session_data__http *pss =
                        (struct per_session_data__http *)user;
        unsigned char buffer[4096 + LWS_PRE];
-       unsigned long amount, file_len, sent;
+       lws_filepos_t amount, file_len, sent;
        char leaf_path[1024];
        const char *mimetype;
        char *other_headers;
@@ -155,7 +208,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
        switch (reason) {
        case LWS_CALLBACK_HTTP:
 
-               lwsl_notice("lws_http_serve: %s\n",in);
+               lwsl_info("lws_http_serve: %s\n", (const char *)in);
 
                if (debug_level & LLL_INFO) {
                        dump_handshake_info(wsi);
@@ -169,11 +222,8 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                }
 
                {
-                       char name[100], rip[50];
-                       lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name,
-                                              sizeof(name), rip, sizeof(rip));
-                       sprintf(buf, "%s (%s)", name, rip);
-                       lwsl_notice("HTTP connect from %s\n", buf);
+                       lws_get_peer_simple(wsi, buf, sizeof(buf));
+                       lwsl_info("HTTP connect from %s\n", buf);
                }
 
                if (len < 1) {
@@ -182,38 +232,37 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                        goto try_to_reuse;
                }
 
-#ifndef LWS_NO_CLIENT
+#if !defined(LWS_NO_CLIENT) && defined(LWS_OPENSSL_SUPPORT)
                if (!strncmp(in, "/proxytest", 10)) {
                        struct lws_client_connect_info i;
-                       char *rootpath = "/";
+                       char *rootpath = "/git/";
                        const char *p = (const char *)in;
 
                        if (lws_get_child(wsi))
                                break;
 
                        pss->client_finished = 0;
-                       memset(&i,0, sizeof(i));
+                       memset(&i, 0, sizeof(i));
                        i.context = lws_get_context(wsi);
-                       i.address = "git.libwebsockets.org";
-                       i.port = 80;
-                       i.ssl_connection = 0;
+                       i.address = "libwebsockets.org";
+                       i.port = 443;
+                       i.ssl_connection = 1;
                        if (p[10])
                                i.path = (char *)in + 10;
                        else
                                i.path = rootpath;
-                       i.host = "git.libwebsockets.org";
+                       i.host = i.address;
                        i.origin = NULL;
                        i.method = "GET";
                        i.parent_wsi = wsi;
-                       i.uri_replace_from = "git.libwebsockets.org/";
+                       i.uri_replace_from = "libwebsockets.org/git/";
                        i.uri_replace_to = "/proxytest/";
+
                        if (!lws_client_connect_via_info(&i)) {
                                lwsl_err("proxy connect fail\n");
                                break;
                        }
 
-
-
                        break;
                }
 #endif
@@ -226,39 +275,6 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                }
 #endif
 
-               if (!strncmp(in, "/postresults", 12)) {
-                       m = sprintf(buf, "<html><body>Form results: '%s'<br>"
-                                       "</body></html>", pss->post_string);
-
-                       p = buffer + LWS_PRE;
-                       start = p;
-                       end = p + sizeof(buffer) - LWS_PRE;
-
-                       if (lws_add_http_header_status(wsi, 200, &p, end))
-                               return 1;
-                       if (lws_add_http_header_by_token(wsi,
-                                       WSI_TOKEN_HTTP_CONTENT_TYPE,
-                                       (unsigned char *)"text/html",
-                                       9, &p, end))
-                               return 1;
-                       if (lws_add_http_header_content_length(wsi, m, &p,
-                                                              end))
-                               return 1;
-                       if (lws_finalize_http_header(wsi, &p, end))
-                               return 1;
-
-                       n = lws_write(wsi, start, p - start,
-                                     LWS_WRITE_HTTP_HEADERS);
-                       if (n < 0)
-                               return 1;
-
-                       n = lws_write(wsi, (unsigned char *)buf, m, LWS_WRITE_HTTP);
-                       if (n < 0)
-                               return 1;
-
-                       goto try_to_reuse;
-               }
-
                /* if a legal POST URL, let it continue and accept data */
                if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
                        return 0;
@@ -266,6 +282,8 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                /* check for the "send a big file by hand" example case */
 
                if (!strcmp((const char *)in, "/leaf.jpg")) {
+                       lws_fop_flags_t flags = LWS_O_RDONLY;
+
                        if (strlen(resource_path) > sizeof(leaf_path) - 10)
                                return -1;
                        sprintf(leaf_path, "%s/leaf.jpg", resource_path);
@@ -275,13 +293,14 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                        p = buffer + LWS_PRE;
                        end = p + sizeof(buffer) - LWS_PRE;
 
-                       pss->fd = lws_plat_file_open(wsi, leaf_path, &file_len,
-                                                    LWS_O_RDONLY);
-
-                       if (pss->fd == LWS_INVALID_FILE) {
-                               lwsl_err("faild to open file %s\n", leaf_path);
+                       pss->fop_fd = lws_vfs_file_open(
+                                       lws_get_fops(lws_get_context(wsi)),
+                                       leaf_path, &flags);
+                       if (!pss->fop_fd) {
+                               lwsl_err("failed to open file %s\n", leaf_path);
                                return -1;
                        }
+                       file_len = lws_vfs_get_length(pss->fop_fd);
 
                        /*
                         * we will send a big jpeg file, but it could be
@@ -293,7 +312,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                         * depending on what connection it happens to be working
                         * on
                         */
-                       if (lws_add_http_header_status(wsi, 200, &p, end))
+                       if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
                                return 1;
                        if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SERVER,
                                        (unsigned char *)"libwebsockets",
@@ -329,7 +348,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                                      p - (buffer + LWS_PRE),
                                      LWS_WRITE_HTTP_HEADERS);
                        if (n < 0) {
-                               lws_plat_file_close(wsi, pss->fd);
+                               lws_vfs_file_close(&pss->fop_fd);
                                return -1;
                        }
                        /*
@@ -359,7 +378,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                if (!mimetype) {
                        lwsl_err("Unknown mimetype for %s\n", buf);
                        lws_return_http_status(wsi,
-                                     HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, NULL);
+                                     HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, "Unknown Mimetype");
                        return -1;
                }
 
@@ -393,38 +412,103 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                n = (char *)p - leaf_path;
 
                n = lws_serve_http_file(wsi, buf, mimetype, other_headers, n);
-               if (n < 0 || ((n > 0) && lws_http_transaction_completed(wsi)))
-                       return -1; /* error or can't reuse connection: close the socket */
+               if (n < 0)
+                       return -1; /* error*/
 
                /*
                 * notice that the sending of the file completes asynchronously,
                 * we'll get a LWS_CALLBACK_HTTP_FILE_COMPLETION callback when
-                * it's done
+                * it's done.  That's the case even if we just completed the
+                * send, so wait for that.
                 */
                break;
 
+        case LWS_CALLBACK_CLIENT_RECEIVE:
+                ((char *)in)[len] = '\0';
+                lwsl_info("rx %d '%s'\n", (int)len, (char *)in);
+                break;
+
        case LWS_CALLBACK_HTTP_BODY:
-               lwsl_notice("LWS_CALLBACK_HTTP_BODY: len %d\n", (int)len);
-               strncpy(pss->post_string, in, sizeof (pss->post_string) -1);
-               pss->post_string[sizeof(pss->post_string) - 1] = '\0';
+               /* create the POST argument parser if not already existing */
+               if (!pss->spa) {
+                       pss->spa = lws_spa_create(wsi, param_names,
+                                       ARRAY_SIZE(param_names), 1024,
+                                       file_upload_cb, pss);
+                       if (!pss->spa)
+                               return -1;
+
+                       pss->filename[0] = '\0';
+                       pss->file_length = 0;
+               }
+
+               /* let it parse the POST data */
+               if (lws_spa_process(pss->spa, in, len))
+                       return -1;
                break;
 
        case LWS_CALLBACK_HTTP_BODY_COMPLETION:
-               lwsl_notice("LWS_CALLBACK_HTTP_BODY_COMPLETION\n");
+               lwsl_debug("LWS_CALLBACK_HTTP_BODY_COMPLETION\n");
                /*
                 * the whole of the sent body arrived,
                 * respond to the client with a redirect to show the
                 * results
                 */
-               p = (unsigned char *)buf + LWS_PRE;
-               n = lws_http_redirect(wsi,
-                                     HTTP_STATUS_SEE_OTHER, /* 303 */
-                                     (unsigned char *)"/postresults", 12, /* location + len */
-                                     &p, /* temp buffer to use */
-                                     p + sizeof(buf) - 1 - LWS_PRE /* buffer len */
-                       );
+
+               /* call to inform no more payload data coming */
+               lws_spa_finalize(pss->spa);
+
+               p = (unsigned char *)pss->result + LWS_PRE;
+               end = p + sizeof(pss->result) - LWS_PRE - 1;
+               p += sprintf((char *)p,
+                       "<html><body><h1>Form results (after urldecoding)</h1>"
+                       "<table><tr><td>Name</td><td>Length</td><td>Value</td></tr>");
+
+               for (n = 0; n < ARRAY_SIZE(param_names); n++)
+                       p += lws_snprintf((char *)p, end - p,
+                                   "<tr><td><b>%s</b></td><td>%d</td><td>%s</td></tr>",
+                                   param_names[n],
+                                   lws_spa_get_length(pss->spa, n),
+                                   lws_spa_get_string(pss->spa, n));
+
+               p += lws_snprintf((char *)p, end - p, "</table><br><b>filename:</b> %s, <b>length</b> %ld",
+                               pss->filename, pss->file_length);
+
+               p += lws_snprintf((char *)p, end - p, "</body></html>");
+               pss->result_len = p - (unsigned char *)(pss->result + LWS_PRE);
+
+               p = buffer + LWS_PRE;
+               start = p;
+               end = p + sizeof(buffer) - LWS_PRE;
+
+               if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
+                       return 1;
+
+               if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
+                               (unsigned char *)"text/html", 9, &p, end))
+                       return 1;
+               if (lws_add_http_header_content_length(wsi, pss->result_len, &p, end))
+                       return 1;
+               if (lws_finalize_http_header(wsi, &p, end))
+                       return 1;
+
+               n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
+               if (n < 0)
+                       return 1;
+
+               n = lws_write(wsi, (unsigned char *)pss->result + LWS_PRE,
+                             pss->result_len, LWS_WRITE_HTTP);
+               if (n < 0)
+                       return 1;
                goto try_to_reuse;
+       case LWS_CALLBACK_HTTP_DROP_PROTOCOL:
+               lwsl_debug("LWS_CALLBACK_HTTP_DROP_PROTOCOL\n");
 
+               /* called when our wsi user_space is going to be destroyed */
+               if (pss->spa) {
+                       lws_spa_destroy(pss->spa);
+                       pss->spa = NULL;
+               }
+               break;
        case LWS_CALLBACK_HTTP_FILE_COMPLETION:
                goto try_to_reuse;
 
@@ -434,8 +518,10 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                if (pss->client_finished)
                        return -1;
 
-               if (pss->fd == LWS_INVALID_FILE)
+               if (!lws_get_child(wsi) && !pss->fop_fd) {
+                       lwsl_notice("fop_fd NULL\n");
                        goto try_to_reuse;
+               }
 
 #ifndef LWS_NO_CLIENT
                if (pss->reason_bf & 2) {
@@ -447,17 +533,24 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                         * suitable size to send or what's available, whichever
                         * is the smaller.
                         */
+
+
                        pss->reason_bf &= ~2;
                        wsi1 = lws_get_child(wsi);
                        if (!wsi1)
                                break;
                        if (lws_http_client_read(wsi1, &px, &lenx) < 0)
-                               goto bail;
+                               return -1;
 
                        if (pss->client_finished)
                                return -1;
+
                        break;
                }
+
+               if (lws_get_child(wsi))
+                       break;
+
 #endif
                /*
                 * we can send more of whatever it is we were sending
@@ -479,7 +572,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                                /* he couldn't handle that much */
                                n = m;
 
-                       n = lws_plat_file_read(wsi, pss->fd,
+                       n = lws_vfs_file_read(pss->fop_fd,
                                               &amount, buffer + LWS_PRE, n);
                        /* problem reading, close conn */
                        if (n < 0) {
@@ -512,12 +605,12 @@ later:
                lws_callback_on_writable(wsi);
                break;
 penultimate:
-               lws_plat_file_close(wsi, pss->fd);
-               pss->fd = LWS_INVALID_FILE;
+               lws_vfs_file_close(&pss->fop_fd);
+               pss->fop_fd = NULL;
                goto try_to_reuse;
 
 bail:
-               lws_plat_file_close(wsi, pss->fd);
+               lws_vfs_file_close(&pss->fop_fd);
 
                return -1;
 
@@ -538,7 +631,7 @@ bail:
                lwsl_err("LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP\n");
                p = buffer + LWS_PRE;
                end = p + sizeof(buffer) - LWS_PRE;
-               if (lws_add_http_header_status(lws_get_parent(wsi), 200, &p, end))
+               if (lws_add_http_header_status(lws_get_parent(wsi), HTTP_STATUS_OK, &p, end))
                        return 1;
                if (lws_add_http_header_by_token(lws_get_parent(wsi),
                                WSI_TOKEN_HTTP_SERVER,
@@ -580,16 +673,12 @@ bail:
                assert(lws_get_parent(wsi));
                if (!lws_get_parent(wsi))
                        break;
-               // lwsl_err("LWS_CALLBACK_RECEIVE_CLIENT_HTTP: wsi %p: sock: %d, parent_wsi: %p, parent_sock:%d,  len %d\n",
-               //              wsi, lws_get_socket_fd(wsi),
-               //              lws_get_parent(wsi),
-               //              lws_get_socket_fd(lws_get_parent(wsi)), len);
                pss1 = lws_wsi_user(lws_get_parent(wsi));
                pss1->reason_bf |= 2;
                lws_callback_on_writable(lws_get_parent(wsi));
                break;
        case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
-               //lwsl_err("LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ len %d\n", len);
+               //lwsl_err("LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ len %d\n", (int)len);
                assert(lws_get_parent(wsi));
                m = lws_write(lws_get_parent(wsi), (unsigned char *)in,
                                len, LWS_WRITE_HTTP);
@@ -669,10 +758,6 @@ bail:
 
                break;
 
-#if defined(LWS_USE_POLARSSL)
-#else
-#if defined(LWS_USE_MBEDTLS)
-#else
 #if defined(LWS_OPENSSL_SUPPORT)
        case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION:
                /* Verify the client certificate */
@@ -705,8 +790,6 @@ bail:
                break;
 #endif
 #endif
-#endif
-#endif
 
        default:
                break;