Esempio n. 1
0
/*
 * handle accept event
 */
int accept_handle( conn_t *pconn )
{
	int fd;
	struct sockaddr_in	addr;
	socklen_t addrlen;
	conn_t	*client_conn;

	bzero( &addr, sizeof(struct sockaddr_in) );
	addrlen = sizeof(struct sockaddr_in);
	fd = accept( pconn->fd, (struct sockaddr*)&addr, &addrlen );
	epoll_mod_connection( pconn, EPOLLIN );			//重新把监听套接子添加到epoll中

	if ( fd < 0 ) {
		log_message( LOG_WARNING, "accept error:%s.", strerror(errno) );
		return -1;		//惊群现象
	}
	
	client_conn = get_conns_slot();
	if ( NULL == client_conn ) {
		log_message( LOG_WARNING, "get_conns_slot NULL." );
		return -2;
	}

	client_conn->fd = fd;
	client_conn->read_handle = read_client_handle;
	client_conn->write_handle = write_client_handle;
	client_conn->read_buffer = new_buffer();		//这里有内存泄漏
	client_conn->write_buffer = new_buffer();		//这里有内存泄漏
	client_conn->server_conn = NULL;
	client_conn->addr = addr;
	client_conn->read_closed = client_conn->write_closed = 0;
	client_conn->type = C_CLIENT;

	char *ip = NULL;
	ip = inet_ntoa( addr.sin_addr );
	log_message( LOG_CONN, "create a new conn[fd:%d] client[%s:%d]--proxy.", client_conn->fd, ip, ntohs(addr.sin_port) );

	epoll_add_connection( client_conn, EPOLLIN );	
	return TRUE;
}
Esempio n. 2
0
int init_conns_array( int epfd )
{
	int i;
	conn_t 	*pconn;

	for ( i = 1; i < MAXCONNSLOTS; ++ i ) {
		conns[i-1].data = &conns[i];
	}
	conns[i-1].data = NULL;
	free_conn = &conns[0];
	fullcnt = 0;	

	for ( i = 0; i < MAXCONNSLOTS; ++ i ) {
		conns[i].read_buffer = NULL;
		conns[i].write_buffer = NULL;
		conns[i].read_closed = conns[i].write_closed = 0;
	}

	for ( i = 0; i < listenfd_cnt; ++ i ) {
		pconn = get_conns_slot();
		if ( NULL == pconn ) {
			log_message( LOG_WARNING, "conns array full, refusing service." );
			return -1;
		}
		pconn->fd = listenfds[i].fd;
		pconn->read_handle = accept_handle;
		pconn->write_handle = NULL;
		pconn->read_buffer = pconn->write_buffer = NULL;
		pconn->type = C_LISTEN;

		epoll_add_connection( pconn, EPOLLIN );

		log_message( LOG_DEBUG, "init_conns_array: add listenfd into epoll." );
	}

	return TRUE;
}
Esempio n. 3
0
static int tcp_connect(TNetWorkMsg *_ptNetWorkMsg, const char *_pcIP, int _iPort)
{
	if(NULL == _ptNetWorkMsg || NULL == _pcIP)
	{
		dbg();
		return ERR;
	}

	int iRet = ERR;
	unsigned int ul;
	dbgprintf(0, "start tcp connect to %s:%d", _ptNetWorkMsg->m_pcIp, _ptNetWorkMsg->m_iPort);
	
	fd_set rdevents,wrevents,exevents;
	struct   timeval tv;
	socklen_t sLen;
	struct sockaddr_in ptDestAddr;
	
	if(INVALID_SOCKET == _ptNetWorkMsg->m_iSocket)
	{
		struct linger so_linger;
    	_ptNetWorkMsg->m_iSocket = socket(AF_INET, SOCK_STREAM, 0);
		
    	if(INVALID_SOCKET == _ptNetWorkMsg->m_iSocket)
    	{
    		dbg();
			iRet = ERR;
			goto EXIT;
    	}

      	so_linger.l_onoff = 1;
       	so_linger.l_linger = 0;
       	iRet = setsockopt(_ptNetWorkMsg->m_iSocket, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger));
       	
    	int cnt = SO_RCVBUF_LEN;
    	iRet = setsockopt(_ptNetWorkMsg->m_iSocket, SOL_SOCKET, SO_RCVBUF, (int *)&cnt,sizeof(int));
    	cnt = SO_SNDBUF_LEN;
    	iRet = setsockopt(_ptNetWorkMsg->m_iSocket, SOL_SOCKET, SO_SNDBUF, (int *)&cnt, sizeof(int));
	}

	#if 0
	// 绑定指定网卡或IP
	strut sockaddr_in sin;
	
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = xxx;
	sin.sin_port = xxx;
	
	bind(sock, (struct sockaddr *)&sin, sizeof(sin));
	// 绑定结束
	#endif

	//设置为非阻塞模式
	ul = 1;
    ioctl(_ptNetWorkMsg->m_iSocket, FIONBIO, &ul);   

	// 指定地址和端口
	memset(&ptDestAddr, 0, sizeof(struct sockaddr_in));
	
	ptDestAddr.sin_family 	 	= AF_INET;
	ptDestAddr.sin_port   	 	= htons(_iPort);
	ptDestAddr.sin_addr.s_addr 	= inet_addr(_pcIP);

    // 与服务器端建立连接
    iRet = connect(_ptNetWorkMsg->m_iSocket,(struct sockaddr*)&ptDestAddr, sizeof(ptDestAddr));

	dbgint(iRet);
	dbgint(errno);
	
    if(-1 == iRet && errno != EINPROGRESS)
	{
		dbg();
 		iRet = ERR;
		goto EXIT;
	}
	
	//若没有直接连接成功则需要等待
	if(0 != iRet)
	{  
		//把先前的套接字加到读集合里面	
		FD_ZERO(&rdevents);
		FD_SET(_ptNetWorkMsg->m_iSocket, &rdevents);  
		wrevents = rdevents;  
		
		//异常集合
		exevents = rdevents;   

		#if 1
		//设置时间为5秒
		tv.tv_sec = 5;  
		tv.tv_usec = 0;
		#else
		//设置时间为10秒
		tv.tv_sec = 10;  
		tv.tv_usec = 0;
		#endif

		iRet = select(_ptNetWorkMsg->m_iSocket + 1, &rdevents, &wrevents, &exevents, &tv);

		dbgint(iRet);

		if(iRet <= 0) 
		{  
			dbg();
			dbgint(errno);
	    	//错误处理
        	iRet = ERR;
			goto EXIT;
		}
		#if 0		
		else if(0 == iRet) 
		{  
	    	//超时处理
	   		close(_pConnection->m_iSocKet);		
	   		_pConnection->m_iSocKet = INVALID_SOCKET;
			
        	iRet = ERR;
			goto leave;
		}
		#endif		
		else 
		{
			if(2 == iRet) 
			{  
				int iErr;
				int iLen = sizeof(iErr); 
				getsockopt(_ptNetWorkMsg->m_iSocket, SOL_SOCKET, SO_ERROR, &iErr, (socklen_t*)&iLen); 

				if(iErr) 
				{ 
					//dbg();
					dbgint(errno);
					//超时处理
					iRet = ERR;
					goto EXIT;
				} 
			}	
			
		    //套接字已经准备好
    		if(_ptNetWorkMsg->m_iSocket < 0)
    		{
    			dbg();
				dbgint(errno);
				iRet = ERR;
				goto EXIT;
    		}
			
    		if(!FD_ISSET(_ptNetWorkMsg->m_iSocket, &rdevents) && !FD_ISSET(_ptNetWorkMsg->m_iSocket, &wrevents)) 
			{
				dbg();
				dbgint(errno);
		      	iRet = ERR;
				goto EXIT;
	    	}
		
  	 		if (getsockopt(_ptNetWorkMsg->m_iSocket, SOL_SOCKET, SO_ERROR, &iRet, &sLen) < 0)
	   		{
				//perror("getsockopt ");
				dbg();
				dbgint(errno);
	   		}

			#if 0
	   		if (iRet != 0) 
	   		{
				dbg();
			}
			#endif
			
	   		if(2 == iRet)
	   		{
	   			dbg();
				dbgint(errno);
				iRet = ERR;
				goto EXIT;
	   		}

			//到这里说明connect()正确返回
			
		}
	}

	
	iRet = OK;
	
	set_socket_nonblock(_ptNetWorkMsg->m_iSocket);

	#if 0
	iRet = epoll_add_connection(_ptConnection, 1);

	if(iRet!=0)
	{
		iRet = ERR;
		goto EXIT;	  
	}
	#endif
	 
