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