mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-12-02 03:47:53 +08:00
Hook getsockopt for get socket's IO timeout in fiber module.
This commit is contained in:
parent
5c85d8fe63
commit
b563e34dc4
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user