diff --git a/lib/hpack.c b/lib/hpack.c index 56f66b54..58d84b70 100644 --- a/lib/hpack.c +++ b/lib/hpack.c @@ -377,6 +377,12 @@ int lws_hpack_interpret(struct libwebsocket_context *context, break; case HPKS_TYPE: + + if (wsi->u.http2.count > (wsi->u.http2.length - wsi->u.http2.padding)) { + lwsl_info("padding eat\n"); + break; + } + if (c & 0x80) { /* indexed header field only */ /* just a possibly-extended integer */ wsi->u.http2.hpack_type = HPKT_INDEXED_HDR_7; diff --git a/lib/http2.c b/lib/http2.c index 7279f6b8..ab08b137 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -222,6 +222,7 @@ lws_http2_parser(struct libwebsocket_context *context, LWS_HTTP2_SETTINGS_LENGTH)) return 1; break; + case LWS_HTTP2_FRAME_TYPE_CONTINUATION: case LWS_HTTP2_FRAME_TYPE_HEADERS: lwsl_info(" %02X\n", c); if (lws_hpack_interpret(context, wsi->u.http2.stream_wsi, c)) @@ -237,6 +238,24 @@ lws_http2_parser(struct libwebsocket_context *context, } wsi->u.http2.GOING_AWAY = 1; break; + case LWS_HTTP2_FRAME_TYPE_DATA: + break; + case LWS_HTTP2_FRAME_TYPE_PRIORITY: + break; + case LWS_HTTP2_FRAME_TYPE_RST_STREAM: + break; + case LWS_HTTP2_FRAME_TYPE_PUSH_PROMISE: + break; + case LWS_HTTP2_FRAME_TYPE_PING: + if (wsi->u.http2.flags & LWS_HTTP2_FLAG_SETTINGS_ACK) { // ack + } else { /* they're sending us a ping request */ + if (wsi->u.http2.count > 8) + return 1; + wsi->u.http2.ping_payload[wsi->u.http2.count - 1] = c; + } + break; + case LWS_HTTP2_FRAME_TYPE_WINDOW_UPDATE: + break; } if (wsi->u.http2.count != wsi->u.http2.length) break; @@ -258,6 +277,12 @@ lws_http2_parser(struct libwebsocket_context *context, n = lws_http_action(context, wsi->u.http2.stream_wsi); lwsl_info(" action result %d\n", n); break; + case LWS_HTTP2_FRAME_TYPE_PING: + if (wsi->u.http2.flags & LWS_HTTP2_FLAG_SETTINGS_ACK) { // ack + } else { /* they're sending us a ping request */ + lws_set_protocol_write_pending(context, wsi, LWS_PPS_HTTP2_PONG); + } + break; } break; } @@ -302,6 +327,12 @@ lws_http2_parser(struct libwebsocket_context *context, /* non-ACK coming in means we must ACK it */ lws_set_protocol_write_pending(context, wsi, LWS_PPS_HTTP2_ACK_SETTINGS); break; + case LWS_HTTP2_FRAME_TYPE_PING: + if (wsi->u.http2.stream_id) + return 1; + if (wsi->u.http2.length != 8) + return 1; + break; case LWS_HTTP2_FRAME_TYPE_CONTINUATION: if (wsi->u.http2.END_HEADERS) return 1; @@ -418,6 +449,17 @@ int lws_http2_do_pps_send(struct libwebsocket_context *context, struct libwebsoc return lws_http_action(context, swsi); } break; + case LWS_PPS_HTTP2_PONG: + memcpy(&settings[LWS_SEND_BUFFER_PRE_PADDING], wsi->u.http2.ping_payload, 8); + n = lws_http2_frame_write(wsi, LWS_HTTP2_FRAME_TYPE_PING, + LWS_HTTP2_FLAG_SETTINGS_ACK, + LWS_HTTP2_STREAM_ID_MASTER, 8, + &settings[LWS_SEND_BUFFER_PRE_PADDING]); + if (n != 8) { + lwsl_info("send %d %d\n", n, m); + return 1; + } + break; default: break; } diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 9ff23c1e..ac7e7c3e 100755 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -325,6 +325,7 @@ enum lws_pending_protocol_send { LWS_PPS_NONE, LWS_PPS_HTTP2_MY_SETTINGS, LWS_PPS_HTTP2_ACK_SETTINGS, + LWS_PPS_HTTP2_PONG, }; enum lws_rx_parse_state { @@ -696,6 +697,8 @@ struct _lws_http2_related { unsigned char flags; unsigned char frame_state; unsigned char padding; + + unsigned char ping_payload[8]; unsigned short round_robin_POLLOUT; unsigned short count_POLLOUT_children; diff --git a/lib/ssl-http2.c b/lib/ssl-http2.c index 445e87d9..134231f2 100644 --- a/lib/ssl-http2.c +++ b/lib/ssl-http2.c @@ -100,7 +100,9 @@ lws_context_init_http2_ssl(struct libwebsocket_context *context) SSL_CTX_set_alpn_select_cb(context->ssl_ctx, alpn_cb, &protos); lwsl_notice(" HTTP2 / ALPN enabled\n"); #else - lwsl_notice(" HTTP2 / ALPN configured but not supported by OpenSSL version 0x%x\n", OPENSSL_VERSION_NUMBER); + lwsl_notice( + " HTTP2 / ALPN configured but not supported by OpenSSL 0x%x\n", + OPENSSL_VERSION_NUMBER); #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L } @@ -119,36 +121,37 @@ void lws_http2_configure_if_upgraded(struct libwebsocket *wsi) method = "npn"; } - if (len) { - lwsl_info("negotiated %s using %s\n", name, method); - wsi->use_ssl = 1; - if (strncmp((char *)name, "http/1.1", 8) == 0) - return; - - /* http2 */ - - wsi->mode = LWS_CONNMODE_HTTP2_SERVING; - wsi->state = WSI_STATE_HTTP2_AWAIT_CLIENT_PREFACE; - - /* adopt the header info */ - - ah = wsi->u.hdr.ah; - - wsi->mode = LWS_CONNMODE_HTTP2_SERVING; - - /* union transition */ - memset(&wsi->u, 0, sizeof(wsi->u)); - - /* http2 union member has http union struct at start */ - wsi->u.http.ah = ah; - - lws_http2_init(&wsi->u.http2.peer_settings); - lws_http2_init(&wsi->u.http2.my_settings); - - /* HTTP2 union */ - - } else + if (!len) { lwsl_info("no npn/alpn upgrade\n"); + return; + } + + lwsl_info("negotiated %s using %s\n", name, method); + wsi->use_ssl = 1; + if (strncmp((char *)name, "http/1.1", 8) == 0) + return; + + /* http2 */ + + wsi->mode = LWS_CONNMODE_HTTP2_SERVING; + wsi->state = WSI_STATE_HTTP2_AWAIT_CLIENT_PREFACE; + + /* adopt the header info */ + + ah = wsi->u.hdr.ah; + + wsi->mode = LWS_CONNMODE_HTTP2_SERVING; + + /* union transition */ + memset(&wsi->u, 0, sizeof(wsi->u)); + + /* http2 union member has http union struct at start */ + wsi->u.http.ah = ah; + + lws_http2_init(&wsi->u.http2.peer_settings); + lws_http2_init(&wsi->u.http2.my_settings); + + /* HTTP2 union */ #endif }