in use by the user code.
If you want to restrict that allocation, or increase it, you can use ulimit or
-similar to change the avaiable number of file descriptors, and when restarted
+similar to change the available number of file descriptors, and when restarted
**libwebsockets** will adapt accordingly.
dead connection will never become writeable. To cover that, you can use TCP
keepalives (see later in this document) or pings.
+@section gzip Serving from inside a zip file
+
+Lws now supports serving gzipped files from inside a zip container. Thanks to
+Per Bothner for contributing the code.
+
+This has the advtantage that if the client can accept GZIP encoding, lws can
+simply send the gzip-compressed file from inside the zip file with no further
+processing, saving time and bandwidth.
+
+In the case the client can't understand gzip compression, lws automatically
+decompressed the file and sends it normally.
+
+Clients with limited storage and RAM will find this useful; the memory needed
+for the inflate case is constrained so that only one input buffer at a time
+is ever in memory.
+
+To use this feature, ensure LWS_WITH_ZIP_FOPS is enabled at CMake (it is by
+default).
+
+`libwebsockets-test-server-v2.0` includes a mount using this technology
+already, run that test server and navigate to http://localhost:7681/ziptest/candide.html
+
+This will serve the book Candide in html, together with two jpgs, all from
+inside a .zip file in /usr/[local/]share-libwebsockets-test-server/candide.zip
+
+Usage is otherwise automatic, if you arrange a mount that points to the zipfile,
+eg, "/ziptest" -> "mypath/test.zip", then URLs like `/ziptest/index.html` will be
+servied from `index.html` inside `mypath/test.zip`
@section frags Fragmented messages
file handling apis
```
- static inline lws_filefd_type
- `lws_plat_file_open`(struct lws *wsi, const char *filename, unsigned long *filelen, int flags)
+ lws_fop_fd_t
+ `lws_plat_file_open`(struct lws_plat_file_ops *fops, const char *filename,
+ lws_fop_flags_t *flags)
+ int
+ `lws_plat_file_close`(lws_fop_fd_t fop_fd)
+
+ unsigned long
+ `lws_plat_file_seek_cur`(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
+
+ int
+ `lws_plat_file_read`(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
+ uint8_t *buf, lws_filepos_t len)
+
+ int
+ `lws_plat_file_write`(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
+ uint8_t *buf, lws_filepos_t len )
+```
- static inline int
- `lws_plat_file_close`(struct lws *wsi, lws_filefd_type fd)
+Generic helpers are provided which provide access to generic fops information or
+call through to the above fops
+
+```
+lws_filepos_t
+lws_vfs_tell(lws_fop_fd_t fop_fd);
- static inline unsigned long
- `lws_plat_file_seek_cur`(struct lws *wsi, lws_filefd_type fd, long offset_from_cur_pos)
+lws_filepos_t
+lws_vfs_get_length(lws_fop_fd_t fop_fd);
- static inline int
- `lws_plat_file_read`(struct lws *wsi, lws_filefd_type fd, unsigned long *amount, unsigned char *buf, unsigned long len)
+uint32_t
+lws_vfs_get_mod_time(lws_fop_fd_t fop_fd);
- static inline int
- `lws_plat_file_write`(struct lws *wsi, lws_filefd_type fd, unsigned long *amount, unsigned char *buf, unsigned long len)
+lws_fileofs_t
+lws_vfs_file_seek_set(lws_fop_fd_t fop_fd, lws_fileofs_t offset);
+
+lws_fileofs_t
+lws_vfs_file_seek_end(lws_fop_fd_t fop_fd, lws_fileofs_t offset);
```
+
The user code can also override or subclass the file operations, to either
wrap or replace them. An example is shown in test server.
+### Changes from v2.1 and before fops
+
+There are several changes:
+
+1) 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.
+
+2) 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.
+
+3) Everything is wrapped in typedefs. See lws-plat-unix.c for examples of how to implement.
+
+4) Position in the file, File Length, and a copy of Flags left after open are now generically held in the fop_fd.
+VFS implementation must set and manage this generic information now. See the implementations in lws-plat-unix.c for
+examples.
+
+5) The file length is no longer set at a pointer provided by the open() fop. The api `lws_vfs_get_length()` is provided to
+get the file length after open.
+
+6) If your file namespace is virtual, ie, is not reachable by platform fops directly, you must set LWS_FOP_FLAG_VIRTUAL
+on the flags during open.
+
+7) There is an optional `mod_time` uint32_t member in the generic fop_fd. If you are able to set it during open, you
+should indicate it by setting `LWS_FOP_FLAG_MOD_TIME_VALID` on the flags.
+
+@section rawfd RAW file descriptor polling
+
+LWS allows you to include generic platform file descriptors in the lws service / poll / event loop.
+
+Open your fd normally and then
+
+```
+ lws_sock_file_fd_type u;
+
+ u.filefd = your_open_file_fd;
+
+ if (!lws_adopt_descriptor_vhost(vhost, 0, u,
+ "protocol-name-to-bind-to",
+ optional_wsi_parent_or_NULL)) {
+ // failed
+ }
+
+ // OK
+```
+
+A wsi is created for the file fd that acts like other wsi, you will get these
+callbacks on the named protocol
+
+```
+ LWS_CALLBACK_RAW_ADOPT_FILE
+ LWS_CALLBACK_RAW_RX_FILE
+ LWS_CALLBACK_RAW_WRITEABLE_FILE
+ LWS_CALLBACK_RAW_CLOSE_FILE
+```
+
+starting with LWS_CALLBACK_RAW_ADOPT_FILE.
+
+`protocol-lws-raw-test` plugin provides a method for testing this with
+`libwebsockets-test-server-v2.0`:
+
+The plugin creates a FIFO on your system called "/tmp/lws-test-raw"
+
+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.
+
+@section rawsrvsocket RAW server socket descriptor polling
+
+You can also enable your vhost to accept RAW socket connections, in addition to
+HTTP[s] and WS[s]. If the first bytes written on the connection are not a
+valid HTTP method, then the connection switches to RAW mode.
+
+This is disabled by default, you enable it by setting the `.options` flag
+LWS_SERVER_OPTION_FALLBACK_TO_RAW when creating the vhost.
+
+RAW mode socket connections receive the following callbacks
+
+```
+ LWS_CALLBACK_RAW_ADOPT
+ LWS_CALLBACK_RAW_RX
+ LWS_CALLBACK_RAW_WRITEABLE
+ LWS_CALLBACK_RAW_CLOSE
+```
+
+You can control which protocol on your vhost handles these RAW mode
+incoming connections by marking the selected protocol with a pvo `raw`, eg
+
+```
+ "protocol-lws-raw-test": {
+ "status": "ok",
+ "raw": "1"
+ },
+```
+
+The "raw" pvo marks this protocol as being used for RAW connections.
+
+`protocol-lws-raw-test` plugin provides a method for testing this with
+`libwebsockets-test-server-v2.0`:
+
+Run libwebsockets-test-server-v2.0 and connect to it by telnet, eg
+
+```
+ $ telnet 127.0.0.1 7681
+```
+
+type something that isn't a valid HTTP method and enter, before the
+connection times out. The connection will switch to RAW mode using this
+protocol, and pass the unused rx as a raw RX callback.
+
+The test protocol echos back what was typed on telnet to telnet.
+
+@section rawclientsocket RAW client socket descriptor polling
+
+You can now also open RAW socket connections in client mode.
+
+Follow the usual method for creating a client connection, but set the
+`info.method` to "RAW". When the connection is made, the wsi will be
+converted to RAW mode and operate using the same callbacks as the
+server RAW sockets described above.
+
+The libwebsockets-test-client supports this using raw:// URLS. To
+test, open a netcat listener in one window
+
+```
+ $ nc -l 9999
+```
+
+and in another window, connect to it using the test client
+
+```
+ $ libwebsockets-test-client raw://127.0.0.1:9999
+```
+
+The connection should succeed, and text typed in the netcat window (including a CRLF)
+will be received in the client.
+
@section ecdh ECDH Support
ECDH Certs are now supported. Enable the CMake option
to build in support and select it at runtime.
+@section sslinfo SSL info callbacks
+
+OpenSSL allows you to receive callbacks for various events defined in a
+bitmask in openssl/ssl.h. The events include stuff like TLS Alerts.
+
+By default, lws doesn't register for these callbacks.
+
+However if you set the info.ssl_info_event_mask to nonzero (ie, set some
+of the bits in it like `SSL_CB_ALERT` at vhost creation time, then
+connections to that vhost will call back using LWS_CALLBACK_SSL_INFO
+for the wsi, and the `in` parameter will be pointing to a struct of
+related args:
+
+```
+struct lws_ssl_info {
+ int where;
+ int ret;
+};
+```
+
+The default callback handler in lws has a handler for LWS_CALLBACK_SSL_INFO
+which prints the related information, You can test it using the switch
+-S -s on `libwebsockets-test-server-v2.0`.
+
+Returning nonzero from the callback will close the wsi.
+
@section smp SMP / Multithreaded service
SMP support is integrated into LWS without any internal threading. It's
```
LWS_VISIBLE struct lws_vhost *
lws_create_vhost(struct lws_context *context,
- struct lws_context_creation_info *info,
- struct lws_http_mount *mounts);
+ struct lws_context_creation_info *info);
```
lws_create_vhost() uses the same info struct as lws_create_context(),
This allocation is only deleted / replaced when the connection accesses a
URL region with a different protocol (or the default protocols[0] if no
CALLBACK area matches it).
+
+@section BINDTODEV SO_BIND_TO_DEVICE
+
+The .bind_iface flag in the context / vhost creation struct lets you
+declare that you want all traffic for listen and transport on that
+vhost to be strictly bound to the network interface named in .iface.
+
+This Linux-only feature requires SO_BIND_TO_DEVICE, which in turn
+requires CAP_NET_RAW capability... root has this capability.
+
+However this feature needs to apply the binding also to accepted
+sockets during normal operation, which implies the server must run
+the whole time as root.
+
+You can avoid this by using the Linux capabilities feature to have
+the unprivileged user inherit just the CAP_NET_RAW capability.
+
+You can confirm this with the test server
+
+
+```
+ $ sudo /usr/local/bin/libwebsockets-test-server -u agreen -i eno1 -k
+```
+
+The part that ensures the capability is inherited by the unprivileged
+user is
+
+```
+#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
+ info.caps[0] = CAP_NET_RAW;
+ info.count_caps = 1;
+#endif
+```
+
+
+@section dim Dimming webpage when connection lost
+
+The lws test plugins' html provides useful feedback on the webpage about if it
+is still connected to the server, by greying out the page if not. You can
+also add this to your own html easily
+
+ - include lws-common.js from your HEAD section
+
+ <script src="/lws-common.js"></script>
+
+ - dim the page during initialization, in a script section on your page
+
+ lws_gray_out(true,{'zindex':'499'});
+
+ - in your ws onOpen(), remove the dimming
+
+ lws_gray_out(false);
+
+ - in your ws onClose(), reapply the dimming
+
+ lws_gray_out(true,{'zindex':'499'});