1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

client: bind and drop protocol like server

HTTP server protocols have had for a while LWS_CALLBACK_HTTP_DROP/BIND_PROTOCOL
callbacks that mark when a wsi is attched to a protocol and detached.

It turns out this is generally useful for everything to know when a wsi is
joining a protocol and definitively completely finished with a protocol.

Particularly with client wsi where you provided the userdata externally, this
makes a clear point to free() it on the protocol binding being dropped.

This patch adds protocol bind / unbind callbacks to the role definition and
lets them operate on all roles.  For the various roles

HTTP server: LWS_CALLBACK_HTTP_BIND/DROP_PROTOCOL as before
HTTP client: LWS_CALLBACK_CLIENT_HTTP_BIND/DROP_PROTOCOL
ws server:   LWS_CALLBACK_WS_SERVER_BIND/DROP_PROTOCOL
ws client:   LWS_CALLBACK_WS_CLIENT_BIND/DROP_PROTOCOL
raw file:    LWS_CALLBACK_RAW_FILE_BIND/DROP_PROTOCOL
raw skt:     LWS_CALLBACK_RAW_SKT_BIND/DROP_PROTOCOL
This commit is contained in:
Andy Green 2018-08-18 14:11:29 +08:00
parent d461f46a97
commit 5c0b0450f2
12 changed files with 98 additions and 34 deletions

View file

