1 /*
2 * Copyright 2019-2021 OARC, Inc.
3 * Copyright 2017-2018 Akamai Technologies
4 * Copyright 2006-2016 Nominum, Inc.
5 * All rights reserved.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #ifndef PERF_NET_H
21 #define PERF_NET_H 1
22
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <openssl/ssl.h>
26 #include <pthread.h>
27 #include <netinet/in.h>
28 #include <assert.h>
29 #include <stdbool.h>
30
31 #define TCP_RECV_BUF_SIZE (16 * 1024)
32 #define TCP_SEND_BUF_SIZE (4 * 1024)
33
34 struct perf_sockaddr {
35 union {
36 struct sockaddr sa;
37 struct sockaddr_in sin;
38 struct sockaddr_in6 sin6;
39 } sa;
40 socklen_t length;
41 };
42 typedef struct perf_sockaddr perf_sockaddr_t;
43
44 enum perf_net_mode {
45 sock_none,
46 sock_file,
47 sock_pipe,
48 sock_udp,
49 sock_tcp,
50 sock_dot,
51 sock_doh
52 };
53
54 struct perf_net_socket;
55
56 typedef ssize_t (*perf_net_recv_t)(struct perf_net_socket* sock, void* buf, size_t len, int flags);
57 typedef ssize_t (*perf_net_sendto_t)(struct perf_net_socket* sock, uint16_t qid, const void* buf, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t addrlen);
58 typedef int (*perf_net_close_t)(struct perf_net_socket* sock);
59 typedef int (*perf_net_sockeq_t)(struct perf_net_socket* sock, struct perf_net_socket* other);
60
61 /* sockready return:
62 * -1: socket readiness timed out / canceled / interrupted or unknown error
63 * 0: Socket is not ready, may still be connecting, negotiating or sending
64 * 1: Socket is ready and can be used for sending to
65 */
66 typedef int (*perf_net_sockready_t)(struct perf_net_socket* sock, int pipe_fd, int64_t timeout);
67
68 /* Indicates if there are more data to be read in buffers of the transport */
69 typedef bool (*perf_net_have_more_t)(struct perf_net_socket* sock);
70
71 /* Callback for when a query has been sent if it was delayed due to partily sent or reconnection */
72 typedef void (*perf_net_sent_cb_t)(struct perf_net_socket* sock, uint16_t qid);
73
74 typedef enum perf_socket_event {
75 perf_socket_event_connecting,
76 perf_socket_event_connected,
77 perf_socket_event_reconnecting,
78 perf_socket_event_reconnected
79 } perf_socket_event_t;
80 /* Callback for socket events related to connection oriented protocols, for statistics */
81 typedef void (*perf_net_event_cb_t)(struct perf_net_socket* sock, perf_socket_event_t event, uint64_t elapsed_time);
82
83 struct perf_net_socket {
84 void* data; /* user data */
85
86 enum perf_net_mode mode;
87 perf_net_recv_t recv;
88 perf_net_sendto_t sendto;
89 perf_net_close_t close;
90 perf_net_sockeq_t sockeq;
91 perf_net_sockready_t sockready;
92 perf_net_have_more_t have_more;
93
94 /*
95 * Not set by protocol, set by caller.
96 * May be 0 if caller don't care.
97 * MUST NOT be called from sendto(), only called if query is delayed in some way.
98 */
99 perf_net_sent_cb_t sent;
100
101 /* Used if caller want info on connection oriented events */
102 perf_net_event_cb_t event;
103
104 /*
105 * The system file descriptor that is used for transport, this is used
106 * in os functions to poll/wait for read/write.
107 */
108 int fd;
109 };
110
perf_net_recv(struct perf_net_socket * sock,void * buf,size_t len,int flags)111 static inline ssize_t perf_net_recv(struct perf_net_socket* sock, void* buf, size_t len, int flags)
112 {
113 return sock->recv(sock, buf, len, flags);
114 }
115
perf_net_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)116 static inline ssize_t perf_net_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)
117 {
118 return sock->sendto(sock, qid, buf, len, flags, dest_addr, addrlen);
119 }
120
perf_net_close(struct perf_net_socket * sock)121 static inline int perf_net_close(struct perf_net_socket* sock)
122 {
123 return sock->close(sock);
124 }
125
perf_net_sockeq(struct perf_net_socket * sock_a,struct perf_net_socket * sock_b)126 static inline int perf_net_sockeq(struct perf_net_socket* sock_a, struct perf_net_socket* sock_b)
127 {
128 assert(sock_a);
129 assert(sock_b);
130 assert(sock_a->mode == sock_b->mode);
131 return sock_a->sockeq(sock_a, sock_b);
132 }
133
perf_net_sockready(struct perf_net_socket * sock,int pipe_fd,int64_t timeout)134 static inline int perf_net_sockready(struct perf_net_socket* sock, int pipe_fd, int64_t timeout)
135 {
136 return sock->sockready(sock, pipe_fd, timeout);
137 }
138
perf_net_have_more(struct perf_net_socket * sock)139 static inline int perf_net_have_more(struct perf_net_socket* sock)
140 {
141 return sock->have_more ? sock->have_more(sock) : false;
142 }
143
144 enum perf_net_mode perf_net_parsemode(const char* mode);
145
146 int perf_net_parsefamily(const char* family);
147
148 void perf_net_parseserver(int family, const char* name, unsigned int port, perf_sockaddr_t* addr);
149 void perf_net_parselocal(int family, const char* name, unsigned int port, perf_sockaddr_t* addr);
150
151 void perf_sockaddr_fromin(perf_sockaddr_t* sockaddr, const struct in_addr* in, in_port_t port);
152 void perf_sockaddr_fromin6(perf_sockaddr_t* sockaddr, const struct in6_addr* in, in_port_t port);
153 in_port_t perf_sockaddr_port(const perf_sockaddr_t* sockaddr);
154 void perf_sockaddr_setport(perf_sockaddr_t* sockaddr, in_port_t port);
155 void perf_sockaddr_format(const perf_sockaddr_t* sockaddr, char* buf, size_t len);
156
perf_sockaddr_isinet6(const perf_sockaddr_t * sockaddr)157 static inline int perf_sockaddr_isinet6(const perf_sockaddr_t* sockaddr)
158 {
159 return sockaddr->sa.sa.sa_family == AF_INET6;
160 }
161
162 struct perf_net_socket* perf_net_opensocket(enum perf_net_mode mode, const perf_sockaddr_t* server, const perf_sockaddr_t* local, unsigned int offset, size_t bufsize, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event);
163
164 struct perf_net_socket* perf_net_udp_opensocket(const perf_sockaddr_t*, const perf_sockaddr_t*, size_t, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event);
165 struct perf_net_socket* perf_net_tcp_opensocket(const perf_sockaddr_t*, const perf_sockaddr_t*, size_t, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event);
166 struct perf_net_socket* perf_net_dot_opensocket(const perf_sockaddr_t*, const perf_sockaddr_t*, size_t, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event);
167 struct perf_net_socket* perf_net_doh_opensocket(const perf_sockaddr_t*, const perf_sockaddr_t*, size_t, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event);
168
169 #define DEFAULT_DOH_URI "https://localhost/dns-query"
170 #define DEFAULT_DOH_METHOD "GET"
171
172 void perf_net_doh_parse_uri(const char*);
173 void perf_net_doh_parse_method(const char*);
174 void perf_net_doh_set_max_concurrent_streams(size_t);
175
176 void perf_net_stats_init(enum perf_net_mode);
177 void perf_net_stats_compile(enum perf_net_mode, struct perf_net_socket*);
178 void perf_net_stats_print(enum perf_net_mode);
179 void perf_net_doh_stats_init();
180 void perf_net_doh_stats_compile(struct perf_net_socket*);
181 void perf_net_doh_stats_print();
182
183 #endif
184