diff --git a/lib/handshake.c b/lib/handshake.c index 28c02efd..7ba96838 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -532,6 +532,19 @@ libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len) wsi->ietf_spec_revision = atoi(wsi->utf8_token[WSI_TOKEN_VERSION].token); + /* + * Give the user code a chance to study the request and + * have the opportunity to deny it + */ + + if ((wsi->protocol->callback)(wsi, + LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION, + &wsi->utf8_token[0], NULL, 0)) { + fprintf(stderr, "User code denied connection\n"); + goto bail; + } + + /* * Perform the handshake according to the protocol version the * client announced diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index b8a07c94..72962f90 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -41,6 +41,7 @@ enum libwebsocket_callback_reasons { LWS_CALLBACK_CLIENT_WRITEABLE, LWS_CALLBACK_HTTP, LWS_CALLBACK_BROADCAST, + LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION, /* external poll() management support */ LWS_CALLBACK_ADD_POLL_FD, @@ -71,6 +72,52 @@ enum libwebsocket_write_protocol { LWS_WRITE_CLIENT_IGNORE_XOR_MASK = 0x80 }; +/* + * you need these to look at headers that have been parsed if using the + * LWS_CALLBACK_FILTER_CONNECTION callback. If a header from the enum + * list below is absent, .token = NULL and token_len = 0. Otherwise .token + * points to .token_len chars containing that header content. + */ + +struct lws_tokens { + char *token; + int token_len; +}; + +enum lws_token_indexes { + WSI_TOKEN_GET_URI, + WSI_TOKEN_HOST, + WSI_TOKEN_CONNECTION, + WSI_TOKEN_KEY1, + WSI_TOKEN_KEY2, + WSI_TOKEN_PROTOCOL, + WSI_TOKEN_UPGRADE, + WSI_TOKEN_ORIGIN, + WSI_TOKEN_DRAFT, + WSI_TOKEN_CHALLENGE, + + /* new for 04 */ + WSI_TOKEN_KEY, + WSI_TOKEN_VERSION, + WSI_TOKEN_SWORIGIN, + + /* new for 05 */ + WSI_TOKEN_EXTENSIONS, + + /* client receives these */ + WSI_TOKEN_ACCEPT, + WSI_TOKEN_NONCE, + WSI_TOKEN_HTTP, + + /* always last real token index*/ + WSI_TOKEN_COUNT, + /* parser state additions */ + WSI_TOKEN_NAME_PART, + WSI_TOKEN_SKIPPING, + WSI_TOKEN_SKIPPING_SAW_CR, + WSI_PARSING_COMPLETE +}; + struct libwebsocket; struct libwebsocket_context; @@ -133,6 +180,16 @@ struct libwebsocket_context; * was able to take another packet without blocking, you'll get * this callback at the next call to the service loop function. * + * LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: called when the handshake has + * been received and parsed from the client, but the response is + * not sent yet. Return non-zero to disallow the connection. + * @user is a pointer to an array of struct lws_tokens, you can + * use the header enums lws_token_indexes from libwebsockets.h + * to check for and read the supported header presence and + * content before deciding to allow the handshake to proceed or + * to kill the connection. + * + * * The next four reasons are optional and only need taking care of if you * will be integrating libwebsockets sockets into an external polling * array. diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index bf8d5286..9376025e 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -99,40 +99,6 @@ enum lws_connection_states { WSI_STATE_RETURNED_CLOSE_ALREADY }; -enum lws_token_indexes { - WSI_TOKEN_GET_URI, - WSI_TOKEN_HOST, - WSI_TOKEN_CONNECTION, - WSI_TOKEN_KEY1, - WSI_TOKEN_KEY2, - WSI_TOKEN_PROTOCOL, - WSI_TOKEN_UPGRADE, - WSI_TOKEN_ORIGIN, - WSI_TOKEN_DRAFT, - WSI_TOKEN_CHALLENGE, - - /* new for 04 */ - WSI_TOKEN_KEY, - WSI_TOKEN_VERSION, - WSI_TOKEN_SWORIGIN, - - /* new for 05 */ - WSI_TOKEN_EXTENSIONS, - - /* client receives these */ - WSI_TOKEN_ACCEPT, - WSI_TOKEN_NONCE, - WSI_TOKEN_HTTP, - - /* always last real token index*/ - WSI_TOKEN_COUNT, - /* parser state additions */ - WSI_TOKEN_NAME_PART, - WSI_TOKEN_SKIPPING, - WSI_TOKEN_SKIPPING_SAW_CR, - WSI_PARSING_COMPLETE -}; - enum lws_rx_parse_state { LWS_RXPS_NEW, @@ -161,11 +127,6 @@ enum lws_rx_parse_state { }; -struct lws_tokens { - char *token; - int token_len; -}; - enum connection_mode { LWS_CONNMODE_WS_SERVING, LWS_CONNMODE_WS_CLIENT, diff --git a/libwebsockets-api-doc.html b/libwebsockets-api-doc.html index 40a0c0b1..2c08d1fb 100644 --- a/libwebsockets-api-doc.html +++ b/libwebsockets-api-doc.html @@ -485,6 +485,59 @@ accept another write packet without blocking. If it already was able to take another packet without blocking, you'll get this callback at the next call to the service loop function. +
+called when the handshake has +been received and parsed from the client, but the response is +not sent yet. Return non-zero to disallow the connection. +user is a pointer to an array of +++
+The next four reasons are optional and only need taking care of if you +will be integrating libwebsockets sockets into an external polling +array. +
+libwebsocket deals with its poll loop +internally, but in the case you are integrating with another +server you will need to have libwebsocket sockets share a +polling array with the other server. This and the other +POLL_FD related callbacks let you put your specialized +poll array interface code in the callback for protocol 0, the +first protocol you support, usually the HTTP protocol in the +serving case. This callback happens when a socket needs to be ++
+user contains the fd, and +len is the events bitmap (like, POLLIN). If you are using the +internal polling loop (the "service" callback), you can just +ignore these callbacks. ++
+This callback happens when a socket descriptor +needs to be removed from an external polling array. user is +the socket desricptor. If you are using the internal polling +loop, you can just ignore it. ++
+This callback happens when libwebsockets +wants to modify the events for the socket descriptor in user. +The handler should OR len on to the events member of the pollfd +struct for this socket descriptor. If you are using the +internal polling loop, you can just ignore it. ++
+This callback occurs when libwebsockets +wants to modify the events for the socket descriptor in user. +The handler should AND ~len on to the events member of the +pollfd struct for this socket descriptor. If you are using the +internal polling loop, you can just ignore it. +