Missmiaom
10/12/2019 - 2:05 AM

connect hook

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