diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 98debfda..d7f7df6f 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -3579,6 +3579,7 @@ lws_remaining_packet_payload(struct lws *wsi); /** * lws_adopt_socket() - adopt foreign socket as if listen socket accepted it + * for the default vhost of context. * \param context: lws context * \param accept_fd: fd of already-accepted socket to adopt * @@ -3590,8 +3591,23 @@ lws_remaining_packet_payload(struct lws *wsi); */ LWS_VISIBLE LWS_EXTERN struct lws * lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd); +/** + * lws_adopt_socket_vhost() - adopt foreign socket as if listen socket accepted it + * for vhost + * \param vhost: lws vhost + * \param accept_fd: fd of already-accepted socket to adopt + * + * 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. + */ +LWS_VISIBLE LWS_EXTERN struct lws * +lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd); /** * lws_adopt_socket_readbuf() - adopt foreign socket and first rx as if listen socket accepted it + * for the default vhost of context. * \param context: lws context * \param accept_fd: fd of already-accepted socket to adopt * \param readbuf: NULL or pointer to data that must be drained before reading from @@ -3614,7 +3630,33 @@ lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd); */ LWS_VISIBLE LWS_EXTERN struct lws * lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd, - const char *readbuf, size_t len); + const char *readbuf, size_t len); +/** + * lws_adopt_socket_vhost_readbuf() - adopt foreign socket and first rx as if listen socket + * accepted it for vhost. + * \param vhost: lws vhost + * \param accept_fd: fd of already-accepted socket to adopt + * \param readbuf: NULL or pointer to data that must be drained before reading from + * accept_fd + * \param len: The length of the data held at \param readbuf + * + * 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 your external code did not already read from the socket, you can use + * lws_adopt_socket() instead. + * + * This api is guaranteed to use the data at \param readbuf first, before reading from + * the socket. + * + * readbuf is limited to the size of the ah rx buf, currently 2048 bytes. + */ +LWS_VISIBLE LWS_EXTERN struct lws * +lws_adopt_socket_vhost_readbuf(struct lws_vhost *vhost, lws_sockfd_type accept_fd, + const char *readbuf, size_t len); ///@} /** \defgroup net Network related helper APIs diff --git a/lib/server.c b/lib/server.c index 45f691bf..bc9033a7 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1672,7 +1672,7 @@ lws_http_transaction_completed(struct lws *wsi) return 0; } -struct lws * +LWS_VISIBLE struct lws * lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd) { struct lws_context *context = vh->context; @@ -1745,11 +1745,10 @@ lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd) return lws_adopt_socket_vhost(context->vhost_list, accept_fd); } -LWS_VISIBLE LWS_EXTERN struct lws * -lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd, - const char *readbuf, size_t len) +/* Common read-buffer adoption for lws_adopt_*_readbuf */ +static struct lws* +adopt_socket_readbuf(struct lws *wsi, const char *readbuf, size_t len) { - struct lws *wsi = lws_adopt_socket(context, accept_fd); struct lws_context_per_thread *pt; struct allocated_headers *ah; struct lws_pollfd *pfd; @@ -1757,7 +1756,7 @@ lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd, if (!wsi) return NULL; - if (!readbuf) + if (!readbuf || len == 0) return wsi; if (len > sizeof(ah->rx)) { @@ -1782,7 +1781,7 @@ lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd, ah->rxlen = len; lwsl_notice("%s: calling service on readbuf ah\n", __func__); - pt = &context->pt[(int)wsi->tsi]; + pt = &wsi->context->pt[(int)wsi->tsi]; /* unlike a normal connect, we have the headers already * (or the first part of them anyway). @@ -1792,7 +1791,7 @@ lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd, pfd = &pt->fds[wsi->position_in_fds_table]; pfd->revents |= LWS_POLLIN; lwsl_err("%s: calling service\n", __func__); - if (lws_service_fd_tsi(context, pfd, wsi->tsi)) + if (lws_service_fd_tsi(wsi->context, pfd, wsi->tsi)) /* service closed us */ return NULL; @@ -1822,6 +1821,20 @@ bail: return NULL; } +LWS_VISIBLE struct lws * +lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd, + const char *readbuf, size_t len) +{ + return adopt_socket_readbuf(lws_adopt_socket(context, accept_fd), readbuf, len); +} + +LWS_VISIBLE struct lws * +lws_adopt_socket_vhost_readbuf(struct lws_vhost *vhost, lws_sockfd_type accept_fd, + const char *readbuf, size_t len) +{ + return adopt_socket_readbuf(lws_adopt_socket_vhost(vhost, accept_fd), readbuf, len); +} + LWS_VISIBLE int lws_server_socket_service(struct lws_context *context, struct lws *wsi, struct lws_pollfd *pollfd)