Some preparations to make the merge with the addons' network manager go smoothly.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/uni@13374 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
unitraxx 2013-07-28 14:11:20 +00:00
parent eed1c88b4c
commit 6699284237
4 changed files with 91 additions and 67 deletions

View File

@ -1,6 +1,8 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Glenn De Jonghe
// Copyright (C) 2010 Lucas Baudin
// 2011 Joerg Henrichs
// 2013 Glenn De Jonghe
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,8 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Glenn De Jonghe
// Copyright (C) 2010 Lucas Baudin
// 2011 Joerg Henrichs
// 2013 Glenn De Jonghe
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -23,7 +23,6 @@
# include <winsock2.h>
#endif
#include <curl/curl.h>
#include <assert.h>
@ -46,7 +45,7 @@ namespace Online{
void Request::execute()
{
beforeOperation();
prepareOperation();
operation();
afterOperation();
}
@ -85,70 +84,73 @@ namespace Online{
return ok;
}
void HTTPRequest::afterOperation()
void HTTPRequest::prepareOperation()
{
callback();
Request::afterOperation();
m_curl_session = curl_easy_init();
if(!m_curl_session)
{
Log::error("HTTPRequest::prepareOperation", "LibCurl session not initialized.");
return;
}
curl_easy_setopt(m_curl_session, CURLOPT_URL, m_url.getAtomic().c_str());
curl_easy_setopt(m_curl_session, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(m_curl_session, CURLOPT_WRITEFUNCTION, &HTTPRequest::WriteCallback);
curl_easy_setopt(m_curl_session, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(m_curl_session, CURLOPT_PROGRESSDATA, this);
curl_easy_setopt(m_curl_session, CURLOPT_PROGRESSFUNCTION, &HTTPRequest::progressDownload);
curl_easy_setopt(m_curl_session, CURLOPT_CONNECTTIMEOUT, 20);
curl_easy_setopt(m_curl_session, CURLOPT_LOW_SPEED_LIMIT, 10);
curl_easy_setopt(m_curl_session, CURLOPT_LOW_SPEED_TIME, 20);
}
std::string HTTPRequest::downloadPage()
void HTTPRequest::operation()
{
CURL * curl_session;
curl_session = curl_easy_init();
if(!curl_session)
{
Log::error("HTTPRequest::downloadPage", "Error while initialising libCurl session");
return "";
}
curl_easy_setopt(curl_session, CURLOPT_URL, m_url.getAtomic().c_str());
if(!m_curl_session)
return;
Parameters::iterator iter;
std::string postString = "";
std::string postString("");
m_parameters.lock();
for (iter = m_parameters.getData()->begin(); iter != m_parameters.getData()->end(); ++iter)
{
if(iter != m_parameters.getData()->begin())
postString.append("&");
char * escaped = curl_easy_escape(curl_session , iter->first.c_str(), iter->first.size());
char * escaped = curl_easy_escape(m_curl_session , iter->first.c_str(), iter->first.size());
postString.append(escaped);
curl_free(escaped);
postString.append("=");
escaped = curl_easy_escape(curl_session , iter->second.c_str(), iter->second.size());
escaped = curl_easy_escape(m_curl_session , iter->second.c_str(), iter->second.size());
postString.append(escaped);
curl_free(escaped);
}
m_parameters.unlock();
curl_easy_setopt(curl_session, CURLOPT_POSTFIELDS, postString.c_str());
std::string readBuffer;
curl_easy_setopt(curl_session, CURLOPT_WRITEFUNCTION, &HTTPRequest::WriteCallback);
curl_easy_setopt(curl_session, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(curl_session, CURLOPT_PROGRESSDATA, this);
curl_easy_setopt(curl_session, CURLOPT_PROGRESSFUNCTION, &HTTPRequest::progressDownload);
curl_easy_setopt(curl_session, CURLOPT_FILE, &readBuffer);
// Timeout
// Reduce the connection phase timeout (it's 300 by default).
// Add a low speed limit to have a sort of timeout in the
// download phase. Being under 10 B/s during a certain time will
// probably only happen when no access to the net is available.
// The timeout is set to 20s, it should be enough to not produce
// false positive error.
curl_easy_setopt(curl_session, CURLOPT_CONNECTTIMEOUT, 20);
curl_easy_setopt(curl_session, CURLOPT_LOW_SPEED_LIMIT, 10);
curl_easy_setopt(curl_session, CURLOPT_LOW_SPEED_TIME, 20);
CURLcode res = curl_easy_perform(curl_session);
if(res == CURLE_OK)
{
Log::info("HTTPRequest::downloadPage", "Received : %s", readBuffer.c_str());
setProgress(1.0f);
}
else
{
Log::error("HTTPRequest::downloadPage", "curl_easy_perform() failed: %s", curl_easy_strerror(res));
setProgress(-1.0f);
}
curl_easy_cleanup(curl_session);
return readBuffer;
curl_easy_setopt(m_curl_session, CURLOPT_POSTFIELDS, postString.c_str());
std::string uagent( std::string("SuperTuxKart/") + STK_VERSION );
#ifdef WIN32
uagent += (std::string)" (Windows)";
#elif defined(__APPLE__)
uagent += (std::string)" (Macintosh)";
#elif defined(__FreeBSD__)
uagent += (std::string)" (FreeBSD)";
#elif defined(linux)
uagent += (std::string)" (Linux)";
#else
// Unknown system type
#endif
curl_easy_setopt(m_curl_session, CURLOPT_USERAGENT, uagent.c_str());
m_curl_code = curl_easy_perform(m_curl_session);
}
void HTTPRequest::afterOperation()
{
if(m_curl_code == CURLE_OK)
setProgress(1.0f);
else
setProgress(-1.0f);
curl_easy_cleanup(m_curl_session);
callback();
Request::afterOperation();
}
size_t HTTPRequest::WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
@ -206,6 +208,7 @@ namespace Online{
XMLRequest::XMLRequest(int type, bool manage_memory, int priority)
: HTTPRequest(priority, manage_memory, type)
{
m_string_buffer = "";
m_info.setAtomic("");
m_success.setAtomic(false);
MutexLocker(m_result);
@ -218,27 +221,39 @@ namespace Online{
delete m_result.getData();
}
void XMLRequest::prepareOperation()
{
HTTPRequest::prepareOperation();
curl_easy_setopt(m_curl_session, CURLOPT_WRITEDATA, &m_string_buffer);
}
void XMLRequest::operation()
{
HTTPRequest::operation();
MutexLocker(m_result);
m_result.getData() = file_manager->createXMLTreeFromString(downloadPage());
m_result.getData() = file_manager->createXMLTreeFromString(m_string_buffer);
}
void XMLRequest::afterOperation()
{
const XMLNode * xml = this->getResult();
if(m_curl_code != CURLE_OK)
Log::error( "XMLRequest::afterOperation", "curl_easy_perform() failed: %s", curl_easy_strerror(m_curl_code));
else
Log::info( "XMLRequest::afterOperation", "Received : %s", m_string_buffer.c_str());
m_result.lock();;
bool success = false;
irr::core::stringw info;
std::string rec_success;
if(xml->get("success", &rec_success))
if(m_result.getData()->get("success", &rec_success))
{
if (rec_success =="yes")
success = true;
xml->get("info", &info);
m_result.getData()->get("info", &info);
}
else
info = _("Unable to connect to the server. Check your internet connection or try again later.");
m_result.unlock();
m_info.lock();
m_info.getData() = info;
m_info.unlock();

View File

@ -1,5 +1,7 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Glenn De Jonghe
// Copyright (C) 2011 Joerg Henrichs
// 2013 Glenn De Jonghe
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
@ -18,12 +20,14 @@
#define HEADER_ONLINE_REQUEST_HPP
#include <string>
#include <curl/curl.h>
#include "utils/cpp2011.h"
#include "utils/string_utils.hpp"
#include "utils/synchronised.hpp"
#include "io/file_manager.hpp"
namespace Online{
/**
@ -54,8 +58,8 @@ namespace Online{
/** Set to though if the reply of the request is in and callbacks are executed */
Synchronised<bool> m_done;
virtual void beforeOperation() {}
virtual void operation() {};
virtual void prepareOperation() {}
virtual void operation() {}
virtual void afterOperation();
public:
@ -115,22 +119,20 @@ namespace Online{
typedef std::map<std::string, std::string> Parameters;
/** The progress indicator. 0 untill it is started and the first
* packet is downloaded. At the end either -1 (error) or 1
* (everything ok) at the end. */
Synchronised<float> m_progress;
Synchronised<std::string> m_url;
Synchronised<Parameters *> m_parameters;
CURL * m_curl_session;
CURLcode m_curl_code;
virtual void prepareOperation() OVERRIDE;
virtual void operation() OVERRIDE;
virtual void afterOperation() OVERRIDE;
/** Executed when a request has finished. */
virtual void callback() {}
/**
* Performs a POST request to the website with URL m_url using the parameters given in m_parameters.
* Returns the page as a string.
**/
std::string downloadPage();
static int progressDownload( void *clientp,
double dltotal,
@ -184,20 +186,23 @@ namespace Online{
{
private:
Synchronised<XMLNode *> m_result;
std::string m_string_buffer;
protected :
Synchronised<irr::core::stringw> m_info;
Synchronised<bool> m_success;
virtual void operation() OVERRIDE;
virtual void afterOperation() OVERRIDE;
virtual void prepareOperation() OVERRIDE;
virtual void operation() OVERRIDE;
virtual void afterOperation() OVERRIDE;
public :
XMLRequest(int type = 0, bool manage_memory = false, int priority = 1);
virtual ~XMLRequest();
const XMLNode * getResult() const;
const irr::core::stringw & getInfo() const;
bool isSuccess() const { return m_success.getAtomic(); }
const XMLNode * getResult() const;
const irr::core::stringw & getInfo() const;
bool isSuccess() const { return m_success.getAtomic(); }
};
} //namespace Online