//! called on a network error void NetworkManager::OnError(const char* strError) { Log.Print("NetworkManager: error - %s\n", strError); m_pMutex->Lock(); Operation operation = m_lOperations.front(); m_pMutex->Unlock(); NetResult result; result.m_Status = NetResult::S_ConnectionError; if(operation.m_pResultCallback) { operation.m_pResultCallback(result); } operation.Release(); m_pMutex->Lock(); m_lOperations.pop_front(); m_pMutex->Unlock(); }
//! Network thread void* NetworkManager::NetworkThread(void* pParam) { Log << "NetworkManager: NetworkThread started\n"; NetworkManager* pMgr = NetworkManager::Instance(); pMgr->m_bActive = true; while(Engine::Instance()->IsRunning()) { if(pMgr->m_lOperations.empty()) { Thread::YieldThread(); continue; } pMgr->m_pMutex->Lock(); Operation operation = pMgr->m_lOperations.front(); pMgr->m_pMutex->Unlock(); struct hostent* server = gethostbyname(operation.m_HostName.c_str()); if(!server) { pMgr->OnError("couldn't resolve host"); continue; } struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(struct sockaddr_in)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(operation.m_Port); memcpy((char *)&serv_addr.sin_addr.s_addr, (char*)server->h_addr, server->h_length); Log.Print("NetworkThread connect: m_SocketID(%d)\n", operation.m_SocketID); if(connect(operation.m_SocketID, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) != 0) { pMgr->OnError("couldn't connect to host"); continue; } Log.Print("NetworkThread send: m_SocketID(%d)\n", operation.m_SocketID); if(send(operation.m_SocketID, (const char*)operation.m_pData,operation.m_DataSize, 0) != operation.m_DataSize) { pMgr->OnError("data send error"); continue; } { std::vector<uchar> readData; while(Engine::Instance()->IsRunning()) { Log.Print("NetworkThread recv: m_SocketID(%d)\n", operation.m_SocketID); int received = recv(operation.m_SocketID, (char*)pMgr->m_ReadBuffer, ReadBufferSize, 0); if(received < 0) { pMgr->OnError("data receive error"); break; } if(received > 0) { auto currentSize = readData.size(); readData.reserve(currentSize+received); std::copy(pMgr->m_ReadBuffer, pMgr->m_ReadBuffer+received, std::back_inserter(readData)); } // HTTP hack to check if we received the end of the response. // TODO: make this check on the application side. int end = received-1; bool bHTPPEnd = false; char* buf = (char*)pMgr->m_ReadBuffer; if(end >= 3) { bHTPPEnd = (buf[end-3] == '\r' && buf[end-2] == '\n' && buf[end-1] == '\r' && buf[end] == '\n'); } if(bHTPPEnd || received == 0) { NetResult result; pMgr->RemoveHTTPMarkers(readData, result.m_Data); result.m_Status = NetResult::S_DataReceived; if(operation.m_pResultCallback) { operation.m_pResultCallback(result); } operation.Release(); pMgr->m_pMutex->Lock(); pMgr->m_lOperations.pop_front(); pMgr->m_pMutex->Unlock(); break; } } } } pMgr->m_bActive = false; Log << "NetworkManager: NetworkThread finished\n"; return NULL; }