コード例 #1
0
void CSSLClientAsync::UnInitSSL()
{
    if (m_ssl)
    {
        int32_t nRet = SSL_shutdown(m_ssl);
        if (nRet == 0)
        {
            int32_t nErrorCode = SSL_get_error(GetSSL(), nRet);
            SOCKET_IO_WARN("ssl shutdown not finished, errno: %d.", nErrorCode);

        }
        else if (nRet == 1)
        {
            SOCKET_IO_DEBUG("ssl shutdown successed.");
        }
        else if (nRet < 0)
        {
            int32_t nErrorCode = SSL_get_error(GetSSL(), nRet);
            SOCKET_IO_ERROR("ssl shutdown failed, errno: %d.", nErrorCode);
        }
        SSL_free(m_ssl);
        m_ssl = NULL;
    }
    if (m_ctx)
    {
        SSL_CTX_free(m_ctx);
        m_ctx = NULL;
    }
}
コード例 #2
0
void CSSLClientAsync::OnRecv()
{
    if (GetSSLConnectStatus() == TRUE)
    {
        char szBuf[TCP_RECV_SIZE] = {0};
        int32_t nRet = SSL_read(GetSSL(), szBuf, TCP_RECV_SIZE);
        if (nRet > 0)
        {
            int32_t nBufSize = nRet;
            char szIP[32] = {0};
            int32_t nPort = 0;
            S_GetPeerName(GetSocket(), szIP, &nPort);
            DoRecv(GetSocketID(), szBuf, nBufSize, szIP, nPort);
        }
        else if (nRet == 0)
        {
            int32_t nErrorCode = SSL_get_error(GetSSL(), nRet);
            if (SSL_ERROR_ZERO_RETURN == nErrorCode)
            {
                //对方关闭socket
                SOCKET_IO_WARN("recv ssl data error, peer closed.");
                DoException(GetSocketID(), SOCKET_IO_SSL_RECV_FAILED);
            }
            else
            {
                SOCKET_IO_ERROR("recv ssl data error.");
                DoException(GetSocketID(), SOCKET_IO_SSL_RECV_FAILED);
            }
        }
        else
        {
            int32_t nErrorCode = SSL_get_error(GetSSL(), nRet);
            if (SSL_ERROR_WANT_READ == nErrorCode || SSL_ERROR_WANT_WRITE == nErrorCode)
            {
                //用select/epoll/iocp的方式应该很少会有这个情况出现
                SOCKET_IO_DEBUG("recv ssl data error, buffer is blocking.");
            }
            else
            {
                SOCKET_IO_ERROR("recv ssl data error, errno: %d.", nErrorCode);
                DoException(GetSocketID(), SOCKET_IO_SSL_RECV_FAILED);
            }
        }
    }
    else
    {
        SSLConnect();
    }
}
コード例 #3
0
void CSSLClientAsync::_Close()
{
    if (m_ssl)
    {
        UnInitSSL();
    }
    if (GetSocket() != S_INVALID_SOCKET)
    {
        if (m_pio)
        {
            m_pio->Remove_Handler(this);
        }
        SetSSLConnectStatus(FALSE);
        S_CloseSocket(GetSocket());
        SOCKET_IO_WARN("close ssl socket, sock %d, real sock: %d.", GetSocketID(), GetSocket());
        m_socket = S_INVALID_SOCKET;
        DoClose(GetSocketID());
        _ClearSendBuffer();
    }
}
コード例 #4
0
int32_t CSSLClientAsync::SSLConnect()
{
    int32_t nErrorCode = SOCKET_IO_SSL_CONNECT_FAILED;
    
    //阻塞的ssl_connect可能会有一个问题,服务端如果不对此处理,可能会一直卡在SSL_connect这个接口
    //此处采用非阻塞的ssl_connect
    int32_t nRet = SSL_connect(GetSSL());
    if (nRet == 1)
    {
        nErrorCode = SOCKET_IO_RESULT_OK;
        SOCKET_IO_INFO("ssl connect successed, remote ip: %s, port: %d.", GetRemoteIP(), GetRemotePort());
        SetSSLConnectStatus(TRUE);
        DoSSLConnect(GetSocket());
    }
    else if (nRet == 0)
    {
        int32_t ssl_error_code = SSL_get_error(GetSSL(), nRet);
        SOCKET_IO_ERROR("ssl connect was shut down, remote ip: %s, port: %d, error code: %d.",
                        GetRemoteIP(), GetRemotePort(), ssl_error_code);
        DoException(GetSocketID(), SOCKET_IO_SSL_CONNECT_FAILED);
    }
    else
    {
        int32_t ssl_error_code = SSL_get_error(GetSSL(), nRet);
        if (SSL_ERROR_WANT_READ == ssl_error_code || SSL_ERROR_WANT_WRITE == ssl_error_code)
        {
            SOCKET_IO_WARN("ssl connect is blocking, remote ip: %s, port: %d, error code: %d.",
                           GetRemoteIP(), GetRemotePort(), ssl_error_code);
        }
        else
        {
            SOCKET_IO_ERROR("ssl connect failed, remote ip: %s, port: %d, error code: %d.",
                            GetRemoteIP(), GetRemotePort(), ssl_error_code);
            DoException(GetSocketID(), SOCKET_IO_SSL_CONNECT_FAILED);
        }
    }
    return nErrorCode;
}
コード例 #5
0
ファイル: epoll_io_loop.cpp プロジェクト: 8521470/TeamTalk
/**	@fn	void CEpollIOLoop::Run()
*	@brief 
*	@return	
*/
void CEpollIOLoop::Run()
{
	struct epoll_event ev;
	ev.data.fd=m_waker.GetWakeSocket();
	//设置要处理的事件类型
	ev.events=EPOLLIN;
	epoll_ctl(m_eid, EPOLL_CTL_ADD, m_waker.GetWakeSocket(), &ev);

	while (TRUE)
	{
		struct epoll_event* events = new epoll_event[_GetEpollSize()];
		int32_t nfds = epoll_wait(m_eid, events, _GetEpollSize(), -1);
		if (nfds <= 0)
			continue;
		for (int32_t i = 0; i < nfds; i++)
		{
			S_SOCKET sock = events[i].data.fd;
			if (sock == m_waker.GetWakeSocket())
			{
				m_waker.Recv();
			}
			else if (events[i].events & EPOLLIN)
			{
				CBaseIOStream* pIOStream = _GetHandlerBySock(sock);
				if (pIOStream != NULL)
				{
					if (pIOStream->GetSockType() == SOCK_TCP_SERVER)
					{
						pIOStream->OnAccept();
					}
					else
					{
						pIOStream->OnRecv();
                        SOCKET_IO_TRACE("socket recv data, sock id: %d.", pIOStream->GetSocketID());
					}
				}
				else
				{
					//调试的时候可能数据还没读,但是对象已经没了,需要清掉
					//epoll也会在调用close(sock)后会自己清除。
					epoll_ctl(m_eid, EPOLL_CTL_DEL, sock, &events[i]);
				}
			}//EPOLLIN
			else if (events[i].events & EPOLLOUT)
			{
				CBaseIOStream* pIOStream = _GetHandlerBySock(sock);
				if (pIOStream != NULL)
				{
					if (pIOStream->GetSockType() == SOCK_TCP_CLIENT && pIOStream->CheckConnect())
					{
						//连接成功
						pIOStream->OnConnect(TRUE);
					}
					pIOStream->SendBufferAsync();
				}
			}//EPOLLOUT
			else if (events[i].events & EPOLLERR)
			{
				CBaseIOStream* pIOStream = _GetHandlerBySock(sock);
				if (pIOStream->GetSockType() == SOCK_TCP_CLIENT && pIOStream->CheckConnect())
				{
					int32_t nError, nCode;
					socklen_t nLen; 
					nLen = sizeof(nError);     
					nCode = getsockopt(pIOStream->GetSocket(), SOL_SOCKET, SO_ERROR, &nError, &nLen);
					if (nCode < 0 || nError) 
					{     
						//连接失败
						SOCKET_IO_WARN("socket connect failed, nCode: %d, nError: %d.", nCode, nError);
						pIOStream->OnConnect(FALSE);
					}
				}
			}//EPOLLERR
		}
	}
}
コード例 #6
0
ファイル: io_loop.cpp プロジェクト: hlyces/teamtalk_TT
/**	@fn	void CIOLoop::Run()
*	@brief 
*	@return	
*/
void CIOLoop::Run()
{
	fd_set fd_read, fd_write, fd_error;
	while (m_bCloseRequest == FALSE)
	{
		int nMaxfd = 0;
		FD_ZERO(&fd_read);
		FD_ZERO(&fd_write);
		FD_ZERO(&fd_error);
		FD_SET(m_waker.GetWakeSocket(), &fd_read);
		if(m_waker.GetWakeSocket() > nMaxfd) 
			nMaxfd = m_waker.GetWakeSocket();
		m_MapMutex.Lock();
		map<S_SOCKET, CBaseIOStream*> mapTmp = m_MapIOStreamBySocket;
		m_MapMutex.Unlock();
		map<S_SOCKET, CBaseIOStream*>::iterator it = mapTmp.begin();
		for (; it != mapTmp.end(); it++)
		{
			CBaseIOStream* pIOStream = it->second;
			if (pIOStream->CheckConnect() == FALSE)
			{
				//如果是要检查TCP CLIENT是否连接,则不设置可读
				FD_SET(it->first, &fd_read);
				if(it->first > nMaxfd) 
					nMaxfd = it->first;
			}
			if (pIOStream->CheckWrite() == TRUE)
			{
				//设置可写
				FD_SET(it->first, &fd_write);
				if(it->first > nMaxfd) 
					nMaxfd = it->first;
				//设置错误信号,用于windows的tcp connect超时检查,同时查看是否有其他触发错误
				FD_SET(it->first, &fd_error);
			}
		}
		timeval tv;
		tv.tv_sec = 1;
		tv.tv_usec = 0;
		int nRet = select(nMaxfd + 1, &fd_read, &fd_write, &fd_error, NULL);
		if (nRet > 0)
		{
			if (FD_ISSET(m_waker.GetWakeSocket(), &fd_read))
			{
				//stop
				m_waker.Recv();
			}
			map<S_SOCKET, CBaseIOStream*>::iterator it1 = mapTmp.begin();
			for (; it1 != mapTmp.end(); it1++)
			{
				//read
				if (FD_ISSET(it1->first, &fd_read))
				{
					CBaseIOStream* pIOStream = _GetHandlerBySock(it1->first);
					if (pIOStream != NULL)
					{
						if (pIOStream->GetSockType() == SOCK_TCP_SERVER)
						{
							pIOStream->OnAccept();
						}
						else
						{
							pIOStream->OnRecv();
						}	
					}
				}//read
				//write
				if (FD_ISSET(it1->first, &fd_write))
				{
					CBaseIOStream* pIOStream = _GetHandlerBySock(it1->first);
					if (pIOStream != NULL)	
					{
						if (pIOStream->GetSockType() == SOCK_TCP_CLIENT && pIOStream->CheckConnect())
						{
#if (defined(_WIN32) || defined(_WIN64))
							pIOStream->OnConnect(TRUE);
//#elif defined(__linux__) //mac???
#else
							//这个是unix的处理方式,经测试linux也适用,mac同理
							int32_t nError, nCode;
							socklen_t nLen; 
							nLen = sizeof(nError);     
							nCode = getsockopt(pIOStream->GetSocket(), SOL_SOCKET, SO_ERROR, &nError,
                                               &nLen);
							if (nCode < 0 || nError) 
							{     
								//连接失败
								//linux的超时失败是也是根据这个可以判断
								SOCKET_IO_WARN("socket connect failed, nCode: %d, nError: %d.", nCode,
                                               nError);
								pIOStream->OnConnect(FALSE);
							}
							else
							{
								//连接成功
								//SOCKET_IO_WARN("socket connect successed.", nCode, nError);
								pIOStream->OnConnect(TRUE);
							}
#endif
						}
						pIOStream->SendBufferAsync();
					}
				}//wirte
				//error
				if (FD_ISSET(it1->first, &fd_error))
				{
					CBaseIOStream* pIOStream = _GetHandlerBySock(it1->first);
					if (pIOStream != NULL)
					{
						//windows的超时判断是利用err_fds来判断
						//对于不存在的IP(即linux会报111错误),或者IP存在,端口不存在(即linux会报110错误)
						//都是超时错误
						if (pIOStream->CheckConnect() == TRUE)
						{
							SOCKET_IO_WARN("socket connect time out, remote ip: %s, port: %d.",
                                           pIOStream->GetRemoteIP(), pIOStream->GetRemotePort());
							pIOStream->OnConnect(FALSE);
						}
						else
						{
							SOCKET_IO_WARN("err_fds, %d.", (int32_t)pIOStream->GetSockType());
						}
					}
				}//error
			}//for
		}// nRet > 0
		else if (0 == nRet)
		{
			//Time Out
			//map<HPR_SOCK_T, CBaseIOStream*>::iterator it1 = mapTmp.begin();
			//for (; it1 != mapTmp.end(); it1++)
			//{
			//	//write
			//	CBaseIOStream* pIOStream = _GetHandlerBySock(it1->first);
			//	if (pIOStream != NULL)
			//	{
			//		if (pIOStream->GetSockType() == SOCK_TCP_CLIENT && pIOStream->CheckConnect())
			//		{
			//		}
			//	}
			//}
		}
		else
		{
			//TODO
			//Error
			SOCKET_IO_ERROR("socket select error");
            break;
		}
	}
}
コード例 #7
0
int32_t CSSLClientAsync::SendBufferAsync()
{
    int32_t nErrorCode = SOCKET_IO_RESULT_OK;
    m_sendqueuemutex.Lock();
    if (m_sendqueue.size() == 0)
    {
        SOCKET_IO_DEBUG("ssl send queue is empty.");
        //待发送队列中为空,则删除写事件的注册,改成读事件
        m_pio->Remove_WriteEvent(this);
        m_sendqueuemutex.Unlock();
        if (_GetWaitForCloseStatus() == TRUE)
        {
            //待发送内容发送完毕,则关闭链接
            _Close();
        }
        return nErrorCode;
    }
    CSimpleBuffer* pBufferLoop = m_sendqueue.front();
    m_sendqueuemutex.Unlock();
    int32_t nRet = SSL_write(GetSSL(), (void*)pBufferLoop->GetBuffer(), pBufferLoop->GetWriteOffset());
    if ( nRet < 0)
    {
        int32_t nError = SSL_get_error(GetSSL(), nRet);
        if (SSL_ERROR_WANT_WRITE == nError || SSL_ERROR_WANT_READ == nError)
        {
            SOCKET_IO_INFO("send ssl data, buffer is blocking, errno: %d.", nError);
        }
        else
        {
            _ClearSendBuffer();
            SOCKET_IO_ERROR("send ssl data error, errno: %d.", nError);
            DoException(GetSocketID(), SOCKET_IO_SSL_SEND_FAILED);
        }
    }
    else if (nRet == 0)
    {
        int32_t nError = SSL_get_error(GetSSL(), nRet);
        if (SSL_ERROR_ZERO_RETURN == nError)
        {
            SOCKET_IO_WARN("send ssl data error, peer closed.");
        }
        else
        {
            SOCKET_IO_ERROR("send ssl data error, errno: %d.", nError);
        }
        _ClearSendBuffer();
        DoException(GetSocketID(), SOCKET_IO_SSL_SEND_FAILED);
    }
    else if (nRet != pBufferLoop->GetWriteOffset())
    {
        //将未成功的数据重新放置buffer loop中,待下次发送
        //对于ssl来说,应该不会出现此种情况
        int32_t nSize = 0;
        pBufferLoop->Read(NULL, nRet);
        SOCKET_IO_WARN("send ssl data, send size: %d, less than %d.", nRet, pBufferLoop->GetWriteOffset());
    }
    else
    {
        SOCKET_IO_INFO("send ssl data from buffer successed.");
        m_sendqueuemutex.Lock();
        delete pBufferLoop;
        pBufferLoop = NULL;
        m_sendqueue.pop();
        m_sendqueuemutex.Unlock();
    }
    return nErrorCode;
}
コード例 #8
0
int32_t CSSLClientAsync::SendMsgAsync(const char *szBuf, int32_t nBufSize)
{
    CSimpleBuffer* pBufferLoop = new CSimpleBuffer();
    pBufferLoop->Write(szBuf, nBufSize);
    
    m_sendqueuemutex.Lock();
    if (m_sendqueue.size() != 0)
    {
        if (_GetWaitForCloseStatus() == TRUE)
        {
            SOCKET_IO_DEBUG("send ssl data error, socket will be closed.");
            delete pBufferLoop;
            pBufferLoop = NULL;
        }
        else
        {
            if (m_sendqueue.size() >= MAX_SEND_QUEUE_SIZE) {
                SOCKET_IO_WARN("send ssl data error, buffer is overload.");
                delete pBufferLoop;
                pBufferLoop = NULL;
            }
            else
            {
                SOCKET_IO_INFO("send ssl data, push data to buffer.");
                m_sendqueue.push(pBufferLoop);
                //m_pio->Add_WriteEvent(this);
            }
        }
        m_sendqueuemutex.Unlock();
        return SOCKET_IO_RESULT_OK;
    }
    m_sendqueuemutex.Unlock();
    
    int32_t nRet = SSL_write(GetSSL(), (void*)pBufferLoop->GetBuffer(), pBufferLoop->GetWriteOffset());
    if ( nRet < 0)
    {
        int32_t nError = SSL_get_error(GetSSL(), nRet);
        if (SSL_ERROR_WANT_WRITE == nError || SSL_ERROR_WANT_READ == nError)
        {
            m_sendqueuemutex.Lock();
            m_sendqueue.push(pBufferLoop);
            m_sendqueuemutex.Unlock();
            //有数据放入待发送队列,则注册为写事件
            m_pio->Add_WriteEvent(this);
            SOCKET_IO_INFO("send ssl data, buffer is blocking, errno: %d.", nError);
        }
        else
        {
            delete pBufferLoop;
            pBufferLoop = NULL;
            SOCKET_IO_ERROR("send ssl data error, errno: %d.", nError);
            DoException(GetSocketID(), SOCKET_IO_SSL_SEND_FAILED);
        }
    }
    else if (nRet == 0)
    {
        int32_t nError = SSL_get_error(GetSSL(), nRet);
        if (SSL_ERROR_ZERO_RETURN == nError)
        {
            SOCKET_IO_WARN("send ssl data error, peer closed.");
        }
        else
        {
            SOCKET_IO_ERROR("send ssl data error, errno: %d.", nError);
        }
        delete pBufferLoop;
        pBufferLoop = NULL;
        DoException(GetSocketID(), SOCKET_IO_SSL_SEND_FAILED);
    }
    else if (nRet != nBufSize)
    {
        int32_t nRest = nBufSize - nRet;
        pBufferLoop->Read(NULL, nRet);
        m_sendqueuemutex.Lock();
        m_sendqueue.push(pBufferLoop);
        m_sendqueuemutex.Unlock();
        //有数据放入待发送队列,则注册为写事件
        //对于ssl来说,应该不会出现此种情况
        m_pio->Add_WriteEvent(this);
        SOCKET_IO_WARN("send ssl data, send size: %d, less than %d.", nRet, nBufSize);
    }
    else if (nRet == nBufSize)
    {
        delete pBufferLoop;
        pBufferLoop = NULL;
        SOCKET_IO_DEBUG("send ssl data successed.");
    }
    else
    {
        delete pBufferLoop;
        pBufferLoop = NULL;
    }
    return SOCKET_IO_RESULT_OK;
}