refactor: most preparation for -DLWS_ROLE_H1=0

This commit is contained in:
Andy Green 2018-04-27 19:16:50 +08:00
parent 16a907180c
commit ac6c48d98f
49 changed files with 407 additions and 242 deletions

View file

@ -199,7 +199,6 @@ if(GIT_EXECUTABLE)
endif()
# translate old functionality enables to set up ROLE enables so nothing changes
if (LWS_WITH_HTTP2)
set(LWS_ROLE_H2 1)
endif()
@ -215,6 +214,8 @@ if (LWS_WITH_HTTP2 AND LWS_WITHOUT_SERVER)
message(FATAL_ERROR "HTTP2 can only be used with server at the moment")
endif()
if (LWS_WITH_LWSWS)
message(STATUS "LWS_WITH_LWSWS --> Enabling LWS_WITH_PLUGINS and LWS_WITH_LIBUV")
set(LWS_WITH_PLUGINS 1)
@ -290,6 +291,40 @@ if (LWS_WITHOUT_SERVER)
set(LWS_WITH_LWSWS OFF)
endif()
# confirm H1 relationships
if (NOT LWS_ROLE_H1 AND LWS_ROLE_H2)
message(FATAL_ERROR "H2 requires LWS_ROLE_H1")
endif()
if (NOT LWS_ROLE_H1 AND LWS_ROLE_WS)
message(FATAL_ERROR "WS requires LWS_ROLE_H1")
endif()
if (NOT LWS_ROLE_H1 AND LWS_ROLE_CGI)
message(FATAL_ERROR "CGI requires LWS_ROLE_H1")
endif()
# confirm HTTP relationships
if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_HTTP_PROXY)
message(FATAL_ERROR "LWS_WITH_LWSWS requires LWS_ROLE_H1")
endif()
if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_HTTP_PROXY)
message(FATAL_ERROR "LWS_WITH_HTTP_PROXY requires LWS_ROLE_H1")
endif()
if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_RANGES)
message(FATAL_ERROR "LWS_WITH_RANGES requires LWS_ROLE_H1")
endif()
if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_ACCESS_LOG)
message(FATAL_ERROR "LWS_WITH_ACCESS_LOG requires LWS_ROLE_H1")
endif()
if (LWS_WITH_HTTP_PROXY AND (LWS_WITHOUT_CLIENT OR LWS_WITHOUT_SERVER))
message(FATAL_ERROR "You have to enable both client and server for http proxy")
endif()
@ -695,13 +730,17 @@ set(SOURCES
lib/service.c
lib/pollfd.c
lib/output.c
lib/roles/http/server/parsers.c
lib/context.c
lib/alloc.c
lib/roles/http/header.c
lib/roles/pipe/ops-pipe.c
lib/misc/lws-ring.c)
if (LWS_ROLE_H1 OR LWS_ROLE_H2)
list(APPEND SOURCES
lib/roles/http/header.c
lib/roles/http/server/parsers.c)
endif()
if (LWS_ROLE_H1)
list(APPEND SOURCES
lib/roles/h1/ops-h1.c)
@ -888,13 +927,13 @@ else()
endif()
endif()
if (NOT LWS_WITHOUT_SERVER)
if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_SERVER)
list(APPEND SOURCES
lib/roles/http/server/server.c
lib/roles/http/server/lws-spa.c)
endif()
if (NOT LWS_WITHOUT_EXTENSIONS)
if (LWS_ROLE_WS AND NOT LWS_WITHOUT_EXTENSIONS)
list(APPEND HDR_PRIVATE
lib/roles/ws/ext/extension-permessage-deflate.h)
list(APPEND SOURCES
@ -1481,7 +1520,7 @@ endif()
# Test applications
#
set(TEST_APP_LIST)
if (NOT LWS_WITHOUT_TESTAPPS)
if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS)
#
# Helper function for adding a test app.
#

View file

@ -288,6 +288,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
#endif
switch (reason) {
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
case LWS_CALLBACK_HTTP:
#ifndef LWS_NO_SERVER
if (lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL))
@ -315,7 +316,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
}
if (!n)
lws_rx_flow_control(
wsi->cgi->stdwsi[LWS_STDOUT], 1);
wsi->http.cgi->stdwsi[LWS_STDOUT], 1);
if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI_HEADERS)
wsi->reason_bf &=
@ -456,10 +457,10 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
case LWS_CALLBACK_CGI_TERMINATED:
lwsl_debug("LWS_CALLBACK_CGI_TERMINATED: %d %" PRIu64 "\n",
wsi->cgi->explicitly_chunked,
(uint64_t)wsi->cgi->content_length);
if (!wsi->cgi->explicitly_chunked &&
!wsi->cgi->content_length) {
wsi->http.cgi->explicitly_chunked,
(uint64_t)wsi->http.cgi->content_length);
if (!wsi->http.cgi->explicitly_chunked &&
!wsi->http.cgi->content_length) {
/* send terminating chunk */
lwsl_debug("LWS_CALLBACK_CGI_TERMINATED: ending\n");
wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_CHUNK_END;
@ -481,7 +482,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
"sent %d only %d went", n, args->len);
return n;
#endif
#endif
case LWS_CALLBACK_SSL_INFO:
si = in;
@ -1150,9 +1151,10 @@ lws_create_context(const struct lws_context_creation_info *info)
context->pt[n].context = context;
#endif
context->pt[n].tid = n;
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
context->pt[n].http.ah_list = NULL;
context->pt[n].http.ah_pool_length = 0;
#endif
lws_pt_mutex_init(&context->pt[n]);
}
@ -1220,7 +1222,7 @@ lws_create_context(const struct lws_context_creation_info *info)
(long)sizeof(struct lws_context),
(long)context->count_threads,
context->pt_serv_buf_size);
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
lwsl_info(" mem: http hdr rsvd: %5lu B (%u thr x (%u + %lu) x %u))\n",
(long)(context->max_http_header_data +
sizeof(struct allocated_headers)) *
@ -1229,6 +1231,7 @@ lws_create_context(const struct lws_context_creation_info *info)
context->max_http_header_data,
(long)sizeof(struct allocated_headers),
context->max_http_header_pool);
#endif
n = sizeof(struct lws_pollfd) * context->count_threads *
context->fd_limit_per_thread;
context->pt[0].fds = lws_zalloc(n, "fds table");
@ -1723,8 +1726,10 @@ lws_context_destroy(struct lws_context *context)
lws_free_set_NULL(context->pt[n].serv_buf);
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
while (pt->http.ah_list)
_lws_destroy_ah(pt, pt->http.ah_list);
#endif
}
lws_plat_context_early_destroy(context);

View file

