Coverage Report

Created: 2024-04-25 06:10

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