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

adoption: make union for socket and file fds

This lets lws support adopting raw file FDs and raw socket fds.

A test plugin creates a FIFO and prints data sent on it, using
the lws event loop.
This commit is contained in:
Andy Green 2017-02-27 12:55:56 +08:00
parent 8bb3dffc86
commit be8d791b5e
20 changed files with 499 additions and 150 deletions

View file

@ -1340,6 +1340,10 @@ if (NOT LWS_WITHOUT_TESTAPPS)
"plugins/protocol_post_demo.c" "" "")
create_plugin(protocol_lws_table_dirlisting
"plugins/generic-table/protocol_table_dirlisting.c" "" "")
if (NOT WIN32)
create_plugin(protocol_lws_raw_test
"plugins/protocol_lws_raw_test.c" "" "")
endif()
if (LWS_WITH_SERVER_STATUS)
create_plugin(protocol_lws_server_status

View file

@ -169,34 +169,34 @@ lws_client_connect_2(struct lws *wsi)
freeaddrinfo(result);
}
if (!lws_socket_is_valid(wsi->sock)) {
if (!lws_socket_is_valid(wsi->desc.sockfd)) {
#ifdef LWS_USE_IPV6
if (LWS_IPV6_ENABLED(wsi->vhost))
wsi->sock = socket(AF_INET6, SOCK_STREAM, 0);
wsi->desc.sockfd = socket(AF_INET6, SOCK_STREAM, 0);
else
#endif
wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
wsi->desc.sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (!lws_socket_is_valid(wsi->sock)) {
if (!lws_socket_is_valid(wsi->desc.sockfd)) {
lwsl_warn("Unable to open socket\n");
cce = "unable to open socket";
goto oom4;
}
if (lws_plat_set_socket_options(wsi->vhost, wsi->sock)) {
if (lws_plat_set_socket_options(wsi->vhost, wsi->desc.sockfd)) {
lwsl_err("Failed to set wsi socket options\n");
compatible_close(wsi->sock);
compatible_close(wsi->desc.sockfd);
cce = "set socket opts failed";
goto oom4;
}
wsi->mode = LWSCM_WSCL_WAITING_CONNECT;
lws_libev_accept(wsi, wsi->sock);
lws_libuv_accept(wsi, wsi->sock);
lws_libev_accept(wsi, wsi->desc);
lws_libuv_accept(wsi, wsi->desc);
if (insert_wsi_socket_into_fds(context, wsi)) {
compatible_close(wsi->sock);
compatible_close(wsi->desc.sockfd);
cce = "insert wsi failed";
goto oom4;
}
@ -217,7 +217,7 @@ lws_client_connect_2(struct lws *wsi)
lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
AWAITING_TIMEOUT);
n = lws_socket_bind(wsi->vhost, wsi->sock, 0, wsi->vhost->iface);
n = lws_socket_bind(wsi->vhost, wsi->desc.sockfd, 0, wsi->vhost->iface);
if (n < 0) {
cce = "unable to bind socket";
goto failed;
@ -235,7 +235,7 @@ lws_client_connect_2(struct lws *wsi)
n = sizeof(struct sockaddr);
}
if (connect(wsi->sock, v, n) == -1 || LWS_ERRNO == LWS_EISCONN) {
if (connect(wsi->desc.sockfd, v, n) == -1 || LWS_ERRNO == LWS_EISCONN) {
if (LWS_ERRNO == LWS_EALREADY ||
LWS_ERRNO == LWS_EINPROGRESS ||
LWS_ERRNO == LWS_EWOULDBLOCK
@ -287,7 +287,7 @@ lws_client_connect_2(struct lws *wsi)
goto failed;
wsi->c_port = wsi->vhost->http_proxy_port;
n = send(wsi->sock, (char *)pt->serv_buf, plen,
n = send(wsi->desc.sockfd, (char *)pt->serv_buf, plen,
MSG_NOSIGNAL);
if (n < 0) {
lwsl_debug("ERROR writing to proxy socket\n");
@ -317,7 +317,7 @@ lws_client_connect_2(struct lws *wsi)
AWAITING_TIMEOUT);
wsi->mode = LWSCM_WSCL_ISSUE_HANDSHAKE;
pfd.fd = wsi->sock;
pfd.fd = wsi->desc.sockfd;
pfd.events = LWS_POLLIN;
pfd.revents = LWS_POLLIN;
@ -411,10 +411,10 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
/* close the connection by hand */
compatible_close(wsi->sock);
compatible_close(wsi->desc.sockfd);
remove_wsi_socket_from_fds(wsi);
wsi->sock = LWS_SOCK_INVALID;
wsi->desc.sockfd = LWS_SOCK_INVALID;
wsi->state = LWSS_CLIENT_UNCONNECTED;
wsi->protocol = NULL;
wsi->pending_timeout = NO_PENDING_TIMEOUT;
@ -581,7 +581,7 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
wsi->context = i->context;
/* assert the mode and union status (hdr) clearly */
lws_union_transition(wsi, LWSCM_HTTP_CLIENT);
wsi->sock = LWS_SOCK_INVALID;
wsi->desc.sockfd = LWS_SOCK_INVALID;
/* 1) fill up the wsi with stuff from the connect_info as far as it
* can go. It's because not only is our connection async, we might

View file

@ -114,7 +114,7 @@ lws_client_socket_service(struct lws_context *context, struct lws *wsi,
return 0;
}
n = recv(wsi->sock, sb, context->pt_serv_buf_size, 0);
n = recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
if (n < 0) {
if (LWS_ERRNO == LWS_EAGAIN) {
lwsl_debug("Proxy read returned EAGAIN... retrying\n");
@ -952,7 +952,7 @@ check_accept:
wsi->u.ws.rx_ubuf_alloc = n;
lwsl_info("Allocating client RX buffer %d\n", n);
if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n,
if (setsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&n,
sizeof n)) {
lwsl_warn("Failed to set SNDBUF to %d", n);
cce = "HS: SO_SNDBUF failed";

View file

@ -97,7 +97,7 @@ lws_ev_initloop(struct lws_context *context, struct ev_loop *loop, int tsi)
while (vh) {
if (vh->lserv_wsi) {
vh->lserv_wsi->w_read.context = context;
ev_io_init(w_accept, lws_accept_cb, vh->lserv_wsi->sock,
ev_io_init(w_accept, lws_accept_cb, vh->lserv_wsi->desc.sockfd,
EV_READ);
}
vh = vh->vhost_next;
@ -160,19 +160,25 @@ lws_libev_destroyloop(struct lws_context *context, int tsi)
}
LWS_VISIBLE void
lws_libev_accept(struct lws *new_wsi, int accept_fd)
lws_libev_accept(struct lws *new_wsi, lws_sock_file_fd_type desc)
{
struct lws_context *context = lws_get_context(new_wsi);
struct ev_io *r = &new_wsi->w_read.ev_watcher;
struct ev_io *w = &new_wsi->w_write.ev_watcher;
int fd;
if (!LWS_LIBEV_ENABLED(context))
return;
if (wsi->mode == LWSCM_RAW_FILEDESC)
fd = desc.filefd;
else
fd = desc.sockfd;
new_wsi->w_read.context = context;
new_wsi->w_write.context = context;
ev_io_init(r, lws_accept_cb, accept_fd, EV_READ);
ev_io_init(w, lws_accept_cb, accept_fd, EV_WRITE);
ev_io_init(r, lws_accept_cb, fd, EV_READ);
ev_io_init(w, lws_accept_cb, fd, EV_WRITE);
}
LWS_VISIBLE void

View file

@ -164,10 +164,10 @@ lws_uv_initvhost(struct lws_vhost* vh, struct lws* wsi)
wsi->w_read.context = vh->context;
n = uv_poll_init_socket(pt->io_loop_uv,
&wsi->w_read.uv_watcher, wsi->sock);
&wsi->w_read.uv_watcher, wsi->desc.sockfd);
if (n) {
lwsl_err("uv_poll_init failed %d, sockfd=%p\n",
n, (void *)(long)wsi->sock);
n, (void *)(long)wsi->desc.sockfd);
return -1;
}
@ -318,7 +318,7 @@ lws_libuv_destroyloop(struct lws_context *context, int tsi)
}
void
lws_libuv_accept(struct lws *wsi, lws_sockfd_type accept_fd)
lws_libuv_accept(struct lws *wsi, lws_sock_file_fd_type desc)
{
struct lws_context *context = lws_get_context(wsi);
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
@ -329,8 +329,12 @@ lws_libuv_accept(struct lws *wsi, lws_sockfd_type accept_fd)
lwsl_debug("%s: new wsi %p\n", __func__, wsi);
wsi->w_read.context = context;
uv_poll_init_socket(pt->io_loop_uv, &wsi->w_read.uv_watcher, accept_fd);
if (wsi->mode == LWSCM_RAW_FILEDESC)
uv_poll_init(pt->io_loop_uv, &wsi->w_read.uv_watcher,
desc.filefd);
else
uv_poll_init_socket(pt->io_loop_uv, &wsi->w_read.uv_watcher,
desc.sockfd);
}
void

View file

@ -154,6 +154,15 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
if (!wsi)
return;
if (wsi->mode == LWSCM_RAW_FILEDESC) {
remove_wsi_socket_from_fds(wsi);
wsi->protocol->callback(wsi,
LWS_CALLBACK_RAW_CLOSE_FILE, wsi->user_space, NULL, 0);
lws_free_wsi(wsi);
return;
}
lws_access_log(wsi);
#if defined(LWS_WITH_ESP8266)
if (wsi->premature_rx)
@ -222,7 +231,7 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
#endif
if (wsi->mode == LWSCM_RAW) {
wsi->vhost->protocols->callback(wsi,
wsi->protocol->callback(wsi,
LWS_CALLBACK_RAW_CLOSE, wsi->user_space, NULL, 0);
wsi->socket_is_permanently_unusable = 1;
goto just_kill_connection;
@ -438,17 +447,17 @@ just_kill_connection:
#ifdef LWS_OPENSSL_SUPPORT
if (lws_is_ssl(wsi) && wsi->ssl)
{
lwsl_info("%s: shutting down SSL connection: %p (ssl %p, sock %d, state %d)\n", __func__, wsi, wsi->ssl, (int)(long)wsi->sock, wsi->state);
lwsl_info("%s: shutting down SSL connection: %p (ssl %p, sock %d, state %d)\n", __func__, wsi, wsi->ssl, (int)(long)wsi->desc.sockfd, wsi->state);
n = SSL_shutdown(wsi->ssl);
if (n == 0) /* Complete bidirectional SSL shutdown */
n = SSL_shutdown(wsi->ssl);
n = shutdown(wsi->sock, SHUT_WR);
n = shutdown(wsi->desc.sockfd, SHUT_WR);
}
else
#endif
{
lwsl_info("%s: shutting down connection: %p (sock %d, state %d)\n", __func__, wsi, (int)(long)wsi->sock, wsi->state);
n = shutdown(wsi->sock, SHUT_WR);
lwsl_info("%s: shutting down connection: %p (sock %d, state %d)\n", __func__, wsi, (int)(long)wsi->desc.sockfd, wsi->state);
n = shutdown(wsi->desc.sockfd, SHUT_WR);
}
if (n)
lwsl_debug("closing: shutdown (state %d) ret %d\n", wsi->state, LWS_ERRNO);
@ -470,7 +479,7 @@ just_kill_connection:
#endif
lwsl_info("%s: real just_kill_connection: %p (sockfd %d)\n", __func__,
wsi, wsi->sock);
wsi, wsi->desc.sockfd);
#ifdef LWS_WITH_HTTP_PROXY
if (wsi->rw) {
@ -487,11 +496,11 @@ just_kill_connection:
lws_remove_from_timeout_list(wsi);
/* checking return redundant since we anyway close */
if (wsi->sock != LWS_SOCK_INVALID)
if (wsi->desc.sockfd != LWS_SOCK_INVALID)
remove_wsi_socket_from_fds(wsi);
#if defined(LWS_WITH_ESP8266)
espconn_disconnect(wsi->sock);
espconn_disconnect(wsi->desc.sockfd);
#endif
wsi->state = LWSS_DEAD_SOCKET;
@ -606,18 +615,18 @@ lws_close_free_wsi_final(struct lws *wsi)
{
int n;
if (!lws_ssl_close(wsi) && lws_socket_is_valid(wsi->sock)) {
if (!lws_ssl_close(wsi) && lws_socket_is_valid(wsi->desc.sockfd)) {
#if LWS_POSIX
//lwsl_err("*** closing sockfd %d\n", wsi->sock);
n = compatible_close(wsi->sock);
//lwsl_err("*** closing sockfd %d\n", wsi->desc.sockfd);
n = compatible_close(wsi->desc.sockfd);
if (n)
lwsl_debug("closing: close ret %d\n", LWS_ERRNO);
#else
compatible_close(wsi->sock);
compatible_close(wsi->desc.sockfd);
(void)n;
#endif
wsi->sock = LWS_SOCK_INVALID;
wsi->desc.sockfd = LWS_SOCK_INVALID;
}
/* outermost destroy notification for wsi (user_space still intact) */
@ -786,7 +795,7 @@ lws_get_peer_simple(struct lws *wsi, char *name, int namelen)
}
olen = len;
if (getpeername(wsi->sock, p, &len) < 0 || len > olen) {
if (getpeername(wsi->desc.sockfd, p, &len) < 0 || len > olen) {
lwsl_warn("getpeername: %s\n", strerror(LWS_ERRNO));
return NULL;
}
@ -974,7 +983,7 @@ lws_now_secs(void)
LWS_VISIBLE int
lws_get_socket_fd(struct lws *wsi)
{
return wsi->sock;
return wsi->desc.sockfd;
}
#endif
@ -1976,7 +1985,7 @@ lws_create_basic_wsi(struct lws_context *context, int tsi)
new_wsi->protocol = context->vhost_list->protocols;
new_wsi->user_space = NULL;
new_wsi->ietf_spec_revision = 0;
new_wsi->sock = LWS_SOCK_INVALID;
new_wsi->desc.sockfd = LWS_SOCK_INVALID;
context->count_wsi_allocated++;
return new_wsi;
@ -2024,7 +2033,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
// 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)];
cgi->stdwsi[n]->desc.sockfd = cgi->pipe_fds[n][!!(n == 0)];
if (fcntl(cgi->pipe_fds[n][!!(n == 0)], F_SETFL, O_NONBLOCK) < 0) {
lwsl_err("%s: setting NONBLOCK failed\n", __func__);
goto bail2;
@ -2032,7 +2041,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
}
for (n = 0; n < 3; n++) {
lws_libuv_accept(cgi->stdwsi[n], cgi->stdwsi[n]->sock);
lws_libuv_accept(cgi->stdwsi[n], cgi->stdwsi[n]->desc);
if (insert_wsi_socket_into_fds(wsi->context, cgi->stdwsi[n]))
goto bail3;
cgi->stdwsi[n]->parent = wsi;
@ -2045,8 +2054,9 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
lws_change_pollfd(cgi->stdwsi[LWS_STDERR], LWS_POLLOUT, LWS_POLLIN);
lwsl_debug("%s: fds in %d, out %d, err %d\n", __func__,
cgi->stdwsi[LWS_STDIN]->sock, cgi->stdwsi[LWS_STDOUT]->sock,
cgi->stdwsi[LWS_STDERR]->sock);
cgi->stdwsi[LWS_STDIN]->desc.sockfd,
cgi->stdwsi[LWS_STDOUT]->desc.sockfd,
cgi->stdwsi[LWS_STDERR]->desc.sockfd);
lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, timeout_secs);

View file

@ -1059,12 +1059,20 @@ enum lws_callback_reasons {
LWS_CALLBACK_RAW_WRITEABLE = 61,
/**< RAW mode connection may be written */
LWS_CALLBACK_RAW_ADOPT = 62,
/**< RAW mode connection was adopted (equivalent to 'created') */
/**< RAW mode connection was adopted (equivalent to 'wsi created') */
LWS_CALLBACK_RAW_ADOPT_FILE = 63,
/**< RAW mode file was adopted (equivalent to 'wsi created') */
LWS_CALLBACK_RAW_RX_FILE = 64,
/**< RAW mode file has something to read */
LWS_CALLBACK_RAW_WRITEABLE_FILE = 65,
/**< RAW mode file is writeable */
LWS_CALLBACK_RAW_CLOSE_FILE = 66,
/**< RAW mode wsi that adopted a file is closing */
/****** add new things just above ---^ ******/
LWS_CALLBACK_USER = 1000,
/**< user code can use any including / above without fear of clashes */
/**< user code can use any including above without fear of clashes */
};
@ -3703,23 +3711,37 @@ lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd);
*/
LWS_VISIBLE LWS_EXTERN struct lws *
lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd);
typedef enum {
LWS_ADOPT_HTTP = 1, /* absent implies RAW */
LWS_ADOPT_SOCKET = 2, /* absent implies file descriptor */
LWS_ADOPT_ALLOW_SSL = 4 /* if set requires LWS_ADOPT_SOCKET */
} lws_adoption_type;
typedef union {
lws_sockfd_type sockfd;
lws_filefd_type filefd;
} lws_sock_file_fd_type;
/*
* lws_adopt_socket_vhost2() - adopt foreign socket as if listen socket accepted it
* for vhost, allow control over defeat SSL and raw transport mode
* lws_adopt_descriptor_vhost() - adopt foreign socket or file descriptor
* if socket descriptor, should already have been accepted from listen socket
*
* \param vhost: lws vhost
* \param accept_fd: fd of already-accepted socket to adopt
* \param allow_ssl: 0 = no SSL even if vhost supports, 1 = SSL if vhost supports
* \param raw: 0 = http[s]/wss[s], 1 = raw mode semantics
* \param type: OR-ed combinations of lws_adoption_type flags
* \param fd: union with either .sockfd or .filefd set
* \param vh_prot_name: NULL or vh protocol name to bind raw connection to
*
* Either returns new wsi bound to accept_fd, or closes accept_fd and
* returns NULL, having cleaned up any new wsi pieces.
*
* LWS adopts the socket in http serving mode, it's ready to accept an upgrade
* to ws or just serve http.
* If LWS_ADOPT_SOCKET is set, LWS adopts the socket in http serving mode, it's
* ready to accept an upgrade to ws or just serve http.
*/
LWS_VISIBLE struct lws *
lws_adopt_socket_vhost2(struct lws_vhost *vh, lws_sockfd_type accept_fd,
int allow_ssl, int raw);
lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
lws_sock_file_fd_type fd, const char *vh_prot_name);
/**
* lws_adopt_socket_readbuf() - adopt foreign socket and first rx as if listen socket accepted it
@ -4254,7 +4276,9 @@ struct lws_fop_fd {
};
#if defined(WIN32) || defined(_WIN32)
/* ... */
#if !defined(ssize_t)
typedef SSIZE_T ssize_t;
#endif
/* !!! >:-[ */
typedef unsigned __int32 uint32_t;
typedef unsigned __int8 uint8_t;

View file

@ -30,9 +30,9 @@ lws_send_pipe_choked(struct lws *wsi)
return 1;
FD_ZERO(&writefds);
FD_SET(wsi->sock, &writefds);
FD_SET(wsi->desc.sockfd, &writefds);
if (select(wsi->sock + 1, NULL, &writefds, NULL, &tv) < 1)
if (select(wsi->desc.sockfd + 1, NULL, &writefds, NULL, &tv) < 1)
return 1;
return 0;

View file

@ -72,7 +72,7 @@ lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, int len)
//lwsl_notice("%s: wsi %p: len %d\n", __func__, wsi, len);
wsi->pending_send_completion++;
espconn_send(wsi->sock, buf, len);
espconn_send(wsi->desc.sockfd, buf, len);
return len;
}
@ -247,7 +247,7 @@ esp8266_create_tcp_listen_socket(struct lws_vhost *vh)
const char *
lws_plat_get_peer_simple(struct lws *wsi, char *name, int namelen)
{
unsigned char *p = wsi->sock->proto.tcp->remote_ip;
unsigned char *p = wsi->desc.sockfd->proto.tcp->remote_ip;
lws_snprintf(name, namelen, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
@ -493,7 +493,7 @@ esp8266_tcp_stream_accept(lws_sockfd_type fd, struct lws *wsi)
fd->reverse = wsi;
for (n = 0; n < wsi->context->max_fds ; n++)
if (wsi->context->connpool[n] == wsi->sock)
if (wsi->context->connpool[n] == wsi->desc.sockfd)
wsi->position_in_fds_table = n;
}
@ -555,7 +555,7 @@ lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
context->connpool[wsi->position_in_fds_table + context->max_fds] = (lws_sockfd_type)wsi;
wsi->sock->reverse = wsi;
wsi->desc.sockfd->reverse = wsi;
pt->fds_count++;
}
@ -567,13 +567,13 @@ lws_plat_delete_socket_from_fds(struct lws_context *context,
int n;
for (n = 0; n < wsi->context->max_fds; n++)
if (wsi->context->connpool[n] == wsi->sock) {
if (wsi->context->connpool[n] == wsi->desc.sockfd) {
wsi->context->connpool[n] = NULL;
wsi->context->connpool[n + wsi->context->max_fds] = NULL;
lwsl_notice(" freed connpool %d\n", n);
}
wsi->sock->reverse = NULL;
wsi->desc.sockfd->reverse = NULL;
pt->fds_count--;
}
@ -596,17 +596,17 @@ lws_plat_change_pollfd(struct lws_context *context,
lwsl_notice("replaying buffered rx: wsi %p\n", wsi);
p = wsi->premature_rx;
wsi->premature_rx = NULL;
esp8266_cb_rx(wsi->sock,
esp8266_cb_rx(wsi->desc.sockfd,
(char *)p + wsi->prem_rx_pos,
wsi->prem_rx_size - wsi->prem_rx_pos);
wsi->prem_rx_size = 0;
wsi->prem_rx_pos = 0;
lws_free(p);
}
if (espconn_recv_unhold(wsi->sock) < 0)
if (espconn_recv_unhold(wsi->desc.sockfd) < 0)
return -1;
} else
if (espconn_recv_hold(wsi->sock) < 0)
if (espconn_recv_hold(wsi->desc.sockfd) < 0)
return -1;
if (!(pfd->events & LWS_POLLOUT))

View file

@ -29,7 +29,7 @@ lws_send_pipe_choked(struct lws *wsi)
if (wsi->trunc_len)
return 1;
fds.fd = wsi->sock;
fds.fd = wsi->desc.sockfd;
fds.events = POLLOUT;
fds.revents = 0;

View file

@ -35,7 +35,7 @@ lws_send_pipe_choked(struct lws *wsi)
if (wsi->trunc_len)
return 1;
fds.fd = wsi->sock;
fds.fd = wsi->desc.sockfd;
fds.events = POLLOUT;
fds.revents = 0;

View file

@ -50,7 +50,7 @@ wsi_from_fd(const struct lws_context *context, lws_sockfd_type fd)
int n = 0;
for (n = 0; n < context->fd_hashtable[h].length; n++)
if (context->fd_hashtable[h].wsi[n]->sock == fd)
if (context->fd_hashtable[h].wsi[n]->desc.sockfd == fd)
return context->fd_hashtable[h].wsi[n];
return NULL;
@ -59,7 +59,7 @@ wsi_from_fd(const struct lws_context *context, lws_sockfd_type fd)
int
insert_wsi(struct lws_context *context, struct lws *wsi)
{
int h = LWS_FD_HASH(wsi->sock);
int h = LWS_FD_HASH(wsi->desc.sockfd);
if (context->fd_hashtable[h].length == (getdtablesize() - 1)) {
lwsl_err("hash table overflow\n");
@ -78,7 +78,7 @@ delete_from_fd(struct lws_context *context, lws_sockfd_type fd)
int n = 0;
for (n = 0; n < context->fd_hashtable[h].length; n++)
if (context->fd_hashtable[h].wsi[n]->sock == fd) {
if (context->fd_hashtable[h].wsi[n]->desc.sockfd == fd) {
while (n < context->fd_hashtable[h].length) {
context->fd_hashtable[h].wsi[n] =
context->fd_hashtable[h].wsi[n + 1];
@ -417,7 +417,7 @@ lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
pt->fds[pt->fds_count++].revents = 0;
pt->events[pt->fds_count] = pt->events[0];
WSAEventSelect(wsi->sock, pt->events[0],
WSAEventSelect(wsi->desc.sockfd, pt->events[0],
LWS_POLLIN | LWS_POLLHUP | FD_CONNECT);
}
@ -441,7 +441,7 @@ lws_plat_check_connection_error(struct lws *wsi)
int optVal;
int optLen = sizeof(int);
if (getsockopt(wsi->sock, SOL_SOCKET, SO_ERROR,
if (getsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_ERROR,
(char*)&optVal, &optLen) != SOCKET_ERROR && optVal &&
optVal != LWS_EALREADY && optVal != LWS_EINPROGRESS &&
optVal != LWS_EWOULDBLOCK && optVal != WSAEINVAL) {
@ -465,7 +465,7 @@ lws_plat_change_pollfd(struct lws_context *context,
if ((pfd->events & LWS_POLLOUT))
networkevents |= LWS_POLLOUT;
if (WSAEventSelect(wsi->sock,
if (WSAEventSelect(wsi->desc.sockfd,
pt->events[0],
networkevents) != SOCKET_ERROR)
return 0;

View file

@ -133,7 +133,7 @@ int lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len)
goto handle_truncated_send;
}
if (!lws_socket_is_valid(wsi->sock))
if (!lws_socket_is_valid(wsi->desc.sockfd))
lwsl_warn("** error invalid sock but expected to send\n");
/* limit sending */
@ -744,7 +744,7 @@ lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, int len)
{
int n;
n = recv(wsi->sock, (char *)buf, len, 0);
n = recv(wsi->desc.sockfd, (char *)buf, len, 0);
if (n >= 0) {
if (wsi->vhost)
wsi->vhost->conn_stats.rx += n;
@ -767,7 +767,7 @@ lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, int len)
int n = 0;
#if LWS_POSIX
n = send(wsi->sock, (char *)buf, len, MSG_NOSIGNAL);
n = send(wsi->desc.sockfd, (char *)buf, len, MSG_NOSIGNAL);
// lwsl_info("%s: sent len %d result %d", __func__, len, n);
if (n >= 0)
return n;
@ -789,7 +789,7 @@ lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, int len)
// !!!
#endif
lwsl_debug("ERROR writing len %d to skt fd %d err %d / errno %d\n", len, wsi->sock, n, LWS_ERRNO);
lwsl_debug("ERROR writing len %d to skt fd %d err %d / errno %d\n", len, wsi->desc.sockfd, n, LWS_ERRNO);
return LWS_SSL_CAPABLE_ERROR;
}
#endif

View file

@ -39,7 +39,7 @@ _lws_change_pollfd(struct lws *wsi, int _and, int _or, struct lws_pollargs *pa)
wsi->position_in_fds_table < pt->fds_count);
pfd = &pt->fds[wsi->position_in_fds_table];
pa->fd = wsi->sock;
pa->fd = wsi->desc.sockfd;
pa->prev_events = pfd->events;
pa->events = pfd->events = (pfd->events & ~_and) | _or;
@ -132,13 +132,13 @@ lws_accept_modulation(struct lws_context_per_thread *pt, int allow)
int
insert_wsi_socket_into_fds(struct lws_context *context, struct lws *wsi)
{
struct lws_pollargs pa = { wsi->sock, LWS_POLLIN, 0 };
struct lws_pollargs pa = { wsi->desc.sockfd, LWS_POLLIN, 0 };
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
int ret = 0;
lwsl_debug("%s: %p: tsi=%d, sock=%d, pos-in-fds=%d\n",
__func__, wsi, wsi->tsi, wsi->sock, pt->fds_count);
__func__, wsi, wsi->tsi, wsi->desc.sockfd, pt->fds_count);
if ((unsigned int)pt->fds_count >= context->fd_limit_per_thread) {
lwsl_err("Too many fds (%d vs %d)\n", context->max_fds,
@ -147,16 +147,16 @@ insert_wsi_socket_into_fds(struct lws_context *context, struct lws *wsi)
}
#if !defined(_WIN32) && !defined(LWS_WITH_ESP8266)
if (wsi->sock >= context->max_fds) {
if (wsi->desc.sockfd >= context->max_fds) {
lwsl_err("Socket fd %d is too high (%d)\n",
wsi->sock, context->max_fds);
wsi->desc.sockfd, context->max_fds);
return 1;
}
#endif
assert(wsi);
assert(wsi->vhost);
assert(lws_socket_is_valid(wsi->sock));
assert(lws_socket_is_valid(wsi->desc.sockfd));
if (wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_LOCK_POLL,
wsi->user_space, (void *) &pa, 1))
@ -172,7 +172,7 @@ insert_wsi_socket_into_fds(struct lws_context *context, struct lws *wsi)
// lwsl_notice("%s: %p: setting posinfds %d\n", __func__, wsi, wsi->position_in_fds_table);
pt->fds[wsi->position_in_fds_table].fd = wsi->sock;
pt->fds[wsi->position_in_fds_table].fd = wsi->desc.sockfd;
#if LWS_POSIX
pt->fds[wsi->position_in_fds_table].events = LWS_POLLIN;
#else
@ -204,7 +204,7 @@ int
remove_wsi_socket_from_fds(struct lws *wsi)
{
struct lws_context *context = wsi->context;
struct lws_pollargs pa = { wsi->sock, 0, 0 };
struct lws_pollargs pa = { wsi->desc.sockfd, 0, 0 };
#if !defined(LWS_WITH_ESP8266)
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
struct lws *end_wsi;
@ -213,8 +213,8 @@ remove_wsi_socket_from_fds(struct lws *wsi)
int m, ret = 0;
#if !defined(_WIN32) && !defined(LWS_WITH_ESP8266)
if (wsi->sock > context->max_fds) {
lwsl_err("fd %d too high (%d)\n", wsi->sock, context->max_fds);
if (wsi->desc.sockfd > context->max_fds) {
lwsl_err("fd %d too high (%d)\n", wsi->desc.sockfd, context->max_fds);
return 1;
}
#endif
@ -259,7 +259,7 @@ remove_wsi_socket_from_fds(struct lws *wsi)
lws_pt_lock(pt);
lwsl_debug("%s: wsi=%p, sock=%d, fds pos=%d, end guy pos=%d, endfd=%d\n",
__func__, wsi, wsi->sock, wsi->position_in_fds_table,
__func__, wsi, wsi->desc.sockfd, wsi->position_in_fds_table,
pt->fds_count, pt->fds[pt->fds_count].fd);
/* have the last guy take up the now vacant slot */
@ -278,12 +278,12 @@ remove_wsi_socket_from_fds(struct lws *wsi)
end_wsi->position_in_fds_table = m;
/* deletion guy's lws_lookup entry needs nuking */
delete_from_fd(context, wsi->sock);
delete_from_fd(context, wsi->desc.sockfd);
/* removed wsi has no position any more */
wsi->position_in_fds_table = -1;
/* remove also from external POLL support via protocol 0 */
if (lws_socket_is_valid(wsi->sock))
if (lws_socket_is_valid(wsi->desc.sockfd))
if (wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_DEL_POLL_FD,
wsi->user_space, (void *) &pa, 0))
ret = -1;
@ -396,7 +396,7 @@ network_sock:
return 1;
if (wsi->position_in_fds_table < 0) {
lwsl_err("%s: failed to find socket %d\n", __func__, wsi->sock);
lwsl_err("%s: failed to find socket %d\n", __func__, wsi->desc.sockfd);
return -1;
}

View file

@ -543,7 +543,8 @@ enum connection_mode {
/* special internal types */
LWSCM_SERVER_LISTENER,
LWSCM_CGI, /* stdin, stdout, stderr for another cgi master wsi */
LWSCM_RAW, /* raw */
LWSCM_RAW, /* raw with bulk handling */
LWSCM_RAW_FILEDESC, /* raw without bulk handling */
/* HTTP Client related */
LWSCM_HTTP_CLIENT = LWSCM_FLAG_IMPLIES_CALLBACK_CLOSED_CLIENT_HTTP,
@ -928,8 +929,7 @@ enum {
#if defined(LWS_USE_LIBEV)
LWS_EXTERN void
lws_libev_accept(struct lws *new_wsi, lws_sockfd_type accept_fd);
LWS_EXTERN void
lws_libev_accept(struct lws *new_wsi, lws_sock_file_fd_type desc);
lws_libev_io(struct lws *wsi, int flags);
LWS_EXTERN int
lws_libev_init_fd_table(struct lws_context *context);
@ -956,7 +956,7 @@ LWS_EXTERN void lws_feature_status_libev(struct lws_context_creation_info *info)
#if defined(LWS_USE_LIBUV)
LWS_EXTERN void
lws_libuv_accept(struct lws *new_wsi, lws_sockfd_type accept_fd);
lws_libuv_accept(struct lws *new_wsi, lws_sock_file_fd_type desc);
LWS_EXTERN void
lws_libuv_io(struct lws *wsi, int flags);
LWS_EXTERN int
@ -1408,8 +1408,7 @@ struct lws {
unsigned long action_start;
unsigned long latency_start;
#endif
/* pointer / int */
lws_sockfd_type sock;
lws_sock_file_fd_type desc; /* .filefd / .sockfd */
/* ints */
int position_in_fds_table;
@ -1562,7 +1561,7 @@ LWS_EXTERN int
delete_from_fd(struct lws_context *context, lws_sockfd_type fd);
#else
#define wsi_from_fd(A,B) A->lws_lookup[B]
#define insert_wsi(A,B) assert(A->lws_lookup[B->sock] == 0); A->lws_lookup[B->sock]=B
#define insert_wsi(A,B) assert(A->lws_lookup[B->desc.sockfd] == 0); A->lws_lookup[B->desc.sockfd]=B
#define delete_from_fd(A,B) A->lws_lookup[B]=0
#endif

View file

@ -142,7 +142,7 @@ lws_context_init_server(struct lws_context_creation_info *info,
goto bail;
}
wsi->context = vhost->context;
wsi->sock = sockfd;
wsi->desc.sockfd = sockfd;
wsi->mode = LWSCM_SERVER_LISTENER;
wsi->protocol = vhost->protocols;
wsi->tsi = m;
@ -161,7 +161,7 @@ lws_context_init_server(struct lws_context_creation_info *info,
vhost->lserv_wsi = wsi;
#if LWS_POSIX
n = listen(wsi->sock, LWS_SOMAXCONN);
n = listen(wsi->desc.sockfd, LWS_SOMAXCONN);
if (n < 0) {
lwsl_err("listen failed with error %d\n", LWS_ERRNO);
vhost->lserv_wsi = NULL;
@ -172,7 +172,7 @@ lws_context_init_server(struct lws_context_creation_info *info,
} /* for each thread able to independently listen */
#else
#if defined(LWS_WITH_ESP8266)
esp8266_tcp_stream_bind(wsi->sock, info->port, wsi);
esp8266_tcp_stream_bind(wsi->desc.sockfd, info->port, wsi);
#endif
#endif
if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) {
@ -1502,7 +1502,7 @@ upgrade_ws:
wsi->u.ws.rx_ubuf_alloc = n;
lwsl_debug("Allocating RX buffer %d\n", n);
#if LWS_POSIX && !defined(LWS_WITH_ESP32)
if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF,
if (setsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_SNDBUF,
(const char *)&n, sizeof n)) {
lwsl_warn("Failed to set SNDBUF to %d", n);
return 1;
@ -1611,7 +1611,7 @@ lws_create_new_server_wsi(struct lws_vhost *vhost)
new_wsi->protocol = vhost->protocols;
new_wsi->user_space = NULL;
new_wsi->ietf_spec_revision = 0;
new_wsi->sock = LWS_SOCK_INVALID;
new_wsi->desc.sockfd = LWS_SOCK_INVALID;
vhost->context->count_wsi_allocated++;
/*
@ -1686,33 +1686,56 @@ lws_http_transaction_completed(struct lws *wsi)
return 0;
}
/* if not a socket, it's a raw, non-ssl file descriptor */
LWS_VISIBLE struct lws *
lws_adopt_socket_vhost2(struct lws_vhost *vh, lws_sockfd_type accept_fd,
int allow_ssl, int raw)
lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
lws_sock_file_fd_type fd, const char *vh_prot_name)
{
struct lws_context *context = vh->context;
struct lws *new_wsi = lws_create_new_server_wsi(vh);
int n;
int n, ssl = 0;
if (!new_wsi) {
compatible_close(accept_fd);
if (type & LWS_ADOPT_SOCKET)
compatible_close(fd.sockfd);
return NULL;
}
lwsl_debug("%s: new wsi %p, sockfd %d, cb %p\n", __func__, new_wsi,
accept_fd, context->vhost_list->protocols[0].callback);
new_wsi->desc = fd;
new_wsi->protocol = &context->vhost_list->
protocols[vh->default_protocol_index];
new_wsi->sock = accept_fd;
if (!(type & LWS_ADOPT_SOCKET)) {
new_wsi->protocol = lws_vhost_name_to_protocol(new_wsi->vhost,
vh_prot_name);
if (!new_wsi->protocol) {
lwsl_err("Protocol %s not enabled on vhost %s\n",
vh_prot_name, new_wsi->vhost->name);
lws_free(new_wsi);
/* the transport is accepted... give him time to negotiate */
lws_set_timeout(new_wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
context->timeout_secs);
return NULL;
}
}
if (type & LWS_ADOPT_SOCKET) {
lwsl_debug("%s: new wsi %p, sockfd %d\n", __func__, new_wsi,
(int)(size_t)fd.sockfd);
/* the transport is accepted... give him time to negotiate */
lws_set_timeout(new_wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
context->timeout_secs);
#if LWS_POSIX == 0
#if defined(LWS_WITH_ESP8266)
esp8266_tcp_stream_accept(accept_fd, new_wsi);
esp8266_tcp_stream_accept(accept_fd, new_wsi);
#endif
#endif
} else //* file desc */
lwsl_debug("%s: new wsi %p, filefd %d\n", __func__, new_wsi,
(int)(size_t)fd.filefd);
/*
* A new connection was accepted. Give the user a chance to
* set properties of the newly created wsi. There's no protocol
@ -1720,45 +1743,65 @@ lws_adopt_socket_vhost2(struct lws_vhost *vh, lws_sockfd_type accept_fd,
* itself by default protocols[0]
*/
n = LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED;
if (raw)
n = LWS_CALLBACK_RAW_ADOPT;
if ((context->vhost_list->protocols[vh->default_protocol_index].callback)(
if (!(type & LWS_ADOPT_HTTP)) {
if (!(type & LWS_ADOPT_SOCKET))
n = LWS_CALLBACK_RAW_ADOPT_FILE;
else
n = LWS_CALLBACK_RAW_ADOPT;
}
if ((new_wsi->protocol->callback)(
new_wsi, n, NULL, NULL, 0)) {
/* force us off the timeout list by hand */
lws_set_timeout(new_wsi, NO_PENDING_TIMEOUT, 0);
compatible_close(new_wsi->sock);
if (type & LWS_ADOPT_SOCKET) {
/* force us off the timeout list by hand */
lws_set_timeout(new_wsi, NO_PENDING_TIMEOUT, 0);
compatible_close(new_wsi->desc.sockfd);
}
lws_free(new_wsi);
return NULL;
}
lws_libev_accept(new_wsi, new_wsi->sock);
lws_libuv_accept(new_wsi, new_wsi->sock);
if (!LWS_SSL_ENABLED(new_wsi->vhost) || !(type & LWS_ADOPT_ALLOW_SSL) ||
!(type & LWS_ADOPT_SOCKET)) {
/* non-SSL */
if (!(type & LWS_ADOPT_HTTP)) {
if (!(type & LWS_ADOPT_SOCKET))
new_wsi->mode = LWSCM_RAW_FILEDESC;
else
new_wsi->mode = LWSCM_RAW;
}
} else {
/* SSL */
if (!(type & LWS_ADOPT_HTTP))
new_wsi->mode = LWSCM_SSL_INIT_RAW;
else
new_wsi->mode = LWSCM_SSL_INIT;
if (!LWS_SSL_ENABLED(new_wsi->vhost) || allow_ssl == 0) {
if (raw)
new_wsi->mode = LWSCM_RAW;
ssl = 1;
}
lws_libev_accept(new_wsi, new_wsi->desc);
lws_libuv_accept(new_wsi, new_wsi->desc);
if (!ssl) {
if (insert_wsi_socket_into_fds(context, new_wsi)) {
lwsl_err("%s: fail inserting socket\n", __func__);
goto fail;
}
} else {
if (raw)
new_wsi->mode = LWSCM_SSL_INIT_RAW;
else
new_wsi->mode = LWSCM_SSL_INIT;
if (lws_server_socket_service_ssl(new_wsi, accept_fd)) {
} else
if (lws_server_socket_service_ssl(new_wsi, fd.sockfd)) {
lwsl_err("%s: fail ssl negotiation\n", __func__);
goto fail;
}
}
if (!lws_header_table_attach(new_wsi, 0))
lwsl_debug("Attached ah immediately\n");
if (type & LWS_ADOPT_HTTP)
if (!lws_header_table_attach(new_wsi, 0))
lwsl_debug("Attached ah immediately\n");
return new_wsi;
fail:
lws_close_free_wsi(new_wsi, LWS_CLOSE_STATUS_NOSTATUS);
if (type & LWS_ADOPT_SOCKET)
lws_close_free_wsi(new_wsi, LWS_CLOSE_STATUS_NOSTATUS);
return NULL;
}
@ -1766,13 +1809,17 @@ fail:
LWS_VISIBLE struct lws *
lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd)
{
return lws_adopt_socket_vhost2(vh, accept_fd, 1, 0);
lws_sock_file_fd_type fd;
fd.sockfd = accept_fd;
return lws_adopt_descriptor_vhost(vh, LWS_ADOPT_SOCKET |
LWS_ADOPT_HTTP | LWS_ADOPT_ALLOW_SSL, fd, NULL);
}
LWS_VISIBLE struct lws *
lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd)
{
return lws_adopt_socket_vhost2(context->vhost_list, accept_fd, 1, 0);
return lws_adopt_socket_vhost(context->vhost_list, accept_fd);
}
/* Common read-buffer adoption for lws_adopt_*_readbuf */

View file

@ -30,6 +30,9 @@ lws_calllback_as_writeable(struct lws *wsi)
case LWSCM_RAW:
n = LWS_CALLBACK_RAW_WRITEABLE;
break;
case LWSCM_RAW_FILEDESC:
n = LWS_CALLBACK_RAW_WRITEABLE_FILE;
break;
case LWSCM_WS_CLIENT:
n = LWS_CALLBACK_CLIENT_WRITEABLE;
break;
@ -198,7 +201,7 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
*/
ret = 1;
if (wsi->mode == LWSCM_RAW)
if (wsi->mode == LWSCM_RAW || wsi->mode == LWSCM_RAW_FILEDESC)
ret = 0;
while (ret == 1) {
@ -366,7 +369,7 @@ lws_service_timeout_check(struct lws *wsi, unsigned int sec)
*/
if ((time_t)sec > wsi->pending_timeout_limit) {
//#if LWS_POSIX
if (wsi->sock != LWS_SOCK_INVALID && wsi->position_in_fds_table >= 0)
if (wsi->desc.sockfd != LWS_SOCK_INVALID && wsi->position_in_fds_table >= 0)
n = pt->fds[wsi->position_in_fds_table].events;
/* no need to log normal idle keepalive timeout */
@ -734,7 +737,7 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t
while (wsi) {
/* we have to take copies, because he may be deleted */
wsi1 = wsi->timeout_list;
tmp_fd = wsi->sock;
tmp_fd = wsi->desc.sockfd;
if (lws_service_timeout_check(wsi, (unsigned int)now)) {
/* he did time out... */
if (tmp_fd == our_fd)
@ -863,17 +866,42 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t
return 1;
goto handled;
case LWSCM_RAW_FILEDESC:
case LWSCM_RAW:
if (pollfd->revents & LWS_POLLOUT) {
n = lws_calllback_as_writeable(wsi);
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
lwsl_info("failed at set pollfd\n");
return 1;
}
if (n)
goto close_and_handled;
}
n = LWS_CALLBACK_RAW_RX;
if (wsi->mode == LWSCM_RAW_FILEDESC)
n = LWS_CALLBACK_RAW_RX_FILE;
if (pollfd->revents & LWS_POLLIN) {
if (user_callback_handle_rxflow(
wsi->protocol->callback,
wsi, n,
wsi->user_space, NULL, 0)) {
lwsl_debug("raw rx callback closed it\n");
goto close_and_handled;
}
}
n = 0;
goto handled;
case LWSCM_WS_SERVING:
case LWSCM_WS_CLIENT:
case LWSCM_HTTP2_SERVING:
case LWSCM_HTTP_CLIENT_ACCEPTED:
case LWSCM_RAW:
/* 1: something requested a callback when it was OK to write */
if ((pollfd->revents & LWS_POLLOUT) &&
((wsi->mode == LWSCM_RAW) ||
(wsi->state == LWSS_ESTABLISHED ||
((wsi->state == LWSS_ESTABLISHED ||
wsi->state == LWSS_HTTP2_ESTABLISHED ||
wsi->state == LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS ||
wsi->state == LWSS_RETURNED_CLOSE_ALREADY ||

View file

@ -184,7 +184,7 @@ lws_ssl_client_bio_create(struct lws *wsi)
#endif
#endif /* USE_WOLFSSL */
wsi->client_bio = BIO_new_socket(wsi->sock, BIO_NOCLOSE);
wsi->client_bio = BIO_new_socket(wsi->desc.sockfd, BIO_NOCLOSE);
SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
#ifdef USE_WOLFSSL

View file

@ -470,7 +470,7 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd)
lws_latency_pre(context, wsi);
n = recv(wsi->sock, (char *)pt->serv_buf, context->pt_serv_buf_size,
n = recv(wsi->desc.sockfd, (char *)pt->serv_buf, context->pt_serv_buf_size,
MSG_PEEK);
/*
@ -550,7 +550,7 @@ go_again:
break;
}
lwsl_err("SSL_accept failed socket %u: %s\n", wsi->sock,
lwsl_err("SSL_accept failed socket %u: %s\n", wsi->desc.sockfd,
lws_ssl_get_error_string(m, n, buf, sizeof(buf)));
lws_ssl_elaborate_error();
goto fail;

View file

@ -0,0 +1,227 @@
/*
* ws protocol handler plugin for testing raw file and raw socket
*
* Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
*
* This file is made available under the Creative Commons CC0 1.0
* Universal Public Domain Dedication.
*
* The person who associated a work with this deed has dedicated
* the work to the public domain by waiving all of his or her rights
* to the work worldwide under copyright law, including all related
* and neighboring rights, to the extent allowed by law. You can copy,
* modify, distribute and perform the work, even for commercial purposes,
* all without asking permission.
*
* These test plugins are intended to be adapted for use in your code, which
* may be proprietary. So unlike the library itself, they are licensed
* Public Domain.
*
* Enable on a vhost like this
*
* "protocol-lws-raw-test": {
* "status": "ok",
* "fifo-path": "/tmp/lws-test-raw"
* },
*
* Then you can feed it data through the FIFO like this
*
* $ sudo sh -c "echo hello > /tmp/lws-test-raw"
*
* This plugin simply prints the data. But it does it through the lws event loop /
* service poll.
*/
#if !defined (LWS_PLUGIN_STATIC)
#define LWS_DLL
#define LWS_INTERNAL
#include "../lib/libwebsockets.h"
#endif
#include <string.h>
struct per_vhost_data__raw_test {
struct lws_context *context;
struct lws_vhost *vhost;
const struct lws_protocols *protocol;
char fifo_path[100];
int fifo;
char zero_length_read;
};
struct per_session_data__raw_test {
int number;
};
static int
callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len)
{
struct per_session_data__raw_test *pss =
(struct per_session_data__raw_test *)user;
struct per_vhost_data__raw_test *vhd =
(struct per_vhost_data__raw_test *)
lws_protocol_vh_priv_get(lws_get_vhost(wsi),
lws_get_protocol(wsi));
lws_sock_file_fd_type u;
(void)pss;
switch (reason) {
case LWS_CALLBACK_PROTOCOL_INIT:
vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
lws_get_protocol(wsi),
sizeof(struct per_vhost_data__raw_test));
vhd->context = lws_get_context(wsi);
vhd->protocol = lws_get_protocol(wsi);
vhd->vhost = lws_get_vhost(wsi);
{
const struct lws_protocol_vhost_options *pvo =
(const struct lws_protocol_vhost_options *)in;
while (pvo) {
if (!strcmp(pvo->name, "fifo-path"))
strncpy(vhd->fifo_path, pvo->value, sizeof(vhd->fifo_path) - 1);
pvo = pvo->next;
}
if (vhd->fifo_path[0] == '\0') {
lwsl_err("Missing pvo \"fifo-path\"\n");
return 1;
}
}
unlink(vhd->fifo_path);
if (mkfifo(vhd->fifo_path, 0666)) {
lwsl_err("mkfifo failed\n");
return 1;
}
vhd->fifo = open(vhd->fifo_path, O_NONBLOCK | O_RDONLY);
if (vhd->fifo == -1) {
lwsl_err("opening fifo failed\n");
unlink(vhd->fifo_path);
return 1;
}
lwsl_notice("FIFO %s created\n", vhd->fifo_path);
u.filefd = vhd->fifo;
if (!lws_adopt_descriptor_vhost(vhd->vhost, 0, u, "protocol-lws-raw-test")) {
lwsl_err("Failed to adopt fifo descriptor\n");
close(vhd->fifo);
unlink(vhd->fifo_path);
return 1;
}
break;
case LWS_CALLBACK_PROTOCOL_DESTROY:
if (!vhd)
break;
if (vhd->fifo >- 0) {
close(vhd->fifo);
unlink(vhd->fifo_path);
}
break;
case LWS_CALLBACK_RAW_ADOPT_FILE:
lwsl_notice("LWS_CALLBACK_RAW_ADOPT_FILE\n");
break;
case LWS_CALLBACK_RAW_RX_FILE:
lwsl_notice("LWS_CALLBACK_RAW_RX_FILE\n");
{
char buf[256];
int n;
n = read(vhd->fifo, buf, sizeof(buf) - 1);
if (n < 0) {
lwsl_err("FIFO read failed\n");
return 1;
}
/*
* When nobody opened the other side of the FIFO, the FIFO fd acts well and
* only signals POLLIN when somebody opened and wrote to it.
*
* But if the other side of the FIFO closed it, we will see an endless
* POLLIN and 0 available to read.
*
* The only way to handle it is to reopen the FIFO our side and wait for a
* new peer. This is a quirk of FIFOs not of LWS.
*/
if (n == 0) { /* peer closed - do reopen in close processing */
vhd->zero_length_read = 1;
return 1;
}
buf[n] = '\0';
lwsl_info("read %d\n", n);
puts(buf);
}
break;
case LWS_CALLBACK_RAW_CLOSE_FILE:
lwsl_notice("LWS_CALLBACK_RAW_CLOSE_FILE\n");
if (vhd->zero_length_read) {
vhd->zero_length_read = 0;
close(vhd->fifo);
/* the wsi that adopted the fifo file is closing... reopen the fifo and readopt */
vhd->fifo = open(vhd->fifo_path, O_NONBLOCK | O_RDONLY);
if (vhd->fifo == -1) {
lwsl_err("opening fifo failed\n");
return 1;
}
lwsl_notice("FIFO %s reopened\n", vhd->fifo_path);
u.filefd = vhd->fifo;
if (!lws_adopt_descriptor_vhost(vhd->vhost, 0, u, "protocol-lws-raw-test")) {
lwsl_err("Failed to adopt fifo descriptor\n");
close(vhd->fifo);
return 1;
}
}
break;
case LWS_CALLBACK_RAW_WRITEABLE_FILE:
lwsl_notice("LWS_CALLBACK_RAW_WRITEABLE_FILE\n");
break;
default:
break;
}
return 0;
}
#define LWS_PLUGIN_PROTOCOL_RAW_TEST \
{ \
"protocol-lws-raw-test", \
callback_raw_test, \
sizeof(struct per_session_data__raw_test), \
1024, /* rx buf size must be >= permessage-deflate rx size */ \
}
#if !defined (LWS_PLUGIN_STATIC)
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_RAW_TEST
};
LWS_EXTERN LWS_VISIBLE int
init_protocol_lws_raw_test(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
LWS_EXTERN LWS_VISIBLE int
destroy_protocol_lws_raw_test(struct lws_context *context)
{
return 0;
}
#endif