xref: /f-stack/app/micro_thread/mt_sys_hook.cpp (revision e7145e36)
1 
2 /**
3  * Tencent is pleased to support the open source community by making MSEC available.
4  *
5  * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
6  *
7  * Licensed under the GNU General Public License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License. You may
9  * obtain a copy of the License at
10  *
11  *     https://opensource.org/licenses/GPL-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software distributed under the
14  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15  * either express or implied. See the License for the specific language governing permissions
16  * and limitations under the License.
17  */
18 
19 
20 /**
21  *  @filename mt_sys_hook.cpp
22  */
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdint.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <assert.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <stdarg.h>
33 
34 #include "micro_thread.h"
35 #include "mt_sys_hook.h"
36 #include "ff_hook.h"
37 
38 using namespace NS_MICRO_THREAD;
39 
40 
41 #define MT_HOOK_MAX_FD      65535*2
42 #define MT_FD_FLG_INUSE     0x1
43 #define MT_FD_FLG_UNBLOCK   0x2
44 
45 typedef struct socket_hook_info
46 {
47     int     sock_flag;
48     int     read_timeout;
49     int     write_timeout;
50 }MtHookFd;
51 
52 MtSyscallFuncTab       g_mt_syscall_tab;
53 int                    g_mt_hook_flag;
54 int                    g_ff_hook_flag;
55 static MtHookFd        g_mt_hook_fd_tab[MT_HOOK_MAX_FD];
56 
57 MtHookFd* mt_hook_find_fd(int fd)
58 {
59     if ((fd < 0) || (fd >= MT_HOOK_MAX_FD)) {
60         return NULL;
61     }
62 
63     MtHookFd* fd_info =  &g_mt_hook_fd_tab[fd];
64     if (!(fd_info->sock_flag & MT_FD_FLG_INUSE)) {
65         return NULL;
66     } else {
67         return fd_info;
68     }
69 }
70 
71 void mt_hook_new_fd(int fd)
72 {
73     if ((fd < 0) || (fd >= MT_HOOK_MAX_FD)) {
74         return;
75     }
76 
77     MtHookFd* fd_info       = &g_mt_hook_fd_tab[fd];
78     fd_info->sock_flag      = MT_FD_FLG_INUSE;
79     fd_info->read_timeout   = 500;
80     fd_info->write_timeout  = 500;
81 }
82 
83 void mt_hook_free_fd(int fd)
84 {
85     if ((fd < 0) || (fd >= MT_HOOK_MAX_FD)) {
86         return;
87     }
88 
89     MtHookFd* fd_info       = &g_mt_hook_fd_tab[fd];
90     fd_info->sock_flag      = 0;
91     fd_info->read_timeout   = 0;
92     fd_info->write_timeout  = 0;
93 }
94 
95 #ifdef __cplusplus
96 extern "C" {
97 #endif
98 int ioctl(int fd, unsigned long cmd, ...)
99 {
100     va_list ap;
101     va_start(ap, cmd);
102     void* arg = va_arg(ap, void *);
103     va_end(ap);
104 
105     mt_hook_syscall(ioctl);
106     MtHookFd* hook_fd = mt_hook_find_fd(fd);
107     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
108     {
109         return ff_hook_ioctl(fd, cmd, arg);
110     }
111 
112     if (cmd == FIONBIO)
113     {
114         int flags =  (arg != NULL) ? *((int*)arg) : 0;
115         if (flags != 0) {
116             hook_fd->sock_flag |= MT_FD_FLG_UNBLOCK;
117         }
118     }
119 
120     return ff_hook_ioctl(fd, cmd, arg);
121 }
122 
123 int socket(int domain, int type, int protocol)
124 {
125     mt_hook_syscall(socket);
126 
127     if (!ff_hook_active())
128     {
129         return mt_real_func(socket)(domain, type, protocol);
130     }
131 
132     int fd = ff_hook_socket(domain, type, protocol);
133     if (fd < 0)
134     {
135         return fd;
136     }
137 
138     mt_hook_new_fd(fd);
139 
140     mt_hook_syscall(ioctl);
141     int nb = 1;
142     ff_hook_ioctl(fd, FIONBIO, &nb);
143 
144     return fd;
145 }
146 
147 int close(int fd)
148 {
149     mt_hook_syscall(close);
150     if (!ff_hook_active())
151     {
152         return mt_real_func(close)(fd);
153     }
154 
155     mt_hook_free_fd(fd);
156     return ff_hook_close(fd);
157 }
158 
159 int connect(int fd, const struct sockaddr *address, socklen_t address_len)
160 {
161     mt_hook_syscall(connect);
162     MtHookFd* hook_fd = mt_hook_find_fd(fd);
163     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
164     {
165         return mt_real_func(connect)(fd, address, address_len);
166     }
167 
168     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
169     {
170         return ff_hook_connect(fd, address, address_len);
171     }
172 
173     return MtFrame::connect(fd, address, (int)address_len, hook_fd->write_timeout);
174 }
175 
176 ssize_t read(int fd, void *buf, size_t nbyte)
177 {
178     mt_hook_syscall(read);
179     MtHookFd* hook_fd = mt_hook_find_fd(fd);
180     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
181     {
182         return mt_real_func(read)(fd, buf, nbyte);
183     }
184 
185     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
186     {
187         return ff_hook_read(fd, buf, nbyte);
188     }
189 
190     return MtFrame::read(fd, buf, nbyte, hook_fd->read_timeout);
191 }
192 
193 ssize_t write(int fd, const void *buf, size_t nbyte)
194 {
195     mt_hook_syscall(write);
196     MtHookFd* hook_fd = mt_hook_find_fd(fd);
197     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
198     {
199         return mt_real_func(write)(fd, buf, nbyte);
200     }
201 
202     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
203     {
204         return ff_hook_write(fd, buf, nbyte);
205     }
206 
207     return MtFrame::write(fd, buf, nbyte, hook_fd->write_timeout);
208 }
209 
210 ssize_t sendto(int fd, const void *message, size_t length, int flags,
211                const struct sockaddr *dest_addr, socklen_t dest_len)
212 {
213     mt_hook_syscall(sendto);
214     MtHookFd* hook_fd = mt_hook_find_fd(fd);
215     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
216     {
217         return mt_real_func(sendto)(fd, message, length, flags, dest_addr, dest_len);
218     }
219 
220     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
221     {
222         return ff_hook_sendto(fd, message, length, flags, dest_addr, dest_len);
223     }
224 
225     return MtFrame::sendto(fd, message, (int)length, flags,
226                            dest_addr, dest_len, hook_fd->write_timeout);
227 }
228 
229 ssize_t recvfrom(int fd, void *buffer, size_t length, int flags,
230                   struct sockaddr *address, socklen_t *address_len)
231 {
232     mt_hook_syscall(recvfrom);
233     MtHookFd* hook_fd = mt_hook_find_fd(fd);
234     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
235     {
236         return mt_real_func(recvfrom)(fd, buffer, length, flags, address, address_len);
237     }
238 
239     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
240     {
241         return ff_hook_recvfrom(fd, buffer, length, flags, address, address_len);
242     }
243 
244     return MtFrame::recvfrom(fd, buffer, length, flags, address, address_len, hook_fd->read_timeout);
245 
246 }
247 
248 ssize_t recv(int fd, void *buffer, size_t length, int flags)
249 {
250     mt_hook_syscall(recv);
251     MtHookFd* hook_fd = mt_hook_find_fd(fd);
252     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
253     {
254         return mt_real_func(recv)(fd, buffer, length, flags);
255     }
256 
257     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
258     {
259         return ff_hook_recv(fd, buffer, length, flags);
260     }
261 
262     return MtFrame::recv(fd, buffer, length, flags, hook_fd->read_timeout);
263 }
264 
265 ssize_t send(int fd, const void *buf, size_t nbyte, int flags)
266 {
267     mt_hook_syscall(send);
268     MtHookFd* hook_fd = mt_hook_find_fd(fd);
269     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
270     {
271         return mt_real_func(send)(fd, buf, nbyte, flags);
272     }
273 
274     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
275     {
276         return ff_hook_send(fd, buf, nbyte, flags);
277     }
278 
279     return MtFrame::send(fd, buf, nbyte, flags, hook_fd->write_timeout);
280 }
281 
282 int setsockopt(int fd, int level, int option_name, const void *option_value, socklen_t option_len)
283 {
284     mt_hook_syscall(setsockopt);
285     MtHookFd* hook_fd = mt_hook_find_fd(fd);
286     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
287     {
288         return mt_real_func(setsockopt)(fd, level, option_name, option_value, option_len);
289     }
290 
291     if (SOL_SOCKET == level)
292     {
293         struct timeval *val = (struct timeval*)option_value;
294         if (SO_RCVTIMEO == option_name)
295         {
296             hook_fd->read_timeout = val->tv_sec * 1000 + val->tv_usec / 1000;
297         }
298         else if (SO_SNDTIMEO == option_name)
299         {
300             hook_fd->write_timeout = val->tv_sec * 1000 + val->tv_usec / 1000;
301         }
302     }
303 
304     return ff_hook_setsockopt(fd, level, option_name, option_value, option_len);
305 }
306 
307 int fcntl(int fd, int cmd, ...)
308 {
309     va_list ap;
310     va_start(ap, cmd);
311     void* arg = va_arg(ap, void *);
312     va_end(ap);
313 
314     mt_hook_syscall(fcntl);
315     MtHookFd* hook_fd = mt_hook_find_fd(fd);
316     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
317     {
318         return mt_real_func(fcntl)(fd, cmd, arg);
319     }
320 
321     if (cmd == F_SETFL)
322     {
323         va_start(ap, cmd);
324         int flags = va_arg(ap, int);
325         va_end(ap);
326 
327         if (flags & O_NONBLOCK)
328         {
329             hook_fd->sock_flag |= MT_FD_FLG_UNBLOCK;
330         }
331     }
332 
333     return ff_hook_fcntl(fd, cmd, arg);
334 }
335 
336 int listen(int sockfd, int backlog)
337 {
338     mt_hook_syscall(listen);
339     if (!ff_hook_active())
340     {
341         return mt_real_func(listen)(sockfd, backlog);
342     }
343 
344     return ff_hook_listen(sockfd, backlog);
345 }
346 
347 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
348 {
349     mt_hook_syscall(bind);
350     if (!ff_hook_active())
351     {
352         return mt_real_func(bind)(sockfd, addr, addrlen);
353     }
354 
355     return ff_hook_bind(sockfd, addr, addrlen);
356 }
357 
358 int accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
359 {
360     mt_hook_syscall(accept);
361     if (!ff_hook_active())
362     {
363         return mt_real_func(accept)(fd, addr, addrlen);
364     }
365 
366     return ff_hook_accept(fd, addr, addrlen);
367 }
368 
369 #ifdef __cplusplus
370 }
371 #endif
372