char *m = mask_summing_buf;
int nonce_len = 0;
int accept_len;
+ char *c;
+ char ext_name[128];
+ struct libwebsocket_extension * ext;
+ int ext_count = 0;
+ int more = 1;
if (!wsi->utf8_token[WSI_TOKEN_HOST].token_len ||
!wsi->utf8_token[WSI_TOKEN_KEY].token_len) {
p += wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len;
}
+ /*
+ * Figure out which extensions the client has that we want to
+ * enable on this connection, and give him back the list
+ */
+
+ if (wsi->utf8_token[WSI_TOKEN_EXTENSIONS].token_len) {
+ strcpy(p, "\x0d\x0aSec-WebSocket-Extensions: ");
+ p += strlen("\x0d\x0aSec-WebSocket-Extensions: ");
+
+ /*
+ * break down the list of client extensions
+ * and go through them
+ */
+
+ c = wsi->utf8_token[WSI_TOKEN_EXTENSIONS].token;
+ n = 0;
+ while (more) {
+
+ if (*c && *c != ',') {
+ ext_name[n] = *c++;
+ if (n < sizeof(ext_name) - 1)
+ n++;
+ continue;
+ }
+ ext_name[n] = '\0';
+ if (!*c)
+ more = 0;
+
+ /* check a client's extension against our support */
+
+ ext = wsi->protocol->owning_server->extensions;
+
+ while (ext && ext->callback) {
+
+ if (strcmp(ext_name, ext->name)) {
+ ext++;
+ continue;
+ }
+
+ /*
+ * oh, we do support this one he
+ * asked for... but let's ask user
+ * code if it's OK to apply it on this
+ * particular connection + protocol
+ */
+
+ n = wsi->protocol->owning_server->
+ protocols[0].callback(
+ wsi->protocol->owning_server,
+ wsi,
+ LWS_CALLBACK_CONFIRM_EXTENSION_OKAY,
+ wsi->user_space, ext_name, 0);
+
+ /*
+ * zero return from callback means
+ * go ahead and allow the extension,
+ * it's what we get if the callback is
+ * unhandled
+ */
+
+ if (n) {
+ ext++;
+ continue;
+ }
+
+ /* apply it */
+
+ if (ext_count)
+ *p++ = ',';
+ p += sprintf(p, ext_name);
+ ext_count++;
+
+ /* instantiate the extension on this conn */
+
+ wsi->active_extensions_user[
+ wsi->count_active_extensions] =
+ malloc(ext->per_session_data_size);
+ wsi->active_extensions[
+ wsi->count_active_extensions] = ext;
+
+ /* allow him to construct his context */
+
+ ext->callback(wsi->protocol->owning_server,
+ wsi, LWS_EXT_CALLBACK_CONSTRUCT,
+ wsi->active_extensions_user[
+ wsi->count_active_extensions], NULL, 0);
+
+ wsi->count_active_extensions++;
+
+ ext++;
+ }
+
+ n = 0;
+ }
+ }
+
+
/* end of response packet */
strcpy(p, "\x0d\x0a\x0d\x0a");
* specific callback for each one. The list is ended with an
* entry that has a NULL callback pointer.
* It's not const because we write the owning_server member
+ * @extensions: NULL or array of libwebsocket_extension structs listing the
+ * extensions this context supports
* @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
* to listen using SSL, set to the filepath to fetch the
* server cert from, otherwise NULL for unencrypted
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
+ LWS_CALLBACK_CONFIRM_EXTENSION_OKAY,
/* external poll() management support */
LWS_CALLBACK_ADD_POLL_FD,
LWS_CALLBACK_DEL_POLL_FD,
LWS_CALLBACK_CLEAR_MODE_POLL_FD,
};
+enum libwebsocket_extension_callback_reasons {
+ LWS_EXT_CALLBACK_CONSTRUCT,
+ LWS_EXT_CALLBACK_DESTROY,
+};
+
enum libwebsocket_write_protocol {
LWS_WRITE_TEXT,
LWS_WRITE_BINARY,
* Notice the callback is coming to protocols[0] all the time,
* because there is no specific protocol handshook yet.
*
+ * LWS_CALLBACK_CONFIRM_EXTENSION_OKAY: When the server handshake code
+ * sees that it does support a requested extension, before
+ * accepting the extension by additing to the list sent back to
+ * the client it gives this callback just to check that it's okay
+ * to use that extension. It calls back to the requested protocol
+ * and with @in being the extension name, @len is 0 and @user is
+ * valid. Note though at this time the ESTABLISHED callback hasn't
+ * happened yet so if you initialize @user content there, @user
+ * content during this callback might not be useful for anything.
+ * Notice this callback comes to protocols[0].
+ *
* The next four reasons are optional and only need taking care of if you
* will be integrating libwebsockets sockets into an external polling
* array.
const char *name;
int (*callback)(struct libwebsocket_context *context,
struct libwebsocket *wsi,
- enum libwebsocket_callback_reasons reason, void *user,
- void *in, size_t len);
+ enum libwebsocket_extension_callback_reasons reason,
+ void *user, void *in, size_t len);
size_t per_session_data_size;
};
specific callback for each one. The list is ended with an
entry that has a NULL callback pointer.
It's not const because we write the owning_server member
+<dt><b>extensions</b>
+<dd>NULL or array of libwebsocket_extension structs listing the
+extensions this context supports
<dt><b>ssl_cert_filepath</b>
<dd>If libwebsockets was compiled to use ssl, and you want
to listen using SSL, set to the filepath to fetch the
<p>
Notice the callback is coming to protocols[0] all the time,
because there is no specific protocol handshook yet.
+</blockquote>
+<h3>LWS_CALLBACK_CONFIRM_EXTENSION_OKAY</h3>
+<blockquote>
+When the server handshake code
+sees that it does support a requested extension, before
+accepting the extension by additing to the list sent back to
+the client it gives this callback just to check that it's okay
+to use that extension. It calls back to the requested protocol
+and with <tt><b>in</b></tt> being the extension name, <tt><b>len</b></tt> is 0 and <tt><b>user</b></tt> is
+valid. Note though at this time the ESTABLISHED callback hasn't
+happened yet so if you initialize <tt><b>user</b></tt> content there, <tt><b>user</b></tt>
+content during this callback might not be useful for anything.
+Notice this callback comes to protocols[0].
<p>
The next four reasons are optional and only need taking care of if you
will be integrating libwebsockets sockets into an external polling