4coder-non-source/test_data/lots_of_files/gjNetwork.cpp

165 lines
4.6 KiB
C++

///////////////////////////////////////////////////////////////////
//*-------------------------------------------------------------*//
//| Part of the Game Jolt API C++ Library (http://gamejolt.com) |//
//*-------------------------------------------------------------*//
//| Released under the zlib License |//
//| More information available in the readme file |//
//*-------------------------------------------------------------*//
///////////////////////////////////////////////////////////////////
#include "gjAPI.h"
// ****************************************************************
/* constructor */
gjNetwork::gjNetwork(gjAPI* pAPI)noexcept
: m_iNumSessions (0)
, m_pAPI (pAPI)
{
// init cURL
curl_global_init(CURL_GLOBAL_ALL);
m_pMultiHandle = curl_multi_init();
// reserve some memory
m_apCall.reserve(GJ_API_RESERVE_CALL);
}
// ****************************************************************
/* destructor */
gjNetwork::~gjNetwork()
{
// finish and remove open sessions
this->Wait(2);
while(!m_apCall.empty())
{
gjAPI::ErrorLogAdd("Network Error: session had to be killed <" + m_apCall[0]->GetInfo() + ">");
this->__KillCall(m_apCall[0]);
}
// clear memory
m_apCall.clear();
// exit cURL
curl_multi_cleanup(m_pMultiHandle);
curl_global_cleanup();
}
// ****************************************************************
/* update all active non-blocking cURL sessions */
bool gjNetwork::Update()
{
if(m_apCall.empty()) return false;
// update cURL
curl_multi_perform(m_pMultiHandle, &m_iNumSessions);
// manage active cURL sessions
CURLMsg* pMsg;
while((pMsg = curl_multi_info_read(m_pMultiHandle, &m_iNumSessions)))
{
// cURL session finished
if(pMsg->msg == CURLMSG_DONE)
{
CURL* pSession = pMsg->easy_handle;
const bool bOK = (pMsg->data.result == CURLE_OK) ? true : false;
// search callback object and finish the operation
FOR_EACH(it, m_apCall)
{
gjCall* pCall = (*it);
if(pCall->GetSession() == pSession)
{
// check for errors
if(!bOK)
{
gjAPI::ErrorLogAdd("Network Error: sending non-blocking request failed <" + pCall->GetInfo() + ">");
gjAPI::ErrorLogAdd("Network Error: " + std::string(curl_easy_strerror(pMsg->data.result)));
}
pCall->Finish(bOK);
SAFE_DELETE(pCall)
m_apCall.erase(it);
break;
}
}
// close cURL session
curl_multi_remove_handle(m_pMultiHandle, pSession);
curl_easy_cleanup(pSession);
}
}
return true;
}
// ****************************************************************
/* finish all active sessions and return */
void gjNetwork::Wait(const unsigned int& iMaxWait)
{
// get max waiting time (low precision)
const time_t iMaxTime = std::time(NULL) + iMaxWait;
// force network update
while((iMaxTime >= std::time(NULL) || !iMaxWait) && this->Update()) {}
}
// ****************************************************************
/* check for existing callbacks on the list */
gjNetwork::gjCall* gjNetwork::__CheckCall(const std::string& sInfo)
{
// search callback object and compare info string
FOR_EACH(it, m_apCall)
{
if((*it)->GetInfo() == sInfo)
return (*it);
}
return NULL;
}
// ****************************************************************
/* kill and remove session and callback object */
void gjNetwork::__KillCall(gjCall* pCall)
{
// search callback object
FOR_EACH(it, m_apCall)
{
gjCall* pCurCall = (*it);
if(pCurCall == pCall)
{
CURL* pSession = pCurCall->GetSession();
// delete callback object
pCurCall->Finish(false);
SAFE_DELETE(pCurCall)
m_apCall.erase(it);
// close cURL session
curl_multi_remove_handle(m_pMultiHandle, pSession);
curl_easy_cleanup(pSession);
return;
}
}
}
// ****************************************************************
/* callbacks for writing operations with cURL */
size_t write_to_string(char* ptr, size_t size, size_t count, std::string* stream)
{
const size_t num = size * count;
stream->append(ptr, 0, num);
return num;
}
size_t write_to_file(void* ptr, size_t size, size_t count, FILE* stream)
{
return fwrite(ptr, size, count, stream);
}