Coverage Report

Created: 2023-06-06 06:17

/src/uWebSockets/uSockets/src/socket.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Authored by Alex Hultman, 2018-2021.
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
#include <stdint.h>
25
26
/* Shared with SSL */
27
28
0
int us_socket_local_port(int ssl, struct us_socket_t *s) {
29
0
    struct bsd_addr_t addr;
30
0
    if (bsd_local_addr(us_poll_fd(&s->p), &addr)) {
31
0
        return -1;
32
0
    } else {
33
0
        return bsd_addr_get_port(&addr);
34
0
    }
35
0
}
36
37
0
void us_socket_shutdown_read(int ssl, struct us_socket_t *s) {
38
    /* This syscall is idempotent so no extra check is needed */
39
0
    bsd_shutdown_socket_read(us_poll_fd((struct us_poll_t *) s));
40
0
}
41
42
0
void us_socket_remote_address(int ssl, struct us_socket_t *s, char *buf, int *length) {
43
0
    struct bsd_addr_t addr;
44
0
    if (bsd_remote_addr(us_poll_fd(&s->p), &addr) || *length < bsd_addr_get_ip_length(&addr)) {
45
0
        *length = 0;
46
0
    } else {
47
0
        *length = bsd_addr_get_ip_length(&addr);
48
0
        memcpy(buf, bsd_addr_get_ip(&addr), *length);
49
0
    }
50
0
}
51
52
14.2M
struct us_socket_context_t *us_socket_context(int ssl, struct us_socket_t *s) {
53
14.2M
    return s->context;
54
14.2M
}
55
56
1.29M
void us_socket_timeout(int ssl, struct us_socket_t *s, unsigned int seconds) {
57
1.29M
    if (seconds) {
58
1.21M
        s->timeout = ((unsigned int)s->context->timestamp + ((seconds + 3) >> 2)) % 240;
59
1.21M
    } else {
60
79.4k
        s->timeout = 255;
61
79.4k
    }
62
1.29M
}
63
64
64.9k
void us_socket_long_timeout(int ssl, struct us_socket_t *s, unsigned int minutes) {
65
64.9k
    if (minutes) {
66
0
        s->long_timeout = ((unsigned int)s->context->long_timestamp + minutes) % 240;
67
64.9k
    } else {
68
64.9k
        s->long_timeout = 255;
69
64.9k
    }
70
64.9k
}
71
72
0
void us_socket_flush(int ssl, struct us_socket_t *s) {
73
0
    if (!us_socket_is_shut_down(0, s)) {
74
0
        bsd_socket_flush(us_poll_fd((struct us_poll_t *) s));
75
0
    }
76
0
}
77
78
5.14M
int us_socket_is_closed(int ssl, struct us_socket_t *s) {
79
5.14M
    return s->prev == (struct us_socket_t *) s->context;
80
5.14M
}
81
82
0
int us_socket_is_established(int ssl, struct us_socket_t *s) {
83
    /* Everything that is not POLL_TYPE_SEMI_SOCKET is established */
84
0
    return us_internal_poll_type((struct us_poll_t *) s) != POLL_TYPE_SEMI_SOCKET;
85
0
}
86
87
/* Exactly the same as us_socket_close but does not emit on_close event */
88
0
struct us_socket_t *us_socket_close_connecting(int ssl, struct us_socket_t *s) {
89
0
    if (!us_socket_is_closed(0, s)) {
90
0
        us_internal_socket_context_unlink_socket(s->context, s);
91
0
        us_poll_stop((struct us_poll_t *) s, s->context->loop);
92
0
        bsd_close_socket(us_poll_fd((struct us_poll_t *) s));
93
94
        /* Link this socket to the close-list and let it be deleted after this iteration */
95
0
        s->next = s->context->loop->data.closed_head;
96
0
        s->context->loop->data.closed_head = s;
97
98
        /* Any socket with prev = context is marked as closed */
99
0
        s->prev = (struct us_socket_t *) s->context;
100
101
        //return s->context->on_close(s, code, reason);
102
0
    }
103
0
    return s;
104
0
}
105
106
/* Same as above but emits on_close */
107
998k
struct us_socket_t *us_socket_close(int ssl, struct us_socket_t *s, int code, void *reason) {
108
998k
    if (!us_socket_is_closed(0, s)) {
109
998k
        if (s->low_prio_state == 1) {
110
            /* Unlink this socket from the low-priority queue */
111
0
            if (!s->prev) s->context->loop->data.low_prio_head = s->next;
112
0
            else s->prev->next = s->next;
113
114
0
            if (s->next) s->next->prev = s->prev;
115
116
0
            s->prev = 0;
117
0
            s->next = 0;
118
0
            s->low_prio_state = 0;
119
998k
        } else {
120
998k
            us_internal_socket_context_unlink_socket(s->context, s);
121
998k
        }
122
998k
        us_poll_stop((struct us_poll_t *) s, s->context->loop);
123
998k
        bsd_close_socket(us_poll_fd((struct us_poll_t *) s));
124
125
        /* Link this socket to the close-list and let it be deleted after this iteration */
126
998k
        s->next = s->context->loop->data.closed_head;
127
998k
        s->context->loop->data.closed_head = s;
128
129
        /* Any socket with prev = context is marked as closed */
130
998k
        s->prev = (struct us_socket_t *) s->context;
131
132
998k
        return s->context->on_close(s, code, reason);
133
998k
    }
134
0
    return s;
135
998k
}
136
137
/* Not shared with SSL */
138
139
0
void *us_socket_get_native_handle(int ssl, struct us_socket_t *s) {
140
#ifndef LIBUS_NO_SSL
141
    if (ssl) {
142
        return us_internal_ssl_socket_get_native_handle((struct us_internal_ssl_socket_t *) s);
143
    }
144
#endif
145
146
0
    return (void *) (uintptr_t) us_poll_fd((struct us_poll_t *) s);
147
0
}
148
149
/* This is not available for SSL sockets as it makes no sense. */
150
0
int us_socket_write2(int ssl, struct us_socket_t *s, const char *header, int header_length, const char *payload, int payload_length) {
151
152
0
    if (us_socket_is_closed(ssl, s) || us_socket_is_shut_down(ssl, s)) {
153
0
        return 0;
154
0
    }
155
156
0
    int written = bsd_write2(us_poll_fd(&s->p), header, header_length, payload, payload_length);
157
0
    if (written != header_length + payload_length) {
158
0
        us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
159
0
    }
160
161
0
    return written < 0 ? 0 : written;
162
0
}
163
164
473k
int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length, int msg_more) {
165
#ifndef LIBUS_NO_SSL
166
    if (ssl) {
167
        return us_internal_ssl_socket_write((struct us_internal_ssl_socket_t *) s, data, length, msg_more);
168
    }
169
#endif
170
171
473k
    if (us_socket_is_closed(ssl, s) || us_socket_is_shut_down(ssl, s)) {
172
0
        return 0;
173
0
    }
174
175
473k
    int written = bsd_send(us_poll_fd(&s->p), data, length, msg_more);
176
473k
    if (written != length) {
177
465k
        s->context->loop->data.last_write_failed = 1;
178
465k
        us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
179
465k
    }
180
181
473k
    return written < 0 ? 0 : written;
182
473k
}
183
184
12.4M
void *us_socket_ext(int ssl, struct us_socket_t *s) {
185
#ifndef LIBUS_NO_SSL
186
    if (ssl) {
187
        return us_internal_ssl_socket_ext((struct us_internal_ssl_socket_t *) s);
188
    }
189
#endif
190
191
12.4M
    return s + 1;
192
12.4M
}
193
194
1.27M
int us_socket_is_shut_down(int ssl, struct us_socket_t *s) {
195
#ifndef LIBUS_NO_SSL
196
    if (ssl) {
197
        return us_internal_ssl_socket_is_shut_down((struct us_internal_ssl_socket_t *) s);
198
    }
199
#endif
200
201
1.27M
    return us_internal_poll_type(&s->p) == POLL_TYPE_SOCKET_SHUT_DOWN;
202
1.27M
}
203
204
304k
void us_socket_shutdown(int ssl, struct us_socket_t *s) {
205
#ifndef LIBUS_NO_SSL
206
    if (ssl) {
207
        us_internal_ssl_socket_shutdown((struct us_internal_ssl_socket_t *) s);
208
        return;
209
    }
210
#endif
211
212
    /* Todo: should we emit on_close if calling shutdown on an already half-closed socket?
213
     * We need more states in that case, we need to track RECEIVED_FIN
214
     * so far, the app has to track this and call close as needed */
215
304k
    if (!us_socket_is_closed(ssl, s) && !us_socket_is_shut_down(ssl, s)) {
216
304k
        us_internal_poll_set_type(&s->p, POLL_TYPE_SOCKET_SHUT_DOWN);
217
304k
        us_poll_change(&s->p, s->context->loop, us_poll_events(&s->p) & LIBUS_SOCKET_READABLE);
218
304k
        bsd_shutdown_socket(us_poll_fd((struct us_poll_t *) s));
219
304k
    }
220
304k
}
221
222
#endif