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
25 #include <private-lib-core.h>
26
27 #if defined(LWS_WITH_CLIENT)
28 static int
lws_raw_skt_connect(struct lws *wsi)29 lws_raw_skt_connect(struct lws *wsi)
30 {
31 int n;
32 #if defined(LWS_WITH_TLS)
33 const char *cce = NULL;
34 char ccebuf[128];
35
36 #if !defined(LWS_WITH_SYS_ASYNC_DNS)
37 switch (lws_client_create_tls(wsi, &cce, 1)) {
38 #else
39 switch (lws_client_create_tls(wsi, &cce, 0)) {
40 #endif
41 case CCTLS_RETURN_ERROR:
42 lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
43 return -1;
44 case CCTLS_RETURN_RETRY:
45 return 0;
46 case CCTLS_RETURN_DONE:
47 break;
48 }
49
50 if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
51 n = lws_ssl_client_connect2(wsi, ccebuf, sizeof(ccebuf));
52 if (n < 0) {
53 lws_inform_client_conn_fail(wsi, (void *)ccebuf,
54 strlen(ccebuf));
55
56 return -1;
57 }
58 if (n != 1)
59 return 0; /* wait */
60 }
61 #endif
62
63 n = user_callback_handle_rxflow(wsi->a.protocol->callback,
64 wsi, wsi->role_ops->adoption_cb[lwsi_role_server(wsi)],
65 wsi->user_space, NULL, 0);
66 if (n) {
67 lws_inform_client_conn_fail(wsi, (void *)"user", 4);
68 return 1;
69 }
70
71 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
72 lwsi_set_state(wsi, LRS_ESTABLISHED);
73
74 return 1; /* success */
75 }
76 #endif
77
78 static int
79 rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi,
80 struct lws_pollfd *pollfd)
81 {
82 #if defined(LWS_WITH_SOCKS5)
83 const char *cce = NULL;
84 #endif
85 struct lws_tokens ebuf;
86 int n = 0, buffered = 0;
87
88 /* pending truncated sends have uber priority */
89
90 if (lws_has_buffered_out(wsi)) {
91 if (!(pollfd->revents & LWS_POLLOUT))
92 return LWS_HPI_RET_HANDLED;
93
94 /* drain the output buflist */
95 if (lws_issue_raw(wsi, NULL, 0) < 0)
96 goto fail;
97 /*
98 * we can't afford to allow input processing to send
99 * something new, so spin around he event loop until
100 * he doesn't have any partials
101 */
102 return LWS_HPI_RET_HANDLED;
103 }
104
105
106 #if defined(LWS_WITH_SERVER)
107 if (!lwsi_role_client(wsi) && lwsi_state(wsi) != LRS_ESTABLISHED) {
108
109 lwsl_wsi_debug(wsi, "wsistate 0x%x\n", (int)wsi->wsistate);
110
111 if (lwsi_state(wsi) != LRS_SSL_INIT)
112 if (lws_server_socket_service_ssl(wsi,
113 LWS_SOCK_INVALID,
114 !!(pollfd->revents & pollfd->events & LWS_POLLIN)))
115 return LWS_HPI_RET_PLEASE_CLOSE_ME;
116
117 return LWS_HPI_RET_HANDLED;
118 }
119 #endif
120
121 if ((pollfd->revents & pollfd->events & LWS_POLLIN) &&
122 !(wsi->favoured_pollin &&
123 (pollfd->revents & pollfd->events & LWS_POLLOUT))) {
124
125 lwsl_wsi_debug(wsi, "POLLIN: state 0x%x", lwsi_state(wsi));
126
127 switch (lwsi_state(wsi)) {
128
129 /* any tunnel has to have been established... */
130 case LRS_SSL_ACK_PENDING:
131 goto nope;
132 /* we are actually connected */
133 case LRS_WAITING_CONNECT:
134 goto nope;
135
136 case LRS_WAITING_SSL:
137 #if defined(LWS_WITH_CLIENT)
138 n = lws_raw_skt_connect(wsi);
139 if (n < 0)
140 goto fail;
141 #endif
142 break;
143
144 #if defined(LWS_WITH_SOCKS5)
145
146 /* SOCKS Greeting Reply */
147 case LRS_WAITING_SOCKS_GREETING_REPLY:
148 case LRS_WAITING_SOCKS_AUTH_REPLY:
149 case LRS_WAITING_SOCKS_CONNECT_REPLY:
150
151 switch (lws_socks5c_handle_state(wsi, pollfd, &cce)) {
152 case LW5CHS_RET_RET0:
153 goto nope;
154 case LW5CHS_RET_BAIL3:
155 lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
156 goto fail;
157 case LW5CHS_RET_STARTHS:
158 lwsi_set_state(wsi, LRS_ESTABLISHED);
159 lws_client_connect_4_established(wsi, NULL, 0);
160
161 /*
162 * Now we got the socks5 connection, we need to
163 * go down the tls path on it now if that's what
164 * we want
165 */
166 goto post_rx;
167
168 default:
169 break;
170 }
171 goto post_rx;
172 #endif
173 default:
174 ebuf.token = NULL;
175 ebuf.len = 0;
176
177 buffered = lws_buflist_aware_read(pt, wsi, &ebuf, 1, __func__);
178 switch (ebuf.len) {
179 case 0:
180 if (wsi->unix_skt)
181 break;
182 lwsl_wsi_info(wsi, "read 0 len");
183 wsi->seen_zero_length_recv = 1;
184 if (lws_change_pollfd(wsi, LWS_POLLIN, 0))
185 goto fail;
186
187 /*
188 * we need to go to fail here, since it's the only
189 * chance we get to understand that the socket has
190 * closed
191 */
192 // goto try_pollout;
193 goto fail;
194
195 case LWS_SSL_CAPABLE_ERROR:
196 goto fail;
197 case LWS_SSL_CAPABLE_MORE_SERVICE:
198 goto try_pollout;
199 }
200
201 #if defined(LWS_WITH_UDP)
202 if (lws_fi(&wsi->fic, "udp_rx_loss")) {
203 n = ebuf.len;
204 goto post_rx;
205 }
206 #endif
207
208 n = user_callback_handle_rxflow(wsi->a.protocol->callback,
209 wsi, LWS_CALLBACK_RAW_RX,
210 wsi->user_space, ebuf.token,
211 (unsigned int)ebuf.len);
212 #if defined(LWS_WITH_UDP) || defined(LWS_WITH_SOCKS5)
213 post_rx:
214 #endif
215 if (n < 0) {
216 lwsl_wsi_info(wsi, "LWS_CALLBACK_RAW_RX_fail");
217 goto fail;
218 }
219
220 if (lws_buflist_aware_finished_consuming(wsi, &ebuf, ebuf.len,
221 buffered, __func__))
222 return LWS_HPI_RET_PLEASE_CLOSE_ME;
223
224 goto try_pollout;
225 }
226 }
227 nope:
228 if (wsi->favoured_pollin &&
229 (pollfd->revents & pollfd->events & LWS_POLLOUT))
230 /* we balanced the last favouring of pollin */
231 wsi->favoured_pollin = 0;
232
233 try_pollout:
234
235 if (!(pollfd->revents & LWS_POLLOUT))
236 return LWS_HPI_RET_HANDLED;
237
238 #if defined(LWS_WITH_CLIENT)
239 if (lwsi_state(wsi) == LRS_WAITING_CONNECT) {
240 if (!lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL))
241 return LWS_HPI_RET_WSI_ALREADY_DIED;
242
243 if (lws_raw_skt_connect(wsi) < 0)
244 goto fail;
245 }
246 #endif
247
248 if (lwsi_state(wsi) == LRS_WAITING_SSL)
249 return LWS_HPI_RET_HANDLED;
250
251 /* one shot */
252 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
253 goto fail;
254
255 /* clear back-to-back write detection */
256 wsi->could_have_pending = 0;
257
258 n = user_callback_handle_rxflow(wsi->a.protocol->callback,
259 wsi, LWS_CALLBACK_RAW_WRITEABLE,
260 wsi->user_space, NULL, 0);
261 if (n < 0) {
262 lwsl_info("writeable_fail\n");
263 goto fail;
264 }
265
266 return LWS_HPI_RET_HANDLED;
267
268 fail:
269 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "raw svc fail");
270
271 return LWS_HPI_RET_WSI_ALREADY_DIED;
272 }
273
274 #if defined(LWS_WITH_SERVER)
275 static int
276 rops_adoption_bind_raw_skt(struct lws *wsi, int type, const char *vh_prot_name)
277 {
278
279 // lwsl_notice("%s: bind type %d\n", __func__, type);
280
281 /* no http but socket... must be raw skt */
282 if ((type & LWS_ADOPT_HTTP) || !(type & LWS_ADOPT_SOCKET) ||
283 ((type & _LWS_ADOPT_FINISH) && (!(type & LWS_ADOPT_FLAG_UDP))))
284 return 0; /* no match */
285
286 #if defined(LWS_WITH_UDP)
287 if ((type & LWS_ADOPT_FLAG_UDP) && !wsi->udp) {
288 /*
289 * these can be >128 bytes, so just alloc for UDP
290 */
291 wsi->udp = lws_malloc(sizeof(*wsi->udp), "udp struct");
292 if (!wsi->udp)
293 return 0;
294 memset(wsi->udp, 0, sizeof(*wsi->udp));
295 }
296 #endif
297
298 lws_role_transition(wsi, 0, (type & LWS_ADOPT_ALLOW_SSL) ? LRS_SSL_INIT :
299 LRS_ESTABLISHED, &role_ops_raw_skt);
300
301 if (vh_prot_name)
302 lws_bind_protocol(wsi, wsi->a.protocol, __func__);
303 else
304 /* this is the only time he will transition */
305 lws_bind_protocol(wsi,
306 &wsi->a.vhost->protocols[wsi->a.vhost->raw_protocol_index],
307 __func__);
308
309 return 1; /* bound */
310 }
311 #endif
312
313 #if defined(LWS_WITH_CLIENT)
314 static int
315 rops_client_bind_raw_skt(struct lws *wsi,
316 const struct lws_client_connect_info *i)
317 {
318 if (!i) {
319
320 /* finalize */
321
322 if (!wsi->user_space && wsi->stash->cis[CIS_METHOD])
323 if (lws_ensure_user_space(wsi))
324 return 1;
325
326 return 0;
327 }
328
329 /* we are a fallback if nothing else matched */
330
331 if (!i->local_protocol_name ||
332 strcmp(i->local_protocol_name, "raw-proxy"))
333 lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED,
334 &role_ops_raw_skt);
335
336 return 1; /* matched */
337 }
338 #endif
339
340 static const lws_rops_t rops_table_raw_skt[] = {
341 /* 1 */ { .handle_POLLIN = rops_handle_POLLIN_raw_skt },
342 #if defined(LWS_WITH_SERVER)
343 /* 2 */ { .adoption_bind = rops_adoption_bind_raw_skt },
344 #else
345 /* 2 */ { .adoption_bind = NULL },
346 #endif
347 #if defined(LWS_WITH_CLIENT)
348 /* 3 */ { .client_bind = rops_client_bind_raw_skt },
349 #endif
350 };
351
352 const struct lws_role_ops role_ops_raw_skt = {
353 /* role name */ "raw-skt",
354 /* alpn id */ NULL,
355
356 /* rops_table */ rops_table_raw_skt,
357 /* rops_idx */ {
358 /* LWS_ROPS_check_upgrades */
359 /* LWS_ROPS_pt_init_destroy */ 0x00,
360 /* LWS_ROPS_init_vhost */
361 /* LWS_ROPS_destroy_vhost */ 0x00,
362 /* LWS_ROPS_service_flag_pending */
363 /* LWS_ROPS_handle_POLLIN */ 0x01,
364 /* LWS_ROPS_handle_POLLOUT */
365 /* LWS_ROPS_perform_user_POLLOUT */ 0x00,
366 /* LWS_ROPS_callback_on_writable */
367 /* LWS_ROPS_tx_credit */ 0x00,
368 /* LWS_ROPS_write_role_protocol */
369 /* LWS_ROPS_encapsulation_parent */ 0x00,
370 /* LWS_ROPS_alpn_negotiated */
371 /* LWS_ROPS_close_via_role_protocol */ 0x00,
372 /* LWS_ROPS_close_role */
373 /* LWS_ROPS_close_kill_connection */ 0x00,
374 /* LWS_ROPS_destroy_role */
375 #if defined(LWS_WITH_SERVER)
376 /* LWS_ROPS_adoption_bind */ 0x02,
377 #else
378 /* LWS_ROPS_adoption_bind */ 0x00,
379 #endif
380 #if defined(LWS_WITH_CLIENT)
381 /* LWS_ROPS_client_bind */
382 /* LWS_ROPS_issue_keepalive */ 0x30,
383 #else
384 /* LWS_ROPS_client_bind */
385 /* LWS_ROPS_issue_keepalive */ 0x00,
386 #endif
387 },
388
389 /* adoption_cb clnt, srv */ { LWS_CALLBACK_RAW_CONNECTED,
390 LWS_CALLBACK_RAW_ADOPT },
391 /* rx_cb clnt, srv */ { LWS_CALLBACK_RAW_RX,
392 LWS_CALLBACK_RAW_RX },
393 /* writeable cb clnt, srv */ { LWS_CALLBACK_RAW_WRITEABLE,
394 LWS_CALLBACK_RAW_WRITEABLE},
395 /* close cb clnt, srv */ { LWS_CALLBACK_RAW_CLOSE,
396 LWS_CALLBACK_RAW_CLOSE },
397 /* protocol_bind cb c, srv */ { LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL,
398 LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL },
399 /* protocol_unbind cb c, srv */ { LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL,
400 LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL },
401 /* file_handle */ 0,
402 };
403