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

cgi header processing

Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
Andy Green 2016-03-09 07:41:59 +08:00 committed by Andy Green
parent 8007cc6829
commit c3c2d6d953
6 changed files with 143 additions and 29 deletions

View file

@ -1585,13 +1585,13 @@ lws_cgi(struct lws *wsi, char * const *exec_array, int timeout_secs)
lws_change_pollfd(cgi->stdwsi[LWS_STDERR], LWS_POLLOUT, LWS_POLLIN);
lwsl_debug("%s: fds in %d, out %d, err %d\n", __func__,
cgi->stdwsi[LWS_STDIN]->sock,
cgi->stdwsi[LWS_STDOUT]->sock,
cgi->stdwsi[LWS_STDERR]->sock);
cgi->stdwsi[LWS_STDIN]->sock, cgi->stdwsi[LWS_STDOUT]->sock,
cgi->stdwsi[LWS_STDERR]->sock);
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;
/* add us to the pt list of active cgis */
cgi->cgi_list = pt->cgi_list;
@ -1674,6 +1674,103 @@ bail1:
return -1;
}
/**
* lws_cgi_write_split_headers: write cgi output accounting for header part
*
* @wsi: connection to own the process
*/
LWS_VISIBLE LWS_EXTERN int
lws_cgi_write_split_stdout_headers(struct lws *wsi)
{
int n, m;
char buf[LWS_PRE + 1024], *start = &buf[LWS_PRE], *p = start,
*end = &buf[sizeof(buf) - 1 - LWS_PRE], c;
while (wsi->hdr_state != LHCS_PAYLOAD) {
/* we have to separate header / finalize and
* payload chunks, since they need to be
* handled separately
*/
n = read(lws_get_socket_fd(wsi->cgi->stdwsi[LWS_STDOUT]), &c, 1);
if (n < 0) {
if (errno != EAGAIN)
return -1;
else
n = 0;
}
if (n) {
lwsl_err("-- %c\n", c);
switch (wsi->hdr_state) {
case LCHS_HEADER:
*p++ = c;
if (c == '\x0d') {
wsi->hdr_state = LCHS_LF1;
break;
}
break;
case LCHS_LF1:
*p++ = c;
if (c == '\x0a') {
wsi->hdr_state = LCHS_CR2;
break;
}
/* we got \r[^\n]... it's unreasonable */
return -1;
case LCHS_CR2:
if (c == '\x0d') {
/* drop the \x0d */
wsi->hdr_state = LCHS_LF2;
break;
}
*p++ = c;
break;
case LCHS_LF2:
if (c == '\x0a') {
wsi->hdr_state = LHCS_PAYLOAD;
/* drop the \0xa ... finalize will add it if needed */
lws_finalize_http_header(wsi,
(unsigned char **)&p,
(unsigned char *)end);
break;
}
/* we got \r\n\r[^\n]... it's unreasonable */
return -1;
case LHCS_PAYLOAD:
break;
}
}
/* ran out of input, ended the headers, or filled up the headers buf */
if (!n || wsi->hdr_state == LHCS_PAYLOAD || (p + 4) == end) {
lwsl_err("a\n");
m = lws_write(wsi, (unsigned char *)start,
p - start, LWS_WRITE_HTTP_HEADERS);
if (m < 0)
return -1;
lwsl_err("b\n");
/* writeability becomes uncertain now we wrote
* something, we must return to the event loop
*/
return 0;
}
}
lwsl_err("%s: stdout\n", __func__);
n = read(lws_get_socket_fd(wsi->cgi->stdwsi[LWS_STDOUT]),
start, sizeof(buf) - LWS_PRE);
if (n < 0 && errno != EAGAIN)
return -1;
if (n > 0) {
m = lws_write(wsi, (unsigned char *)start, n,
LWS_WRITE_HTTP);
//lwsl_notice("write %d\n", m);
if (m < 0)
return -1;
}
return 0;
}
/**
* lws_cgi_kill: terminate cgi process associated with wsi

View file

@ -1866,16 +1866,29 @@ enum lws_enum_stdinouterr {
LWS_STDERR = 2,
};
enum lws_cgi_hdr_state {
LCHS_HEADER,
LCHS_CR1,
LCHS_LF1,
LCHS_CR2,
LCHS_LF2,
LHCS_PAYLOAD,
};
struct lws_cgi_args {
struct lws **stdwsi; /* get fd with lws_get_socket_fd() */
enum lws_enum_stdinouterr ch;
unsigned char *data; /* for messages with payload */
enum lws_cgi_hdr_state hdr_state;
int len;
};
LWS_VISIBLE LWS_EXTERN int
lws_cgi(struct lws *wsi, char * const *exec_array, int timeout_secs);
LWS_VISIBLE LWS_EXTERN int
lws_cgi_write_split_stdout_headers(struct lws *wsi);
LWS_VISIBLE LWS_EXTERN int
lws_cgi_kill(struct lws *wsi);
#endif