EXIT:	
	if(OK != iRet && INVALID_SOCKET != _ptNetWorkMsg->m_iSocket)
	{
		//dbg();
		close(_ptNetWorkMsg->m_iSocket);
		_ptNetWorkMsg->m_iSocket = INVALID_SOCKET;
	}
	
	return iRet;
}
Esempio n. 4
0
/*
 * pconn: client --> proxy, its buffer isn't NULL
 */
int read_client_handle( conn_t *pconn )
{
	log_message( LOG_DEBUG, "in read_client_handle" );

	int ret;
	char ip[100];				//有可能不是ip
	uint16_t	port;

	if ( 1 == pconn->read_closed ) {		//因为某种原因不想读取client数据了
		log_message( LOG_WARNING, "try reading from client[%s], but it closed read", inet_ntoa( pconn->addr.sin_addr ) );
		return -1;							
	}

	ret = read_buffer( pconn->fd, pconn->read_buffer );
	log_message( LOG_DEBUG, "read %d bytes from client[%s:%d].", ret, inet_ntoa(pconn->addr.sin_addr), ntohs(pconn->addr.sin_port) );

	if ( g_errno <= 0 ) {		//read occur error, or closed
		log_message( LOG_CONN, "read occur error, close read from client[%s:%d].", inet_ntoa(pconn->addr.sin_addr), ntohs(pconn->addr.sin_port) );
		CONN_CLOSE_READ( pconn );

		/**
		 *  client关闭写,并且buffer没有数据了,proxy也要关闭server的写
		 *  write_server的事情
		 *  发现问题了,这里要判断是否删除pconn->server_conn
		 */
		if ( NULL != pconn->server_conn && 0 == buffer_size( pconn->read_buffer ) ) {
			CONN_CLOSE_WRITE( pconn->server_conn );

			if ( 1 == pconn->server_conn->read_closed ) {		//very important
				epoll_del_connection( pconn->server_conn );
				release_conns_slot( pconn->server_conn );
			}
		}
		/**
		 *  当客户端关闭写,并且没有VM,(或者VM关闭写并且buffer空了,这时就该关闭连接)--write_client_handle有处理
		 */
		if ( 1 == pconn->write_closed || NULL == pconn->server_conn )
			return -1;			//删除pconn
	}

	/**
	 * 这个很重要,不然容易导致工作进程突然死掉
	 */
	if ( /*1 == pconn->read_closed &&*/ 0 == buffer_size( pconn->read_buffer ) ) {
		//return 0;		//没有数据,不需要进入下一步
		goto CLIENT_EPOLLSET;
	}

	/**
	 *  处理读取的数据
	 */

	if ( NULL == pconn->server_conn || 
      //the fd connection to server has been reused by another client.
	  //maybe has some potential problem.
		pconn->server_conn->server_conn != pconn ) {

		memset( ip, 0, sizeof(ip) );

		//抽取VM IP:port,并重写url 需要再次修改这段代码
		ret = extract_ip_buffer(pconn->read_buffer, ip, sizeof(ip), &port);
		if ( ret < 0 ) {
			log_message( LOG_WARNING, "extract_ip_buffer not find vm ip:port" );
			//return 0;				//等待新的数据到来
			goto CLIENT_EPOLLSET;
		}

		int fd;	
		struct sockaddr_in	addr;

NEWCONN:
		fd = open_client_socket( &addr, ip, port );
		if ( fd < 0 ) {
			//发送error.html
			log_message( LOG_WARNING, "conn to Vm[%s:%d] failed.", ip, port );

			if ( '\0' == ip[0] || 0 == port ) {			//just for test
				char tmp[1024];
				memset( tmp, 0, sizeof(tmp) );
				memcpy( tmp, BLOCK_SENDADDR(pconn->read_buffer->head), 100 );
				log_message( LOG_ERROR, "ip error:%s", tmp );
			}

			if ( send_error_html( pconn->write_buffer ) < 0 )
				return -1;				//需要修改epll
			goto CLIENT_EPOLLSET;
		}
		
		conn_t * server_conn;
		server_conn = get_conns_slot();
		if ( NULL == server_conn ) {
			log_message( LOG_WARNING, "conn slot full." );
			if ( send_slot_full( pconn->write_buffer ) < 0 )
				return -1;				//需要修改epll
			goto CLIENT_EPOLLSET;
		}
		server_conn->fd = fd;
		server_conn->read_handle = read_server_handle;
		server_conn->write_handle = write_server_handle;
		server_conn->type = C_SERVER;
		server_conn->server_conn = pconn;
		server_conn->read_buffer = pconn->write_buffer;
		server_conn->write_buffer = pconn->read_buffer;
		server_conn->addr = addr;
		pconn->server_conn = server_conn;	

		log_message( LOG_CONN, "client[%s:%d] conn to Vm[%s:%d:%d]\n", inet_ntoa(pconn->addr.sin_addr), ntohs(pconn->addr.sin_port), ip, port, fd );

		epoll_add_connection( server_conn, EPOLLIN|EPOLLOUT );
	}
	else {			//这里假设http请求可以一次读完,以后需要再次修改

		 //rewrite URL in request
		ret = extract_ip_buffer(pconn->read_buffer, ip, sizeof(ip), &port);
		if ( ret < 0 ) {		//表示没有请求行或是格式出错
		
			epoll_mod_connection( pconn->server_conn, EPOLLIN );	//等待server读事件
			log_message( LOG_ERROR, "extract_ip_buffer error, just rewrite url." );
			//return 0;			//没有加入epollout中,因为需要等待更多数据的到来
			goto CLIENT_EPOLLSET;
		}

		//判断当前server是否与url中的vm匹配,如果不匹配,则需要把整个连接删除
		// ip=0, 表示符合格式,但是没有包含vm:port,有可能已经删除过了
		if ( '\0' != ip[0] && 0 != strcasecmp( ip, 
					inet_ntoa(pconn->server_conn->addr.sin_addr) ) ) {
			epoll_del_connection( pconn->server_conn );
			release_conns_slot( pconn->server_conn );
			pconn->server_conn = NULL;
			//log_message( LOG_ERROR, "hp, goto NEWCOM" );
			goto NEWCONN;		//与新的vm创建连接
		}

		epoll_mod_connection( pconn->server_conn, EPOLLIN|EPOLLOUT );
	}

	/*
	 * it's very important
	 */
	uint32_t clientf = 0;
CLIENT_EPOLLSET:
	if ( 0 == pconn->write_closed && buffer_size( pconn->write_buffer ) > 0 )
		clientf |= EPOLLOUT;
	if ( 0 == pconn->read_closed && buffer_size( pconn->read_buffer ) < MAXBUFFSIZE )
		clientf |= EPOLLIN;
	epoll_mod_connection( pconn, clientf );

	return 0;
}