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 #include "private-lib-core.h" 26 #include "private-lib-abstract.h" 27 28 typedef struct lws_abstxp_raw_skt_priv { 29 struct lws_abs *abs; 30 struct lws *wsi; 31 32 lws_dll2_t same_abs_transport_list; 33 34 uint8_t established:1; 35 uint8_t connecting:1; 36 } abs_raw_skt_priv_t; 37 38 struct vhd { 39 lws_dll2_owner_t owner; 40 }; 41 42 static int heartbeat_cb(struct lws_dll2 * d,void * user)43 heartbeat_cb(struct lws_dll2 *d, void *user) 44 { 45 abs_raw_skt_priv_t *priv = lws_container_of(d, abs_raw_skt_priv_t, 46 same_abs_transport_list); 47 48 if (priv->abs->ap->heartbeat) 49 priv->abs->ap->heartbeat(priv->abs->api); 50 51 return 0; 52 } 53 54 static int callback_abs_client_raw_skt(struct lws * wsi,enum lws_callback_reasons reason,void * user,void * in,size_t len)55 callback_abs_client_raw_skt(struct lws *wsi, enum lws_callback_reasons reason, 56 void *user, void *in, size_t len) 57 { 58 abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)user; 59 struct vhd *vhd = (struct vhd *) 60 lws_protocol_vh_priv_get(lws_get_vhost(wsi), 61 lws_get_protocol(wsi)); 62 63 switch (reason) { 64 case LWS_CALLBACK_PROTOCOL_INIT: 65 vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), 66 lws_get_protocol(wsi), sizeof(struct vhd)); 67 if (!vhd) 68 return 1; 69 lws_timed_callback_vh_protocol(lws_get_vhost(wsi), 70 lws_get_protocol(wsi), 71 LWS_CALLBACK_USER, 1); 72 break; 73 74 case LWS_CALLBACK_USER: 75 /* 76 * This comes at 1Hz without a wsi context, so there is no 77 * valid priv. We need to track the live abstract objects that 78 * are using our abstract protocol, and pass the heartbeat 79 * through to the ones that care. 80 */ 81 if (!vhd) 82 break; 83 84 lws_dll2_foreach_safe(&vhd->owner, NULL, heartbeat_cb); 85 86 lws_timed_callback_vh_protocol(lws_get_vhost(wsi), 87 lws_get_protocol(wsi), 88 LWS_CALLBACK_USER, 1); 89 break; 90 91 case LWS_CALLBACK_RAW_CONNECTED: 92 lwsl_debug("LWS_CALLBACK_RAW_CONNECTED\n"); 93 priv->connecting = 0; 94 priv->established = 1; 95 if (priv->abs->ap->accept) 96 priv->abs->ap->accept(priv->abs->api); 97 if (wsi->seq) 98 /* 99 * we are bound to a sequencer who wants to know about 100 * our lifecycle events 101 */ 102 103 lws_seq_queue_event(wsi->seq, LWSSEQ_WSI_CONNECTED, 104 wsi, NULL); 105 break; 106 107 case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: 108 lwsl_user("CONNECTION_ERROR\n"); 109 if (in) 110 lwsl_user(" %s\n", (const char *)in); 111 112 if (wsi->seq) 113 /* 114 * we are bound to a sequencer who wants to know about 115 * our lifecycle events 116 */ 117 118 lws_seq_queue_event(wsi->seq, LWSSEQ_WSI_CONN_FAIL, 119 wsi, NULL); 120 121 goto close_path; 122 123 /* fallthru */ 124 case LWS_CALLBACK_RAW_CLOSE: 125 if (!user) 126 break; 127 128 if (wsi->seq) 129 /* 130 * we are bound to a sequencer who wants to know about 131 * our lifecycle events 132 */ 133 134 lws_seq_queue_event(wsi->seq, LWSSEQ_WSI_CONN_CLOSE, 135 wsi, NULL); 136 137 close_path: 138 lwsl_debug("LWS_CALLBACK_RAW_CLOSE\n"); 139 priv->established = 0; 140 priv->connecting = 0; 141 if (priv->abs && priv->abs->ap->closed) 142 priv->abs->ap->closed(priv->abs->api); 143 lws_set_wsi_user(wsi, NULL); 144 break; 145 146 case LWS_CALLBACK_RAW_RX: 147 lwsl_debug("LWS_CALLBACK_RAW_RX (%d)\n", (int)len); 148 return !!priv->abs->ap->rx(priv->abs->api, in, len); 149 150 case LWS_CALLBACK_RAW_WRITEABLE: 151 lwsl_debug("LWS_CALLBACK_RAW_WRITEABLE\n"); 152 priv->abs->ap->writeable(priv->abs->api, 153 lws_get_peer_write_allowance(priv->wsi)); 154 break; 155 156 case LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL: 157 lws_dll2_add_tail(&priv->same_abs_transport_list, &vhd->owner); 158 break; 159 160 case LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL: 161 lws_dll2_remove(&priv->same_abs_transport_list); 162 break; 163 164 default: 165 break; 166 } 167 168 return 0; 169 } 170 171 static int lws_atcrs_close(lws_abs_transport_inst_t * ati)172 lws_atcrs_close(lws_abs_transport_inst_t *ati) 173 { 174 abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati; 175 struct lws *wsi = priv->wsi; 176 177 if (!priv->wsi) 178 return 0; 179 180 if (!lws_raw_transaction_completed(priv->wsi)) 181 return 0; 182 183 priv->wsi = NULL; 184 lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC); 185 186 /* priv is destroyed in the CLOSE callback */ 187 188 return 0; 189 } 190 191 192 const struct lws_protocols protocol_abs_client_raw_skt = { 193 "lws-abs-cli-raw-skt", callback_abs_client_raw_skt, 194 0, 1024, 1024, NULL, 0 195 }; 196 197 static int lws_atcrs_tx(lws_abs_transport_inst_t * ati,uint8_t * buf,size_t len)198 lws_atcrs_tx(lws_abs_transport_inst_t *ati, uint8_t *buf, size_t len) 199 { 200 abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati; 201 202 if (!priv->wsi) { 203 lwsl_err("%s: NULL priv->wsi\n", __func__); 204 return 1; 205 } 206 207 lwsl_debug("%s: priv %p, wsi %p, ro %p\n", __func__, 208 priv, priv->wsi, priv->wsi->role_ops); 209 210 if (lws_write(priv->wsi, buf, len, LWS_WRITE_RAW) < 0) 211 lws_atcrs_close(ati); 212 213 return 0; 214 } 215 216 #if defined(LWS_WITH_CLIENT) 217 static int lws_atcrs_client_conn(const lws_abs_t * abs)218 lws_atcrs_client_conn(const lws_abs_t *abs) 219 { 220 abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)abs->ati; 221 struct lws_client_connect_info i; 222 const lws_token_map_t *tm; 223 224 if (priv->connecting) 225 return 0; 226 227 if (priv->established) { 228 lws_set_timeout(priv->wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, 5); 229 230 return 0; 231 } 232 233 memset(&i, 0, sizeof(i)); 234 235 /* address and port are passed-in using the abstract transport tokens */ 236 237 tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_V_DNS_ADDRESS); 238 if (!tm) { 239 lwsl_notice("%s: raw_skt needs LTMI_PEER_V_DNS_ADDRESS\n", 240 __func__); 241 242 return 1; 243 } 244 i.address = tm->u.value; 245 246 tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_LV_PORT); 247 if (!tm) { 248 lwsl_notice("%s: raw_skt needs LTMI_PEER_LV_PORT\n", __func__); 249 250 return 1; 251 } 252 i.port = tm->u.lvalue; 253 254 /* optional */ 255 i.ssl_connection = 0; 256 tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_LV_TLS_FLAGS); 257 if (tm) 258 i.ssl_connection = tm->u.lvalue; 259 260 261 lwsl_debug("%s: raw_skt priv %p connecting to %s:%u %p\n", 262 __func__, priv, i.address, i.port, abs->vh->context); 263 264 i.path = ""; 265 i.method = "RAW"; 266 i.vhost = abs->vh; 267 i.userdata = priv; 268 i.host = i.address; 269 i.pwsi = &priv->wsi; 270 i.origin = i.address; 271 i.context = abs->vh->context; 272 i.local_protocol_name = "lws-abs-cli-raw-skt"; 273 i.seq = abs->seq; 274 i.opaque_user_data = abs->opaque_user_data; 275 276 /* 277 * the protocol itself has some natural attributes we should pass on 278 */ 279 280 if (abs->ap->flags & LWS_AP_FLAG_PIPELINE_TRANSACTIONS) 281 i.ssl_connection |= LCCSCF_PIPELINE; 282 283 if (abs->ap->flags & LWS_AP_FLAG_MUXABLE_STREAM) 284 i.ssl_connection |= LCCSCF_MUXABLE_STREAM; 285 286 priv->wsi = lws_client_connect_via_info(&i); 287 if (!priv->wsi) 288 return 1; 289 290 priv->connecting = 1; 291 292 return 0; 293 } 294 #endif 295 296 static int lws_atcrs_ask_for_writeable(lws_abs_transport_inst_t * ati)297 lws_atcrs_ask_for_writeable(lws_abs_transport_inst_t *ati) 298 { 299 abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati; 300 301 if (!priv->wsi || !priv->established) 302 return 1; 303 304 lws_callback_on_writable(priv->wsi); 305 306 return 0; 307 } 308 309 static int lws_atcrs_create(struct lws_abs * ai)310 lws_atcrs_create(struct lws_abs *ai) 311 { 312 abs_raw_skt_priv_t *at = (abs_raw_skt_priv_t *)ai->ati; 313 314 memset(at, 0, sizeof(*at)); 315 at->abs = ai; 316 317 return 0; 318 } 319 320 static void lws_atcrs_destroy(lws_abs_transport_inst_t ** pati)321 lws_atcrs_destroy(lws_abs_transport_inst_t **pati) 322 { 323 /* 324 * For ourselves, we don't free anything because the abstract layer 325 * combined our allocation with that of the abs instance, and it will 326 * free the whole thing after this. 327 */ 328 *pati = NULL; 329 } 330 331 static int lws_atcrs_set_timeout(lws_abs_transport_inst_t * ati,int reason,int secs)332 lws_atcrs_set_timeout(lws_abs_transport_inst_t *ati, int reason, int secs) 333 { 334 abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati; 335 336 lws_set_timeout(priv->wsi, reason, secs); 337 338 return 0; 339 } 340 341 static int lws_atcrs_state(lws_abs_transport_inst_t * ati)342 lws_atcrs_state(lws_abs_transport_inst_t *ati) 343 { 344 abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati; 345 346 if (!priv || !priv->wsi || (!priv->established && !priv->connecting)) 347 return 0; 348 349 return 1; 350 } 351 352 static int lws_atcrs_compare(lws_abs_t * abs1,lws_abs_t * abs2)353 lws_atcrs_compare(lws_abs_t *abs1, lws_abs_t *abs2) 354 { 355 const lws_token_map_t *tm1, *tm2; 356 357 tm1 = lws_abs_get_token(abs1->at_tokens, LTMI_PEER_V_DNS_ADDRESS); 358 tm2 = lws_abs_get_token(abs2->at_tokens, LTMI_PEER_V_DNS_ADDRESS); 359 360 /* Address token is mandatory and must match */ 361 if (!tm1 || !tm2 || strcmp(tm1->u.value, tm2->u.value)) 362 return 1; 363 364 /* Port token is mandatory and must match */ 365 tm1 = lws_abs_get_token(abs1->at_tokens, LTMI_PEER_LV_PORT); 366 tm2 = lws_abs_get_token(abs2->at_tokens, LTMI_PEER_LV_PORT); 367 if (!tm1 || !tm2 || tm1->u.lvalue != tm2->u.lvalue) 368 return 1; 369 370 /* TLS is optional... */ 371 tm1 = lws_abs_get_token(abs1->at_tokens, LTMI_PEER_LV_TLS_FLAGS); 372 tm2 = lws_abs_get_token(abs2->at_tokens, LTMI_PEER_LV_TLS_FLAGS); 373 374 /* ... but both must have the same situation with it given or not... */ 375 if (!!tm1 != !!tm2) 376 return 1; 377 378 /* if not using TLS, then that's enough to call it */ 379 if (!tm1) 380 return 0; 381 382 /* ...and if there are tls flags, both must have the same tls flags */ 383 if (tm1->u.lvalue != tm2->u.lvalue) 384 return 1; 385 386 /* ... and both must use the same client tls ctx / vhost */ 387 return abs1->vh != abs2->vh; 388 } 389 390 const lws_abs_transport_t lws_abs_transport_cli_raw_skt = { 391 .name = "raw_skt", 392 .alloc = sizeof(abs_raw_skt_priv_t), 393 394 .create = lws_atcrs_create, 395 .destroy = lws_atcrs_destroy, 396 .compare = lws_atcrs_compare, 397 398 .tx = lws_atcrs_tx, 399 #if !defined(LWS_WITH_CLIENT) 400 .client_conn = NULL, 401 #else 402 .client_conn = lws_atcrs_client_conn, 403 #endif 404 .close = lws_atcrs_close, 405 .ask_for_writeable = lws_atcrs_ask_for_writeable, 406 .set_timeout = lws_atcrs_set_timeout, 407 .state = lws_atcrs_state, 408 }; 409