mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-30 00:00:16 +01:00
add explicit parent child wsi relationships
wsi can have a full tree relationship with each other using linked lists. closing the parent ensures the children are closed first. Convert cgi to use this instead of his cgi-specific sub-wsi management. Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
parent
fe16003644
commit
494418abac
7 changed files with 91 additions and 24 deletions
|
@ -149,6 +149,13 @@ There are 4 new related callbacks
|
||||||
LWS_CALLBACK_RECEIVE_CLIENT_HTTP = 46,
|
LWS_CALLBACK_RECEIVE_CLIENT_HTTP = 46,
|
||||||
LWS_CALLBACK_COMPLETED_CLIENT_HTTP = 47,
|
LWS_CALLBACK_COMPLETED_CLIENT_HTTP = 47,
|
||||||
|
|
||||||
|
6) struct lws_client_connect_info has a new member
|
||||||
|
|
||||||
|
const char *parent_wsi
|
||||||
|
|
||||||
|
if non-NULL, the client wsi is set to be a child of parent_wsi. This ensures
|
||||||
|
if parent_wsi closes, then the client child is closed just before.
|
||||||
|
|
||||||
|
|
||||||
v1.7.0
|
v1.7.0
|
||||||
======
|
======
|
||||||
|
|
|
@ -407,7 +407,12 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
|
||||||
if (wsi && !wsi->user_space && i->userdata) {
|
if (wsi && !wsi->user_space && i->userdata) {
|
||||||
wsi->user_space_externally_allocated = 1;
|
wsi->user_space_externally_allocated = 1;
|
||||||
wsi->user_space = i->userdata;
|
wsi->user_space = i->userdata;
|
||||||
}
|
} else
|
||||||
|
/* if we stay in http, we can assign the user space now,
|
||||||
|
* otherwise do it after the protocol negotiated
|
||||||
|
*/
|
||||||
|
if (i->method)
|
||||||
|
lws_ensure_user_space(wsi);
|
||||||
|
|
||||||
#ifdef LWS_OPENSSL_SUPPORT
|
#ifdef LWS_OPENSSL_SUPPORT
|
||||||
wsi->use_ssl = i->ssl_connection;
|
wsi->use_ssl = i->ssl_connection;
|
||||||
|
@ -417,11 +422,6 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
wsi->protocol = &i->context->protocols[0];
|
|
||||||
if (wsi && !wsi->user_space && i->userdata) {
|
|
||||||
wsi->user_space_externally_allocated = 1;
|
|
||||||
wsi->user_space = i->userdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 2) stash the things from connect_info that we can't process without
|
/* 2) stash the things from connect_info that we can't process without
|
||||||
* an ah. Because if no ah, we will go on the ah waiting list and
|
* an ah. Because if no ah, we will go on the ah waiting list and
|
||||||
|
@ -469,6 +469,14 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
|
||||||
if (lws_header_table_attach(wsi, 0))
|
if (lws_header_table_attach(wsi, 0))
|
||||||
lwsl_debug("%s: went on ah wait list\n", __func__);
|
lwsl_debug("%s: went on ah wait list\n", __func__);
|
||||||
|
|
||||||
|
if (i->parent_wsi) {
|
||||||
|
lwsl_info("%s: created child %p of parent %p\n", __func__,
|
||||||
|
wsi, i->parent_wsi);
|
||||||
|
wsi->parent = i->parent_wsi;
|
||||||
|
wsi->sibling_list = i->parent_wsi->child_list;
|
||||||
|
i->parent_wsi->child_list = wsi;
|
||||||
|
}
|
||||||
|
|
||||||
return wsi;
|
return wsi;
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
|
|
|
@ -142,10 +142,11 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs)
|
||||||
void
|
void
|
||||||
lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
|
lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
|
||||||
{
|
{
|
||||||
struct lws_context *context;
|
|
||||||
struct lws_context_per_thread *pt;
|
struct lws_context_per_thread *pt;
|
||||||
int n, m, ret;
|
struct lws **pwsi, *wsi1, *wsi2;
|
||||||
|
struct lws_context *context;
|
||||||
struct lws_tokens eff_buf;
|
struct lws_tokens eff_buf;
|
||||||
|
int n, m, ret;
|
||||||
|
|
||||||
if (!wsi)
|
if (!wsi)
|
||||||
return;
|
return;
|
||||||
|
@ -153,24 +154,31 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
|
||||||
context = wsi->context;
|
context = wsi->context;
|
||||||
pt = &context->pt[(int)wsi->tsi];
|
pt = &context->pt[(int)wsi->tsi];
|
||||||
|
|
||||||
|
/* if we have children, close them first */
|
||||||
|
if (wsi->child_list) {
|
||||||
|
wsi2 = wsi->child_list;
|
||||||
|
while (wsi2) {
|
||||||
|
lwsl_notice("%s: closing %p: close child %p\n",
|
||||||
|
__func__, wsi, wsi2);
|
||||||
|
wsi1 = wsi2->sibling_list;
|
||||||
|
lws_close_free_wsi(wsi2, reason);
|
||||||
|
wsi2 = wsi1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef LWS_WITH_CGI
|
#ifdef LWS_WITH_CGI
|
||||||
if (wsi->mode == LWSCM_CGI) {
|
if (wsi->mode == LWSCM_CGI) {
|
||||||
/* we are not a network connection, but a handler for CGI io */
|
/* we are not a network connection, but a handler for CGI io */
|
||||||
assert(wsi->master);
|
if (wsi->parent && wsi->parent->cgi)
|
||||||
assert(wsi->master->cgi);
|
|
||||||
assert(wsi->master->cgi->stdwsi[(int)wsi->cgi_channel] == wsi);
|
|
||||||
/* end the binding between us and master */
|
/* end the binding between us and master */
|
||||||
wsi->master->cgi->stdwsi[(int)wsi->cgi_channel] = NULL;
|
wsi->parent->cgi->stdwsi[(int)wsi->cgi_channel] = NULL;
|
||||||
wsi->master = NULL;
|
|
||||||
wsi->socket_is_permanently_unusable = 1;
|
wsi->socket_is_permanently_unusable = 1;
|
||||||
|
|
||||||
goto just_kill_connection;
|
goto just_kill_connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wsi->cgi) {
|
if (wsi->cgi) {
|
||||||
/* we have a cgi going, we must kill it and close the
|
/* we have a cgi going, we must kill it */
|
||||||
* related stdin/out/err wsis first
|
|
||||||
*/
|
|
||||||
wsi->cgi->being_closed = 1;
|
wsi->cgi->being_closed = 1;
|
||||||
lws_cgi_kill(wsi);
|
lws_cgi_kill(wsi);
|
||||||
}
|
}
|
||||||
|
@ -327,6 +335,22 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
just_kill_connection:
|
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__);
|
||||||
|
}
|
||||||
|
|
||||||
#if LWS_POSIX
|
#if LWS_POSIX
|
||||||
/*
|
/*
|
||||||
|
@ -1182,6 +1206,18 @@ lws_wsi_user(struct lws *wsi)
|
||||||
return wsi->user_space;
|
return wsi->user_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LWS_VISIBLE LWS_EXTERN struct lws *
|
||||||
|
lws_get_parent(const struct lws *wsi)
|
||||||
|
{
|
||||||
|
return wsi->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
LWS_VISIBLE LWS_EXTERN struct lws *
|
||||||
|
lws_get_child(const struct lws *wsi)
|
||||||
|
{
|
||||||
|
return wsi->child_list;
|
||||||
|
}
|
||||||
|
|
||||||
LWS_VISIBLE LWS_EXTERN void
|
LWS_VISIBLE LWS_EXTERN void
|
||||||
lws_close_reason(struct lws *wsi, enum lws_close_status status,
|
lws_close_reason(struct lws *wsi, enum lws_close_status status,
|
||||||
unsigned char *buf, size_t len)
|
unsigned char *buf, size_t len)
|
||||||
|
@ -1480,9 +1516,11 @@ lws_cgi(struct lws *wsi, char * const *exec_array, int timeout_secs)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (n = 0; n < 3; n++) {
|
for (n = 0; n < 3; n++) {
|
||||||
cgi->stdwsi[n]->master = wsi;
|
|
||||||
if (insert_wsi_socket_into_fds(wsi->context, cgi->stdwsi[n]))
|
if (insert_wsi_socket_into_fds(wsi->context, cgi->stdwsi[n]))
|
||||||
goto bail3;
|
goto bail3;
|
||||||
|
cgi->stdwsi[n]->parent = wsi;
|
||||||
|
cgi->stdwsi[n]->sibling_list = wsi->child_list;
|
||||||
|
wsi->child_list = cgi->stdwsi[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
lws_change_pollfd(cgi->stdwsi[LWS_STDIN], LWS_POLLIN, LWS_POLLOUT);
|
lws_change_pollfd(cgi->stdwsi[LWS_STDIN], LWS_POLLIN, LWS_POLLOUT);
|
||||||
|
@ -1496,6 +1534,8 @@ lws_cgi(struct lws *wsi, char * const *exec_array, int timeout_secs)
|
||||||
|
|
||||||
lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, timeout_secs);
|
lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, timeout_secs);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* add us to the pt list of active cgis */
|
/* add us to the pt list of active cgis */
|
||||||
cgi->cgi_list = pt->cgi_list;
|
cgi->cgi_list = pt->cgi_list;
|
||||||
pt->cgi_list = cgi;
|
pt->cgi_list = cgi;
|
||||||
|
@ -1633,8 +1673,6 @@ lws_cgi_kill(struct lws *wsi)
|
||||||
if (wsi->cgi->pipe_fds[n][!!(n == 0)] >= 0) {
|
if (wsi->cgi->pipe_fds[n][!!(n == 0)] >= 0) {
|
||||||
close(wsi->cgi->pipe_fds[n][!!(n == 0)]);
|
close(wsi->cgi->pipe_fds[n][!!(n == 0)]);
|
||||||
wsi->cgi->pipe_fds[n][!!(n == 0)] = -1;
|
wsi->cgi->pipe_fds[n][!!(n == 0)] = -1;
|
||||||
|
|
||||||
lws_close_free_wsi(wsi->cgi->stdwsi[n], 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1410,6 +1410,9 @@ struct lws_context_creation_info {
|
||||||
* @client_exts: array of extensions that may be used on connection
|
* @client_exts: array of extensions that may be used on connection
|
||||||
* @method: if non-NULL, do this http method instead of ws[s] upgrade.
|
* @method: if non-NULL, do this http method instead of ws[s] upgrade.
|
||||||
* use "GET" to be a simple http client connection
|
* use "GET" to be a simple http client connection
|
||||||
|
* @parent_wsi: if another wsi is responsible for this connection, give it here.
|
||||||
|
* this is used to make sure if the parent closes so do any
|
||||||
|
* child connections first.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct lws_client_connect_info {
|
struct lws_client_connect_info {
|
||||||
|
@ -1425,6 +1428,7 @@ struct lws_client_connect_info {
|
||||||
void *userdata;
|
void *userdata;
|
||||||
const struct lws_extension *client_exts;
|
const struct lws_extension *client_exts;
|
||||||
const char *method;
|
const char *method;
|
||||||
|
struct lws *parent_wsi;
|
||||||
|
|
||||||
/* Add new things just above here ---^
|
/* Add new things just above here ---^
|
||||||
* This is part of the ABI, don't needlessly break compatibility
|
* This is part of the ABI, don't needlessly break compatibility
|
||||||
|
@ -1847,6 +1851,12 @@ lws_get_context(const struct lws *wsi);
|
||||||
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
|
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
|
||||||
lws_get_count_threads(struct lws_context *context);
|
lws_get_count_threads(struct lws_context *context);
|
||||||
|
|
||||||
|
LWS_VISIBLE LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT
|
||||||
|
lws_get_parent(const struct lws *wsi);
|
||||||
|
|
||||||
|
LWS_VISIBLE LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT
|
||||||
|
lws_get_child(const struct lws *wsi);
|
||||||
|
|
||||||
#ifdef LWS_WITH_CGI
|
#ifdef LWS_WITH_CGI
|
||||||
enum lws_enum_stdinouterr {
|
enum lws_enum_stdinouterr {
|
||||||
LWS_STDIN = 0,
|
LWS_STDIN = 0,
|
||||||
|
|
|
@ -1075,9 +1075,11 @@ struct lws {
|
||||||
/* pointers */
|
/* pointers */
|
||||||
|
|
||||||
struct lws_context *context;
|
struct lws_context *context;
|
||||||
|
struct lws *parent; /* points to parent, if any */
|
||||||
|
struct lws *child_list; /* points to first child */
|
||||||
|
struct lws *sibling_list; /* subsequent children at same level */
|
||||||
#ifdef LWS_WITH_CGI
|
#ifdef LWS_WITH_CGI
|
||||||
struct lws_cgi *cgi; /* wsi being cgi master have one of these */
|
struct lws_cgi *cgi; /* wsi being cgi master have one of these */
|
||||||
struct lws *master; /* for stdin/out/err wsi to point to cgi master */
|
|
||||||
#endif
|
#endif
|
||||||
const struct lws_protocols *protocol;
|
const struct lws_protocols *protocol;
|
||||||
struct lws *timeout_list;
|
struct lws *timeout_list;
|
||||||
|
|
|
@ -871,12 +871,12 @@ handle_pending:
|
||||||
}
|
}
|
||||||
|
|
||||||
args.ch = wsi->cgi_channel;
|
args.ch = wsi->cgi_channel;
|
||||||
args.stdwsi = &wsi->master->cgi->stdwsi[0];
|
args.stdwsi = &wsi->parent->cgi->stdwsi[0];
|
||||||
|
|
||||||
if (user_callback_handle_rxflow(
|
if (user_callback_handle_rxflow(
|
||||||
wsi->master->protocol->callback,
|
wsi->parent->protocol->callback,
|
||||||
wsi->master, LWS_CALLBACK_CGI,
|
wsi->parent, LWS_CALLBACK_CGI,
|
||||||
wsi->master->user_space,
|
wsi->parent->user_space,
|
||||||
(void *)&args, 0))
|
(void *)&args, 0))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@ echo "REQUEST_METHOD=$REQUEST_METHOD"
|
||||||
if [ "$REQUEST_METHOD" = "POST" ] ; then
|
if [ "$REQUEST_METHOD" = "POST" ] ; then
|
||||||
read line
|
read line
|
||||||
echo "read=\"$line\""
|
echo "read=\"$line\""
|
||||||
|
else
|
||||||
|
cat /proc/meminfo
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "done"
|
echo "done"
|
||||||
|
|
Loading…
Add table
Reference in a new issue