Coverage Report

Created: 2025-06-13 06:09

/src/uWebSockets/uSockets/src/udp.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
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
27
0
int us_udp_packet_buffer_ecn(struct us_udp_packet_buffer_t *buf, int index) {
28
0
    return bsd_udp_packet_buffer_ecn(buf, index);
29
0
}
30
31
0
int us_udp_packet_buffer_local_ip(struct us_udp_packet_buffer_t *buf, int index, char *ip) {
32
0
    return bsd_udp_packet_buffer_local_ip(buf, index, ip);
33
0
}
34
35
0
char *us_udp_packet_buffer_peer(struct us_udp_packet_buffer_t *buf, int index) {
36
0
    return bsd_udp_packet_buffer_peer(buf, index);
37
0
}
38
39
0
char *us_udp_packet_buffer_payload(struct us_udp_packet_buffer_t *buf, int index) {
40
0
    return bsd_udp_packet_buffer_payload(buf, index);
41
0
}
42
43
0
int us_udp_packet_buffer_payload_length(struct us_udp_packet_buffer_t *buf, int index) {
44
0
    return bsd_udp_packet_buffer_payload_length(buf, index);
45
0
}
46
47
// what should we return? number of sent datagrams?
48
0
int us_udp_socket_send(struct us_udp_socket_t *s, struct us_udp_packet_buffer_t *buf, int num) {
49
0
    int fd = us_poll_fd((struct us_poll_t *) s);
50
51
    // we need to poll out if we failed
52
53
0
    return bsd_sendmmsg(fd, buf, num, 0);
54
0
}
55
56
0
int us_udp_socket_receive(struct us_udp_socket_t *s, struct us_udp_packet_buffer_t *buf) {
57
0
    int fd = us_poll_fd((struct us_poll_t *) s);
58
0
    return bsd_recvmmsg(fd, buf, LIBUS_UDP_MAX_NUM, 0, 0);
59
0
}
60
61
0
void us_udp_buffer_set_packet_payload(struct us_udp_packet_buffer_t *send_buf, int index, int offset, void *payload, int length, void *peer_addr) {
62
0
    bsd_udp_buffer_set_packet_payload(send_buf, index, offset, payload, length, peer_addr);
63
0
}
64
65
0
struct us_udp_packet_buffer_t *us_create_udp_packet_buffer() {
66
0
    return (struct us_udp_packet_buffer_t *) bsd_create_udp_packet_buffer();
67
0
}
68
69
struct us_internal_udp_t {
70
    struct us_internal_callback_t cb;
71
    struct us_udp_packet_buffer_t *receive_buf;
72
    void (*data_cb)(struct us_udp_socket_t *, struct us_udp_packet_buffer_t *, int);
73
    void (*drain_cb)(struct us_udp_socket_t *);
74
    void *user;
75
    /* An UDP socket can only ever be bound to one single port regardless of how
76
     * many interfaces it may listen to. Therefore we cache the port after creation
77
     * and use it to build a proper and full sockaddr_in or sockaddr_in6 for every received packet */
78
    int port;
79
};
80
81
0
int us_udp_socket_bound_port(struct us_udp_socket_t *s) {
82
0
    return ((struct us_internal_udp_t *) s)->port;
83
0
}
84
85
/* Internal wrapper, move from here */
86
0
void internal_on_udp_read(struct us_udp_socket_t *s) {
87
88
    // lookup receive buffer and callback here
89
0
    struct us_internal_udp_t *udp = (struct us_internal_udp_t *) s;
90
91
0
    int packets = us_udp_socket_receive(s, udp->receive_buf);
92
    //printf("Packets: %d\n", packets);
93
94
    // we need to get the socket data and lookup its callback here
95
96
97
0
    udp->data_cb(s, udp->receive_buf, packets);
98
0
}
99
100
0
void *us_udp_socket_user(struct us_udp_socket_t *s) {
101
0
    struct us_internal_udp_t *udp = (struct us_internal_udp_t *) s;
102
103
0
    return udp->user;
104
0
}
105
106
0
struct us_udp_socket_t *us_create_udp_socket(struct us_loop_t *loop, struct us_udp_packet_buffer_t *buf, void (*data_cb)(struct us_udp_socket_t *, struct us_udp_packet_buffer_t *, int), void (*drain_cb)(struct us_udp_socket_t *), const char *host, unsigned short port, void *user) {
107
    
108
0
    LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_udp_socket(host, port);
109
0
    if (fd == LIBUS_SOCKET_ERROR) {
110
0
        return 0;
111
0
    }
112
113
    /* If buf is 0 then create one here */
114
0
    if (!buf) {
115
0
        buf = us_create_udp_packet_buffer();
116
0
    }
117
118
0
    int ext_size = 0;
119
0
    int fallthrough = 0;
120
121
0
    struct us_poll_t *p = us_create_poll(loop, fallthrough, sizeof(struct us_internal_udp_t) - sizeof(struct us_poll_t) + ext_size);
122
0
    us_poll_init(p, fd, POLL_TYPE_CALLBACK);
123
124
0
    struct us_internal_udp_t *cb = (struct us_internal_udp_t *) p;
125
0
    cb->cb.loop = loop;
126
0
    cb->cb.cb_expects_the_loop = 0;
127
0
    cb->cb.leave_poll_ready = 1;
128
129
    /* Get and store the port once */
130
0
    struct bsd_addr_t tmp;
131
0
    bsd_local_addr(fd, &tmp);
132
0
    cb->port = bsd_addr_get_port(&tmp);
133
134
0
    printf("The port of UDP is: %d\n", cb->port);
135
136
    /* There is no udp socket context, only user data */
137
    /* This should really be ext like everything else */
138
0
    cb->user = user;
139
140
0
    cb->data_cb = data_cb;
141
0
    cb->receive_buf = buf;
142
0
    cb->drain_cb = drain_cb;
143
144
0
    cb->cb.cb = (void (*)(struct us_internal_callback_t *)) internal_on_udp_read;
145
146
0
    us_poll_start((struct us_poll_t *) cb, cb->cb.loop, LIBUS_SOCKET_READABLE);
147
    
148
0
    return (struct us_udp_socket_t *) cb;
149
0
}
150
151
#endif