adopt variant with preamble rx

Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
Andy Green 2016-02-24 11:05:56 +08:00
parent 26d4249a3f
commit 51d9afadd6
6 changed files with 139 additions and 0 deletions

View file

@ -53,6 +53,14 @@ User API additions
which lets you set the name of the ECDH curve OpenSSL should use. By which lets you set the name of the ECDH curve OpenSSL should use. By
default (if you leave ecdh_curve NULL) it will use "prime256v1" default (if you leave ecdh_curve NULL) it will use "prime256v1"
2) MINOR NEWAPI It was already possible to adopt a foreign socket that had not
been read from using lws_adopt_socket() since v1.7. Now you can adopt a
partially-used socket if you don't need SSL, by passing it what you read
so it can drain that before reading from the socket.
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);
v1.7.0 v1.7.0

View file

@ -1712,6 +1712,9 @@ lws_client_connect_via_info(struct lws_client_connect_info * ccinfo);
LWS_VISIBLE LWS_EXTERN struct lws * LWS_VISIBLE LWS_EXTERN struct lws *
lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd); 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);
LWS_VISIBLE LWS_EXTERN const char * LWS_WARN_UNUSED_RESULT LWS_VISIBLE LWS_EXTERN const char * LWS_WARN_UNUSED_RESULT
lws_canonical_hostname(struct lws_context *context); lws_canonical_hostname(struct lws_context *context);

View file

