714 lines
26 KiB
C
714 lines
26 KiB
C
|
/*
|
||
|
* libwebsockets - small server side websockets and web server implementation
|
||
|
*
|
||
|
* Copyright (C) 2019 - 2021 Andy Green <andy@warmcat.com>
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
* of this software and associated documentation files (the "Software"), to
|
||
|
* deal in the Software without restriction, including without limitation the
|
||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||
|
* furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included in
|
||
|
* all copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||
|
* IN THE SOFTWARE.
|
||
|
*
|
||
|
* included from libwebsockets.h
|
||
|
*
|
||
|
*
|
||
|
* Secure Streams is a *payload-only* client communication channel where all the
|
||
|
* details about the connection are held in a systemwide policy database and
|
||
|
* are keyed by the streamtype field... the user of the communication channel
|
||
|
* does not know or manage the choice of endpoint, tls CA, or even wire
|
||
|
* protocol. The advantage is he then does not have any dependency on any of
|
||
|
* those and they can be changed just by changing the policy database without
|
||
|
* touching the code using the stream.
|
||
|
*
|
||
|
* There are two ways secure streams interfaces to user code:
|
||
|
*
|
||
|
* 1) [Linux / RTOS] the natural, smallest interface is to call back to user
|
||
|
* code that only operates directly from the lws event loop thread context
|
||
|
* (direct callbacks from lws_ss_t)
|
||
|
*
|
||
|
* lws_thread( [user code] ---- lws )
|
||
|
*
|
||
|
* 2) [Linux] where the user code is in a different process and communicates
|
||
|
* asynchronously via a proxy socket
|
||
|
*
|
||
|
* user_process{ [user code] | shim | socket-}------ lws_process{ lws }
|
||
|
*
|
||
|
* In the second, IPC, case, all packets are prepended by one or more bytes
|
||
|
* indicating the packet type and serializing any associated data, known as
|
||
|
* Serialized Secure Streams or SSS.
|
||
|
*/
|
||
|
|
||
|
/** \defgroup secstr Secure Streams
|
||
|
* ##Secure Streams
|
||
|
*
|
||
|
* Secure Streams related apis
|
||
|
*/
|
||
|
///@{
|
||
|
|
||
|
#define LWS_SS_MTU 1540
|
||
|
|
||
|
struct lws_ss_handle;
|
||
|
typedef uint32_t lws_ss_tx_ordinal_t;
|
||
|
|
||
|
#if defined(STANDALONE)
|
||
|
#define lws_context lws_context_standalone
|
||
|
struct lws_context_standalone;
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* connection state events
|
||
|
*
|
||
|
* If you add states, take care about the state names and state transition
|
||
|
* validity enforcement tables too
|
||
|
*/
|
||
|
typedef enum {
|
||
|
/* zero means unset */
|
||
|
LWSSSCS_CREATING = 1,
|
||
|
LWSSSCS_DISCONNECTED,
|
||
|
LWSSSCS_UNREACHABLE, /* oridinal arg = 1 = caused by dns
|
||
|
* server reachability failure */
|
||
|
LWSSSCS_AUTH_FAILED,
|
||
|
LWSSSCS_CONNECTED,
|
||
|
LWSSSCS_CONNECTING,
|
||
|
LWSSSCS_DESTROYING,
|
||
|
LWSSSCS_POLL,
|
||
|
LWSSSCS_ALL_RETRIES_FAILED, /* all retries in bo policy failed */
|
||
|
LWSSSCS_QOS_ACK_REMOTE, /* remote peer received and acked tx */
|
||
|
LWSSSCS_QOS_NACK_REMOTE,
|
||
|
LWSSSCS_QOS_ACK_LOCAL, /* local proxy accepted our tx */
|
||
|
LWSSSCS_QOS_NACK_LOCAL, /* local proxy refused our tx */
|
||
|
LWSSSCS_TIMEOUT, /* optional timeout timer fired */
|
||
|
|
||
|
LWSSSCS_SERVER_TXN,
|
||
|
LWSSSCS_SERVER_UPGRADE, /* the server protocol upgraded */
|
||
|
|
||
|
LWSSSCS_EVENT_WAIT_CANCELLED, /* somebody called lws_cancel_service */
|
||
|
|
||
|
LWSSSCS_UPSTREAM_LINK_RETRY, /* if we are being proxied over some
|
||
|
* intermediate link, this transient
|
||
|
* state may be sent to indicate we are
|
||
|
* waiting to establish that link before
|
||
|
* creation can proceed.. ack is the
|
||
|
* number of ms we have been trying */
|
||
|
|
||
|
LWSSSCS_SINK_JOIN, /* sinks get this when a new source
|
||
|
* stream joins the sink */
|
||
|
LWSSSCS_SINK_PART, /* sinks get this when a new source
|
||
|
* stream leaves the sink */
|
||
|
|
||
|
LWSSSCS_USER_BASE = 1000
|
||
|
} lws_ss_constate_t;
|
||
|
|
||
|
enum {
|
||
|
LWSSS_FLAG_SOM = (1 << 0),
|
||
|
/* payload contains the start of new message */
|
||
|
LWSSS_FLAG_EOM = (1 << 1),
|
||
|
/* payload contains the end of message */
|
||
|
LWSSS_FLAG_POLL = (1 << 2),
|
||
|
/* Not a real transmit... poll for rx if protocol needs it */
|
||
|
LWSSS_FLAG_RELATED_START = (1 << 3),
|
||
|
/* Appears in a zero-length message indicating a message group of zero
|
||
|
* or more messages is now starting. */
|
||
|
LWSSS_FLAG_RELATED_END = (1 << 4),
|
||
|
/* Appears in a zero-length message indicating a message group of zero
|
||
|
* or more messages has now finished. */
|
||
|
LWSSS_FLAG_RIDESHARE = (1 << 5),
|
||
|
/* Serialized payload starts with non-default rideshare name length and
|
||
|
* name string without NUL, then payload */
|
||
|
LWSSS_FLAG_PERF_JSON = (1 << 6),
|
||
|
/* This RX is JSON performance data, only on streams with "perf" flag
|
||
|
* set */
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* Returns from state() callback can tell the caller what the user code
|
||
|
* wants to do
|
||
|
*/
|
||
|
|
||
|
typedef enum lws_ss_state_return {
|
||
|
LWSSSSRET_TX_DONT_SEND = 1, /* (*tx) only, or failure */
|
||
|
|
||
|
LWSSSSRET_OK = 0, /* no error */
|
||
|
LWSSSSRET_DISCONNECT_ME = -1, /* caller should disconnect us */
|
||
|
LWSSSSRET_DESTROY_ME = -2, /* caller should destroy us */
|
||
|
} lws_ss_state_return_t;
|
||
|
|
||
|
/**
|
||
|
* lws_ss_info_t: information about stream to be created
|
||
|
*
|
||
|
* Prepare this struct with information about what the stream type is and how
|
||
|
* the stream should interface with your code, and pass it to lws_ss_create()
|
||
|
* to create the requested stream.
|
||
|
*/
|
||
|
|
||
|
enum {
|
||
|
LWSSSINFLAGS_REGISTER_SINK = (1 << 0),
|
||
|
/**< If set, we're not creating a specific stream, but registering
|
||
|
* ourselves as the "sink" for .streamtype. It's analogous to saying
|
||
|
* we want to be the many-to-one "server" for .streamtype; when other
|
||
|
* streams are created with that streamtype, they should be forwarded
|
||
|
* to this stream owner, where they join and part from the sink via
|
||
|
* (*state) LWSSSCS_SINK_JOIN / _PART events, the new client handle
|
||
|
* being provided in the h_src parameter.
|
||
|
*/
|
||
|
LWSSSINFLAGS_PROXIED = (1 << 1),
|
||
|
/**< Set if the stream is being created as a stand-in at the proxy */
|
||
|
LWSSSINFLAGS_SERVER = (1 << 2),
|
||
|
/**< Set on the server object copy of the ssi / info to indicate that
|
||
|
* stream creation using this ssi is for Accepted connections belonging
|
||
|
* to a server */
|
||
|
LWSSSINFLAGS_ACCEPTED = (1 << 3),
|
||
|
/**< Set on the accepted object copy of the ssi / info to indicate that
|
||
|
* we are an accepted connection from a server's listening socket */
|
||
|
LWSSSINFLAGS_ACCEPTED_SINK = (1 << 4),
|
||
|
/**< Set on the accepted object copy of the ssi / info to indicate that
|
||
|
* we are an accepted connection from a local sink */
|
||
|
};
|
||
|
|
||
|
typedef lws_ss_state_return_t (*lws_sscb_rx)(void *userobj, const uint8_t *buf,
|
||
|
size_t len, int flags);
|
||
|
typedef lws_ss_state_return_t (*lws_sscb_tx)(void *userobj,
|
||
|
lws_ss_tx_ordinal_t ord,
|
||
|
uint8_t *buf, size_t *len,
|
||
|
int *flags);
|
||
|
typedef lws_ss_state_return_t (*lws_sscb_state)(void *userobj, void *h_src,
|
||
|
lws_ss_constate_t state,
|
||
|
lws_ss_tx_ordinal_t ack);
|
||
|
|
||
|
#if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP)
|
||
|
typedef void (*lws_ss_buffer_dump_cb)(void *userobj, const uint8_t *buf,
|
||
|
size_t len, int done);
|
||
|
#endif
|
||
|
|
||
|
struct lws_ss_policy;
|
||
|
|
||
|
typedef struct lws_ss_info {
|
||
|
const char *streamtype; /**< type of stream we want to create */
|
||
|
size_t user_alloc; /**< size of user allocation */
|
||
|
size_t handle_offset; /**< offset of handle stg in user_alloc type,
|
||
|
set to offsetof(mytype, my_handle_member) */
|
||
|
size_t opaque_user_data_offset;
|
||
|
/**< offset of opaque user data ptr in user_alloc type, set to
|
||
|
offsetof(mytype, opaque_ud_member) */
|
||
|
|
||
|
#if defined(LWS_WITH_SECURE_STREAMS_CPP)
|
||
|
const struct lws_ss_policy *policy;
|
||
|
/**< Normally NULL, or a locally-generated policy to apply to this
|
||
|
* connection instead of a named streamtype */
|
||
|
#endif
|
||
|
|
||
|
#if defined(LWS_WITH_SYS_FAULT_INJECTION)
|
||
|
lws_fi_ctx_t fic;
|
||
|
/**< Attach external Fault Injection context to the stream, hierarchy
|
||
|
* is ss->context */
|
||
|
#endif
|
||
|
|
||
|
lws_sscb_rx rx;
|
||
|
/**< callback with rx payload for this stream */
|
||
|
lws_sscb_tx tx;
|
||
|
/**< callback to send payload on this stream... 0 = send as set in
|
||
|
* len and flags, 1 = do not send anything (ie, not even 0 len frame) */
|
||
|
lws_sscb_state state;
|
||
|
/**< advisory cb about state of stream and QoS status if applicable...
|
||
|
* h_src is only used with sinks and LWSSSCS_SINK_JOIN/_PART events.
|
||
|
* Return nonzero to indicate you want to destroy the stream. */
|
||
|
#if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP)
|
||
|
lws_ss_buffer_dump_cb dump;
|
||
|
/**< cb to record needed protocol buffer data*/
|
||
|
#endif
|
||
|
int manual_initial_tx_credit;
|
||
|
/**< 0 = manage any tx credit automatically, nonzero explicitly sets the
|
||
|
* peer stream to have the given amount of tx credit, if the protocol
|
||
|
* can support it.
|
||
|
*
|
||
|
* In the special case of _lws_smd streamtype, this is used to indicate
|
||
|
* the connection's rx class mask.
|
||
|
* */
|
||
|
uint32_t client_pid;
|
||
|
/**< used in proxy / serialization case to hold the client pid this
|
||
|
* proxied connection is to be tagged with
|
||
|
*/
|
||
|
uint8_t flags;
|
||
|
uint8_t sss_protocol_version;
|
||
|
/**< used in proxy / serialization case to hold the SS serialization
|
||
|
* protocol level to use with this peer... clients automatically request
|
||
|
* the most recent version they were built with
|
||
|
* (LWS_SSS_CLIENT_PROTOCOL_VERSION) and the proxy stores the requested
|
||
|
* version in here
|
||
|
*/
|
||
|
|
||
|
} lws_ss_info_t;
|
||
|
|
||
|
#define LWS_SS_USER_TYPEDEF \
|
||
|
typedef struct { \
|
||
|
struct lws_ss_handle *ss; \
|
||
|
void *opaque_data;
|
||
|
|
||
|
#define LWS_SS_INFO(_streamtype, _type) \
|
||
|
const lws_ss_info_t ssi_##_type = { \
|
||
|
.handle_offset = offsetof(_type, ss), \
|
||
|
.opaque_user_data_offset = offsetof(_type, opaque_data), \
|
||
|
.user_alloc = sizeof(_type), \
|
||
|
.streamtype = _streamtype,
|
||
|
|
||
|
#define lws_ss_from_user(_u) (_u)->ss
|
||
|
#define lws_ss_opaque_from_user(_u) (_u)->opaque_data
|
||
|
#define lws_ss_cx_from_user(_u) lws_ss_get_context((_u)->ss)
|
||
|
|
||
|
#if defined(LWS_SS_USE_SSPC)
|
||
|
#define lws_context_info_defaults(_x, _y) _lws_context_info_defaults(_x, NULL)
|
||
|
#else
|
||
|
#define lws_context_info_defaults(_x, _y) _lws_context_info_defaults(_x, _y)
|
||
|
#endif
|
||
|
|
||
|
/**
|
||
|
* lws_ss_create() - Create secure stream
|
||
|
*
|
||
|
* \param context: the lws context to create this inside
|
||
|
* \param tsi: service thread index to create on (normally 0)
|
||
|
* \param ssi: pointer to lws_ss_info_t filled in with info about desired stream
|
||
|
* \param opaque_user_data: opaque data to set in the stream's user object
|
||
|
* \param ppss: pointer to secure stream handle pointer set on exit
|
||
|
* \param ppayload_fmt: NULL or pointer to a string ptr to take payload format
|
||
|
* name from the policy
|
||
|
*
|
||
|
* Requests a new secure stream described by \p ssi be created. If successful,
|
||
|
* the stream is created, its state callback called with LWSSSCS_CREATING, \p *ppss
|
||
|
* is set to point to the handle, and it returns 0. If it failed, it returns
|
||
|
* nonzero.
|
||
|
*
|
||
|
* Along with the opaque stream object, streams overallocate
|
||
|
*
|
||
|
* 1) a user data struct whose size is set in ssi
|
||
|
* 2) nauth plugin instantiation data (size set in the plugin struct)
|
||
|
* 3) sauth plugin instantiation data (size set in the plugin struct)
|
||
|
* 4) space for a copy of the stream type name
|
||
|
*
|
||
|
* The user data struct is initialized to all zeros, then the .handle_offset and
|
||
|
* .opaque_user_data_offset fields of the ssi are used to prepare the user data
|
||
|
* struct with the ss handle that was created, and a copy of the
|
||
|
* opaque_user_data pointer given as an argument.
|
||
|
*
|
||
|
* If you want to set up the stream with specific information, point to it in
|
||
|
* opaque_user_data and use the copy of that pointer in your user data member
|
||
|
* for it starting from the LWSSSCS_CREATING state call.
|
||
|
*
|
||
|
* Since different endpoints chosen by the policy may require different payload
|
||
|
* formats, \p ppayload_fmt is set to point to the name of the needed payload
|
||
|
* format from the policy database if non-NULL.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
|
||
|
lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi,
|
||
|
void *opaque_user_data, struct lws_ss_handle **ppss,
|
||
|
void *reserved, const char **ppayload_fmt);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_destroy() - Destroy secure stream
|
||
|
*
|
||
|
* \param ppss: pointer to lws_ss_t pointer to be destroyed
|
||
|
*
|
||
|
* Destroys the lws_ss_t pointed to by \p *ppss, and sets \p *ppss to NULL.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN void
|
||
|
lws_ss_destroy(struct lws_ss_handle **ppss);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_request_tx() - Schedule stream for tx
|
||
|
*
|
||
|
* \param pss: pointer to lws_ss_t representing stream that wants to transmit
|
||
|
*
|
||
|
* Schedules a write on the stream represented by \p pss. When it's possible to
|
||
|
* write on this stream, the \p *tx callback will occur with an empty buffer for
|
||
|
* the stream owner to fill in.
|
||
|
*
|
||
|
* Returns 0 or LWSSSSRET_DESTROY_ME
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT
|
||
|
lws_ss_request_tx(struct lws_ss_handle *pss);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_request_tx() - Schedule stream for tx
|
||
|
*
|
||
|
* \param pss: pointer to lws_ss_t representing stream that wants to transmit
|
||
|
* \param len: the length of the write in bytes
|
||
|
*
|
||
|
* Schedules a write on the stream represented by \p pss. When it's possible to
|
||
|
* write on this stream, the \p *tx callback will occur with an empty buffer for
|
||
|
* the stream owner to fill in.
|
||
|
*
|
||
|
* This api variant should be used when it's possible the payload will go out
|
||
|
* over h1 with x-web-form-urlencoded or similar Content-Type.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT
|
||
|
lws_ss_request_tx_len(struct lws_ss_handle *pss, unsigned long len);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_client_connect() - Attempt the client connect
|
||
|
*
|
||
|
* \param h: secure streams handle
|
||
|
*
|
||
|
* Starts the connection process for the secure stream.
|
||
|
*
|
||
|
* Can return any of the lws_ss_state_return_t values depending on user
|
||
|
* state callback returns.
|
||
|
*
|
||
|
* LWSSSSRET_OK means the connection is ongoing.
|
||
|
*
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT
|
||
|
lws_ss_client_connect(struct lws_ss_handle *h);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_proxy_create() - Start a unix domain socket proxy for Secure Streams
|
||
|
*
|
||
|
* \param context: lws_context
|
||
|
* \param bind: if port is 0, unix domain path with leading @ for abstract.
|
||
|
* if port nonzero, NULL, or network interface to bind listen to
|
||
|
* \param port: tcp port to listen on
|
||
|
*
|
||
|
* Creates a vhost that listens either on an abstract namespace unix domain
|
||
|
* socket (port = 0) or a tcp listen socket (port nonzero). If bind is NULL
|
||
|
* and port is 0, the abstract unix domain socket defaults to "proxy.ss.lws".
|
||
|
*
|
||
|
* Client connections to this proxy to Secure Streams are fulfilled using the
|
||
|
* policy local to the proxy and the data passed between the client and the
|
||
|
* proxy using serialized Secure Streams protocol.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN int
|
||
|
lws_ss_proxy_create(struct lws_context *context, const char *bind, int port);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_state_name() - convenience helper to get a printable conn state name
|
||
|
*
|
||
|
* \param state: the connection state index
|
||
|
*
|
||
|
* Returns a printable name for the connection state index passed in.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN const char *
|
||
|
lws_ss_state_name(int state);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_get_context() - convenience helper to recover the lws context
|
||
|
*
|
||
|
* \param h: secure streams handle
|
||
|
*
|
||
|
* Returns the lws context. Dispenses with the need to pass a copy of it into
|
||
|
* your secure streams handler.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN struct lws_context *
|
||
|
lws_ss_get_context(struct lws_ss_handle *h);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_get_vhost() - convenience helper to get the vhost the ss is bound to
|
||
|
*
|
||
|
* \param h: secure streams handle
|
||
|
*
|
||
|
* Returns NULL if disconnected, or the the lws_vhost of the ss' wsi connection.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN struct lws_vhost *
|
||
|
lws_ss_get_vhost(struct lws_ss_handle *h);
|
||
|
|
||
|
|
||
|
#define LWSSS_TIMEOUT_FROM_POLICY 0
|
||
|
|
||
|
/**
|
||
|
* lws_ss_start_timeout() - start or restart the timeout on the stream
|
||
|
*
|
||
|
* \param h: secure streams handle
|
||
|
* \param timeout_ms: LWSSS_TIMEOUT_FROM_POLICY for policy value, else use timeout_ms
|
||
|
*
|
||
|
* Starts or restarts the stream's own timeout timer. If the specified time
|
||
|
* passes without lws_ss_cancel_timeout() being called on the stream, then the
|
||
|
* stream state callback receives LWSSSCS_TIMEOUT
|
||
|
*
|
||
|
* The process being protected by the timeout is up to the user code, it may be
|
||
|
* arbitrarily long and cross multiple protocol transactions or involve other
|
||
|
* streams. It's up to the user to decide when to start and when / if to cancel
|
||
|
* the stream timeout.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN void
|
||
|
lws_ss_start_timeout(struct lws_ss_handle *h, unsigned int timeout_ms);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_cancel_timeout() - remove any timeout on the stream
|
||
|
*
|
||
|
* \param h: secure streams handle
|
||
|
*
|
||
|
* Disable any timeout that was applied to the stream by lws_ss_start_timeout().
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN void
|
||
|
lws_ss_cancel_timeout(struct lws_ss_handle *h);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_to_user_object() - convenience helper to get user object from handle
|
||
|
*
|
||
|
* \param h: secure streams handle
|
||
|
*
|
||
|
* Returns the user allocation related to the handle. Normally you won't need
|
||
|
* this since it's available in the rx, tx and state callbacks as "userdata"
|
||
|
* already.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN void *
|
||
|
lws_ss_to_user_object(struct lws_ss_handle *h);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_rideshare() - find the current streamtype when types rideshare
|
||
|
*
|
||
|
* \param h: the stream handle
|
||
|
*
|
||
|
* Under some conditions, the payloads may be structured using protocol-
|
||
|
* specific formatting, eg, http multipart mime. It's possible to map the
|
||
|
* logical partitions in the payload to different stream types using
|
||
|
* the policy "rideshare" feature.
|
||
|
*
|
||
|
* This api lets the callback code find out which rideshare stream type the
|
||
|
* current payload chunk belongs to.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN const char *
|
||
|
lws_ss_rideshare(struct lws_ss_handle *h);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* lws_ss_set_metadata() - allow user to bind external data to defined ss metadata
|
||
|
*
|
||
|
* \param h: secure streams handle
|
||
|
* \param name: metadata name from the policy
|
||
|
* \param value: pointer to user-managed data to bind to name
|
||
|
* \param len: length of the user-managed data in value
|
||
|
*
|
||
|
* Binds user-managed data to the named metadata item from the ss policy.
|
||
|
* If present, the metadata item is handled in a protocol-specific way using
|
||
|
* the associated policy information. For example, in the policy
|
||
|
*
|
||
|
* "\"metadata\":" "["
|
||
|
* "{\"uptag\":" "\"X-Upload-Tag:\"},"
|
||
|
* "{\"ctype\":" "\"Content-Type:\"},"
|
||
|
* "{\"xctype\":" "\"\"}"
|
||
|
* "],"
|
||
|
*
|
||
|
* when the policy is using h1 is interpreted to add h1 headers of the given
|
||
|
* name with the value of the metadata on the left.
|
||
|
*
|
||
|
* Return 0 if OK or nonzero if, eg, metadata name does not exist on the
|
||
|
* streamtype. You must check the result of this, eg, transient OOM can cause
|
||
|
* these to fail and you should retry later.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
|
||
|
lws_ss_set_metadata(struct lws_ss_handle *h, const char *name,
|
||
|
const void *value, size_t len);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_alloc_set_metadata() - copy data and bind to ss metadata
|
||
|
*
|
||
|
* \param h: secure streams handle
|
||
|
* \param name: metadata name from the policy
|
||
|
* \param value: pointer to user-managed data to bind to name
|
||
|
* \param len: length of the user-managed data in value
|
||
|
*
|
||
|
* Same as lws_ss_set_metadata(), but allocates a heap buffer for the data
|
||
|
* first and takes a copy of it, so the original can go out of scope
|
||
|
* immediately after.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
|
||
|
lws_ss_alloc_set_metadata(struct lws_ss_handle *h, const char *name,
|
||
|
const void *value, size_t len);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_get_metadata() - get current value of stream metadata item
|
||
|
*
|
||
|
* \param h: secure streams handle
|
||
|
* \param name: metadata name from the policy
|
||
|
* \param value: pointer to pointer to be set to point at the value
|
||
|
* \param len: pointer to size_t to set to the length of the value
|
||
|
*
|
||
|
* Binds user-managed data to the named metadata item from the ss policy.
|
||
|
* If present, the metadata item is handled in a protocol-specific way using
|
||
|
* the associated policy information. For example, in the policy
|
||
|
*
|
||
|
* "\"metadata\":" "["
|
||
|
* "{\"uptag\":" "\"X-Upload-Tag:\"},"
|
||
|
* "{\"ctype\":" "\"Content-Type:\"},"
|
||
|
* "{\"xctype\":" "\"\"}"
|
||
|
* "],"
|
||
|
*
|
||
|
* when the policy is using h1 is interpreted to add h1 headers of the given
|
||
|
* name with the value of the metadata on the left.
|
||
|
*
|
||
|
* Return 0 if \p *value and \p *len set OK, or nonzero if, eg, metadata \p name does
|
||
|
* not exist on the streamtype.
|
||
|
*
|
||
|
* The pointed-to values may only exist until the next time around the event
|
||
|
* loop.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN int
|
||
|
lws_ss_get_metadata(struct lws_ss_handle *h, const char *name,
|
||
|
const void **value, size_t *len);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_server_ack() - indicate how we feel about what the server has sent
|
||
|
*
|
||
|
* \param h: ss handle of accepted connection
|
||
|
* \param nack: 0 means we are OK with it, else some problem
|
||
|
*
|
||
|
* For SERVER secure streams
|
||
|
*
|
||
|
* Depending on the protocol, the server sending us something may be
|
||
|
* transactional, ie, built into it sending something is the idea we will
|
||
|
* respond somehow out-of-band; HTTP is like this with, eg, 200 response code.
|
||
|
*
|
||
|
* Calling this with nack=0 indicates that when we later respond, we want to
|
||
|
* acknowledge the transaction (eg, it means a 200 if http underneath), if
|
||
|
* nonzero that the transaction should act like it failed.
|
||
|
*
|
||
|
* If the underlying protocol doesn't understand transactions (eg, ws) then this
|
||
|
* has no effect either way.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN void
|
||
|
lws_ss_server_ack(struct lws_ss_handle *h, int nack);
|
||
|
|
||
|
typedef void (*lws_sssfec_cb)(struct lws_ss_handle *h, void *arg);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_server_foreach_client() - callback for each live client connected to server
|
||
|
*
|
||
|
* \param h: server ss handle
|
||
|
* \param cb: the callback
|
||
|
* \param arg: arg passed to callback
|
||
|
*
|
||
|
* For SERVER secure streams
|
||
|
*
|
||
|
* Call the callback \p cb once for each client ss connected to the server,
|
||
|
* passing \p arg as an additional callback argument each time.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN void
|
||
|
lws_ss_server_foreach_client(struct lws_ss_handle *h, lws_sssfec_cb cb,
|
||
|
void *arg);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_change_handlers() - helper for dynamically changing stream handlers
|
||
|
*
|
||
|
* \param h: ss handle
|
||
|
* \param rx: the new RX handler
|
||
|
* \param tx: the new TX handler
|
||
|
* \param state: the new state handler
|
||
|
*
|
||
|
* Handlers set to NULL are left unchanged.
|
||
|
*
|
||
|
* This works on any handle, client or server and takes effect immediately.
|
||
|
*
|
||
|
* Depending on circumstances this may be helpful when
|
||
|
*
|
||
|
* a) a server stream undergoes an LWSSSCS_SERVER_UPGRADE (as in http -> ws) and
|
||
|
* the payloads in the new protocol have a different purpose that is best
|
||
|
* handled in their own rx and tx callbacks, and
|
||
|
*
|
||
|
* b) you may want to serve several different, possibly large things based on
|
||
|
* what was requested. Setting a customized handler allows clean encapsulation
|
||
|
* of the different serving strategies.
|
||
|
*
|
||
|
* If the stream is long-lived, like ws, you should set the changed handler back
|
||
|
* to the default when the transaction wanting it is completed.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN void
|
||
|
lws_ss_change_handlers(struct lws_ss_handle *h, lws_sscb_rx rx, lws_sscb_tx tx,
|
||
|
lws_sscb_state state);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_add_peer_tx_credit() - allow peer to transmit more to us
|
||
|
*
|
||
|
* \param h: secure streams handle
|
||
|
* \param add: additional tx credit (signed)
|
||
|
*
|
||
|
* Indicate to remote peer that we can accept \p add bytes more payload being
|
||
|
* sent to us.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN int
|
||
|
lws_ss_add_peer_tx_credit(struct lws_ss_handle *h, int32_t add);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_get_est_peer_tx_credit() - get our current estimate of peer's tx credit
|
||
|
*
|
||
|
* \param h: secure streams handle
|
||
|
*
|
||
|
* Based on what credit we gave it, and what we have received, report our
|
||
|
* estimate of peer's tx credit usable to transmit to us. This may be outdated
|
||
|
* in that some or all of its credit may already have been expended by sending
|
||
|
* stuff to us that is in flight already.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN int
|
||
|
lws_ss_get_est_peer_tx_credit(struct lws_ss_handle *h);
|
||
|
|
||
|
LWS_VISIBLE LWS_EXTERN const char *
|
||
|
lws_ss_tag(struct lws_ss_handle *h);
|
||
|
|
||
|
/**
|
||
|
* lws_ss_adopt_raw() - bind ss to existing fd
|
||
|
*
|
||
|
* \param ss: pointer to lws_ss_t to adopt the fd
|
||
|
* \param fd: the existing fd
|
||
|
*
|
||
|
* "connects" the existing ss to a wsi adoption of fd, it's useful for cases
|
||
|
* like local representation of eg a pipe() fd using ss.
|
||
|
*/
|
||
|
LWS_VISIBLE LWS_EXTERN int
|
||
|
lws_ss_adopt_raw(struct lws_ss_handle *ss, lws_sock_file_fd_type fd);
|
||
|
|
||
|
#if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4)
|
||
|
/**
|
||
|
* lws_ss_sigv4_set_aws_key() - set aws credential into system blob
|
||
|
*
|
||
|
* \param context: lws_context
|
||
|
* \param idx: the system blob index specified in the policy, currently
|
||
|
* up to 4 blobs.
|
||
|
* \param keyid: aws access keyid
|
||
|
* \param key: aws access key
|
||
|
*
|
||
|
* Return 0 if OK or nonzero if e.g. idx is invalid; system blob heap appending
|
||
|
* fails.
|
||
|
*/
|
||
|
|
||
|
LWS_VISIBLE LWS_EXTERN int
|
||
|
lws_ss_sigv4_set_aws_key(struct lws_context* context, uint8_t idx,
|
||
|
const char * keyid, const char * key);
|
||
|
|
||
|
/**
|
||
|
* lws_aws_filesystem_credentials_helper() - read aws credentials from file
|
||
|
*
|
||
|
* \param path: path to read, ~ at start is converted to $HOME contents if any
|
||
|
* \param kid: eg, "aws_access_key_id"
|
||
|
* \param ak: eg, "aws_secret_access_key"
|
||
|
* \param aws_keyid: pointer to pointer for allocated keyid from credentials file
|
||
|
* \param aws_key: pointer to pointer for allocated key from credentials file
|
||
|
*
|
||
|
* Return 0 if both *aws_keyid and *aws_key allocated from the config file, else
|
||
|
* nonzero, and neither *aws_keyid or *aws_key are allocated.
|
||
|
*
|
||
|
* If *aws_keyid and *aws_key are set, it's the user's responsibility to
|
||
|
* free() them when they are no longer needed.
|
||
|
*/
|
||
|
|
||
|
LWS_VISIBLE LWS_EXTERN int
|
||
|
lws_aws_filesystem_credentials_helper(const char *path, const char *kid,
|
||
|
const char *ak, char **aws_keyid,
|
||
|
char **aws_key);
|
||
|
#endif
|
||
|
|
||
|
#if defined(STANDALONE)
|
||
|
#undef lws_context
|
||
|
#endif
|
||
|
|
||
|
///@}
|
||
|
|