1 | /* |
2 | * libwebsockets - small server side websockets and web server implementation |
3 | * |
4 | * Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com> |
5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | * of this software and associated documentation files (the "Software"), to |
8 | * deal in the Software without restriction, including without limitation the |
9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
10 | * sell copies of the Software, and to permit persons to whom the Software is |
11 | * furnished to do so, subject to the following conditions: |
12 | * |
13 | * The above copyright notice and this permission notice shall be included in |
14 | * all copies or substantial portions of the Software. |
15 | * |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
22 | * IN THE SOFTWARE. |
23 | * |
24 | * included from libwebsockets.h |
25 | * |
26 | * |
27 | * Secure Streams is a *payload-only* client communication channel where all the |
28 | * details about the connection are held in a systemwide policy database and |
29 | * are keyed by the streamtype field... the user of the communication channel |
30 | * does not know or manage the choice of endpoint, tls CA, or even wire |
31 | * protocol. The advantage is he then does not have any dependency on any of |
32 | * those and they can be changed just by changing the policy database without |
33 | * touching the code using the stream. |
34 | * |
35 | * There are two ways secure streams interfaces to user code: |
36 | * |
37 | * 1) [Linux / RTOS] the natural, smallest interface is to call back to user |
38 | * code that only operates directly from the lws event loop thread context |
39 | * (direct callbacks from lws_ss_t) |
40 | * |
41 | * lws_thread( [user code] ---- lws ) |
42 | * |
43 | * 2) [Linux] where the user code is in a different process and communicates |
44 | * asynchronously via a proxy socket |
45 | * |
46 | * user_process{ [user code] | shim | socket-}------ lws_process{ lws } |
47 | * |
48 | * In the second, IPC, case, all packets are prepended by one or more bytes |
49 | * indicating the packet type and serializing any associated data, known as |
50 | * Serialized Secure Streams or SSS. |
51 | * |
52 | * Serialized Secure Streams |
53 | * ------------------------- |
54 | * |
55 | * On the transport, adjacent packets may be coalesced, that is, the original |
56 | * packet sizes are lost and two or more packets are combined. For that reason |
57 | * the serialization format always contains a 1-byte type and then a 2-byte |
58 | * frame length. |
59 | * |
60 | * Client to proxy |
61 | * |
62 | * - Proxied connection setup |
63 | * |
64 | * - 0: LWSSS_SER_TXPRE_STREAMTYPE |
65 | * - 1: 2-byte MSB-first rest-of-frame length |
66 | * - 3: 1-byte Client SSS protocol version (introduced in SSSv1) |
67 | * - 4: 4-byte Client PID (introduced in SSSv1) |
68 | * - 8: 4-byte MSB-first initial tx credit |
69 | * - 12: the streamtype name with no NUL |
70 | * |
71 | * - Proxied tx |
72 | * |
73 | * - 0: LWSSS_SER_TXPRE_TX_PAYLOAD |
74 | * - 1: 2 byte MSB-first rest-of-frame length |
75 | * - 3: 4-byte MSB-first flags |
76 | * - 7: 4-byte MSB-first us between client requested write and wrote to proxy |
77 | * - 11: 8-byte MSB-first us resolution unix time client wrote to proxy |
78 | * - 19: payload |
79 | * |
80 | * - Proxied secure stream destroy |
81 | * |
82 | * - 0: LWSSS_SER_TXPRE_DESTROYING |
83 | * - 1: 00, 00 |
84 | * |
85 | * - Proxied metadata - sent when one metadata item set clientside |
86 | * |
87 | * - 0: LWSSS_SER_TXPRE_METADATA |
88 | * - 1: 2-byte MSB-first rest-of-frame length |
89 | * - 3: 1-byte metadata name length |
90 | * - 4: metadata name |
91 | * - ...: metadata value (for rest of packet) |
92 | * |
93 | * - TX credit management - sent when using tx credit apis, cf METADATA |
94 | * |
95 | * - 0: LWSSS_SER_TXPRE_TXCR_UPDATE |
96 | * - 1: 2-byte MSB-first rest-of-frame length 00, 04 |
97 | * - 3: 4-byte additional tx credit adjust value |
98 | * |
99 | * - Stream timeout management - forwarded when user applying or cancelling t.o. |
100 | * |
101 | * - 0: LWSSS_SER_TXPRE_TIMEOUT_UPDATE |
102 | * - 1: 2-byte MSB-first rest-of-frame length 00, 04 |
103 | * - 3: 4-byte MSB-first unsigned 32-bit timeout, 0 = use policy, -1 = cancel |
104 | * |
105 | * - Passing up payload length hint |
106 | * |
107 | * - 0: LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT |
108 | * - 1: 2-byte MSB-first rest-of-frame length 00, 04 |
109 | * - 3: 4-byte MSB-first unsigned 32-bit payload length hint |
110 | * |
111 | * Proxy to client |
112 | * |
113 | * - Proxied connection setup result |
114 | * |
115 | * - 0: LWSSS_SER_RXPRE_CREATE_RESULT |
116 | * - 1: 2 byte MSB-first rest-of-frame length (usually 00, 03) |
117 | * - 3: 1 byte result, 0 = success. On failure, proxy will close connection. |
118 | * - 4: 4 byte client dsh allocation recommended for stream type, from policy |
119 | * (introduced in SSSv1) |
120 | * - 8: 2 byte MSB-first initial tx credit |
121 | * - 10: if present, comma-sep list of rideshare types from policy |
122 | * |
123 | * - Proxied rx |
124 | * |
125 | * - 0: LWSSS_SER_RXPRE_RX_PAYLOAD |
126 | * - 1: 2 byte MSB-first rest-of-frame length |
127 | * - 3: 4-byte MSB-first flags |
128 | * - 7: 4-byte MSB-first us between inbound read and wrote to client |
129 | * - 11: 8-byte MSB-first us resolution unix time proxy wrote to client |
130 | * - 17: (rideshare name len + rideshare name if flags & LWSSS_FLAG_RIDESHARE) |
131 | * payload |
132 | * |
133 | * - Proxied tx credit |
134 | * |
135 | * - 0: LWSSS_SER_RXPRE_TXCR_UPDATE |
136 | * - 1: 00, 04 |
137 | * - 3: 4-byte MSB-first addition tx credit bytes |
138 | * |
139 | * - Proxied rx metadata |
140 | * |
141 | * - 0: LWSSS_SER_RXPRE_METADATA |
142 | * - 1: 2-byte MSB-first rest-of-frame length |
143 | * - 3: 1-byte metadata name length |
144 | * - 4: metadata name |
145 | * - ...: metadata value (for rest of packet) |
146 | * |
147 | * - Proxied state (8 or 11 byte packet) |
148 | * |
149 | * - 0: LWSSS_SER_RXPRE_CONNSTATE |
150 | * - 1: 00, 05 if state < 256, else 00, 08 |
151 | * - 3: 1 byte state index if state < 256, else 4-byte MSB-first state index |
152 | * - 4 or 7: 4-byte MSB-first ordinal |
153 | * |
154 | * - Proxied performance information |
155 | * |
156 | * - 0: LWSSS_SER_RXPRE_PERF |
157 | * - 1: 2-byte MSB-first rest-of-frame length |
158 | * - 3: ... performance JSON (for rest of packet) |
159 | * |
160 | * Proxied tx may be read by the proxy but rejected due to lack of buffer space |
161 | * at the proxy. For that reason, tx must be held at the sender until it has |
162 | * been acknowledged or denied. |
163 | * |
164 | * Sinks |
165 | * ----- |
166 | * |
167 | * Sinks are logical "servers", you can register as a sink for a particular |
168 | * streamtype by using the lws_ss_create() api with ssi->register_sink set to 1. |
169 | * |
170 | * For directly fulfilled Secure Streams, new streams of that streamtype bind |
171 | * to the rx, tx and state handlers given when it was registered. |
172 | * |
173 | * - When new streams are created the registered sink handler for (*state) is |
174 | * called with event LWSSSCS_SINK_JOIN and the new client stream handle in |
175 | * the h_src parameter. |
176 | * |
177 | * - When the client stream sends something to the sink, it calls the sink's |
178 | * (*rx) with the client stream's |
179 | */ |
180 | |
181 | /** \defgroup secstr Secure Streams |
182 | * ##Secure Streams |
183 | * |
184 | * Secure Streams related apis |
185 | */ |
186 | ///@{ |
187 | |
188 | #define LWS_SS_MTU 1540 |
189 | |
190 | struct lws_ss_handle; |
191 | typedef uint32_t lws_ss_tx_ordinal_t; |
192 | |
193 | /* |
194 | * connection state events |
195 | * |
196 | * If you add states, take care about the state names and state transition |
197 | * validity enforcement tables too |
198 | */ |
199 | typedef enum { |
200 | /* zero means unset */ |
201 | LWSSSCS_CREATING = 1, |
202 | LWSSSCS_DISCONNECTED, |
203 | LWSSSCS_UNREACHABLE, /* oridinal arg = 1 = caused by dns |
204 | * server reachability failure */ |
205 | LWSSSCS_AUTH_FAILED, |
206 | LWSSSCS_CONNECTED, |
207 | LWSSSCS_CONNECTING, |
208 | LWSSSCS_DESTROYING, |
209 | LWSSSCS_POLL, |
210 | LWSSSCS_ALL_RETRIES_FAILED, /* all retries in bo policy failed */ |
211 | LWSSSCS_QOS_ACK_REMOTE, /* remote peer received and acked tx */ |
212 | LWSSSCS_QOS_NACK_REMOTE, |
213 | LWSSSCS_QOS_ACK_LOCAL, /* local proxy accepted our tx */ |
214 | LWSSSCS_QOS_NACK_LOCAL, /* local proxy refused our tx */ |
215 | LWSSSCS_TIMEOUT, /* optional timeout timer fired */ |
216 | |
217 | LWSSSCS_SERVER_TXN, |
218 | LWSSSCS_SERVER_UPGRADE, /* the server protocol upgraded */ |
219 | |
220 | LWSSSCS_EVENT_WAIT_CANCELLED, /* somebody called lws_cancel_service */ |
221 | |
222 | LWSSSCS_UPSTREAM_LINK_RETRY, /* if we are being proxied over some |
223 | * intermediate link, this transient |
224 | * state may be sent to indicate we are |
225 | * waiting to establish that link before |
226 | * creation can proceed.. ack is the |
227 | * number of ms we have been trying */ |
228 | |
229 | LWSSSCS_SINK_JOIN, /* sinks get this when a new source |
230 | * stream joins the sink */ |
231 | LWSSSCS_SINK_PART, /* sinks get this when a new source |
232 | * stream leaves the sink */ |
233 | |
234 | LWSSSCS_USER_BASE = 1000 |
235 | } lws_ss_constate_t; |
236 | |
237 | enum { |
238 | LWSSS_FLAG_SOM = (1 << 0), |
239 | /* payload contains the start of new message */ |
240 | LWSSS_FLAG_EOM = (1 << 1), |
241 | /* payload contains the end of message */ |
242 | LWSSS_FLAG_POLL = (1 << 2), |
243 | /* Not a real transmit... poll for rx if protocol needs it */ |
244 | LWSSS_FLAG_RELATED_START = (1 << 3), |
245 | /* Appears in a zero-length message indicating a message group of zero |
246 | * or more messages is now starting. */ |
247 | LWSSS_FLAG_RELATED_END = (1 << 4), |
248 | /* Appears in a zero-length message indicating a message group of zero |
249 | * or more messages has now finished. */ |
250 | LWSSS_FLAG_RIDESHARE = (1 << 5), |
251 | /* Serialized payload starts with non-default rideshare name length and |
252 | * name string without NUL, then payload */ |
253 | LWSSS_FLAG_PERF_JSON = (1 << 6), |
254 | /* This RX is JSON performance data, only on streams with "perf" flag |
255 | * set */ |
256 | |
257 | /* |
258 | * In the case the secure stream is proxied across a process or thread |
259 | * boundary, eg by proxying through a socket for IPC, metadata must be |
260 | * carried in-band. A byte is prepended to each rx payload to |
261 | * differentiate what it is. |
262 | * |
263 | * Secure streams where the user is called back directly does not need |
264 | * any of this and only pure payloads are passed. |
265 | * |
266 | * rx (received by client) prepends for proxied connections |
267 | */ |
268 | |
269 | LWSSS_SER_RXPRE_RX_PAYLOAD = 0x55, |
270 | LWSSS_SER_RXPRE_CREATE_RESULT, |
271 | LWSSS_SER_RXPRE_CONNSTATE, |
272 | LWSSS_SER_RXPRE_TXCR_UPDATE, |
273 | LWSSS_SER_RXPRE_METADATA, |
274 | LWSSS_SER_RXPRE_TLSNEG_ENCLAVE_SIGN, |
275 | LWSSS_SER_RXPRE_PERF, |
276 | |
277 | /* tx (send by client) prepends for proxied connections */ |
278 | |
279 | LWSSS_SER_TXPRE_STREAMTYPE = 0xaa, |
280 | LWSSS_SER_TXPRE_ONWARD_CONNECT, |
281 | LWSSS_SER_TXPRE_DESTROYING, |
282 | LWSSS_SER_TXPRE_TX_PAYLOAD, |
283 | LWSSS_SER_TXPRE_METADATA, |
284 | LWSSS_SER_TXPRE_TXCR_UPDATE, |
285 | LWSSS_SER_TXPRE_TIMEOUT_UPDATE, |
286 | LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT, |
287 | LWSSS_SER_TXPRE_TLSNEG_ENCLAVE_SIGNED, |
288 | }; |
289 | |
290 | typedef enum { |
291 | LPCSPROX_WAIT_INITIAL_TX = 1, /* after connect, must send streamtype */ |
292 | LPCSPROX_REPORTING_FAIL, /* stream creation failed, wait to to tell */ |
293 | LPCSPROX_REPORTING_OK, /* stream creation succeeded, wait to to tell */ |
294 | LPCSPROX_OPERATIONAL, /* ready for payloads */ |
295 | LPCSPROX_DESTROYED, |
296 | |
297 | LPCSCLI_SENDING_INITIAL_TX, /* after connect, must send streamtype */ |
298 | LPCSCLI_WAITING_CREATE_RESULT, /* wait to hear if proxy ss create OK */ |
299 | LPCSCLI_LOCAL_CONNECTED, /* we are in touch with the proxy */ |
300 | LPCSCLI_ONWARD_CONNECT, /* request onward ss connection */ |
301 | LPCSCLI_OPERATIONAL, /* ready for payloads */ |
302 | |
303 | } lws_ss_conn_states_t; |
304 | |
305 | /* |
306 | * Returns from state() callback can tell the caller what the user code |
307 | * wants to do |
308 | */ |
309 | |
310 | typedef enum lws_ss_state_return { |
311 | LWSSSSRET_TX_DONT_SEND = 1, /* (*tx) only, or failure */ |
312 | |
313 | LWSSSSRET_OK = 0, /* no error */ |
314 | LWSSSSRET_DISCONNECT_ME = -1, /* caller should disconnect us */ |
315 | LWSSSSRET_DESTROY_ME = -2, /* caller should destroy us */ |
316 | } lws_ss_state_return_t; |
317 | |
318 | /** |
319 | * lws_ss_info_t: information about stream to be created |
320 | * |
321 | * Prepare this struct with information about what the stream type is and how |
322 | * the stream should interface with your code, and pass it to lws_ss_create() |
323 | * to create the requested stream. |
324 | */ |
325 | |
326 | enum { |
327 | LWSSSINFLAGS_REGISTER_SINK = (1 << 0), |
328 | /**< If set, we're not creating a specific stream, but registering |
329 | * ourselves as the "sink" for .streamtype. It's analogous to saying |
330 | * we want to be the many-to-one "server" for .streamtype; when other |
331 | * streams are created with that streamtype, they should be forwarded |
332 | * to this stream owner, where they join and part from the sink via |
333 | * (*state) LWSSSCS_SINK_JOIN / _PART events, the new client handle |
334 | * being provided in the h_src parameter. |
335 | */ |
336 | LWSSSINFLAGS_PROXIED = (1 << 1), |
337 | /**< Set if the stream is being created as a stand-in at the proxy */ |
338 | LWSSSINFLAGS_SERVER = (1 << 2), |
339 | /**< Set on the server object copy of the ssi / info to indicate that |
340 | * stream creation using this ssi is for Accepted connections belonging |
341 | * to a server */ |
342 | LWSSSINFLAGS_ACCEPTED = (1 << 3), |
343 | /**< Set on the accepted object copy of the ssi / info to indicate that |
344 | * we are an accepted connection from a server's listening socket */ |
345 | }; |
346 | |
347 | typedef lws_ss_state_return_t (*lws_sscb_rx)(void *userobj, const uint8_t *buf, |
348 | size_t len, int flags); |
349 | typedef lws_ss_state_return_t (*lws_sscb_tx)(void *userobj, |
350 | lws_ss_tx_ordinal_t ord, |
351 | uint8_t *buf, size_t *len, |
352 | int *flags); |
353 | typedef lws_ss_state_return_t (*lws_sscb_state)(void *userobj, void *h_src, |
354 | lws_ss_constate_t state, |
355 | lws_ss_tx_ordinal_t ack); |
356 | |
357 | #if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP) |
358 | typedef void (*lws_ss_buffer_dump_cb)(void *userobj, const uint8_t *buf, |
359 | size_t len, int done); |
360 | #endif |
361 | |
362 | struct lws_ss_policy; |
363 | |
364 | typedef struct lws_ss_info { |
365 | const char *streamtype; /**< type of stream we want to create */ |
366 | size_t user_alloc; /**< size of user allocation */ |
367 | size_t handle_offset; /**< offset of handle stg in user_alloc type, |
368 | set to offsetof(mytype, my_handle_member) */ |
369 | size_t opaque_user_data_offset; |
370 | /**< offset of opaque user data ptr in user_alloc type, set to |
371 | offsetof(mytype, opaque_ud_member) */ |
372 | |
373 | #if defined(LWS_WITH_SECURE_STREAMS_CPP) |
374 | const struct lws_ss_policy *policy; |
375 | /**< Normally NULL, or a locally-generated policy to apply to this |
376 | * connection instead of a named streamtype */ |
377 | #endif |
378 | |
379 | #if defined(LWS_WITH_SYS_FAULT_INJECTION) |
380 | lws_fi_ctx_t fic; |
381 | /**< Attach external Fault Injection context to the stream, hierarchy |
382 | * is ss->context */ |
383 | #endif |
384 | |
385 | lws_sscb_rx rx; |
386 | /**< callback with rx payload for this stream */ |
387 | lws_sscb_tx tx; |
388 | /**< callback to send payload on this stream... 0 = send as set in |
389 | * len and flags, 1 = do not send anything (ie, not even 0 len frame) */ |
390 | lws_sscb_state state; |
391 | /**< advisory cb about state of stream and QoS status if applicable... |
392 | * h_src is only used with sinks and LWSSSCS_SINK_JOIN/_PART events. |
393 | * Return nonzero to indicate you want to destroy the stream. */ |
394 | #if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP) |
395 | lws_ss_buffer_dump_cb dump; |
396 | /**< cb to record needed protocol buffer data*/ |
397 | #endif |
398 | int manual_initial_tx_credit; |
399 | /**< 0 = manage any tx credit automatically, nonzero explicitly sets the |
400 | * peer stream to have the given amount of tx credit, if the protocol |
401 | * can support it. |
402 | * |
403 | * In the special case of _lws_smd streamtype, this is used to indicate |
404 | * the connection's rx class mask. |
405 | * */ |
406 | uint32_t client_pid; |
407 | /**< used in proxy / serialization case to hold the client pid this |
408 | * proxied connection is to be tagged with |
409 | */ |
410 | uint8_t flags; |
411 | uint8_t sss_protocol_version; |
412 | /**< used in proxy / serialization case to hold the SS serialization |
413 | * protocol level to use with this peer... clients automatically request |
414 | * the most recent version they were built with |
415 | * (LWS_SSS_CLIENT_PROTOCOL_VERSION) and the proxy stores the requested |
416 | * version in here |
417 | */ |
418 | |
419 | } lws_ss_info_t; |
420 | |
421 | /** |
422 | * lws_ss_create() - Create secure stream |
423 | * |
424 | * \param context: the lws context to create this inside |
425 | * \param tsi: service thread index to create on (normally 0) |
426 | * \param ssi: pointer to lws_ss_info_t filled in with info about desired stream |
427 | * \param opaque_user_data: opaque data to set in the stream's user object |
428 | * \param ppss: pointer to secure stream handle pointer set on exit |
429 | * \param ppayload_fmt: NULL or pointer to a string ptr to take payload format |
430 | * name from the policy |
431 | * |
432 | * Requests a new secure stream described by \p ssi be created. If successful, |
433 | * the stream is created, its state callback called with LWSSSCS_CREATING, \p *ppss |
434 | * is set to point to the handle, and it returns 0. If it failed, it returns |
435 | * nonzero. |
436 | * |
437 | * Along with the opaque stream object, streams overallocate |
438 | * |
439 | * 1) a user data struct whose size is set in ssi |
440 | * 2) nauth plugin instantiation data (size set in the plugin struct) |
441 | * 3) sauth plugin instantiation data (size set in the plugin struct) |
442 | * 4) space for a copy of the stream type name |
443 | * |
444 | * The user data struct is initialized to all zeros, then the .handle_offset and |
445 | * .opaque_user_data_offset fields of the ssi are used to prepare the user data |
446 | * struct with the ss handle that was created, and a copy of the |
447 | * opaque_user_data pointer given as an argument. |
448 | * |
449 | * If you want to set up the stream with specific information, point to it in |
450 | * opaque_user_data and use the copy of that pointer in your user data member |
451 | * for it starting from the LWSSSCS_CREATING state call. |
452 | * |
453 | * Since different endpoints chosen by the policy may require different payload |
454 | * formats, \p ppayload_fmt is set to point to the name of the needed payload |
455 | * format from the policy database if non-NULL. |
456 | */ |
457 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
458 | lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, |
459 | void *opaque_user_data, struct lws_ss_handle **ppss, |
460 | struct lws_sequencer *seq_owner, const char **ppayload_fmt); |
461 | |
462 | /** |
463 | * lws_ss_destroy() - Destroy secure stream |
464 | * |
465 | * \param ppss: pointer to lws_ss_t pointer to be destroyed |
466 | * |
467 | * Destroys the lws_ss_t pointed to by \p *ppss, and sets \p *ppss to NULL. |
468 | */ |
469 | LWS_VISIBLE LWS_EXTERN void |
470 | lws_ss_destroy(struct lws_ss_handle **ppss); |
471 | |
472 | /** |
473 | * lws_ss_request_tx() - Schedule stream for tx |
474 | * |
475 | * \param pss: pointer to lws_ss_t representing stream that wants to transmit |
476 | * |
477 | * Schedules a write on the stream represented by \p pss. When it's possible to |
478 | * write on this stream, the \p *tx callback will occur with an empty buffer for |
479 | * the stream owner to fill in. |
480 | * |
481 | * Returns 0 or LWSSSSRET_DESTROY_ME |
482 | */ |
483 | LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT |
484 | lws_ss_request_tx(struct lws_ss_handle *pss); |
485 | |
486 | /** |
487 | * lws_ss_request_tx() - Schedule stream for tx |
488 | * |
489 | * \param pss: pointer to lws_ss_t representing stream that wants to transmit |
490 | * \param len: the length of the write in bytes |
491 | * |
492 | * Schedules a write on the stream represented by \p pss. When it's possible to |
493 | * write on this stream, the \p *tx callback will occur with an empty buffer for |
494 | * the stream owner to fill in. |
495 | * |
496 | * This api variant should be used when it's possible the payload will go out |
497 | * over h1 with x-web-form-urlencoded or similar Content-Type. |
498 | */ |
499 | LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT |
500 | lws_ss_request_tx_len(struct lws_ss_handle *pss, unsigned long len); |
501 | |
502 | /** |
503 | * lws_ss_client_connect() - Attempt the client connect |
504 | * |
505 | * \param h: secure streams handle |
506 | * |
507 | * Starts the connection process for the secure stream. |
508 | * |
509 | * Can return any of the lws_ss_state_return_t values depending on user |
510 | * state callback returns. |
511 | * |
512 | * LWSSSSRET_OK means the connection is ongoing. |
513 | * |
514 | */ |
515 | LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT |
516 | lws_ss_client_connect(struct lws_ss_handle *h); |
517 | |
518 | /** |
519 | * lws_ss_get_sequencer() - Return parent sequencer pointer if any |
520 | * |
521 | * \param h: secure streams handle |
522 | * |
523 | * Returns NULL if the secure stream is not associated with a sequencer. |
524 | * Otherwise returns a pointer to the owning sequencer. You can use this to |
525 | * identify which sequencer to direct messages to, from the secure stream |
526 | * callback. |
527 | */ |
528 | LWS_VISIBLE LWS_EXTERN struct lws_sequencer * |
529 | lws_ss_get_sequencer(struct lws_ss_handle *h); |
530 | |
531 | /** |
532 | * lws_ss_proxy_create() - Start a unix domain socket proxy for Secure Streams |
533 | * |
534 | * \param context: lws_context |
535 | * \param bind: if port is 0, unix domain path with leading @ for abstract. |
536 | * if port nonzero, NULL, or network interface to bind listen to |
537 | * \param port: tcp port to listen on |
538 | * |
539 | * Creates a vhost that listens either on an abstract namespace unix domain |
540 | * socket (port = 0) or a tcp listen socket (port nonzero). If bind is NULL |
541 | * and port is 0, the abstract unix domain socket defaults to "proxy.ss.lws". |
542 | * |
543 | * Client connections to this proxy to Secure Streams are fulfilled using the |
544 | * policy local to the proxy and the data passed between the client and the |
545 | * proxy using serialized Secure Streams protocol. |
546 | */ |
547 | LWS_VISIBLE LWS_EXTERN int |
548 | lws_ss_proxy_create(struct lws_context *context, const char *bind, int port); |
549 | |
550 | /** |
551 | * lws_ss_state_name() - convenience helper to get a printable conn state name |
552 | * |
553 | * \param state: the connection state index |
554 | * |
555 | * Returns a printable name for the connection state index passed in. |
556 | */ |
557 | LWS_VISIBLE LWS_EXTERN const char * |
558 | lws_ss_state_name(int state); |
559 | |
560 | /** |
561 | * lws_ss_get_context() - convenience helper to recover the lws context |
562 | * |
563 | * \param h: secure streams handle |
564 | * |
565 | * Returns the lws context. Dispenses with the need to pass a copy of it into |
566 | * your secure streams handler. |
567 | */ |
568 | LWS_VISIBLE LWS_EXTERN struct lws_context * |
569 | lws_ss_get_context(struct lws_ss_handle *h); |
570 | |
571 | #define LWSSS_TIMEOUT_FROM_POLICY 0 |
572 | |
573 | /** |
574 | * lws_ss_start_timeout() - start or restart the timeout on the stream |
575 | * |
576 | * \param h: secure streams handle |
577 | * \param timeout_ms: LWSSS_TIMEOUT_FROM_POLICY for policy value, else use timeout_ms |
578 | * |
579 | * Starts or restarts the stream's own timeout timer. If the specified time |
580 | * passes without lws_ss_cancel_timeout() being called on the stream, then the |
581 | * stream state callback receives LWSSSCS_TIMEOUT |
582 | * |
583 | * The process being protected by the timeout is up to the user code, it may be |
584 | * arbitrarily long and cross multiple protocol transactions or involve other |
585 | * streams. It's up to the user to decide when to start and when / if to cancel |
586 | * the stream timeout. |
587 | */ |
588 | LWS_VISIBLE LWS_EXTERN void |
589 | lws_ss_start_timeout(struct lws_ss_handle *h, unsigned int timeout_ms); |
590 | |
591 | /** |
592 | * lws_ss_cancel_timeout() - remove any timeout on the stream |
593 | * |
594 | * \param h: secure streams handle |
595 | * |
596 | * Disable any timeout that was applied to the stream by lws_ss_start_timeout(). |
597 | */ |
598 | LWS_VISIBLE LWS_EXTERN void |
599 | lws_ss_cancel_timeout(struct lws_ss_handle *h); |
600 | |
601 | /** |
602 | * lws_ss_to_user_object() - convenience helper to get user object from handle |
603 | * |
604 | * \param h: secure streams handle |
605 | * |
606 | * Returns the user allocation related to the handle. Normally you won't need |
607 | * this since it's available in the rx, tx and state callbacks as "userdata" |
608 | * already. |
609 | */ |
610 | LWS_VISIBLE LWS_EXTERN void * |
611 | lws_ss_to_user_object(struct lws_ss_handle *h); |
612 | |
613 | /** |
614 | * lws_ss_rideshare() - find the current streamtype when types rideshare |
615 | * |
616 | * \param h: the stream handle |
617 | * |
618 | * Under some conditions, the payloads may be structured using protocol- |
619 | * specific formatting, eg, http multipart mime. It's possible to map the |
620 | * logical partitions in the payload to different stream types using |
621 | * the policy "rideshare" feature. |
622 | * |
623 | * This api lets the callback code find out which rideshare stream type the |
624 | * current payload chunk belongs to. |
625 | */ |
626 | LWS_VISIBLE LWS_EXTERN const char * |
627 | lws_ss_rideshare(struct lws_ss_handle *h); |
628 | |
629 | |
630 | /** |
631 | * lws_ss_set_metadata() - allow user to bind external data to defined ss metadata |
632 | * |
633 | * \param h: secure streams handle |
634 | * \param name: metadata name from the policy |
635 | * \param value: pointer to user-managed data to bind to name |
636 | * \param len: length of the user-managed data in value |
637 | * |
638 | * Binds user-managed data to the named metadata item from the ss policy. |
639 | * If present, the metadata item is handled in a protocol-specific way using |
640 | * the associated policy information. For example, in the policy |
641 | * |
642 | * "\"metadata\":" "[" |
643 | * "{\"uptag\":" "\"X-Upload-Tag:\"}," |
644 | * "{\"ctype\":" "\"Content-Type:\"}," |
645 | * "{\"xctype\":" "\"\"}" |
646 | * "]," |
647 | * |
648 | * when the policy is using h1 is interpreted to add h1 headers of the given |
649 | * name with the value of the metadata on the left. |
650 | * |
651 | * Return 0 if OK or nonzero if, eg, metadata name does not exist on the |
652 | * streamtype. You must check the result of this, eg, transient OOM can cause |
653 | * these to fail and you should retry later. |
654 | */ |
655 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
656 | lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, |
657 | const void *value, size_t len); |
658 | |
659 | /** |
660 | * lws_ss_alloc_set_metadata() - copy data and bind to ss metadata |
661 | * |
662 | * \param h: secure streams handle |
663 | * \param name: metadata name from the policy |
664 | * \param value: pointer to user-managed data to bind to name |
665 | * \param len: length of the user-managed data in value |
666 | * |
667 | * Same as lws_ss_set_metadata(), but allocates a heap buffer for the data |
668 | * first and takes a copy of it, so the original can go out of scope |
669 | * immediately after. |
670 | */ |
671 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
672 | lws_ss_alloc_set_metadata(struct lws_ss_handle *h, const char *name, |
673 | const void *value, size_t len); |
674 | |
675 | /** |
676 | * lws_ss_get_metadata() - get current value of stream metadata item |
677 | * |
678 | * \param h: secure streams handle |
679 | * \param name: metadata name from the policy |
680 | * \param value: pointer to pointer to be set to point at the value |
681 | * \param len: pointer to size_t to set to the length of the value |
682 | * |
683 | * Binds user-managed data to the named metadata item from the ss policy. |
684 | * If present, the metadata item is handled in a protocol-specific way using |
685 | * the associated policy information. For example, in the policy |
686 | * |
687 | * "\"metadata\":" "[" |
688 | * "{\"uptag\":" "\"X-Upload-Tag:\"}," |
689 | * "{\"ctype\":" "\"Content-Type:\"}," |
690 | * "{\"xctype\":" "\"\"}" |
691 | * "]," |
692 | * |
693 | * when the policy is using h1 is interpreted to add h1 headers of the given |
694 | * name with the value of the metadata on the left. |
695 | * |
696 | * Return 0 if \p *value and \p *len set OK, or nonzero if, eg, metadata \p name does |
697 | * not exist on the streamtype. |
698 | * |
699 | * The pointed-to values may only exist until the next time around the event |
700 | * loop. |
701 | */ |
702 | LWS_VISIBLE LWS_EXTERN int |
703 | lws_ss_get_metadata(struct lws_ss_handle *h, const char *name, |
704 | const void **value, size_t *len); |
705 | |
706 | /** |
707 | * lws_ss_server_ack() - indicate how we feel about what the server has sent |
708 | * |
709 | * \param h: ss handle of accepted connection |
710 | * \param nack: 0 means we are OK with it, else some problem |
711 | * |
712 | * For SERVER secure streams |
713 | * |
714 | * Depending on the protocol, the server sending us something may be |
715 | * transactional, ie, built into it sending something is the idea we will |
716 | * respond somehow out-of-band; HTTP is like this with, eg, 200 response code. |
717 | * |
718 | * Calling this with nack=0 indicates that when we later respond, we want to |
719 | * acknowledge the transaction (eg, it means a 200 if http underneath), if |
720 | * nonzero that the transaction should act like it failed. |
721 | * |
722 | * If the underlying protocol doesn't understand transactions (eg, ws) then this |
723 | * has no effect either way. |
724 | */ |
725 | LWS_VISIBLE LWS_EXTERN void |
726 | lws_ss_server_ack(struct lws_ss_handle *h, int nack); |
727 | |
728 | typedef void (*lws_sssfec_cb)(struct lws_ss_handle *h, void *arg); |
729 | |
730 | /** |
731 | * lws_ss_server_foreach_client() - callback for each live client connected to server |
732 | * |
733 | * \param h: server ss handle |
734 | * \param cb: the callback |
735 | * \param arg: arg passed to callback |
736 | * |
737 | * For SERVER secure streams |
738 | * |
739 | * Call the callback \p cb once for each client ss connected to the server, |
740 | * passing \p arg as an additional callback argument each time. |
741 | */ |
742 | LWS_VISIBLE LWS_EXTERN void |
743 | lws_ss_server_foreach_client(struct lws_ss_handle *h, lws_sssfec_cb cb, |
744 | void *arg); |
745 | |
746 | /** |
747 | * lws_ss_change_handlers() - helper for dynamically changing stream handlers |
748 | * |
749 | * \param h: ss handle |
750 | * \param rx: the new RX handler |
751 | * \param tx: the new TX handler |
752 | * \param state: the new state handler |
753 | * |
754 | * Handlers set to NULL are left unchanged. |
755 | * |
756 | * This works on any handle, client or server and takes effect immediately. |
757 | * |
758 | * Depending on circumstances this may be helpful when |
759 | * |
760 | * a) a server stream undergoes an LWSSSCS_SERVER_UPGRADE (as in http -> ws) and |
761 | * the payloads in the new protocol have a different purpose that is best |
762 | * handled in their own rx and tx callbacks, and |
763 | * |
764 | * b) you may want to serve several different, possibly large things based on |
765 | * what was requested. Setting a customized handler allows clean encapsulation |
766 | * of the different serving strategies. |
767 | * |
768 | * If the stream is long-lived, like ws, you should set the changed handler back |
769 | * to the default when the transaction wanting it is completed. |
770 | */ |
771 | LWS_VISIBLE LWS_EXTERN void |
772 | lws_ss_change_handlers(struct lws_ss_handle *h, lws_sscb_rx rx, lws_sscb_tx tx, |
773 | lws_sscb_state state); |
774 | |
775 | /** |
776 | * lws_ss_add_peer_tx_credit() - allow peer to transmit more to us |
777 | * |
778 | * \param h: secure streams handle |
779 | * \param add: additional tx credit (signed) |
780 | * |
781 | * Indicate to remote peer that we can accept \p add bytes more payload being |
782 | * sent to us. |
783 | */ |
784 | LWS_VISIBLE LWS_EXTERN int |
785 | lws_ss_add_peer_tx_credit(struct lws_ss_handle *h, int32_t add); |
786 | |
787 | /** |
788 | * lws_ss_get_est_peer_tx_credit() - get our current estimate of peer's tx credit |
789 | * |
790 | * \param h: secure streams handle |
791 | * |
792 | * Based on what credit we gave it, and what we have received, report our |
793 | * estimate of peer's tx credit usable to transmit to us. This may be outdated |
794 | * in that some or all of its credit may already have been expended by sending |
795 | * stuff to us that is in flight already. |
796 | */ |
797 | LWS_VISIBLE LWS_EXTERN int |
798 | lws_ss_get_est_peer_tx_credit(struct lws_ss_handle *h); |
799 | |
800 | LWS_VISIBLE LWS_EXTERN const char * |
801 | lws_ss_tag(struct lws_ss_handle *h); |
802 | |
803 | |
804 | #if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4) |
805 | /** |
806 | * lws_ss_sigv4_set_aws_key() - set aws credential into system blob |
807 | * |
808 | * \param context: lws_context |
809 | * \param idx: the system blob index specified in the policy, currently |
810 | * up to 4 blobs. |
811 | * \param keyid: aws access keyid |
812 | * \param key: aws access key |
813 | * |
814 | * Return 0 if OK or nonzero if e.g. idx is invalid; system blob heap appending |
815 | * fails. |
816 | */ |
817 | |
818 | LWS_VISIBLE LWS_EXTERN int |
819 | lws_ss_sigv4_set_aws_key(struct lws_context* context, uint8_t idx, |
820 | const char * keyid, const char * key); |
821 | |
822 | /** |
823 | * lws_aws_filesystem_credentials_helper() - read aws credentials from file |
824 | * |
825 | * \param path: path to read, ~ at start is converted to $HOME contents if any |
826 | * \param kid: eg, "aws_access_key_id" |
827 | * \param ak: eg, "aws_secret_access_key" |
828 | * \param aws_keyid: pointer to pointer for allocated keyid from credentials file |
829 | * \param aws_key: pointer to pointer for allocated key from credentials file |
830 | * |
831 | * Return 0 if both *aws_keyid and *aws_key allocated from the config file, else |
832 | * nonzero, and neither *aws_keyid or *aws_key are allocated. |
833 | * |
834 | * If *aws_keyid and *aws_key are set, it's the user's responsibility to |
835 | * free() them when they are no longer needed. |
836 | */ |
837 | |
838 | LWS_VISIBLE LWS_EXTERN int |
839 | lws_aws_filesystem_credentials_helper(const char *path, const char *kid, |
840 | const char *ak, char **aws_keyid, |
841 | char **aws_key); |
842 | |
843 | #endif |
844 | |
845 | ///@} |
846 | |
847 | |