cgi: also allow for generic spawn

This commit is contained in:
Andy Green 2017-09-19 07:58:04 +08:00
parent 4a0db7fbf1
commit 66a402cc96
4 changed files with 72 additions and 30 deletions

View file

@ -230,7 +230,6 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
int n;
#endif
switch (reason) {
case LWS_CALLBACK_HTTP:
#ifndef LWS_NO_SERVER

View file

@ -1249,6 +1249,8 @@ lws_now_secs(void)
LWS_VISIBLE int
lws_get_socket_fd(struct lws *wsi)
{
if (!wsi)
return -1;
return wsi->desc.sockfd;
}
@ -2511,8 +2513,8 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
cgi->stdwsi[n]->cgi_channel = n;
cgi->stdwsi[n]->vhost = wsi->vhost;
// lwsl_err("%s: cgi %p: pipe fd %d -> fd %d / %d\n", __func__, wsi, n,
// cgi->pipe_fds[n][!!(n == 0)], cgi->pipe_fds[n][!(n == 0)]);
lwsl_debug("%s: cgi %p: pipe fd %d -> fd %d / %d\n", __func__, cgi->stdwsi[n], n,
cgi->pipe_fds[n][!!(n == 0)], cgi->pipe_fds[n][!(n == 0)]);
/* read side is 0, stdin we want the write side, others read */
cgi->stdwsi[n]->desc.sockfd = cgi->pipe_fds[n][!!(n == 0)];
@ -2540,7 +2542,8 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
cgi->stdwsi[LWS_STDOUT]->desc.sockfd,
cgi->stdwsi[LWS_STDERR]->desc.sockfd);
lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, timeout_secs);
if (timeout_secs)
lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, timeout_secs);
/* the cgi stdout is always sending us http1.x header data first */
wsi->hdr_state = LCHS_HEADER;
@ -2569,15 +2572,18 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
"GET", "POST", "OPTIONS", "PUT", "PATCH", "DELETE",
};
for (m = 0; m < ARRAY_SIZE(meths); m++)
if (lws_hdr_total_length(wsi, meths[m]) >=
script_uri_path_len) {
uritok = meths[m];
break;
}
if (script_uri_path_len >= 0)
for (m = 0; m < ARRAY_SIZE(meths); m++)
if (lws_hdr_total_length(wsi, meths[m]) >=
script_uri_path_len) {
uritok = meths[m];
break;
}
if (uritok < 0)
if (script_uri_path_len < 0 && uritok < 0)
goto bail3;
if (script_uri_path_len < 0)
uritok = 0;
lws_snprintf(cgi_path, sizeof(cgi_path) - 1, "REQUEST_URI=%s",
lws_hdr_simple_ptr(wsi, uritok));
@ -2593,7 +2599,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
p += lws_snprintf(p, end - p, "QUERY_STRING=");
/* dump the individual URI Arg parameters */
m = 0;
while (1) {
while (script_uri_path_len >= 0) {
i = lws_hdr_copy_fragment(wsi, tok, sizeof(tok),
WSI_TOKEN_HTTP_URI_ARGS, m);
if (i < 0)
@ -2614,37 +2620,44 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
p--;
*p++ = '\0';
env_array[n++] = p;
p += lws_snprintf(p, end - p, "PATH_INFO=%s",
lws_hdr_simple_ptr(wsi, uritok) +
script_uri_path_len);
p++;
if (script_uri_path_len >= 0) {
env_array[n++] = p;
p += lws_snprintf(p, end - p, "PATH_INFO=%s",
lws_hdr_simple_ptr(wsi, uritok) +
script_uri_path_len);
p++;
}
}
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_REFERER)) {
if (script_uri_path_len >= 0 &&
lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_REFERER)) {
env_array[n++] = p;
p += lws_snprintf(p, end - p, "HTTP_REFERER=%s",
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_REFERER));
p++;
}
if (lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) {
if (script_uri_path_len >= 0 &&
lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) {
env_array[n++] = p;
p += lws_snprintf(p, end - p, "HTTP_HOST=%s",
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST));
p++;
}
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE)) {
if (script_uri_path_len >= 0 &&
lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE)) {
env_array[n++] = p;
p += lws_snprintf(p, end - p, "HTTP_COOKIE=%s",
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COOKIE));
p++;
}
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_USER_AGENT)) {
if (script_uri_path_len >= 0 &&
lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_USER_AGENT)) {
env_array[n++] = p;
p += lws_snprintf(p, end - p, "USER_AGENT=%s",
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_USER_AGENT));
p++;
}
if (uritok == WSI_TOKEN_POST_URI) {
if (script_uri_path_len >= 0 &&
uritok == WSI_TOKEN_POST_URI) {
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
env_array[n++] = p;
p += lws_snprintf(p, end - p, "CONTENT_TYPE=%s",
@ -2685,7 +2698,8 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
* Actually having made the env, as a cgi we don't need the ah
* any more
*/
if (lws_header_table_is_in_detachable_state(wsi))
if (script_uri_path_len >= 0 &&
lws_header_table_is_in_detachable_state(wsi))
lws_header_table_detach(wsi, 0);
/* we are ready with the redirection pipes... run the thing */
@ -2713,6 +2727,12 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
for (n = 0; n < 3; n++)
close(cgi->pipe_fds[n][!(n == 0)]);
/* inform cgi owner of the child PID */
n = user_callback_handle_rxflow(wsi->protocol->callback, wsi,
LWS_CALLBACK_CGI_PROCESS_ATTACH,
wsi->user_space, NULL, cgi->pid);
(void)n;
return 0;
}
@ -3106,7 +3126,7 @@ handled:
n = user_callback_handle_rxflow(wsi->protocol->callback, wsi,
LWS_CALLBACK_CGI_TERMINATED,
wsi->user_space,
(void *)&args, 0);
(void *)&args, wsi->cgi->pid);
wsi->cgi->pid = -1;
if (n && !wsi->cgi->being_closed)
lws_close_free_wsi(wsi, 0);
@ -3251,6 +3271,16 @@ finish_him:
return 0;
}
LWS_VISIBLE LWS_EXTERN struct lws *
lws_cgi_get_stdwsi(struct lws *wsi, enum lws_enum_stdinouterr ch)
{
if (!wsi->cgi)
return NULL;
return wsi->cgi->stdwsi[ch];
}
#endif
#ifdef LWS_NO_EXTENSIONS

