Thanks to Fabrice Gilot for reporting the problem that led to uncovering this.
Due to a misunderstanding of the return value of snprintf (it is not truncated according
to the max size passed in) in several places relying on snprintf to truncate the length
overflows are possible.
This patch wraps snprintf with a new lws_snprintf() which does truncate its length to allow
the buffer limiting scheme to work properly.
All users should update with these fixes.
This clears up a couple of issues with client connect.
- if CLIENT_CONNECTION_ERROR is coming, which of the many
ways the rejection may have happened is documented in the
in argument. It's still possible if it just got hung up on
in will be NULL, but now it has MANY more canned strings
describing the issue available at the callback
"getaddrinfo (ipv6) failed"
"unknown address family"
"getaddrinfo (ipv4) failed"
"set socket opts failed"
"insert wsi failed"
"lws_ssl_client_connect1 failed"
"lws_ssl_client_connect2 failed"
"Peer hung up"
"read failed"
"HS: URI missing"
"HS: Redirect code but no Location"
"HS: URI did not parse"
"HS: Redirect failed"
"HS: Server did not return 200"
"HS: OOM"
"HS: disallowed by client filter"
"HS: disallowed at ESTABLISHED"
"HS: ACCEPT missing"
"HS: ws upgrade response not 101"
"HS: UPGRADE missing"
"HS: Upgrade to something other than websocket"
"HS: CONNECTION missing"
"HS: UPGRADE malformed"
"HS: PROTOCOL malformed"
"HS: Cannot match protocol"
"HS: EXT: list too big"
"HS: EXT: failed setting defaults"
"HS: EXT: failed parsing defaults"
"HS: EXT: failed parsing options"
"HS: EXT: Rejects server options"
"HS: EXT: unknown ext"
"HS: Accept hash wrong"
"HS: Rejected by filter cb"
"HS: OOM"
"HS: SO_SNDBUF failed"
"HS: Rejected at CLIENT_ESTABLISHED"
- until now the user code did not get the new wsi that was created
in the client connection action until it returned. However the
client connection action may provoke callbacks like
CLIENT_CONNECTION_ERROR before then, if multiple client connections
are initiated it makes it unknown to user code which one the callback
applies to. The wsi is provided in the callback but it has not yet
returned from the client connect api to give that wsi to the user code.
To solve that there is a new member added to client connect info struct,
pwsi, which lets you pass a pointer to a struct wsi * in the user code
that will get filled in with the new wsi. That happens before any
callbacks could be provoked, and it is updated to NULL if the connect
action fails before returning from the client connect api.
- libuv socket init binding was missing for client
- failures like no ws protocol match are deferred until the
ah is bound. Check for these failures and make sure we
tell the guy trying to set up the client connection the
wsi is NULL if it has already failed and closed.
- pfd.events was not initialized for the client init path
With this general client function is more robust but also
client connections work properly with libuv.
Signed-off-by: Andy Green <andy@warmcat.com>
This patch splits out some lws_context members into a new lws_vhost struct.
- ssl state and options per vhost
- SSL_CTX for serving and client per vhost
- protocols[] per vhost
- extensions[] per vhost
lws_context maintains a linked list of lws_vhosts.
The same lws_context_creation_info struct is used to regulate both the
context creation and to create vhosts: for backward compatibility if you
didn't provide the new LWS_SERVER_OPTION_EXPLICIT_VHOSTS option, then
a default vhost is created at context creation time using the same info
data as the context itself.
If you will have multiple vhosts though, you should give the
LWS_SERVER_OPTION_EXPLICIT_VHOSTS option at context creation time,
create the context first and then the vhosts afterwards using
lws_create_vhost(contest, &info);
Although there is a lot of housekeeping to implement this change, there
is almost no additional overhead if you don't use multiple vhosts and
very little api impact (no changes to test apps).
Signed-off-by: Andy Green <andy@warmcat.com>
If you enable -DLWS_WITH_HTTP_PROXY=1 at cmake, the test server has a
new URI path http://localhost:7681/proxytest If you visit here, a client
connection to http://example.com:80 is spawned, and the results piped on
to your original connection.
Also with LWS_WITH_HTTP_PROXY enabled at cmake, lws wants to link to an
additional library, "libhubbub". This allows lws to do html rewriting on the
fly, adjusting proxied urls in a lightweight and fast way.
Move the socket bind to interface code out of server into
libwebsockets.c and make a private api for it.
Signed-off-by: Andy Green <andy.green@linaro.org>
wsi can have a full tree relationship with each other using
linked lists. closing the parent ensures the children are
closed first.
Convert cgi to use this instead of his cgi-specific sub-wsi
management.
Signed-off-by: Andy Green <andy.green@linaro.org>
Server support for http[s] as well as ws[s] is implicit.
But until now client only supported ws[s].
This allows the user code to pass an explicit http method
like "GET" in the connect_info, disabling the ws upgrade logic.
Then you can also use lws client as http client, not just ws.
Signed-off-by: Andy Green <andy.green@linaro.org>
It can join the free ah list and pick up client connect processing
later when the ah becomes available; this simplifies the code
doing the request since he won't have to deal with unexpected
failures / retries based on dynamic ah availability.
To do this though we have to handle that the connect_info members
may not have scope that lets them still exist after we return from
the first connect call, we stash them in a malloc'd buffer so the
connect processing can have them much later even so.
Signed-off-by: Andy Green <andy.green@linaro.org>
This is intended to solve a longstanding problem with the
relationship between http/1.1 keep-alive and the service
loop.
Ah now contain an rx buffer which is used during header
processing, and the ah may not be detached from the wsi
until the rx buffer is exhausted.
Having the rx buffer in the ah means we can delay using the
rx until a later service loop.
Ah which have pending rx force POLLIN service on the wsi
they are attached to automatically, so we can interleave
general service / connections with draining each ah rx
buffer.
The possible http/1.1 situations and their dispositions are:
1) exactly one set of http headers come. After processing,
the ah is detached since no pending rx left. If more
headers come later, a fresh ah is aqcuired when available
and the rx flow control blocks the read until then.
2) more that one whole set of headers come and we remain in
http mode (no upgrade). The ah is left attached and
returns to the service loop after the first set of headers.
We will get forced service due to the ah having pending
content (respecting flowcontrol) and process the pending
rx in the ah. If we use it all up, we will detach the
ah.
3) one set of http headers come with ws traffic appended.
We service the headers, do the upgrade, and keep the ah
until the remaining ws content is used. When we
exhausted the ws traffix in the ah rx buffer, we
detach the ah.
Since there can be any amount of http/1.1 pipelining on a
connection, and each may be expensive to service, it's now
enforced there is a return to the service loop after each
header set is serviced on a connection.
When I added the forced service for ah with pending buffering,
I added support for it to the windows plat code. However this
is untested.
Signed-off-by: Andy Green <andy.green@linaro.org>
This gets the libuv stuff plumbed in and working.
Currently it's only workable for some service thread, and there
is an isolated valgrind problem left
==28425== 128 bytes in 1 blocks are definitely lost in loss record 3 of 3
==28425== at 0x4C28C50: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==28425== by 0x4C2AB1E: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==28425== by 0x58BBB27: maybe_resize (core.c:748)
==28425== by 0x58BBB27: uv__io_start (core.c:787)
==28425== by 0x58C1B80: uv__signal_loop_once_init (signal.c:225)
==28425== by 0x58C1B80: uv_signal_init (signal.c:260)
==28425== by 0x58BF7A6: uv_loop_init (loop.c:66)
==28425== by 0x4157F5: lws_uv_initloop (libuv.c:89)
==28425== by 0x405536: main (test-server-libuv.c:284)
libuv wants to sign off on all libuv 'handles' that will close, and
callback to do the close confirmation asynchronously. The wsi close function
is adapted when libuv is in use to work with libuv accordingly and exit the uv
loop the number of remaining wsi is zero.
Signed-off-by: Andy Green <andy.green@linaro.org>
Enforce no more internal use of deprecated apis (esp in the test apps)
Also signal clearly to users what is on the way out.
Signed-off-by: Andy Green <andy.green@linaro.org>
This adds support for multithreaded service to lws without adding any
threading or locking code in the library.
At context creation time you can request split the service part of the
context into n service domains, which are load-balanced so that the most
idle one gets the next listen socket accept.
There's a single listen socket on one port still.
User code may then spawn n threads doing n service loops / poll()s
simultaneously. Locking is only required (I think) in the existing
FD lock callbacks already handled by the pthreads server example,
and that locking takes place in user code. So the library remains
completely agnostic about the threading / locking scheme.
And by default, it's completely compatible with one service thread
so no changes are required by people uninterested in multithreaded
service.
However for people interested in extremely lightweight mass http[s]/
ws[s] service with minimum provisioning, the library can now do
everything out of the box.
To test it, just try
$ libwebsockets-test-server-pthreads -j 8
where -j controls the number of service threads
Signed-off-by: Andy Green <andy.green@linaro.org>
This adds redirect support to the client side. Lws will follow
server redirects (301) up to three deep.
Signed-off-by: Andy Green <andy.green@linaro.org>
- Mainly symbol length reduction
- Whitespace clean
- Code refactor for linear flow
- Audit @Context for API docs vs changes
Signed-off-by: Andy Green <andy.green@linaro.org>
Extend the cleanout caused by wsi having a context pointer
into the public api.
There's no point keeping the 1.5 compatibility work,
we have changed the api in several places and
rebuilt wasn't going to be enough a while ago.
Signed-off-by: Andy Green <andy.green@linaro.org>
Now we bit the bullet and gave each wsi an lws_context *, many
internal apis that take both a context and wsi parameter only
need the wsi.
Also simplify parser code by making a temp var for
allocated_headers * instead of the longwinded
dereference chain everywhere.
Signed-off-by: Andy Green <andy.green@linaro.org>
Because getaddrinfo will return error on Android when
AI_V4MAPPED is specified. So we should use old implemntation.
Android support of IPv6 is very poor.
This nukes all the oldstyle prefixes except in the compatibility code.
struct libwebsockets becomes struct lws too.
The api docs are updated accordingly as are the READMEs that mention
those apis.
Signed-off-by: Andy Green <andy.green@linaro.org>
Between changing to lws_ a few years ago and the previous two
patches migrating the public apis, there are only a few
internal functions left using libwebsocket_*.
Change those to also use lws_ without regard to compatibility
since they were never visible outside the library.
Signed-off-by: Andy Green <andy.green@linaro.org>
Change all internal uses of rationalized public apis to reflect the
new names.
Theer are a few things that got changed as side effect of search/replace
matches, but these are almost all internal. I added a compatibility define
for the public enum that got renamed.
Theoretically existing code should not notice the difference from these
two patches. And new code will find the new names.
https://github.com/warmcat/libwebsockets/issues/357
Signed-off-by: Andy Green <andy.green@linaro.org>
Simplifies proxy code to use the existing libwebsocket_set_proxy.
Enables libwebsocket_set_proxy() to parse username:password@ at front of
servername in both http_proxy and info->http_proxy_address.
If given the base64 version of the credentials are sent in the CONNECT
header to the proxy.
Port is now taken from info->http_proxy_address server:port syntax, but if
a port is given in the now deprecated info->http_proxy_port (ie, is nonzero)
then it is allowed to be missed out and the info port used instead for
backwards compatibility.
Signed-off-by: Andy Green <andy.green@linaro.org>