1/* 2 * libwebsockets - small server side websockets and web server implementation 3 * 4 * Copyright (C) 2019 - 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 is the glue that wires up raw-socket to Secure Streams. 25 */ 26 27#include <private-lib-core.h> 28 29int 30secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, 31 void *in, size_t len) 32{ 33#if defined(LWS_WITH_SERVER) 34 struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 35#endif 36 lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); 37 uint8_t buf[LWS_PRE + 1520], *p = &buf[LWS_PRE], 38 *end = &buf[sizeof(buf) - 1]; 39 lws_ss_state_return_t r; 40 size_t buflen; 41 int f = 0; 42 43 switch (reason) { 44 45 case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: 46 assert(h); 47 assert(h->policy); 48 lwsl_info("%s: %s, %s CLIENT_CONNECTION_ERROR: %s\n", __func__, 49 lws_ss_tag(h), h->policy->streamtype, in ? (char *)in : "(null)"); 50 51#if defined(LWS_WITH_CONMON) 52 lws_conmon_ss_json(h); 53#endif 54 55 r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); 56 if (r == LWSSSSRET_DESTROY_ME) 57 return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 58 h->wsi = NULL; 59 r = lws_ss_backoff(h); 60 if (r != LWSSSSRET_OK) 61 return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 62 break; 63 64 case LWS_CALLBACK_RAW_CLOSE: 65 if (!h) 66 break; 67 lws_sul_cancel(&h->sul_timeout); 68 69#if defined(LWS_WITH_CONMON) 70 lws_conmon_ss_json(h); 71#endif 72 73 lwsl_info("%s: %s, %s RAW_CLOSE\n", __func__, lws_ss_tag(h), 74 h->policy ? h->policy->streamtype : "no policy"); 75 h->wsi = NULL; 76#if defined(LWS_WITH_SERVER) 77 lws_pt_lock(pt, __func__); 78 lws_dll2_remove(&h->cli_list); 79 lws_pt_unlock(pt); 80#endif 81 82 /* wsi is going down anyway */ 83 r = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); 84 if (r == LWSSSSRET_DESTROY_ME) 85 return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 86 87 if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && 88#if defined(LWS_WITH_SERVER) 89 !(h->info.flags & LWSSSINFLAGS_ACCEPTED) && /* not server */ 90#endif 91 !h->txn_ok && !wsi->a.context->being_destroyed) { 92 r = lws_ss_backoff(h); 93 if (r != LWSSSSRET_OK) 94 return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 95 break; 96 } 97 98 break; 99 100 case LWS_CALLBACK_RAW_CONNECTED: 101 lwsl_info("%s: RAW_CONNECTED\n", __func__); 102 103 h->retry = 0; 104 h->seqstate = SSSEQ_CONNECTED; 105 lws_sul_cancel(&h->sul); 106#if defined(LWS_WITH_SYS_METRICS) 107 /* 108 * If any hanging caliper measurement, dump it, and free any tags 109 */ 110 lws_metrics_caliper_report_hist(h->cal_txn, (struct lws *)NULL); 111#endif 112 r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); 113 if (r != LWSSSSRET_OK) 114 return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 115 116 lws_validity_confirmed(wsi); 117 break; 118 119 case LWS_CALLBACK_RAW_ADOPT: 120 lwsl_info("%s: RAW_ADOPT\n", __func__); 121 break; 122 123 /* chunks of chunked content, with header removed */ 124 case LWS_CALLBACK_RAW_RX: 125 if (!h || !h->info.rx) 126 return 0; 127 128 r = h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, 0); 129 if (r != LWSSSSRET_OK) 130 return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 131 132 return 0; /* don't passthru */ 133 134 case LWS_CALLBACK_RAW_WRITEABLE: 135 lwsl_info("%s: RAW_WRITEABLE\n", __func__); 136 if (!h || !h->info.tx) 137 return 0; 138 139 buflen = lws_ptr_diff_size_t(end, p); 140 r = h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f); 141 if (r == LWSSSSRET_TX_DONT_SEND) 142 return 0; 143 if (r < 0) 144 return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 145 146 /* 147 * flags are ignored with raw, there are no protocol payload 148 * boundaries, just an arbitrarily-fragmented bytestream 149 */ 150 151 p += buflen; 152 if (lws_write(wsi, buf + LWS_PRE, lws_ptr_diff_size_t(p, buf + LWS_PRE), 153 LWS_WRITE_HTTP) != lws_ptr_diff(p, buf + LWS_PRE)) { 154 lwsl_err("%s: write failed\n", __func__); 155 return -1; 156 } 157 158 lws_set_timeout(wsi, 0, 0); 159 break; 160 161 default: 162 break; 163 } 164 165 return 0; 166} 167 168static int 169secstream_connect_munge_raw(lws_ss_handle_t *h, char *buf, size_t len, 170 struct lws_client_connect_info *i, 171 union lws_ss_contemp *ct) 172{ 173 i->method = "RAW"; 174 175 return 0; 176} 177 178 179const struct lws_protocols protocol_secstream_raw = { 180 "lws-secstream-raw", 181 secstream_raw, 182 0, 183 0, 184 0, NULL, 0 185}; 186 187const struct ss_pcols ss_pcol_raw = { 188 "raw", 189 "", 190 &protocol_secstream_raw, 191 secstream_connect_munge_raw, 192 NULL, NULL 193}; 194