Coverage Report

Created: 2025-06-13 06:09

/src/uWebSockets/uSockets/src/context.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Authored by Alex Hultman, 2018-2019.
3
 * Intellectual property of third-party.
4
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
9
 *     http://www.apache.org/licenses/LICENSE-2.0
10
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
#ifndef LIBUS_USE_IO_URING
19
20
#include "libusockets.h"
21
#include "internal/internal.h"
22
#include <stdlib.h>
23
#include <string.h>
24
25
905k
int default_is_low_prio_handler(struct us_socket_t *s) {
26
905k
    return 0;
27
905k
}
28
29
/* Shared with SSL */
30
31
0
unsigned short us_socket_context_timestamp(int ssl, struct us_socket_context_t *context) {
32
0
    return context->timestamp;
33
0
}
34
35
5.93k
void us_listen_socket_close(int ssl, struct us_listen_socket_t *ls) {
36
    /* us_listen_socket_t extends us_socket_t so we close in similar ways */
37
5.93k
    if (!us_socket_is_closed(0, &ls->s)) {
38
5.93k
        us_internal_socket_context_unlink_listen_socket(ls->s.context, ls);
39
5.93k
        us_poll_stop((struct us_poll_t *) &ls->s, ls->s.context->loop);
40
5.93k
        bsd_close_socket(us_poll_fd((struct us_poll_t *) &ls->s));
41
42
        /* Link this socket to the close-list and let it be deleted after this iteration */
43
5.93k
        ls->s.next = ls->s.context->loop->data.closed_head;
44
5.93k
        ls->s.context->loop->data.closed_head = &ls->s;
45
46
        /* Any socket with prev = context is marked as closed */
47
5.93k
        ls->s.prev = (struct us_socket_t *) ls->s.context;
48
5.93k
    }
49
50
    /* We cannot immediately free a listen socket as we can be inside an accept loop */
51
5.93k
}
52
53
0
void us_socket_context_close(int ssl, struct us_socket_context_t *context) {
54
    /* Begin by closing all listen sockets */
55
0
    struct us_listen_socket_t *ls = context->head_listen_sockets;
56
0
    while (ls) {
57
0
        struct us_listen_socket_t *nextLS = (struct us_listen_socket_t *) ls->s.next;
58
0
        us_listen_socket_close(ssl, ls);
59
0
        ls = nextLS;
60
0
    }
61
62
    /* Then close all regular sockets */
63
0
    struct us_socket_t *s = context->head_sockets;
64
0
    while (s) {
65
0
        struct us_socket_t *nextS = s->next;
66
0
        us_socket_close(ssl, s, 0, 0);
67
0
        s = nextS;
68
0
    }
69
0
}
70
71
5.93k
void us_internal_socket_context_unlink_listen_socket(struct us_socket_context_t *context, struct us_listen_socket_t *ls) {
72
    /* We have to properly update the iterator used to sweep sockets for timeouts */
73
5.93k
    if (ls == (struct us_listen_socket_t *) context->iterator) {
74
0
        context->iterator = ls->s.next;
75
0
    }
76
77
5.93k
    if (ls->s.prev == ls->s.next) {
78
5.93k
        context->head_listen_sockets = 0;
79
5.93k
    } else {
80
0
        if (ls->s.prev) {
81
0
            ls->s.prev->next = ls->s.next;
82
0
        } else {
83
0
            context->head_listen_sockets = (struct us_listen_socket_t *) ls->s.next;
84
0
        }
85
0
        if (ls->s.next) {
86
0
            ls->s.next->prev = ls->s.prev;
87
0
        }
88
0
    }
89
5.93k
}
90
91
1.12M
void us_internal_socket_context_unlink_socket(struct us_socket_context_t *context, struct us_socket_t *s) {
92
    /* We have to properly update the iterator used to sweep sockets for timeouts */
93
1.12M
    if (s == context->iterator) {
94
11.0k
        context->iterator = s->next;
95
11.0k
    }
96
97
1.12M
    if (s->prev == s->next) {
98
262k
        context->head_sockets = 0;
99
863k
    } else {
100
863k
        if (s->prev) {
101
559k
            s->prev->next = s->next;
102
559k
        } else {
103
303k
            context->head_sockets = s->next;
104
303k
        }
105
863k
        if (s->next) {
106
835k
            s->next->prev = s->prev;
107
835k
        }
108
863k
    }
109
1.12M
}
110
111
/* We always add in the top, so we don't modify any s.next */
112
5.93k
void us_internal_socket_context_link_listen_socket(struct us_socket_context_t *context, struct us_listen_socket_t *ls) {
113
5.93k
    ls->s.context = context;
114
5.93k
    ls->s.next = (struct us_socket_t *) context->head_listen_sockets;
115
5.93k
    ls->s.prev = 0;
116
5.93k
    if (context->head_listen_sockets) {
117
0
        context->head_listen_sockets->s.prev = &ls->s;
118
0
    }
119
5.93k
    context->head_listen_sockets = ls;
120
5.93k
}
121
122
/* We always add in the top, so we don't modify any s.next */
123
1.12M
void us_internal_socket_context_link_socket(struct us_socket_context_t *context, struct us_socket_t *s) {
124
1.12M
    s->context = context;
125
1.12M
    s->next = context->head_sockets;
126
1.12M
    s->prev = 0;
127
1.12M
    if (context->head_sockets) {
128
863k
        context->head_sockets->prev = s;
129
863k
    }
130
1.12M
    context->head_sockets = s;
131
1.12M
}
132
133
6.60M
struct us_loop_t *us_socket_context_loop(int ssl, struct us_socket_context_t *context) {
134
6.60M
    return context->loop;
135
6.60M
}
136
137
/* Not shared with SSL */
138
139
/* Lookup userdata by server name pattern */
140
0
void *us_socket_context_find_server_name_userdata(int ssl, struct us_socket_context_t *context, const char *hostname_pattern) {
141
#ifndef LIBUS_NO_SSL
142
    if (ssl) {
143
        return us_internal_ssl_socket_context_find_server_name_userdata((struct us_internal_ssl_socket_context_t *) context, hostname_pattern);
144
    }
145
#endif
146
0
    return NULL;
147
0
}
148
149
/* Get userdata attached to this SNI-routed socket, or nullptr if default */
150
124k
void *us_socket_server_name_userdata(int ssl, struct us_socket_t *s) {
151
#ifndef LIBUS_NO_SSL
152
    if (ssl) {
153
        return us_internal_ssl_socket_get_sni_userdata((struct us_internal_ssl_socket_t *) s);
154
    }
155
#endif
156
124k
    return NULL;
157
124k
}
158
159
/* Add SNI context */
160
0
void us_socket_context_add_server_name(int ssl, struct us_socket_context_t *context, const char *hostname_pattern, struct us_socket_context_options_t options, void *user) {
161
#ifndef LIBUS_NO_SSL
162
    if (ssl) {
163
        us_internal_ssl_socket_context_add_server_name((struct us_internal_ssl_socket_context_t *) context, hostname_pattern, options, user);
164
    }
165
#endif
166
0
}
167
168
/* Remove SNI context */
169
0
void us_socket_context_remove_server_name(int ssl, struct us_socket_context_t *context, const char *hostname_pattern) {
170
#ifndef LIBUS_NO_SSL
171
    if (ssl) {
172
        us_internal_ssl_socket_context_remove_server_name((struct us_internal_ssl_socket_context_t *) context, hostname_pattern);
173
    }
174
#endif
175
0
}
176
177
/* I don't like this one - maybe rename it to on_missing_server_name? */
178
179
/* Called when SNI matching fails - not if a match could be made.
180
 * You may modify the context by adding/removing names in this callback.
181
 * If the correct name is added immediately in the callback, it will be used */
