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