View file

@ -1213,7 +1213,7 @@ enum lws_callback_reasons {
* the wsi is closed. Used to, eg, terminate chunking.
* The provided `lws_callback_http_dummy()`
* handles this and the callback should be directed there if
* you use CGI. */
* you use CGI. The child PID that terminated is in @len. */
LWS_CALLBACK_CGI_STDIN_DATA = 42,
/**< CGI: Data is, to be sent to the CGI process stdin, eg from
* a POST body. The provided `lws_callback_http_dummy()`
@ -1389,6 +1389,9 @@ enum lws_callback_reasons {
/**< Sent to parent to notify them a child is closing / being
* destroyed. @in is the child wsi.
*/
LWS_CALLBACK_CGI_PROCESS_ATTACH = 70,
/**< CGI: Sent when the CGI process is spawned for the wsi. The
* @len parameter is the PID of the child process */
/****** add new things just above ---^ ******/
@ -5140,7 +5143,7 @@ lws_b64_decode_string(const char *in, char *out, int out_size);
* However for most cases, binding the cgi to http in and out, the default
* lws implementation already does the right thing.
*/
#ifdef LWS_WITH_CGI
enum lws_enum_stdinouterr {
LWS_STDIN = 0,
LWS_STDOUT = 1,
@ -5167,13 +5170,14 @@ struct lws_cgi_args {
int len; /**< length */
};
#ifdef LWS_WITH_CGI
/**
* lws_cgi: spawn network-connected cgi process
*
* \param wsi: connection to own the process
* \param exec_array: array of "exec-name" "arg1" ... "argn" NULL
* \param script_uri_path_len: how many chars on the left of the uri are the path to the cgi
* \param script_uri_path_len: how many chars on the left of the uri are the
* path to the cgi, or -1 to spawn without URL-related env vars
* \param timeout_secs: seconds script should be allowed to run
* \param mp_cgienv: pvo list with per-vhost cgi options to put in env
*/
@ -5197,6 +5201,15 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi);
*/
LWS_VISIBLE LWS_EXTERN int
lws_cgi_kill(struct lws *wsi);
/**
* lws_cgi_get_stdwsi: get wsi for stdin, stdout, or stderr
*
* \param wsi: parent wsi that has cgi
*/
LWS_VISIBLE LWS_EXTERN struct lws *
lws_cgi_get_stdwsi(struct lws *wsi, enum lws_enum_stdinouterr ch);
#endif
///@}

View file

@ -1418,8 +1418,8 @@ drain:
args.stdwsi = &wsi->parent->cgi->stdwsi[0];
args.hdr_state = wsi->hdr_state;
//lwsl_err("CGI LWS_STDOUT waiting wsi %p mode %d state %d\n",
// wsi->parent, wsi->parent->mode, wsi->parent->state);
lwsl_debug("CGI LWS_STDOUT waiting wsi %p mode %d state %d\n",
wsi->parent, wsi->parent->mode, wsi->parent->state);
if (user_callback_handle_rxflow(
wsi->parent->protocol->callback,