182
0
void us_socket_context_on_server_name(int ssl, struct us_socket_context_t *context, void (*cb)(struct us_socket_context_t *, const char *hostname)) {
183
#ifndef LIBUS_NO_SSL
184
    if (ssl) {
185
        us_internal_ssl_socket_context_on_server_name((struct us_internal_ssl_socket_context_t *) context, (void (*)(struct us_internal_ssl_socket_context_t *, const char *hostname)) cb);
186
    }
187
#endif
188
0
}
189
190
/* Todo: get native context from SNI pattern */
191
192
0
void *us_socket_context_get_native_handle(int ssl, struct us_socket_context_t *context) {
193
#ifndef LIBUS_NO_SSL
194
    if (ssl) {
195
        return us_internal_ssl_socket_context_get_native_handle((struct us_internal_ssl_socket_context_t *) context);
196
    }
197
#endif
198
199
    /* There is no native handle for a non-SSL socket context */
200
0
    return 0;
201
0
}
202
203
/* Options is currently only applicable for SSL - this will change with time (prefer_low_memory is one example) */
204
11.8k
struct us_socket_context_t *us_create_socket_context(int ssl, struct us_loop_t *loop, int context_ext_size, struct us_socket_context_options_t options) {
205
#ifndef LIBUS_NO_SSL
206
    if (ssl) {
207
        /* This function will call us, again, with SSL = false and a bigger ext_size */
208
        return (struct us_socket_context_t *) us_internal_create_ssl_socket_context(loop, context_ext_size, options);
209
    }
210
#endif
211
212
    /* This path is taken once either way - always BEFORE whatever SSL may do LATER.
213
     * context_ext_size will however be modified larger in case of SSL, to hold SSL extensions */
214
215
11.8k
    struct us_socket_context_t *context = malloc(sizeof(struct us_socket_context_t) + context_ext_size);
216
11.8k
    context->loop = loop;
217
11.8k
    context->head_sockets = 0;
218
11.8k
    context->head_listen_sockets = 0;
219
11.8k
    context->iterator = 0;
220
11.8k
    context->next = 0;
221
11.8k
    context->is_low_prio = default_is_low_prio_handler;
222
223
    /* Begin at 0 */
224
11.8k
    context->timestamp = 0;
225
11.8k
    context->long_timestamp = 0;
226
11.8k
    context->global_tick = 0;
227
228
    /* Some new events must be set to null for backwards compatibility */
229
11.8k
    context->on_pre_open = 0;
230
231
11.8k
    us_internal_loop_link(loop, context);
232
233
    /* If we are called from within SSL code, SSL code will make further changes to us */
234
11.8k
    return context;
235
11.8k
}
236
237
11.8k
void us_socket_context_free(int ssl, struct us_socket_context_t *context) {
238
#ifndef LIBUS_NO_SSL
239
    if (ssl) {
240
        /* This function will call us again with SSL=false */
241
        us_internal_ssl_socket_context_free((struct us_internal_ssl_socket_context_t *) context);
242
        return;
243
    }
244
#endif
245
246
    /* This path is taken once either way - always AFTER whatever SSL may do BEFORE.
247
     * This is the opposite order compared to when creating the context - SSL code is cleaning up before non-SSL */
248
249
11.8k
    us_internal_loop_unlink(context->loop, context);
250
11.8k
    free(context);
251
11.8k
}
252
253
5.94k
struct us_listen_socket_t *us_socket_context_listen(int ssl, struct us_socket_context_t *context, const char *host, int port, int options, int socket_ext_size) {
254
#ifndef LIBUS_NO_SSL
255
    if (ssl) {
256
        return us_internal_ssl_socket_context_listen((struct us_internal_ssl_socket_context_t *) context, host, port, options, socket_ext_size);
257
    }
258
#endif
259
260
5.94k
    LIBUS_SOCKET_DESCRIPTOR listen_socket_fd = bsd_create_listen_socket(host, port, options);
261
262
5.94k
    if (listen_socket_fd == LIBUS_SOCKET_ERROR) {
263
12
        return 0;
264
12
    }
265
266
5.93k
    struct us_poll_t *p = us_create_poll(context->loop, 0, sizeof(struct us_listen_socket_t) - sizeof(struct us_poll_t));
267
5.93k
    us_poll_init(p, listen_socket_fd, POLL_TYPE_SEMI_SOCKET);
268
5.93k
    us_poll_start(p, context->loop, LIBUS_SOCKET_READABLE);
269
270
5.93k
    struct us_listen_socket_t *ls = (struct us_listen_socket_t *) p;
271
272
5.93k
    ls->s.context = context;
273
5.93k
    ls->s.timeout = 255;
274
5.93k
    ls->s.long_timeout = 255;
275
5.93k
    ls->s.low_prio_state = 0;
276
5.93k
    ls->s.next = 0;
277
5.93k
    us_internal_socket_context_link_listen_socket(context, ls);
278
279
5.93k
    ls->socket_ext_size = socket_ext_size;
280
281
5.93k
    return ls;
282
5.94k
}
283
284
0
struct us_listen_socket_t *us_socket_context_listen_unix(int ssl, struct us_socket_context_t *context, const char *path, int options, int socket_ext_size) {
285
#ifndef LIBUS_NO_SSL
286
    if (ssl) {
287
        return us_internal_ssl_socket_context_listen_unix((struct us_internal_ssl_socket_context_t *) context, path, options, socket_ext_size);
288
    }
289
#endif
290
291
0
    LIBUS_SOCKET_DESCRIPTOR listen_socket_fd = bsd_create_listen_socket_unix(path, options);
292
293
0
    if (listen_socket_fd == LIBUS_SOCKET_ERROR) {
294
0
        return 0;
295
0
    }
296
297
0
    struct us_poll_t *p = us_create_poll(context->loop, 0, sizeof(struct us_listen_socket_t) - sizeof(struct us_poll_t));
298
0
    us_poll_init(p, listen_socket_fd, POLL_TYPE_SEMI_SOCKET);
299
0
    us_poll_start(p, context->loop, LIBUS_SOCKET_READABLE);
300
301
0
    struct us_listen_socket_t *ls = (struct us_listen_socket_t *) p;
302
303
0
    ls->s.context = context;
304
0
    ls->s.timeout = 255;
305
0
    ls->s.long_timeout = 255;
306
0
    ls->s.low_prio_state = 0;
307
0
    ls->s.next = 0;
308
0
    us_internal_socket_context_link_listen_socket(context, ls);
309
310
0
    ls->socket_ext_size = socket_ext_size;
311
312
0
    return ls;
313
0
}
314
315
0
struct us_socket_t *us_socket_context_connect(int ssl, struct us_socket_context_t *context, const char *host, int port, const char *source_host, int options, int socket_ext_size) {
316
#ifndef LIBUS_NO_SSL
317
    if (ssl) {
318
        return (struct us_socket_t *) us_internal_ssl_socket_context_connect((struct us_internal_ssl_socket_context_t *) context, host, port, source_host, options, socket_ext_size);
319
    }
320
#endif
321
322
0
    LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket(host, port, source_host, options);
323
0
    if (connect_socket_fd == LIBUS_SOCKET_ERROR) {
324
0
        return 0;
325
0
    }
326
327
    /* Connect sockets are semi-sockets just like listen sockets */
328
0
    struct us_poll_t *p = us_create_poll(context->loop, 0, sizeof(struct us_socket_t) - sizeof(struct us_poll_t) + socket_ext_size);
329
0
    us_poll_init(p, connect_socket_fd, POLL_TYPE_SEMI_SOCKET);
330
0
    us_poll_start(p, context->loop, LIBUS_SOCKET_WRITABLE);
331
332
0
    struct us_socket_t *connect_socket = (struct us_socket_t *) p;
333
334
    /* Link it into context so that timeout fires properly */
335
0
    connect_socket->context = context;
336
0
    connect_socket->timeout = 255;
337
0
    connect_socket->long_timeout = 255;
338
0
    connect_socket->low_prio_state = 0;
339
0
    us_internal_socket_context_link_socket(context, connect_socket);
340
341
0
    return connect_socket;
342
0
}
343
344
0
struct us_socket_t *us_socket_context_connect_unix(int ssl, struct us_socket_context_t *context, const char *server_path, int options, int socket_ext_size) {
345
#ifndef LIBUS_NO_SSL
346
    if (ssl) {
347
        return (struct us_socket_t *) us_internal_ssl_socket_context_connect_unix((struct us_internal_ssl_socket_context_t *) context, server_path, options, socket_ext_size);
348
    }
349
#endif
350
351
0
    LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket_unix(server_path, options);
352
0
    if (connect_socket_fd == LIBUS_SOCKET_ERROR) {
353
0
        return 0;
354
0
    }
355
356
    /* Connect sockets are semi-sockets just like listen sockets */
357
0
    struct us_poll_t *p = us_create_poll(context->loop, 0, sizeof(struct us_socket_t) - sizeof(struct us_poll_t) + socket_ext_size);
358
0
    us_poll_init(p, connect_socket_fd, POLL_TYPE_SEMI_SOCKET);
359
0
    us_poll_start(p, context->loop, LIBUS_SOCKET_WRITABLE);
360
361
0
    struct us_socket_t *connect_socket = (struct us_socket_t *) p;
362
363
    /* Link it into context so that timeout fires properly */
364
0
    connect_socket->context = context;
365
0
    connect_socket->timeout = 255;
366
0
    connect_socket->long_timeout = 255;
367
0
    connect_socket->low_prio_state = 0;
368
0
    us_internal_socket_context_link_socket(context, connect_socket);
369
370
0
    return connect_socket;
371
0
}
372
373
5.94k
struct us_socket_context_t *us_create_child_socket_context(int ssl, struct us_socket_context_t *context, int context_ext_size) {
374
#ifndef LIBUS_NO_SSL
375
    if (ssl) {
376
        return (struct us_socket_context_t *) us_internal_create_child_ssl_socket_context((struct us_internal_ssl_socket_context_t *) context, context_ext_size);
377
    }
378
#endif
379
380
    /* For TCP we simply create a new context as nothing is shared */
381
5.94k
    struct us_socket_context_options_t options = {0};
382
5.94k
    return us_create_socket_context(ssl, context->loop, context_ext_size, options);
383
5.94k
}
384
385
/* Note: This will set timeout to 0 */
386
106k
struct us_socket_t *us_socket_context_adopt_socket(int ssl, struct us_socket_context_t *context, struct us_socket_t *s, int ext_size) {
387
#ifndef LIBUS_NO_SSL
388
    if (ssl) {
389
        return (struct us_socket_t *) us_internal_ssl_socket_context_adopt_socket((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t *) s, ext_size);
390
    }
391
#endif
392
393
    /* Cannot adopt a closed socket */
394
106k
    if (us_socket_is_closed(ssl, s)) {
395
0
        return s;
396
0
    }
397
398
106k
    if (s->low_prio_state != 1) {
399
        /* This properly updates the iterator if in on_timeout */
400
106k
        us_internal_socket_context_unlink_socket(s->context, s);
401
106k
    }
402
403
106k
    struct us_socket_t *new_s = (struct us_socket_t *) us_poll_resize(&s->p, s->context->loop, sizeof(struct us_socket_t) + ext_size);
404
106k
    new_s->timeout = 255;
405
106k
    new_s->long_timeout = 255;
406
407
106k
    if (new_s->low_prio_state == 1) {
408
        /* update pointers in low-priority queue */
409
0
        if (!new_s->prev) new_s->context->loop->data.low_prio_head = new_s;
410
0
        else new_s->prev->next = new_s;
411
412
0
        if (new_s->next) new_s->next->prev = new_s;
413
106k
    } else {
414
106k
        us_internal_socket_context_link_socket(context, new_s);
415
106k
    }
416
417
106k
    return new_s;
418
106k
}
419
420
/* For backwards compatibility, this function will be set to nullptr by default. */
421
0
void us_socket_context_on_pre_open(int ssl, struct us_socket_context_t *context, LIBUS_SOCKET_DESCRIPTOR (*on_pre_open)(struct us_socket_context_t *context, LIBUS_SOCKET_DESCRIPTOR fd)) {
422
    /* For this event, there is no difference between SSL and non-SSL */
423
0
    context->on_pre_open = on_pre_open;
424
0
}
425
426
5.94k
void us_socket_context_on_open(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_open)(struct us_socket_t *s, int is_client, char *ip, int ip_length)) {
427
#ifndef LIBUS_NO_SSL
428
    if (ssl) {
429
        us_internal_ssl_socket_context_on_open((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *, int,  char *, int)) on_open);
430
        return;
431
    }
