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_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
|
||||
======
|
||||
|
|
|
@ -407,7 +407,12 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
|
|||
if (wsi && !wsi->user_space && i->userdata) {
|
||||
wsi->user_space_externally_allocated = 1;
|
||||
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
|
||||
wsi->use_ssl = i->ssl_connection;
|
||||
|
@ -417,11 +422,6 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
|
|||
goto bail;
|
||||
}
|
||||
#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
|
||||
* 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))
|
||||
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;
|
||||
|
||||
bail:
|
||||
|
|
|
@ -142,10 +142,11 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs)
|
|||
void
|
||||
lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
|
||||
{
|
||||
struct lws_context *context;
|
||||
struct lws_context_per_thread *pt;
|
||||
int n, m, ret;
|
||||
struct lws **pwsi, *wsi1, *wsi2;
|
||||
struct lws_context *context;
|
||||
struct lws_tokens eff_buf;
|
||||
int n, m, ret;
|
||||
|
||||
if (!wsi)
|
||||
return;
|
||||
|
@ -153,24 +154,31 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
|
|||
context = wsi->context;
|
||||
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
|
||||
if (wsi->mode == LWSCM_CGI) {
|
||||
/* we are not a network connection, but a handler for CGI io */
|
||||
assert(wsi->master);
|
||||
assert(wsi->master->cgi);
|
||||
assert(wsi->master->cgi->stdwsi[(int)wsi->cgi_channel] == wsi);
|
||||
if (wsi->parent && wsi->parent->cgi)
|
||||
/* end the binding between us and master */
|
||||
wsi->master->cgi->stdwsi[(int)wsi->cgi_channel] = NULL;
|
||||
wsi->master = NULL;
|
||||
wsi->parent->cgi->stdwsi[(int)wsi->cgi_channel] = NULL;
|
||||
wsi->socket_is_permanently_unusable = 1;
|
||||
|
||||
goto just_kill_connection;
|
||||
}
|
||||
|
||||
if (wsi->cgi) {
|
||||
/* we have a cgi going, we must kill it and close the
|
||||
* related stdin/out/err wsis first
|
||||
*/
|
||||
/* we have a cgi going, we must kill it */
|
||||
wsi->cgi->being_closed = 1;
|
||||
lws_cgi_kill(wsi);
|
||||
}
|
||||
|
@ -327,6 +335,22 @@ 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__);
|
||||
}
|
||||
|
||||
#if LWS_POSIX
|
||||
/*
|
||||
|
@ -1182,6 +1206,18 @@ lws_wsi_user(struct lws *wsi)
|
|||
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_close_reason(struct lws *wsi, enum lws_close_status status,
|
||||
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++) {
|
||||
cgi->stdwsi[n]->master = wsi;
|
||||
if (insert_wsi_socket_into_fds(wsi->context, cgi->stdwsi[n]))
|
||||
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);
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
||||
/* add us to the pt list of active cgis */
|
||||
cgi->cgi_list = pt->cgi_list;
|
||||
pt->cgi_list = cgi;
|
||||
|
@ -1633,8 +1673,6 @@ lws_cgi_kill(struct lws *wsi)
|
|||
if (wsi->cgi->pipe_fds[n][!!(n == 0)] >= 0) {
|
||||
close(wsi->cgi->pipe_fds[n][!!(n == 0)]);
|
||||
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
|
||||
* @method: if non-NULL, do this http method instead of ws[s] upgrade.
|
||||
* 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 {
|
||||
|
@ -1425,6 +1428,7 @@ struct lws_client_connect_info {
|
|||
void *userdata;
|
||||
const struct lws_extension *client_exts;
|
||||
const char *method;
|
||||
struct lws *parent_wsi;
|
||||
|
||||
/* Add new things just above here ---^
|
||||
* 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_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
|
||||
enum lws_enum_stdinouterr {
|
||||
LWS_STDIN = 0,
|
||||
|
|
|
@ -1075,9 +1075,11 @@ struct lws {
|
|||
/* pointers */
|
||||
|
||||
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
|
||||
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
|
||||
const struct lws_protocols *protocol;
|
||||
struct lws *timeout_list;
|
||||
|
|
|
@ -871,12 +871,12 @@ handle_pending:
|
|||
}
|
||||
|
||||
args.ch = wsi->cgi_channel;
|
||||
args.stdwsi = &wsi->master->cgi->stdwsi[0];
|
||||
args.stdwsi = &wsi->parent->cgi->stdwsi[0];
|
||||
|
||||
if (user_callback_handle_rxflow(
|
||||
wsi->master->protocol->callback,
|
||||
wsi->master, LWS_CALLBACK_CGI,
|
||||
wsi->master->user_space,
|
||||
wsi->parent->protocol->callback,
|
||||
wsi->parent, LWS_CALLBACK_CGI,
|
||||
wsi->parent->user_space,
|
||||
(void *)&args, 0))
|
||||
return 1;
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ echo "REQUEST_METHOD=$REQUEST_METHOD"
|
|||
if [ "$REQUEST_METHOD" = "POST" ] ; then
|
||||
read line
|
||||
echo "read=\"$line\""
|
||||
else
|
||||
cat /proc/meminfo
|
||||
fi
|
||||
|
||||
echo "done"
|
||||
|
|
Loading…
Add table
Reference in a new issue