You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
348 lines
9.5 KiB
348 lines
9.5 KiB
/*
|
|
* libwebsockets - small server side websockets and web server implementation
|
|
*
|
|
* Copyright (C) 2019 - 2020 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.
|
|
*/
|
|
|
|
/*
|
|
* Secure Stream state
|
|
*/
|
|
|
|
typedef enum {
|
|
SSSEQ_IDLE,
|
|
SSSEQ_TRY_CONNECT,
|
|
SSSEQ_TRY_CONNECT_NAUTH,
|
|
SSSEQ_TRY_CONNECT_SAUTH,
|
|
SSSEQ_RECONNECT_WAIT,
|
|
SSSEQ_DO_RETRY,
|
|
SSSEQ_CONNECTED,
|
|
} lws_ss_seq_state_t;
|
|
|
|
|
|
/**
|
|
* lws_ss_handle_t: publicly-opaque secure stream object implementation
|
|
*/
|
|
|
|
typedef struct lws_ss_handle {
|
|
lws_ss_info_t info; /**< copy of stream creation info */
|
|
struct lws_dll2 list; /**< pt lists active ss */
|
|
struct lws_dll2 to_list; /**< pt lists ss with pending to-s */
|
|
|
|
struct lws_dll2_owner src_list; /**< sink's list of bound sources */
|
|
|
|
struct lws_context *context; /**< lws context we are created on */
|
|
const lws_ss_policy_t *policy; /**< system policy for stream */
|
|
|
|
struct lws_sequencer *seq; /**< owning sequencer if any */
|
|
struct lws *wsi; /**< the stream wsi if any */
|
|
|
|
void *nauthi; /**< the nauth plugin instance data */
|
|
void *sauthi; /**< the sauth plugin instance data */
|
|
|
|
lws_ss_metadata_t *metadata;
|
|
const lws_ss_policy_t *rideshare;
|
|
|
|
struct lws_ss_handle *h_sink; /**< sink we are bound to, or NULL */
|
|
void *sink_obj;/**< sink's private object representing us */
|
|
|
|
lws_sorted_usec_list_t sul;
|
|
lws_ss_tx_ordinal_t txord;
|
|
|
|
/* protocol-specific connection helpers */
|
|
|
|
union {
|
|
|
|
/* ...for http-related protocols... */
|
|
|
|
struct {
|
|
|
|
/* common to all http-related protocols */
|
|
|
|
/* incoming multipart parsing */
|
|
|
|
char boundary[24]; /* --boundary from headers */
|
|
uint8_t boundary_len; /* length of --boundary */
|
|
uint8_t boundary_seq; /* current match amount */
|
|
uint8_t boundary_dashes; /* check for -- after */
|
|
uint8_t boundary_post; /* swallow post CRLF */
|
|
|
|
uint8_t som:1; /* SOM has been sent */
|
|
uint8_t any:1; /* any content has been sent */
|
|
|
|
|
|
uint8_t good_respcode:1; /* 200 type response code */
|
|
|
|
union {
|
|
struct { /* LWSSSP_H1 */
|
|
} h1;
|
|
struct { /* LWSSSP_H2 */
|
|
} h2;
|
|
struct { /* LWSSSP_WS */
|
|
} ws;
|
|
} u;
|
|
} http;
|
|
|
|
/* details for non-http related protocols... */
|
|
#if defined(LWS_ROLE_MQTT)
|
|
struct {
|
|
lws_mqtt_topic_elem_t topic_qos;
|
|
lws_mqtt_topic_elem_t sub_top;
|
|
lws_mqtt_subscribe_param_t sub_info;
|
|
} mqtt;
|
|
#endif
|
|
} u;
|
|
|
|
unsigned long writeable_len;
|
|
|
|
lws_ss_constate_t connstate;/**< public connection state */
|
|
lws_ss_seq_state_t seqstate; /**< private connection state */
|
|
|
|
uint16_t retry; /**< retry / backoff tracking */
|
|
int16_t temp16;
|
|
|
|
uint8_t tsi; /**< service thread idx, usually 0 */
|
|
uint8_t subseq; /**< emulate SOM tracking */
|
|
uint8_t txn_ok; /**< 1 = transaction was OK */
|
|
|
|
uint8_t hanging_som:1;
|
|
uint8_t inside_msg:1;
|
|
uint8_t being_serialized:1; /* we are not the consumer */
|
|
} lws_ss_handle_t;
|
|
|
|
/* connection helper that doesn't need to hang around after connection starts */
|
|
|
|
union lws_ss_contemp {
|
|
#if defined(LWS_ROLE_MQTT)
|
|
lws_mqtt_client_connect_param_t ccp;
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
* When allocating the opaque handle, we overallocate for:
|
|
*
|
|
* 1) policy->nauth_plugin->alloc (.nauthi) if any
|
|
* 2) policy->sauth_plugin->alloc (.sauthi) if any
|
|
* 3) copy of creation info stream type pointed to by info.streamtype... this
|
|
* may be arbitrarily long and since it may be coming from socket ipc and be
|
|
* temporary at creation time, we need a place for the copy to stay in scope
|
|
* 4) copy of info->streamtype contents
|
|
*/
|
|
|
|
|
|
/* the user object allocation is immediately after the ss object allocation */
|
|
#define ss_to_userobj(ss) ((void *)&(ss)[1])
|
|
|
|
/*
|
|
* serialization parser state
|
|
*/
|
|
|
|
enum {
|
|
KIND_C_TO_P,
|
|
KIND_SS_TO_P,
|
|
};
|
|
|
|
struct lws_ss_serialization_parser {
|
|
char streamtype[32];
|
|
char rideshare[32];
|
|
char metadata_name[32];
|
|
|
|
uint64_t ust_pwait;
|
|
|
|
lws_ss_metadata_t *ssmd;
|
|
|
|
int ps;
|
|
int ctr;
|
|
|
|
uint32_t usd_phandling;
|
|
uint32_t flags;
|
|
int32_t temp32;
|
|
|
|
int32_t txcr_out;
|
|
int32_t txcr_in;
|
|
uint16_t rem;
|
|
|
|
uint8_t type;
|
|
uint8_t frag1;
|
|
uint8_t slen;
|
|
uint8_t rsl_pos;
|
|
uint8_t rsl_idx;
|
|
};
|
|
|
|
/*
|
|
* Unlike locally-fulfilled SS, SSS doesn't have to hold metadata on client side
|
|
* but pass it through to the proxy. The client side doesn't know the real
|
|
* metadata names that are available in the policy (since it's hardcoded in code
|
|
* no point passing them back to the client from the policy). Because of that,
|
|
* it doesn't know how many to allocate when we create the sspc_handle either.
|
|
*
|
|
* So we use a linked-list of changed-but-not-yet-proxied metadata allocated
|
|
* on the heap and items removed as they are proxied out. Anything on the list
|
|
* is sent to the proxy before any requested tx is handled.
|
|
*
|
|
* This is also used to queue tx credit changes
|
|
*/
|
|
|
|
typedef struct lws_sspc_metadata {
|
|
lws_dll2_t list;
|
|
char name[32]; /* empty string, then actually TCXR */
|
|
size_t len;
|
|
int tx_cr_adjust;
|
|
|
|
/* the value of length .len is overallocated after this */
|
|
} lws_sspc_metadata_t;
|
|
|
|
|
|
typedef struct lws_sspc_handle {
|
|
char rideshare_list[128];
|
|
lws_ss_info_t ssi;
|
|
lws_sorted_usec_list_t sul_retry;
|
|
|
|
struct lws_ss_serialization_parser parser;
|
|
|
|
lws_dll2_owner_t metadata_owner;
|
|
|
|
struct lws_dll2 client_list;
|
|
struct lws_tx_credit txc;
|
|
|
|
struct lws *cwsi;
|
|
|
|
struct lws_dsh *dsh;
|
|
struct lws_context *context;
|
|
|
|
lws_usec_t us_earliest_write_req;
|
|
|
|
lws_ss_conn_states_t state;
|
|
|
|
int16_t temp16;
|
|
|
|
uint32_t ord;
|
|
|
|
uint8_t rideshare_ofs[4];
|
|
uint8_t conn_req;
|
|
uint8_t rsidx;
|
|
|
|
uint8_t destroying:1;
|
|
} lws_sspc_handle_t;
|
|
|
|
int
|
|
lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par,
|
|
struct lws_context *context,
|
|
struct lws_dsh *dsh, const uint8_t *cp, size_t len,
|
|
lws_ss_conn_states_t *state, void *parconn,
|
|
lws_ss_handle_t **pss, lws_ss_info_t *ssi, char client);
|
|
int
|
|
lws_ss_serialize_rx_payload(struct lws_dsh *dsh, const uint8_t *buf,
|
|
size_t len, int flags, const char *rsp);
|
|
int
|
|
lws_ss_deserialize_tx_payload(struct lws_dsh *dsh, struct lws *wsi,
|
|
lws_ss_tx_ordinal_t ord, uint8_t *buf,
|
|
size_t *len, int *flags);
|
|
int
|
|
lws_ss_serialize_state(struct lws_dsh *dsh, lws_ss_constate_t state,
|
|
lws_ss_tx_ordinal_t ack);
|
|
|
|
void
|
|
lws_ss_serialize_state_transition(lws_ss_conn_states_t *state, int new_state);
|
|
|
|
const lws_ss_policy_t *
|
|
lws_ss_policy_lookup(const struct lws_context *context, const char *streamtype);
|
|
|
|
/* can be used as a cb from lws_dll2_foreach_safe() to destroy ss */
|
|
int
|
|
lws_ss_destroy_dll(struct lws_dll2 *d, void *user);
|
|
|
|
int
|
|
lws_sspc_destroy_dll(struct lws_dll2 *d, void *user);
|
|
|
|
|
|
int
|
|
lws_ss_policy_parse_begin(struct lws_context *context);
|
|
|
|
int
|
|
lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len);
|
|
|
|
int
|
|
lws_ss_policy_set(struct lws_context *context, const char *name);
|
|
|
|
int
|
|
lws_ss_policy_parse_abandon(struct lws_context *context);
|
|
|
|
int
|
|
lws_ss_sys_fetch_policy(struct lws_context *context);
|
|
|
|
int
|
|
lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs);
|
|
|
|
int
|
|
lws_ss_backoff(lws_ss_handle_t *h);
|
|
|
|
int
|
|
lws_ss_set_timeout_us(lws_ss_handle_t *h, lws_usec_t us);
|
|
|
|
void
|
|
ss_proxy_onward_txcr(void *userobj, int bump);
|
|
|
|
int
|
|
lws_ss_serialize_txcr(struct lws_dsh *dsh, int txcr);
|
|
|
|
int
|
|
lws_ss_sys_auth_api_amazon_com(struct lws_context *context);
|
|
|
|
lws_ss_metadata_t *
|
|
lws_ss_get_handle_metadata(struct lws_ss_handle *h, const char *name);
|
|
lws_ss_metadata_t *
|
|
lws_ss_policy_metadata_index(const lws_ss_policy_t *p, size_t index);
|
|
|
|
lws_ss_metadata_t *
|
|
lws_ss_policy_metadata(const lws_ss_policy_t *p, const char *name);
|
|
|
|
int
|
|
lws_ss_exp_cb_metadata(void *priv, const char *name, char *out, size_t *pos,
|
|
size_t olen, size_t *exp_ofs);
|
|
|
|
typedef int (* const secstream_protocol_connect_munge_t)(lws_ss_handle_t *h,
|
|
char *buf, size_t len, struct lws_client_connect_info *i,
|
|
union lws_ss_contemp *ct);
|
|
|
|
typedef int (* const secstream_protocol_add_txcr_t)(lws_ss_handle_t *h, int add);
|
|
|
|
typedef int (* const secstream_protocol_get_txcr_t)(lws_ss_handle_t *h);
|
|
|
|
struct ss_pcols {
|
|
const char *name;
|
|
const char *alpn;
|
|
const char *protocol_name;
|
|
const secstream_protocol_connect_munge_t munge;
|
|
const secstream_protocol_add_txcr_t tx_cr_add;
|
|
const secstream_protocol_get_txcr_t tx_cr_est;
|
|
};
|
|
|
|
extern const struct ss_pcols ss_pcol_h1;
|
|
extern const struct ss_pcols ss_pcol_h2;
|
|
extern const struct ss_pcols ss_pcol_ws;
|
|
extern const struct ss_pcols ss_pcol_mqtt;
|
|
|
|
extern const struct lws_protocols protocol_secstream_h1;
|
|
extern const struct lws_protocols protocol_secstream_h2;
|
|
extern const struct lws_protocols protocol_secstream_ws;
|
|
extern const struct lws_protocols protocol_secstream_mqtt;
|
|
|