/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 |