432
#endif
433
434
5.94k
    context->on_open = on_open;
435
5.94k
}
436
437
11.8k
void us_socket_context_on_close(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_close)(struct us_socket_t *s, int code, void *reason)) {
438
#ifndef LIBUS_NO_SSL
439
    if (ssl) {
440
        us_internal_ssl_socket_context_on_close((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *, int code, void *reason)) on_close);
441
        return;
442
    }
443
#endif
444
445
11.8k
    context->on_close = on_close;
446
11.8k
}
447
448
11.8k
void us_socket_context_on_data(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_data)(struct us_socket_t *s, char *data, int length)) {
449
#ifndef LIBUS_NO_SSL
450
    if (ssl) {
451
        us_internal_ssl_socket_context_on_data((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *, char *, int)) on_data);
452
        return;
453
    }
454
#endif
455
456
11.8k
    context->on_data = on_data;
457
11.8k
}
458
459
11.8k
void us_socket_context_on_writable(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_writable)(struct us_socket_t *s)) {
460
#ifndef LIBUS_NO_SSL
461
    if (ssl) {
462
        us_internal_ssl_socket_context_on_writable((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *)) on_writable);
463
        return;
464
    }
465
#endif
466
467
11.8k
    context->on_writable = on_writable;
468
11.8k
}
469
470
5.94k
void us_socket_context_on_long_timeout(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_long_timeout)(struct us_socket_t *)) {
471
#ifndef LIBUS_NO_SSL
472
    if (ssl) {
473
        us_internal_ssl_socket_context_on_long_timeout((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *)) on_long_timeout);
474
        return;
475
    }
