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

adopt: allow binding to parent at same time

- if protocol set, allocate own user_space

   If the child wsi wants the parent wsi user_space, it can use

       lws_wsi_user(lws_get_parent(child_wsi))

 - raw file close processing handles parent-child relationship
This commit is contained in:
Per Bothner 2017-03-03 07:36:08 +08:00 committed by Andy Green
parent 2495afa604
commit 60f4569bb8
4 changed files with 79 additions and 49 deletions

View file

@ -142,11 +142,34 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs)
lws_remove_from_timeout_list(wsi);
}
static void
lws_remove_child_from_any_parent(struct lws *wsi)
{
struct lws **pwsi;
if (wsi->parent) {
/* detach ourselves from parent's child list */
pwsi = &wsi->parent->child_list;
while (*pwsi) {
if (*pwsi == wsi) {
//lwsl_notice("%s: detach %p from parent %p\n",
// __func__, wsi, wsi->parent);
*pwsi = wsi->sibling_list;
break;
}
pwsi = &(*pwsi)->sibling_list;
}
if (*pwsi)
lwsl_err("%s: failed to detach from parent\n",
__func__);
}
}
void
lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
{
struct lws_context_per_thread *pt;
struct lws **pwsi, *wsi1, *wsi2;
struct lws *wsi1, *wsi2;
struct lws_context *context;
struct lws_tokens eff_buf;
int n, m, ret;
@ -154,15 +177,6 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
if (!wsi)
return;
if (wsi->mode == LWSCM_RAW_FILEDESC) {
remove_wsi_socket_from_fds(wsi);
wsi->protocol->callback(wsi,
LWS_CALLBACK_RAW_CLOSE_FILE, wsi->user_space, NULL, 0);
lws_free_wsi(wsi);
return;
}
lws_access_log(wsi);
#if defined(LWS_WITH_ESP8266)
if (wsi->premature_rx)
@ -200,6 +214,17 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
wsi->child_list = NULL;
}
if (wsi->mode == LWSCM_RAW_FILEDESC) {
lws_remove_child_from_any_parent(wsi);
remove_wsi_socket_from_fds(wsi);
wsi->protocol->callback(wsi,
LWS_CALLBACK_RAW_CLOSE_FILE,
wsi->user_space, NULL, 0);
lws_free_wsi(wsi);
return;
}
#ifdef LWS_WITH_CGI
if (wsi->mode == LWSCM_CGI) {
/* we are not a network connection, but a handler for CGI io */
@ -400,22 +425,8 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
just_kill_connection:
if (wsi->parent) {
/* detach ourselves from parent's child list */
pwsi = &wsi->parent->child_list;
while (*pwsi) {
if (*pwsi == wsi) {
//lwsl_notice("%s: detach %p from parent %p\n",
// __func__, wsi, wsi->parent);
*pwsi = wsi->sibling_list;
break;
}
pwsi = &(*pwsi)->sibling_list;
}
if (*pwsi)
lwsl_err("%s: failed to detach from parent\n",
__func__);
}
lws_remove_child_from_any_parent(wsi);
#if 0
/* manage the vhost same protocol list entry */

View file

@ -3725,9 +3725,10 @@ LWS_VISIBLE LWS_EXTERN struct lws *
lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd);
typedef enum {
LWS_ADOPT_HTTP = 1, /* absent implies RAW */
LWS_ADOPT_SOCKET = 2, /* absent implies file descriptor */
LWS_ADOPT_ALLOW_SSL = 4 /* if set requires LWS_ADOPT_SOCKET */
LWS_ADOPT_RAW_FILE_DESC = 0, /* convenience constant */
LWS_ADOPT_HTTP = 1, /* flag: absent implies RAW */
LWS_ADOPT_SOCKET = 2, /* flag: absent implies file descr */
LWS_ADOPT_ALLOW_SSL = 4 /* flag: if set requires LWS_ADOPT_SOCKET */
} lws_adoption_type;
typedef union {
@ -3743,17 +3744,21 @@ typedef union {
* \param type: OR-ed combinations of lws_adoption_type flags
* \param fd: union with either .sockfd or .filefd set
* \param vh_prot_name: NULL or vh protocol name to bind raw connection to
* \param parent: NULL or struct lws to attach new_wsi to as a child
*
* Either returns new wsi bound to accept_fd, or closes accept_fd and
* returns NULL, having cleaned up any new wsi pieces.
*
* If LWS_ADOPT_SOCKET is set, LWS adopts the socket in http serving mode, it's
* ready to accept an upgrade to ws or just serve http.
*
* parent may be NULL, if given it should be an existing wsi that will become the
* parent of the new wsi created by this call.
*/
LWS_VISIBLE struct lws *
lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
lws_sock_file_fd_type fd, const char *vh_prot_name);
lws_sock_file_fd_type fd, const char *vh_prot_name,
struct lws *parent);
/**
* lws_adopt_socket_readbuf() - adopt foreign socket and first rx as if listen socket accepted it

View file

@ -1690,7 +1690,8 @@ lws_http_transaction_completed(struct lws *wsi)
LWS_VISIBLE struct lws *
lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
lws_sock_file_fd_type fd, const char *vh_prot_name)
lws_sock_file_fd_type fd, const char *vh_prot_name,
struct lws *parent)
{
struct lws_context *context = vh->context;
struct lws *new_wsi = lws_create_new_server_wsi(vh);
@ -1702,27 +1703,32 @@ lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
return NULL;
}
new_wsi->desc = fd;
new_wsi->protocol = &context->vhost_list->
protocols[vh->default_protocol_index];
if (parent) {
new_wsi->parent = parent;
new_wsi->sibling_list = parent->child_list;
parent->child_list = new_wsi;
}
if (!(type & LWS_ADOPT_SOCKET)) {
new_wsi->desc = fd;
if (vh_prot_name) {
new_wsi->protocol = lws_vhost_name_to_protocol(new_wsi->vhost,
vh_prot_name);
vh_prot_name);
if (!new_wsi->protocol) {
lwsl_err("Protocol %s not enabled on vhost %s\n",
vh_prot_name, new_wsi->vhost->name);
lws_free(new_wsi);
return NULL;
goto bail;
}
}
if (type & LWS_ADOPT_SOCKET) {
if (lws_ensure_user_space(new_wsi))
goto bail;
} else
new_wsi->protocol = &context->vhost_list->
protocols[vh->default_protocol_index];
if (type & LWS_ADOPT_SOCKET) { /* socket desc */
lwsl_debug("%s: new wsi %p, sockfd %d\n", __func__, new_wsi,
(int)(size_t)fd.sockfd);
/* the transport is accepted... give him time to negotiate */
lws_set_timeout(new_wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
context->timeout_secs);
@ -1732,7 +1738,7 @@ lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
esp8266_tcp_stream_accept(accept_fd, new_wsi);
#endif
#endif
} else //* file desc */
} else /* file desc */
lwsl_debug("%s: new wsi %p, filefd %d\n", __func__, new_wsi,
(int)(size_t)fd.filefd);
@ -1756,8 +1762,7 @@ lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
lws_set_timeout(new_wsi, NO_PENDING_TIMEOUT, 0);
compatible_close(new_wsi->desc.sockfd);
}
lws_free(new_wsi);
return NULL;
goto bail;
}
if (!LWS_SSL_ENABLED(new_wsi->vhost) || !(type & LWS_ADOPT_ALLOW_SSL) ||
@ -1804,6 +1809,15 @@ fail:
lws_close_free_wsi(new_wsi, LWS_CLOSE_STATUS_NOSTATUS);
return NULL;
bail:
if (parent)
parent->child_list = new_wsi->sibling_list;
if (new_wsi->user_space)
lws_free(new_wsi->user_space);
lws_free(new_wsi);
return NULL;
}
LWS_VISIBLE struct lws *
@ -1813,7 +1827,7 @@ lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd)
fd.sockfd = accept_fd;
return lws_adopt_descriptor_vhost(vh, LWS_ADOPT_SOCKET |
LWS_ADOPT_HTTP | LWS_ADOPT_ALLOW_SSL, fd, NULL);
LWS_ADOPT_HTTP | LWS_ADOPT_ALLOW_SSL, fd, NULL, NULL);
}
LWS_VISIBLE struct lws *

View file

@ -101,7 +101,7 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason,
}
lwsl_notice("FIFO %s created\n", vhd->fifo_path);
u.filefd = vhd->fifo;
if (!lws_adopt_descriptor_vhost(vhd->vhost, 0, u, "protocol-lws-raw-test")) {
if (!lws_adopt_descriptor_vhost(vhd->vhost, 0, u, "protocol-lws-raw-test", NULL)) {
lwsl_err("Failed to adopt fifo descriptor\n");
close(vhd->fifo);
unlink(vhd->fifo_path);
@ -167,7 +167,7 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason,
}
lwsl_notice("FIFO %s reopened\n", vhd->fifo_path);
u.filefd = vhd->fifo;
if (!lws_adopt_descriptor_vhost(vhd->vhost, 0, u, "protocol-lws-raw-test")) {
if (!lws_adopt_descriptor_vhost(vhd->vhost, 0, u, "protocol-lws-raw-test", NULL)) {
lwsl_err("Failed to adopt fifo descriptor\n");
close(vhd->fifo);
return 1;