1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
/*
* Copyright 2019-2021 OARC, Inc.
* Copyright 2017-2018 Akamai Technologies
* Copyright 2006-2016 Nominum, Inc.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "config.h"
#include "net.h"
#include "log.h"
#include "strerror.h"
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define self ((struct perf__udp_socket*)sock)
struct perf__udp_socket {
struct perf_net_socket base;
};
static ssize_t perf__udp_recv(struct perf_net_socket* sock, void* buf, size_t len, int flags)
{
return recv(sock->fd, buf, len, flags);
}
static ssize_t perf__udp_sendto(struct perf_net_socket* sock, uint16_t qid, const void* buf, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t addrlen)
{
return sendto(sock->fd, buf, len, flags, dest_addr, addrlen);
}
static int perf__udp_close(struct perf_net_socket* sock)
{
return close(sock->fd);
}
static int perf__udp_sockeq(struct perf_net_socket* sock_a, struct perf_net_socket* sock_b)
{
return sock_a->fd == sock_b->fd;
}
static int perf__udp_sockready(struct perf_net_socket* sock, int pipe_fd, int64_t timeout)
{
return 1;
}
struct perf_net_socket* perf_net_udp_opensocket(const perf_sockaddr_t* server, const perf_sockaddr_t* local, size_t bufsize)
{
struct perf__udp_socket* tmp = calloc(1, sizeof(struct perf__udp_socket)); // clang scan-build
struct perf_net_socket* sock = (struct perf_net_socket*)tmp;
int ret, flags;
if (!sock) {
perf_log_fatal("perf_net_udp_opensocket() out of memory");
return 0; // needed for clang scan build
}
sock->recv = perf__udp_recv;
sock->sendto = perf__udp_sendto;
sock->close = perf__udp_close;
sock->sockeq = perf__udp_sockeq;
sock->sockready = perf__udp_sockready;
sock->fd = socket(server->sa.sa.sa_family, SOCK_DGRAM, 0);
if (sock->fd == -1) {
char __s[256];
perf_log_fatal("socket: %s", perf_strerror_r(errno, __s, sizeof(__s)));
}
if (server->sa.sa.sa_family == AF_INET6) {
int on = 1;
if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) {
perf_log_warning("setsockopt(IPV6_V6ONLY) failed");
}
}
if (bind(sock->fd, &local->sa.sa, local->length) == -1) {
char __s[256];
perf_log_fatal("bind: %s", perf_strerror_r(errno, __s, sizeof(__s)));
}
if (bufsize > 0) {
bufsize *= 1024;
ret = setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
&bufsize, sizeof(bufsize));
if (ret < 0)
perf_log_warning("setsockbuf(SO_RCVBUF) failed");
ret = setsockopt(sock->fd, SOL_SOCKET, SO_SNDBUF,
&bufsize, sizeof(bufsize));
if (ret < 0)
perf_log_warning("setsockbuf(SO_SNDBUF) failed");
}
flags = fcntl(sock->fd, F_GETFL, 0);
if (flags < 0)
perf_log_fatal("fcntl(F_GETFL)");
ret = fcntl(sock->fd, F_SETFL, flags | O_NONBLOCK);
if (ret < 0)
perf_log_fatal("fcntl(F_SETFL)");
return sock;
}
|