lws_intptr_t
[platform/upstream/libwebsockets.git] / lib / http2.c
index a2aa3f9..0bde700 100644 (file)
@@ -52,10 +52,10 @@ lws_http2_wsi_from_id(struct lws *wsi, unsigned int sid)
 }
 
 struct lws *
-lws_create_server_child_wsi(struct lws_context *context, struct lws *parent_wsi,
+lws_create_server_child_wsi(struct lws_vhost *vhost, struct lws *parent_wsi,
                            unsigned int sid)
 {
-       struct lws *wsi = lws_create_new_server_wsi(context);
+       struct lws *wsi = lws_create_new_server_wsi(vhost);
 
        if (!wsi)
                return NULL;
@@ -64,8 +64,7 @@ lws_create_server_child_wsi(struct lws_context *context, struct lws *parent_wsi,
        if (parent_wsi->u.http2.child_count + 1 ==
            parent_wsi->u.http2.peer_settings.setting[
                        LWS_HTTP2_SETTINGS__MAX_CONCURRENT_STREAMS])
-               return NULL;
-
+               goto bail;
        lws_http2_init(&wsi->u.http2.peer_settings);
        lws_http2_init(&wsi->u.http2.my_settings);
        wsi->u.http2.stream_id = sid;
@@ -82,13 +81,21 @@ lws_create_server_child_wsi(struct lws_context *context, struct lws *parent_wsi,
        wsi->state = LWSS_HTTP2_ESTABLISHED;
        wsi->mode = parent_wsi->mode;
 
-       wsi->protocol = &context->protocols[0];
-       lws_ensure_user_space(wsi);
+       wsi->protocol = &vhost->protocols[0];
+       if (lws_ensure_user_space(wsi))
+               goto bail;
 
        lwsl_info("%s: %p new child %p, sid %d, user_space=%p\n", __func__,
                  parent_wsi, wsi, sid, wsi->user_space);
 
        return wsi;
+
+bail:
+       vhost->protocols[0].callback(wsi, LWS_CALLBACK_WSI_DESTROY,
+                              NULL, NULL, 0);
+       lws_free(wsi);
+
+       return NULL;
 }
 
 int lws_remove_server_child_wsi(struct lws_context *context, struct lws *wsi)
@@ -162,14 +169,14 @@ int lws_http2_frame_write(struct lws *wsi, int type, int flags,
        *p++ = sid >> 8;
        *p++ = sid;
 
-       lwsl_info("%s: %p (eff %p). type %d, flags 0x%x, sid=%d, len=%d\n",
+       lwsl_info("%s: %p (eff %p). type %d, flags 0x%x, sid=%d, len=%d, tx_credit=%d\n",
                  __func__, wsi, wsi_eff, type, flags, sid, len,
                  wsi->u.http2.tx_credit);
 
        if (type == LWS_HTTP2_FRAME_TYPE_DATA) {
                if (wsi->u.http2.tx_credit < len)
                        lwsl_err("%s: %p: sending payload len %d"
-                                " but tx_credit only %d!\n", len,
+                                " but tx_credit only %d!\n", __func__, wsi, len,
                                 wsi->u.http2.tx_credit);
                wsi->u.http2.tx_credit -= len;
        }
@@ -198,7 +205,6 @@ static const char * https_client_preface =
 int
 lws_http2_parser(struct lws *wsi, unsigned char c)
 {
-       struct lws_context *context = wsi->context;
        struct lws *swsi;
        int n;
 
@@ -243,8 +249,15 @@ lws_http2_parser(struct lws *wsi, unsigned char c)
                        case LWS_HTTP2_FRAME_TYPE_CONTINUATION:
                        case LWS_HTTP2_FRAME_TYPE_HEADERS:
                                lwsl_info(" %02X\n", c);
-                               if (lws_hpack_interpret(wsi->u.http2.stream_wsi, c))
+                               if (!wsi->u.http2.stream_wsi->u.hdr.ah)
+                                       if (lws_header_table_attach(wsi->u.http2.stream_wsi, 0)) {
+                                               lwsl_err("%s: Failed to get ah\n", __func__);
+                                               return 1;
+                                       }
+                               if (lws_hpack_interpret(wsi->u.http2.stream_wsi, c)) {
+                                       lwsl_notice("%s: lws_hpack_interpret failed\n", __func__);
                                        return 1;
+                               }
                                break;
                        case LWS_HTTP2_FRAME_TYPE_GOAWAY:
                                if (wsi->u.http2.count >= 5 && wsi->u.http2.count <= 8) {
@@ -307,7 +320,7 @@ lws_http2_parser(struct lws *wsi, unsigned char c)
                                break;
                        case LWS_HTTP2_FRAME_TYPE_WINDOW_UPDATE:
                                wsi->u.http2.hpack_e_dep &= ~(1 << 31);
-                               if ((long long)swsi->u.http2.tx_credit + (unsigned long long)wsi->u.http2.hpack_e_dep > (~(1 << 31)))
+                               if ((lws_intptr_t)swsi->u.http2.tx_credit + (lws_intptr_t)wsi->u.http2.hpack_e_dep > (~(1 << 31)))
                                        return 1; /* actually need to close swsi not the whole show */
                                swsi->u.http2.tx_credit += wsi->u.http2.hpack_e_dep;
                                if (swsi->u.http2.waiting_tx_credit && swsi->u.http2.tx_credit > 0) {
@@ -377,8 +390,11 @@ lws_http2_parser(struct lws *wsi, unsigned char c)
                                lwsl_info("LWS_HTTP2_FRAME_TYPE_HEADERS: stream_id = %d\n", wsi->u.http2.stream_id);
                                if (!wsi->u.http2.stream_id)
                                        return 1;
-                               if (!wsi->u.http2.stream_wsi)
-                                       wsi->u.http2.stream_wsi = lws_create_server_child_wsi(context, wsi, wsi->u.http2.stream_id);
+                               if (!wsi->u.http2.stream_wsi) {
+                                       wsi->u.http2.stream_wsi =
+                                               lws_create_server_child_wsi(wsi->vhost, wsi, wsi->u.http2.stream_id);
+                                       wsi->u.http2.stream_wsi->http2_substream = 1;
+                               }
 
                                /* END_STREAM means after servicing this, close the stream */
                                wsi->u.http2.END_STREAM = !!(wsi->u.http2.flags & LWS_HTTP2_FLAG_END_STREAM);
@@ -460,10 +476,10 @@ int lws_http2_do_pps_send(struct lws_context *context, struct lws *wsi)
                if (wsi->state == LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS) {
                        wsi->state = LWSS_HTTP2_ESTABLISHED;
 
-                       wsi->u.http.fd = LWS_INVALID_FILE;
+                       wsi->u.http.fop_fd = NULL;
 
                        if (lws_is_ssl(lws_http2_get_network_wsi(wsi))) {
-                               lwsl_info("skipping nonexistant ssl upgrade headers\n");
+                               lwsl_info("skipping nonexistent ssl upgrade headers\n");
                                break;
                        }
 
@@ -474,7 +490,8 @@ int lws_http2_do_pps_send(struct lws_context *context, struct lws *wsi)
                         */
                        lwsl_info("%s: setting up sid 1\n", __func__);
 
-                       swsi = wsi->u.http2.stream_wsi = lws_create_server_child_wsi(context, wsi, 1);
+                       swsi = wsi->u.http2.stream_wsi =
+                                       lws_create_server_child_wsi(wsi->vhost, wsi, 1);
                        /* pass on the initial headers to SID 1 */
                        swsi->u.http.ah = wsi->u.http.ah;
                        wsi->u.http.ah = NULL;