@ -133,11 +133,21 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
wsi->protocol = &wsi->vhost->protocols[0];
wsi->client_pipeline = !!(i->ssl_connection & LCCSCF_PIPELINE);
/*
* PHASE 5: handle external user_space now, generic alloc is done in
* role finalization
*/
if (wsi && !wsi->user_space && i->userdata) {
wsi->user_space_externally_allocated = 1;
wsi->user_space = i->userdata;
}
if (local) {
lwsl_info("%s: protocol binding to %s\n", __func__, local);
p = lws_vhost_name_to_protocol(wsi->vhost, local);
if (p)
wsi->protocol = p;
lws_bind_protocol(wsi, p);
}
/*

View file

@ -544,7 +544,8 @@ lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p)
const struct lws_protocols *vp = wsi->vhost->protocols, *vpo;
if (wsi->protocol && wsi->protocol_bind_balance) {
wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_DROP_PROTOCOL,
wsi->protocol->callback(wsi,
wsi->role_ops->protocol_unbind_cb[!!lwsi_role_server(wsi)],
wsi->user_space, NULL, 0);
wsi->protocol_bind_balance = 0;
}
@ -581,7 +582,8 @@ lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p)
__func__, p, wsi->vhost->name);
}
if (wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_BIND_PROTOCOL,
if (wsi->protocol->callback(wsi, wsi->role_ops->protocol_bind_cb[
!!lwsi_role_server(wsi)],
wsi->user_space, NULL, 0))
return 1;
@ -742,15 +744,13 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, const char *
lwsi_state(wsi) == LRS_H1C_ISSUE_HANDSHAKE)
goto just_kill_connection;
if (!wsi->told_user_closed && lwsi_role_http(wsi) &&
lwsi_role_server(wsi)) {
if (wsi->user_space && wsi->protocol &&
wsi->protocol_bind_balance) {
wsi->protocol->callback(wsi,
LWS_CALLBACK_HTTP_DROP_PROTOCOL,
wsi->user_space, NULL, 0);
wsi->protocol_bind_balance = 0;
}
if (!wsi->told_user_closed && wsi->user_space && wsi->protocol &&
wsi->protocol_bind_balance) {
wsi->protocol->callback(wsi,
wsi->role_ops->protocol_unbind_cb[
!!lwsi_role_server(wsi)],
wsi->user_space, NULL, 0);
wsi->protocol_bind_balance = 0;
}
/*
@ -781,8 +781,10 @@ just_kill_connection:
wsi->protocol_bind_balance) {
lwsl_debug("%s: %p: DROP_PROTOCOL %s\n", __func__, wsi,
wsi->protocol->name);
wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_DROP_PROTOCOL,
wsi->user_space, NULL, 0);
wsi->protocol->callback(wsi,
wsi->role_ops->protocol_unbind_cb[
!!lwsi_role_server(wsi)],
wsi->user_space, NULL, 0);
wsi->protocol_bind_balance = 0;
}

View file

@ -940,23 +940,6 @@ enum lws_callback_reasons {
LWS_CALLBACK_WSI_DESTROY = 30,
/**< outermost (latest) wsi destroy notification to protocols[0] */
LWS_CALLBACK_HTTP_BIND_PROTOCOL = 49,
/**< By default, all HTTP handling is done in protocols[0].
* However you can bind different protocols (by name) to
* different parts of the URL space using callback mounts. This
* callback occurs in the new protocol when a wsi is bound
* to that protocol. Any protocol allocation related to the
* http transaction processing should be created then.
* These specific callbacks are necessary because with HTTP/1.1,
* a single connection may perform at series of different
* transactions at different URLs, thus the lifetime of the
* protocol bind is just for one transaction, not connection. */
LWS_CALLBACK_HTTP_DROP_PROTOCOL = 50,
/**< This is called when a transaction is unbound from a protocol.
* It indicates the connection completed its transaction and may
* do something different now. Any protocol allocation related
* to the http transaction processing should be destroyed. */
/* ---------------------------------------------------------------------
* ----- Callbacks related to Server TLS -----
@ -1145,6 +1128,24 @@ enum lws_callback_reasons {
* bytes per buffer).
*/
LWS_CALLBACK_HTTP_BIND_PROTOCOL = 49,
/**< By default, all HTTP handling is done in protocols[0].
* However you can bind different protocols (by name) to
* different parts of the URL space using callback mounts. This
* callback occurs in the new protocol when a wsi is bound
* to that protocol. Any protocol allocation related to the
* http transaction processing should be created then.
* These specific callbacks are necessary because with HTTP/1.1,
* a single connection may perform at series of different
* transactions at different URLs, thus the lifetime of the
* protocol bind is just for one transaction, not connection. */
LWS_CALLBACK_HTTP_DROP_PROTOCOL = 50,
/**< This is called when a transaction is unbound from a protocol.
* It indicates the connection completed its transaction and may
* do something different now. Any protocol allocation related
* to the http transaction processing should be destroyed. */
/* ---------------------------------------------------------------------
* ----- Callbacks related to HTTP Client -----
*/
@ -1192,6 +1193,9 @@ enum lws_callback_reasons {
* lws know by calling lws_client_http_body_pending(wsi, 0)
*/
LWS_CALLBACK_CLIENT_HTTP_BIND_PROTOCOL = 75,
LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL = 76,
/* ---------------------------------------------------------------------
* ----- Callbacks related to Websocket Server -----
*/
@ -1252,6 +1256,9 @@ enum lws_callback_reasons {
* happened yet so if you initialize user content there, user
* content during this callback might not be useful for anything. */
LWS_CALLBACK_WS_SERVER_BIND_PROTOCOL = 77,
LWS_CALLBACK_WS_SERVER_DROP_PROTOCOL = 78,
/* ---------------------------------------------------------------------
* ----- Callbacks related to Websocket Client -----
*/
@ -1392,6 +1399,9 @@ enum lws_callback_reasons {
* network connection from the client, there's no websocket protocol
* selected yet so this callback is issued only to protocol 0. */
LWS_CALLBACK_WS_CLIENT_BIND_PROTOCOL = 79,
LWS_CALLBACK_WS_CLIENT_DROP_PROTOCOL = 80,
/* ---------------------------------------------------------------------
* ----- Callbacks related to external poll loop integration -----
*/
@ -1519,6 +1529,9 @@ enum lws_callback_reasons {
LWS_CALLBACK_RAW_ADOPT = 62,
/**< RAW mode connection was adopted (equivalent to 'wsi created') */
LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL = 81,
LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL = 82,
/* ---------------------------------------------------------------------
* ----- Callbacks related to RAW file handles -----
*/
@ -1538,6 +1551,9 @@ enum lws_callback_reasons {
LWS_CALLBACK_RAW_CLOSE_FILE = 66,
/**< RAW mode wsi that adopted a file is closing */
LWS_CALLBACK_RAW_FILE_BIND_PROTOCOL = 83,
LWS_CALLBACK_RAW_FILE_DROP_PROTOCOL = 84,
/* ---------------------------------------------------------------------
* ----- Callbacks related to generic wsi events -----
*/

View file

@ -116,5 +116,7 @@ struct lws_role_ops role_ops_cgi = {
/* client_bind */ NULL,
/* writeable cb clnt, srv */ { 0, 0 },
/* close cb clnt, srv */ { 0, 0 },
/* protocol_bind_cb c,s */ { 0, 0 },
/* protocol_unbind_cb c,s */ { 0, 0 },
/* file_handle */ 0,
};

View file

@ -838,5 +838,9 @@ struct lws_role_ops role_ops_h1 = {
LWS_CALLBACK_HTTP_WRITEABLE },
/* close cb clnt, srv */ { LWS_CALLBACK_CLOSED_CLIENT_HTTP,
LWS_CALLBACK_CLOSED_HTTP },
/* protocol_bind cb c, srv */ { LWS_CALLBACK_CLIENT_HTTP_BIND_PROTOCOL,
LWS_CALLBACK_HTTP_BIND_PROTOCOL },
/* protocol_unbind cb c, srv */ { LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL,
LWS_CALLBACK_HTTP_DROP_PROTOCOL },
/* file_handle */ 0,
};

View file

@ -1082,5 +1082,9 @@ struct lws_role_ops role_ops_h2 = {
LWS_CALLBACK_HTTP_WRITEABLE },
/* close cb clnt, srv */ { LWS_CALLBACK_CLOSED_CLIENT_HTTP,
LWS_CALLBACK_CLOSED_HTTP },
/* protocol_bind cb c, srv */ { LWS_CALLBACK_CLIENT_HTTP_BIND_PROTOCOL,
LWS_CALLBACK_HTTP_BIND_PROTOCOL },
/* protocol_unbind cb c, srv */ { LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL,
LWS_CALLBACK_HTTP_DROP_PROTOCOL },
/* file_handle */ 0,
};

View file

@ -180,5 +180,7 @@ struct lws_role_ops role_ops_listen = {
/* client_bind */ NULL,
/* writeable cb clnt, srv */ { 0, 0 },
/* close cb clnt, srv */ { 0, 0 },
/* protocol_bind_cb c,s */ { 0, 0 },
/* protocol_unbind_cb c,s */ { 0, 0 },
/* file_handle */ 0,
};

View file

@ -79,5 +79,7 @@ struct lws_role_ops role_ops_pipe = {
/* client_bind */ NULL,
/* writeable cb clnt, srv */ { 0, 0 },
/* close cb clnt, srv */ { 0, 0 },
/* protocol_bind_cb c,s */ { 0, 0 },
/* protocol_unbind_cb c,s */ { 0, 0 },
/* file_handle */ 1,
};

View file

@ -241,6 +241,16 @@ struct lws_role_ops {
* (just client applies if no concept of client or server)
*/
uint16_t close_cb[2];
/*
* the callback reasons for protocol bind for client, server
* (just client applies if no concept of client or server)
*/
uint16_t protocol_bind_cb[2];
/*
* the callback reasons for protocol unbind for client, server
* (just client applies if no concept of client or server)
*/
uint16_t protocol_unbind_cb[2];
unsigned int file_handle:1; /* role operates on files not sockets */
};

View file

@ -100,5 +100,9 @@ struct lws_role_ops role_ops_raw_file = {
/* client_bind */ NULL,
/* writeable cb clnt, srv */ { LWS_CALLBACK_RAW_WRITEABLE_FILE, 0 },
/* close cb clnt, srv */ { LWS_CALLBACK_RAW_CLOSE_FILE, 0 },
/* protocol_bind cb c, srv */ { LWS_CALLBACK_RAW_FILE_BIND_PROTOCOL,
LWS_CALLBACK_RAW_FILE_BIND_PROTOCOL },
/* protocol_unbind cb c, srv */ { LWS_CALLBACK_RAW_FILE_DROP_PROTOCOL,
LWS_CALLBACK_RAW_FILE_DROP_PROTOCOL },
/* file_handle */ 1,
};

View file

@ -152,6 +152,9 @@ rops_adoption_bind_raw_skt(struct lws *wsi, int type, const char *vh_prot_name)
wsi->udp = lws_malloc(sizeof(*wsi->udp), "udp struct");
#endif
lws_role_transition(wsi, 0, type & LWS_ADOPT_ALLOW_SSL ? LRS_SSL_INIT :
LRS_ESTABLISHED, &role_ops_raw_skt);
if (vh_prot_name)
lws_bind_protocol(wsi, wsi->protocol);
else
@ -159,9 +162,6 @@ rops_adoption_bind_raw_skt(struct lws *wsi, int type, const char *vh_prot_name)
lws_bind_protocol(wsi,
&wsi->vhost->protocols[wsi->vhost->raw_protocol_index]);
lws_role_transition(wsi, 0, type & LWS_ADOPT_ALLOW_SSL ? LRS_SSL_INIT :
LRS_ESTABLISHED, &role_ops_raw_skt);
return 1; /* bound */
}
#endif
@ -224,5 +224,9 @@ struct lws_role_ops role_ops_raw_skt = {
#endif
/* writeable cb clnt, srv */ { LWS_CALLBACK_RAW_WRITEABLE, 0 },
/* close cb clnt, srv */ { LWS_CALLBACK_RAW_CLOSE, 0 },
/* protocol_bind cb c, srv */ { LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL,
LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL },
/* protocol_unbind cb c, srv */ { LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL,
LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL },
/* file_handle */ 0,
};

View file

@ -1988,5 +1988,9 @@ struct lws_role_ops role_ops_ws = {
LWS_CALLBACK_SERVER_WRITEABLE },
/* close cb clnt, srv */ { LWS_CALLBACK_CLIENT_CLOSED,
LWS_CALLBACK_CLOSED },
/* protocol_bind cb c, srv */ { LWS_CALLBACK_WS_CLIENT_BIND_PROTOCOL,
LWS_CALLBACK_WS_SERVER_BIND_PROTOCOL },
/* protocol_unbind cb c, srv */ { LWS_CALLBACK_WS_CLIENT_DROP_PROTOCOL,
LWS_CALLBACK_WS_SERVER_DROP_PROTOCOL },
/* file handles */ 0
};