1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00
Signed-off-by: Andy Green <andy@warmcat.com>
This commit is contained in:
Andy Green 2016-04-13 11:42:53 +08:00
parent 22d6f39e7f
commit f5efa74cb7
15 changed files with 317 additions and 263 deletions

View file

@ -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

View file

@ -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));

View file

@ -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));

View file

@ -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;

View file

@ -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 {

View file

@ -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;

View file

@ -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");

View file

@ -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,

View file

@ -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);

View file

@ -4,8 +4,8 @@
{
"global": {
"uid": "99",
"gid": "99",
"uid": "48",
"gid": "48",
"interface": "eth0",
"count-threads": "1",
"init-ssl": "yes"

View file

@ -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"
}]
}

View 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"
}]
}
]
}

View file

@ -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;

View file

@ -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 {

View file

@ -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>"