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