1 /* 2 * libwebsockets - small server side websockets and web server implementation 3 * 4 * Copyright (C) 2010 - 2019 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 25 typedef uint32_t lws_wsi_state_t; 26 27 /* 28 * The wsi->role_ops pointer decides almost everything about what role the wsi 29 * will play, h2, raw, ws, etc. 30 * 31 * However there are a few additional flags needed that vary, such as if the 32 * role is a client or server side, if it has that concept. And the connection 33 * fulfilling the role, has a separate dynamic state. 34 * 35 * 31 16 15 0 36 * [ role flags ] [ state ] 37 * 38 * The role flags part is generally invariant for the lifetime of the wsi, 39 * although it can change if the connection role itself does, eg, if the 40 * connection upgrades from H1 -> WS1 the role flags may be changed at that 41 * point. 42 * 43 * The state part reflects the dynamic connection state, and the states are 44 * reused between roles. 45 * 46 * None of the internal role or state representations are made available outside 47 * of lws internals. Even for lws internals, if you add stuff here, please keep 48 * the constants inside this header only by adding necessary helpers here and 49 * use the helpers in the actual code. This is to ease any future refactors. 50 * 51 * Notice LWSIFR_ENCAP means we have a parent wsi that actually carries our 52 * data as a stream inside a different protocol. 53 */ 54 55 #define _RS 16 56 57 #define LWSIFR_CLIENT (0x1000 << _RS) /* client side */ 58 #define LWSIFR_SERVER (0x2000 << _RS) /* server side */ 59 60 #define LWSIFR_P_ENCAP_H2 (0x0100 << _RS) /* we are encapsulated by h2 */ 61 62 enum lwsi_role { 63 LWSI_ROLE_MASK = (0xffff << _RS), 64 LWSI_ROLE_ENCAP_MASK = (0x0f00 << _RS), 65 }; 66 67 #define lwsi_role(wsi) (wsi->wsistate & (unsigned int)LWSI_ROLE_MASK) 68 #if !defined (_DEBUG) 69 #define lwsi_set_role(wsi, role) wsi->wsistate = \ 70 (wsi->wsistate & (~LWSI_ROLE_MASK)) | role 71 #else 72 void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role); 73 #endif 74 75 #define lwsi_role_client(wsi) (!!(wsi->wsistate & LWSIFR_CLIENT)) 76 #define lwsi_role_server(wsi) (!!(wsi->wsistate & LWSIFR_SERVER)) 77 #define lwsi_role_h2_ENCAPSULATION(wsi) \ 78 ((wsi->wsistate & LWSI_ROLE_ENCAP_MASK) == LWSIFR_P_ENCAP_H2) 79 80 /* Pollout wants a callback in this state */ 81 #define LWSIFS_POCB (0x100) 82 /* Before any protocol connection was established */ 83 #define LWSIFS_NOT_EST (0x200) 84 85 enum lwsi_state { 86 87 /* Phase 1: pre-transport */ 88 89 LRS_UNCONNECTED = LWSIFS_NOT_EST | 0, 90 LRS_WAITING_DNS = LWSIFS_NOT_EST | 1, 91 LRS_WAITING_CONNECT = LWSIFS_NOT_EST | 2, 92 93 /* Phase 2: establishing intermediaries on top of transport */ 94 95 LRS_WAITING_PROXY_REPLY = LWSIFS_NOT_EST | 3, 96 LRS_WAITING_SSL = LWSIFS_NOT_EST | 4, 97 LRS_WAITING_SOCKS_GREETING_REPLY = LWSIFS_NOT_EST | 5, 98 LRS_WAITING_SOCKS_CONNECT_REPLY = LWSIFS_NOT_EST | 6, 99 LRS_WAITING_SOCKS_AUTH_REPLY = LWSIFS_NOT_EST | 7, 100 101 /* Phase 3: establishing tls tunnel */ 102 103 LRS_SSL_INIT = LWSIFS_NOT_EST | 8, 104 LRS_SSL_ACK_PENDING = LWSIFS_NOT_EST | 9, 105 LRS_PRE_WS_SERVING_ACCEPT = LWSIFS_NOT_EST | 10, 106 107 /* Phase 4: connected */ 108 109 LRS_WAITING_SERVER_REPLY = LWSIFS_NOT_EST | 11, 110 LRS_H2_AWAIT_PREFACE = LWSIFS_NOT_EST | 12, 111 LRS_H2_AWAIT_SETTINGS = LWSIFS_NOT_EST | 112 LWSIFS_POCB | 13, 113 LRS_MQTTC_IDLE = LWSIFS_POCB | 33, 114 LRS_MQTTC_AWAIT_CONNACK = 34, 115 116 /* Phase 5: protocol logically established */ 117 118 LRS_H2_CLIENT_SEND_SETTINGS = LWSIFS_POCB | 14, 119 LRS_H2_WAITING_TO_SEND_HEADERS = LWSIFS_POCB | 15, 120 LRS_DEFERRING_ACTION = LWSIFS_POCB | 16, 121 LRS_IDLING = 17, 122 LRS_H1C_ISSUE_HANDSHAKE = 18, 123 LRS_H1C_ISSUE_HANDSHAKE2 = 19, 124 LRS_ISSUE_HTTP_BODY = 20, 125 LRS_ISSUING_FILE = 21, 126 LRS_HEADERS = 22, 127 LRS_BODY = 23, 128 LRS_DISCARD_BODY = 24, 129 LRS_ESTABLISHED = LWSIFS_POCB | 25, 130 131 /* we are established, but we have embarked on serving a single 132 * transaction. Other transaction input may be pending, but we will 133 * not service it while we are busy dealing with the current 134 * transaction. 135 * 136 * When we complete the current transaction, we would reset our state 137 * back to ESTABLISHED and start to process the next transaction. 138 */ 139 LRS_DOING_TRANSACTION = LWSIFS_POCB | 26, 140 141 /* Phase 6: finishing */ 142 143 LRS_WAITING_TO_SEND_CLOSE = LWSIFS_POCB | 27, 144 LRS_RETURNED_CLOSE = LWSIFS_POCB | 28, 145 LRS_AWAITING_CLOSE_ACK = LWSIFS_POCB | 29, 146 LRS_FLUSHING_BEFORE_CLOSE = LWSIFS_POCB | 30, 147 LRS_SHUTDOWN = 31, 148 149 /* Phase 7: dead */ 150 151 LRS_DEAD_SOCKET = 32, 152 153 LRS_MASK = 0xffff 154 }; 155 156 #define lwsi_state(wsi) ((enum lwsi_state)(wsi->wsistate & LRS_MASK)) 157 #define lwsi_state_PRE_CLOSE(wsi) \ 158 ((enum lwsi_state)(wsi->wsistate_pre_close & LRS_MASK)) 159 #define lwsi_state_est(wsi) (!(wsi->wsistate & LWSIFS_NOT_EST)) 160 #define lwsi_state_est_PRE_CLOSE(wsi) \ 161 (!(wsi->wsistate_pre_close & LWSIFS_NOT_EST)) 162 #define lwsi_state_can_handle_POLLOUT(wsi) (wsi->wsistate & LWSIFS_POCB) 163 #if !defined (_DEBUG) 164 #define lwsi_set_state(wsi, lrs) wsi->wsistate = \ 165 (wsi->wsistate & (lws_wsi_state_t)(~LRS_MASK)) | lrs 166 #else 167 void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs); 168 #endif 169 170 #define _LWS_ADOPT_FINISH (1 << 24) 171 172 /* 173 * Internal role-specific ops 174 * 175 * Many roles are sparsely filled with callbacks, rather than has 20 x 176 * function pointers in the ops struct, let's have a 20 nybble array telling us 177 * if the pointer doesn't exist, or its offset in a smaller "just pointers that 178 * exist" array. 179 * 180 * We can support up to 15 valid pointers in the role that way and only have to 181 * provide pointers that exist for that role, at the cost of a 10-byte nybble 182 * table. 183 * 184 * For x86_64, a set 196 byte allocation becomes 60 + 8 bytes per defined ptr, 185 * where the ops table is sparse this is a considable .rodata saving, for 32-bit 186 * 52 + 4 bytes per defined ptr accounting for padding. 187 */ 188 189 /* 190 * After http headers have parsed, this is the last chance for a role 191 * to upgrade the connection to something else using the headers. 192 * ws-over-h2 is upgraded from h2 like this. 193 */ 194 typedef int (*lws_rops_check_upgrades_t)(struct lws *wsi); 195 /* role-specific context init during context creation */ 196 typedef int (*lws_rops_pt_init_destroy_t)(struct lws_context *context, 197 const struct lws_context_creation_info *info, 198 struct lws_context_per_thread *pt, int destroy); 199 /* role-specific per-vhost init during vhost creation */ 200 typedef int (*lws_rops_init_vhost_t)(struct lws_vhost *vh, 201 const struct lws_context_creation_info *info); 202 /* role-specific per-vhost destructor during vhost destroy */ 203 typedef int (*lws_rops_destroy_vhost_t)(struct lws_vhost *vh); 204 /* chance for the role to force POLLIN without network activity */ 205 typedef int (*lws_rops_service_flag_pending_t)(struct lws_context *context, 206 int tsi); 207 /* an fd using this role has POLLIN signalled */ 208 typedef int (*lws_rops_handle_POLLIN_t)(struct lws_context_per_thread *pt, 209 struct lws *wsi, 210 struct lws_pollfd *pollfd); 211 /* an fd using the role wanted a POLLOUT callback and now has it */ 212 typedef int (*lws_rops_handle_POLLOUT_t)(struct lws *wsi); 213 /* perform user pollout */ 214 typedef int (*lws_rops_perform_user_POLLOUT_t)(struct lws *wsi); 215 /* do effective callback on writeable */ 216 typedef int (*lws_rops_callback_on_writable_t)(struct lws *wsi); 217 /* connection-specific tx credit in bytes */ 218 typedef int (*lws_rops_tx_credit_t)(struct lws *wsi, char peer_to_us, int add); 219 /* role-specific write formatting */ 220 typedef int (*lws_rops_write_role_protocol_t)(struct lws *wsi, 221 unsigned char *buf, size_t len, 222 enum lws_write_protocol *wp); 223 224 /* get encapsulation parent */ 225 typedef struct lws * (*lws_rops_encapsulation_parent_t)(struct lws *wsi); 226 227 /* role-specific destructor */ 228 typedef int (*lws_rops_alpn_negotiated_t)(struct lws *wsi, const char *alpn); 229 230 /* chance for the role to handle close in the protocol */ 231 typedef int (*lws_rops_close_via_role_protocol_t)(struct lws *wsi, 232 enum lws_close_status reason); 233 /* role-specific close processing */ 234 typedef int (*lws_rops_close_role_t)(struct lws_context_per_thread *pt, 235 struct lws *wsi); 236 /* role-specific connection close processing */ 237 typedef int (*lws_rops_close_kill_connection_t)(struct lws *wsi, 238 enum lws_close_status reason); 239 /* role-specific destructor */ 240 typedef int (*lws_rops_destroy_role_t)(struct lws *wsi); 241 242 /* role-specific socket-adopt */ 243 typedef int (*lws_rops_adoption_bind_t)(struct lws *wsi, int type, 244 const char *prot); 245 /* role-specific client-bind: 246 * ret 1 = bound, 0 = not bound, -1 = fail out 247 * i may be NULL, indicating client_bind is being called after 248 * a successful bind earlier, to finalize the binding. In that 249 * case ret 0 = OK, 1 = fail, wsi needs freeing, -1 = fail, wsi freed */ 250 typedef int (*lws_rops_client_bind_t)(struct lws *wsi, 251 const struct lws_client_connect_info *i); 252 /* isvalid = 0: request a role-specific keepalive (PING etc) 253 * = 1: reset any related validity timer */ 254 typedef int (*lws_rops_issue_keepalive_t)(struct lws *wsi, int isvalid); 255 256 #define LWS_COUNT_ROLE_OPS 20 257 258 typedef union lws_rops { 259 lws_rops_check_upgrades_t check_upgrades; 260 lws_rops_pt_init_destroy_t pt_init_destroy; 261 lws_rops_init_vhost_t init_vhost; 262 lws_rops_destroy_vhost_t destroy_vhost; 263 lws_rops_service_flag_pending_t service_flag_pending; 264 lws_rops_handle_POLLIN_t handle_POLLIN; 265 lws_rops_handle_POLLOUT_t handle_POLLOUT; 266 lws_rops_perform_user_POLLOUT_t perform_user_POLLOUT; 267 lws_rops_callback_on_writable_t callback_on_writable; 268 lws_rops_tx_credit_t tx_credit; 269 lws_rops_write_role_protocol_t write_role_protocol; 270 lws_rops_encapsulation_parent_t encapsulation_parent; 271 lws_rops_alpn_negotiated_t alpn_negotiated; 272 lws_rops_close_via_role_protocol_t close_via_role_protocol; 273 lws_rops_close_role_t close_role; 274 lws_rops_close_kill_connection_t close_kill_connection; 275 lws_rops_destroy_role_t destroy_role; 276 lws_rops_adoption_bind_t adoption_bind; 277 lws_rops_client_bind_t client_bind; 278 lws_rops_issue_keepalive_t issue_keepalive; 279 } lws_rops_t; 280 281 typedef enum { 282 LWS_ROPS_check_upgrades, 283 LWS_ROPS_pt_init_destroy, 284 LWS_ROPS_init_vhost, 285 LWS_ROPS_destroy_vhost, 286 LWS_ROPS_service_flag_pending, 287 LWS_ROPS_handle_POLLIN, 288 LWS_ROPS_handle_POLLOUT, 289 LWS_ROPS_perform_user_POLLOUT, 290 LWS_ROPS_callback_on_writable, 291 LWS_ROPS_tx_credit, 292 LWS_ROPS_write_role_protocol, 293 LWS_ROPS_encapsulation_parent, 294 LWS_ROPS_alpn_negotiated, 295 LWS_ROPS_close_via_role_protocol, 296 LWS_ROPS_close_role, 297 LWS_ROPS_close_kill_connection, 298 LWS_ROPS_destroy_role, 299 LWS_ROPS_adoption_bind, 300 LWS_ROPS_client_bind, 301 LWS_ROPS_issue_keepalive, 302 } lws_rops_func_idx_t; 303 304 struct lws_context_per_thread; 305 306 struct lws_role_ops { 307 const char *name; 308 const char *alpn; 309 310 const lws_rops_t *rops_table; 311 /**< the occupied role ops func ptrs */ 312 uint8_t rops_idx[(LWS_COUNT_ROLE_OPS + 1) / 2]; 313 /**< translates role index into .rops[] offset */ 314 315 /* 316 * the callback reasons for adoption for client, server 317 * (just client applies if no concept of client or server) 318 */ 319 uint8_t adoption_cb[2]; 320 /* 321 * the callback reasons for adoption for client, server 322 * (just client applies if no concept of client or server) 323 */ 324 uint8_t rx_cb[2]; 325 /* 326 * the callback reasons for WRITEABLE for client, server 327 * (just client applies if no concept of client or server) 328 */ 329 uint8_t writeable_cb[2]; 330 /* 331 * the callback reasons for CLOSE for client, server 332 * (just client applies if no concept of client or server) 333 */ 334 uint8_t close_cb[2]; 335 /* 336 * the callback reasons for protocol bind for client, server 337 * (just client applies if no concept of client or server) 338 */ 339 uint8_t protocol_bind_cb[2]; 340 /* 341 * the callback reasons for protocol unbind for client, server 342 * (just client applies if no concept of client or server) 343 */ 344 uint8_t protocol_unbind_cb[2]; 345 346 uint8_t file_handle:1; 347 /* role operates on files not sockets */ 348 }; 349 350 #define lws_rops_fidx(_rops, fidx) \ 351 ((fidx & 1) ? (_rops)->rops_idx[fidx / 2] & 0xf : \ 352 (_rops)->rops_idx[fidx / 2] >> 4) 353 354 #define lws_rops_func_fidx(_rops, fidx) \ 355 ((_rops)->rops_table[lws_rops_fidx(_rops, fidx) - 1]) 356 357 /* core roles */ 358 extern const struct lws_role_ops role_ops_raw_skt, role_ops_raw_file, 359 role_ops_listen, role_ops_pipe, 360 role_ops_netlink; 361 362 /* bring in role private declarations */ 363 364 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) 365 #include "private-lib-roles-http.h" 366 #else 367 #define lwsi_role_http(wsi) (0) 368 #endif 369 370 #if defined(LWS_ROLE_H1) 371 #include "private-lib-roles-h1.h" 372 #else 373 #define lwsi_role_h1(wsi) (0) 374 #endif 375 376 #if defined(LWS_ROLE_H2) 377 #include "private-lib-roles-h2.h" 378 #else 379 #define lwsi_role_h2(wsi) (0) 380 #endif 381 382 #if defined(LWS_ROLE_WS) 383 #include "private-lib-roles-ws.h" 384 #else 385 #define lwsi_role_ws(wsi) (0) 386 #endif 387 388 #if defined(LWS_ROLE_CGI) 389 #include "private-lib-roles-cgi.h" 390 #else 391 #define lwsi_role_cgi(wsi) (0) 392 #endif 393 394 #if defined(LWS_ROLE_DBUS) 395 #include "private-lib-roles-dbus.h" 396 #else 397 #define lwsi_role_dbus(wsi) (0) 398 #endif 399 400 #if defined(LWS_ROLE_RAW_PROXY) 401 #include "private-lib-roles-raw-proxy.h" 402 #else 403 #define lwsi_role_raw_proxy(wsi) (0) 404 #endif 405 406 #if defined(LWS_ROLE_MQTT) 407 #include "mqtt/private-lib-roles-mqtt.h" 408 #else 409 #define lwsi_role_mqtt(wsi) (0) 410 #endif 411 412 enum { 413 LWS_HP_RET_BAIL_OK, 414 LWS_HP_RET_BAIL_DIE, 415 LWS_HP_RET_USER_SERVICE, 416 LWS_HP_RET_DROP_POLLOUT, 417 418 LWS_HPI_RET_WSI_ALREADY_DIED, /* we closed it */ 419 LWS_HPI_RET_HANDLED, /* no probs */ 420 LWS_HPI_RET_PLEASE_CLOSE_ME, /* close it for us */ 421 422 LWS_UPG_RET_DONE, 423 LWS_UPG_RET_CONTINUE, 424 LWS_UPG_RET_BAIL 425 }; 426 427 #define LWS_CONNECT_COMPLETION_GOOD (-99) 428 429 int 430 lws_role_call_adoption_bind(struct lws *wsi, int type, const char *prot); 431 432 struct lws * 433 lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, 434 ssize_t plen); 435 436 struct lws * 437 lws_client_connect_3_connect(struct lws *wsi, const char *ads, 438 const struct addrinfo *result, int n, void *opaque); 439