• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.  65535 means never stop trying.
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`
383
384Indicate which metadata should be used to set aws region for certain streamtype
385
386### `aws_service`
387
388Indicate which metadata should be used to set aws service for certain streamtype
389
390### `direct_proto_str`
391
392If set to `true`, application can use `lws_ss_set_metadata()` to directly set protocol related string and use `lws_ss_get_metadata` to fetch certain protocol related string.  Please note that currently HTTP header is the supported protocol string.  The `name` parameter is the name of HTTP header name (**with ':'**, e.g. `"Content-Type:"`) and `value` is the header's value. `LWS_WITH_SS_DIRECT_PROTOCOL_STR` flag needs to be configured during compilation for this.  Currently it's only work for non-proxy case.
393
394### `server_cert`
395
396**SERVER ONLY**: subject to change... the name of the x.509 cert that is the
397server's tls certificate
398
399### `server_key`
400
401**SERVER ONLY**: subject to change... the name of the x.509 cert that is the
402server's tls key
403
404### `swake_validity`
405
406Set to `true` if this streamtype is important enough for the functioning of the
407device that its locally-initiated periodic connection validity checks of the
408interval described in the associated retry / backoff selection, are important
409enough to wake the whole system from low power suspend so they happen on
410schedule.
411
412### `proxy_buflen`
413
414Only used when the streamtype is proxied... sets the maximum size of the
415payload buffering (in bytes) the proxy will hold for this type of stream.  If
416the endpoint dumps a lot of data without any flow control, this may need to
417be correspondingly large.  Default is 32KB.
418
419### `proxy_buflen_rxflow_on_above`, `proxy_buflen_rxflow_off_below`
420
421When `proxy_buflen` is set, you can also wire up the amount of buffered
422data intended for the client held at the proxy, to the onward ss wsi
423rx flow control state.  If more than `proxy_buflen_rxflow_on_above`
424bytes are buffered, rx flow control is set stopping further rx.  Once
425the dsh is drained below `proxy_buflen_rxflow_off_below`, the rx flow
426control is released and RX resumes.
427
428### `client_buflen`
429
430Only used when the streamtype is proxied... sets the maximum size of the
431payload buffering (in bytes) the client will hold for this type of stream.  If
432the client sends a lot of data without any flow control, this may need to
433be correspondingly large.  Default is 32KB.
434
435### `attr_priority`
436
437A number between 0 (normal priority) and 6 (very high priority).  7 is also
438possible, but requires CAP_NET_ADMIN on Linux and is reserved for network
439administration packets.  Normally default priority is fine, but under some
440conditions when transporting over IP packets, you may want to control the
441IP packet ToS priority for the streamtype by using this.
442
443### `attr_low_latency`
444
445This is a flag indicating that the streamtype packets should be transported
446in a way that results in lower latency where there is a choice.  For IP packets,
447this sets the ToS "low delay" flag on packets from this streamtype.
448
449### `attr_high_throughput`
450
451This is a flag indicating that this streamtype should be expected to produce
452bulk content that requires high throughput.  For IP packets,
453this sets the ToS "high throughput" flag on packets from this streamtype.
454
455### `attr_high_reliability`
456
457This is a flag indicating that extra efforts should be made to deliver packets
458from this streamtype where possible.  For IP packets, this sets the ToS "high
459reliability" flag on packets from this streamtype.
460
461### `attr_low_cost`
462
463This is a flag indicating that packets from this streamtype should be routed as
464inexpensively as possible by trading off latency and reliability where there is
465a choice.  For IP packets, this sets the ToS "low cost" flag on packets from
466this streamtype.
467
468### `metadata`
469
470This allows declaring basically dynamic symbol names to be used by the streamtype,
471along with an optional mapping to a protocol-specific entity such as a given
472http header.  Eg:
473
474```
475		"metadata": [ { "myname": "" }, { "ctype": "content-type:" } ],
476```
477
478In this example "ctype" is associated with the http header "content-type" while
479"myname" doesn't have any association to a header.
480
481Symbol names may be used in the other policy for the streamtype for string
482substitution using the syntax like `xxx${myname}yyy`, forward references are
483valid but the scope of the symbols is just the streamtype the metadata is
484defined for.
485
486Client code can set metadata by name, using the `lws_ss_set_metadata()` api, this
487should be done before a transaction.  And for metadata associated with a
488protocol-specific entity, like http headers, if incoming responses contain the
489mentioned header, the metadata symbol is set to that value at the client before
490any rx proceeds.
491
492Metadata continues to work the same for the client in the case it is proxying its
493connectivity, metadata is passed in both directions serialized over the proxy link.
494
495## http transport
496
497### `http_method`
498
499HTTP method to use with http-related protocols, like GET or POST.
500Not required for ws.
501
502### `http_expect`
503
504Optionally indicates that success for HTTP transactions using this
505streamtype is different than the default 200 - 299.
506
507Eg, you may choose to set this to 204 for Captive Portal Detect usage
508if that's what you expect the server to reply with to indicate
509success.  In that case, anything other than 204 will be treated as a
510connection failure.
511
512### `http_fail_redirect`
513
514Set to `true` if you want to fail the connection on meeting an
515http redirect.  This is needed to, eg, detect Captive Portals
516correctly.  Normally, if on https, you would want the default behaviour
517of following the redirect.
518
519### `http_url`
520
521Url path to use with http-related protocols
522
523The URL path can include metatadata like this
524
525"/mypath?whatever=${metadataname}"
526
527${metadataname} will be replaced by the current value of the
528same metadata name.  The metadata names must be listed in the
529"metadata": [ ] section.
530
531### `http_resp_map`
532
533If your server overloads the meaning of the http transport response code with
534server-custom application codes, you can map these to discrete Secure Streams
535state callbacks using a JSON map, eg
536
537```
538		"http_resp_map": [ { "530": 1530 }, { "531": 1531 } ],
539```
540
541It's not recommended to abuse the transport layer http response code by
542mixing it with application state information like this, but if it's dealing
543with legacy serverside that takes this approach, it's possible to handle it
544in SS this way while removing the dependency on http.
545
546### `http_auth_header`
547
548The name of the header that takes the auth token, with a trailing ':', eg
549
550```
551  "http_auth_header": "authorization:"
552```
553
554### `http_dsn_header`
555
556The name of the header that takes the dsn token, with a trailing ':', eg
557
558```
559  "http_dsn_header": "x-dsn:"
560```
561
562### `http_fwv_header`
563
564The name of the header that takes the firmware version token, with a trailing ':', eg
565
566```
567  "http_fwv_header": "x-fw-version:"
568```
569
570### `http_devtype_header`
571
572The name of the header that takes the device type token, with a trailing ':', eg
573
574```
575  "http_devtype_header": "x-device-type:"
576```
577
578### `http_auth_preamble`
579
580An optional string that precedes the auth token, eg
581
582```
583 "http_auth_preamble": "bearer "
584```
585
586### `auth_hexify`
587
588Convert the auth token to hex ('A' -> "41") before transporting.  Not necessary if the
589auth token is already in printable string format suitable for transport.  Needed if the
590auth token is a chunk of 8-bit binary.
591
592### `nghttp2_quirk_end_stream`
593
594Set this to `true` if the peer server has the quirk it won't send a response until we have
595sent an `END_STREAM`, even though we have sent headers with `END_HEADERS`.
596
597### `h2q_oflow_txcr`
598
599Set this to `true` if the peer server has the quirk it sends an maximum initial tx credit
600of 0x7fffffff and then later increments it illegally.
601
602### `http_multipart_ss_in`
603
604Indicates that SS should parse any incoming multipart mime on this stream
605
606### `http_multipart_name`
607
608Indicates this stream goes out using multipart mime, and provides the name part of the
609multipart header
610
611### `http_multipart_filename`
612
613Indicates this stream goes out using multipart mime, and provides the filename part of the
614multipart header
615
616### `http_multipart_content_type`
617
618The `content-type` to mark up the multipart mime section with if present
619
620### `http_www_form_urlencoded`
621
622Indicate the data is sent in `x-www-form-urlencoded` form
623
624### `http_cookies`
625
626This streamtype should store and bring out http cookies from the peer.
627
628### `rideshare`
629
630For special cases where one logically separate stream travels with another when using this
631protocol.  Eg, a single multipart mime transaction carries content from two or more streams.
632
633## ws transport
634
635### `ws_subprotocol`
636
637** CLIENT **: Name of the ws subprotocol to request from the server
638
639** SERVER **: Name of the subprotocol we will accept
640
641### `ws_binary`
642
643Use if the ws messages are binary
644
645### `ws_prioritize_reads`
646
647Set `true` if the event loop should prioritize keeping up with input at the
648potential expense of output latency.
649
650## MQTT transport
651
652### `mqtt_topic`
653
654Set the topic this streamtype uses for writes
655
656### `mqtt_subscribe`
657
658Set the topic this streamtype subscribes to
659
660### `mqtt qos`
661
662Set the QOS level for this streamtype
663
664### `mqtt_keep_alive`
665
66616-bit number representing MQTT keep alive for the stream.
667
668This is applied at connection time... where different streams may bind to the
669same underlying MQTT connection, all the streams should have an identical
670setting for this.
671
672### `mqtt_clean_start`
673
674Set to true if the connection should use MQTT's "clean start" feature.
675
676This is applied at connection time... where different streams may bind to the
677same underlying MQTT connection, all the streams should have an identical
678setting for this.
679
680### `mqtt_will_topic`
681
682Set the topic of the connection's will message, if any (there is none by default).
683
684This is applied at connection time... where different streams may bind to the
685same underlying MQTT connection, all the streams should have an identical
686setting for this.
687
688### `mqtt_will_message`
689
690Set the content of the connect's will message, if any (there is none by default).
691
692This is applied at connection time... where different streams may bind to the
693same underlying MQTT connection, all the streams should have an identical
694setting for this.
695
696### `mqtt_will_qos`
697
698Set the QoS of the will message, if any (there is none by default).
699
700This is applied at connection time... where different streams may bind to the
701same underlying MQTT connection, all the streams should have an identical
702setting for this.
703
704### `mqtt_will_retain`
705
706Set to true if the connection should use MQTT's "will retain" feature, if there
707is a will message (there is none by default).
708
709This is applied at connection time... where different streams may bind to the
710same underlying MQTT connection, all the streams should have an identical
711setting for this.
712
713## Loading and using updated remote policy
714
715If the default, hardcoded policy includes a streamtype `fetch_policy`,
716during startup when lws_system reaches the POLICY state, lws will use
717a Secure Stream of type `fetch_policy` to download, parse and update
718the policy to use it.
719
720The secure-streams-proxy minimal example shows how this is done and
721fetches its real policy from warmcat.com at startup using the built-in
722one.
723
724## Applying streamtype policy overlays
725
726This is intended for modifying policies at runtime for testing, eg, to
727force error paths to be taken.  After the main policy is processed, you
728may parse additional, usually smaller policy fragments on top of it.
729
730Where streamtype names in the new fragment already exist in the current
731parsed policy, the settings in the fragment are applied over the parsed
732policy, overriding settings.  There's a simple api to enable this by
733giving it the override JSON in one string
734
735```
736int
737lws_ss_policy_overlay(struct lws_context *context, const char *overlay);
738```
739
740but there are also other apis available that can statefully process
741larger overlay fragments if needed.
742
743An example overlay fragment looks like this
744
745```
746	{ "s": [{ "captive_portal_detect": {
747		"endpoint": "google.com",
748		"http_url": "/",
749		"port": 80
750	}}]}
751```
752
753ie the overlay fragment completely follows the structure of the main policy,
754just misses out anything it doesn't override.
755
756Currently ONLY streamtypes may be overridden.
757
758You can see an example of this in use in `minimal-secure-streams` example
759where `--force-portal` and `--force-no-internet` options cause the captive
760portal detect streamtype to be overridden to force the requested kind of
761outcome.
762
763## Captive Portal Detection
764
765If the policy contains a streamtype `captive_portal_detect` then the
766type of transaction described there is automatically performed after
767acquiring a DHCP address to try to determine the captive portal
768situation.
769
770```
771		"captive_portal_detect": {
772                        "endpoint": "connectivitycheck.android.com",
773                        "port": 80,
774                        "protocol": "h1",
775                        "http_method": "GET",
776                        "http_url": "generate_204",
777                        "opportunistic": true,
778                        "http_expect": 204,
779			"http_fail_redirect": true
780                }
781```
782
783## Stream serialization and proxying
784
785By default Secure Streams expects to make the outgoing connection described in
786the policy in the same process / thread, this suits the case where all the
787participating clients are in the same statically-linked image.
788
789In this case the `lws_ss_` apis are fulfilled locally by secure-streams.c and
790policy.c for policy lookups.
791
792However it also supports serialization, where the SS api can be streamed over
793another transport such as a Unix Domain Socket connection.  This suits the case
794where the clients are actually in different processes in, eg, Linux or Android.
795
796In those cases, you run a proxy process (minimal-secure-streams-proxy) that
797listens on a Unix Domain Socket and is connected to by one or more other
798processes that pass their SS API activity to the proxy for fulfilment (or
799onward proxying).
800
801Each Secure Stream that is created then in turn creates a private Unix Domain
802Socket connection to the proxy for each stream.
803
804In this case the proxy uses secure-streams.c and policy.c as before to fulfil
805the inbound proxy streams, but uses secure-streams-serialize.c to serialize and
806deserialize the proxied SS API activity.  The proxy clients define
807LWS_SS_USE_SSPC either very early in their sources before the includes, or on
808the compiler commandline... this causes the lws_ss_ apis to be replaced at
809preprocessor time with lws_sspc_ equivalents.  These serialize the api action
810and pass it to the proxy over a Unix Domain Socket for fulfilment, the results
811and state changes etc are streamed over the Unix Domain Socket and presented to
812the application exactly the same as if it was being fulfilled locally.
813
814To demonstrate this, some minimal examples, eg, minimal-secure-streams and
815mimimal-secure-streams-avs build themselves both ways, once with direct SS API
816fulfilment and once with Unix Domain Socket proxying and -client appended on the
817executable name.  To test the -client variants, run minimal-secure-streams-proxy
818on the same machine.
819
820## Complicated scenarios with secure streams proxy
821
822As mentioned above, Secure Streams has two modes, by default the application
823directly parses the policy and makes the outgoing connections itself.
824However when configured at cmake with
825
826```
827-DLWS_WITH_SOCKS5=1 -DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_SECURE_STREAMS_PROXY_API=1 -DLWS_WITH_MINIMAL_EXAMPLES=1
828```
829
830and define `LWS_SS_USE_SSPC` when building the application, applications forward
831their network requests to a local or remote SS proxy for fulfilment... and only
832the SS proxy has the system policy.  By default, the SS proxy is on the local
833machine and is connected to via a Unix Domain Socket, but tcp links are also
834possible.  (Note the proxied traffic is not encrypyed by default.)
835
836Using the configuration above, the example SS applications are built two ways,
837once for direct connection fulfilment (eg, `./bin/lws-minimal-secure-streams`),
838and once with `LWS_SS_USE_SSPC` also defined so it connects via an SS proxy,
839(eg, `./bin/lws-minimal-secure-streams-client`).
840
841## Testing an example scenario with SS Proxy and socks5 proxy
842
843```
844 [ SS application ] --- tcp --- [ socks 5 proxy ] --- tcp --- [ SS proxy ] --- internet
845```
846
847In this scenario, everything is on localhost, the socks5 proxy listens on :1337 and
848the SS proxy listens on :1234.  The SS application connects to the socks5
849proxy to get to the SS proxy, which then goes out to the internet
850
851### 1 Start the SS proxy
852
853Tell it to listen on lo interface on port 1234
854
855```
856$ ./bin/lws-minimal-secure-streams-proxy -p 1234 -i lo
857```
858
859### 2 Start the SOCKS5 proxy
860
861```
862$ ssh -D 1337 -N -v localhost
863```
864
865The -v makes connections to the proxy visible in the terminal for testing
866
867### 3 Run the SS application
868
869The application is told to make all connections via the socks5 proxy at
870127.0.0.1:1337, and to fulfil its SS connections via an SS proxy, binding
871connections to 127.0.0.1 (ipv4 lo interface, -1), to 127.0.0.1:1234 (-a/-p).
872
873```
874socks_proxy=127.0.0.1:1337 ./bin/lws-minimal-secure-streams-client -p 1234 -i 127.0.0.1 -a 127.0.0.1
875```
876
877You can confirm this goes through the ssh socks5 proxy to get to the SS proxy
878and fulfil the connection.
879
880## Using static policies
881
882If one of your targets is too constrained to make use of dynamic JSON policies, but
883using SS and the policies is attractive for wider reasons, you can use a static policy
884built into the firmware for the constrained target.
885
886The secure-streams example "policy2c" (which runs on the build machine, not the device)
887
888https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/secure-streams/minimal-secure-streams-policy2c
889
890accepts a normal JSON policy on stdin, and emits a C code representation that can be
891included directly in the firmware.
892
893https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.h
894
895Using this technique it's possible to standardize on maintaining JSON policies across a
896range of devices with different contraints, and use the C conversion of the policy on devices
897that are too small.
898
899The Cmake option `LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY` should be enabled to use this
900mode, it will not build the JSON parser (and the option for LEJP can also be disabled if
901you're not otherwise using it, saving an additional couple of KB).
902
903Notice policy2c example tool must be built with `LWS_ROLE_H1`, `LWS_ROLE_H2`, `LWS_ROLE_WS`
904and `LWS_ROLE_MQTT` enabled so it can handle any kind of policy.
905
906## HTTP and ws serving
907
908All ws servers start out as http servers... for that reason ws serving is
909handled as part of http serving, if you give the `ws_subprotocol` entry to the
910streamtype additionally, the server will also accept upgrades to ws.
911
912To help the user code understand if the upgrade occurred, there's a special
913state `LWSSSCS_SERVER_UPGRADE`, so subsequent rx and tx can be understood to
914have come from the upgraded protocol.  To allow separation of rx and tx
915handling between http and ws, there's a ss api `lws_ss_change_handlers()`
916which allows dynamically setting SS handlers.
917
918Since the http and ws upgrade identity is encapsulated in one streamtype, the
919user object for the server streamtype should contain related user data for both
920http and ws underlying protocol identity.
921