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 static int
rops_handle_POLLIN_raw_skt(struct lws_context_per_thread * pt,struct lws * wsi,struct lws_pollfd * pollfd)28 rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi,
29 struct lws_pollfd *pollfd)
30 {
31 #if defined(LWS_WITH_SOCKS5)
32 const char *cce = NULL;
33 #endif
34 struct lws_tokens ebuf;
35 int n = 0, buffered = 0;
36
37 /* pending truncated sends have uber priority */
38
39 if (lws_has_buffered_out(wsi)) {
40 if (!(pollfd->revents & LWS_POLLOUT))
41 return LWS_HPI_RET_HANDLED;
42
43 /* drain the output buflist */
44 if (lws_issue_raw(wsi, NULL, 0) < 0)
45 goto fail;
46 /*
47 * we can't afford to allow input processing to send
48 * something new, so spin around he event loop until
49 * he doesn't have any partials
50 */
51 return LWS_HPI_RET_HANDLED;
52 }
53
54
55 #if defined(LWS_WITH_SERVER)
56 if (!lwsi_role_client(wsi) && lwsi_state(wsi) != LRS_ESTABLISHED) {
57
58 lwsl_debug("%s: %p: wsistate 0x%x\n", __func__, wsi,
59 (int)wsi->wsistate);
60
61 if (lwsi_state(wsi) != LRS_SSL_INIT)
62 if (lws_server_socket_service_ssl(wsi,
63 LWS_SOCK_INVALID))
64 return LWS_HPI_RET_PLEASE_CLOSE_ME;
65
66 return LWS_HPI_RET_HANDLED;
67 }
68 #endif
69
70 if ((pollfd->revents & pollfd->events & LWS_POLLIN) &&
71 !(wsi->favoured_pollin &&
72 (pollfd->revents & pollfd->events & LWS_POLLOUT))) {
73
74 lwsl_debug("%s: POLLIN: wsi %p, state 0x%x\n", __func__,
75 wsi, lwsi_state(wsi));
76
77 switch (lwsi_state(wsi)) {
78
79 /* any tunnel has to have been established... */
80 case LRS_SSL_ACK_PENDING:
81 goto nope;
82 /* we are actually connected */
83 case LRS_WAITING_CONNECT:
84 goto nope;
85
86 #if defined(LWS_WITH_SOCKS5)
87
88 /* SOCKS Greeting Reply */
89 case LRS_WAITING_SOCKS_GREETING_REPLY:
90 case LRS_WAITING_SOCKS_AUTH_REPLY:
91 case LRS_WAITING_SOCKS_CONNECT_REPLY:
92
93 switch (lws_socks5c_handle_state(wsi, pollfd, &cce)) {
94 case LW5CHS_RET_RET0:
95 goto nope;
96 case LW5CHS_RET_BAIL3:
97 lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
98 goto fail;
99 case LW5CHS_RET_STARTHS:
100 lwsi_set_state(wsi, LRS_ESTABLISHED);
101 lws_client_connect_4_established(wsi, NULL, 0);
102
103 /*
104 * Now we got the socks5 connection, we need to
105 * go down the tls path on it now if that's what
106 * we want
107 */
108 goto post_rx;
109
110 default:
111 break;
112 }
113 goto post_rx;
114 #endif
115 default:
116 ebuf.token = NULL;
117 ebuf.len = 0;
118
119 buffered = lws_buflist_aware_read(pt, wsi, &ebuf, 1, __func__);
120 switch (ebuf.len) {
121 case 0:
122 lwsl_info("%s: read 0 len\n", __func__);
123 wsi->seen_zero_length_recv = 1;
124 if (lws_change_pollfd(wsi, LWS_POLLIN, 0))
125 goto fail;
126
127 /*
128 * we need to go to fail here, since it's the only
129 * chance we get to understand that the socket has
130 * closed
131 */
132 // goto try_pollout;
133 goto fail;
134
135 case LWS_SSL_CAPABLE_ERROR:
136 goto fail;
137 case LWS_SSL_CAPABLE_MORE_SERVICE:
138 goto try_pollout;
139 }
140
141 #if defined(LWS_WITH_UDP)
142 if (wsi->context->udp_loss_sim_rx_pc) {
143 uint16_t u16;
144 /*
145 * We should randomly drop some of these
146 */
147
148 if (lws_get_random(wsi->context, &u16, 2) == 2 &&
149 ((u16 * 100) / 0xffff) <=
150 wsi->context->udp_loss_sim_rx_pc) {
151 lwsl_warn("%s: dropping udp rx\n", __func__);
152 /* pretend it was handled */
153 n = ebuf.len;
154 goto post_rx;
155 }
156 }
157 #endif
158
159 n = user_callback_handle_rxflow(wsi->protocol->callback,
160 wsi, LWS_CALLBACK_RAW_RX,
161 wsi->user_space, ebuf.token,
162 ebuf.len);
163 #if defined(LWS_WITH_UDP) || defined(LWS_WITH_SOCKS5)
164 post_rx:
165 #endif
166 if (n < 0) {
167 lwsl_info("LWS_CALLBACK_RAW_RX_fail\n");
168 goto fail;
169 }
170
171 if (lws_buflist_aware_finished_consuming(wsi, &ebuf, ebuf.len,
172 buffered, __func__))
173 return LWS_HPI_RET_PLEASE_CLOSE_ME;
174
175 goto try_pollout;
176 }
177 }
178 nope:
179 if (wsi->favoured_pollin &&
180 (pollfd->revents & pollfd->events & LWS_POLLOUT))
181 /* we balanced the last favouring of pollin */
182 wsi->favoured_pollin = 0;
183
184 try_pollout:
185
186 if (!(pollfd->revents & LWS_POLLOUT))
187 return LWS_HPI_RET_HANDLED;
188
189 #if defined(LWS_WITH_CLIENT)
190 if (lwsi_state(wsi) == LRS_WAITING_CONNECT &&
191 !lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL))
192 return LWS_HPI_RET_WSI_ALREADY_DIED;
193 #endif
194
195 /* one shot */
196 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
197 lwsl_notice("%s a\n", __func__);
198 goto fail;
199 }
200
201 /* clear back-to-back write detection */
202 wsi->could_have_pending = 0;
203
204 lws_stats_bump(pt, LWSSTATS_C_WRITEABLE_CB, 1);
205 #if defined(LWS_WITH_STATS)
206 if (wsi->active_writable_req_us) {
207 uint64_t ul = lws_now_usecs() -
208 wsi->active_writable_req_us;
209
210 lws_stats_bump(pt, LWSSTATS_US_WRITABLE_DELAY_AVG, ul);
211 lws_stats_max(pt,
212 LWSSTATS_US_WORST_WRITABLE_DELAY, ul);
213 wsi->active_writable_req_us = 0;
214 }
215 #endif
216 n = user_callback_handle_rxflow(wsi->protocol->callback,
217 wsi, LWS_CALLBACK_RAW_WRITEABLE,
218 wsi->user_space, NULL, 0);
219 if (n < 0) {
220 lwsl_info("writeable_fail\n");
221 goto fail;
222 }
223
224 return LWS_HPI_RET_HANDLED;
225
226 fail:
227 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "raw svc fail");
228
229 return LWS_HPI_RET_WSI_ALREADY_DIED;
230 }
231
232 #if defined(LWS_WITH_SERVER)
233 static int
rops_adoption_bind_raw_skt(struct lws * wsi,int type,const char * vh_prot_name)234 rops_adoption_bind_raw_skt(struct lws *wsi, int type, const char *vh_prot_name)
235 {
236 /* no http but socket... must be raw skt */
237 if ((type & LWS_ADOPT_HTTP) || !(type & LWS_ADOPT_SOCKET) ||
238 (type & _LWS_ADOPT_FINISH))
239 return 0; /* no match */
240
241 #if defined(LWS_WITH_UDP)
242 if (type & LWS_ADOPT_FLAG_UDP)
243 /*
244 * these can be >128 bytes, so just alloc for UDP
245 */
246 wsi->udp = lws_malloc(sizeof(*wsi->udp), "udp struct");
247 #endif
248
249 lws_role_transition(wsi, 0, (type & LWS_ADOPT_ALLOW_SSL) ? LRS_SSL_INIT :
250 LRS_ESTABLISHED, &role_ops_raw_skt);
251
252 if (vh_prot_name)
253 lws_bind_protocol(wsi, wsi->protocol, __func__);
254 else
255 /* this is the only time he will transition */
256 lws_bind_protocol(wsi,
257 &wsi->vhost->protocols[wsi->vhost->raw_protocol_index],
258 __func__);
259
260 return 1; /* bound */
261 }
262 #endif
263
264 #if defined(LWS_WITH_CLIENT)
265 static int
rops_client_bind_raw_skt(struct lws * wsi,const struct lws_client_connect_info * i)266 rops_client_bind_raw_skt(struct lws *wsi,
267 const struct lws_client_connect_info *i)
268 {
269 if (!i) {
270
271 /* finalize */
272
273 if (!wsi->user_space && wsi->stash->cis[CIS_METHOD])
274 if (lws_ensure_user_space(wsi))
275 return 1;
276
277 return 0;
278 }
279
280 /* we are a fallback if nothing else matched */
281
282 if (!i->local_protocol_name ||
283 strcmp(i->local_protocol_name, "raw-proxy"))
284 lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED,
285 &role_ops_raw_skt);
286
287 return 1; /* matched */
288 }
289 #endif
290
291 const struct lws_role_ops role_ops_raw_skt = {
292 /* role name */ "raw-skt",
293 /* alpn id */ NULL,
294 /* check_upgrades */ NULL,
295 /* pt_init_destroy */ NULL,
296 /* init_vhost */ NULL,
297 /* destroy_vhost */ NULL,
298 /* service_flag_pending */ NULL,
299 /* handle_POLLIN */ rops_handle_POLLIN_raw_skt,
300 /* handle_POLLOUT */ NULL,
301 /* perform_user_POLLOUT */ NULL,
302 /* callback_on_writable */ NULL,
303 /* tx_credit */ NULL,
304 /* write_role_protocol */ NULL,
305 /* encapsulation_parent */ NULL,
306 /* alpn_negotiated */ NULL,
307 /* close_via_role_protocol */ NULL,
308 /* close_role */ NULL,
309 /* close_kill_connection */ NULL,
310 /* destroy_role */ NULL,
311 #if defined(LWS_WITH_SERVER)
312 /* adoption_bind */ rops_adoption_bind_raw_skt,
313 #else
314 NULL,
315 #endif
316 #if defined(LWS_WITH_CLIENT)
317 /* client_bind */ rops_client_bind_raw_skt,
318 #else
319 NULL,
320 #endif
321 /* issue_keepalive */ NULL,
322 /* adoption_cb clnt, srv */ { LWS_CALLBACK_RAW_CONNECTED,
323 LWS_CALLBACK_RAW_ADOPT },
324 /* rx_cb clnt, srv */ { LWS_CALLBACK_RAW_RX,
325 LWS_CALLBACK_RAW_RX },
326 /* writeable cb clnt, srv */ { LWS_CALLBACK_RAW_WRITEABLE,
327 LWS_CALLBACK_RAW_WRITEABLE},
328 /* close cb clnt, srv */ { LWS_CALLBACK_RAW_CLOSE,
329 LWS_CALLBACK_RAW_CLOSE },
330 /* protocol_bind cb c, srv */ { LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL,
331 LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL },
332 /* protocol_unbind cb c, srv */ { LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL,
333 LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL },
334 /* file_handle */ 0,
335 };
336