diff --git a/src/online/http_manager.cpp b/src/online/http_manager.cpp index a3d065134..4fb08a8d2 100644 --- a/src/online/http_manager.cpp +++ b/src/online/http_manager.cpp @@ -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 diff --git a/src/online/http_manager.hpp b/src/online/http_manager.hpp index ddb337059..c7f22a1dd 100644 --- a/src/online/http_manager.hpp +++ b/src/online/http_manager.hpp @@ -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 diff --git a/src/online/request.cpp b/src/online/request.cpp index ed1a6cc71..41ded10c1 100644 --- a/src/online/request.cpp +++ b/src/online/request.cpp @@ -23,7 +23,6 @@ # include #endif -#include #include @@ -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(); diff --git a/src/online/request.hpp b/src/online/request.hpp index 8ed28e81a..c621a014a 100644 --- a/src/online/request.hpp +++ b/src/online/request.hpp @@ -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 +#include #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 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 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 m_progress; Synchronised m_url; Synchronised 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 m_result; + std::string m_string_buffer; + protected : Synchronised m_info; Synchronised 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