1 /* 2 * libwebsockets - small server side websockets and web server implementation 3 * 4 * Copyright (C) 2010 - 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 * This provides a clean way to interface lws user code to be able to 25 * work unchanged on different systems for fetching common system information, 26 * and performing common system operations like reboot. 27 */ 28 29 /* 30 * Types of system blob that can be set and retreived 31 */ 32 33 typedef enum { 34 LWS_SYSBLOB_TYPE_AUTH, 35 LWS_SYSBLOB_TYPE_CLIENT_CERT_DER = LWS_SYSBLOB_TYPE_AUTH + 2, 36 LWS_SYSBLOB_TYPE_CLIENT_KEY_DER, 37 LWS_SYSBLOB_TYPE_DEVICE_SERIAL, 38 LWS_SYSBLOB_TYPE_DEVICE_FW_VERSION, 39 LWS_SYSBLOB_TYPE_DEVICE_TYPE, 40 LWS_SYSBLOB_TYPE_NTP_SERVER, 41 42 LWS_SYSBLOB_TYPE_COUNT /* ... always last */ 43 } lws_system_blob_item_t; 44 45 /* opaque generic blob whose content may be on-the-heap or pointed-to 46 * directly case by case. When it's on the heap, it can be produced by 47 * appending (it's a buflist underneath). Either way, it can be consumed by 48 * copying out a given length from a given offset. 49 */ 50 51 typedef struct lws_system_blob lws_system_blob_t; 52 53 LWS_EXTERN LWS_VISIBLE void 54 lws_system_blob_direct_set(lws_system_blob_t *b, const uint8_t *ptr, size_t len); 55 56 LWS_EXTERN LWS_VISIBLE void 57 lws_system_blob_heap_empty(lws_system_blob_t *b); 58 59 LWS_EXTERN LWS_VISIBLE int 60 lws_system_blob_heap_append(lws_system_blob_t *b, const uint8_t *ptr, size_t len); 61 62 LWS_EXTERN LWS_VISIBLE size_t 63 lws_system_blob_get_size(lws_system_blob_t *b); 64 65 /* return 0 and sets *ptr to point to blob data if possible, nonzero = fail */ 66 LWS_EXTERN LWS_VISIBLE int 67 lws_system_blob_get_single_ptr(lws_system_blob_t *b, const uint8_t **ptr); 68 69 LWS_EXTERN LWS_VISIBLE int 70 lws_system_blob_get(lws_system_blob_t *b, uint8_t *ptr, size_t *len, size_t ofs); 71 72 LWS_EXTERN LWS_VISIBLE void 73 lws_system_blob_destroy(lws_system_blob_t *b); 74 75 /* 76 * Get the opaque blob for index idx of various system blobs. Returns 0 if 77 * *b was set otherwise nonzero means out of range 78 */ 79 80 LWS_EXTERN LWS_VISIBLE lws_system_blob_t * 81 lws_system_get_blob(struct lws_context *context, lws_system_blob_item_t type, 82 int idx); 83 84 /* 85 * Lws view of system state... normal operation from user code perspective is 86 * dependent on implicit (eg, knowing the date for cert validation) and 87 * explicit dependencies. 88 * 89 * Bit of lws and user code can register notification handlers that can enforce 90 * dependent operations before state transitions can complete. 91 */ 92 93 typedef enum { /* keep system_state_names[] in sync in context.c */ 94 LWS_SYSTATE_UNKNOWN, 95 96 LWS_SYSTATE_CONTEXT_CREATED, /* context was just created */ 97 LWS_SYSTATE_INITIALIZED, /* protocols initialized. Lws itself 98 * can operate normally */ 99 LWS_SYSTATE_IFACE_COLDPLUG, /* existing net ifaces iterated */ 100 LWS_SYSTATE_DHCP, /* at least one net iface configured */ 101 LWS_SYSTATE_TIME_VALID, /* ntpclient ran, or hw time valid... 102 * tls cannot work until we reach here 103 */ 104 LWS_SYSTATE_POLICY_VALID, /* user code knows how to operate... */ 105 LWS_SYSTATE_REGISTERED, /* device has an identity... */ 106 LWS_SYSTATE_AUTH1, /* identity used for main auth token */ 107 LWS_SYSTATE_AUTH2, /* identity used for optional auth */ 108 109 LWS_SYSTATE_OPERATIONAL, /* user code can operate normally */ 110 111 LWS_SYSTATE_POLICY_INVALID, /* user code is changing its policies 112 * drop everything done with old 113 * policy, switch to new then enter 114 * LWS_SYSTATE_POLICY_VALID */ 115 } lws_system_states_t; 116 117 118 typedef void (*lws_attach_cb_t)(struct lws_context *context, int tsi, void *opaque); 119 struct lws_attach_item; 120 121 typedef struct lws_system_ops { 122 int (*reboot)(void); 123 int (*set_clock)(lws_usec_t us); 124 int (*attach)(struct lws_context *context, int tsi, lws_attach_cb_t cb, 125 lws_system_states_t state, void *opaque, 126 struct lws_attach_item **get); 127 /**< if \p get is NULL, add an attach callback request to the pt for 128 * \p cb with arg \p opaque, that should be called when we're at or past 129 * system state \p state. 130 * 131 * If \p get is non-NULL, look for the first listed item on the pt whose 132 * state situation is ready, and set *get to point to it. If no items, 133 * or none where the system state is right, set *get to NULL. 134 * 135 * It's done like this so (*attach) can perform system-specific 136 * locking outside of lws core, for both getting and adding items the 137 * same so it is thread-safe. A non-threadsafe helper 138 * __lws_system_attach() is provided to do the actual work inside the 139 * system-specific locking. 140 */ 141 } lws_system_ops_t; 142 143 /** 144 * lws_system_get_state_manager() - return the state mgr object for system state 145 * 146 * \param context: the lws_context 147 * 148 * The returned pointer can be used with the lws_state_ apis 149 */ 150 151 LWS_EXTERN LWS_VISIBLE lws_state_manager_t * 152 lws_system_get_state_manager(struct lws_context *context); 153 154 155 156 /* wrappers handle NULL members or no ops struct set at all cleanly */ 157 158 #define LWSSYSGAUTH_HEX (1 << 0) 159 160 /** 161 * lws_system_get_ops() - get ahold of the system ops struct from the context 162 * 163 * \param context: the lws_context 164 * 165 * Returns the system ops struct. It may return NULL and if not, anything in 166 * there may be NULL. 167 */ 168 LWS_EXTERN LWS_VISIBLE const lws_system_ops_t * 169 lws_system_get_ops(struct lws_context *context); 170 171 /** 172 * lws_system_context_from_system_mgr() - return context from system state mgr 173 * 174 * \param mgr: pointer to specifically the system state mgr 175 * 176 * Returns the context from the system state mgr. Helper since the lws_context 177 * is opaque. 178 */ 179 LWS_EXTERN LWS_VISIBLE struct lws_context * 180 lws_system_context_from_system_mgr(lws_state_manager_t *mgr); 181 182 183 /** 184 * __lws_system_attach() - get and set items on context attach list 185 * 186 * \param context: context to get or set attach items to 187 * \param tsi: thread service index (normally 0) 188 * \param cb: callback to call from context event loop thread 189 * \param state: the lws_system state we have to be in or have passed through 190 * \param opaque: optional pointer to user specific info given to callback 191 * \param get: NULL, or pointer to pointer to take detached tail item on exit 192 * 193 * This allows other threads to enqueue callback requests to happen from a pt's 194 * event loop thread safely. The callback gets the context pointer and a user 195 * opaque pointer that can be optionally given when the item is added to the 196 * attach list. 197 * 198 * This api is the no-locking core function for getting and setting items on the 199 * pt's attach list. The lws_system operation (*attach) is the actual 200 * api that user and internal code calls for this feature, it should perform 201 * system-specific locking, call this helper, release the locking and then 202 * return the result. This api is public only so it can be used in the locked 203 * implementation of (*attach). 204 * 205 * If get is NULL, then the call adds to the head of the pt attach list using 206 * cb, state, and opaque; if get is non-NULL, then *get is set to the first 207 * waiting attached item that meets the state criteria and that item is removed 208 * from the list. 209 * 210 * This is a non-threadsafe helper only designed to be called from 211 * implementations of struct lws_system's (*attach) operation where system- 212 * specific locking has been applied around it, making it threadsafe. 213 */ 214 LWS_EXTERN LWS_VISIBLE int 215 __lws_system_attach(struct lws_context *context, int tsi, lws_attach_cb_t cb, 216 lws_system_states_t state, void *opaque, 217 struct lws_attach_item **get); 218 219 220 typedef int (*dhcpc_cb_t)(void *opaque, int af, uint8_t *ip, int ip_len); 221 222 /** 223 * lws_dhcpc_request() - add a network interface to dhcpc management 224 * 225 * \param c: the lws_context 226 * \param i: the interface name, like "eth0" 227 * \param af: address family 228 * \param cb: the change callback 229 * \param opaque: opaque pointer given to the callback 230 * 231 * Register a network interface as being managed by DHCP. lws will proceed to 232 * try to acquire an IP. Requires LWS_WITH_SYS_DHCP_CLIENT at cmake. 233 */ 234 int 235 lws_dhcpc_request(struct lws_context *c, const char *i, int af, dhcpc_cb_t cb, 236 void *opaque); 237 238 /** 239 * lws_dhcpc_remove() - remove a network interface to dhcpc management 240 * 241 * \param context: the lws_context 242 * \param iface: the interface name, like "eth0" 243 * 244 * Remove handling of the network interface from dhcp. 245 */ 246 int 247 lws_dhcpc_remove(struct lws_context *context, const char *iface); 248 249 /** 250 * lws_dhcpc_status() - has any interface reached BOUND state 251 * 252 * \param context: the lws_context 253 * \param sa46: set to a DNS server from a bound interface, or NULL 254 * 255 * Returns 1 if any network interface managed by dhcpc has reached the BOUND 256 * state (has acquired an IP, gateway and DNS server), otherwise 0. 257 */ 258 int 259 lws_dhcpc_status(struct lws_context *context, lws_sockaddr46 *sa46); 260