476
#endif
477
478
5.94k
    context->on_socket_long_timeout = on_long_timeout;
479
5.94k
}
480
481
11.8k
void us_socket_context_on_timeout(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_timeout)(struct us_socket_t *)) {
482
#ifndef LIBUS_NO_SSL
483
    if (ssl) {
484
        us_internal_ssl_socket_context_on_timeout((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *)) on_timeout);
485
        return;
486
    }
487
#endif
488
489
11.8k
    context->on_socket_timeout = on_timeout;
490
11.8k
}
491
492
11.8k
void us_socket_context_on_end(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_end)(struct us_socket_t *)) {
493
#ifndef LIBUS_NO_SSL
494
    if (ssl) {
495
        us_internal_ssl_socket_context_on_end((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *)) on_end);
496
        return;
497
    }
498
#endif
499
500
11.8k
    context->on_end = on_end;
501
11.8k
}
502
503
0
void us_socket_context_on_connect_error(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_connect_error)(struct us_socket_t *s, int code)) {
504
#ifndef LIBUS_NO_SSL
505
    if (ssl) {
506
        us_internal_ssl_socket_context_on_connect_error((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *, int)) on_connect_error);
507
        return;
508
    }
509
#endif
510
    
511
0
    context->on_connect_error = on_connect_error;
512
0
}
513
514
16.1M
void *us_socket_context_ext(int ssl, struct us_socket_context_t *context) {
515
#ifndef LIBUS_NO_SSL
516
    if (ssl) {
517
        return us_internal_ssl_socket_context_ext((struct us_internal_ssl_socket_context_t *) context);
518
    }
519
#endif
520
521
16.1M
    return context + 1;
522
16.1M
}
523
524
#endif