xref: /f-stack/app/redis-5.0.5/src/anet_ff.c (revision 2317ada5)
1 /*
2  * Inspired by opendp/dpdk-nginx's ans_module.c.
3  * License of opendp:
4  *
5  BSD LICENSE
6  Copyright(c) 2015-2017 Ansyun [email protected]. All rights reserved.
7  All rights reserved.
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions
10  are met:
11 
12  Redistributions of source code must retain the above copyright
13  notice, this list of conditions and the following disclaimer.
14  Redistributions in binary form must reproduce the above copyright
15  notice, this list of conditions and the following disclaimer in
16  the documentation and/or other materials provided with the
17  distribution.
18  Neither the name of Ansyun [email protected] nor the names of its
19  contributors may be used to endorse or promote products derived
20  from this software without specific prior written permission.
21  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  Author: JiaKai ([email protected]) and Bluestar ([email protected])
33  */
34 
35 /*
36  * Copyright (C) 2017-2021 THL A29 Limited, a Tencent company.
37  * All rights reserved.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions are met:
41  *
42  * 1. Redistributions of source code must retain the above copyright notice, this
43  *   list of conditions and the following disclaimer.
44  * 2. Redistributions in binary form must reproduce the above copyright notice,
45  *   this list of conditions and the following disclaimer in the documentation
46  *   and/or other materials provided with the distribution.
47  *
48  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
51  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
52  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
53  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
54  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
55  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
56  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
57  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58  *
59  */
60 
61 #include <stdio.h>
62 #include <stdint.h>
63 #include <string.h>
64 #include <stdlib.h>
65 #include <stdarg.h>
66 #include <errno.h>
67 #include <netinet/in.h>
68 #include <assert.h>
69 #include <unistd.h>
70 #include <sys/types.h>
71 #include <sys/socket.h>
72 #include <arpa/inet.h>
73 #include <sys/time.h>
74 #include <sys/select.h>
75 
76 typedef unsigned short u_short;
77 typedef unsigned int u_int;
78 #include "ff_api.h"
79 
80 #define _GNU_SOURCE
81 #define __USE_GNU
82 
83 #include <unistd.h>
84 //#include <sched.h>
85 #include <sys/types.h>
86 //#include <fcntl.h>
87 #include <sys/syscall.h>
88 #include <dlfcn.h>
89 
90 #pragma GCC diagnostic push
91 #pragma GCC diagnostic ignored "-Wpedantic"
92 
93 #ifndef likely
94 #define likely(x)  __builtin_expect((x),1)
95 #endif
96 
97 #ifndef unlikely
98 #define unlikely(x)  __builtin_expect((x),0)
99 #endif
100 
101 #define INIT_FUNCTION(func) \
102     real_##func = dlsym(RTLD_NEXT, #func); \
103     assert(real_##func)
104 
105 static int inited = 0;
106 
107 static int (*real_close)(int);
108 static int (*real_socket)(int, int, int);
109 static int (*real_bind)(int, const struct sockaddr*, socklen_t);
110 static int (*real_connect)(int, const struct sockaddr*, socklen_t);
111 static int (*real_listen)(int, int);
112 static int (*real_setsockopt)(int, int, int, const void *, socklen_t);
113 
114 static int (*real_accept)(int, struct sockaddr *, socklen_t *);
115 static int (*real_accept4)(int, struct sockaddr *, socklen_t *, int);
116 static ssize_t (*real_recv)(int, void *, size_t, int);
117 static ssize_t (*real_send)(int, const void *, size_t, int);
118 
119 static ssize_t (*real_writev)(int, const struct iovec *, int);
120 static ssize_t (*real_write)(int, const void *, size_t );
121 static ssize_t (*real_read)(int, void *, size_t );
122 static ssize_t (*real_readv)(int, const struct iovec *, int);
123 
124 static int (*real_ioctl)(int, int, void *);
125 static int (*real_fcntl)(int, int, void *);
126 
127 static int (*real_select) (int, fd_set *, fd_set *, fd_set *, struct timeval *);
128 
129 
ff_mod_init()130 void ff_mod_init() {
131     INIT_FUNCTION(socket);
132     INIT_FUNCTION(bind);
133     INIT_FUNCTION(connect);
134     INIT_FUNCTION(close);
135     INIT_FUNCTION(listen);
136     INIT_FUNCTION(setsockopt);
137     INIT_FUNCTION(accept);
138     INIT_FUNCTION(accept4);
139     INIT_FUNCTION(recv);
140     INIT_FUNCTION(send);
141     INIT_FUNCTION(writev);
142     INIT_FUNCTION(write);
143     INIT_FUNCTION(read);
144     INIT_FUNCTION(readv);
145 
146     INIT_FUNCTION(ioctl);
147     INIT_FUNCTION(fcntl);
148     INIT_FUNCTION(select);
149 
150     inited = 1;
151 }
152 
153 int
socket(int domain,int type,int protocol)154 socket(int domain, int type, int protocol)
155 {
156     int rc;
157 
158     if (unlikely(inited == 0)) {
159         INIT_FUNCTION(socket);
160         return real_socket(domain, type, protocol);
161     }
162 
163     if ((AF_INET != domain) || (SOCK_STREAM != type && SOCK_DGRAM != type)) {
164         rc = real_socket(domain, type, protocol);
165         return rc;
166     }
167 
168     rc = ff_socket(domain, type, protocol);
169 
170     return rc;
171 }
172 
173 int
bind(int sockfd,const struct sockaddr * addr,socklen_t addrlen)174 bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
175 {
176     if (unlikely(inited == 0)) {
177         INIT_FUNCTION(bind);
178         return real_bind(sockfd, addr, addrlen);
179     }
180 
181     if (ff_fdisused(sockfd)) {
182         return ff_bind(sockfd, (struct linux_sockaddr *)addr, addrlen);
183     } else {
184         return real_bind(sockfd, addr, addrlen);
185     }
186 }
187 
188 int
connect(int sockfd,const struct sockaddr * addr,socklen_t addrlen)189 connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
190 {
191     if (unlikely(inited == 0)) {
192         INIT_FUNCTION(connect);
193         return real_connect(sockfd, addr, addrlen);
194     }
195 
196     if (ff_fdisused(sockfd)) {
197         return ff_connect(sockfd, (struct linux_sockaddr *)addr, addrlen);
198     } else {
199         return real_connect(sockfd, addr, addrlen);
200     }
201 }
202 
203 ssize_t
send(int sockfd,const void * buf,size_t len,int flags)204 send(int sockfd, const void *buf, size_t len, int flags)
205 {
206     if (unlikely(inited == 0)) {
207         INIT_FUNCTION(send);
208         return real_send(sockfd, buf, len, flags);
209     }
210 
211     if (ff_fdisused(sockfd)) {
212         return ff_send(sockfd, buf, len, flags);
213     } else {
214         return real_send(sockfd, buf, len, flags);
215     }
216 }
217 
218 ssize_t
recv(int sockfd,void * buf,size_t len,int flags)219 recv(int sockfd, void *buf, size_t len, int flags)
220 {
221     if (unlikely(inited == 0)) {
222         INIT_FUNCTION(recv);
223         return real_recv(sockfd, buf, len, flags);
224     }
225 
226     if (ff_fdisused(sockfd)) {
227         return ff_recv(sockfd, buf, len, flags);
228     } else {
229         return real_recv(sockfd, buf, len, flags);
230     }
231 }
232 
233 int
listen(int sockfd,int backlog)234 listen(int sockfd, int backlog)
235 {
236     if (unlikely(inited == 0)) {
237         INIT_FUNCTION(listen);
238         return real_listen(sockfd, backlog);
239     }
240 
241     if (ff_fdisused(sockfd)) {
242         return ff_listen(sockfd, backlog);
243     } else {
244         return real_listen(sockfd, backlog);
245     }
246 }
247 
248 int
setsockopt(int sockfd,int level,int optname,const void * optval,socklen_t optlen)249 setsockopt (int sockfd, int level, int optname,
250     const void *optval, socklen_t optlen)
251 {
252     if (unlikely(inited == 0)) {
253         INIT_FUNCTION(setsockopt);
254         return real_setsockopt(sockfd, level, optname, optval, optlen);
255     }
256 
257     if (ff_fdisused(sockfd)) {
258         return ff_setsockopt(sockfd, level, optname, optval, optlen);
259     } else {
260         return real_setsockopt(sockfd, level, optname, optval, optlen);
261     }
262 }
263 
264 int
accept(int sockfd,struct sockaddr * addr,socklen_t * addrlen)265 accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
266 {
267     if (unlikely(inited == 0)) {
268         INIT_FUNCTION(accept);
269         return real_accept(sockfd, addr, addrlen);
270     }
271 
272     if (ff_fdisused(sockfd)) {
273         return ff_accept(sockfd, (struct linux_sockaddr *)addr, addrlen);
274     } else {
275         return real_accept(sockfd, addr, addrlen);
276     }
277 }
278 
279 int
accept4(int sockfd,struct sockaddr * addr,socklen_t * addrlen,int flags)280 accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
281 {
282     if (unlikely(inited == 0)) {
283         INIT_FUNCTION(accept4);
284         return real_accept4(sockfd, addr, addrlen, flags);
285     }
286 
287     if (ff_fdisused(sockfd)) {
288         return ff_accept(sockfd, (struct linux_sockaddr *)addr, addrlen);
289     } else {
290         return real_accept4(sockfd, addr, addrlen, flags);
291     }
292 }
293 
294 int
close(int sockfd)295 close(int sockfd)
296 {
297     if (unlikely(inited == 0)) {
298         INIT_FUNCTION(close);
299         return real_close(sockfd);
300     }
301 
302     if (ff_fdisused(sockfd)) {
303         return ff_close(sockfd);
304     } else {
305         return real_close(sockfd);
306     }
307 }
308 
write(int sockfd,const void * buf,size_t count)309 ssize_t write(int sockfd, const void *buf, size_t count)
310 {
311     if (unlikely(inited == 0)) {
312         INIT_FUNCTION(write);
313         return real_write(sockfd, buf, count);
314     }
315 
316     if (ff_fdisused(sockfd)) {
317         return ff_write(sockfd, buf, count);
318     } else {
319         return real_write(sockfd, buf, count);
320     }
321 }
322 
323 ssize_t
writev(int sockfd,const struct iovec * iov,int iovcnt)324 writev(int sockfd, const struct iovec *iov, int iovcnt)
325 {
326     if (unlikely(inited == 0)) {
327         INIT_FUNCTION(writev);
328         return real_writev(sockfd, iov, iovcnt);
329     }
330 
331     if (ff_fdisused(sockfd)) {
332         return ff_writev(sockfd, iov, iovcnt);
333     } else {
334         return real_writev(sockfd, iov, iovcnt);
335     }
336 }
337 
read(int sockfd,void * buf,size_t count)338 ssize_t read(int sockfd, void *buf, size_t count)
339 {
340     if (unlikely(inited == 0)) {
341         INIT_FUNCTION(read);
342         return real_read(sockfd, buf, count);
343     }
344 
345     if (ff_fdisused(sockfd)) {
346         return ff_read(sockfd, buf, count);
347     } else {
348         return real_read(sockfd, buf, count);
349     }
350 }
351 
352 ssize_t
readv(int sockfd,const struct iovec * iov,int iovcnt)353 readv(int sockfd, const struct iovec *iov, int iovcnt)
354 {
355     if (unlikely(inited == 0)) {
356         INIT_FUNCTION(readv);
357         return real_readv(sockfd, iov, iovcnt);
358     }
359 
360     if (ff_fdisused(sockfd)) {
361         return ff_readv(sockfd, iov, iovcnt);
362     } else {
363         return real_readv(sockfd, iov, iovcnt);
364     }
365 }
366 
367 int
ioctl(int sockfd,int request,void * p)368 ioctl(int sockfd, int request, void *p)
369 {
370     if (unlikely(inited == 0)) {
371         INIT_FUNCTION(ioctl);
372         return real_ioctl(sockfd, request, p);
373     }
374 
375     if (ff_fdisused(sockfd)) {
376         return ff_ioctl(sockfd, request, p);
377     } else {
378         return real_ioctl(sockfd, request, p);
379     }
380 }
381 
fcntl(int sockfd,int cmd,void * p)382 int fcntl(int sockfd, int cmd, void *p)
383 {
384     if (unlikely(inited == 0)) {
385         INIT_FUNCTION(fcntl);
386         return real_fcntl(sockfd, cmd, p);
387     }
388 
389     if (ff_fdisused(sockfd)) {
390         return ff_fcntl(sockfd, cmd, p);
391     } else {
392         return real_fcntl(sockfd, cmd, p);
393     }
394 }
395 
396 int
select(int nfds,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout)397 select(int nfds, fd_set *readfds, fd_set *writefds,
398     fd_set *exceptfds, struct timeval *timeout)
399 {
400     if (unlikely(inited == 0)) {
401         INIT_FUNCTION(select);
402         return real_select(nfds, readfds, writefds, exceptfds, timeout);
403     }
404 
405     if (ff_fdisused(nfds)) {
406         struct timeval tv;
407         tv.tv_sec = 0;
408         tv.tv_usec = 0;
409         return ff_select(nfds, readfds, writefds, exceptfds, &tv);
410     } else {
411         return real_select(nfds, readfds, writefds, exceptfds, timeout);
412     }
413 }
414 
415 #pragma GCC diagnostic pop
416 
417