@ -81,6 +81,16 @@ lws_header_table_reset(struct lws *wsi)
/* since we will restart the ah, our new headers are not completed */ /* since we will restart the ah, our new headers are not completed */
wsi->hdr_parsing_completed = 0; wsi->hdr_parsing_completed = 0;
/*
* if we inherited pending rx (from socket adoption deferred
* processing), apply and free it.
*/
if (wsi->u.hdr.preamble_rx) {
memcpy(ah->rx, wsi->u.hdr.preamble_rx, wsi->u.hdr.preamble_rx_len);
ah->rxlen = wsi->u.hdr.preamble_rx_len;
lws_free_set_NULL(wsi->u.hdr.preamble_rx);
}
} }
int LWS_WARN_UNUSED_RESULT int LWS_WARN_UNUSED_RESULT
@ -179,6 +189,9 @@ int lws_header_table_detach(struct lws *wsi)
(void *)wsi, (void *)wsi->u.hdr.ah, wsi->tsi, (void *)wsi, (void *)wsi->u.hdr.ah, wsi->tsi,
pt->ah_count_in_use); pt->ah_count_in_use);
if (wsi->u.hdr.preamble_rx)
lws_free_set_NULL(wsi->u.hdr.preamble_rx);
/* may not be detached while he still has unprocessed rx */ /* may not be detached while he still has unprocessed rx */
if (ah && ah->rxpos != ah->rxlen) { if (ah && ah->rxpos != ah->rxlen) {
lwsl_err("%s: %p: rxpos:%d, rxlen:%d\n", __func__, wsi, lwsl_err("%s: %p: rxpos:%d, rxlen:%d\n", __func__, wsi,

View file

@ -940,6 +940,8 @@ struct _lws_header_related {
/* MUST be first in struct */ /* MUST be first in struct */
struct allocated_headers *ah; struct allocated_headers *ah;
struct lws *ah_wait_list; struct lws *ah_wait_list;
unsigned char *preamble_rx;
unsigned int preamble_rx_len;
enum uri_path_states ups; enum uri_path_states ups;
enum uri_esc_states ues; enum uri_esc_states ues;
short lextable_pos; short lextable_pos;

View file

@ -821,6 +821,80 @@ fail:
return NULL; return NULL;
} }
/**
* lws_adopt_socket_readbuf() - adopt foreign socket and first rx as if listen socket accepted it
* @context: lws context
* @accept_fd: fd of already-accepted socket to adopt
* @readbuf: NULL or pointer to data that must be drained before reading from
* accept_fd
* @len: The length of the data held at @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 @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_readbuf(struct lws_context *context, lws_sockfd_type accept_fd,
const char *readbuf, size_t len)
{
struct lws *wsi = lws_adopt_socket(context, accept_fd);
struct allocated_headers *ah;
if (!wsi)
return NULL;
if (!readbuf)
return wsi;
if (len > sizeof(ah->rx)) {
lwsl_err("%s: rx in too big\n", __func__);
goto bail;
}
/*
* we can't process the initial read data until we can attach an ah.
*
* if one is available, get it and place the data in his ah rxbuf...
* wsi with ah that have pending rxbuf get auto-POLLIN service.
*/
if (!lws_header_table_attach(wsi)) {
ah = wsi->u.hdr.ah;
memcpy(ah->rx, readbuf, len);
ah->rxpos = 0;
ah->rxlen = len;
return wsi;
}
/*
* hum if no ah came, we are on the wait list and must defer
* dealing with this until the ah arrives.
*
* later successful lws_header_table_attach() will apply the
* below to the rx buffer.
*/
wsi->u.hdr.preamble_rx = lws_malloc(len);
wsi->u.hdr.preamble_rx_len = len;
return wsi;
bail:
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
return NULL;
}
LWS_VISIBLE int LWS_VISIBLE int
lws_server_socket_service(struct lws_context *context, struct lws *wsi, lws_server_socket_service(struct lws_context *context, struct lws *wsi,
struct lws_pollfd *pollfd) struct lws_pollfd *pollfd)

View file

@ -790,6 +790,42 @@ LWS adopts the socket in http serving mode, it's ready to accept an upgrade
to ws or just serve http. to ws or just serve http.
</blockquote> </blockquote>
<hr> <hr>
<h2>lws_adopt_socket_readbuf - adopt foreign socket and first rx as if listen socket accepted it</h2>
<i>LWS_EXTERN struct lws *</i>
<b>lws_adopt_socket_readbuf</b>
(<i>struct lws_context *</i> <b>context</b>,
<i>lws_sockfd_type</i> <b>accept_fd</b>,
<i>const char *</i> <b>readbuf</b>,
<i>size_t</i> <b>len</b>)
<h3>Arguments</h3>
<dl>
<dt><b>context</b>
<dd>lws context
<dt><b>accept_fd</b>
<dd>fd of already-accepted socket to adopt
<dt><b>readbuf</b>
<dd>NULL or pointer to data that must be drained before reading from
accept_fd
<dt><b>len</b>
<dd>The length of the data held at <tt><b>readbuf</b></tt>
</dl>
<h3>Description</h3>
<blockquote>
Either returns new wsi bound to accept_fd, or closes accept_fd and
returns NULL, having cleaned up any new wsi pieces.
<p>
LWS adopts the socket in http serving mode, it's ready to accept an upgrade
to ws or just serve http.
<p>
If your external code did not already read from the socket, you can use
<b>lws_adopt_socket</b> instead.
<p>
This api is guaranteed to use the data at <tt><b>readbuf</b></tt> first, before reading from
the socket.
<p>
<tt><b>readbuf</b></tt> is limited to the size of the ah rx buf, currently 2048 bytes.
</blockquote>
<hr>
<h2>lws_serve_http_file - Send a file back to the client using http</h2> <h2>lws_serve_http_file - Send a file back to the client using http</h2>
<i>int</i> <i>int</i>
<b>lws_serve_http_file</b> <b>lws_serve_http_file</b>
@ -1518,6 +1554,7 @@ header.
&nbsp; &nbsp; <i>unsigned int</i> <b>count_threads</b>;<br> &nbsp; &nbsp; <i>unsigned int</i> <b>count_threads</b>;<br>
&nbsp; &nbsp; <i>unsigned int</i> <b>fd_limit_per_thread</b>;<br> &nbsp; &nbsp; <i>unsigned int</i> <b>fd_limit_per_thread</b>;<br>
&nbsp; &nbsp; <i>unsigned int</i> <b>timeout_secs</b>;<br> &nbsp; &nbsp; <i>unsigned int</i> <b>timeout_secs</b>;<br>
&nbsp; &nbsp; <i>const char *</i> <b>ecdh_curve</b>;<br>
};<br> };<br>
<h3>Members</h3> <h3>Members</h3>
<dl> <dl>
@ -1613,6 +1650,8 @@ limit by the number of threads.
library are protected from hanging forever by timeouts. If library are protected from hanging forever by timeouts. If
nonzero, this member lets you set the timeout used in seconds. nonzero, this member lets you set the timeout used in seconds.
Otherwise a default timeout is used. Otherwise a default timeout is used.
<dt><b>ecdh_curve</b>
<dd>if NULL, defaults to initializing server with "prime256v1"
</dl> </dl>
<hr> <hr>
<h2>struct lws_client_connect_info - parameters to connect with when using lws_client_connect_via_info()</h2> <h2>struct lws_client_connect_info - parameters to connect with when using lws_client_connect_via_info()</h2>