View file

@ -1054,6 +1054,7 @@ struct lws_cgi {
unsigned int being_closed:1;
};
#endif
struct lws {
@ -1158,6 +1159,7 @@ struct lws {
char tsi; /* thread service index we belong to */
#ifdef LWS_WITH_CGI
char cgi_channel; /* which of stdin/out/err */
char hdr_state;
#endif
};

View file

@ -874,6 +874,7 @@ handle_pending:
args.ch = wsi->cgi_channel;
args.stdwsi = &wsi->parent->cgi->stdwsi[0];
args.hdr_state = wsi->hdr_state;
if (user_callback_handle_rxflow(
wsi->parent->protocol->callback,

View file

@ -1,18 +1,31 @@
#!/bin/sh
echo "lwstest script stdout"
echo -e -n "Content-type: text/html\x0d\x0a"
echo -e -n "\x0d\x0a"
echo "<html><body>"
echo "<h1>lwstest script stdout</h1>"
>&2 echo "lwstest script stderr"
echo "REQUEST_METHOD=$REQUEST_METHOD"
echo "<h2>REQUEST_METHOD=$REQUEST_METHOD</h2>"
if [ "$REQUEST_METHOD" = "POST" ] ; then
read line
echo "read=\"$line\""
else
cat /proc/meminfo
echo "<table>"
echo "<tr><td colspan=\"2\" style=\"font-size:120%;text-align:center\">/proc/meminfo</td></tr>"
cat /proc/meminfo | while read line ; do
A=`echo "$line" | cut -d: -f1`
B=`echo "$line" | tr -s ' ' | cut -d' ' -f2-`
echo -e "<tr><td style=\"background-color:#f0e8c0\">$A</td>"
echo -e "<td style=\"text-align:right\">$B</td></tr>"
done
echo "</table>"
fi
echo "done"
echo "<br/>done"
echo "</body></html>"
exit 0

View file

@ -213,19 +213,17 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
if (lws_add_http_header_status(wsi, 200, &p, end))
return 1;
if (lws_add_http_header_by_token(wsi,
WSI_TOKEN_HTTP_CONTENT_TYPE,
(unsigned char *)"text/plain",
10, &p, end))
return 1;
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION,
(unsigned char *)"close", 5, &p, end))
return 1;
if (lws_finalize_http_header(wsi, &p, end))
return 1;
n = lws_write(wsi, buffer + LWS_PRE,
p - (buffer + LWS_PRE),
LWS_WRITE_HTTP_HEADERS);
/* the cgi starts by outputting headers, we can't
* finalize the headers until we see the end of that
*/
break;
}
#endif
@ -399,20 +397,10 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
goto try_to_reuse;
#ifdef LWS_WITH_CGI
if (pss->reason_bf) {
lwsl_debug("%s: stdout\n", __func__);
n = read(lws_get_socket_fd(pss->args.stdwsi[LWS_STDOUT]),
buf + LWS_PRE, sizeof(buf) - LWS_PRE);
//lwsl_notice("read %d (errno %d)\n", n, errno);
if (n < 0 && errno != EAGAIN)
return -1;
if (n > 0) {
m = lws_write(wsi, (unsigned char *)buf + LWS_PRE, n,
LWS_WRITE_HTTP);
//lwsl_notice("write %d\n", m);
if (m < 0)
goto bail;
pss->reason_bf = 0;
}
if (lws_cgi_write_split_stdout_headers(wsi) < 0)
goto bail;
pss->reason_bf = 0;
break;
}
#endif