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