void CTcpServer::HandleReceive(CONNID dwConnID, TSocketObj* pSocketObj, TBufferObj* pBufferObj) { if(m_bMarkSilence) pSocketObj->activeTime = ::TimeGetTime(); EnHandleResult hr = TriggerFireReceive(pSocketObj, pBufferObj); if(hr == HR_OK || hr == HR_IGNORE) { if(ContinueReceive(pSocketObj, pBufferObj, hr)) { { CSpinLock locallock(pSocketObj->sgPause); pSocketObj->recving = FALSE; } DoReceive(pSocketObj, pBufferObj); } } if(hr == HR_CLOSED) { AddFreeBufferObj(pBufferObj); } else if(hr == HR_ERROR) { TRACE("<S-CNNID: %Iu> OnReceive() event return 'HR_ERROR', connection will be closed !\n", dwConnID); AddFreeSocketObj(pSocketObj, SCF_ERROR, SO_RECEIVE, ENSURE_ERROR_CANCELLED); AddFreeBufferObj(pBufferObj); } }
void CTcpServer::HandleAccept(SOCKET soListen, TBufferObj* pBufferObj) { VERIFY(::PostIocpAccept(m_hCompletePort)); int iLocalSockaddrLen; int iRemoteSockaddrLen; HP_PSOCKADDR pLocalSockAddr; HP_PSOCKADDR pRemoteSockAddr; int iAddrLen = HP_SOCKADDR::AddrSize(m_usFamily) + 16; m_pfnGetAcceptExSockaddrs ( pBufferObj->buff.buf, 0, iAddrLen, iAddrLen, (SOCKADDR**)&pLocalSockAddr, &iLocalSockaddrLen, (SOCKADDR**)&pRemoteSockAddr, &iRemoteSockaddrLen ); CONNID dwConnID = 0; SOCKET socket = pBufferObj->client; if(!HasStarted() || !m_bfActiveSockets.AcquireLock(dwConnID)) { ::ManualCloseSocket(socket, SD_BOTH); AddFreeBufferObj(pBufferObj); return; } TSocketObj* pSocketObj = GetFreeSocketObj(dwConnID, socket); pRemoteSockAddr->Copy(pSocketObj->remoteAddr); AddClientSocketObj(dwConnID, pSocketObj); ::SSO_UpdateAcceptContext(socket, soListen); ::CreateIoCompletionPort((HANDLE)socket, m_hCompletePort, (ULONG_PTR)pSocketObj, 0); if(TriggerFireAccept(pSocketObj) != HR_ERROR) DoReceive(pSocketObj, pBufferObj); else { AddFreeSocketObj(pSocketObj, SCF_NONE); AddFreeBufferObj(pBufferObj); } }
int CTcpAgent::SendDirect(TSocketObj* pSocketObj, const BYTE* pBuffer, int iLength) { int result = NO_ERROR; int iRemain = iLength; while(iRemain > 0) { int iBufferSize = min(iRemain, (int)m_dwSocketBufferSize); TBufferObj* pBufferObj = GetFreeBufferObj(iBufferSize); memcpy(pBufferObj->buff.buf, pBuffer, iBufferSize); result = ::PostSend(pSocketObj, pBufferObj); if(result != NO_ERROR) { AddFreeBufferObj(pBufferObj); break; } iRemain -= iBufferSize; pBuffer += iBufferSize; } if(result != NO_ERROR) CheckError(pSocketObj->connID, SO_SEND, result); return result; }
int CTcpAgent::SendItem(TSocketObj* pSocketObj) { int result = NO_ERROR; while(pSocketObj->sndBuff.Size() > 0) { ::InterlockedIncrement(&pSocketObj->sndCount); TBufferObj* pBufferObj = pSocketObj->sndBuff.PopFront(); int iBufferSize = pBufferObj->buff.len; ASSERT(iBufferSize > 0 && iBufferSize <= (int)m_dwSocketBufferSize); pSocketObj->pending -= iBufferSize; result = ::PostSendNotCheck(pSocketObj, pBufferObj); if(result != NO_ERROR) { if(result != WSA_IO_PENDING) AddFreeBufferObj(pBufferObj); break; } } return result; }
int CTcpAgent::SendItem(TSocketObj* pSocketObj) { int result = NO_ERROR; while(pSocketObj->sndBuff.Size() > 0) { ::InterlockedIncrement(&pSocketObj->sndCount); TItemPtr itPtr(m_itPool, pSocketObj->sndBuff.PopFront()); int iBufferSize = itPtr->Size(); ASSERT(iBufferSize > 0 && iBufferSize <= (int)m_dwSocketBufferSize); pSocketObj->pending -= iBufferSize; TBufferObj* pBufferObj = GetFreeBufferObj(iBufferSize); memcpy(pBufferObj->buff.buf, itPtr->Ptr(), iBufferSize); result = ::PostSendNotCheck(pSocketObj, pBufferObj); if(result != NO_ERROR) { if(result != WSA_IO_PENDING) AddFreeBufferObj(pBufferObj);; break; } } return result; }
void CTcpAgent::HandleIo(CONNID dwConnID, TSocketObj* pSocketObj, TBufferObj* pBufferObj, DWORD dwBytes, DWORD dwErrorCode) { ASSERT(pBufferObj != nullptr); ASSERT(pSocketObj != nullptr); if(dwErrorCode != NO_ERROR) { HandleError(dwConnID, pBufferObj, dwErrorCode); return; } if(dwBytes == 0 && pBufferObj->operation != SO_CONNECT) { AddFreeSocketObj(dwConnID, SCF_CLOSE); AddFreeBufferObj(pBufferObj); return; } pBufferObj->buff.len = dwBytes; switch(pBufferObj->operation) { case SO_CONNECT: HandleConnect(dwConnID, pSocketObj, pBufferObj); break; case SO_SEND: HandleSend(dwConnID, pSocketObj, pBufferObj); break; case SO_RECEIVE: HandleReceive(dwConnID, pSocketObj, pBufferObj); break; default: ASSERT(FALSE); } }
int CTcpServer::DoSend(CONNID dwConnID, TSocketObj* pSocketObj, const BYTE* pBuffer, int iLen) { int result = NO_ERROR; int iRemain = iLen; CCriSecLock locallock(pSocketObj->crisec); while(iRemain > 0) { int iBufferSize = min(iRemain, (int)m_dwSocketBufferSize); TBufferObj* pBufferObj = GetFreeBufferObj(iBufferSize); memcpy(pBufferObj->buff.buf, pBuffer, iBufferSize); result = ::PostSend(pSocketObj, pBufferObj); if(result != NO_ERROR) { AddFreeBufferObj(pBufferObj); break; } iRemain -= iBufferSize; pBuffer += iBufferSize; } return result; }
EnHandleResult CTcpServer::TriggerFireSend(TSocketObj* pSocketObj, TBufferObj* pBufferObj) { EnHandleResult rs = (EnHandleResult)HR_CLOSED; if(m_enOnSendSyncPolicy == OSSP_NONE) rs = TRIGGER(FireSend(pSocketObj, (BYTE*)pBufferObj->buff.buf, pBufferObj->buff.len)); else { ASSERT(m_enOnSendSyncPolicy >= OSSP_CLOSE && m_enOnSendSyncPolicy <= OSSP_RECEIVE); if(TSocketObj::IsValid(pSocketObj)) { CCriSecLock locallock(m_enOnSendSyncPolicy == OSSP_CLOSE ? pSocketObj->csSend : pSocketObj->csRecv); if(TSocketObj::IsValid(pSocketObj)) { rs = TRIGGER(FireSend(pSocketObj, (BYTE*)pBufferObj->buff.buf, pBufferObj->buff.len)); } } } if(rs == HR_ERROR) { TRACE("<S-CNNID: %Iu> OnSend() event should not return 'HR_ERROR' !!\n", pSocketObj->connID); ASSERT(FALSE); } if(pBufferObj->ReleaseSendCounter() == 0) AddFreeBufferObj(pBufferObj); return rs; }
BOOL CTcpServer::ContinueReceive(TSocketObj* pSocketObj, TBufferObj* pBufferObj, EnHandleResult& hr) { int rs = NO_ERROR; for(int i = 0; i < MAX_IOCP_CONTINUE_RECEIVE || MAX_IOCP_CONTINUE_RECEIVE < 0; i++) { if(hr != HR_OK && hr != HR_IGNORE) break; if(pBufferObj->buff.len != m_dwSocketBufferSize) break; pBufferObj->buff.len = m_dwSocketBufferSize; rs =::NoBlockReceiveNotCheck(pBufferObj); if(rs != NO_ERROR) break; hr = TriggerFireReceive(pSocketObj, pBufferObj); } if(rs != NO_ERROR && rs != WSAEWOULDBLOCK) { if(rs == WSAEDISCON) AddFreeSocketObj(pSocketObj, SCF_CLOSE); else CheckError(pSocketObj, SO_RECEIVE, rs); AddFreeBufferObj(pBufferObj); return FALSE; } return TRUE; }
int CTcpServer::SendItem(TSocketObj* pSocketObj) { int result = NO_ERROR; while(pSocketObj->sndBuff.Size() > 0) { TBufferObj* pBufferObj = pSocketObj->sndBuff.PopFront(); int iBufferSize = pBufferObj->buff.len; ASSERT(iBufferSize > 0 && iBufferSize <= (int)m_dwSocketBufferSize); pSocketObj->pending -= iBufferSize; ::InterlockedExchangeAdd(&pSocketObj->sndCount, iBufferSize); result = ::PostSendNotCheck(pSocketObj, pBufferObj); LONG sndCounter = pBufferObj->ReleaseSendCounter(); if(sndCounter == 0 || !IOCP_SUCCESS(result)) AddFreeBufferObj(pBufferObj); if(result != NO_ERROR) break; } return result; }
int CTcpServer::SendDirect(TSocketObj* pSocketObj, const BYTE* pBuffer, int iLength) { int result = NO_ERROR; int iRemain = iLength; while(iRemain > 0) { int iBufferSize = min(iRemain, (int)m_dwSocketBufferSize); TBufferObj* pBufferObj = GetFreeBufferObj(iBufferSize); memcpy(pBufferObj->buff.buf, pBuffer, iBufferSize); ::InterlockedExchangeAdd(&pSocketObj->pending, iBufferSize); result = ::PostSend(pSocketObj, pBufferObj); LONG sndCounter = pBufferObj->ReleaseSendCounter(); if(sndCounter == 0 || result != NO_ERROR) { AddFreeBufferObj(pBufferObj); if(result != NO_ERROR) { ::InterlockedExchangeAdd(&pSocketObj->pending, -iBufferSize); break; } } iRemain -= iBufferSize; pBuffer += iBufferSize; } return result; }
int CTcpServer::DoReceive(TSocketObj* pSocketObj, TBufferObj* pBufferObj) { int result = NO_ERROR; BOOL bNeedFree = FALSE; { CSpinLock locallock(pSocketObj->sgPause); if(pSocketObj->paused || pSocketObj->recving) bNeedFree = TRUE; else { pSocketObj->recving = TRUE; pBufferObj->buff.len = m_dwSocketBufferSize; result = ::PostReceive(pSocketObj, pBufferObj); } } if(result != NO_ERROR) { CheckError(pSocketObj, SO_RECEIVE, result); bNeedFree = TRUE; } if(bNeedFree) AddFreeBufferObj(pBufferObj); return result; }
BOOL CTcpServer::DoAccept() { BOOL isOK = FALSE; if(HasStarted()) { SOCKET soClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); TBufferObj* pBufferObj = GetFreeBufferObj(); ASSERT(soClient != INVALID_SOCKET); isOK = (::PostAccept(m_pfnAcceptEx, m_soListen, soClient, pBufferObj) == NO_ERROR); if(!isOK) { VERIFY(!HasStarted()); ::ManualCloseSocket(soClient); AddFreeBufferObj(pBufferObj); } } if(!isOK) { ::InterlockedDecrement(&m_iRemainAcceptSockets); ASSERT(m_iRemainAcceptSockets >= 0); } return isOK; }
int CUdpServer::SendItem(TUdpSocketObj* pSocketObj) { int result = NO_ERROR; while(pSocketObj->sndBuff.Size() > 0) { ::InterlockedIncrement(&pSocketObj->sndCount); TItemPtr itPtr(m_itPool, pSocketObj->sndBuff.PopFront()); int iBufferSize = itPtr->Size(); ASSERT(iBufferSize > 0 && iBufferSize <= (int)m_dwMaxDatagramSize); pSocketObj->pending -= iBufferSize; TUdpBufferObj* pBufferObj = GetFreeBufferObj(iBufferSize); memcpy(&pBufferObj->remoteAddr, &pSocketObj->remoteAddr, sizeof(SOCKADDR_IN)); memcpy(pBufferObj->buff.buf, itPtr->Ptr(), iBufferSize); int result = ::PostSendToNotCheck(m_soListen, pBufferObj); if(result != NO_ERROR) { if(result != WSA_IO_PENDING) AddFreeBufferObj(pBufferObj);; break; } } return result; }
void CIocpServer::HandleIo(TSocketObj* pSocketObj, TBufferObj* pBufferObj, DWORD dwBytes, DWORD dwErrorCode) { ASSERT(pBufferObj != NULL); ASSERT(pSocketObj != NULL); //判断是否已经标记失败 if(dwErrorCode != NO_ERROR) { if(pBufferObj->operation != SO_ACCEPT) { FireError(pSocketObj->connID, pBufferObj->operation, dwErrorCode); AddFreeSocketObj(pSocketObj->connID); } else { DeleteAcceptSocket(pBufferObj->client, TRUE); } AddFreeBufferObj(pBufferObj); return; } if(dwBytes == 0 && pBufferObj->operation != SO_ACCEPT) { FireClose(pSocketObj->connID); AddFreeSocketObj(pSocketObj->connID); AddFreeBufferObj(pBufferObj); return; } pBufferObj->buff.len = dwBytes; switch(pBufferObj->operation) { case SO_ACCEPT: HandleAccept((SOCKET)pSocketObj, pBufferObj); break; case SO_SEND: HandleSend(pSocketObj, pBufferObj); break; case SO_RECEIVE: HandleReceive(pSocketObj, pBufferObj); break; default: ASSERT(FALSE); } }
void CUdpServer::HandleSend(CONNID dwConnID, TUdpBufferObj* pBufferObj) { BOOL bNeedFree = FALSE; switch(m_enSendPolicy) { case SP_PACK: { TUdpSocketObj* pSocketObj = FindSocketObj(dwConnID); if(TUdpSocketObj::IsValid(pSocketObj)) { long sndCount = ::InterlockedDecrement(&pSocketObj->sndCount); TriggerFireSend(dwConnID, pBufferObj); if(sndCount == 0) DoSendPack(pSocketObj); } else bNeedFree = TRUE; } break; case SP_SAFE: { long sndCount = -1; TUdpSocketObj* pSocketObj = FindSocketObj(dwConnID); if(TUdpSocketObj::IsValid(pSocketObj)) { sndCount = ::InterlockedDecrement(&pSocketObj->sndCount); if(sndCount == 0 && !pSocketObj->smooth) { CCriSecLock locallock(pSocketObj->crisec); if((sndCount = pSocketObj->sndCount) == 0) pSocketObj->smooth = TRUE; } TriggerFireSend(dwConnID, pBufferObj); if(sndCount == 0) DoSendSafe(pSocketObj); } else bNeedFree = TRUE; } break; case SP_DIRECT: { TriggerFireSend(dwConnID, pBufferObj); } break; default: ASSERT(FALSE); } if(bNeedFree) AddFreeBufferObj(pBufferObj); }
void CTcpServer::HandleReceive(CONNID dwConnID, TSocketObj* pSocketObj, TBufferObj* pBufferObj) { if(m_bMarkSilence) pSocketObj->activeTime = ::TimeGetTime(); EnHandleResult hr = TriggerFireReceive(pSocketObj, pBufferObj); if(hr == HR_OK || hr == HR_IGNORE) DoReceive(dwConnID, pSocketObj, pBufferObj); else if(hr == HR_CLOSED) { AddFreeBufferObj(pBufferObj); } else { AddFreeSocketObj(pSocketObj, SCF_ERROR, SO_RECEIVE, ERROR_CANCELLED); AddFreeBufferObj(pBufferObj); } }
DWORD CTcpAgent::ConnectToServer(CONNID dwConnID, SOCKET& soClient, LPCTSTR pszRemoteAddress, USHORT usPort) { TCHAR szAddress[40]; int iAddressLen = sizeof(szAddress) / sizeof(TCHAR); if(!::GetIPAddress(pszRemoteAddress, szAddress, iAddressLen)) return ERROR_INVALID_ADDRESS; SOCKADDR_IN addr; if(!::sockaddr_A_2_IN(AF_INET, szAddress, usPort, addr)) return ERROR_INVALID_ADDRESS; TBufferObj* pBufferObj = GetFreeBufferObj(); TSocketObj* pSocketObj = GetFreeSocketObj(dwConnID, soClient); memcpy(&pSocketObj->remoteAddr, &addr, sizeof(SOCKADDR_IN)); AddClientSocketObj(dwConnID, pSocketObj); DWORD result = NO_ERROR; if(m_bAsyncConnect) { if(::CreateIoCompletionPort((HANDLE)soClient, m_hCompletePort, (ULONG_PTR)pSocketObj, 0)) result = ::PostConnect(m_pfnConnectEx, soClient, addr, pBufferObj); else result = ::GetLastError(); } else { if(::connect(soClient, (SOCKADDR*)&addr, sizeof(SOCKADDR_IN)) != SOCKET_ERROR) { if(::CreateIoCompletionPort((HANDLE)soClient, m_hCompletePort, (ULONG_PTR)pSocketObj, 0)) { BOOL bOnOff = (m_dwKeepAliveTime > 0 && m_dwKeepAliveInterval > 0); VERIFY(::SSO_KeepAliveVals(pSocketObj->socket, bOnOff, m_dwKeepAliveTime, m_dwKeepAliveInterval) == NO_ERROR); if(FireConnect(dwConnID) != HR_ERROR) result = DoReceive(dwConnID, pSocketObj, pBufferObj); else result = ERROR_FUNCTION_FAILED; } else result = ::GetLastError(); } else result = ::WSAGetLastError(); } if(result != NO_ERROR) { AddFreeSocketObj(dwConnID, SCF_NONE); AddFreeBufferObj(pBufferObj); soClient = INVALID_SOCKET; } return result; }
void CTcpServer::HandleReceive(CONNID dwConnID, TSocketObj* pSocketObj, TBufferObj* pBufferObj) { EnHandleResult hr = FireReceive(pSocketObj, (BYTE*)pBufferObj->buff.buf, pBufferObj->buff.len); if(hr == HR_OK || hr == HR_IGNORE) DoReceive(dwConnID, pSocketObj, pBufferObj); else if(hr == HR_CLOSED) { ASSERT(m_enRecvPolicy == RP_SERIAL); AddFreeBufferObj(pBufferObj); } else { TRACE("<S-CNNID: %Iu> OnReceive() event return 'HR_ERROR', connection will be closed !\n", dwConnID); AddFreeSocketObj(pSocketObj, SCF_ERROR, SO_RECEIVE, ERROR_CANCELLED); AddFreeBufferObj(pBufferObj); } }
void CTcpAgent::HandleReceive(CONNID dwConnID, TSocketObj* pSocketObj, TBufferObj* pBufferObj) { if(m_bMarkSilence) pSocketObj->activeTime = ::TimeGetTime(); EnHandleResult hr = TriggerFireReceive(pSocketObj, pBufferObj); if(hr == HR_OK || hr == HR_IGNORE) DoReceive(dwConnID, pSocketObj, pBufferObj); else if(hr == HR_CLOSED) { AddFreeBufferObj(pBufferObj); } else { TRACE("<A-CNNID: %Iu> OnReceive() event return 'HR_ERROR', connection will be closed !\n", dwConnID); AddFreeSocketObj(pSocketObj, SCF_ERROR, SO_RECEIVE, ERROR_CANCELLED); AddFreeBufferObj(pBufferObj); } }
void CTcpAgent::TriggerFireSend(CONNID dwConnID, TBufferObj* pBufferObj) { if(FireSend(dwConnID, (BYTE*)pBufferObj->buff.buf, pBufferObj->buff.len) == HR_ERROR) { TRACE("<A-CNNID: %Iu> OnSend() event should not return 'HR_ERROR' !!\n", dwConnID); ASSERT(FALSE); } AddFreeBufferObj(pBufferObj); }
void CUdpServer::HandleError(CONNID dwConnID, TUdpBufferObj* pBufferObj, DWORD dwErrorCode) { if(dwConnID != 0) AddFreeSocketObj(dwConnID, SCF_ERROR, pBufferObj->operation, dwErrorCode); if(pBufferObj->operation == SO_RECEIVE) DoReceive(pBufferObj); else AddFreeBufferObj(pBufferObj); }
void CTcpServer::HandleSend(CONNID dwConnID, TSocketObj* pSocketObj, TBufferObj* pBufferObj) { if(FireSend(dwConnID, (BYTE*)pBufferObj->buff.buf, pBufferObj->buff.len) == ISocketListener::HR_ERROR) { TRACE("<S-CNNID: %Iu> OnSend() event should not return 'HR_ERROR' !!\n", dwConnID); ASSERT(FALSE); } AddFreeBufferObj(pBufferObj); }
void CTcpAgent::HandleReceive(CONNID dwConnID, TSocketObj* pSocketObj, TBufferObj* pBufferObj) { if(FireReceive(dwConnID, (BYTE*)pBufferObj->buff.buf, pBufferObj->buff.len) != HR_ERROR) DoReceive(dwConnID, pSocketObj, pBufferObj); else { TRACE("<A-CNNID: %Iu> OnReceive() event return 'HR_ERROR', connection will be closed !\n", dwConnID); AddFreeSocketObj(dwConnID, SCF_ERROR, SO_RECEIVE, ERROR_FUNCTION_FAILED); AddFreeBufferObj(pBufferObj); } }
int CTcpAgent::DoConnect(CONNID dwConnID, TSocketObj* pSocketObj, TBufferObj* pBufferObj) { int result = ::PostConnect(m_pfnConnectEx, pSocketObj->socket, pSocketObj->remoteAddr, pBufferObj); if(result != NO_ERROR) { CheckError(pSocketObj, SO_CONNECT, result); AddFreeBufferObj(pBufferObj); } return result; }
void CTcpAgent::HandleConnect(CONNID dwConnID, TSocketObj* pSocketObj, TBufferObj* pBufferObj) { ::SSO_UpdateConnectContext(pBufferObj->client, 0); if(TriggerFireConnect(pSocketObj) != HR_ERROR) DoReceive(dwConnID, pSocketObj, pBufferObj); else { AddFreeSocketObj(pSocketObj, SCF_NONE); AddFreeBufferObj(pBufferObj); } }
void CTcpServer::HandleError(CONNID dwConnID, TSocketObj* pSocketObj, TBufferObj* pBufferObj, DWORD dwErrorCode) { if(pBufferObj->operation != SO_ACCEPT) CheckError(pSocketObj, pBufferObj->operation, dwErrorCode); else { ::ManualCloseSocket(pBufferObj->client); VERIFY(::PostIocpAccept(m_hCompletePort)); } AddFreeBufferObj(pBufferObj); }
int CIocpServer::DoSend(TSocketObj* pSocketObj, TBufferObj* pBufferObj) { int result = ::PostSend(pSocketObj, pBufferObj); if(result != NO_ERROR) { FireError(pSocketObj->connID, SO_SEND, result); AddFreeSocketObj(pSocketObj->connID); AddFreeBufferObj(pBufferObj); } return result; }
void CTcpServer::HandleError(CONNID dwConnID, TBufferObj* pBufferObj, DWORD dwErrorCode) { if(pBufferObj->operation != SO_ACCEPT) CheckError(dwConnID, pBufferObj->operation, dwErrorCode); else { ::ManualCloseSocket(pBufferObj->client); ::PostQueuedCompletionStatus(m_hCompletePort, IOCP_SI_ACCEPT, 0, nullptr); } AddFreeBufferObj(pBufferObj); }
int CTcpAgent::DoReceive(CONNID dwConnID, TSocketObj* pSocketObj, TBufferObj* pBufferObj) { pBufferObj->buff.len = m_dwSocketBufferSize; int result = ::PostReceive(pSocketObj, pBufferObj); if(result != NO_ERROR) { CheckError(dwConnID, SO_RECEIVE, result); AddFreeBufferObj(pBufferObj); } return result; }