int connect(int fd, const struct sockaddr *address, socklen_t address_len)
{
//--- hook 系统connect函数
HOOK_SYS_FUNC( connect );
//---如果不允许hook,则直接调用系统connect,并返回
if( !co_is_enable_sys_hook() )
{
return g_sys_connect_func(fd,address,address_len);
}
//1.sys call
int ret = g_sys_connect_func( fd,address,address_len );
rpchook_t *lp = get_by_fd( fd );
if( !lp ) return ret;
if( sizeof(lp->dest) >= address_len )
{
memcpy( &(lp->dest),address,(int)address_len );
}
if( O_NONBLOCK & lp->user_flag )
{
return ret;
}
//--- 如果connect成功,则返回
if (!(ret < 0 && errno == EINPROGRESS))
{
return ret;
}
//--- connect不成功,需要进行等待和协程切换
//2.wait
int pollret = 0;
struct pollfd pf = { 0 };
for(int i=0;i<3;i++) //25s * 3 = 75s
{
memset( &pf,0,sizeof(pf) );
pf.fd = fd;
pf.events = ( POLLOUT | POLLERR | POLLHUP );
//--- 利用poll监听fd事件,注意这里的poll也被hook
pollret = poll( &pf,1,25000 );
if( 1 == pollret )
{
break;
}
}
//--- 连接成功
if( pf.revents & POLLOUT ) //connect succ
{
errno = 0;
return 0;
}
//--- 连接失败
//3.set errno
int err = 0;
socklen_t errlen = sizeof(err);
getsockopt( fd,SOL_SOCKET,SO_ERROR,&err,&errlen);
if( err )
{
errno = err;
}
else
{
errno = ETIMEDOUT;
}
return ret;
}