Coverage Report

Created: 2023-03-26 07:20

/src/libwebsockets/lib/roles/raw-skt/ops-raw-skt.c
Line
Count
Source (jump to first uncovered line)
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
29
lws_raw_skt_connect(struct lws *wsi)
30
0
{
31
0
  int n;
32
0
#if defined(LWS_WITH_TLS)
33
0
  const char *cce = NULL;
34
0
  char ccebuf[128];
35
36
0
#if !defined(LWS_WITH_SYS_ASYNC_DNS)
37
0
  switch (lws_client_create_tls(wsi, &cce, 1)) {
38
#else
39
  switch (lws_client_create_tls(wsi, &cce, 0)) {
40
#endif
41
0
  case CCTLS_RETURN_ERROR:
42
0
    lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
43
0
    return -1;
44
0
  case CCTLS_RETURN_RETRY:
45
0
    return 0;
46
0
  case CCTLS_RETURN_DONE:
47
0
    break;
48
0
  }
49
50
0
  if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
51
0
    n = lws_ssl_client_connect2(wsi, ccebuf, sizeof(ccebuf));
52
0
    if (n < 0) {
53
0
      lws_inform_client_conn_fail(wsi, (void *)ccebuf,
54
0
                strlen(ccebuf));
55
56
0
      return -1;
57
0
    }
58
0
    if (n != 1)
59
0
      return 0; /* wait */
60
0
  }
61
0
#endif
62
63
0
  n = user_callback_handle_rxflow(wsi->a.protocol->callback,
64
0
          wsi, wsi->role_ops->adoption_cb[lwsi_role_server(wsi)],
65
0
          wsi->user_space, NULL, 0);
66
0
  if (n) {
67
0
    lws_inform_client_conn_fail(wsi, (void *)"user", 4);
68
0
    return 1;
69
0
  }
70
71
0
  lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
72
0
  lwsi_set_state(wsi, LRS_ESTABLISHED);
73
74
0
  return 1; /* success */
75
0
}
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
0
{
82
#if defined(LWS_WITH_SOCKS5)
83
  const char *cce = NULL;
84
#endif
85
0
  struct lws_tokens ebuf;
86
0
  int n = 0, buffered = 0;
87
88
  /* pending truncated sends have uber priority */
89
90
0
  if (lws_has_buffered_out(wsi)) {
91
0
    if (!(pollfd->revents & LWS_POLLOUT))
92
0
      return LWS_HPI_RET_HANDLED;
93
94
    /* drain the output buflist */
95
0
    if (lws_issue_raw(wsi, NULL, 0) < 0)
96
0
      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
0
    return LWS_HPI_RET_HANDLED;
103
0
  }
104
105
106
0
#if defined(LWS_WITH_SERVER)
107
0
  if (!lwsi_role_client(wsi) &&  lwsi_state(wsi) != LRS_ESTABLISHED) {
108
109
0
    lwsl_wsi_debug(wsi, "wsistate 0x%x\n", (int)wsi->wsistate);
110
111
0
    if (lwsi_state(wsi) != LRS_SSL_INIT)
112
0
      if (lws_server_socket_service_ssl(wsi,
113
0
                LWS_SOCK_INVALID,
114
0
        !!(pollfd->revents & pollfd->events & LWS_POLLIN)))
115
0
        return LWS_HPI_RET_PLEASE_CLOSE_ME;
116
117
0
    return LWS_HPI_RET_HANDLED;
118
0
  }
119
0
#endif
120
121
0
  if ((pollfd->revents & pollfd->events & LWS_POLLIN) &&
122
0
      !(wsi->favoured_pollin &&
123
0
        (pollfd->revents & pollfd->events & LWS_POLLOUT))) {
124
125
0
    lwsl_wsi_debug(wsi, "POLLIN: state 0x%x", lwsi_state(wsi));
126
127
0
    switch (lwsi_state(wsi)) {
128
129
        /* any tunnel has to have been established... */
130
0
    case LRS_SSL_ACK_PENDING:
131
0
      goto nope;
132
        /* we are actually connected */
133
0
    case LRS_WAITING_CONNECT:
134
0
      goto nope;
135
136
0
    case LRS_WAITING_SSL:
137
0
#if defined(LWS_WITH_CLIENT)
138
0
      n = lws_raw_skt_connect(wsi);
139
0
      if (n < 0)
140
0
        goto fail;
141
0
#endif
142
0
      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
0
    default:
174
0
      ebuf.token = NULL;
175
0
      ebuf.len = 0;
176
177
0
      buffered = lws_buflist_aware_read(pt, wsi, &ebuf, 1, __func__);
178
0
      switch (ebuf.len) {
179
0
      case 0:
180
0
        if (wsi->unix_skt)
181
0
          break;
182
0
        lwsl_wsi_info(wsi, "read 0 len");
183
0
        wsi->seen_zero_length_recv = 1;
184
0
        if (lws_change_pollfd(wsi, LWS_POLLIN, 0))
185
0
          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
0
        goto fail;
194
195
0
      case LWS_SSL_CAPABLE_ERROR:
196
0
        goto fail;
197
0
      case LWS_SSL_CAPABLE_MORE_SERVICE:
198
0
        goto try_pollout;
199
0
      }
200
201
0
#if defined(LWS_WITH_UDP)
202
0
      if (lws_fi(&wsi->fic, "udp_rx_loss")) {
203
0
        n = ebuf.len;
204
0
        goto post_rx;
205
0
      }
206
0
#endif
207
208
0
      n = user_callback_handle_rxflow(wsi->a.protocol->callback,
209
0
              wsi, LWS_CALLBACK_RAW_RX,
210
0
              wsi->user_space, ebuf.token,
211
0
              (unsigned int)ebuf.len);
212
0
#if defined(LWS_WITH_UDP) || defined(LWS_WITH_SOCKS5)
213
0
post_rx:
214
0
#endif
215
0
      if (n < 0) {
216
0
        lwsl_wsi_info(wsi, "LWS_CALLBACK_RAW_RX_fail");
217
0
        goto fail;
218
0
      }
219
220
0
      if (lws_buflist_aware_finished_consuming(wsi, &ebuf, ebuf.len,
221
0
                 buffered, __func__))
222
0
        return LWS_HPI_RET_PLEASE_CLOSE_ME;
223
224
0
      goto try_pollout;
225
0
    }
226
0
  }
227
0
nope:
228
0
  if (wsi->favoured_pollin &&
229
0
      (pollfd->revents & pollfd->events & LWS_POLLOUT))
230
    /* we balanced the last favouring of pollin */
231
0
    wsi->favoured_pollin = 0;
232
233
0
try_pollout:
234
235
0
  if (!(pollfd->revents & LWS_POLLOUT))
236
0
    return LWS_HPI_RET_HANDLED;
237
238
0
#if defined(LWS_WITH_CLIENT)
239
0
  if (lwsi_state(wsi) == LRS_WAITING_CONNECT) {
240
0
      if (!lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL))
241
0
    return LWS_HPI_RET_WSI_ALREADY_DIED;
242
243
0
      if (lws_raw_skt_connect(wsi) < 0)
244
0
        goto fail;
245
0
  }
