1# Secure Streams
2
3Secure Streams is a networking api that strictly separates payload from any
4metadata.  That includes the client endpoint address for the connection, the tls
5trust chain and even the protocol used to connect to the endpoint.
6
7The user api just receives and transmits payload, and receives advisory
8connection state information.
9
10The details about how the connections for different types of secure stream should
11be made are held in JSON "policy database" initially passed in to the context
12creation, but able to be updated from a remote copy.
13
14Both client and server networking can be handled using Secure Streams APIS.
15
16![overview](/doc-assets/ss-operation-modes.png)
17
18## Secure Streams CLIENT State lifecycle
19
20![overview](/doc-assets/ss-state-flow.png)
21
22Secure Streams are created using `lws_ss_create()`, after that they may acquire
23underlying connections, and lose them, but the lifecycle of the Secure Stream
24itself is not directly related to any underlying connection.
25
26Once created, Secure Streams may attempt connections, these may fail and once
27the number of failures exceeds the count of attempts to conceal in the retry /
28backoff policy, the stream reaches `LWSSSCS_ALL_RETRIES_FAILED`.  The stream becomes
29idle again until another explicit connection attempt is given.
30
31Once connected, the user code can use `lws_ss_request_tx()` to ask for a slot
32to write to the peer, when this if forthcoming the tx handler can send a message.
33If the underlying protocol gives indications of transaction success, such as,
34eg, a 200 for http, or an ACK from MQTT, the stream state is called back with
35an `LWSSSCS_QOS_ACK_REMOTE` or `LWSSSCS_QOS_NACK_REMOTE`.
36
37## SS Callback return handling
38
39SS state(), rx() and tx() can indicate with their return code some common
40situations that should be handled by the caller.
41
42Constant|Scope|Meaning
43---|---|---
44LWSSSSRET_TX_DONT_SEND|tx|This opportunity to send something was passed on
45LWSSSSRET_OK|state, rx, tx|No error, continue doing what we're doing
46LWSSSSRET_DISCONNECT_ME|state, rx|assertively disconnect from peer
47LWSSSSRET_DESTROY_ME|state, rx|Caller should now destroy the stream itself
48LWSSSSRET_SS_HANDLE_DESTROYED|state|Something handled a request to destroy the stream
49
50Destruction of the stream we're calling back on inside the callback is tricky,
51it's preferable to return `LWSSSSRET_DESTROY_ME` if it is required, and let the
52caller handle it.  But in some cases, helpers called from the callbacks may
53destroy the handle themselves, in that case the handler should return
54`LWSSSSRET_SS_HANDLE_DESTROYED` indicating that the handle is already destroyed.
55
56## Secure Streams SERVER State lifecycle
57
58![overview](/doc-assets/ss-state-flow-server.png)
59
60You can also run servers defined using Secure Streams, the main difference is
61that the user code must assertively create a secure stream of the server type
62in order to create the vhost and listening socket.  When this stream is
63destroyed, the vhost is destroyed and the listen socket closed, otherwise it
64does not perform any rx or tx, it just represents the server lifecycle.
65
66When client connections randomly arrive at the listen socket, new Secure Stream
67objects are created along with accept sockets to represent each client
68connection.  As they represent the incoming connection, their lifecycle is the
69same as that of the underlying connection.  There is no retry concept since as
70with eg, http servers, the clients may typically not be routable for new
71connections initiated by the server.
72
73Since connections at socket level are already established, new connections are
74immediately taken through CREATING, CONNECTING, CONNECTED states for
75consistency.
76
77Some underlying protocols like http are "transactional", the server receives
78a logical request and must reply with a logical response.  The additional
79state `LWSSSCS_SERVER_TXN` provides a point where the user code can set
80transaction metadata before or in place of sending any payload.  It's also
81possible to defer this until any rx related to the transaction was received,
82but commonly with http requests, there is no rx / body.  Configuring the
83response there may look like
84
85```
86		/*
87		 * We do want to ack the transaction...
88		 */
89		lws_ss_server_ack(m->ss, 0);
90		/*
91		 * ... it's going to be text/html...
92		 */
93		lws_ss_set_metadata(m->ss, "mime", "text/html", 9);
94		/*
95		 * ...it's going to be 128 byte (and request tx)
96		 */
97		lws_ss_request_tx_len(m->ss, 128);
98```
99
100Otherwise the general api usage is very similar to client usage.
101
102## Convention for rx and tx callback return
103
104Function|Return|Meaning
105---|---|---
106tx|`LWSSSSRET_OK`|Send the amount of `buf` stored in `*len`
107tx|`LWSSSSRET_TX_DONT_SEND`|Do not send anything
108tx|`LWSSSSRET_DISCONNECT_ME`|Close the current connection
109tx|`LWSSSSRET_DESTROY_ME`|Destroy the Secure Stream
110rx|>=0|accepted
111rx|<0|Close the current connection
112
113# JSON Policy Database
114
115Example JSON policy... formatting is shown for clarity but whitespace can be
116omitted in the actual policy.
117
118Ordering is not critical in itself, but forward references are not allowed,
119things must be defined before they are allowed to be referenced later in the
120JSON.
121
122
123```
124{
125	"release": "01234567",
126	"product": "myproduct",
127	"schema-version": 1,
128	"retry": [{
129		"default": {
130			"backoff": [1000, 2000, 3000, 5000, 10000],
131			"conceal": 5,
132			"jitterpc": 20
133		}
134	}],
135	"certs": [{
136		"isrg_root_x1": "MIIFazCCA1OgAw...AnX5iItreGCc="
137	}, {
138		"LEX3_isrg_root_x1": "MIIFjTCCA3WgAwIB...WEsikxqEt"
139	}],
140	"trust_stores": [{
141		"le_via_isrg": ["isrg_root_x1", "LEX3_isrg_root_x1"]
142	}],
143	"s": [{
144		"mintest": {
145			"endpoint": "warmcat.com",
146			"port": 4443,
147			"protocol": "h1get",
148			"aux": "index.html",
149			"plugins": [],
150			"tls": true,
151			"opportunistic": true,
152			"retry": "default",
153			"tls_trust_store": "le_via_isrg"
154		}
155	}]
156}
157```
158
159### `Release`
160
161Identifies the policy version
162
163### `Product`
164
165Identifies the product the policy should apply to
166
167### `Schema-version`
168
169The minimum version of the policy parser required to parse this policy
170
171### `via-socks5`
172
173Optional redirect for Secure Streams client traffic through a socks5
174proxy given in the format `address:port`, eg, `127.0.0.1:12345`.
175
176### `retry`
177
178A list of backoff schemes referred to in the policy
179
180### `backoff`
181
182An array of ms delays for each retry in turn
183
184### `conceal`
185
186The number of retries to conceal from higher layers before giving errors.  If
187this is larger than the number of times in the backoff array, then the last time
188is used for the extra delays
189
190### `jitterpc`
191
192Percentage of the delay times mentioned in the backoff array that may be
193randomly added to the figure from the array.  For example with an array entry of
1941000ms, and jitterpc of 20%, actual delays will be chosen randomly from 1000ms
195through 1200ms.  This is to stop retry storms triggered by a single event like
196an outage becoming synchronized into a DoS.
197
198### `certs`
199
200Certificates needed for validation should be listed here each with a name.  The
201format is base64 DER, which is the same as the part of PEM that is inside the
202start and end lines.
203
204### `trust_stores`
205
206Chains of certificates given in the `certs` section may be named and described
207inside the `trust_stores` section.  Each entry in `trust_stores` is created as
208a vhost + tls context with the given name.  Stream types can later be associated
209with one of these to enforce validity checking of the remote server.
210
211Entries should be named using "name" and the stack array defined using "stack"
212
213### `auth`
214
215Optional section describing a map of available authentication streamtypes to
216auth token blob indexes.
217
218```
219...
220 "auth": [{"name":"newauth","type":"sigv4", "blob":0}]
221...
222```
223
224Streams can indicate they depend on a valid auth token from one of these schemes
225by using the `"use_auth": "name"` member in the streamtype definition, where name
226is, eg, "sigv4" in the example above.  If "use_auth" is not in the streamtype
227definition, default auth is lwa if "http_auth_header" is there.
228
229### `auth[].name`
230
231This is the name of the authentication scheme used by other streamtypes
232
233### `auth[].type`
234
235Indicate the auth type, e.g. sigv4
236
237### `auth[].streamtype`
238
239This is the auth streamtype to be used to refresh the authentication token
240
241### `auth[].blob`
242
243This is the auth blob index the authentication token is stored into and retreived
244from system blob, currently up to 4 blobs.
245
246
247### `s`
248
249These are an array of policies for the supported stream type names.
250
251### `server`
252
253**SERVER ONLY**: if set to `true`, the policy describes a secure streams
254server.
255
256### `endpoint`
257
258**CLIENT**: The DNS address the secure stream should connect to.
259
260This may contain string symbols which will be replaced with the
261corresponding streamtype metadata value at runtime.  Eg, if the
262streamtype lists a metadata name "region", it's then possible to
263define the endpoint as, eg, `${region}.mysite.com`, and before
264attempting the connection setting the stream's metadata item
265"region" to the desired value, eg, "uk".
266
267If the endpoint string begins with `+`, then it's understood to
268mean a connection to a Unix Domain Socket, for Linux `+@` means
269the following Unix Domain Socket is in the Linux Abstract
270Namespace and doesn't have a filesystem footprint.  This is only
271supported on unix-type and windows platforms and when lws was
272configured with `-DLWS_UNIX_SOCK=1`
273
274**SERVER**: If given, the network interface name or IP address the listen socket
275should bind to.
276
277**SERVER**: If begins with '!', the rest of the endpoint name is the
278vhost name of an existing vhost to bind to, instead of creating a new
279one.  This is useful when the vhost layout is already being managed by
280lejp-conf JSON and it's more convenient to put the details in there.
281
282### `port`
283
284**CLIENT**: The port number as an integer on the endpoint to connect to
285
286**SERVER**: The port number the server will listen on
287
288### `protocol`
289
290**CLIENT**: The wire protocol to connect to the endpoint with.  Currently
291supported streamtypes are
292
293|Wire protocol|Description|
294|---|---|
295|h1|http/1|
296|h2|http/2|
297|ws|http/1 Websockets|
298|mqtt|mqtt 3.1.1|
299|raw||
300
301Raw protocol is a bit different than the others in that there is no protocol framing,
302whatever is received on the connection is passed to the user rx callback and whatever
303the tx callback provides is issued on to the connection.  Because tcp can be
304arbitrarily fragmented by any intermediary, such streams have to be regarded as an
305ordered bytestream that may be fragmented at any byte without any meaning in terms
306of message boundaries, for that reason SOM and EOM are ignored with raw.
307
308### `allow_redirects`
309
310By default redirects are not followed, if you wish a streamtype to observe them, eg,
311because that's how it responds to a POST, set `"allow_redirects": true`
312
313### `tls`
314
315Set to `true` to enforce the stream travelling in a tls tunnel
316
317### `client cert`
318
319Set if the stream needs to authenticate itself using a tls client certificate.
320Set to the certificate index counting from 0+.  The certificates are managed
321using lws_sytstem blobs.
322
323### `opportunistic`
324
325Set to `true` if the connection may be left dropped except when in use
326
327### `nailed_up`
328
329Set to `true` to have lws retry if the connection carrying this stream should
330ever drop.
331
332### `retry`
333
334The name of the policy described in the `retry` section to apply to this
335connection for retry + backoff
336
337### `timeout_ms`
338
339Optional timeout associated with streams of this streamtype.
340
341If user code applies the `lws_ss_start_timeout()` api on a stream with a
342timeout of LWSSS_TIMEOUT_FROM_POLICY, the `timeout_ms` entry given in the
343policy is applied.
344
345### `perf`
346
347If set to true, and lws was built with `LWS_WITH_CONMON`, causes this streamtype
348to receive additional rx payload with the `LWSSS_FLAG_PERF_JSON` flag set on it,
349that is JSON representing the onward connection performance information.
350
351These are based on the information captured in the struct defined in
352libwebsockets/lws-conmon.h, represented in JSON
353
354```
355	{
356	  "peer": "46.105.127.147",
357	  "dns_us": 1234,
358	  "sockconn_us": 1234,
359	  "tls_us": 1234,
360	  "txn_resp_us": 1234,
361	  "dns":["46.105.127.147", "2001:41d0:2:ee93::1"]
362	}
363```
364
365Streamtypes without "perf": true will never see the special rx payloads.
366Notice that the `LWSSS_FLAG_PERF_JSON` payloads must be handled out of band
367for the normal payloads, as they can appear inside normal payload messages.
368
369### `tls_trust_store`
370
371The name of the trust store described in the `trust_stores` section to apply
372to validate the remote server cert.
373
374If missing and tls is enabled on the streamtype, then validation is
375attempted using the OS trust store, otherwise the connection fails.
376
377### `use_auth`
378
379Indicate that the streamtype should use the named auth type from the `auth`
380array in the policy
381
382### `aws_region`
383Indicate which metadata should be used to set aws region for certain streamtype
384
385### `aws_service`
386Indicate which metadata should be used to set aws service for certain streamtype
387
388### `server_cert`
389
390**SERVER ONLY**: subject to change... the name of the x.509 cert that is the
391server's tls certificate
392
393### `server_key`
394
395**SERVER ONLY**: subject to change... the name of the x.509 cert that is the
396server's tls key
397
398### `swake_validity`
399
400Set to `true` if this streamtype is important enough for the functioning of the
401device that its locally-initiated periodic connection validity checks of the
402interval described in the associated retry / backoff selection, are important
403enough to wake the whole system from low power suspend so they happen on
404schedule.
405
406### `proxy_buflen`
407
408Only used when the streamtype is proxied... sets the maximum size of the
409payload buffering (in bytes) the proxy will hold for this type of stream.  If
410the endpoint dumps a lot of data without any flow control, this may need to
411be correspondingly large.  Default is 32KB.
412
413### `proxy_buflen_rxflow_on_above`, `proxy_buflen_rxflow_off_below`
414
415When `proxy_buflen` is set, you can also wire up the amount of buffered
416data intended for the client held at the proxy, to the onward ss wsi
417rx flow control state.  If more than `proxy_buflen_rxflow_on_above`
418bytes are buffered, rx flow control is set stopping further rx.  Once
419the dsh is drained below `proxy_buflen_rxflow_off_below`, the rx flow
420control is released and RX resumes.
421
422### `client_buflen`
423
424Only used when the streamtype is proxied... sets the maximum size of the
425payload buffering (in bytes) the client will hold for this type of stream.  If
426the client sends a lot of data without any flow control, this may need to
427be correspondingly large.  Default is 32KB.
428
429### `attr_priority`
430
431A number between 0 (normal priority) and 6 (very high priority).  7 is also
432possible, but requires CAP_NET_ADMIN on Linux and is reserved for network
433administration packets.  Normally default priority is fine, but under some
434conditions when transporting over IP packets, you may want to control the
435IP packet ToS priority for the streamtype by using this.
436
437### `attr_low_latency`
438
439This is a flag indicating that the streamtype packets should be transported
440in a way that results in lower latency where there is a choice.  For IP packets,
441this sets the ToS "low delay" flag on packets from this streamtype.
442
443### `attr_high_throughput`
444
445This is a flag indicating that this streamtype should be expected to produce
446bulk content that requires high throughput.  For IP packets,
447this sets the ToS "high throughput" flag on packets from this streamtype.
448
449### `attr_high_reliability`
450
451This is a flag indicating that extra efforts should be made to deliver packets
452from this streamtype where possible.  For IP packets, this sets the ToS "high
453reliability" flag on packets from this streamtype.
454
455### `attr_low_cost`
456
457This is a flag indicating that packets from this streamtype should be routed as
458inexpensively as possible by trading off latency and reliability where there is
459a choice.  For IP packets, this sets the ToS "low cost" flag on packets from
460this streamtype.
461
462### `metadata`
463
464This allows declaring basically dynamic symbol names to be used by the streamtype,
465along with an optional mapping to a protocol-specific entity such as a given
466http header.  Eg:
467
468```
469		"metadata": [ { "myname": "" }, { "ctype": "content-type:" } ],
470```
471
472In this example "ctype" is associated with the http header "content-type" while
473"myname" doesn't have any association to a header.
474
475Symbol names may be used in the other policy for the streamtype for string
476substitution using the syntax like `xxx${myname}yyy`, forward references are
477valid but the scope of the symbols is just the streamtype the metadata is
478defined for.
479
480Client code can set metadata by name, using the `lws_ss_set_metadata()` api, this
481should be done before a transaction.  And for metadata associated with a
482protocol-specific entity, like http headers, if incoming responses contain the
483mentioned header, the metadata symbol is set to that value at the client before
484any rx proceeds.
485
486Metadata continues to work the same for the client in the case it is proxying its
487connectivity, metadata is passed in both directions serialized over the proxy link.
488
489## http transport
490
491### `http_method`
492
493HTTP method to use with http-related protocols, like GET or POST.
494Not required for ws.
495
496### `http_expect`
497
498Optionally indicates that success for HTTP transactions using this
499streamtype is different than the default 200 - 299.
500
501Eg, you may choose to set this to 204 for Captive Portal Detect usage
502if that's what you expect the server to reply with to indicate
503success.  In that case, anything other than 204 will be treated as a
504connection failure.
505
506### `http_fail_redirect`
507
508Set to `true` if you want to fail the connection on meeting an
509http redirect.  This is needed to, eg, detect Captive Portals
510correctly.  Normally, if on https, you would want the default behaviour
511of following the redirect.
512
513### `http_url`
514
515Url path to use with http-related protocols
516
517The URL path can include metatadata like this
518
519"/mypath?whatever=${metadataname}"
520
521${metadataname} will be replaced by the current value of the
522same metadata name.  The metadata names must be listed in the
523"metadata": [ ] section.
524
525### `http_resp_map`
526
527If your server overloads the meaning of the http transport response code with
528server-custom application codes, you can map these to discrete Secure Streams
529state callbacks using a JSON map, eg
530
531```
532		"http_resp_map": [ { "530": 1530 }, { "531": 1531 } ],
533```
534
535It's not recommended to abuse the transport layer http response code by
536mixing it with application state information like this, but if it's dealing
537with legacy serverside that takes this approach, it's possible to handle it
538in SS this way while removing the dependency on http.
539
540### `http_auth_header`
541
542The name of the header that takes the auth token, with a trailing ':', eg
543
544```
545  "http_auth_header": "authorization:"
546```
547
548### `http_dsn_header`
549
550The name of the header that takes the dsn token, with a trailing ':', eg
551
552```
553  "http_dsn_header": "x-dsn:"
554```
555
556### `http_fwv_header`
557
558The name of the header that takes the firmware version token, with a trailing ':', eg
559
560```
561  "http_fwv_header": "x-fw-version:"
562```
563
564### `http_devtype_header`
565
566The name of the header that takes the device type token, with a trailing ':', eg
567
568```
569  "http_devtype_header": "x-device-type:"
570```
571
572### `http_auth_preamble`
573
574An optional string that precedes the auth token, eg
575
576```
577 "http_auth_preamble": "bearer "
578```
579
580### `auth_hexify`
581
582Convert the auth token to hex ('A' -> "41") before transporting.  Not necessary if the
583auth token is already in printable string format suitable for transport.  Needed if the
584auth token is a chunk of 8-bit binary.
585
586### `nghttp2_quirk_end_stream`
587
588Set this to `true` if the peer server has the quirk it won't send a response until we have
589sent an `END_STREAM`, even though we have sent headers with `END_HEADERS`.
590
591### `h2q_oflow_txcr`
592
593Set this to `true` if the peer server has the quirk it sends an maximum initial tx credit
594of 0x7fffffff and then later increments it illegally.
595
596### `http_multipart_ss_in`
597
598Indicates that SS should parse any incoming multipart mime on this stream
599
600### `http_multipart_name`
601
602Indicates this stream goes out using multipart mime, and provides the name part of the
603multipart header
604
605### `http_multipart_filename`
606
607Indicates this stream goes out using multipart mime, and provides the filename part of the
608multipart header
609
610### `http_multipart_content_type`
611
612The `content-type` to mark up the multipart mime section with if present
613
614### `http_www_form_urlencoded`
615
616Indicate the data is sent in `x-www-form-urlencoded` form
617
618### `rideshare`
619
620For special cases where one logically separate stream travels with another when using this
621protocol.  Eg, a single multipart mime transaction carries content from two or more streams.
622
623## ws transport
624
625### `ws_subprotocol`
626
627** CLIENT **: Name of the ws subprotocol to request from the server
628
629** SERVER **: Name of the subprotocol we will accept
630
631### `ws_binary`
632
633Use if the ws messages are binary
634
635## MQTT transport
636
637### `mqtt_topic`
638
639Set the topic this streamtype uses for writes
640
641### `mqtt_subscribe`
642
643Set the topic this streamtype subscribes to
644
645### `mqtt qos`
646
647Set the QOS level for this streamtype
648
649### `mqtt_keep_alive`
650
65116-bit number representing MQTT keep alive for the stream.
652
653This is applied at connection time... where different streams may bind to the
654same underlying MQTT connection, all the streams should have an identical
655setting for this.
656
657### `mqtt_clean_start`
658
659Set to true if the connection should use MQTT's "clean start" feature.
660
661This is applied at connection time... where different streams may bind to the
662same underlying MQTT connection, all the streams should have an identical
663setting for this.
664
665### `mqtt_will_topic`
666
667Set the topic of the connection's will message, if any (there is none by default).
668
669This is applied at connection time... where different streams may bind to the
670same underlying MQTT connection, all the streams should have an identical
671setting for this.
672
673### `mqtt_will_message`
674
675Set the content of the connect's will message, if any (there is none by default).
676
677This is applied at connection time... where different streams may bind to the
678same underlying MQTT connection, all the streams should have an identical
679setting for this.
680
681### `mqtt_will_qos`
682
683Set the QoS of the will message, if any (there is none by default).
684
685This is applied at connection time... where different streams may bind to the
686same underlying MQTT connection, all the streams should have an identical
687setting for this.
688
689### `mqtt_will_retain`
690
691Set to true if the connection should use MQTT's "will retain" feature, if there
692is a will message (there is none by default).
693
694This is applied at connection time... where different streams may bind to the
695same underlying MQTT connection, all the streams should have an identical
696setting for this.
697
698## Loading and using updated remote policy
699
700If the default, hardcoded policy includes a streamtype `fetch_policy`,
701during startup when lws_system reaches the POLICY state, lws will use
702a Secure Stream of type `fetch_policy` to download, parse and update
703the policy to use it.
704
705The secure-streams-proxy minimal example shows how this is done and
706fetches its real policy from warmcat.com at startup using the built-in
707one.
708
709## Applying streamtype policy overlays
710
711This is intended for modifying policies at runtime for testing, eg, to
712force error paths to be taken.  After the main policy is processed, you
713may parse additional, usually smaller policy fragments on top of it.
714
715Where streamtype names in the new fragment already exist in the current
716parsed policy, the settings in the fragment are applied over the parsed
717policy, overriding settings.  There's a simple api to enable this by
718giving it the override JSON in one string
719
720```
721int
722lws_ss_policy_overlay(struct lws_context *context, const char *overlay);
723```
724
725but there are also other apis available that can statefully process
726larger overlay fragments if needed.
727
728An example overlay fragment looks like this
729
730```
731	{ "s": [{ "captive_portal_detect": {
732		"endpoint": "google.com",
733		"http_url": "/",
734		"port": 80
735	}}]}
736```
737
738ie the overlay fragment completely follows the structure of the main policy,
739just misses out anything it doesn't override.
740
741Currently ONLY streamtypes may be overridden.
742
743You can see an example of this in use in `minimal-secure-streams` example
744where `--force-portal` and `--force-no-internet` options cause the captive
745portal detect streamtype to be overridden to force the requested kind of
746outcome.
747
748## Captive Portal Detection
749
750If the policy contains a streamtype `captive_portal_detect` then the
751type of transaction described there is automatically performed after
752acquiring a DHCP address to try to determine the captive portal
753situation.
754
755```
756		"captive_portal_detect": {
757                        "endpoint": "connectivitycheck.android.com",
758                        "port": 80,
759                        "protocol": "h1",
760                        "http_method": "GET",
761                        "http_url": "generate_204",
762                        "opportunistic": true,
763                        "http_expect": 204,
764			"http_fail_redirect": true
765                }
766```
767
768## Stream serialization and proxying
769
770By default Secure Streams expects to make the outgoing connection described in
771the policy in the same process / thread, this suits the case where all the
772participating clients are in the same statically-linked image.
773
774In this case the `lws_ss_` apis are fulfilled locally by secure-streams.c and
775policy.c for policy lookups.
776
777However it also supports serialization, where the SS api can be streamed over
778another transport such as a Unix Domain Socket connection.  This suits the case
779where the clients are actually in different processes in, eg, Linux or Android.
780
781In those cases, you run a proxy process (minimal-secure-streams-proxy) that
782listens on a Unix Domain Socket and is connected to by one or more other
783processes that pass their SS API activity to the proxy for fulfilment (or
784onward proxying).
785
786Each Secure Stream that is created then in turn creates a private Unix Domain
787Socket connection to the proxy for each stream.
788
789In this case the proxy uses secure-streams.c and policy.c as before to fulfil
790the inbound proxy streams, but uses secure-streams-serialize.c to serialize and
791deserialize the proxied SS API activity.  The proxy clients define
792LWS_SS_USE_SSPC either very early in their sources before the includes, or on
793the compiler commandline... this causes the lws_ss_ apis to be replaced at
794preprocessor time with lws_sspc_ equivalents.  These serialize the api action
795and pass it to the proxy over a Unix Domain Socket for fulfilment, the results
796and state changes etc are streamed over the Unix Domain Socket and presented to
797the application exactly the same as if it was being fulfilled locally.
798
799To demonstrate this, some minimal examples, eg, minimal-secure-streams and
800mimimal-secure-streams-avs build themselves both ways, once with direct SS API
801fulfilment and once with Unix Domain Socket proxying and -client appended on the
802executable name.  To test the -client variants, run minimal-secure-streams-proxy
803on the same machine.
804
805## Complicated scenarios with secure streams proxy
806
807As mentioned above, Secure Streams has two modes, by default the application
808directly parses the policy and makes the outgoing connections itself.
809However when configured at cmake with
810
811```
812-DLWS_WITH_SOCKS5=1 -DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_SECURE_STREAMS_PROXY_API=1 -DLWS_WITH_MINIMAL_EXAMPLES=1
813```
814
815and define `LWS_SS_USE_SSPC` when building the application, applications forward
816their network requests to a local or remote SS proxy for fulfilment... and only
817the SS proxy has the system policy.  By default, the SS proxy is on the local
818machine and is connected to via a Unix Domain Socket, but tcp links are also
819possible.  (Note the proxied traffic is not encrypyed by default.)
820
821Using the configuration above, the example SS applications are built two ways,
822once for direct connection fulfilment (eg, `./bin/lws-minimal-secure-streams`),
823and once with `LWS_SS_USE_SSPC` also defined so it connects via an SS proxy,
824(eg, `./bin/lws-minimal-secure-streams-client`).
825
826## Testing an example scenario with SS Proxy and socks5 proxy
827
828```
829 [ SS application ] --- tcp --- [ socks 5 proxy ] --- tcp --- [ SS proxy ] --- internet
830```
831
832In this scenario, everything is on localhost, the socks5 proxy listens on :1337 and
833the SS proxy listens on :1234.  The SS application connects to the socks5
834proxy to get to the SS proxy, which then goes out to the internet
835
836### 1 Start the SS proxy
837
838Tell it to listen on lo interface on port 1234
839
840```
841$ ./bin/lws-minimal-secure-streams-proxy -p 1234 -i lo
842```
843
844### 2 Start the SOCKS5 proxy
845
846```
847$ ssh -D 1337 -N -v localhost
848```
849
850The -v makes connections to the proxy visible in the terminal for testing
851
852### 3 Run the SS application
853
854The application is told to make all connections via the socks5 proxy at
855127.0.0.1:1337, and to fulfil its SS connections via an SS proxy, binding
856connections to 127.0.0.1 (ipv4 lo interface, -1), to 127.0.0.1:1234 (-a/-p).
857
858```
859socks_proxy=127.0.0.1:1337 ./bin/lws-minimal-secure-streams-client -p 1234 -i 127.0.0.1 -a 127.0.0.1
860```
861
862You can confirm this goes through the ssh socks5 proxy to get to the SS proxy
863and fulfil the connection.
864
865## Using static policies
866
867If one of your targets is too constrained to make use of dynamic JSON policies, but
868using SS and the policies is attractive for wider reasons, you can use a static policy
869built into the firmware for the constrained target.
870
871The secure-streams example "policy2c" (which runs on the build machine, not the device)
872
873https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/secure-streams/minimal-secure-streams-policy2c
874
875accepts a normal JSON policy on stdin, and emits a C code representation that can be
876included directly in the firmware.
877
878https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.h
879
880Using this technique it's possible to standardize on maintaining JSON policies across a
881range of devices with different contraints, and use the C conversion of the policy on devices
882that are too small.
883
884The Cmake option `LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY` should be enabled to use this
885mode, it will not build the JSON parser (and the option for LEJP can also be disabled if
886you're not otherwise using it, saving an additional couple of KB).
887
888Notice policy2c example tool must be built with `LWS_ROLE_H1`, `LWS_ROLE_H2`, `LWS_ROLE_WS`
889and `LWS_ROLE_MQTT` enabled so it can handle any kind of policy.
890
891## HTTP and ws serving
892
893All ws servers start out as http servers... for that reason ws serving is
894handled as part of http serving, if you give the `ws_subprotocol` entry to the
895streamtype additionally, the server will also accept upgrades to ws.
896
897To help the user code understand if the upgrade occurred, there's a special
898state `LWSSSCS_SERVER_UPGRADE`, so subsequent rx and tx can be understood to
899have come from the upgraded protocol.  To allow separation of rx and tx
900handling between http and ws, there's a ss api `lws_ss_change_handlers()`
901which allows dynamically setting SS handlers.
902
903Since the http and ws upgrade identity is encapsulated in one streamtype, the
904user object for the server streamtype should contain related user data for both
905http and ws underlying protocol identity.
906