@ -74,16 +74,32 @@ void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs)
}
#endif
signed char char_to_hex(const char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return -1;
}
void
__lws_free_wsi(struct lws *wsi)
{
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
struct lws_context_per_thread *pt;
struct allocated_headers *ah;
#endif
if (!wsi)
return;
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
pt = &wsi->context->pt[(int)wsi->tsi];
#endif
/*
* Protocol user data may be allocated either internally by lws
@ -97,24 +113,29 @@ __lws_free_wsi(struct lws *wsi)
lws_free_set_NULL(wsi->trunc_alloc);
lws_free_set_NULL(wsi->udp);
if (wsi->vhost && wsi->vhost->lserv_wsi == wsi)
wsi->vhost->lserv_wsi = NULL;
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
/* we may not have an ah, but may be on the waiting list... */
lwsl_info("ah det due to close\n");
__lws_header_table_detach(wsi, 0);
if (wsi->vhost && wsi->vhost->lserv_wsi == wsi)
wsi->vhost->lserv_wsi = NULL;
ah = pt->http.ah_list;
while (ah) {
if (ah->in_use && ah->wsi == wsi) {
lwsl_err("%s: ah leak: wsi %p\n", __func__, wsi);
ah->in_use = 0;
ah->wsi = NULL;
pt->http.ah_count_in_use--;
break;
{
struct allocated_headers *ah = pt->http.ah_list;
while (ah) {
if (ah->in_use && ah->wsi == wsi) {
lwsl_err("%s: ah leak: wsi %p\n", __func__, wsi);
ah->in_use = 0;
ah->wsi = NULL;
pt->http.ah_count_in_use--;
break;
}
ah = ah->next;
}
ah = ah->next;
}
#endif
#if defined(LWS_WITH_PEER_LIMITS)
lws_peer_track_wsi_close(wsi->context, wsi->peer);
@ -606,20 +627,20 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, const char *
#ifdef LWS_WITH_CGI
if (wsi->role_ops == &role_ops_cgi) {
/* we are not a network connection, but a handler for CGI io */
if (wsi->parent && wsi->parent->cgi) {
if (wsi->parent && wsi->parent->http.cgi) {
if (wsi->cgi_channel == LWS_STDOUT)
lws_cgi_remove_and_kill(wsi->parent);
/* end the binding between us and master */
wsi->parent->cgi->stdwsi[(int)wsi->cgi_channel] = NULL;
wsi->parent->http.cgi->stdwsi[(int)wsi->cgi_channel] = NULL;
}
wsi->socket_is_permanently_unusable = 1;
goto just_kill_connection;
}
if (wsi->cgi)
if (wsi->http.cgi)
lws_cgi_remove_and_kill(wsi);
#endif
@ -631,10 +652,11 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, const char *
wsi->socket_is_permanently_unusable = 1;
goto just_kill_connection;
}
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
if (lwsi_role_http(wsi) && lwsi_role_server(wsi) &&
wsi->http.fop_fd != NULL)
lws_vfs_file_close(&wsi->http.fop_fd);
#endif
if (lwsi_state(wsi) == LRS_DEAD_SOCKET)
return;
@ -879,17 +901,17 @@ __lws_close_free_wsi_final(struct lws *wsi)
wsi->user_space, NULL, 0);
#ifdef LWS_WITH_CGI
if (wsi->cgi) {
if (wsi->http.cgi) {
for (n = 0; n < 3; n++) {
if (wsi->cgi->pipe_fds[n][!!(n == 0)] == 0)
if (wsi->http.cgi->pipe_fds[n][!!(n == 0)] == 0)
lwsl_err("ZERO FD IN CGI CLOSE");
if (wsi->cgi->pipe_fds[n][!!(n == 0)] >= 0)
close(wsi->cgi->pipe_fds[n][!!(n == 0)]);
if (wsi->http.cgi->pipe_fds[n][!!(n == 0)] >= 0)
close(wsi->http.cgi->pipe_fds[n][!!(n == 0)]);
}
lws_free(wsi->cgi);
lws_free(wsi->http.cgi);
}
#endif
@ -2882,7 +2904,7 @@ lws_strncpy(char *dest, const char *src, size_t size)
LWS_VISIBLE LWS_EXTERN int
lws_is_cgi(struct lws *wsi) {
#ifdef LWS_WITH_CGI
return !!wsi->cgi;
return !!wsi->http.cgi;
#else
return 0;
#endif
@ -2944,6 +2966,7 @@ lws_cmdline_option(int argc, const char **argv, const char *val)
LWS_EXTERN int
lws_json_dump_vhost(const struct lws_vhost *vh, char *buf, int len)
{
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
static const char * const prots[] = {
"http://",
"https://",
@ -2953,6 +2976,7 @@ lws_json_dump_vhost(const struct lws_vhost *vh, char *buf, int len)
">https://",
"callback://"
};
#endif
char *orig = buf, *end = buf + len - 1, first = 1;
int n = 0;

View file

@ -215,7 +215,7 @@ LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len,
lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_B_WRITE, len);
#ifdef LWS_WITH_ACCESS_LOG
wsi->access_log.sent += len;
wsi->http.access_log.sent += len;
#endif
if (wsi->vhost)
wsi->vhost->conn_stats.tx += len;

View file

@ -1397,9 +1397,6 @@ struct lws {
#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBEVENT)
struct lws_io_watcher w_write;
#endif
#ifdef LWS_WITH_ACCESS_LOG
struct lws_access_log access_log;
#endif
/* pointers */
@ -1409,9 +1406,6 @@ struct lws {
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 */
#endif
const struct lws_protocols *protocol;
struct lws **same_vh_protocol_prev, *same_vh_protocol_next;
@ -1678,8 +1672,7 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd);
LWS_EXTERN struct lws *
lws_client_connect_via_info2(struct lws *wsi);
LWS_EXTERN int
_lws_destroy_ah(struct lws_context_per_thread *pt, struct allocated_headers *ah);
LWS_EXTERN void
lws_client_stash_destroy(struct lws *wsi);
@ -1733,8 +1726,7 @@ __lws_header_table_detach(struct lws *wsi, int autoservice);
LWS_EXTERN void
lws_header_table_reset(struct lws *wsi, int autoservice);
void
_lws_header_table_reset(struct allocated_headers *ah);
void
__lws_header_table_reset(struct lws *wsi, int autoservice);
@ -2095,8 +2087,7 @@ __lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs);
int
__lws_change_pollfd(struct lws *wsi, int _and, int _or);
int
lws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len);
int
lws_callback_as_writeable(struct lws *wsi);
int
@ -2105,12 +2096,8 @@ lws_buflist_aware_read(struct lws_context_per_thread *pt, struct lws *wsi,
int
lws_buflist_aware_consume(struct lws *wsi, struct lws_tokens *ebuf, int used,
int buffered);
int
lws_process_ws_upgrade(struct lws *wsi);
int
lws_server_init_wsi_for_ws(struct lws *wsi);
int
handshake_0405(struct lws_context *context, struct lws *wsi);
char *
lws_generate_client_ws_handshake(struct lws *wsi, char *p);
int

View file

@ -121,15 +121,15 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
* give the master wsi a cgi struct
*/
wsi->cgi = lws_zalloc(sizeof(*wsi->cgi), "new cgi");
if (!wsi->cgi) {
wsi->http.cgi = lws_zalloc(sizeof(*wsi->http.cgi), "new cgi");
if (!wsi->http.cgi) {
lwsl_err("%s: OOM\n", __func__);
return -1;
}
wsi->cgi->response_code = HTTP_STATUS_OK;
wsi->http.cgi->response_code = HTTP_STATUS_OK;
cgi = wsi->cgi;
cgi = wsi->http.cgi;
cgi->wsi = wsi; /* set cgi's owning wsi */
sum = cgi->summary;
sumend = sum + strlen(cgi->summary) - 1;
@ -187,7 +187,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
wsi->hdr_state = LCHS_HEADER;
/* add us to the pt list of active cgis */
lwsl_debug("%s: adding cgi %p to list\n", __func__, wsi->cgi);
lwsl_debug("%s: adding cgi %p to list\n", __func__, wsi->http.cgi);
cgi->cgi_list = pt->http.cgi_list;
pt->http.cgi_list = cgi;
@ -445,10 +445,10 @@ bail3:
pt->http.cgi_list = cgi->cgi_list;
while (--n >= 0)
__remove_wsi_socket_from_fds(wsi->cgi->stdwsi[n]);
__remove_wsi_socket_from_fds(wsi->http.cgi->stdwsi[n]);
bail2:
for (n = 0; n < 3; n++)
if (wsi->cgi->stdwsi[n])
if (wsi->http.cgi->stdwsi[n])
__lws_free_wsi(cgi->stdwsi[n]);
bail1:
@ -459,7 +459,7 @@ bail1:
close(cgi->pipe_fds[n][1]);
}
lws_free_set_NULL(wsi->cgi);
lws_free_set_NULL(wsi->http.cgi);
lwsl_err("%s: failed\n", __func__);
@ -491,7 +491,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
*value = NULL;
char c, hrs;
if (!wsi->cgi)
if (!wsi->http.cgi)
return -1;
while (wsi->hdr_state != LHCS_PAYLOAD) {
@ -502,13 +502,13 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
switch (wsi->hdr_state) {
case LHCS_RESPONSE:
lwsl_debug("LHCS_RESPONSE: issuing response %d\n",
wsi->cgi->response_code);
wsi->http.cgi->response_code);
if (lws_add_http_header_status(wsi,
wsi->cgi->response_code,
wsi->http.cgi->response_code,
&p, end))
return 1;
if (!wsi->cgi->explicitly_chunked &&
!wsi->cgi->content_length &&
if (!wsi->http.cgi->explicitly_chunked &&
!wsi->http.cgi->content_length &&
lws_add_http_header_by_token(wsi,
WSI_TOKEN_HTTP_TRANSFER_ENCODING,
(unsigned char *)"chunked", 7, &p, end))
@ -524,8 +524,8 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
/*
* so we have a bunch of http/1 style ascii headers
* starting from wsi->cgi->headers_buf through
* wsi->cgi->headers_pos. These are OK for http/1
* starting from wsi->http.cgi->headers_buf through
* wsi->http.cgi->headers_pos. These are OK for http/1
* connections, but they're no good for http/2 conns.
*
* Let's redo them at headers_pos forward using the
@ -534,13 +534,13 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
if (!wsi->http2_substream)
goto post_hpack_recode;
p = wsi->cgi->headers_start;
wsi->cgi->headers_start = wsi->cgi->headers_pos;
wsi->cgi->headers_dumped = wsi->cgi->headers_start;
p = wsi->http.cgi->headers_start;
wsi->http.cgi->headers_start = wsi->http.cgi->headers_pos;
wsi->http.cgi->headers_dumped = wsi->http.cgi->headers_start;
hrs = HR_NAME;
name = buf;
while (p < wsi->cgi->headers_start) {
while (p < wsi->http.cgi->headers_start) {
switch (hrs) {
case HR_NAME:
/*
@ -582,7 +582,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
/* fallthru */
case HR_CRLF:
if ((*p != '\x0a' && *p != '\x0d') ||
p + 1 == wsi->cgi->headers_start) {
p + 1 == wsi->http.cgi->headers_start) {
*name = '\0';
if ((strcmp((const char *)buf,
"transfer-encoding")
@ -592,8 +592,8 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
if (
lws_add_http_header_by_name(wsi, buf,
(unsigned char *)value, name - value,
(unsigned char **)&wsi->cgi->headers_pos,
(unsigned char *)wsi->cgi->headers_end))
(unsigned char **)&wsi->http.cgi->headers_pos,
(unsigned char *)wsi->http.cgi->headers_end))
return 1;
hrs = HR_NAME;
name = buf;
@ -607,8 +607,8 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
post_hpack_recode:
/* finalize cached headers before dumping them */
if (lws_finalize_http_header(wsi,
(unsigned char **)&wsi->cgi->headers_pos,
(unsigned char *)wsi->cgi->headers_end)) {
(unsigned char **)&wsi->http.cgi->headers_pos,
(unsigned char *)wsi->http.cgi->headers_end)) {
lwsl_notice("finalize failed\n");
return -1;
@ -622,30 +622,30 @@ post_hpack_recode:
case LHCS_DUMP_HEADERS:
n = wsi->cgi->headers_pos - wsi->cgi->headers_dumped;
n = wsi->http.cgi->headers_pos - wsi->http.cgi->headers_dumped;
if (n > 512)
n = 512;
lwsl_debug("LHCS_DUMP_HEADERS: %d\n", n);
cmd = LWS_WRITE_HTTP_HEADERS_CONTINUATION;
if (wsi->cgi->headers_dumped + n !=
wsi->cgi->headers_pos) {
if (wsi->http.cgi->headers_dumped + n !=
wsi->http.cgi->headers_pos) {
lwsl_notice("adding no fin flag\n");
cmd |= LWS_WRITE_NO_FIN;
}
m = lws_write(wsi,
(unsigned char *)wsi->cgi->headers_dumped,
(unsigned char *)wsi->http.cgi->headers_dumped,
n, cmd);
if (m < 0) {
lwsl_debug("%s: write says %d\n", __func__, m);
return -1;
}
wsi->cgi->headers_dumped += n;
if (wsi->cgi->headers_dumped == wsi->cgi->headers_pos) {
wsi->http.cgi->headers_dumped += n;
if (wsi->http.cgi->headers_dumped == wsi->http.cgi->headers_pos) {
wsi->hdr_state = LHCS_PAYLOAD;
lws_free_set_NULL(wsi->cgi->headers_buf);
lws_free_set_NULL(wsi->http.cgi->headers_buf);
lwsl_debug("freed cgi headers\n");
} else {
wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_HEADERS;
@ -658,31 +658,31 @@ post_hpack_recode:
return 0;
}
if (!wsi->cgi->headers_buf) {
if (!wsi->http.cgi->headers_buf) {
/* if we don't already have a headers buf, cook one up */
n = 2048;
if (wsi->http2_substream)
n = 4096;
wsi->cgi->headers_buf = lws_malloc(n + LWS_PRE,
wsi->http.cgi->headers_buf = lws_malloc(n + LWS_PRE,
"cgi hdr buf");
if (!wsi->cgi->headers_buf) {
if (!wsi->http.cgi->headers_buf) {
lwsl_err("OOM\n");
return -1;
}
lwsl_debug("allocated cgi hdrs\n");
wsi->cgi->headers_start = wsi->cgi->headers_buf + LWS_PRE;
wsi->cgi->headers_pos = wsi->cgi->headers_start;
wsi->cgi->headers_dumped = wsi->cgi->headers_pos;
wsi->cgi->headers_end = wsi->cgi->headers_buf + n - 1;
wsi->http.cgi->headers_start = wsi->http.cgi->headers_buf + LWS_PRE;
wsi->http.cgi->headers_pos = wsi->http.cgi->headers_start;
wsi->http.cgi->headers_dumped = wsi->http.cgi->headers_pos;
wsi->http.cgi->headers_end = wsi->http.cgi->headers_buf + n - 1;
for (n = 0; n < SIGNIFICANT_HDR_COUNT; n++) {
wsi->cgi->match[n] = 0;
wsi->cgi->lp = 0;
wsi->http.cgi->match[n] = 0;
wsi->http.cgi->lp = 0;
}
}
n = lws_get_socket_fd(wsi->cgi->stdwsi[LWS_STDOUT]);
n = lws_get_socket_fd(wsi->http.cgi->stdwsi[LWS_STDOUT]);
if (n < 0)
return -1;
n = read(n, &c, 1);
@ -694,7 +694,7 @@ post_hpack_recode:
else
n = 0;
if (wsi->cgi->headers_pos >= wsi->cgi->headers_end - 4) {
if (wsi->http.cgi->headers_pos >= wsi->http.cgi->headers_end - 4) {
lwsl_notice("CGI hdrs > buf size\n");
return -1;
@ -704,7 +704,7 @@ post_hpack_recode:
goto agin;
lwsl_debug("-- 0x%02X %c %d %d\n", (unsigned char)c, c,
wsi->cgi->match[1], wsi->hdr_state);
wsi->http.cgi->match[1], wsi->hdr_state);
if (!c)
return -1;
switch (wsi->hdr_state) {
@ -715,64 +715,64 @@ post_hpack_recode:
* significant headers with
* numeric decimal payloads
*/
if (!significant_hdr[n][wsi->cgi->match[n]] &&
if (!significant_hdr[n][wsi->http.cgi->match[n]] &&
(c >= '0' && c <= '9') &&
wsi->cgi->lp < (int)sizeof(wsi->cgi->l) - 1) {
wsi->cgi->l[wsi->cgi->lp++] = c;
wsi->cgi->l[wsi->cgi->lp] = '\0';
wsi->http.cgi->lp < (int)sizeof(wsi->http.cgi->l) - 1) {
wsi->http.cgi->l[wsi->http.cgi->lp++] = c;
wsi->http.cgi->l[wsi->http.cgi->lp] = '\0';
switch (n) {
case SIGNIFICANT_HDR_CONTENT_LENGTH:
wsi->cgi->content_length =
atoll(wsi->cgi->l);
wsi->http.cgi->content_length =
atoll(wsi->http.cgi->l);
break;
case SIGNIFICANT_HDR_STATUS:
wsi->cgi->response_code =
atol(wsi->cgi->l);
wsi->http.cgi->response_code =
atol(wsi->http.cgi->l);
lwsl_debug("Status set to %d\n",
wsi->cgi->response_code);
wsi->http.cgi->response_code);
break;
default:
break;
}
}
/* hits up to the NUL are sticky until next hdr */
if (significant_hdr[n][wsi->cgi->match[n]]) {
if (significant_hdr[n][wsi->http.cgi->match[n]]) {
if (tolower(c) ==
significant_hdr[n][wsi->cgi->match[n]])
wsi->cgi->match[n]++;
significant_hdr[n][wsi->http.cgi->match[n]])
wsi->http.cgi->match[n]++;
else
wsi->cgi->match[n] = 0;
wsi->http.cgi->match[n] = 0;
}
}
/* some cgi only send us \x0a for EOL */
if (c == '\x0a') {
wsi->hdr_state = LCHS_SINGLE_0A;
*wsi->cgi->headers_pos++ = '\x0d';
*wsi->http.cgi->headers_pos++ = '\x0d';
}
*wsi->cgi->headers_pos++ = c;
*wsi->http.cgi->headers_pos++ = c;
if (c == '\x0d')
wsi->hdr_state = LCHS_LF1;
if (wsi->hdr_state != LCHS_HEADER &&
!significant_hdr[SIGNIFICANT_HDR_TRANSFER_ENCODING]
[wsi->cgi->match[
[wsi->http.cgi->match[
SIGNIFICANT_HDR_TRANSFER_ENCODING]]) {
lwsl_debug("cgi produced chunked\n");
wsi->cgi->explicitly_chunked = 1;
wsi->http.cgi->explicitly_chunked = 1;
}
/* presence of Location: mandates 302 retcode */
if (wsi->hdr_state != LCHS_HEADER &&
!significant_hdr[SIGNIFICANT_HDR_LOCATION][
wsi->cgi->match[SIGNIFICANT_HDR_LOCATION]]) {
wsi->http.cgi->match[SIGNIFICANT_HDR_LOCATION]]) {
lwsl_debug("CGI: Location hdr seen\n");
wsi->cgi->response_code = 302;
wsi->http.cgi->response_code = 302;
}
break;
case LCHS_LF1:
*wsi->cgi->headers_pos++ = c;
*wsi->http.cgi->headers_pos++ = c;
if (c == '\x0a') {
wsi->hdr_state = LCHS_CR2;
break;
@ -790,8 +790,8 @@ post_hpack_recode:
}
wsi->hdr_state = LCHS_HEADER;
for (n = 0; n < SIGNIFICANT_HDR_COUNT; n++)
wsi->cgi->match[n] = 0;
wsi->cgi->lp = 0;
wsi->http.cgi->match[n] = 0;
wsi->http.cgi->lp = 0;
goto hdr;
case LCHS_LF2:
@ -800,7 +800,7 @@ post_hpack_recode:
if (c == '\x0a') {
lwsl_debug("Content-Length: %lld\n",
(unsigned long long)
wsi->cgi->content_length);
wsi->http.cgi->content_length);
wsi->hdr_state = LHCS_RESPONSE;
/*
* drop the \0xa ... finalize
@ -812,11 +812,11 @@ post_hpack_recode:
/* we got \r\n\r[^\n]... unreasonable */
return -1;
/* we got \x0anext header, it's reasonable */
*wsi->cgi->headers_pos++ = c;
*wsi->http.cgi->headers_pos++ = c;
wsi->hdr_state = LCHS_HEADER;
for (n = 0; n < SIGNIFICANT_HDR_COUNT; n++)
wsi->cgi->match[n] = 0;
wsi->cgi->lp = 0;
wsi->http.cgi->match[n] = 0;
wsi->http.cgi->lp = 0;
break;
case LHCS_PAYLOAD:
break;
@ -830,8 +830,8 @@ agin:
/* payload processing */
m = !wsi->cgi->explicitly_chunked && !wsi->cgi->content_length;
n = lws_get_socket_fd(wsi->cgi->stdwsi[LWS_STDOUT]);
m = !wsi->http.cgi->explicitly_chunked && !wsi->http.cgi->content_length;
n = lws_get_socket_fd(wsi->http.cgi->stdwsi[LWS_STDOUT]);
if (n < 0)
return -1;
n = read(n, start, sizeof(buf) - LWS_PRE -
@ -852,7 +852,7 @@ agin:
n += m + 2;
}
cmd = LWS_WRITE_HTTP;
if (wsi->cgi->content_length_seen + n == wsi->cgi->content_length)
if (wsi->http.cgi->content_length_seen + n == wsi->http.cgi->content_length)
cmd = LWS_WRITE_HTTP_FINAL;
m = lws_write(wsi, (unsigned char *)start, n, cmd);
//lwsl_notice("write %d\n", m);
@ -860,7 +860,7 @@ agin:
lwsl_debug("%s: stdout write says %d\n", __func__, m);
return -1;
}
wsi->cgi->content_length_seen += n;
wsi->http.cgi->content_length_seen += n;
} else {
if (wsi->cgi_stdout_zero_length) {
lwsl_debug("%s: stdout is POLLHUP'd\n", __func__);
@ -882,20 +882,20 @@ lws_cgi_kill(struct lws *wsi)
lwsl_debug("%s: %p\n", __func__, wsi);
if (!wsi->cgi)
if (!wsi->http.cgi)
return 0;
if (wsi->cgi->pid > 0) {
n = waitpid(wsi->cgi->pid, &status, WNOHANG);
if (wsi->http.cgi->pid > 0) {
n = waitpid(wsi->http.cgi->pid, &status, WNOHANG);
if (n > 0) {
lwsl_debug("%s: PID %d reaped\n", __func__,
wsi->cgi->pid);
wsi->http.cgi->pid);
goto handled;
}
/* kill the process group */
n = kill(-wsi->cgi->pid, SIGTERM);
n = kill(-wsi->http.cgi->pid, SIGTERM);
lwsl_debug("%s: SIGTERM child PID %d says %d (errno %d)\n",
__func__, wsi->cgi->pid, n, errno);
__func__, wsi->http.cgi->pid, n, errno);
if (n < 0) {
/*
* hum seen errno=3 when process is listed in ps,
@ -903,28 +903,28 @@ lws_cgi_kill(struct lws *wsi)
*
* Direct these fallback attempt to the exact child
*/
n = kill(wsi->cgi->pid, SIGTERM);
n = kill(wsi->http.cgi->pid, SIGTERM);
if (n < 0) {
n = kill(wsi->cgi->pid, SIGPIPE);
n = kill(wsi->http.cgi->pid, SIGPIPE);
if (n < 0) {
n = kill(wsi->cgi->pid, SIGKILL);
n = kill(wsi->http.cgi->pid, SIGKILL);
if (n < 0)
lwsl_err("%s: SIGKILL PID %d "
"failed errno %d "
"(maybe zombie)\n",
__func__,
wsi->cgi->pid, errno);
wsi->http.cgi->pid, errno);
}
}
}
/* He could be unkillable because he's a zombie */
n = 1;
while (n > 0) {
n = waitpid(-wsi->cgi->pid, &status, WNOHANG);
n = waitpid(-wsi->http.cgi->pid, &status, WNOHANG);
if (n > 0)
lwsl_debug("%s: reaped PID %d\n", __func__, n);
if (n <= 0) {
n = waitpid(wsi->cgi->pid, &status, WNOHANG);
n = waitpid(wsi->http.cgi->pid, &status, WNOHANG);
if (n > 0)
lwsl_debug("%s: reaped PID %d\n",
__func__, n);
@ -933,15 +933,15 @@ lws_cgi_kill(struct lws *wsi)
}
handled:
args.stdwsi = &wsi->cgi->stdwsi[0];
args.stdwsi = &wsi->http.cgi->stdwsi[0];
if (wsi->cgi->pid != -1) {
if (wsi->http.cgi->pid != -1) {
n = user_callback_handle_rxflow(wsi->protocol->callback, wsi,
LWS_CALLBACK_CGI_TERMINATED,
wsi->user_space,
(void *)&args, wsi->cgi->pid);
wsi->cgi->pid = -1;
if (n && !wsi->cgi->being_closed)
(void *)&args, wsi->http.cgi->pid);
wsi->http.cgi->pid = -1;
if (n && !wsi->http.cgi->being_closed)
lws_close_free_wsi(wsi, 0, "lws_cgi_kill");
}
@ -1085,10 +1085,10 @@ finish_him:
LWS_VISIBLE LWS_EXTERN struct lws *
lws_cgi_get_stdwsi(struct lws *wsi, enum lws_enum_stdinouterr ch)
{
if (!wsi->cgi)
if (!wsi->http.cgi)
return NULL;
return wsi->cgi->stdwsi[ch];
return wsi->http.cgi->stdwsi[ch];
}
void
@ -1098,20 +1098,20 @@ lws_cgi_remove_and_kill(struct lws *wsi)
struct lws_cgi **pcgi = &pt->http.cgi_list;
/* remove us from the cgi list */
lwsl_debug("%s: remove cgi %p from list\n", __func__, wsi->cgi);
lwsl_debug("%s: remove cgi %p from list\n", __func__, wsi->http.cgi);
while (*pcgi) {
if (*pcgi == wsi->cgi) {
if (*pcgi == wsi->http.cgi) {
/* drop us from the pt cgi list */
*pcgi = (*pcgi)->cgi_list;
break;
}
pcgi = &(*pcgi)->cgi_list;
}
if (wsi->cgi->headers_buf) {
if (wsi->http.cgi->headers_buf) {
lwsl_debug("close: freed cgi headers\n");
lws_free_set_NULL(wsi->cgi->headers_buf);
lws_free_set_NULL(wsi->http.cgi->headers_buf);
}
/* we have a cgi going, we must kill it */
wsi->cgi->being_closed = 1;
wsi->http.cgi->being_closed = 1;
lws_cgi_kill(wsi);
}

View file

@ -44,7 +44,7 @@ rops_handle_POLLIN_cgi(struct lws_context_per_thread *pt, struct lws *wsi,
}
args.ch = wsi->cgi_channel;
args.stdwsi = &wsi->parent->cgi->stdwsi[0];
args.stdwsi = &wsi->parent->http.cgi->stdwsi[0];
args.hdr_state = wsi->hdr_state;
lwsl_debug("CGI LWS_STDOUT %p wsistate 0x%x\n",

View file

@ -128,11 +128,11 @@ http_postbody:
wsi->http.rx_content_remain -= body_chunk_len;
len -= body_chunk_len;
#ifdef LWS_WITH_CGI
if (wsi->cgi) {
if (wsi->http.cgi) {
struct lws_cgi_args args;
args.ch = LWS_STDIN;
args.stdwsi = &wsi->cgi->stdwsi[0];
args.stdwsi = &wsi->http.cgi->stdwsi[0];
args.data = buf;
args.len = body_chunk_len;
@ -169,14 +169,14 @@ postbody_completion:
* If we're running a cgi, we can't let him off the
* hook just because he sent his POST data
*/
if (wsi->cgi)
if (wsi->http.cgi)
lws_set_timeout(wsi, PENDING_TIMEOUT_CGI,
wsi->context->timeout_secs);
else
#endif
lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
#ifdef LWS_WITH_CGI
if (!wsi->cgi)
if (!wsi->http.cgi)
#endif
{
lwsl_info("HTTP_BODY_COMPLETION: %p (%s)\n",
@ -478,7 +478,7 @@ rops_handle_POLLIN_h1(struct lws_context_per_thread *pt, struct lws *wsi,
// wsi->wsistate, wsi->role_ops->name, pollfd->revents);
#ifdef LWS_WITH_CGI
if (wsi->cgi && (pollfd->revents & LWS_POLLOUT)) {
if (wsi->http.cgi && (pollfd->revents & LWS_POLLOUT)) {
if (lws_handle_POLLOUT_event(wsi, pollfd))
return LWS_HPI_RET_PLEASE_CLOSE_ME;

View file

@ -98,7 +98,7 @@ rops_handle_POLLIN_h2(struct lws_context_per_thread *pt, struct lws *wsi,
int n, m;
#ifdef LWS_WITH_CGI
if (wsi->cgi && (pollfd->revents & LWS_POLLOUT)) {
if (wsi->http.cgi && (pollfd->revents & LWS_POLLOUT)) {
if (lws_handle_POLLOUT_event(wsi, pollfd))
return LWS_HPI_RET_PLEASE_CLOSE_ME;

View file

@ -28,16 +28,20 @@ lws_getaddrinfo46(struct lws *wsi, const char *ads, struct addrinfo **result)
struct lws *
lws_client_connect_2(struct lws *wsi)
{
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
struct lws_context *context = wsi->context;
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
const char *cce = "", *iface, *adsin, *meth;
const char *adsin;
struct lws *wsi_piggyback = NULL;
struct addrinfo *result;
struct lws_pollfd pfd;
ssize_t plen = 0;
#endif
struct addrinfo *result;
const char *ads;
sockaddr46 sa46;
int n, port;
const char *cce = "", *iface;
const char *meth = NULL;
#ifdef LWS_WITH_IPV6
char ipv6only = lws_check_opt(wsi->vhost->options,
LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY |
@ -50,13 +54,14 @@ lws_client_connect_2(struct lws *wsi)
lwsl_client("%s: %p\n", __func__, wsi);
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
if (!wsi->http.ah) {
cce = "ah was NULL at cc2";
lwsl_err("%s\n", cce);
goto oom4;
}
/* we can only piggyback GET */
/* we can only piggyback GET or POST */
meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD);
if (meth && strcmp(meth, "GET") && strcmp(meth, "POST"))
@ -142,6 +147,7 @@ lws_client_connect_2(struct lws *wsi)
lws_vhost_unlock(wsi->vhost);
create_new_conn:
#endif
/*
* clients who will create their own fresh connection keep a copy of
@ -176,6 +182,8 @@ create_new_conn:
*/
wsi->ipv6 = LWS_IPV6_ENABLED(wsi->vhost);
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
/* Decide what it is we need to connect to:
*
* Priority 1: connect to http proxy */
@ -195,6 +203,9 @@ create_new_conn:
plen += sprintf((char *)pt->serv_buf + plen, "\x0d\x0a");
ads = wsi->vhost->http.http_proxy_address;
port = wsi->vhost->http.http_proxy_port;
#else
if (0) {
#endif
#if defined(LWS_WITH_SOCKS5)
@ -328,7 +339,7 @@ create_new_conn:
if (!lws_socket_is_valid(wsi->desc.sockfd)) {
#if defined(LWS_WITH_LIBUV)
if (LWS_LIBUV_ENABLED(context))
if (LWS_LIBUV_ENABLED(wsi->context))
if (lws_libuv_check_watcher_active(wsi)) {
lwsl_warn("Waiting for libuv watcher to close\n");
cce = "waiting for libuv watcher to close";
@ -362,7 +373,7 @@ create_new_conn:
lws_libuv_accept(wsi, wsi->desc);
lws_libevent_accept(wsi, wsi->desc);
if (__insert_wsi_socket_into_fds(context, wsi)) {
if (__insert_wsi_socket_into_fds(wsi->context, wsi)) {
compatible_close(wsi->desc.sockfd);
cce = "insert wsi failed";
goto oom4;
@ -444,6 +455,7 @@ create_new_conn:
lwsl_client("connected\n");
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
/* we are connected to server, or proxy */
/* http proxy */
@ -475,6 +487,7 @@ create_new_conn:
return wsi;
}
#endif
#if defined(LWS_WITH_SOCKS5)
/* socks proxy */
else if (wsi->vhost->socks_proxy_port) {
@ -494,8 +507,9 @@ create_new_conn:
return wsi;
}
#endif
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
send_hs:
if (wsi_piggyback &&
!lws_dll_is_null(&wsi->dll_client_transaction_queue)) {
/*
@ -548,7 +562,7 @@ send_hs:
if (n) /* returns 1 on failure after closing wsi */
return NULL;
}
#endif
return wsi;
oom4:
@ -562,7 +576,9 @@ oom4:
if (wsi->position_in_fds_table != -1)
goto failed1;
lws_remove_from_timeout_list(wsi);
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
lws_header_table_detach(wsi, 0);
#endif
lws_client_stash_destroy(wsi);
lws_free_set_NULL(wsi->client_hostname_copy);
lws_free(wsi);
@ -580,6 +596,8 @@ failed1:
return NULL;
}
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
/**
* lws_client_reset() - retarget a connected wsi to start over with a new connection (ie, redirect)
* this only works if still in HTTP, ie, not upgraded yet
@ -833,6 +851,8 @@ html_parser_cb(const hubbub_token *token, void *pw)
}
#endif
#endif
static char *
lws_strdup(const char *s)
{
@ -891,7 +911,7 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
/* assert the mode and union status (hdr) clearly */
lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED, &role_ops_h1);
#else
lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED, &role_ops_raw);
lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED, &role_ops_raw_skt);
#endif
wsi->desc.sockfd = LWS_SOCK_INVALID;
@ -926,7 +946,12 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
wsi->client_pipeline = !!(i->ssl_connection & LCCSCF_PIPELINE);
/* reasonable place to start */
lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED, &role_ops_h1);
lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED,
#if defined(LWS_ROLE_H1)
&role_ops_h1);
#else
&role_ops_raw_skt);
#endif
/*
* 1) for http[s] connection, allow protocol selection by name
@ -1027,6 +1052,7 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
if (i->pwsi)
*i->pwsi = wsi;
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
/* if we went on the waiting list, no probs just return the wsi
* when we get the ah, now or later, he will call
* lws_client_connect_via_info2() below.
@ -1039,6 +1065,8 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
goto bail2;
}
#endif
if (i->parent_wsi) {
lwsl_info("%s: created child %p of parent %p\n", __func__,
wsi, i->parent_wsi);
@ -1060,8 +1088,9 @@ bail1:
bail:
lws_free(wsi);
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
bail2:
#endif
if (i->pwsi)
*i->pwsi = NULL;

View file

@ -84,10 +84,12 @@ lws_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd,
char ebuf[128];
#endif
const char *cce = NULL;
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
ssize_t len = 0;
unsigned char c;
#endif
char *sb = p;
int n = 0;
ssize_t len = 0;
#if defined(LWS_WITH_SOCKS5)
char conn_mode = 0, pending_timeout = 0;
#endif
@ -404,11 +406,12 @@ start_ws_handshake:
if (lwsi_state(w) == LRS_IDLING) {
lwsi_set_state(w, LRS_WAITING_SERVER_REPLY);
w->hdr_parsing_completed = 0;
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
w->http.ah->parser_state = WSI_TOKEN_NAME_PART;
w->http.ah->lextable_pos = 0;
/* If we're (re)starting on headers, need other implied init */
wsi->http.ah->ues = URIES_IDLE;
#endif
}
lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
@ -427,9 +430,11 @@ start_ws_handshake:
break;
}
client_http_body_sent:
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
/* prepare ourselves to do the parsing */
wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART;
wsi->http.ah->lextable_pos = 0;
#endif
lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
context->timeout_secs);
@ -452,6 +457,7 @@ client_http_body_sent:
if (!(pollfd->revents & LWS_POLLIN))
break;
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
/* interpret the server response
*
* HTTP/1.1 101 Switching Protocols
@ -499,7 +505,7 @@ client_http_body_sent:
if (wsi->http.ah->parser_state != WSI_PARSING_COMPLETE)
break;
#endif
/*
* otherwise deal with the handshake. If there's any
@ -526,7 +532,7 @@ bail3:
return 0;
}
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
int LWS_WARN_UNUSED_RESULT
lws_http_transaction_completed_client(struct lws *wsi)
@ -622,6 +628,7 @@ lws_http_client_http_response(struct lws *wsi)
return wsi->http.ah->http_response;
}
#endif
#if defined(LWS_PLAT_OPTEE)
char *
strrchr(const char *s, int c)
@ -638,6 +645,7 @@ strrchr(const char *s, int c)
#define atoll atoi
#endif
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
int
lws_client_interpret_server_handshake(struct lws *wsi)
{
@ -663,9 +671,15 @@ lws_client_interpret_server_handshake(struct lws *wsi)
} else
#endif
{
#if defined(LWS_ROLE_H1)
{
lwsl_debug("%s: %p: transitioning to h1 client\n", __func__, wsi);
lws_role_transition(wsi, LWSIFR_CLIENT,
LRS_ESTABLISHED, &role_ops_h1);
}
#else
return -1;
#endif
}
wsi->http.ah = ah;
@ -826,7 +840,15 @@ lws_client_interpret_server_handshake(struct lws *wsi)
/* go back to "trying to connect" state */
lws_role_transition(ww, LWSIFR_CLIENT,
LRS_UNCONNECTED,
#if defined(LWS_ROLE_H1)
&role_ops_h1);
#else
#if defined (LWS_ROLE_H2)
&role_ops_h2);
#else
&role_ops_raw);
#endif
#endif
ww->user_space = NULL;
} lws_end_foreach_dll_safe(d, d1);
lws_vhost_unlock(wsi->vhost);
@ -948,7 +970,7 @@ bail2:
return 1;
}
#endif
char *
lws_generate_client_handshake(struct lws *wsi, char *pkt)
@ -1045,6 +1067,8 @@ lws_generate_client_handshake(struct lws *wsi, char *pkt)
return p;
}
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
LWS_VISIBLE int
lws_http_client_read(struct lws *wsi, char **buf, int *len)
{
@ -1195,3 +1219,5 @@ completed:
return 0;
}
#endif

View file

@ -200,7 +200,7 @@ lws_add_http_header_status(struct lws *wsi, unsigned int _code,
int n;
#ifdef LWS_WITH_ACCESS_LOG
wsi->access_log.response = code;
wsi->http.access_log.response = code;
#endif
#ifdef LWS_WITH_HTTP2

View file

@ -182,6 +182,16 @@ struct lws_vhost_role_http {
unsigned int http_proxy_port;
};
#ifdef LWS_WITH_ACCESS_LOG
struct lws_access_log {
char *header_log;
char *user_agent;
char *referrer;
unsigned long sent;
int response;
};
#endif
struct _lws_http_mode_related {
struct lws *new_wsi_list;
@ -200,6 +210,13 @@ struct _lws_http_mode_related {
char multipart_content_type[64];
#endif
#ifdef LWS_WITH_ACCESS_LOG
struct lws_access_log access_log;
#endif
#ifdef LWS_WITH_CGI
struct lws_cgi *cgi; /* wsi being cgi master have one of these */
#endif
enum http_version request_version;
enum http_connection_type connection_type;
lws_filepos_t tx_content_length;
@ -230,15 +247,11 @@ enum lws_parse_urldecode_results {
LPUR_EXCESSIVE,
};
struct lws_rewrite;
int
lws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len);
#ifdef LWS_WITH_ACCESS_LOG
struct lws_access_log {
char *header_log;
char *user_agent;
char *referrer;
unsigned long sent;
int response;
};
#endif
void
_lws_header_table_reset(struct allocated_headers *ah);
LWS_EXTERN int
_lws_destroy_ah(struct lws_context_per_thread *pt, struct allocated_headers *ah);

View file

@ -61,8 +61,8 @@ lws_prepare_access_log_info(struct lws *wsi, char *uri_ptr, int meth)
if (wsi->access_log_pending)
lws_access_log(wsi);
wsi->access_log.header_log = lws_malloc(l, "access log");
if (wsi->access_log.header_log) {
wsi->http.access_log.header_log = lws_malloc(l, "access log");
if (wsi->http.access_log.header_log) {
tmp = localtime(&t);
if (tmp)
@ -81,42 +81,42 @@ lws_prepare_access_log_info(struct lws *wsi, char *uri_ptr, int meth)
if (!me)
me = "(null)";
lws_snprintf(wsi->access_log.header_log, l,
lws_snprintf(wsi->http.access_log.header_log, l,
"%s - - [%s] \"%s %s %s\"",
pa, da, me, uri_ptr,
hver[wsi->http.request_version]);
l = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_USER_AGENT);
if (l) {
wsi->access_log.user_agent = lws_malloc(l + 2, "access log");
if (!wsi->access_log.user_agent) {
wsi->http.access_log.user_agent = lws_malloc(l + 2, "access log");
if (!wsi->http.access_log.user_agent) {
lwsl_err("OOM getting user agent\n");
lws_free_set_NULL(wsi->access_log.header_log);
lws_free_set_NULL(wsi->http.access_log.header_log);
return;
}
lws_hdr_copy(wsi, wsi->access_log.user_agent,
lws_hdr_copy(wsi, wsi->http.access_log.user_agent,
l + 1, WSI_TOKEN_HTTP_USER_AGENT);
for (m = 0; m < l; m++)
if (wsi->access_log.user_agent[m] == '\"')
wsi->access_log.user_agent[m] = '\'';
if (wsi->http.access_log.user_agent[m] == '\"')
wsi->http.access_log.user_agent[m] = '\'';
}
l = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_REFERER);
if (l) {
wsi->access_log.referrer = lws_malloc(l + 2, "referrer");
if (!wsi->access_log.referrer) {
wsi->http.access_log.referrer = lws_malloc(l + 2, "referrer");
if (!wsi->http.access_log.referrer) {
lwsl_err("OOM getting user agent\n");
lws_free_set_NULL(wsi->access_log.user_agent);
lws_free_set_NULL(wsi->access_log.header_log);
lws_free_set_NULL(wsi->http.access_log.user_agent);
lws_free_set_NULL(wsi->http.access_log.header_log);
return;
}
lws_hdr_copy(wsi, wsi->access_log.referrer,
lws_hdr_copy(wsi, wsi->http.access_log.referrer,
l + 1, WSI_TOKEN_HTTP_REFERER);
for (m = 0; m < l; m++)
if (wsi->access_log.referrer[m] == '\"')
wsi->access_log.referrer[m] = '\'';
if (wsi->http.access_log.referrer[m] == '\"')
wsi->http.access_log.referrer[m] = '\'';
}
wsi->access_log_pending = 1;
}
@ -126,8 +126,8 @@ lws_prepare_access_log_info(struct lws *wsi, char *uri_ptr, int meth)
int
lws_access_log(struct lws *wsi)
{
char *p = wsi->access_log.user_agent, ass[512],
*p1 = wsi->access_log.referrer;
char *p = wsi->http.access_log.user_agent, ass[512],
*p1 = wsi->http.access_log.referrer;
int l;
if (!wsi->vhost)
@ -139,7 +139,7 @@ lws_access_log(struct lws *wsi)
if (!wsi->access_log_pending)
return 0;
if (!wsi->access_log.header_log)
if (!wsi->http.access_log.header_log)
return 0;
if (!p)
@ -154,8 +154,8 @@ lws_access_log(struct lws *wsi)
* maintaining the structure of the log text
*/
l = lws_snprintf(ass, sizeof(ass) - 7, "%s %d %lu \"%s",
wsi->access_log.header_log,
wsi->access_log.response, wsi->access_log.sent, p1);
wsi->http.access_log.header_log,
wsi->http.access_log.response, wsi->http.access_log.sent, p1);
if (strlen(p) > sizeof(ass) - 6 - l)
p[sizeof(ass) - 6 - l] = '\0';
l += lws_snprintf(ass + l, sizeof(ass) - 1 - l, "\" \"%s\"\n", p);
@ -163,17 +163,17 @@ lws_access_log(struct lws *wsi)
if (write(wsi->vhost->log_fd, ass, l) != l)
lwsl_err("Failed to write log\n");
if (wsi->access_log.header_log) {
lws_free(wsi->access_log.header_log);
wsi->access_log.header_log = NULL;
if (wsi->http.access_log.header_log) {
lws_free(wsi->http.access_log.header_log);
wsi->http.access_log.header_log = NULL;
}
if (wsi->access_log.user_agent) {
lws_free(wsi->access_log.user_agent);
wsi->access_log.user_agent = NULL;
if (wsi->http.access_log.user_agent) {
lws_free(wsi->http.access_log.user_agent);
wsi->http.access_log.user_agent = NULL;
}
if (wsi->access_log.referrer) {
lws_free(wsi->access_log.referrer);
wsi->access_log.referrer = NULL;
if (wsi->http.access_log.referrer) {
lws_free(wsi->http.access_log.referrer);
wsi->http.access_log.referrer = NULL;
}
wsi->access_log_pending = 0;

View file

@ -586,20 +586,6 @@ lws_hdr_simple_create(struct lws *wsi, enum lws_token_indexes h, const char *s)
return 0;
}
signed char char_to_hex(const char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return -1;
}
static int LWS_WARN_UNUSED_RESULT
issue_char(struct lws *wsi, unsigned char c)
{

View file

@ -1749,7 +1749,7 @@ lws_http_transaction_completed(struct lws *wsi)
wsi->http.tx_content_remain = 0;
wsi->hdr_parsing_completed = 0;
#ifdef LWS_WITH_ACCESS_LOG
wsi->access_log.sent = 0;
wsi->http.access_log.sent = 0;
#endif
if (wsi->vhost->keepalive_timeout)
@ -1905,12 +1905,15 @@ lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
}
#endif
} else
#if defined(LWS_ROLE_H1)
if (type & LWS_ADOPT_HTTP) {/* he will transition later */
new_wsi->protocol =
&vh->protocols[vh->default_protocol_index];
new_wsi->role_ops = &role_ops_h1;
}
else { /* this is the only time he will transition */
else
#endif
{ /* this is the only time he will transition */
lws_bind_protocol(new_wsi,
&vh->protocols[vh->raw_protocol_index]);
lws_role_transition(new_wsi, 0, LRS_ESTABLISHED,
@ -1964,18 +1967,22 @@ lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
else
lws_role_transition(new_wsi, 0, LRS_UNCONNECTED,
&role_ops_raw_skt);
} else
}
#if defined(LWS_ROLE_H1)
else
lws_role_transition(new_wsi, LWSIFR_SERVER,
LRS_HEADERS, &role_ops_h1);
#endif
} else {
/* SSL */
if (!(type & LWS_ADOPT_HTTP))
lws_role_transition(new_wsi, 0, LRS_SSL_INIT,
&role_ops_raw_skt);
#if defined(LWS_ROLE_H1)
else
lws_role_transition(new_wsi, LWSIFR_SERVER,
LRS_SSL_INIT, &role_ops_h1);
#endif
ssl = 1;
}

View file

@ -155,3 +155,10 @@ LWS_EXTERN int
lws_ext_cb_all_exts(struct lws_context *context, struct lws *wsi, int reason,
void *arg, int len);
#endif
int
handshake_0405(struct lws_context *context, struct lws *wsi);
int
lws_process_ws_upgrade(struct lws *wsi);
int
lws_server_init_wsi_for_ws(struct lws *wsi);

View file

@ -96,7 +96,7 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
* A cgi master's wire protocol remains h1 or h2. He is just getting
* his data from his child cgis.
*/
if (wsi->cgi) {
if (wsi->http.cgi) {
/* also one shot */
if (pollfd)
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
@ -236,6 +236,7 @@ __lws_service_timeout_check(struct lws *wsi, time_t sec)
/* no need to log normal idle keepalive timeout */
if (wsi->pending_timeout != PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE)
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
lwsl_info("wsi %p: TIMEDOUT WAITING on %d "
"(did hdr %d, ah %p, wl %d, pfd "
"events %d) %llu vs %llu\n",
@ -245,8 +246,12 @@ __lws_service_timeout_check(struct lws *wsi, time_t sec)
(unsigned long long)sec,
(unsigned long long)wsi->pending_timeout_limit);
#if defined(LWS_WITH_CGI)
if (wsi->cgi)
lwsl_notice("CGI timeout: %s\n", wsi->cgi->summary);
if (wsi->http.cgi)
lwsl_notice("CGI timeout: %s\n", wsi->http.cgi->summary);
#endif
#else
lwsl_info("wsi %p: TIMEDOUT WAITING on %d ", (void *)wsi,
wsi->pending_timeout);
#endif
/*
@ -509,14 +514,16 @@ lws_service_periodic_checks(struct lws_context *context,
{
struct lws_context_per_thread *pt = &context->pt[tsi];
lws_sockfd_type our_fd = 0, tmp_fd;
struct allocated_headers *ah;
struct lws *wsi;
int timed_out = 0;
time_t now;
#if defined(LWS_WITH_TLS)
int n = 0;
#endif
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
struct allocated_headers *ah;
int m;
#endif
if (!context->protocol_init_done)
if (lws_protocol_init(context))
@ -608,6 +615,7 @@ lws_service_periodic_checks(struct lws_context *context,
}
} lws_end_foreach_dll_safe(d, d1);
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
/*
* Phase 2: double-check active ah timeouts independent of wsi
* timeout status
@ -688,7 +696,7 @@ lws_service_periodic_checks(struct lws_context *context,
ah = pt->http.ah_list;
}
#endif
lws_pt_unlock(pt);
#if 0

View file

@ -101,8 +101,11 @@ lws_ssl_client_bio_create(struct lws *wsi)
int n;
#endif
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
_WSI_TOKEN_CLIENT_HOST) <= 0) {
_WSI_TOKEN_CLIENT_HOST) <= 0)
#endif
{
lwsl_err("%s: Unable to get hostname\n", __func__);
return -1;
@ -208,10 +211,11 @@ lws_ssl_client_bio_create(struct lws *wsi)
defined(LWS_HAVE_SSL_get0_alpn_selected)
if (wsi->vhost->alpn)
alpn_comma = wsi->vhost->alpn;
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
_WSI_TOKEN_CLIENT_ALPN) > 0)
alpn_comma = hostname;
#endif
lwsl_info("client conn using alpn list '%s'\n", alpn_comma);

View file

@ -63,6 +63,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_WS 1 requirements)
require_lws_config(LWS_WITHOUT_CLIENT 0 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)

View file

@ -64,6 +64,7 @@ ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_CLIENT 0 requirements)
require_lws_config(LWS_OPENSSL_SUPPORT 1 requirements)

View file

@ -63,6 +63,7 @@ ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_CLIENT 0 requirements)
if (requirements)

View file

@ -64,6 +64,7 @@ ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_CLIENT 0 requirements)
if (requirements)

View file

@ -63,6 +63,7 @@ ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_CLIENT 0 requirements)
if (requirements)

View file

@ -64,6 +64,7 @@ ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_CLIENT 0 requirements)
if (requirements)

View file

@ -62,6 +62,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
if (requirements)

View file

@ -63,6 +63,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
if (requirements)

View file

@ -62,6 +62,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
if (requirements)

View file

@ -62,6 +62,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
if (requirements)

View file

@ -62,6 +62,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
if (requirements)

View file

@ -62,6 +62,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITH_LIBUV 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)

View file

@ -63,6 +63,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITH_LIBUV 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)

View file

@ -62,6 +62,7 @@ MACRO(require_lws_config reqconfig _val result)
endif()
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
if (requirements)

View file

@ -76,6 +76,7 @@ ENDMACRO()
set(requirements 1)
require_pthreads(requirements)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
if (requirements)

View file

@ -76,6 +76,7 @@ ENDMACRO()
set(requirements 1)
require_pthreads(requirements)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
if (requirements)

View file

@ -63,6 +63,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
if (requirements)

View file

@ -63,6 +63,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
require_lws_config(LWS_OPENSSL_SUPPORT 1 requirements)

View file

@ -64,6 +64,7 @@ ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
if (requirements)

View file

@ -63,6 +63,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_WS 1 requirements)
require_lws_config(LWS_WITHOUT_CLIENT 0 requirements)
require_lws_config(LWS_WITHOUT_EXTENSIONS 0 requirements)

View file

@ -63,6 +63,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_WS 1 requirements)
require_lws_config(LWS_WITHOUT_CLIENT 0 requirements)
#require_lws_config(LWS_WITHOUT_EXTENSIONS 0 requirements)

View file

@ -63,6 +63,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_WS 1 requirements)
require_lws_config(LWS_WITHOUT_CLIENT 0 requirements)
if (requirements)

View file

@ -75,6 +75,7 @@ ENDMACRO()
set(requirements 1)
require_pthreads(requirements)
require_lws_config(LWS_ROLE_WS 1 requirements)
require_lws_config(LWS_WITHOUT_CLIENT 0 requirements)
if (requirements)

View file

@ -62,6 +62,7 @@ MACRO(require_lws_config reqconfig _val result)
endif()
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_WS 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
if (requirements)

View file

@ -63,6 +63,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_WS 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
require_lws_config(LWS_WITHOUT_EXTENSIONS 0 requirements)

View file

@ -63,6 +63,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_WS 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
#require_lws_config(LWS_WITHOUT_EXTENSIONS 0 requirements)

View file

@ -63,6 +63,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_WS 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
require_lws_config(LWS_WITHOUT_EXTENSIONS 0 requirements)

View file

@ -63,6 +63,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_WS 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
if (requirements)

View file

@ -76,6 +76,7 @@ ENDMACRO()
set(requirements 1)
require_pthreads(requirements)
require_lws_config(LWS_ROLE_WS 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
if (requirements)

View file

@ -63,6 +63,7 @@ MACRO(require_lws_config reqconfig _val result)
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_WS 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
if (requirements)