• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Notes about coding with lws
2===========================
3
4@section era Old lws and lws v2.0+
5
6Originally lws only supported the "manual" method of handling everything in the
7user callback found in test-server.c / test-server-http.c.
8
9Since v2.0, the need for most or all of this manual boilerplate has been
10eliminated: the protocols[0] http stuff is provided by a generic lib export
11`lws_callback_http_dummy()`.  You can serve parts of your filesystem at part of
12the URL space using mounts, the dummy http callback will do the right thing.
13
14It's much preferred to use the "automated" v2.0 type scheme, because it's less
15code and it's easier to support.
16
17The minimal examples all use the modern, recommended way.
18
19If you just need generic serving capability, without the need to integrate lws
20to some other app, consider not writing any server code at all, and instead use
21the generic server `lwsws`, and writing your special user code in a standalone
22"plugin".  The server is configured for mounts etc using JSON, see
23./READMEs/README.lwsws.md.
24
25Although the "plugins" are dynamically loaded if you use lwsws or lws built
26with libuv, actually they may perfectly well be statically included if that
27suits your situation better, eg, ESP32 test server, where the platform does
28not support processes or dynamic loading, just #includes the plugins
29one after the other and gets the same benefit from the same code.
30
31Isolating and collating the protocol code in one place also makes it very easy
32to maintain and understand.
33
34So it if highly recommended you put your protocol-specific code into the
35form of a "plugin" at the source level, even if you have no immediate plan to
36use it dynamically-loaded.
37
38@section writeable Only send data when socket writeable
39
40You should only send data on a websocket connection from the user callback
41`LWS_CALLBACK_SERVER_WRITEABLE` (or `LWS_CALLBACK_CLIENT_WRITEABLE` for
42clients).
43
44If you want to send something, do NOT just send it but request a callback
45when the socket is writeable using
46
47 - `lws_callback_on_writable(wsi)` for a specific `wsi`, or
48
49 - `lws_callback_on_writable_all_protocol(protocol)` for all connections
50using that protocol to get a callback when next writeable.
51
52Usually you will get called back immediately next time around the service
53loop, but if your peer is slow or temporarily inactive the callback will be
54delayed accordingly.  Generating what to write and sending it should be done
55in the ...WRITEABLE callback.
56
57See the test server code for an example of how to do this.
58
59Otherwise evolved libs like libuv get this wrong, they will allow you to "send"
60anything you want but it only uses up your local memory (and costs you
61memcpys) until the socket can actually accept it.  It is much better to regulate
62your send action by the downstream peer readiness to take new data in the first
63place, avoiding all the wasted buffering.
64
65Libwebsockets' concept is that the downstream peer is truly the boss, if he,
66or our connection to him, cannot handle anything new, we should not generate
67anything new for him.  This is how unix shell piping works, you may have
68`cat a.txt | grep xyz > remote", but actually that does not cat anything from
69a.txt while remote cannot accept anything new.
70
71@section oneper Only one lws_write per WRITEABLE callback
72
73From v2.5, lws strictly enforces only one lws_write() per WRITEABLE callback.
74
75You will receive a message about "Illegal back-to-back write of ... detected"
76if there is a second lws_write() before returning to the event loop.
77
78This is because with http/2, the state of the network connection carrying a
79wsi is unrelated to any state of the wsi.  The situation on http/1 where a
80new request implied a new tcp connection and new SSL buffer, so you could
81assume some window for writes is no longer true.  Any lws_write() can fail
82and be buffered for completion by lws; it will be auto-completed by the
83event loop.
84
85Note that if you are handling your own http responses, writing the headers
86needs to be done with a separate lws_write() from writing any payload.  That
87means after writing the headers you must call `lws_callback_on_writable(wsi)`
88and send any payload from the writable callback.
89
90@section otherwr Do not rely on only your own WRITEABLE requests appearing
91
92Libwebsockets may generate additional `LWS_CALLBACK_CLIENT_WRITEABLE` events
93if it met network conditions where it had to buffer your send data internally.
94
95So your code for `LWS_CALLBACK_CLIENT_WRITEABLE` needs to own the decision
96about what to send, it can't assume that just because the writeable callback
97came something is ready to send.
98
99It's quite possible you get an 'extra' writeable callback at any time and
100just need to `return 0` and wait for the expected callback later.
101
102@section dae Daemonization
103
104There's a helper api `lws_daemonize` built by default that does everything you
105need to daemonize well, including creating a lock file.  If you're making
106what's basically a daemon, just call this early in your init to fork to a
107headless background process and exit the starting process.
108
109Notice stdout, stderr, stdin are all redirected to /dev/null to enforce your
110daemon is headless, so you'll need to sort out alternative logging, by, eg,
111syslog via `lws_set_log_level(..., lwsl_emit_syslog)`.
112
113@section conns Maximum number of connections
114
115The maximum number of connections the library can deal with is decided when
116it starts by querying the OS to find out how many file descriptors it is
117allowed to open (1024 on Fedora for example).  It then allocates arrays that
118allow up to that many connections, minus whatever other file descriptors are
119in use by the user code.
120
121If you want to restrict that allocation, or increase it, you can use ulimit or
122similar to change the available number of file descriptors, and when restarted
123**libwebsockets** will adapt accordingly.
124
125@section peer_limits optional LWS_WITH_PEER_LIMITS
126
127If you select `LWS_WITH_PEER_LIMITS` at cmake, then lws will track peer IPs
128and monitor how many connections and ah resources they are trying to use
129at one time.  You can choose to limit these at context creation time, using
130`info.ip_limit_ah` and `info.ip_limit_wsi`.
131
132Note that although the ah limit is 'soft', ie, the connection will just wait
133until the IP is under the ah limit again before attaching a new ah, the
134wsi limit is 'hard', lws will drop any additional connections from the
135IP until it's under the limit again.
136
137If you use these limits, you should consider multiple clients may simultaneously
138try to access the site through NAT, etc.  So the limits should err on the side
139of being generous, while still making it impossible for one IP to exhaust
140all the server resources.
141
142@section evtloop Libwebsockets is singlethreaded
143
144Libwebsockets works in a serialized event loop, in a single thread.  It supports
145the default poll() backend, and libuv, libev, and libevent event loop
146libraries that also take this locking-free, nonblocking event loop approach that
147is not threadsafe.  There are several advantages to this technique, but one
148disadvantage, it doesn't integrate easily if there are multiple threads that
149want to use libwebsockets.
150
151However integration to multithreaded apps is possible if you follow some guidelines.
152
1531) Aside from two APIs, directly calling lws apis from other threads is not allowed.
154
1552) If you want to keep a list of live wsi, you need to use lifecycle callbacks on
156the protocol in the service thread to manage the list, with your own locking.
157Typically you use an ESTABLISHED callback to add ws wsi to your list and a CLOSED
158callback to remove them.
159
1603) LWS regulates your write activity by being able to let you know when you may
161write more on a connection.  That reflects the reality that you cannot succeed to
162send data to a peer that has no room for it, so you should not generate or buffer
163write data until you know the peer connection can take more.
164
165Other libraries pretend that the guy doing the writing is the boss who decides
166what happens, and absorb as much as you want to write to local buffering.  That does
167not scale to a lot of connections, because it will exhaust your memory and waste
168time copying data around in memory needlessly.
169
170The truth is the receiver, along with the network between you, is the boss who
171decides what will happen.  If he stops accepting data, no data will move.  LWS is
172designed to reflect that.
173
174If you have something to send, you call `lws_callback_on_writable()` on the
175connection, and when it is writeable, you will get a `LWS_CALLBACK_SERVER_WRITEABLE`
176callback, where you should generate the data to send and send it with `lws_write()`.
177
178You cannot send data using `lws_write()` outside of the WRITEABLE callback.
179
1804) For multithreaded apps, this corresponds to a need to be able to provoke the
181`lws_callback_on_writable()` action and to wake the service thread from its event
182loop wait (sleeping in `poll()` or `epoll()` or whatever).  The rules above
183mean directly sending data on the connection from another thread is out of the
184question.
185
186The only lws api that's safe to call from other thread contexts is `lws_cancel_service()`.
187This will take a platform-specific action to wake the lws event loop thread wait,
188either put a byte into a pipe2() the event loop is waiting on, or send a packet on
189a UDP socket pair that the event loop waits on.  When the wake is handled by the
190lws event loop thread, it will broadcast a `LWS_CALLBACK_EVENT_WAIT_CANCELLED`
191message to every vhost-protocol instantiation, so you can handle this callback,
192usually lock a shared data region, and if you see you need to write, call
193`lws_callback_on_writeable()` for the wsi(s) that need to write.
194
195There's no restriction on multiple threads calling `lws_cancel_service()`, it's
196unconditionally safe due to how it is implemented underneath.
197
1985) The obverse of this truism about the receiver being the boss is the case where
199we are receiving.  If we get into a situation we actually can't usefully
200receive any more, perhaps because we are passing the data on and the guy we want
201to send to can't receive any more, then we should "turn off RX" by using the
202RX flow control API, `lws_rx_flow_control(wsi, 0)`.  When something happens where we
203can accept more RX, (eg, we learn our onward connection is writeable) we can call
204it again to re-enable it on the incoming wsi.
205
206LWS stops calling back about RX immediately you use flow control to disable RX, it
207buffers the data internally if necessary.  So you will only see RX when you can
208handle it.  When flow control is disabled, LWS stops taking new data in... this makes
209the situation known to the sender by TCP "backpressure", the tx window fills and the
210sender finds he cannot write any more to the connection.
211
212See the mirror protocol implementations for example code.
213
214If you need to service other socket or file descriptors as well as the
215websocket ones, you can combine them together with the websocket ones
216in one poll loop, see "External Polling Loop support" below, and
217still do it all in one thread / process context.  If the need is less
218architectural, you can also create RAW mode client and serving sockets; this
219is how the lws plugin for the ssh server works.
220
221@section anonprot Working without a protocol name
222
223Websockets allows connections to negotiate without a protocol name...
224in that case by default it will bind to the first protocol in your
225vhost protocols[] array.
226
227You can tell the vhost to use a different protocol by attaching a
228pvo (per-vhost option) to the
229
230```
231/*
232 * this sets a per-vhost, per-protocol option name:value pair
233 * the effect is to set this protocol to be the default one for the vhost,
234 * ie, selected if no Protocol: header is sent with the ws upgrade.
235 */
236
237static const struct lws_protocol_vhost_options pvo_opt = {
238	NULL,
239	NULL,
240	"default",
241	"1"
242};
243
244static const struct lws_protocol_vhost_options pvo = {
245	NULL,
246	&pvo_opt,
247	"my-protocol",
248	""
249};
250
251...
252
253	context_info.pvo = &pvo;
254...
255
256```
257
258Will select "my-protocol" from your protocol list (even if it came
259in by plugin) as being the target of client connections that don't
260specify a protocol.
261
262@section closing Closing connections from the user side
263
264When you want to close a connection, you do it by returning `-1` from a
265callback for that connection.
266
267You can provoke a callback by calling `lws_callback_on_writable` on
268the wsi, then notice in the callback you want to close it and just return -1.
269But usually, the decision to close is made in a callback already and returning
270-1 is simple.
271
272If the socket knows the connection is dead, because the peer closed or there
273was an affirmitive network error like a FIN coming, then **libwebsockets**  will
274take care of closing the connection automatically.
275
276If you have a silently dead connection, it's possible to enter a state where
277the send pipe on the connection is choked but no ack will ever come, so the
278dead connection will never become writeable.  To cover that, you can use TCP
279keepalives (see later in this document) or pings.
280
281@section gzip Serving from inside a zip file
282
283Lws now supports serving gzipped files from inside a zip container.  Thanks to
284Per Bothner for contributing the code.
285
286This has the advtantage that if the client can accept GZIP encoding, lws can
287simply send the gzip-compressed file from inside the zip file with no further
288processing, saving time and bandwidth.
289
290In the case the client can't understand gzip compression, lws automatically
291decompressed the file and sends it normally.
292
293Clients with limited storage and RAM will find this useful; the memory needed
294for the inflate case is constrained so that only one input buffer at a time
295is ever in memory.
296
297To use this feature, ensure LWS_WITH_ZIP_FOPS is enabled at CMake.
298
299`libwebsockets-test-server-v2.0` includes a mount using this technology
300already, run that test server and navigate to http://localhost:7681/ziptest/candide.html
301
302This will serve the book Candide in html, together with two jpgs, all from
303inside a .zip file in /usr/[local/]share-libwebsockets-test-server/candide.zip
304
305Usage is otherwise automatic, if you arrange a mount that points to the zipfile,
306eg, "/ziptest" -> "mypath/test.zip", then URLs like `/ziptest/index.html` will be
307servied from `index.html` inside `mypath/test.zip`
308
309@section frags Fragmented messages
310
311To support fragmented messages you need to check for the final
312frame of a message with `lws_is_final_fragment`. This
313check can be combined with `libwebsockets_remaining_packet_payload`
314to gather the whole contents of a message, eg:
315
316```
317	    case LWS_CALLBACK_RECEIVE:
318	    {
319	        Client * const client = (Client *)user;
320	        const size_t remaining = lws_remaining_packet_payload(wsi);
321
322	        if (!remaining && lws_is_final_fragment(wsi)) {
323	            if (client->HasFragments()) {
324	                client->AppendMessageFragment(in, len, 0);
325	                in = (void *)client->GetMessage();
326	                len = client->GetMessageLength();
327	            }
328
329	            client->ProcessMessage((char *)in, len, wsi);
330	            client->ResetMessage();
331	        } else
332	            client->AppendMessageFragment(in, len, remaining);
333	    }
334	    break;
335```
336
337The test app libwebsockets-test-fraggle sources also show how to
338deal with fragmented messages.
339
340
341@section debuglog Debug Logging
342
343See ./READMEs/README.logging.md
344
345@section asan Building with ASAN
346
347Under GCC you can select for the build to be instrumented with the Address
348Sanitizer, using `cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_ASAN=1`.  LWS is routinely run during development with valgrind, but ASAN is capable of finding different issues at runtime, like operations which are not strictly defined in the C
349standard and depend on platform behaviours.
350
351Run your application like this
352
353```
354	$ sudo ASAN_OPTIONS=verbosity=2:halt_on_error=1  /usr/local/bin/lwsws
355```
356
357and attach gdb to catch the place it halts.
358
359@section extpoll External Polling Loop support
360
361**libwebsockets** maintains an internal `poll()` array for all of its
362sockets, but you can instead integrate the sockets into an
363external polling array.  That's needed if **libwebsockets** will
364cooperate with an existing poll array maintained by another
365server.
366
367Three callbacks `LWS_CALLBACK_ADD_POLL_FD`, `LWS_CALLBACK_DEL_POLL_FD`
368and `LWS_CALLBACK_CHANGE_MODE_POLL_FD` appear in the callback for protocol 0
369and allow interface code to manage socket descriptors in other poll loops.
370
371You can pass all pollfds that need service to `lws_service_fd()`, even
372if the socket or file does not belong to **libwebsockets** it is safe.
373
374If **libwebsocket** handled it, it zeros the pollfd `revents` field before returning.
375So you can let **libwebsockets** try and if `pollfd->revents` is nonzero on return,
376you know it needs handling by your code.
377
378Also note that when integrating a foreign event loop like libev or libuv where
379it doesn't natively use poll() semantics, and you must return a fake pollfd
380reflecting the real event:
381
382 - be sure you set .events to .revents value as well in the synthesized pollfd
383
384 - check the built-in support for the event loop if possible (eg, ./lib/libuv.c)
385   to see how it interfaces to lws
386
387 - use LWS_POLLHUP / LWS_POLLIN / LWS_POLLOUT from libwebsockets.h to avoid
388   losing windows compatibility
389
390You also need to take care about "forced service" somehow... these are cases
391where the network event was consumed, incoming data was all read, for example,
392but the work arising from it was not completed.  There will not be any more
393network event to trigger the remaining work, Eg, we read compressed data, but
394we did not use up all the decompressed data before returning to the event loop
395because we had to write some of it.
396
397Lws provides an API to determine if anyone is waiting for forced service,
398`lws_service_adjust_timeout(context, 1, tsi)`, normally tsi is 0.  If it returns
3990, then at least one connection has pending work you can get done by calling
400`lws_service_tsi(context, -1, tsi)`, again normally tsi is 0.
401
402For eg, the default poll() event loop, or libuv/ev/event, lws does this
403checking for you and handles it automatically.  But in the external polling
404loop case, you must do it explicitly.  Handling it after every normal service
405triggered by the external poll fd should be enough, since the situations needing
406it are initially triggered by actual network events.
407
408An example of handling it is shown in the test-server code specific to
409external polling.
410
411@section cpp Using with in c++ apps
412
413The library is ready for use by C++ apps.  You can get started quickly by
414copying the test server
415
416```
417	$ cp test-apps/test-server.c test.cpp
418```
419
420and building it in C++ like this
421
422```
423	$ g++ -DINSTALL_DATADIR=\"/usr/share\" -ocpptest test.cpp -lwebsockets
424```
425
426`INSTALL_DATADIR` is only needed because the test server uses it as shipped, if
427you remove the references to it in your app you don't need to define it on
428the g++ line either.
429
430
431@section headerinfo Availability of header information
432
433HTTP Header information is managed by a pool of "ah" structs.  These are a
434limited resource so there is pressure to free the headers and return the ah to
435the pool for reuse.
436
437For that reason header information on HTTP connections that get upgraded to
438websockets is lost after the ESTABLISHED callback.  Anything important that
439isn't processed by user code before then should be copied out for later.
440
441For HTTP connections that don't upgrade, header info remains available the
442whole time.
443
444@section http2compat Code Requirements for HTTP/2 compatibility
445
446Websocket connections only work over http/1, so there is nothing special to do
447when you want to enable -DLWS_WITH_HTTP2=1.
448
449The internal http apis already follow these requirements and are compatible with
450http/2 already.  So if you use stuff like mounts and serve stuff out of the
451filesystem, there's also nothing special to do.
452
453However if you are getting your hands dirty with writing response headers, or
454writing bulk data over http/2, you need to observe these rules so that it will
455work over both http/1.x and http/2 the same.
456
4571) LWS_PRE requirement applies on ALL lws_write().  For http/1, you don't have
458to take care of LWS_PRE for http data, since it is just sent straight out.
459For http/2, it will write up to LWS_PRE bytes behind the buffer start to create
460the http/2 frame header.
461
462This has implications if you treated the input buffer to lws_write() as const...
463it isn't any more with http/2, up to 9 bytes behind the buffer will be trashed.
464
4652) Headers are encoded using a sophisticated scheme in http/2.  The existing
466header access apis are already made compatible for incoming headers,
467for outgoing headers you must:
468
469 - observe the LWS_PRE buffer requirement mentioned above
470
471 - Use `lws_add_http_header_status()` to add the transaction status (200 etc)
472
473 - use lws apis `lws_add_http_header_by_name()` and `lws_add_http_header_by_token()`
474   to put the headers into the buffer (these will translate what is actually
475   written to the buffer depending on if the connection is in http/2 mode or not)
476
477 - use the `lws api lws_finalize_http_header()` api after adding the last
478   response header
479
480 - write the header using lws_write(..., `LWS_WRITE_HTTP_HEADERS`);
481
482 3) http/2 introduces per-stream transmit credit... how much more you can send
483 on a stream is decided by the peer.  You start off with some amount, as the
484 stream sends stuff lws will reduce your credit accordingly, when it reaches
485 zero, you must not send anything further until lws receives "more credit" for
486 that stream the peer.  Lws will suppress writable callbacks if you hit 0 until
487 more credit for the stream appears, and lws built-in file serving (via mounts
488 etc) already takes care of observing the tx credit restrictions.  However if
489 you write your own code that wants to send http data, you must consult the
490 `lws_get_peer_write_allowance()` api to find out the state of your tx credit.
491 For http/1, it will always return (size_t)-1, ie, no limit.
492
493 This is orthogonal to the question of how much space your local side's kernel
494 will make to buffer your send data on that connection.  So although the result
495 from `lws_get_peer_write_allowance()` is "how much you can send" logically,
496 and may be megabytes if the peer allows it, you should restrict what you send
497 at one time to whatever your machine will generally accept in one go, and
498 further reduce that amount if `lws_get_peer_write_allowance()` returns
499 something smaller.  If it returns 0, you should not consume or send anything
500 and return having asked for callback on writable, it will only come back when
501 more tx credit has arrived for your stream.
502
503 4) Header names with captital letters are illegal in http/2.  Header names in
504 http/1 are case insensitive.  So if you generate headers by name, change all
505 your header name strings to lower-case to be compatible both ways.
506
507 5) Chunked Transfer-encoding is illegal in http/2, http/2 peers will actively
508 reject it.  Lws takes care of removing the header and converting CGIs that
509 emit chunked into unchunked automatically for http/2 connections.
510
511If you follow these rules, your code will automatically work with both http/1.x
512and http/2.
513
514@section ka TCP Keepalive
515
516It is possible for a connection which is not being used to send to die
517silently somewhere between the peer and the side not sending.  In this case
518by default TCP will just not report anything and you will never get any more
519incoming data or sign the link is dead until you try to send.
520
521To deal with getting a notification of that situation, you can choose to
522enable TCP keepalives on all **libwebsockets** sockets, when you create the
523context.
524
525To enable keepalive, set the ka_time member of the context creation parameter
526struct to a nonzero value (in seconds) at context creation time.  You should
527also fill ka_probes and ka_interval in that case.
528
529With keepalive enabled, the TCP layer will send control packets that should
530stimulate a response from the peer without affecting link traffic.  If the
531response is not coming, the socket will announce an error at `poll()` forcing
532a close.
533
534Note that BSDs don't support keepalive time / probes / interval per-socket
535like Linux does.  On those systems you can enable keepalive by a nonzero
536value in `ka_time`, but the systemwide kernel settings for the time / probes/
537interval are used, regardless of what nonzero value is in `ka_time`.
538
539
540@section sslopt Optimizing SSL connections
541
542There's a member `ssl_cipher_list` in the `lws_context_creation_info` struct
543which allows the user code to restrict the possible cipher selection at
544context-creation time.
545
546You might want to look into that to stop the ssl peers selecting a cipher which
547is too computationally expensive.  To use it, point it to a string like
548
549	`"RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL"`
550
551if left `NULL`, then the "DEFAULT" set of ciphers are all possible to select.
552
553You can also set it to `"ALL"` to allow everything (including insecure ciphers).
554
555
556@section sslcerts Passing your own cert information direct to SSL_CTX
557
558For most users it's enough to pass the SSL certificate and key information by
559giving filepaths to the info.ssl_cert_filepath and info.ssl_private_key_filepath
560members when creating the vhost.
561
562If you want to control that from your own code instead, you can do so by leaving
563the related info members NULL, and setting the info.options flag
564LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX at vhost creation time.  That will create
565the vhost SSL_CTX without any certificate, and allow you to use the callback
566LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS to add your certificate to
567the SSL_CTX directly.  The vhost SSL_CTX * is in the user parameter in that
568callback.
569
570@section clientasync Async nature of client connections
571
572When you call `lws_client_connect_info(..)` and get a `wsi` back, it does not
573mean your connection is active.  It just means it started trying to connect.
574
575Your client connection is actually active only when you receive
576`LWS_CALLBACK_CLIENT_ESTABLISHED` for it.
577
578There's a 5 second timeout for the connection, and it may give up or die for
579other reasons, if any of that happens you'll get a
580`LWS_CALLBACK_CLIENT_CONNECTION_ERROR` callback on protocol 0 instead for the
581`wsi`.
582
583After attempting the connection and getting back a non-`NULL` `wsi` you should
584loop calling `lws_service()` until one of the above callbacks occurs.
585
586As usual, see [test-client.c](../test-apps/test-client.c) for example code.
587
588Notice that the client connection api tries to progress the connection
589somewhat before returning.  That means it's possible to get callbacks like
590CONNECTION_ERROR on the new connection before your user code had a chance to
591get the wsi returned to identify it (in fact if the connection did fail early,
592NULL will be returned instead of the wsi anyway).
593
594To avoid that problem, you can fill in `pwsi` in the client connection info
595struct to point to a struct lws that get filled in early by the client
596connection api with the related wsi.  You can then check for that in the
597callback to confirm the identity of the failing client connection.
598
599
600@section fileapi Lws platform-independent file access apis
601
602lws now exposes his internal platform file abstraction in a way that can be
603both used by user code to make it platform-agnostic, and be overridden or
604subclassed by user code.  This allows things like handling the URI "directory
605space" as a virtual filesystem that may or may not be backed by a regular
606filesystem.  One example use is serving files from inside large compressed
607archive storage without having to unpack anything except the file being
608requested.
609
610The test server shows how to use it, basically the platform-specific part of
611lws prepares a file operations structure that lives in the lws context.
612
613The user code can get a pointer to the file operations struct
614
615```
616	LWS_VISIBLE LWS_EXTERN struct lws_plat_file_ops *
617		`lws_get_fops`(struct lws_context *context);
618```
619
620and then can use helpers to also leverage these platform-independent
621file handling apis
622
623```
624	lws_fop_fd_t
625	`lws_plat_file_open`(struct lws_plat_file_ops *fops, const char *filename,
626			   lws_fop_flags_t *flags)
627	int
628	`lws_plat_file_close`(lws_fop_fd_t fop_fd)
629
630	unsigned long
631	`lws_plat_file_seek_cur`(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
632
633	int
634	`lws_plat_file_read`(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
635		   uint8_t *buf, lws_filepos_t len)
636
637	int
638	`lws_plat_file_write`(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
639		   uint8_t *buf, lws_filepos_t len )
640```
641
642Generic helpers are provided which provide access to generic fops information or
643call through to the above fops
644
645```
646lws_filepos_t
647lws_vfs_tell(lws_fop_fd_t fop_fd);
648
649lws_filepos_t
650lws_vfs_get_length(lws_fop_fd_t fop_fd);
651
652uint32_t
653lws_vfs_get_mod_time(lws_fop_fd_t fop_fd);
654
655lws_fileofs_t
656lws_vfs_file_seek_set(lws_fop_fd_t fop_fd, lws_fileofs_t offset);
657
658lws_fileofs_t
659lws_vfs_file_seek_end(lws_fop_fd_t fop_fd, lws_fileofs_t offset);
660```
661
662
663The user code can also override or subclass the file operations, to either
664wrap or replace them.  An example is shown in test server.
665
666### Changes from v2.1 and before fops
667
668There are several changes:
669
6701) Pre-2.2 fops directly used platform file descriptors.  Current fops returns and accepts a wrapper type lws_fop_fd_t which is a pointer to a malloc'd struct containing information specific to the filesystem implementation.
671
6722) Pre-2.2 fops bound the fops to a wsi.  This is completely removed, you just give a pointer to the fops struct that applies to this file when you open it.  Afterwards, the operations in the fops just need the lws_fop_fd_t returned from the open.
673
6743) Everything is wrapped in typedefs.  See lws-plat-unix.c for examples of how to implement.
675
6764) Position in the file, File Length, and a copy of Flags left after open are now generically held in the fop_fd.
677VFS implementation must set and manage this generic information now.  See the implementations in lws-plat-unix.c for
678examples.
679
6805) The file length is no longer set at a pointer provided by the open() fop.  The api `lws_vfs_get_length()` is provided to
681get the file length after open.
682
6836) If your file namespace is virtual, ie, is not reachable by platform fops directly, you must set LWS_FOP_FLAG_VIRTUAL
684on the flags during open.
685
6867) There is an optional `mod_time` uint32_t member in the generic fop_fd.  If you are able to set it during open, you
687should indicate it by setting `LWS_FOP_FLAG_MOD_TIME_VALID` on the flags.
688
689@section rawfd RAW file descriptor polling
690
691LWS allows you to include generic platform file descriptors in the lws service / poll / event loop.
692
693Open your fd normally and then
694
695```
696	lws_sock_file_fd_type u;
697
698	u.filefd = your_open_file_fd;
699
700	if (!lws_adopt_descriptor_vhost(vhost, 0, u,
701					"protocol-name-to-bind-to",
702					optional_wsi_parent_or_NULL)) {
703		// failed
704	}
705
706	// OK
707```
708
709A wsi is created for the file fd that acts like other wsi, you will get these
710callbacks on the named protocol
711
712```
713	LWS_CALLBACK_RAW_ADOPT_FILE
714	LWS_CALLBACK_RAW_RX_FILE
715	LWS_CALLBACK_RAW_WRITEABLE_FILE
716	LWS_CALLBACK_RAW_CLOSE_FILE
717```
718
719starting with LWS_CALLBACK_RAW_ADOPT_FILE.
720
721The minimal example `raw/minimal-raw-file` demonstrates how to use it.
722
723`protocol-lws-raw-test` plugin also provides a method for testing this with
724`libwebsockets-test-server-v2.0`:
725
726The plugin creates a FIFO on your system called "/tmp/lws-test-raw"
727
728You can feed it data through the FIFO like this
729
730```
731  $ sudo sh -c "echo hello > /tmp/lws-test-raw"
732```
733
734This plugin simply prints the data.  But it does it through the lws event
735loop / service poll.
736
737@section rawsrvsocket RAW server socket descriptor polling
738
739You can also enable your vhost to accept RAW socket connections, in addition to
740HTTP[s] and WS[s].  If the first bytes written on the connection are not a
741valid HTTP method, then the connection switches to RAW mode.
742
743This is disabled by default, you enable it by setting the `.options` flag
744LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG, and setting
745`.listen_accept_role` to `"raw-skt"` when creating the vhost.
746
747RAW mode socket connections receive the following callbacks
748
749```
750	LWS_CALLBACK_RAW_ADOPT
751	LWS_CALLBACK_RAW_RX
752	LWS_CALLBACK_RAW_WRITEABLE
753	LWS_CALLBACK_RAW_CLOSE
754```
755
756You can control which protocol on your vhost handles these RAW mode
757incoming connections by setting the vhost info struct's `.listen_accept_protocol`
758to the vhost protocol name to use.
759
760`protocol-lws-raw-test` plugin provides a method for testing this with
761`libwebsockets-test-server-v2.0`:
762
763Run libwebsockets-test-server-v2.0 and connect to it by telnet, eg
764
765```
766    $ telnet 127.0.0.1 7681
767```
768
769type something that isn't a valid HTTP method and enter, before the
770connection times out.  The connection will switch to RAW mode using this
771protocol, and pass the unused rx as a raw RX callback.
772
773The test protocol echos back what was typed on telnet to telnet.
774
775@section rawclientsocket RAW client socket descriptor polling
776
777You can now also open RAW socket connections in client mode.
778
779Follow the usual method for creating a client connection, but set the
780`info.method` to "RAW".  When the connection is made, the wsi will be
781converted to RAW mode and operate using the same callbacks as the
782server RAW sockets described above.
783
784The libwebsockets-test-client supports this using raw:// URLS.  To
785test, open a netcat listener in one window
786
787```
788 $ nc -l 9999
789```
790
791and in another window, connect to it using the test client
792
793```
794 $ libwebsockets-test-client raw://127.0.0.1:9999
795```
796
797The connection should succeed, and text typed in the netcat window (including a CRLF)
798will be received in the client.
799
800@section rawudp RAW UDP socket integration
801
802Lws provides an api to create, optionally bind, and adopt a RAW UDP
803socket (RAW here means an uninterpreted normal UDP socket, not a
804"raw socket").
805
806```
807LWS_VISIBLE LWS_EXTERN struct lws *
808lws_create_adopt_udp(struct lws_vhost *vhost, int port, int flags,
809		     const char *protocol_name, struct lws *parent_wsi);
810```
811
812`flags` should be `LWS_CAUDP_BIND` if the socket will receive packets.
813
814The callbacks `LWS_CALLBACK_RAW_ADOPT`, `LWS_CALLBACK_RAW_CLOSE`,
815`LWS_CALLBACK_RAW_RX` and `LWS_CALLBACK_RAW_WRITEABLE` apply to the
816wsi.  But UDP is different than TCP in some fundamental ways.
817
818For receiving on a UDP connection, data becomes available at
819`LWS_CALLBACK_RAW_RX` as usual, but because there is no specific
820connection with UDP, it is necessary to also get the source address of
821the data separately, using `struct lws_udp * lws_get_udp(wsi)`.
822You should take a copy of the `struct lws_udp` itself (not the
823pointer) and save it for when you want to write back to that peer.
824
825Writing is also a bit different for UDP.  By default, the system has no
826idea about the receiver state and so asking for a `callback_on_writable()`
827always believes that the socket is writeable... the callback will
828happen next time around the event loop.
829
830With UDP, there is no single "connection".  You need to write with sendto() and
831direct the packets to a specific destination.  To return packets to a
832peer who sent something earlier and you copied his `struct lws_udp`, you
833use the .sa and .salen members as the last two parameters of the sendto().
834
835The kernel may not accept to buffer / write everything you wanted to send.
836So you are responsible to watch the result of sendto() and resend the
837unsent part next time (which may involve adding new protocol headers to
838the remainder depending on what you are doing).
839
840@section ecdh ECDH Support
841
842ECDH Certs are now supported.  Enable the CMake option
843
844	cmake .. -DLWS_SSL_SERVER_WITH_ECDH_CERT=1
845
846**and** the info->options flag
847
848	LWS_SERVER_OPTION_SSL_ECDH
849
850to build in support and select it at runtime.
851
852@section sslinfo SSL info callbacks
853
854OpenSSL allows you to receive callbacks for various events defined in a
855bitmask in openssl/ssl.h.  The events include stuff like TLS Alerts.
856
857By default, lws doesn't register for these callbacks.
858
859However if you set the info.ssl_info_event_mask to nonzero (ie, set some
860of the bits in it like `SSL_CB_ALERT` at vhost creation time, then
861connections to that vhost will call back using LWS_CALLBACK_SSL_INFO
862for the wsi, and the `in` parameter will be pointing to a struct of
863related args:
864
865```
866struct lws_ssl_info {
867	int where;
868	int ret;
869};
870```
871
872The default callback handler in lws has a handler for LWS_CALLBACK_SSL_INFO
873which prints the related information,  You can test it using the switch
874-S -s  on `libwebsockets-test-server-v2.0`.
875
876Returning nonzero from the callback will close the wsi.
877
878@section smp SMP / Multithreaded service
879
880SMP support is integrated into LWS without any internal threading.  It's
881very simple to use, libwebsockets-test-server-pthread shows how to do it,
882use -j n argument there to control the number of service threads up to 32.
883
884Two new members are added to the info struct
885
886	unsigned int count_threads;
887	unsigned int fd_limit_per_thread;
888
889leave them at the default 0 to get the normal singlethreaded service loop.
890
891Set count_threads to n to tell lws you will have n simultaneous service threads
892operating on the context.
893
894There is still a single listen socket on one port, no matter how many
895service threads.
896
897When a connection is made, it is accepted by the service thread with the least
898connections active to perform load balancing.
899
900The user code is responsible for spawning n threads running the service loop
901associated to a specific tsi (Thread Service Index, 0 .. n - 1).  See
902the libwebsockets-test-server-pthread for how to do.
903
904If you leave fd_limit_per_thread at 0, then the process limit of fds is shared
905between the service threads; if you process was allowed 1024 fds overall then
906each thread is limited to 1024 / n.
907
908You can set fd_limit_per_thread to a nonzero number to control this manually, eg
909the overall supported fd limit is less than the process allowance.
910
911You can control the context basic data allocation for multithreading from Cmake
912using -DLWS_MAX_SMP=, if not given it's set to 1.  The serv_buf allocation
913for the threads (currently 4096) is made at runtime only for active threads.
914
915Because lws will limit the requested number of actual threads supported
916according to LWS_MAX_SMP, there is an api lws_get_count_threads(context) to
917discover how many threads were actually allowed when the context was created.
918
919See the test-server-pthreads.c sample for how to use.
920
921@section smplocking SMP Locking Helpers
922
923Lws provide a set of pthread mutex helpers that reduce to no code or
924variable footprint in the case that LWS_MAX_SMP == 1.
925
926Define your user mutex like this
927
928```
929	lws_pthread_mutex(name);
930```
931
932If LWS_MAX_SMP > 1, this produces `pthread_mutex_t name;`.  In the case
933LWS_MAX_SMP == 1, it produces nothing.
934
935Likewise these helpers for init, destroy, lock and unlock
936
937
938```
939	void lws_pthread_mutex_init(pthread_mutex_t *lock)
940	void lws_pthread_mutex_destroy(pthread_mutex_t *lock)
941	void lws_pthread_mutex_lock(pthread_mutex_t *lock)
942	void lws_pthread_mutex_unlock(pthread_mutex_t *lock)
943```
944
945resolve to nothing if LWS_MAX_SMP == 1, otherwise produce the equivalent
946pthread api.
947
948pthreads is required in lws only if LWS_MAX_SMP > 1.
949
950
951@section libevuv libev / libuv / libevent support
952
953You can select either or both
954
955	-DLWS_WITH_LIBEV=1
956	-DLWS_WITH_LIBUV=1
957	-DLWS_WITH_LIBEVENT=1
958
959at cmake configure-time.  The user application may use one of the
960context init options flags
961
962	LWS_SERVER_OPTION_LIBEV
963	LWS_SERVER_OPTION_LIBUV
964	LWS_SERVER_OPTION_LIBEVENT
965
966to indicate it will use one of the event libraries at runtime.
967
968libev and libevent headers conflict, they both define critical constants like
969EV_READ to different values.  Attempts to discuss clearing that up with both
970libevent and libev did not get anywhere useful.  Therefore CMakeLists.txt will
971error out if you enable both LWS_WITH_LIBEV and LWS_WITH_LIBEVENT.
972
973In addition depending on libev / compiler version, building anything with libev
974apis using gcc may blow strict alias warnings (which are elevated to errors in
975lws).  I did some googling at found these threads related to it, the issue goes
976back at least to 2010 on and off
977
978https://github.com/redis/hiredis/issues/434
979https://bugs.gentoo.org/show_bug.cgi?id=615532
980http://lists.schmorp.de/pipermail/libev/2010q1/000916.html
981http://lists.schmorp.de/pipermail/libev/2010q1/000920.html
982http://lists.schmorp.de/pipermail/libev/2010q1/000923.html
983
984We worked around this problem by disabling -Werror on the parts of lws that
985use libev.  FWIW as of Dec 2019 using Fedora 31 libev 4.27.1 and its gcc 9.2.1
986doesn't seem to trigger the problem even without the workaround.
987
988For these reasons and the response I got trying to raise these issues with
989them, if you have a choice about event loop, I would gently encourage you
990to avoid libev.  Where lws uses an event loop itself, eg in lwsws, we use
991libuv.
992
993@section extopts Extension option control from user code
994
995User code may set per-connection extension options now, using a new api
996`lws_set_extension_option()`.
997
998This should be called from the ESTABLISHED callback like this
999```
1000	 lws_set_extension_option(wsi, "permessage-deflate",
1001	                          "rx_buf_size", "12"); /* 1 << 12 */
1002```
1003
1004If the extension is not active (missing or not negotiated for the
1005connection, or extensions are disabled on the library) the call is
1006just returns -1.  Otherwise the connection's extension has its
1007named option changed.
1008
1009The extension may decide to alter or disallow the change, in the
1010example above permessage-deflate restricts the size of his rx
1011output buffer also considering the protocol's rx_buf_size member.
1012
1013
1014@section httpsclient Client connections as HTTP[S] rather than WS[S]
1015
1016You may open a generic http client connection using the same
1017struct lws_client_connect_info used to create client ws[s]
1018connections.
1019
1020To stay in http[s], set the optional info member "method" to
1021point to the string "GET" instead of the default NULL.
1022
1023After the server headers are processed, when payload from the
1024server is available the callback LWS_CALLBACK_RECEIVE_CLIENT_HTTP
1025will be made.
1026
1027You can choose whether to process the data immediately, or
1028queue a callback when an outgoing socket is writeable to provide
1029flow control, and process the data in the writable callback.
1030
1031Either way you use the api `lws_http_client_read()` to access the
1032data, eg
1033
1034```
1035	case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
1036		{
1037			char buffer[1024 + LWS_PRE];
1038			char *px = buffer + LWS_PRE;
1039			int lenx = sizeof(buffer) - LWS_PRE;
1040
1041			lwsl_notice("LWS_CALLBACK_RECEIVE_CLIENT_HTTP\n");
1042
1043			/*
1044			 * Often you need to flow control this by something
1045			 * else being writable.  In that case call the api
1046			 * to get a callback when writable here, and do the
1047			 * pending client read in the writeable callback of
1048			 * the output.
1049			 */
1050			if (lws_http_client_read(wsi, &px, &lenx) < 0)
1051				return -1;
1052			while (lenx--)
1053				putchar(*px++);
1054		}
1055		break;
1056```
1057
1058Notice that if you will use SSL client connections on a vhost, you must
1059prepare the client SSL context for the vhost after creating the vhost, since
1060this is not normally done if the vhost was set up to listen / serve.  Call
1061the api lws_init_vhost_client_ssl() to also allow client SSL on the vhost.
1062
1063@section clipipe Pipelining Client Requests to same host
1064
1065If you are opening more client requests to the same host and port, you
1066can give the flag LCCSCF_PIPELINE on `info.ssl_connection` to indicate
1067you wish to pipeline them.
1068
1069Without the flag, the client connections will occur concurrently using a
1070socket and tls wrapper if requested for each connection individually.
1071That is fast, but resource-intensive.
1072
1073With the flag, lws will queue subsequent client connections on the first
1074connection to the same host and port.  When it has confirmed from the
1075first connection that pipelining / keep-alive is supported by the server,
1076it lets the queued client pipeline connections send their headers ahead
1077of time to create a pipeline of requests on the server side.
1078
1079In this way only one tcp connection and tls wrapper is required to transfer
1080all the transactions sequentially.  It takes a little longer but it
1081can make a significant difference to resources on both sides.
1082
1083If lws learns from the first response header that keepalive is not possible,
1084then it marks itself with that information and detaches any queued clients
1085to make their own individual connections as a fallback.
1086
1087Lws can also intelligently combine multiple ongoing client connections to
1088the same host and port into a single http/2 connection with multiple
1089streams if the server supports it.
1090
1091Unlike http/1 pipelining, with http/2 the client connections all occur
1092simultaneously using h2 stream multiplexing inside the one tcp + tls
1093connection.
1094
1095You can turn off the h2 client support either by not building lws with
1096`-DLWS_WITH_HTTP2=1` or giving the `LCCSCF_NOT_H2` flag in the client
1097connection info struct `ssl_connection` member.
1098
1099@section vhosts Using lws vhosts
1100
1101If you set LWS_SERVER_OPTION_EXPLICIT_VHOSTS options flag when you create
1102your context, it won't create a default vhost using the info struct
1103members for compatibility.  Instead you can call lws_create_vhost()
1104afterwards to attach one or more vhosts manually.
1105
1106```
1107	LWS_VISIBLE struct lws_vhost *
1108	lws_create_vhost(struct lws_context *context,
1109			 struct lws_context_creation_info *info);
1110```
1111
1112lws_create_vhost() uses the same info struct as lws_create_context(),
1113it ignores members related to context and uses the ones meaningful
1114for vhost (marked with VH in libwebsockets.h).
1115
1116```
1117	struct lws_context_creation_info {
1118		int port;					/* VH */
1119		const char *iface;				/* VH */
1120		const struct lws_protocols *protocols;		/* VH */
1121		const struct lws_extension *extensions;		/* VH */
1122	...
1123```
1124
1125When you attach the vhost, if the vhost's port already has a listen socket
1126then both vhosts share it and use SNI (is SSL in use) or the Host: header
1127from the client to select the right one.  Or if no other vhost already
1128listening the a new listen socket is created.
1129
1130There are some new members but mainly it's stuff you used to set at
1131context creation time.
1132
1133
1134@section sni How lws matches hostname or SNI to a vhost
1135
1136LWS first strips any trailing :port number.
1137
1138Then it tries to find an exact name match for a vhost listening on the correct
1139port, ie, if SNI or the Host: header provided abc.com:1234, it will match on a
1140vhost named abc.com that is listening on port 1234.
1141
1142If there is no exact match, lws will consider wildcard matches, for example
1143if cats.abc.com:1234 is provided by the client by SNI or Host: header, it will
1144accept a vhost "abc.com" listening on port 1234.  If there was a better, exact,
1145match, it will have been chosen in preference to this.
1146
1147Connections with SSL will still have the client go on to check the
1148certificate allows wildcards and error out if not.
1149
1150
1151
1152@section mounts Using lws mounts on a vhost
1153
1154The last argument to lws_create_vhost() lets you associate a linked
1155list of lws_http_mount structures with that vhost's URL 'namespace', in
1156a similar way that unix lets you mount filesystems into areas of your /
1157filesystem how you like and deal with the contents transparently.
1158
1159```
1160	struct lws_http_mount {
1161		struct lws_http_mount *mount_next;
1162		const char *mountpoint; /* mountpoint in http pathspace, eg, "/" */
1163		const char *origin; /* path to be mounted, eg, "/var/www/warmcat.com" */
1164		const char *def; /* default target, eg, "index.html" */
1165
1166		struct lws_protocol_vhost_options *cgienv;
1167
1168		int cgi_timeout;
1169		int cache_max_age;
1170
1171		unsigned int cache_reusable:1;
1172		unsigned int cache_revalidate:1;
1173		unsigned int cache_intermediaries:1;
1174
1175		unsigned char origin_protocol;
1176		unsigned char mountpoint_len;
1177	};
1178```
1179
1180The last mount structure should have a NULL mount_next, otherwise it should
1181point to the 'next' mount structure in your list.
1182
1183Both the mount structures and the strings must persist until the context is
1184destroyed, since they are not copied but used in place.
1185
1186`.origin_protocol` should be one of
1187
1188```
1189	enum {
1190		LWSMPRO_HTTP,
1191		LWSMPRO_HTTPS,
1192		LWSMPRO_FILE,
1193		LWSMPRO_CGI,
1194		LWSMPRO_REDIR_HTTP,
1195		LWSMPRO_REDIR_HTTPS,
1196		LWSMPRO_CALLBACK,
1197	};
1198```
1199
1200 - LWSMPRO_FILE is used for mapping url namespace to a filesystem directory and
1201serve it automatically.
1202
1203 - LWSMPRO_CGI associates the url namespace with the given CGI executable, which
1204runs when the URL is accessed and the output provided to the client.
1205
1206 - LWSMPRO_REDIR_HTTP and LWSMPRO_REDIR_HTTPS auto-redirect clients to the given
1207origin URL.
1208
1209 - LWSMPRO_CALLBACK causes the http connection to attach to the callback
1210associated with the named protocol (which may be a plugin).
1211
1212
1213@section mountcallback Operation of LWSMPRO_CALLBACK mounts
1214
1215The feature provided by CALLBACK type mounts is binding a part of the URL
1216namespace to a named protocol callback handler.
1217
1218This allows protocol plugins to handle areas of the URL namespace.  For example
1219in test-server-v2.0.c, the URL area "/formtest" is associated with the plugin
1220providing "protocol-post-demo" like this
1221
1222```
1223	static const struct lws_http_mount mount_post = {
1224		NULL,		/* linked-list pointer to next*/
1225		"/formtest",		/* mountpoint in URL namespace on this vhost */
1226		"protocol-post-demo",	/* handler */
1227		NULL,	/* default filename if none given */
1228		NULL,
1229		0,
1230		0,
1231		0,
1232		0,
1233		0,
1234		LWSMPRO_CALLBACK,	/* origin points to a callback */
1235		9,			/* strlen("/formtest"), ie length of the mountpoint */
1236	};
1237```
1238
1239Client access to /formtest[anything] will be passed to the callback registered
1240with the named protocol, which in this case is provided by a protocol plugin.
1241
1242Access by all methods, eg, GET and POST are handled by the callback.
1243
1244protocol-post-demo deals with accepting and responding to the html form that
1245is in the test server HTML.
1246
1247When a connection accesses a URL related to a CALLBACK type mount, the
1248connection protocol is changed until the next access on the connection to a
1249URL outside the same CALLBACK mount area.  User space on the connection is
1250arranged to be the size of the new protocol user space allocation as given in
1251the protocol struct.
1252
1253This allocation is only deleted / replaced when the connection accesses a
1254URL region with a different protocol (or the default protocols[0] if no
1255CALLBACK area matches it).
1256
1257This "binding connection to a protocol" lifecycle in managed by
1258`LWS_CALLBACK_HTTP_BIND_PROTOCOL` and `LWS_CALLBACK_HTTP_DROP_PROTOCOL`.
1259Because of HTTP/1.1 connection pipelining, one connection may perform
1260many transactions, each of which may map to different URLs and need
1261binding to different protocols.  So these messages are used to
1262create the binding of the wsi to your protocol including any
1263allocations, and to destroy the binding, at which point you should
1264destroy any related allocations.
1265
1266@section BINDTODEV SO_BIND_TO_DEVICE
1267
1268The .bind_iface flag in the context / vhost creation struct lets you
1269declare that you want all traffic for listen and transport on that
1270vhost to be strictly bound to the network interface named in .iface.
1271
1272This Linux-only feature requires SO_BIND_TO_DEVICE, which in turn
1273requires CAP_NET_RAW capability... root has this capability.
1274
1275However this feature needs to apply the binding also to accepted
1276sockets during normal operation, which implies the server must run
1277the whole time as root.
1278
1279You can avoid this by using the Linux capabilities feature to have
1280the unprivileged user inherit just the CAP_NET_RAW capability.
1281
1282You can confirm this with the test server
1283
1284
1285```
1286 $ sudo /usr/local/bin/libwebsockets-test-server -u agreen -i eno1 -k
1287```
1288
1289The part that ensures the capability is inherited by the unprivileged
1290user is
1291
1292```
1293#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
1294                        info.caps[0] = CAP_NET_RAW;
1295                        info.count_caps = 1;
1296#endif
1297```
1298
1299
1300@section dim Dimming webpage when connection lost
1301
1302The lws test plugins' html provides useful feedback on the webpage about if it
1303is still connected to the server, by greying out the page if not.  You can
1304also add this to your own html easily
1305
1306 - include lws-common.js from your HEAD section
1307
1308   \<script src="/lws-common.js">\</script>
1309
1310 - dim the page during initialization, in a script section on your page
1311
1312   lws_gray_out(true,{'zindex':'499'});
1313
1314 - in your ws onOpen(), remove the dimming
1315
1316   lws_gray_out(false);
1317
1318 - in your ws onClose(), reapply the dimming
1319
1320   lws_gray_out(true,{'zindex':'499'});
1321
1322@section errstyle Styling http error pages
1323
1324In the code, http errors should be handled by `lws_return_http_status()`.
1325
1326There are basically two ways... the vhost can be told to redirect to an "error
1327page" URL in response to specifically a 404... this is controlled by the
1328context / vhost info struct (`struct lws_context_creation_info`) member
1329`.error_document_404`... if non-null the client is redirected to this string.
1330
1331If it wasn't redirected, then the response code html is synthesized containing
1332the user-selected text message and attempts to pull in `/error.css` for styling.
1333
1334If this file exists, it can be used to style the error page.  See
1335https://libwebsockets.org/git/badrepo for an example of what can be done (
1336and https://libwebsockets.org/error.css for the corresponding css).
1337
1338