mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
http2 handle flags
Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
parent
0c51239023
commit
91b0589795
6 changed files with 85 additions and 23 deletions
19
lib/http2.c
19
lib/http2.c
|
@ -212,6 +212,7 @@ lws_http2_parser(struct libwebsocket_context *context,
|
|||
return 1;
|
||||
break;
|
||||
case LWS_HTTP2_FRAME_TYPE_HEADERS:
|
||||
lwsl_info(" %02X\n", c);
|
||||
if (lws_hpack_interpret(context, wsi->u.http2.stream_wsi, c))
|
||||
return 1;
|
||||
break;
|
||||
|
@ -276,11 +277,16 @@ lws_http2_parser(struct libwebsocket_context *context,
|
|||
if (wsi->u.http2.stream_id)
|
||||
return 1;
|
||||
|
||||
if (wsi->u.http2.flags & 1) { // ack
|
||||
} else {
|
||||
if (wsi->u.http2.flags & LWS_HTTP2_FLAG_SETTINGS_ACK) { // ack
|
||||
} else
|
||||
/* 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_CONTINUATION:
|
||||
if (wsi->u.http2.END_HEADERS)
|
||||
return 1;
|
||||
goto update_end_headers;
|
||||
|
||||
case LWS_HTTP2_FRAME_TYPE_HEADERS:
|
||||
lwsl_info("LWS_HTTP2_FRAME_TYPE_HEADERS: stream_id = %d\n", wsi->u.http2.stream_id);
|
||||
if (!wsi->u.http2.stream_id)
|
||||
|
@ -291,6 +297,13 @@ lws_http2_parser(struct libwebsocket_context *context,
|
|||
|
||||
if (!wsi->u.http2.stream_wsi)
|
||||
return 1;
|
||||
|
||||
/* END_STREAM means after servicing this, close the stream */
|
||||
wsi->u.http2.END_STREAM = !!(wsi->u.http2.flags & LWS_HTTP2_FLAG_END_STREAM);
|
||||
update_end_headers:
|
||||
/* no END_HEADERS means CONTINUATION must come */
|
||||
wsi->u.http2.END_HEADERS = !!(wsi->u.http2.flags & LWS_HTTP2_FLAG_END_HEADERS);
|
||||
break;
|
||||
}
|
||||
if (wsi->u.http2.length == 0)
|
||||
wsi->u.http2.frame_state = 0;
|
||||
|
|
|
@ -1089,6 +1089,8 @@ lws_add_http_header_status(struct libwebsocket_context *context,
|
|||
unsigned char **p,
|
||||
unsigned char *end);
|
||||
|
||||
LWS_EXTERN int lws_http_transaction_completed(struct libwebsocket *wsi);
|
||||
|
||||
#ifdef LWS_USE_LIBEV
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
libwebsocket_initloop(
|
||||
|
|
|
@ -441,7 +441,7 @@ send_raw:
|
|||
n = LWS_HTTP2_FRAME_TYPE_DATA;
|
||||
if (protocol == LWS_WRITE_HTTP_HEADERS) {
|
||||
n = LWS_HTTP2_FRAME_TYPE_HEADERS;
|
||||
flags = LWS_HTTP2_FLAGS__HEADER__END_HEADER;
|
||||
flags = LWS_HTTP2_FLAG_END_HEADERS;
|
||||
}
|
||||
return lws_http2_frame_write(wsi, n, flags, wsi->u.http2.my_stream_id, len, buf);
|
||||
}
|
||||
|
|
|
@ -608,12 +608,19 @@ enum lws_http2_wellknown_frame_types {
|
|||
LWS_HTTP2_FRAME_TYPE_COUNT /* always last */
|
||||
};
|
||||
|
||||
enum lws_http2_flags {
|
||||
LWS_HTTP2_FLAG_END_STREAM = 1,
|
||||
LWS_HTTP2_FLAG_END_HEADERS = 4,
|
||||
LWS_HTTP2_FLAG_PADDED = 8,
|
||||
LWS_HTTP2_FLAG_PRIORITY = 0x20,
|
||||
|
||||
LWS_HTTP2_FLAG_SETTINGS_ACK = 1,
|
||||
};
|
||||
|
||||
#define LWS_HTTP2_STREAM_ID_MASTER 0
|
||||
#define LWS_HTTP2_FRAME_HEADER_LENGTH 9
|
||||
#define LWS_HTTP2_SETTINGS_LENGTH 6
|
||||
|
||||
#define LWS_HTTP2_FLAGS__HEADER__END_HEADER 4
|
||||
|
||||
struct http2_settings {
|
||||
unsigned int setting[LWS_HTTP2_SETTINGS__COUNT];
|
||||
};
|
||||
|
@ -661,6 +668,9 @@ struct _lws_http2_related {
|
|||
unsigned char type;
|
||||
unsigned char flags;
|
||||
unsigned char frame_state;
|
||||
|
||||
unsigned int END_STREAM:1;
|
||||
unsigned int END_HEADERS:1;
|
||||
|
||||
/* hpack */
|
||||
enum http2_hpack_state hpack;
|
||||
|
@ -862,6 +872,7 @@ libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
|
|||
LWS_EXTERN int
|
||||
lws_handle_POLLOUT_event(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd);
|
||||
|
||||
/*
|
||||
* EXTENSIONS
|
||||
*/
|
||||
|
|
44
lib/server.c
44
lib/server.c
|
@ -640,6 +640,32 @@ libwebsocket_create_new_server_wsi(struct libwebsocket_context *context)
|
|||
return new_wsi;
|
||||
}
|
||||
|
||||
/**
|
||||
* lws_http_transaction_completed() - wait for new http transaction or close
|
||||
* @wsi: websocket connection
|
||||
*
|
||||
* Returns 1 if the HTTP connection must close now
|
||||
* Returns 0 and resets connection to wait for new HTTP header /
|
||||
* transaction if possible
|
||||
*/
|
||||
|
||||
LWS_VISIBLE
|
||||
int lws_http_transaction_completed(struct libwebsocket *wsi)
|
||||
{
|
||||
/* if we can't go back to accept new headers, drop the connection */
|
||||
if (wsi->u.http.connection_type != HTTP_CONNECTION_KEEP_ALIVE) {
|
||||
lwsl_info("%s: close connection\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* otherwise set ourselves up ready to go again */
|
||||
wsi->state = WSI_STATE_HTTP;
|
||||
|
||||
lwsl_info("%s: await new transaction\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lws_server_socket_service(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd)
|
||||
{
|
||||
|
@ -739,8 +765,9 @@ try_pollout:
|
|||
break;
|
||||
}
|
||||
|
||||
/* nonzero for completion or error */
|
||||
if (libwebsockets_serve_http_file_fragment(context, wsi))
|
||||
/* >0 == completion, <0 == error */
|
||||
n = libwebsockets_serve_http_file_fragment(context, wsi);
|
||||
if (n < 0 || (n > 0 && lws_http_transaction_completed(wsi)))
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
break;
|
||||
|
@ -1026,7 +1053,8 @@ LWS_VISIBLE int libwebsockets_return_http_status(
|
|||
* local files down the http link in a single step.
|
||||
*
|
||||
* Returning <0 indicates error and the wsi should be closed. Returning
|
||||
* >0 indicates the file was completely sent and the wsi should be closed.
|
||||
* >0 indicates the file was completely sent and
|
||||
* lws_http_transaction_completed() called on the wsi (and close if != 0)
|
||||
* ==0 indicates the file transfer is started and needs more service later,
|
||||
* the wsi should be left alone.
|
||||
*/
|
||||
|
@ -1055,14 +1083,14 @@ LWS_VISIBLE int libwebsockets_serve_http_file(
|
|||
}
|
||||
|
||||
if (lws_add_http_header_status(context, wsi, 200, &p, end))
|
||||
return 1;
|
||||
return -1;
|
||||
if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_SERVER, (unsigned char *)"libwebsockets", 13, &p, end))
|
||||
return 1;
|
||||
return -1;
|
||||
if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)content_type, strlen(content_type), &p, end))
|
||||
return 1;
|
||||
return -1;
|
||||
n = sprintf((char *)clen, "%lu", (unsigned long)wsi->u.http.filelen);
|
||||
if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH, clen, n, &p, end))
|
||||
return 1;
|
||||
return -1;
|
||||
|
||||
if (other_headers) {
|
||||
if ((end - p) < other_headers_len)
|
||||
|
@ -1072,7 +1100,7 @@ LWS_VISIBLE int libwebsockets_serve_http_file(
|
|||
}
|
||||
|
||||
if (lws_finalize_http_header(context, wsi, &p, end))
|
||||
return 1;
|
||||
return -1;
|
||||
|
||||
ret = libwebsocket_write(wsi, response,
|
||||
p - response, LWS_WRITE_HTTP_HEADERS);
|
||||
|
|
|
@ -182,14 +182,14 @@ static int callback_http(struct libwebsocket_context *context,
|
|||
if (len < 1) {
|
||||
libwebsockets_return_http_status(context, wsi,
|
||||
HTTP_STATUS_BAD_REQUEST, NULL);
|
||||
return -1;
|
||||
goto try_to_reuse;
|
||||
}
|
||||
|
||||
/* this example server has no concept of directories */
|
||||
if (strchr((const char *)in + 1, '/')) {
|
||||
libwebsockets_return_http_status(context, wsi,
|
||||
HTTP_STATUS_FORBIDDEN, NULL);
|
||||
return -1;
|
||||
goto try_to_reuse;
|
||||
}
|
||||
|
||||
/* if a legal POST URL, let it continue and accept data */
|
||||
|
@ -306,9 +306,10 @@ static int callback_http(struct libwebsocket_context *context,
|
|||
other_headers = leaf_path;
|
||||
}
|
||||
|
||||
if (libwebsockets_serve_http_file(context, wsi, buf,
|
||||
mimetype, other_headers, n))
|
||||
return -1; /* through completion or error, close the socket */
|
||||
n = libwebsockets_serve_http_file(context, 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 */
|
||||
|
||||
/*
|
||||
* notice that the sending of the file completes asynchronously,
|
||||
|
@ -331,16 +332,15 @@ static int callback_http(struct libwebsocket_context *context,
|
|||
|
||||
case LWS_CALLBACK_HTTP_BODY_COMPLETION:
|
||||
lwsl_notice("LWS_CALLBACK_HTTP_BODY_COMPLETION\n");
|
||||
/* the whole of the sent body arried, close the connection */
|
||||
/* the whole of the sent body arrived, close or reuse the connection */
|
||||
libwebsockets_return_http_status(context, wsi,
|
||||
HTTP_STATUS_OK, NULL);
|
||||
|
||||
return -1;
|
||||
goto try_to_reuse;
|
||||
|
||||
case LWS_CALLBACK_HTTP_FILE_COMPLETION:
|
||||
// lwsl_info("LWS_CALLBACK_HTTP_FILE_COMPLETION seen\n");
|
||||
/* kill the connection after we sent one file */
|
||||
return -1;
|
||||
goto try_to_reuse;
|
||||
|
||||
case LWS_CALLBACK_HTTP_WRITEABLE:
|
||||
/*
|
||||
|
@ -386,6 +386,8 @@ flush_bail:
|
|||
libwebsocket_callback_on_writable(context, wsi);
|
||||
break;
|
||||
}
|
||||
close(pss->fd);
|
||||
goto try_to_reuse;
|
||||
|
||||
bail:
|
||||
close(pss->fd);
|
||||
|
@ -475,6 +477,12 @@ bail:
|
|||
}
|
||||
|
||||
return 0;
|
||||
|
||||
try_to_reuse:
|
||||
if (lws_http_transaction_completed(wsi))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue