Hook getsockopt for get socket's IO timeout in fiber module.

This commit is contained in:
zhengshuxin 2024-07-23 14:39:42 +08:00
parent 5c85d8fe63
commit b563e34dc4
3 changed files with 99 additions and 7 deletions

View File

@ -55,6 +55,9 @@ fcntl_fn *sys_fcntl = NULL;
setsockopt_fn __sys_setsockopt = NULL;
setsockopt_fn *sys_setsockopt = NULL;
getsockopt_fn __sys_getsockopt = NULL;
getsockopt_fn *sys_getsockopt = NULL;
read_fn __sys_read = NULL;
read_fn *sys_read = NULL;
@ -250,6 +253,7 @@ static void hook_api(void)
LOAD_FN("accept", accept_fn, __sys_accept, sys_accept, 1);
LOAD_FN("connect", connect_fn, __sys_connect, sys_connect, 1);
LOAD_FN("setsockopt", setsockopt_fn, __sys_setsockopt, sys_setsockopt, 1);
LOAD_FN("getsockopt", getsockopt_fn, __sys_getsockopt, sys_getsockopt, 1);
LOAD_FN("sleep", sleep_fn, __sys_sleep, sys_sleep, 1);
LOAD_FN("fcntl", fcntl_fn, __sys_fcntl, sys_fcntl, 1);
LOAD_FN("read", read_fn, __sys_read, sys_read, 1);

View File

@ -46,6 +46,7 @@ typedef socket_t (WSAAPI *WSAAccept_fn)(SOCKET, struct sockaddr FAR *,
typedef int (*fcntl_fn)(int, int, ...);
typedef int (*setsockopt_fn)(socket_t, int, int, const void *, socklen_t);
typedef int (*getsockopt_fn)(socket_t, int, int, void *, socklen_t*);
typedef unsigned (*sleep_fn)(unsigned int seconds);
typedef ssize_t (*read_fn)(socket_t, void *, size_t);
typedef ssize_t (*readv_fn)(socket_t, const struct iovec *, int);
@ -154,6 +155,7 @@ extern WSAAccept_fn *sys_WSAAccept;
extern fcntl_fn *sys_fcntl;
extern setsockopt_fn *sys_setsockopt;
extern getsockopt_fn *sys_getsockopt;
extern sleep_fn *sys_sleep;
extern read_fn *sys_read;

View File

@ -554,17 +554,16 @@ int setsockopt(int sockfd, int level, int optname,
if (sys_setsockopt == NULL) {
hook_once();
if (sys_setsockopt == NULL) {
msg_error("sys_setsockopt null");
return -1;
}
}
if (!var_hook_sys_api || (optname != SO_RCVTIMEO
&& optname != SO_SNDTIMEO)) {
return sys_setsockopt ? (*sys_setsockopt)(sockfd, level,
optname, optval, optlen) : -1;
}
if (sys_setsockopt == NULL) {
msg_error("sys_setsockopt null");
return -1;
return (*sys_setsockopt)(sockfd, level, optname, optval, optlen);
}
switch (optlen) {
@ -588,6 +587,7 @@ int setsockopt(int sockfd, int level, int optname,
val = tm->tv_sec + tm->tv_usec / 1000000;
break;
default:
acl_fiber_set_error(FIBER_EINVAL);
msg_error("invalid optlen=%d", (int) optlen);
return -1;
}
@ -642,4 +642,90 @@ int setsockopt(int sockfd, int level, int optname,
#endif
}
int getsockopt(int sockfd, int level, int optname,
void *optval, socklen_t *optlen)
{
FILE_EVENT *fe;
if (sys_getsockopt == NULL) {
hook_once();
if (sys_getsockopt == NULL) {
msg_error("sys_getsockopt null");
return -1;
}
}
if (!var_hook_sys_api || (optname != SO_RCVTIMEO
&& optname != SO_SNDTIMEO)) {
return (*sys_getsockopt)(sockfd, level, optname, optval, optlen);
}
if (optval == NULL || optlen == NULL) {
acl_fiber_set_error(FIBER_EINVAL);
return -1;
}
fe = fiber_file_open(sockfd);
#if defined(SYS_WIN)
if (*optlen < (socklen_t) sizeof(int)) {
acl_fiber_set_error(FIBER_EINVAL);
msg_error("optlen(%d) too short < %zd", (int) (*optlen), sizeof(int));
return -1;
}
if (optname == SO_RCVTIMEO) {
if (fe->r_timeout < 0) {
*((int*) optval) = fe->r_timeout;
} else {
*((int*) optval) = fe->r_timeout / 1000;
}
} else if (optname == SO_SNDTIMEO) {
if (fe->w_timeout < 0) {
*((int*) optval) = fe->w_timeout;
} else {
*((int*) optval) = fe->w_timeout / 1000;
}
} else {
return -1; // xxx
}
*optlen = (socklen_t) sizeof(int);
return 0;
#else
if (*optlen < (socklen_t) sizeof(struct timeval)) {
acl_fiber_set_error(FIBER_EINVAL);
msg_error("optlen(%d) too short < %zd",
(int) (*optlen), sizeof(struct timeval));
return -1;
}
if (optname == SO_RCVTIMEO) {
struct timeval *tm = (struct timeval*) optval;
if (fe->r_timeout < 0) {
tm->tv_sec = 0;
tm->tv_usec = 0;
} else {
tm->tv_sec = fe->r_timeout / 1000;
tm->tv_usec = 1000000 * (fe->r_timeout % 1000);
}
} else if (optname == SO_SNDTIMEO) {
struct timeval *tm = (struct timeval*) optval;
if (fe->w_timeout < 0) {
tm->tv_sec = 0;
tm->tv_usec = 0;
} else {
tm->tv_sec = fe->w_timeout / 1000;
tm->tv_usec = 1000000 * (fe->w_timeout % 1000);
}
} else {
return -1; // xxx
}
*optlen = (socklen_t) sizeof(struct timeval);
return 0;
#endif
}
#endif