246
0
#endif
247
248
0
  if (lwsi_state(wsi) == LRS_WAITING_SSL)
249
0
    return LWS_HPI_RET_HANDLED;
250
251
  /* one shot */
252
0
  if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
253
0
    goto fail;
254
255
  /* clear back-to-back write detection */
256
0
  wsi->could_have_pending = 0;
257
258
0
  n = user_callback_handle_rxflow(wsi->a.protocol->callback,
259
0
      wsi, LWS_CALLBACK_RAW_WRITEABLE,
260
0
      wsi->user_space, NULL, 0);
261
0
  if (n < 0) {
262
0
    lwsl_info("writeable_fail\n");
263
0
    goto fail;
264
0
  }
265
266
0
  return LWS_HPI_RET_HANDLED;
267
268
0
fail:
269
0
  lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "raw svc fail");
270
271
0
  return LWS_HPI_RET_WSI_ALREADY_DIED;
272
0
}
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
0
{
278
279
  // lwsl_notice("%s: bind type %d\n", __func__, type);
280
281
  /* no http but socket... must be raw skt */
282
0
  if ((type & LWS_ADOPT_HTTP) || !(type & LWS_ADOPT_SOCKET) ||
283
0
      ((type & _LWS_ADOPT_FINISH) && (!(type & LWS_ADOPT_FLAG_UDP))))
284
0
    return 0; /* no match */
285
286
0
#if defined(LWS_WITH_UDP)
287
0
  if ((type & LWS_ADOPT_FLAG_UDP) && !wsi->udp) {
288
    /*
289
     * these can be >128 bytes, so just alloc for UDP
290
     */
291
0
    wsi->udp = lws_malloc(sizeof(*wsi->udp), "udp struct");
292
0
    if (!wsi->udp)
293
0
      return 0;
294
0
    memset(wsi->udp, 0, sizeof(*wsi->udp));
295
0
  }
296
0
#endif
297
298
0
  lws_role_transition(wsi, 0, (type & LWS_ADOPT_ALLOW_SSL) ? LRS_SSL_INIT :
299
0
        LRS_ESTABLISHED, &role_ops_raw_skt);
300
301
0
  if (vh_prot_name)
302
0
    lws_bind_protocol(wsi, wsi->a.protocol, __func__);
303
0
  else
304
    /* this is the only time he will transition */
305
0
    lws_bind_protocol(wsi,
306
0
      &wsi->a.vhost->protocols[wsi->a.vhost->raw_protocol_index],
307
0
      __func__);
308
309
0
  return 1; /* bound */
310
0
}
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
0
{
318
0
  if (!i) {
319
320
    /* finalize */
321
322
0
    if (!wsi->user_space && wsi->stash->cis[CIS_METHOD])
323
0
      if (lws_ensure_user_space(wsi))
324
0
        return 1;
325
326
0
    return 0;
327
0
  }
328
329
  /* we are a fallback if nothing else matched */
330
331
0
  if (!i->local_protocol_name ||
332
0
      strcmp(i->local_protocol_name, "raw-proxy"))
333
0
    lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED,
334
0
          &role_ops_raw_skt);
335
336
0
  return 1; /* matched */
337
0
}
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
};