mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
cgi post
Signed-off-by: Andy Green <andy@warmcat.com>
This commit is contained in:
parent
22d6f39e7f
commit
f5efa74cb7
15 changed files with 317 additions and 263 deletions
|
@ -15,8 +15,9 @@ It enables libuv and plugin support automatically.
|
|||
Configuration
|
||||
-------------
|
||||
|
||||
lwsws uses JSON config files, there is a single file intended for global
|
||||
settings
|
||||
lwsws uses JSON config files, they're pure JSON but # may be used to turn the rest of the line into a comment.
|
||||
|
||||
There is a single file intended for global settings
|
||||
|
||||
/etc/lwsws/conf
|
||||
|
||||
|
@ -189,7 +190,14 @@ Mount protocols are used to control what kind of translation happens
|
|||
|
||||
This allows you to customize one cgi depending on the mountpoint (and / or vhost).
|
||||
|
||||
Currently only a fixed set of mimetypes are supported.
|
||||
It's also possible to set the cgi timeout (in secs) per cgi:// mount, like this
|
||||
|
||||
```
|
||||
"cgi-timeout": "30"
|
||||
```
|
||||
|
||||
|
||||
Note: currently only a fixed set of mimetypes are supported.
|
||||
|
||||
|
||||
Plugins
|
||||
|
|
|
@ -52,7 +52,8 @@ static const char * const mount_protocols[] = {
|
|||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_write_http_mount(struct lws_http_mount *next, struct lws_http_mount **res,
|
||||
void *store, const char *mountpoint, const char *origin,
|
||||
const char *def, struct lws_protocol_vhost_options *cgienv)
|
||||
const char *def, struct lws_protocol_vhost_options *cgienv,
|
||||
int cgi_timeout)
|
||||
{
|
||||
struct lws_http_mount *m;
|
||||
void *orig = store;
|
||||
|
@ -71,6 +72,8 @@ lws_write_http_mount(struct lws_http_mount *next, struct lws_http_mount **res,
|
|||
m->mountpoint_len = (unsigned char)strlen(mountpoint);
|
||||
m->mount_next = NULL;
|
||||
m->cgienv = cgienv;
|
||||
m->cgi_timeout = cgi_timeout;
|
||||
|
||||
if (next)
|
||||
next->mount_next = m;
|
||||
|
||||
|
@ -83,7 +86,7 @@ lws_write_http_mount(struct lws_http_mount *next, struct lws_http_mount **res,
|
|||
}
|
||||
|
||||
if (n == ARRAY_SIZE(mount_protocols)) {
|
||||
lwsl_err("unsupported protocol://\n");
|
||||
lwsl_err("unsupported protocol:// %s\n", origin);
|
||||
return 0; /* ie, fail */
|
||||
}
|
||||
|
||||
|
@ -586,6 +589,8 @@ lws_create_context(struct lws_context_creation_info *info)
|
|||
|
||||
lws_context_init_ssl_library(info);
|
||||
|
||||
context->user_space = info->user;
|
||||
|
||||
/*
|
||||
* if he's not saying he'll make his own vhosts later then act
|
||||
* compatibly and make a default vhost using the data in the info
|
||||
|
@ -598,8 +603,6 @@ lws_create_context(struct lws_context_creation_info *info)
|
|||
|
||||
lws_context_init_extensions(info, context);
|
||||
|
||||
context->user_space = info->user;
|
||||
|
||||
lwsl_notice(" mem: per-conn: %5u bytes + protocol rx buf\n",
|
||||
sizeof(struct lws));
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ lws_daemonize(const char *_lock_path)
|
|||
* Change the current working directory. This prevents the current
|
||||
* directory from being locked; hence not being able to remove it.
|
||||
*/
|
||||
if (chdir("/") < 0) {
|
||||
if (chdir("/tmp") < 0) {
|
||||
fprintf(stderr,
|
||||
"unable to change directory to %s, code %d (%s)",
|
||||
"/", errno, strerror(errno));
|
||||
|
|
|
@ -530,6 +530,17 @@ lws_close_free_wsi_final(struct lws *wsi)
|
|||
wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_WSI_DESTROY,
|
||||
wsi->user_space, NULL, 0);
|
||||
|
||||
#ifdef LWS_WITH_CGI
|
||||
if (wsi->cgi) {
|
||||
for (n = 0; n < 6; n++)
|
||||
if (wsi->cgi->pipe_fds[n / 2][n & 1] >= 0) {
|
||||
lwsl_notice(" closing %d\n", wsi->cgi->pipe_fds[n / 2][n & 1]);
|
||||
close(wsi->cgi->pipe_fds[n / 2][n & 1]);
|
||||
}
|
||||
lws_free(wsi->cgi);
|
||||
}
|
||||
#endif
|
||||
|
||||
lws_free_wsi(wsi);
|
||||
}
|
||||
|
||||
|
@ -1644,7 +1655,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
char *env_array[30], cgi_path[400], e[1024], *p = e,
|
||||
*end = p + sizeof(e) - 1, tok[256], *t;
|
||||
struct lws_cgi *cgi;
|
||||
int n, m, i;
|
||||
int n, m, i, uritok = WSI_TOKEN_GET_URI;
|
||||
|
||||
/*
|
||||
* give the master wsi a cgi struct
|
||||
|
@ -1674,6 +1685,9 @@ 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)]);
|
||||
|
||||
/* read side is 0, stdin we want the write side, others read */
|
||||
cgi->stdwsi[n]->sock = cgi->pipe_fds[n][!!(n == 0)];
|
||||
fcntl(cgi->pipe_fds[n][!!(n == 0)], F_SETFL, O_NONBLOCK);
|
||||
|
@ -1712,11 +1726,13 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
if (lws_is_ssl(wsi))
|
||||
env_array[n++] = "HTTPS=ON";
|
||||
if (wsi->u.hdr.ah) {
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
|
||||
uritok = WSI_TOKEN_POST_URI;
|
||||
snprintf(cgi_path, sizeof(cgi_path) - 1, "REQUEST_URI=%s",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI));
|
||||
lws_hdr_simple_ptr(wsi, uritok));
|
||||
cgi_path[sizeof(cgi_path) - 1] = '\0';
|
||||
env_array[n++] = cgi_path;
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
|
||||
if (uritok == WSI_TOKEN_POST_URI)
|
||||
env_array[n++] = "REQUEST_METHOD=POST";
|
||||
else
|
||||
env_array[n++] = "REQUEST_METHOD=GET";
|
||||
|
@ -1748,7 +1764,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
|
||||
env_array[n++] = p;
|
||||
p += snprintf(p, end - p, "PATH_INFO=%s",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI) +
|
||||
lws_hdr_simple_ptr(wsi, uritok) +
|
||||
script_uri_path_len);
|
||||
p++;
|
||||
}
|
||||
|
@ -1764,12 +1780,32 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST));
|
||||
p++;
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE)) {
|
||||
env_array[n++] = p;
|
||||
p += 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)) {
|
||||
env_array[n++] = p;
|
||||
p += 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 (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
|
||||
env_array[n++] = p;
|
||||
p += snprintf(p, end - p, "CONTENT_TYPE=%s",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE));
|
||||
p++;
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
|
||||
env_array[n++] = p;
|
||||
p += snprintf(p, end - p, "CONTENT_LENGTH=%s",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH));
|
||||
p++;
|
||||
}
|
||||
}
|
||||
env_array[n++] = p;
|
||||
p += snprintf(p, end - p, "SCRIPT_PATH=%s", exec_array[0]) + 1;
|
||||
|
||||
|
@ -1808,7 +1844,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
return 0;
|
||||
|
||||
/* somewhere we can at least read things and enter it */
|
||||
if (chdir("/"))
|
||||
if (chdir("/tmp"))
|
||||
lwsl_notice("%s: Failed to chdir\n", __func__);
|
||||
|
||||
/* We are the forked process, redirect and kill inherited things.
|
||||
|
@ -1818,13 +1854,11 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
* process is OK. Stuff that happens after the execvpe() is OK.
|
||||
*/
|
||||
|
||||
for (n = 0; n < 3; n++) {
|
||||
for (n = 0; n < 3; n++)
|
||||
if (dup2(cgi->pipe_fds[n][!(n == 0)], n) < 0) {
|
||||
lwsl_err("%s: stdin dup2 failed\n", __func__);
|
||||
goto bail3;
|
||||
}
|
||||
close(cgi->pipe_fds[n][!(n == 0)]);
|
||||
}
|
||||
|
||||
#if !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE)
|
||||
for (m = 0; m < n; m++) {
|
||||
|
@ -1872,9 +1906,13 @@ bail1:
|
|||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_cgi_write_split_stdout_headers(struct lws *wsi)
|
||||
{
|
||||
int n, m;
|
||||
int n, m, match = 0, lp = 0;
|
||||
static const char * const content_length = "content-length: ";
|
||||
char buf[LWS_PRE + 1024], *start = &buf[LWS_PRE], *p = start,
|
||||
*end = &buf[sizeof(buf) - 1 - LWS_PRE], c;
|
||||
*end = &buf[sizeof(buf) - 1 - LWS_PRE], c, l[12];
|
||||
|
||||
if (!wsi->cgi)
|
||||
return -1;
|
||||
|
||||
while (wsi->hdr_state != LHCS_PAYLOAD) {
|
||||
/* we have to separate header / finalize and
|
||||
|
@ -1883,20 +1921,40 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
|
|||
*/
|
||||
n = read(lws_get_socket_fd(wsi->cgi->stdwsi[LWS_STDOUT]), &c, 1);
|
||||
if (n < 0) {
|
||||
if (errno != EAGAIN)
|
||||
if (errno != EAGAIN) {
|
||||
lwsl_debug("%s: read says %d\n", __func__, n);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
n = 0;
|
||||
}
|
||||
if (n) {
|
||||
//lwsl_err("-- %c\n", c);
|
||||
lwsl_debug("-- 0x%02X %c\n", (unsigned char)c, c);
|
||||
switch (wsi->hdr_state) {
|
||||
case LCHS_HEADER:
|
||||
if (!content_length[match] &&
|
||||
(c >= '0' && c <= '9') &&
|
||||
lp < sizeof(l) - 1) {
|
||||
l[lp++] = c;
|
||||
l[lp] = '\0';
|
||||
wsi->cgi->content_length = atol(l);
|
||||
}
|
||||
if (tolower(c) == content_length[match])
|
||||
match++;
|
||||
else
|
||||
match = 0;
|
||||
|
||||
/* some cgi only send us \x0a for EOL */
|
||||
if (c == '\x0a') {
|
||||
wsi->hdr_state = LCHS_SINGLE_0A;
|
||||
*p++ = '\x0d';
|
||||
}
|
||||
*p++ = c;
|
||||
if (c == '\x0d') {
|
||||
wsi->hdr_state = LCHS_LF1;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case LCHS_LF1:
|
||||
*p++ = c;
|
||||
|
@ -1905,17 +1963,24 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
|
|||
break;
|
||||
}
|
||||
/* we got \r[^\n]... it's unreasonable */
|
||||
lwsl_debug("%s: funny CRLF 0x%02X\n", __func__, (unsigned char)c);
|
||||
return -1;
|
||||
|
||||
case LCHS_CR2:
|
||||
if (c == '\x0d') {
|
||||
/* drop the \x0d */
|
||||
wsi->hdr_state = LCHS_LF2;
|
||||
break;
|
||||
}
|
||||
wsi->hdr_state = LCHS_HEADER;
|
||||
match = 0;
|
||||
*p++ = c;
|
||||
break;
|
||||
case LCHS_LF2:
|
||||
case LCHS_SINGLE_0A:
|
||||
m = wsi->hdr_state;
|
||||
if (c == '\x0a') {
|
||||
lwsl_err("Content-Length: %ld\n", wsi->cgi->content_length);
|
||||
wsi->hdr_state = LHCS_PAYLOAD;
|
||||
/* drop the \0xa ... finalize will add it if needed */
|
||||
lws_finalize_http_header(wsi,
|
||||
|
@ -1923,8 +1988,13 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
|
|||
(unsigned char *)end);
|
||||
break;
|
||||
}
|
||||
/* we got \r\n\r[^\n]... it's unreasonable */
|
||||
return -1;
|
||||
if (m == LCHS_LF2)
|
||||
/* we got \r\n\r[^\n]... it's unreasonable */
|
||||
return -1;
|
||||
/* we got \x0anext header, it's reasonable */
|
||||
*p++ = c;
|
||||
wsi->hdr_state = LCHS_HEADER;
|
||||
break;
|
||||
case LHCS_PAYLOAD:
|
||||
break;
|
||||
}
|
||||
|
@ -1935,8 +2005,10 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
|
|||
|
||||
m = lws_write(wsi, (unsigned char *)start,
|
||||
p - start, LWS_WRITE_HTTP_HEADERS);
|
||||
if (m < 0)
|
||||
if (m < 0) {
|
||||
lwsl_debug("%s: write says %d\n", __func__, m);
|
||||
return -1;
|
||||
}
|
||||
/* writeability becomes uncertain now we wrote
|
||||
* something, we must return to the event loop
|
||||
*/
|
||||
|
@ -1944,18 +2016,22 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
|
|||
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)
|
||||
if (n < 0 && errno != EAGAIN) {
|
||||
lwsl_debug("%s: stdout read says %d\n", __func__, n);
|
||||
return -1;
|
||||
}
|
||||
if (n > 0) {
|
||||
m = lws_write(wsi, (unsigned char *)start, n,
|
||||
LWS_WRITE_HTTP);
|
||||
m = lws_write(wsi, (unsigned char *)start, n, LWS_WRITE_HTTP);
|
||||
//lwsl_notice("write %d\n", m);
|
||||
if (m < 0)
|
||||
if (m < 0) {
|
||||
lwsl_debug("%s: stdout write says %d\n", __func__, m);
|
||||
return -1;
|
||||
}
|
||||
wsi->cgi->content_length_seen += m;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1979,10 +2055,6 @@ lws_cgi_kill(struct lws *wsi)
|
|||
if (!wsi->cgi)
|
||||
return 0;
|
||||
|
||||
// lwsl_notice("%s: wsi %p\n", __func__, wsi);
|
||||
|
||||
assert(wsi->cgi);
|
||||
|
||||
if (wsi->cgi->pid > 0) {
|
||||
/* kill the process */
|
||||
n = kill(wsi->cgi->pid, SIGTERM);
|
||||
|
@ -2014,16 +2086,6 @@ lws_cgi_kill(struct lws *wsi)
|
|||
pcgi = &(*pcgi)->cgi_list;
|
||||
}
|
||||
|
||||
if (!do_close)
|
||||
for (n = 0 ; n < 3; n++) {
|
||||
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_free_set_NULL(wsi->cgi);
|
||||
|
||||
if (do_close) {
|
||||
lwsl_debug("!!!!! %s: do_close\n", __func__);
|
||||
lws_close_free_wsi(wsi, 0);
|
||||
|
@ -2044,8 +2106,15 @@ lws_cgi_kill_terminated(struct lws_context_per_thread *pt)
|
|||
cgi = *pcgi;
|
||||
pcgi = &(*pcgi)->cgi_list;
|
||||
|
||||
if (cgi->pid > 0 &&
|
||||
waitpid(cgi->pid, &status, WNOHANG) > 0) {
|
||||
if (cgi->pid <= 0)
|
||||
continue;
|
||||
|
||||
/* wait for stdout to be drained */
|
||||
if (cgi->content_length > cgi->content_length_seen)
|
||||
continue;
|
||||
|
||||
if (waitpid(cgi->pid, &status, WNOHANG) > 0) {
|
||||
lwsl_notice("content length seen: %ld\n", cgi->content_length_seen);
|
||||
cgi->pid = 0;
|
||||
lws_cgi_kill(cgi->wsi);
|
||||
pcgi = &pt->cgi_list;
|
||||
|
|
|
@ -1551,7 +1551,8 @@ LWS_VISIBLE LWS_EXTERN int
|
|||
lws_write_http_mount(struct lws_http_mount *next, struct lws_http_mount **res,
|
||||
void *store, const char *mountpoint, const char *origin,
|
||||
const char *def,
|
||||
struct lws_protocol_vhost_options *cgienv);
|
||||
struct lws_protocol_vhost_options *cgienv,
|
||||
int cgi_timeout);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_set_log_level(int level,
|
||||
|
@ -2011,6 +2012,7 @@ enum lws_cgi_hdr_state {
|
|||
LCHS_CR2,
|
||||
LCHS_LF2,
|
||||
LHCS_PAYLOAD,
|
||||
LCHS_SINGLE_0A,
|
||||
};
|
||||
|
||||
struct lws_cgi_args {
|
||||
|
|
|
@ -624,6 +624,8 @@ struct lws_http_mount {
|
|||
|
||||
struct lws_protocol_vhost_options *cgienv;
|
||||
|
||||
int cgi_timeout;
|
||||
|
||||
unsigned char origin_protocol;
|
||||
unsigned char mountpoint_len;
|
||||
};
|
||||
|
@ -1121,6 +1123,8 @@ struct lws_cgi {
|
|||
struct lws_cgi *cgi_list;
|
||||
struct lws *stdwsi[3]; /* points to the associated stdin/out/err wsis */
|
||||
struct lws *wsi; /* owner */
|
||||
unsigned long content_length;
|
||||
unsigned long content_length_seen;
|
||||
int pipe_fds[3][2];
|
||||
int pid;
|
||||
|
||||
|
|
33
lib/server.c
33
lib/server.c
|
@ -234,7 +234,7 @@ int lws_http_serve(struct lws *wsi, char *uri, const char *origin)
|
|||
}
|
||||
|
||||
lwsl_debug(" %s mode %d\n", path, S_IFMT & st.st_mode);
|
||||
|
||||
#if !defined(WIN32)
|
||||
if ((S_IFMT & st.st_mode) == S_IFLNK) {
|
||||
if (readlink(path, sym, sizeof(sym))) {
|
||||
lwsl_err("Failed to read link %s\n", path);
|
||||
|
@ -243,7 +243,7 @@ int lws_http_serve(struct lws *wsi, char *uri, const char *origin)
|
|||
lwsl_debug("symlink %s -> %s\n", path, sym);
|
||||
snprintf(path, sizeof(path) - 1, "%s", sym);
|
||||
}
|
||||
|
||||
#endif
|
||||
if ((S_IFMT & st.st_mode) == S_IFDIR) {
|
||||
lwsl_debug("default filename append to dir\n");
|
||||
snprintf(path, sizeof(path) - 1, "%s/%s/index.html",
|
||||
|
@ -409,6 +409,7 @@ lws_http_action(struct lws *wsi)
|
|||
lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
|
||||
wsi->context->timeout_secs);
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
#if 0
|
||||
if (wsi->redirect_to_https) {
|
||||
/*
|
||||
* we accepted http:// only so we could redirect to
|
||||
|
@ -435,6 +436,7 @@ lws_http_action(struct lws *wsi)
|
|||
|
||||
return lws_http_transaction_completed(wsi);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* can we serve it from the mount list? */
|
||||
|
@ -447,7 +449,9 @@ lws_http_action(struct lws *wsi)
|
|||
uri_ptr[hm->mountpoint_len] == '/' ||
|
||||
hm->mountpoint_len == 1)
|
||||
) {
|
||||
if (hm->mountpoint_len > best) {
|
||||
if ((hm->origin_protocol == LWSMPRO_CGI ||
|
||||
lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) &&
|
||||
hm->mountpoint_len > best) {
|
||||
best = hm->mountpoint_len;
|
||||
hit = hm;
|
||||
}
|
||||
|
@ -476,14 +480,15 @@ lws_http_action(struct lws *wsi)
|
|||
* understands he is one "directory level" down.
|
||||
*/
|
||||
if ((hit->mountpoint_len > 1 || (hit->origin_protocol & 4)) &&
|
||||
(*s != '/' || (hit->origin_protocol & 4))) {
|
||||
(*s != '/' || (hit->origin_protocol & 4)) &&
|
||||
(hit->origin_protocol != LWSMPRO_CGI)) {
|
||||
unsigned char *start = pt->serv_buf + LWS_PRE,
|
||||
*p = start, *end = p + 512;
|
||||
static const char *oprot[] = {
|
||||
"http://", "https://"
|
||||
};
|
||||
|
||||
// lwsl_err("inin '%s'\n", s);
|
||||
lwsl_err("Doing 301 '%s' org %s\n", s, hit->origin);
|
||||
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST))
|
||||
goto bail_nuke_ah;
|
||||
|
@ -527,7 +532,12 @@ lws_http_action(struct lws *wsi)
|
|||
|
||||
lwsl_debug("%s: cgi\n", __func__);
|
||||
cmd[0] = hit->origin;
|
||||
n = lws_cgi(wsi, cmd, hit->mountpoint_len, 5,
|
||||
|
||||
n = 5;
|
||||
if (hit->cgi_timeout)
|
||||
n = hit->cgi_timeout;
|
||||
|
||||
n = lws_cgi(wsi, cmd, hit->mountpoint_len, n,
|
||||
hit->cgienv);
|
||||
if (n) {
|
||||
lwsl_err("%s: cgi failed\n");
|
||||
|
@ -545,7 +555,7 @@ lws_http_action(struct lws *wsi)
|
|||
p - (buffer + LWS_PRE),
|
||||
LWS_WRITE_HTTP_HEADERS);
|
||||
|
||||
return 0;
|
||||
goto deal_body;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -569,6 +579,9 @@ lws_http_action(struct lws *wsi)
|
|||
return 1;
|
||||
}
|
||||
|
||||
#ifdef LWS_WITH_CGI
|
||||
deal_body:
|
||||
#endif
|
||||
/*
|
||||
* If we're not issuing a file, check for content_length or
|
||||
* HTTP keep-alive. No keep-alive header allocation for
|
||||
|
@ -611,7 +624,11 @@ lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
|
|||
while (len--) {
|
||||
wsi->more_rx_waiting = !!len;
|
||||
|
||||
assert(wsi->mode == LWSCM_HTTP_SERVING);
|
||||
if (wsi->mode != LWSCM_HTTP_SERVING &&
|
||||
wsi->mode != LWSCM_HTTP_SERVING_ACCEPTED) {
|
||||
lwsl_err("%s: bad wsi mode %d\n", __func__, wsi->mode);
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
||||
if (lws_parse(wsi, *(*buf)++)) {
|
||||
lwsl_info("lws_parse failed\n");
|
||||
|
|
|
@ -53,6 +53,8 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
|
|||
#endif
|
||||
int ret, m, n;
|
||||
|
||||
//lwsl_err("%s: %p\n", __func__, wsi);
|
||||
|
||||
/*
|
||||
* user callback is lowest priority to get these notifications
|
||||
* actually, since other pending things cannot be disordered
|
||||
|
@ -94,6 +96,12 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
|
|||
return 0; /* leave POLLOUT active */
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LWS_WITH_CGI
|
||||
if (wsi->cgi)
|
||||
goto user_service_go_again;
|
||||
#endif
|
||||
|
||||
/* Priority 3: pending control packets (pong or close)
|
||||
*/
|
||||
if ((wsi->state == LWSS_ESTABLISHED &&
|
||||
|
@ -239,9 +247,14 @@ user_service:
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if (!wsi->hdr_parsing_completed)
|
||||
return 0;
|
||||
|
||||
#ifdef LWS_WITH_CGI
|
||||
user_service_go_again:
|
||||
#endif
|
||||
|
||||
#ifdef LWS_USE_HTTP2
|
||||
/*
|
||||
* we are the 'network wsi' for potentially many muxed child wsi with
|
||||
|
@ -738,9 +751,17 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t
|
|||
case LWSCM_HTTP_SERVING_ACCEPTED:
|
||||
case LWSCM_SERVER_LISTENER:
|
||||
case LWSCM_SSL_ACK_PENDING:
|
||||
if (wsi->state == LWSS_CLIENT_HTTP_ESTABLISHED) {
|
||||
if (wsi->state == LWSS_CLIENT_HTTP_ESTABLISHED)
|
||||
goto handled;
|
||||
|
||||
#ifdef LWS_WITH_CGI
|
||||
if (wsi->cgi && (pollfd->revents & LWS_POLLOUT)) {
|
||||
n = lws_handle_POLLOUT_event(wsi, pollfd);
|
||||
if (n)
|
||||
goto close_and_handled;
|
||||
goto handled;
|
||||
}
|
||||
#endif
|
||||
n = lws_server_socket_service(context, wsi, pollfd);
|
||||
if (n) /* closed by above */
|
||||
return 1;
|
||||
|
@ -995,6 +1016,9 @@ 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);
|
||||
|
||||
if (user_callback_handle_rxflow(
|
||||
wsi->parent->protocol->callback,
|
||||
wsi->parent, LWS_CALLBACK_CGI,
|
||||
|
|
10
lwsws/conf.c
10
lwsws/conf.c
|
@ -48,6 +48,7 @@ static const char * const paths_vhosts[] = {
|
|||
"vhosts[].mounts[].mountpoint",
|
||||
"vhosts[].mounts[].origin",
|
||||
"vhosts[].mounts[].default",
|
||||
"vhosts[].mounts[].cgi-timeout",
|
||||
"vhosts[].mounts[].cgi-env[].*",
|
||||
"vhosts[].ws-protocols[].*.*",
|
||||
"vhosts[].ws-protocols[].*",
|
||||
|
@ -65,6 +66,7 @@ enum lejp_vhost_paths {
|
|||
LEJPVP_MOUNTPOINT,
|
||||
LEJPVP_ORIGIN,
|
||||
LEJPVP_DEFAULT,
|
||||
LEJPVP_CGI_TIMEOUT,
|
||||
LEJPVP_CGI_ENV,
|
||||
LEJPVP_PROTOCOL_NAME_OPT,
|
||||
LEJPVP_PROTOCOL_NAME,
|
||||
|
@ -81,6 +83,7 @@ struct jpargs {
|
|||
char *mountpoint, *origin, *def;
|
||||
struct lws_protocol_vhost_options *pvo;
|
||||
struct lws_protocol_vhost_options *mp_cgienv;
|
||||
int cgi_timeout;
|
||||
};
|
||||
|
||||
static void *
|
||||
|
@ -192,6 +195,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
|
|||
a->origin = NULL;
|
||||
a->def = NULL;
|
||||
a->mp_cgienv = NULL;
|
||||
a->cgi_timeout = 0;
|
||||
}
|
||||
|
||||
/* this catches, eg, vhosts[].ws-protocols[].xxx-protocol */
|
||||
|
@ -241,7 +245,8 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
|
|||
}
|
||||
|
||||
n = lws_write_http_mount(a->last, &m, a->p, a->mountpoint,
|
||||
a->origin, a->def, a->mp_cgienv);
|
||||
a->origin, a->def, a->mp_cgienv,
|
||||
a->cgi_timeout);
|
||||
if (!n)
|
||||
return 1;
|
||||
a->p += n;
|
||||
|
@ -280,6 +285,9 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
|
|||
case LEJPVP_DEFAULT:
|
||||
a->def = a->p;
|
||||
break;
|
||||
case LEJPVP_CGI_TIMEOUT:
|
||||
a->cgi_timeout = atoi(ctx->buf);
|
||||
return 0;
|
||||
case LEJPVP_CGI_ENV:
|
||||
mp_cgienv = lwsws_align(a);
|
||||
a->p += sizeof(*a->mp_cgienv);
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
{
|
||||
"global": {
|
||||
"uid": "99",
|
||||
"gid": "99",
|
||||
"uid": "48",
|
||||
"gid": "48",
|
||||
"interface": "eth0",
|
||||
"count-threads": "1",
|
||||
"init-ssl": "yes"
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
# comment
|
||||
|
||||
{
|
||||
"vhosts": [ {
|
||||
"name": "libwebsockets.org",
|
||||
"port": "443",
|
||||
"host-ssl-key": "/etc/pki/tls/private/libwebsockets.org.key",
|
||||
"host-ssl-cert": "/etc/pki/tls/certs/libwebsockets.org.crt",
|
||||
"host-ssl-ca": "/etc/pki/tls/certs/libwebsockets.org.cer",
|
||||
"mounts": [{
|
||||
"mountpoint": "/",
|
||||
"origin": "file:///var/www/libwebsockets.org",
|
||||
"default": "index.html"
|
||||
}, {
|
||||
"mountpoint": "/git",
|
||||
"origin": "http://git.warmcat.com",
|
||||
"default": "/"
|
||||
}, {
|
||||
"mountpoint": "/mailman",
|
||||
"origin": "cgi://usr/lib/mailman/cgi-bin/",
|
||||
"default": "/list-info"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "libwebsockets.org", # disambiguated by port, must be same for SNI
|
||||
"port": "7681",
|
||||
"host-ssl-key": "/etc/pki/tls/private/libwebsockets.org.key",
|
||||
"host-ssl-cert": "/etc/pki/tls/certs/libwebsockets.org.crt",
|
||||
"host-ssl-ca": "/etc/pki/tls/certs/libwebsockets.org.cer",
|
||||
"ws-protocols": [{
|
||||
"wsprotocol": "dumb-increment-protocol",
|
||||
"wsprotocol": "lws-mirror-protocol",
|
||||
"wsprotocol": "lws-status"
|
||||
}],
|
||||
"ws-extensions": [{
|
||||
"extension": "permessage-deflate"
|
||||
}],
|
||||
"mounts": [{
|
||||
"mountpoint": "/",
|
||||
"origin": "file:///usr/local/share/libwebsockets-test-server",
|
||||
"default": "test.html"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "libwebsockets.org",
|
||||
"port": "80",
|
||||
"global-redirect": "https://libwebsockets.org"
|
||||
}]
|
||||
}
|
||||
|
99
lwsws/etc-lwsws-conf.d-localhost-EXAMPLE
Normal file
99
lwsws/etc-lwsws-conf.d-localhost-EXAMPLE
Normal file
|
@ -0,0 +1,99 @@
|
|||
{
|
||||
"vhosts": [ {
|
||||
"name": "localhost",
|
||||
"port": "80",
|
||||
"mounts": [{
|
||||
"mountpoint": "/",
|
||||
"origin": "file:///var/www/libwebsockets.org",
|
||||
"default": "index.html"
|
||||
}, {
|
||||
"mountpoint": "/git",
|
||||
"origin": "cgi:///var/www/cgi-bin/cgit",
|
||||
"default": "/",
|
||||
"cgi-env": [{
|
||||
"CGIT_CONFIG": "/etc/cgitrc/libwebsockets.org"
|
||||
}]
|
||||
}, {
|
||||
"mountpoint": "/cgit-data",
|
||||
"origin": "file:///usr/share/cgit",
|
||||
"default": "/"
|
||||
}, {
|
||||
"mountpoint": "/testcgi",
|
||||
"origin": "cgi:///usr/local/share/libwebsockets-test-server/lws-cgi-test.sh"
|
||||
}, {
|
||||
"mountpoint": "/mailman",
|
||||
"origin": ">http://localhost/mailman/listinfo"
|
||||
}, {
|
||||
"mountpoint": "/mailman/listinfo",
|
||||
"origin": "cgi:///usr/lib/mailman/cgi-bin/listinfo"
|
||||
}, {
|
||||
"mountpoint": "/mailman/admin",
|
||||
"origin": "cgi:///usr/lib/mailman/cgi-bin/admin"
|
||||
}, {
|
||||
"mountpoint": "/mailman/admindb",
|
||||
"origin": "cgi:///usr/lib/mailman/cgi-bin/admindb"
|
||||
}, {
|
||||
"mountpoint": "/mailman/confirm",
|
||||
"origin": "cgi:///usr/lib/mailman/cgi-bin/confirm"
|
||||
}, {
|
||||
"mountpoint": "/mailman/create",
|
||||
"origin": "cgi:///usr/lib/mailman/cgi-bin/create"
|
||||
}, {
|
||||
"mountpoint": "/mailman/edithtml",
|
||||
"origin": "cgi:///usr/lib/mailman/cgi-bin/edithtml"
|
||||
}, {
|
||||
"mountpoint": "/mailman/options",
|
||||
"origin": "cgi:///usr/lib/mailman/cgi-bin/options"
|
||||
}, {
|
||||
"mountpoint": "/mailman/private",
|
||||
"origin": "cgi:///usr/lib/mailman/cgi-bin/private"
|
||||
}, {
|
||||
"mountpoint": "/mailman/rmlist",
|
||||
"origin": "cgi:///usr/lib/mailman/cgi-bin/rmlist"
|
||||
}, {
|
||||
"mountpoint": "/mailman/roster",
|
||||
"origin": "cgi:///usr/lib/mailman/cgi-bin/roster"
|
||||
}, {
|
||||
"mountpoint": "/mailman/subscribe",
|
||||
"origin": "cgi:///usr/lib/mailman/cgi-bin/subscribe"
|
||||
}, {
|
||||
"mountpoint": "/pipermail",
|
||||
"origin": "file:///var/lib/mailman/archives/public",
|
||||
"default": "index.html"
|
||||
}, {
|
||||
"mountpoint": "/testserver",
|
||||
"origin": "file:///usr/local/share/libwebsockets-test-server",
|
||||
"default": "test.html"
|
||||
}],
|
||||
# which protocols are enabled for this vhost, and optional
|
||||
# vhost-specific config options for the protocol
|
||||
#
|
||||
"ws-protocols": [{
|
||||
"warmcat,timezoom": {
|
||||
"status": "ok"
|
||||
}
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "localhost",
|
||||
"port": "7681",
|
||||
"host-ssl-key": "/etc/pki/tls/private/libwebsockets.org.key",
|
||||
"host-ssl-cert": "/etc/pki/tls/certs/libwebsockets.org.crt",
|
||||
"host-ssl-ca": "/etc/pki/tls/certs/libwebsockets.org.cer",
|
||||
"mounts": [{
|
||||
"mountpoint": "/",
|
||||
"origin": ">https://localhost"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "localhostx",
|
||||
"port": "80",
|
||||
"mounts": [{
|
||||
"mountpoint": "/",
|
||||
"origin": ">https://localhost"
|
||||
}]
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
|
172
lwsws/http.c
172
lwsws/http.c
|
@ -71,7 +71,6 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
|||
struct per_session_data__http *pss =
|
||||
(struct per_session_data__http *)user;
|
||||
unsigned char buffer[4096 + LWS_PRE];
|
||||
unsigned long amount, file_len, sent;
|
||||
char leaf_path[1024];
|
||||
const char *mimetype;
|
||||
char *other_headers;
|
||||
|
@ -137,9 +136,6 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
|||
lwsl_err("proxy connect fail\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -156,89 +152,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
|||
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
|
||||
return 0;
|
||||
|
||||
/* check for the "send a big file by hand" example case */
|
||||
lwsl_notice("%s\n", in);
|
||||
if (!strcmp((const char *)in, "/leaf.jpg")) {
|
||||
if (strlen(resource_path) > sizeof(leaf_path) - 10)
|
||||
return -1;
|
||||
sprintf(leaf_path, "%s/leaf.jpg", resource_path);
|
||||
|
||||
/* well, let's demonstrate how to send the hard way */
|
||||
|
||||
p = buffer + LWS_PRE;
|
||||
end = p + sizeof(buffer) - LWS_PRE;
|
||||
|
||||
pss->fd = lws_plat_file_open(wsi, leaf_path, &file_len,
|
||||
LWS_O_RDONLY);
|
||||
|
||||
if (pss->fd == LWS_INVALID_FILE) {
|
||||
lwsl_err("faild to open file %s\n", leaf_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* we will send a big jpeg file, but it could be
|
||||
* anything. Set the Content-Type: appropriately
|
||||
* so the browser knows what to do with it.
|
||||
*
|
||||
* Notice we use the APIs to build the header, which
|
||||
* will do the right thing for HTTP 1/1.1 and HTTP2
|
||||
* depending on what connection it happens to be working
|
||||
* on
|
||||
*/
|
||||
if (lws_add_http_header_status(wsi, 200, &p, end))
|
||||
return 1;
|
||||
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SERVER,
|
||||
(unsigned char *)"libwebsockets",
|
||||
13, &p, end))
|
||||
return 1;
|
||||
if (lws_add_http_header_by_token(wsi,
|
||||
WSI_TOKEN_HTTP_CONTENT_TYPE,
|
||||
(unsigned char *)"image/jpeg",
|
||||
10, &p, end))
|
||||
return 1;
|
||||
if (lws_add_http_header_content_length(wsi,
|
||||
file_len, &p,
|
||||
end))
|
||||
return 1;
|
||||
if (lws_finalize_http_header(wsi, &p, end))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* send the http headers...
|
||||
* this won't block since it's the first payload sent
|
||||
* on the connection since it was established
|
||||
* (too small for partial)
|
||||
*
|
||||
* Notice they are sent using LWS_WRITE_HTTP_HEADERS
|
||||
* which also means you can't send body too in one step,
|
||||
* this is mandated by changes in HTTP2
|
||||
*/
|
||||
|
||||
*p = '\0';
|
||||
lwsl_info("%s\n", buffer + LWS_PRE);
|
||||
|
||||
n = lws_write(wsi, buffer + LWS_PRE,
|
||||
p - (buffer + LWS_PRE),
|
||||
LWS_WRITE_HTTP_HEADERS);
|
||||
if (n < 0) {
|
||||
lws_plat_file_close(wsi, pss->fd);
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* book us a LWS_CALLBACK_HTTP_WRITEABLE callback
|
||||
*/
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
}
|
||||
|
||||
/* if not, send a file the easy way */
|
||||
if (!strncmp(in, "/cgit-data/", 11)) {
|
||||
in = (char *)in + 11;
|
||||
strcpy(buf, "/usr/share/cgit");
|
||||
} else
|
||||
strcpy(buf, resource_path);
|
||||
|
||||
strcpy(buf, resource_path);
|
||||
if (strcmp(in, "/")) {
|
||||
if (*((const char *)in) != '/')
|
||||
strcat(buf, "/");
|
||||
|
@ -317,17 +231,14 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
|||
goto try_to_reuse;
|
||||
|
||||
case LWS_CALLBACK_HTTP_WRITEABLE:
|
||||
lwsl_info("LWS_CALLBACK_HTTP_WRITEABLE\n");
|
||||
// lwsl_notice("LWS_CALLBACK_HTTP_WRITEABLE\n");
|
||||
|
||||
if (pss->client_finished)
|
||||
return -1;
|
||||
|
||||
if (pss->fd == LWS_INVALID_FILE)
|
||||
goto try_to_reuse;
|
||||
#ifdef LWS_WITH_CGI
|
||||
if (pss->reason_bf & 1) {
|
||||
if (lws_cgi_write_split_stdout_headers(wsi) < 0)
|
||||
goto bail;
|
||||
if (lws_cgi_write_split_stdout_headers(wsi) < 0) {
|
||||
lwsl_debug("lws_cgi_write_split_stdout_headers says close\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pss->reason_bf &= ~1;
|
||||
break;
|
||||
|
@ -348,13 +259,20 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
|||
if (!wsi1)
|
||||
break;
|
||||
if (lws_http_client_read(wsi1, &px, &lenx) < 0)
|
||||
goto bail;
|
||||
return -1;
|
||||
|
||||
if (pss->client_finished)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
if (pss->client_finished)
|
||||
return -1;
|
||||
|
||||
if (pss->fd == LWS_INVALID_FILE)
|
||||
goto try_to_reuse;
|
||||
|
||||
/*
|
||||
* we can send more of whatever it is we were sending
|
||||
*/
|
||||
|
@ -416,16 +334,7 @@ bail:
|
|||
lws_plat_file_close(wsi, pss->fd);
|
||||
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* callback for confirming to continue with client IP appear in
|
||||
* protocol 0 callback since no websocket protocol has been agreed
|
||||
* yet. You can just ignore this if you won't filter on client IP
|
||||
* since the default unhandled callback return is 0 meaning let the
|
||||
* connection continue.
|
||||
*/
|
||||
case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
|
||||
/* if we returned non-zero from here, we kill the connection */
|
||||
#endif
|
||||
break;
|
||||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
|
@ -516,7 +425,7 @@ bail:
|
|||
case LWS_STDIN:
|
||||
/* TBD stdin rx flow control */
|
||||
break;
|
||||
case LWS_STDOUT:
|
||||
case LWS_STDOUT:;
|
||||
pss->reason_bf |= 1;
|
||||
/* when writing to MASTER would not block */
|
||||
lws_callback_on_writable(wsi);
|
||||
|
@ -541,8 +450,10 @@ bail:
|
|||
return -1;
|
||||
|
||||
case LWS_CALLBACK_CGI_STDIN_DATA: /* POST body for stdin */
|
||||
//lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA\n");
|
||||
lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA\n");
|
||||
pss->args = *((struct lws_cgi_args *)in);
|
||||
pss->args.data[pss->args.len] = '\0';
|
||||
//lwsl_err("(stdin fd = %d) %s\n", lws_get_socket_fd(pss->args.stdwsi[LWS_STDIN]), pss->args.data);
|
||||
n = write(lws_get_socket_fd(pss->args.stdwsi[LWS_STDIN]),
|
||||
pss->args.data, pss->args.len);
|
||||
//lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA: write says %d", n);
|
||||
|
@ -558,59 +469,14 @@ bail:
|
|||
*/
|
||||
|
||||
case LWS_CALLBACK_LOCK_POLL:
|
||||
/*
|
||||
* lock mutex to protect pollfd state
|
||||
* called before any other POLL related callback
|
||||
* if protecting wsi lifecycle change, len == 1
|
||||
*/
|
||||
test_server_lock(len);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_UNLOCK_POLL:
|
||||
/*
|
||||
* unlock mutex to protect pollfd state when
|
||||
* called after any other POLL related callback
|
||||
* if protecting wsi lifecycle change, len == 1
|
||||
*/
|
||||
test_server_unlock(len);
|
||||
break;
|
||||
|
||||
#ifdef EXTERNAL_POLL
|
||||
case LWS_CALLBACK_ADD_POLL_FD:
|
||||
|
||||
if (count_pollfds >= max_poll_elements) {
|
||||
lwsl_err("LWS_CALLBACK_ADD_POLL_FD: too many sockets to track\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fd_lookup[pa->fd] = count_pollfds;
|
||||
pollfds[count_pollfds].fd = pa->fd;
|
||||
pollfds[count_pollfds].events = pa->events;
|
||||
pollfds[count_pollfds++].revents = 0;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_DEL_POLL_FD:
|
||||
if (!--count_pollfds)
|
||||
break;
|
||||
m = fd_lookup[pa->fd];
|
||||
/* have the last guy take up the vacant slot */
|
||||
pollfds[m] = pollfds[count_pollfds];
|
||||
fd_lookup[pollfds[count_pollfds].fd] = m;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CHANGE_MODE_POLL_FD:
|
||||
pollfds[fd_lookup[pa->fd]].events = pa->events;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case LWS_CALLBACK_GET_THREAD_ID:
|
||||
/*
|
||||
* if you will call "lws_callback_on_writable"
|
||||
* from a different thread, return the caller thread ID
|
||||
* here so lws can use this information to work out if it
|
||||
* should signal the poll() loop to exit and restart early
|
||||
*/
|
||||
|
||||
/* return pthread_getthreadid_np(); */
|
||||
|
||||
break;
|
||||
|
|
|
@ -155,7 +155,7 @@ typedef char (*lejp_callback)(struct lejp_ctx *ctx, char reason);
|
|||
#endif
|
||||
#ifndef LEJP_STRING_CHUNK
|
||||
/* must be >= 30 to assemble floats */
|
||||
#define LEJP_STRING_CHUNK 64
|
||||
#define LEJP_STRING_CHUNK 128
|
||||
#endif
|
||||
|
||||
enum num_flags {
|
||||
|
|
|
@ -5,12 +5,16 @@ echo -e -n "\x0d\x0a"
|
|||
|
||||
echo "<html><body>"
|
||||
echo "<h1>lwstest script stdout</h1>"
|
||||
>&2 echo "lwstest script stderr"
|
||||
>&2 echo "lwstest script stderr: $REQUEST_METHOD"
|
||||
|
||||
echo "<h2>REQUEST_METHOD=$REQUEST_METHOD</h2>"
|
||||
|
||||
if [ "$REQUEST_METHOD" = "POST" ] ; then
|
||||
read line
|
||||
>&2 echo "lwstest script stderr: doing read"
|
||||
echo "CONTENT_LENGTH=$CONTENT_LENGTH"
|
||||
read -n $CONTENT_LENGTH line
|
||||
>&2 echo "lwstest script stderr: done read"
|
||||
|
||||
echo "read=\"$line\""
|
||||
else
|
||||
echo "<table>"
|
||||
|
|
Loading…
Add table
Reference in a new issue