diff --git a/sources.cmake b/sources.cmake index ec7051ef2..2e9db0485 100644 --- a/sources.cmake +++ b/sources.cmake @@ -190,13 +190,15 @@ src/network/stk_host.cpp src/network/stk_peer.cpp src/network/types.cpp src/online/current_user.cpp -src/online/http_manager.cpp +src/online/http_request.cpp src/online/messages.cpp src/online/profile.cpp src/online/profile_manager.cpp src/online/request.cpp +src/online/request_manager.cpp src/online/server.cpp src/online/servers_manager.cpp +src/online/xml_request.cpp src/physics/btKart.cpp src/physics/btKartRaycast.cpp src/physics/btUprightConstraint.cpp @@ -517,13 +519,15 @@ src/network/stk_host.hpp src/network/stk_peer.hpp src/network/types.hpp src/online/current_user.hpp -src/online/http_manager.hpp +src/online/http_request.hpp src/online/messages.hpp src/online/profile.hpp src/online/profile_manager.hpp src/online/request.hpp +src/online/request_manager.hpp src/online/server.hpp src/online/servers_manager.hpp +src/online/xml_request.hpp src/physics/btKart.hpp src/physics/btKartRaycast.hpp src/physics/btUprightConstraint.hpp diff --git a/src/achievements/achievements_slot.hpp b/src/achievements/achievements_slot.hpp index 97ed65d72..cfb73ab07 100644 --- a/src/achievements/achievements_slot.hpp +++ b/src/achievements/achievements_slot.hpp @@ -21,7 +21,8 @@ #include "utils/types.hpp" #include "achievements/achievement.hpp" -#include "online/http_manager.hpp" +#include "online/request_manager.hpp" +#include "online/xml_request.hpp" #include #include diff --git a/src/main.cpp b/src/main.cpp index e67c6cfe8..e98dc57b4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -176,13 +176,13 @@ #include "network/protocol_manager.hpp" #include "network/protocols/server_lobby_room_protocol.hpp" #include "online/current_user.hpp" -#include "online/http_manager.hpp" +#include "online/request_manager.hpp" #include "network/client_network_manager.hpp" #include "network/server_network_manager.hpp" #include "network/protocol_manager.hpp" #include "network/protocols/server_lobby_room_protocol.hpp" #include "online/current_user.hpp" -#include "online/http_manager.hpp" +#include "online/request_manager.hpp" #include "online/profile_manager.hpp" #include "online/servers_manager.hpp" #include "race/grand_prix_manager.hpp" @@ -1027,7 +1027,7 @@ void initRest() // to network_http (since the thread might use network_http, otherwise // a race condition can be introduced resulting in a crash). INetworkHttp::get()->startNetworkThread(); - Online::HTTPManager::get()->startNetworkThread(); + Online::RequestManager::get()->startNetworkThread(); AchievementsManager::get()->init(); music_manager = new MusicManager(); sfx_manager = new SFXManager(); @@ -1083,12 +1083,12 @@ static void cleanSuperTuxKart() if(INetworkHttp::get()) INetworkHttp::get()->stopNetworkThread(); - if(Online::HTTPManager::isRunning()) - Online::HTTPManager::get()->stopNetworkThread(); + if(Online::RequestManager::isRunning()) + Online::RequestManager::get()->stopNetworkThread(); //delete in reverse order of what they were created in. //see InitTuxkart() - Online::HTTPManager::deallocate(); + Online::RequestManager::deallocate(); Online::ServersManager::deallocate(); Online::ProfileManager::deallocate(); AchievementsManager::deallocate(); diff --git a/src/main_loop.cpp b/src/main_loop.cpp index e7299a915..cdb571b65 100644 --- a/src/main_loop.cpp +++ b/src/main_loop.cpp @@ -32,7 +32,7 @@ #include "modes/world.hpp" #include "network/protocol_manager.hpp" #include "network/network_world.hpp" -#include "online/http_manager.hpp" +#include "online/request_manager.hpp" #include "race/race_manager.hpp" #include "states_screens/state_manager.hpp" #include "utils/profiler.hpp" @@ -156,7 +156,7 @@ void MainLoop::run() PROFILER_POP_CPU_MARKER(); PROFILER_PUSH_CPU_MARKER("Database polling update", 0x00, 0x7F, 0x7F); - Online::HTTPManager::get()->update(dt); + Online::RequestManager::get()->update(dt); PROFILER_POP_CPU_MARKER(); PROFILER_SYNC_FRAME(); @@ -168,7 +168,7 @@ void MainLoop::run() PROFILER_POP_CPU_MARKER(); PROFILER_PUSH_CPU_MARKER("Database polling update", 0x00, 0x7F, 0x7F); - Online::HTTPManager::get()->update(dt); + Online::RequestManager::get()->update(dt); PROFILER_POP_CPU_MARKER(); } diff --git a/src/network/protocols/get_peer_address.cpp b/src/network/protocols/get_peer_address.cpp index 7585898a6..1cf772dcb 100644 --- a/src/network/protocols/get_peer_address.cpp +++ b/src/network/protocols/get_peer_address.cpp @@ -20,7 +20,7 @@ #include "network/protocol_manager.hpp" #include "network/network_manager.hpp" -#include "online/http_manager.hpp" +#include "online/request_manager.hpp" #include "online/current_user.hpp" #include "config/user_config.hpp" #include "utils/log.hpp" @@ -51,7 +51,7 @@ void GetPeerAddress::asynchronousUpdate() m_request->addParameter("peer_id",m_peer_id); m_request->addParameter("action","get"); - Online::HTTPManager::get()->addRequest(m_request); + Online::RequestManager::get()->addRequest(m_request); m_state = REQUEST_PENDING; } else if (m_state == REQUEST_PENDING && m_request->isDone()) diff --git a/src/network/protocols/hide_public_address.cpp b/src/network/protocols/hide_public_address.cpp index 6c3758957..1d1578712 100644 --- a/src/network/protocols/hide_public_address.cpp +++ b/src/network/protocols/hide_public_address.cpp @@ -19,7 +19,7 @@ #include "network/protocols/hide_public_address.hpp" #include "network/protocol_manager.hpp" -#include "online/http_manager.hpp" +#include "online/request_manager.hpp" #include "online/current_user.hpp" #include "config/user_config.hpp" #include "utils/log.hpp" @@ -47,7 +47,7 @@ void HidePublicAddress::asynchronousUpdate() m_request->addParameter("token",Online::CurrentUser::get()->getToken()); m_request->addParameter("action","unset"); - Online::HTTPManager::get()->addRequest(m_request); + Online::RequestManager::get()->addRequest(m_request); m_state = REQUEST_PENDING; } else if (m_state == REQUEST_PENDING && m_request->isDone()) diff --git a/src/network/protocols/quick_join_protocol.cpp b/src/network/protocols/quick_join_protocol.cpp index 57843e430..6ef50d0f7 100644 --- a/src/network/protocols/quick_join_protocol.cpp +++ b/src/network/protocols/quick_join_protocol.cpp @@ -20,7 +20,7 @@ #include "network/network_manager.hpp" #include "online/current_user.hpp" -#include "online/http_manager.hpp" +#include "online/request_manager.hpp" #include "config/user_config.hpp" #include "utils/log.hpp" @@ -49,7 +49,7 @@ void QuickJoinProtocol::asynchronousUpdate() m_request->addParameter("token",Online::CurrentUser::get()->getToken()); m_request->addParameter("action","quick-join"); - Online::HTTPManager::get()->addRequest(m_request); + Online::RequestManager::get()->addRequest(m_request); m_state = REQUEST_PENDING; } else if (m_state == REQUEST_PENDING && m_request->isDone()) diff --git a/src/network/protocols/request_connection.cpp b/src/network/protocols/request_connection.cpp index cd8824e3d..e412f711a 100644 --- a/src/network/protocols/request_connection.cpp +++ b/src/network/protocols/request_connection.cpp @@ -19,7 +19,7 @@ #include "network/protocols/request_connection.hpp" #include "network/protocol_manager.hpp" -#include "online/http_manager.hpp" +#include "online/request_manager.hpp" #include "online/current_user.hpp" #include "config/user_config.hpp" @@ -50,7 +50,7 @@ void RequestConnection::asynchronousUpdate() m_request->addParameter("server_id",m_server_id); m_request->addParameter("action","request-connection"); - Online::HTTPManager::get()->addRequest(m_request); + Online::RequestManager::get()->addRequest(m_request); m_state = REQUEST_PENDING; break; } diff --git a/src/network/protocols/server_lobby_room_protocol.cpp b/src/network/protocols/server_lobby_room_protocol.cpp index 676c42aa8..0c5d28088 100644 --- a/src/network/protocols/server_lobby_room_protocol.cpp +++ b/src/network/protocols/server_lobby_room_protocol.cpp @@ -27,7 +27,7 @@ #include "network/protocols/start_game_protocol.hpp" #include "online/current_user.hpp" -#include "online/http_manager.hpp" +#include "online/request_manager.hpp" #include "config/user_config.hpp" #include "modes/world.hpp" #include "utils/log.hpp" diff --git a/src/network/protocols/show_public_address.cpp b/src/network/protocols/show_public_address.cpp index 0e0e2e604..a22b8fff9 100644 --- a/src/network/protocols/show_public_address.cpp +++ b/src/network/protocols/show_public_address.cpp @@ -19,7 +19,7 @@ #include "network/protocols/show_public_address.hpp" #include "network/network_manager.hpp" -#include "online/http_manager.hpp" +#include "online/request_manager.hpp" #include "online/current_user.hpp" #include "config/user_config.hpp" #include "utils/log.hpp" @@ -52,7 +52,7 @@ void ShowPublicAddress::asynchronousUpdate() m_request->addParameter("action","set"); Log::info("ShowPublicAddress", "Showing addr %u and port %d", addr.ip, addr.port); - Online::HTTPManager::get()->addRequest(m_request); + Online::RequestManager::get()->addRequest(m_request); m_state = REQUEST_PENDING; } else if (m_state == REQUEST_PENDING && m_request->isDone()) diff --git a/src/network/protocols/start_server.cpp b/src/network/protocols/start_server.cpp index 978a3b794..bc689ea6c 100644 --- a/src/network/protocols/start_server.cpp +++ b/src/network/protocols/start_server.cpp @@ -20,7 +20,7 @@ #include "network/network_manager.hpp" #include "online/current_user.hpp" -#include "online/http_manager.hpp" +#include "online/request_manager.hpp" #include "config/user_config.hpp" StartServer::StartServer() : Protocol(NULL, PROTOCOL_SILENT) @@ -52,7 +52,7 @@ void StartServer::asynchronousUpdate() m_request->addParameter("action","start-server"); Log::info("ShowPublicAddress", "Showing addr %u and port %d", addr.ip, addr.port); - Online::HTTPManager::get()->addRequest(m_request); + Online::RequestManager::get()->addRequest(m_request); m_state = REQUEST_PENDING; } else if (m_state == REQUEST_PENDING && m_request->isDone()) diff --git a/src/network/protocols/stop_server.cpp b/src/network/protocols/stop_server.cpp index c0d7ded4a..0dc5dbe0b 100644 --- a/src/network/protocols/stop_server.cpp +++ b/src/network/protocols/stop_server.cpp @@ -20,7 +20,7 @@ #include "network/network_manager.hpp" #include "online/current_user.hpp" -#include "online/http_manager.hpp" +#include "online/request_manager.hpp" #include "config/user_config.hpp" StopServer::StopServer() : Protocol(NULL, PROTOCOL_SILENT) @@ -55,7 +55,7 @@ void StopServer::asynchronousUpdate() m_request->addParameter("action","stop-server"); Log::info("StopServer", "address %u, port %d", addr.ip, addr.port); - Online::HTTPManager::get()->addRequest(m_request); + Online::RequestManager::get()->addRequest(m_request); m_state = REQUEST_PENDING; } else if (m_state == REQUEST_PENDING && m_request->isDone()) diff --git a/src/network/stk_host.hpp b/src/network/stk_host.hpp index a9951000c..97cc96dad 100644 --- a/src/network/stk_host.hpp +++ b/src/network/stk_host.hpp @@ -28,7 +28,7 @@ // enet.h includes win32.h, which without lean_and_mean includes // winspool.h, which defines MAX_PRIORITY as a macro, which then -// results in http_manager.hpp not being compilable. +// results in request_manager.hpp not being compilable. #define WIN32_LEAN_AND_MEAN #include diff --git a/src/online/current_user.cpp b/src/online/current_user.cpp index c86c79190..dede03afc 100644 --- a/src/online/current_user.cpp +++ b/src/online/current_user.cpp @@ -77,7 +77,7 @@ namespace Online request->addParameter("action", std::string("recovery")); request->addParameter("username", username); request->addParameter("email", email); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); return request; } @@ -97,7 +97,7 @@ namespace Online request->addParameter("password_confirm", password_confirm); request->addParameter("email", email); request->addParameter("terms", std::string("on")); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); return request; } @@ -112,7 +112,7 @@ namespace Online request->addParameter("action",std::string("saved-session")); request->addParameter("userid", UserConfigParams::m_saved_user); request->addParameter("token", UserConfigParams::m_saved_token.c_str()); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); m_state = US_SIGNING_IN; } } @@ -131,7 +131,7 @@ namespace Online request->addParameter("save-session", StringUtils::boolstr(save_session)); if (request_now) { - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); m_state = US_SIGNING_IN; } return request; @@ -200,7 +200,7 @@ namespace Online request->addParameter("userid", getID()); request->addParameter("name", name); request->addParameter("max_players", max_players); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); return request; } @@ -222,7 +222,7 @@ namespace Online request->addParameter("action",std::string("disconnect")); request->addParameter("token", getToken()); request->addParameter("userid", getID()); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); m_state = US_SIGNING_OUT; } @@ -260,7 +260,7 @@ namespace Online request->addParameter("id", getID()); request->addParameter("server_id", server_id); if (request_now) - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); return request; } @@ -286,7 +286,7 @@ namespace Online request->addParameter("token", getToken()); request->addParameter("userid", getID()); request->addParameter("addonid", addon_id.substr(6)); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); return request; } @@ -304,7 +304,7 @@ namespace Online request->addParameter("token", getToken()); request->addParameter("userid", getID()); request->addParameter("search-string", search_string); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); return request; } @@ -324,7 +324,7 @@ namespace Online request->addParameter("userid", getID()); request->addParameter("addonid", addon_id.substr(6)); request->addParameter("rating", rating); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); return request; } @@ -357,7 +357,7 @@ namespace Online request->addParameter("token", getToken()); request->addParameter("userid", getID()); request->addParameter("friendid", friend_id); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); } /** @@ -394,7 +394,7 @@ namespace Online request->addParameter("token", getToken()); request->addParameter("userid", getID()); request->addParameter("friendid", friend_id); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); } /** @@ -432,7 +432,7 @@ namespace Online request->addParameter("token", getToken()); request->addParameter("userid", getID()); request->addParameter("friendid", friend_id); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); } /** @@ -471,7 +471,7 @@ namespace Online request->addParameter("token", getToken()); request->addParameter("userid", getID()); request->addParameter("friendid", friend_id); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); } /** @@ -510,7 +510,7 @@ namespace Online request->addParameter("token", getToken()); request->addParameter("userid", getID()); request->addParameter("friendid", friend_id); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); } /** @@ -554,7 +554,7 @@ namespace Online request->addParameter("current", current_password); request->addParameter("new1", new_password); request->addParameter("new2", new_password_ver); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); } /** @@ -586,7 +586,7 @@ namespace Online request->addParameter("action", std::string("poll")); request->addParameter("token", getToken()); request->addParameter("userid", getID()); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); } /** @@ -713,12 +713,12 @@ namespace Online { if(isRegisteredUser()) { - HTTPRequest * request = new HTTPRequest(true, HTTPManager::HTTP_MAX_PRIORITY); + HTTPRequest * request = new HTTPRequest(true, RequestManager::HTTP_MAX_PRIORITY); request->setServerURL("client-user.php"); request->addParameter("action", std::string("client-quit")); request->addParameter("token", getToken()); request->addParameter("userid", getID()); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); } } @@ -737,7 +737,7 @@ namespace Online request->addParameter("token", getToken()); request->addParameter("userid", getID()); request->addParameter("achievementid", achievement_id); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); } } diff --git a/src/online/current_user.hpp b/src/online/current_user.hpp index 7eb6f4857..c75e62604 100644 --- a/src/online/current_user.hpp +++ b/src/online/current_user.hpp @@ -19,9 +19,10 @@ #ifndef HEADER_CURRENT_ONLINE_USER_HPP #define HEADER_CURRENT_ONLINE_USER_HPP -#include "online/http_manager.hpp" +#include "online/request_manager.hpp" #include "online/server.hpp" #include "online/profile.hpp" +#include "online/xml_request.hpp" #include "utils/types.hpp" #include "utils/synchronised.hpp" diff --git a/src/online/http_request.cpp b/src/online/http_request.cpp new file mode 100644 index 000000000..a303da6f3 --- /dev/null +++ b/src/online/http_request.cpp @@ -0,0 +1,232 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 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 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "online/http_request.hpp" + +#include "config/user_config.hpp" +#include "online/request_manager.hpp" +#include "utils/constants.hpp" +#include "utils/translation.hpp" + +#ifdef WIN32 +# include +#endif + +#include + +#include + + +namespace Online{ + + /** Creates a HTTP(S) request that will have a raw string as result. (Can + * of course be used if the result doesn't matter.) + * \param manage_memory whether or not the HTTPManager should take care of + * deleting the object after all callbacks have been done. + * \param priority by what priority should the HTTPManager take care of + * this request. + */ + HTTPRequest::HTTPRequest(bool manage_memory, int priority) + : Request(manage_memory, priority, 0) + { + m_url = ""; + m_string_buffer = ""; + m_parameters = new Parameters(); + m_progress.setAtomic(0); + } // HTTPRequest + + // ------------------------------------------------------------------------ + HTTPRequest::~HTTPRequest() + { + delete m_parameters; + } // ~HTTPRequest + + // ------------------------------------------------------------------------ + /** A handy shortcut that appends the given path to the URL of the server. + * \param path The path to add to the server. + */ + void HTTPRequest::setServerURL(const std::string& path) + { + setURL((std::string)UserConfigParams::m_server_multiplayer+path); + } // setServerURL + + // ------------------------------------------------------------------------ + /** Checks the request if it has enough (correct) information to be + * executed (and thus allowed to add to the queue). + */ + bool HTTPRequest::isAllowedToAdd() + { + return Request::isAllowedToAdd() && m_url.substr(0, 5) == "http:"; + } // isAllowedToAdd + + // ------------------------------------------------------------------------ + /** Sets up the curl data structures. + */ + void HTTPRequest::prepareOperation() + { + 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.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); + //https + struct curl_slist *chunk = NULL; + chunk = curl_slist_append(chunk, "Host: api.stkaddons.net"); + curl_easy_setopt(m_curl_session, CURLOPT_HTTPHEADER, chunk); + curl_easy_setopt(m_curl_session, CURLOPT_CAINFO, + (file_manager->getAsset("web.tuxfamily.org.pem")).c_str()); + curl_easy_setopt(m_curl_session, CURLOPT_SSL_VERIFYPEER, 0L); + //curl_easy_setopt(m_curl_session, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(m_curl_session, CURLOPT_WRITEDATA, &m_string_buffer); + } // prepareOperation + + // ------------------------------------------------------------------------ + /** The actual curl download happens here. + */ + void HTTPRequest::operation() + { + if(!m_curl_session) + return; + Parameters::iterator iter; + std::string postString(""); + for (iter = m_parameters->begin(); iter != m_parameters->end(); ++iter) + { + if(iter != m_parameters->begin()) + postString.append("&"); + 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(m_curl_session, + iter->second.c_str(), + iter->second.size()); + postString.append(escaped); + curl_free(escaped); + } + Log::info("HTTPRequest::operation", "Sending : %s", + postString.c_str()); + 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); + Request::operation(); + } // operation + + // ------------------------------------------------------------------------ + /** Cleanup once the download is finished. The value of progress is + * guaranteed to be >=0 and <1 while the download is in progress, and + * will only be set to 1 on a successfull finish here. + */ + void HTTPRequest::afterOperation() + { + if(m_curl_code == CURLE_OK) + setProgress(1.0f); + else + setProgress(-1.0f); + Request::afterOperation(); + curl_easy_cleanup(m_curl_session); + } // afterOperation + + // ------------------------------------------------------------------------ + /** Callback from curl. This stores the data received by curl in the + * buffer of this request. + * \param content Pointer to the data received by curl. + * \param size Size of one block. + * \param nmemb Number of blocks received. + * \param userp Pointer to the user buffer. + */ + size_t HTTPRequest::writeCallback(void *contents, size_t size, + size_t nmemb, void *userp) + { + ((std::string*)userp)->append((char*)contents, size * nmemb); + return size * nmemb; + } // writeCallback + + // ---------------------------------------------------------------------------- + /** Callback function from curl: inform about progress. It makes sure that + * the value reported by getProgress () is <1 while the download is still + * in progress. + * \param clientp + * \param download_total Total size of data to download. + * \param download_now How much has been downloaded so far. + * \param upload_total Total amount of upload. + * \param upload_now How muc has been uploaded so far. + */ + int HTTPRequest::progressDownload(void *clientp, + double download_total, double download_now, + double upload_total, double upload_now) + { + HTTPRequest *request = (HTTPRequest *)clientp; + + RequestManager* request_manager = RequestManager::get(); + + // Check if we are asked to abort the download. If so, signal this + // back to libcurl by returning a non-zero status. + if(request_manager->getAbort() || request->isCancelled() ) + { + // Indicates to abort the current download, which means that this + // thread will go back to the mainloop and handle the next request. + return 1; + } + + float f; + if(download_now < download_total) + { + f = (float)download_now / (float)download_total; + // In case of floating point rouding errors make sure that + // 1.0 is only reached when downloadFileInternal is finished + if (f>=1.0f) f=0.99f; + } + else + { + // Don't set progress to 1.0f; this is done in afterOperation() + // after checking curls return code! + f= download_total==0 ? 0 : 0.99f; + } + request->setProgress(f); + return 0; + } // progressDownload + + +} // namespace Online diff --git a/src/online/http_request.hpp b/src/online/http_request.hpp new file mode 100644 index 000000000..91ea86f95 --- /dev/null +++ b/src/online/http_request.hpp @@ -0,0 +1,145 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2011-2013 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 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HEADER_HTTP_REQUEST_HPP +#define HEADER_HTTP_REQUEST_HPP + +#include "io/file_manager.hpp" +#include "online/request.hpp" +#include "utils/cpp2011.h" +#include "utils/string_utils.hpp" +#include "utils/synchronised.hpp" + +#ifdef WIN32 +# include +#endif +#include +#include +#include + +namespace Online +{ + /** A http request. + */ + class HTTPRequest : public Request + { + private: + typedef std::map Parameters; + + /** The progress indicator. 0 untill it is started and the first + * packet is downloaded. Guaranteed to be <1 while the download + * is in progress, it will be set to either -1 (error) or 1 + * (everything ok) at the end. */ + Synchronised m_progress; + + /** The url to download. */ + std::string m_url; + + /** The POST parameters that will be send with the request. */ + Parameters *m_parameters; + + /** Pointer to the curl data structure for this request. */ + CURL *m_curl_session; + + /** curl return code. */ + CURLcode m_curl_code; + + /** String to store the received data in. */ + std::string m_string_buffer; + + protected: + virtual void prepareOperation() OVERRIDE; + virtual void operation() OVERRIDE; + virtual void afterOperation() OVERRIDE; + + static int progressDownload(void *clientp, double dltotal, + double dlnow, double ultotal, + double ulnow); + + static size_t writeCallback(void *contents, size_t size, + size_t nmemb, void *userp); + + + public : + HTTPRequest(bool manage_memory = false, + int priority = 1); + virtual ~HTTPRequest(); + virtual bool isAllowedToAdd() OVERRIDE; + void setServerURL(const std::string& url); + // ------------------------------------------------------------------------ + /** Returns the curl error status of the request. + */ + CURLcode getResult() const { return m_curl_code; } + // ------------------------------------------------------------------------ + /** Returns the downloaded string. + * \pre request has to be done + * \return get the result string from the request reply + */ + const std::string & getData() const + { + assert(hasBeenExecuted()); + return m_string_buffer; + } // getData + + // -------------------------------------------------------------------- + /** Sets a parameter to 'value' (std::string). + */ + void addParameter(const std::string & name, const std::string &value) + { + assert(isPreparing()); + (*m_parameters)[name] = value; + }; // addParameter + // -------------------------------------------------------------------- + /** Sets a parameter to 'value' (stringw). + */ + void addParameter(const std::string & name, + const irr::core::stringw &value) + { + assert(isPreparing()); + (*m_parameters)[name] = irr::core::stringc(value.c_str()).c_str(); + } // addParameter + // -------------------------------------------------------------------- + /** Sets a parameter to 'value' (arbitrary types). + */ + template + void addParameter(const std::string & name, const T& value){ + assert(isPreparing()); + (*m_parameters)[name] = StringUtils::toString(value); + } // addParameter + // -------------------------------------------------------------------- + /** Returns the current progress. */ + float getProgress() const { return m_progress.getAtomic(); } + // -------------------------------------------------------------------- + /** Sets the current progress. */ + void setProgress(float f) { m_progress.setAtomic(f); } + // -------------------------------------------------------------------- + const std::string & getURL() const { assert(isBusy()); return m_url;} + // -------------------------------------------------------------------- + /** Sets the URL for this request. */ + void setURL(const std::string & url) + { + assert(isPreparing()); + m_url = url; + } // setURL + + }; // class HTTPRequest + +} //namespace Online + +#endif + diff --git a/src/online/profile.cpp b/src/online/profile.cpp index 2a65c6633..fbddd2f05 100644 --- a/src/online/profile.cpp +++ b/src/online/profile.cpp @@ -20,7 +20,7 @@ #include "online/profile.hpp" #include "online/profile_manager.hpp" -#include "online/http_manager.hpp" +#include "online/request_manager.hpp" #include "config/user_config.hpp" #include "online/current_user.hpp" #include "utils/log.hpp" @@ -146,7 +146,7 @@ namespace Online{ request->addParameter("token", CurrentUser::get()->getToken()); request->addParameter("userid", CurrentUser::get()->getID()); request->addParameter("visitingid", m_id); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); } void Profile::AchievementsRequest::callback() @@ -202,7 +202,7 @@ namespace Online{ request->addParameter("token", CurrentUser::get()->getToken()); request->addParameter("userid", CurrentUser::get()->getID()); request->addParameter("visitingid", m_id); - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); } void Profile::FriendsListRequest::callback() diff --git a/src/online/profile.hpp b/src/online/profile.hpp index 60f5b39b6..1095d474d 100644 --- a/src/online/profile.hpp +++ b/src/online/profile.hpp @@ -19,8 +19,8 @@ #ifndef HEADER_ONLINE_PROFILE_HPP #define HEADER_ONLINE_PROFILE_HPP -#include "http_manager.hpp" -#include "online/request.hpp" +#include "online/request_manager.hpp" +#include "online/xml_request.hpp" #include "utils/types.hpp" #include "utils/ptr_vector.hpp" diff --git a/src/online/request.cpp b/src/online/request.cpp index a33c7f666..7c6eb9fc0 100644 --- a/src/online/request.cpp +++ b/src/online/request.cpp @@ -17,32 +17,27 @@ #include "online/request.hpp" #include "config/user_config.hpp" -#include "online/http_manager.hpp" -#include "utils/constants.hpp" -#include "utils/translation.hpp" +#include "online/request_manager.hpp" #ifdef WIN32 # include #endif -#include - #include -namespace Online{ - - class HTTPManager; +namespace Online +{ // ======================================================================== /** - * Creates a request that can be handled by the HTTPManager - * \param manage_memory whether or not the HTTPManager should take care of + * Creates a request that can be handled by the RequestManager + * \param manage_memory whether or not the RequestManager should take care of * deleting the object after all callbacks have been done - * \param priority by what priority should the HTTPManager take care of + * \param priority by what priority should the RequestManager take care of * this request * \param type indicates whether the request has a special task for the - * HTTPManager + * RequestManager */ Request::Request(bool manage_memory, int priority, int type) : m_type(type), m_manage_memory(manage_memory), m_priority(priority) @@ -77,248 +72,5 @@ namespace Online{ setDone(); } // executeNow - // ======================================================================== - /** Creates a HTTP(S) request that will have a raw string as result. (Can - * of course be used if the result doesn't matter.) - * \param manage_memory whether or not the HTTPManager should take care of - * deleting the object after all callbacks have been done. - * \param priority by what priority should the HTTPManager take care of - * this request. - */ - HTTPRequest::HTTPRequest(bool manage_memory, int priority) - : Request(manage_memory, priority, 0) - { - m_url = ""; - m_string_buffer = ""; - m_parameters = new Parameters(); - m_progress.setAtomic(0); - } // HTTPRequest - - // ------------------------------------------------------------------------ - HTTPRequest::~HTTPRequest() - { - delete m_parameters; - } // ~HTTPRequest - - // ------------------------------------------------------------------------ - /** A handy shortcut that appends the given path to the URL of the server. - * \param path The path to add to the server. - */ - void HTTPRequest::setServerURL(const std::string& path) - { - setURL((std::string)UserConfigParams::m_server_multiplayer+path); - } // setServerURL - - // ------------------------------------------------------------------------ - /** Checks the request if it has enough (correct) information to be - * executed (and thus allowed to add to the queue). - */ - bool HTTPRequest::isAllowedToAdd() - { - return Request::isAllowedToAdd() && m_url.substr(0, 5) == "http:"; - } // isAllowedToAdd - - // ------------------------------------------------------------------------ - /** Sets up the curl data structures. - */ - void HTTPRequest::prepareOperation() - { - 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.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); - //https - struct curl_slist *chunk = NULL; - chunk = curl_slist_append(chunk, "Host: api.stkaddons.net"); - curl_easy_setopt(m_curl_session, CURLOPT_HTTPHEADER, chunk); - curl_easy_setopt(m_curl_session, CURLOPT_CAINFO, - (file_manager->getAsset("web.tuxfamily.org.pem")).c_str()); - curl_easy_setopt(m_curl_session, CURLOPT_SSL_VERIFYPEER, 0L); - //curl_easy_setopt(m_curl_session, CURLOPT_VERBOSE, 1L); - curl_easy_setopt(m_curl_session, CURLOPT_WRITEDATA, &m_string_buffer); - } // prepareOperation - - // ------------------------------------------------------------------------ - /** The actual curl download happens here. - */ - void HTTPRequest::operation() - { - if(!m_curl_session) - return; - Parameters::iterator iter; - std::string postString(""); - for (iter = m_parameters->begin(); iter != m_parameters->end(); ++iter) - { - if(iter != m_parameters->begin()) - postString.append("&"); - 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(m_curl_session, - iter->second.c_str(), - iter->second.size()); - postString.append(escaped); - curl_free(escaped); - } - Log::info("HTTPRequest::operation", "Sending : %s", - postString.c_str()); - 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); - Request::operation(); - } // operation - - // ------------------------------------------------------------------------ - /** Cleanup once the download is finished. The value of progress is - * guaranteed to be >=0 and <1 while the download is in progress, and - * will only be set to 1 on a successfull finish here. - */ - void HTTPRequest::afterOperation() - { - if(m_curl_code == CURLE_OK) - setProgress(1.0f); - else - setProgress(-1.0f); - Request::afterOperation(); - curl_easy_cleanup(m_curl_session); - } // afterOperation - - // ------------------------------------------------------------------------ - /** Callback from curl. This stores the data received by curl in the - * buffer of this request. - * \param content Pointer to the data received by curl. - * \param size Size of one block. - * \param nmemb Number of blocks received. - * \param userp Pointer to the user buffer. - */ - size_t HTTPRequest::writeCallback(void *contents, size_t size, - size_t nmemb, void *userp) - { - ((std::string*)userp)->append((char*)contents, size * nmemb); - return size * nmemb; - } // writeCallback - - // ---------------------------------------------------------------------------- - /** Callback function from curl: inform about progress. It makes sure that - * the value reported by getProgress () is <1 while the download is still - * in progress. - * \param clientp - * \param download_total Total size of data to download. - * \param download_now How much has been downloaded so far. - * \param upload_total Total amount of upload. - * \param upload_now How muc has been uploaded so far. - */ - int HTTPRequest::progressDownload(void *clientp, - double download_total, double download_now, - double upload_total, double upload_now) - { - HTTPRequest *request = (HTTPRequest *)clientp; - - HTTPManager* http_manager = HTTPManager::get(); - - // Check if we are asked to abort the download. If so, signal this - // back to libcurl by returning a non-zero status. - if(http_manager->getAbort() || request->isCancelled() ) - { - // Indicates to abort the current download, which means that this - // thread will go back to the mainloop and handle the next request. - return 1; - } - - float f; - if(download_now < download_total) - { - f = (float)download_now / (float)download_total; - // In case of floating point rouding errors make sure that - // 1.0 is only reached when downloadFileInternal is finished - if (f>=1.0f) f=0.99f; - } - else - { - // Don't set progress to 1.0f; this is done in afterOperation() - // after checking curls return code! - f= download_total==0 ? 0 : 0.99f; - } - request->setProgress(f); - return 0; - } // progressDownload - - // ======================================================================== - /** Creates a HTTP(S) request that will automatically parse the answer into - * a XML structure. - * \param manage_memory whether or not the HTTPManager should take care of - * deleting the object after all callbacks have been done. - * \param priority by what priority should the HTTPManager take care of - * this request. - */ - XMLRequest::XMLRequest(bool manage_memory, int priority) - : HTTPRequest(manage_memory, priority) - { - m_info = ""; - m_success = false; - m_xml_data = NULL; - } // XMLRequest - - // ------------------------------------------------------------------------ - /** Cleans up the XML tree. */ - XMLRequest::~XMLRequest() - { - delete m_xml_data; - } // ~XMLRequest - - // ------------------------------------------------------------------------ - /** On a successful download converts the string into an XML tree. - */ - void XMLRequest::afterOperation() - { - m_xml_data = file_manager->createXMLTreeFromString(getData()); - if(getResult() != CURLE_OK) - Log::error("XMLRequest::afterOperation", - "curl_easy_perform() failed: %s", - curl_easy_strerror(getResult())); - m_success = false; - std::string rec_success; - if(m_xml_data->get("success", &rec_success)) - { - m_success = rec_success =="yes"; - m_xml_data->get("info", &m_info); - } - else - m_info = _("Unable to connect to the server. Check your internet " - "connection or try again later."); - HTTPRequest::afterOperation(); - } // afterOperation - } // namespace Online diff --git a/src/online/request.hpp b/src/online/request.hpp index 8e0423cc5..66ece63ac 100644 --- a/src/online/request.hpp +++ b/src/online/request.hpp @@ -31,7 +31,8 @@ #include #include -namespace Online{ +namespace Online +{ /** Stores a request for the HTTP Manager. They will be sorted by * prioritiy. Requests have four different states they can be in, and @@ -40,7 +41,7 @@ namespace Online{ * and code to the main thread. The states are: * - Preparing\n The request is created, and parameter are set. * Only the main thread can access this object. - * - Busy\n The request is put into the http_manager queue. It remains + * - Busy\n The request is put into the request_manager queue. It remains * in this states till its operation is finished. No more changes * to this object by the main thread are allowed, only the manager * thread can change it now. @@ -75,15 +76,15 @@ namespace Online{ * - S_PREPARING:\n The request is created and can be configured, it * is not yet started. * - S_BUSY:\n The request is added to the execution queue of the - * http_manager (and potentially executing). This implies that - * now only the http_manager thread should access the requests's + * request_manager (and potentially executing). This implies that + * now only the request_manager thread should access the requests's * data structures. * - S_EXECUTED:\n The request was executed, but was not yet marked - * as finished in the http_manager. This importantly indicates + * as finished in the request_manager. This importantly indicates * that the main thread should not yet access this request, * since the http thread is still executing it. * - S_DONE:\n The request is finished, and it is marked as - * finished in the http_manager. This implies that the main + * finished in the request_manager. This implies that the main * stk thread can access its data safely now. */ enum State @@ -199,174 +200,10 @@ namespace Online{ { return a->getPriority() < b->getPriority(); } - }; // Compare - }; // Request + }; // class Compare + }; // class Request - // ======================================================================== - /** A http request. - */ - class HTTPRequest : public Request - { - private: - typedef std::map Parameters; - - /** The progress indicator. 0 untill it is started and the first - * packet is downloaded. Guaranteed to be <1 while the download - * is in progress, it will be set to either -1 (error) or 1 - * (everything ok) at the end. */ - Synchronised m_progress; - - /** The url to download. */ - std::string m_url; - - /** The POST parameters that will be send with the request. */ - Parameters *m_parameters; - - /** Pointer to the curl data structure for this request. */ - CURL *m_curl_session; - - /** curl return code. */ - CURLcode m_curl_code; - - /** String to store the received data in. */ - std::string m_string_buffer; - - protected: - virtual void prepareOperation() OVERRIDE; - virtual void operation() OVERRIDE; - virtual void afterOperation() OVERRIDE; - - static int progressDownload(void *clientp, double dltotal, - double dlnow, double ultotal, - double ulnow); - - static size_t writeCallback(void *contents, size_t size, - size_t nmemb, void *userp); - - - public : - HTTPRequest(bool manage_memory = false, - int priority = 1); - virtual ~HTTPRequest(); - virtual bool isAllowedToAdd() OVERRIDE; - void setServerURL(const std::string& url); - // ------------------------------------------------------------------------ - /** Returns the curl error status of the request. - */ - CURLcode getResult() const { return m_curl_code; } - // ------------------------------------------------------------------------ - /** Returns the downloaded string. - * \pre request has to be done - * \return get the result string from the request reply - */ - const std::string & getData() const - { - assert(hasBeenExecuted()); - return m_string_buffer; - } // getData - - // -------------------------------------------------------------------- - /** Sets a parameter to 'value' (std::string). - */ - void addParameter(const std::string & name, const std::string &value) - { - assert(isPreparing()); - (*m_parameters)[name] = value; - }; // addParameter - // -------------------------------------------------------------------- - /** Sets a parameter to 'value' (stringw). - */ - void addParameter(const std::string & name, - const irr::core::stringw &value) - { - assert(isPreparing()); - (*m_parameters)[name] = irr::core::stringc(value.c_str()).c_str(); - } // addParameter - // -------------------------------------------------------------------- - /** Sets a parameter to 'value' (arbitrary types). - */ - template - void addParameter(const std::string & name, const T& value){ - assert(isPreparing()); - (*m_parameters)[name] = StringUtils::toString(value); - } // addParameter - // -------------------------------------------------------------------- - /** Returns the current progress. */ - float getProgress() const { return m_progress.getAtomic(); } - // -------------------------------------------------------------------- - /** Sets the current progress. */ - void setProgress(float f) { m_progress.setAtomic(f); } - // -------------------------------------------------------------------- - const std::string & getURL() const { assert(isBusy()); return m_url;} - // -------------------------------------------------------------------- - /** Sets the URL for this request. */ - void setURL(const std::string & url) - { - assert(isPreparing()); - m_url = url; - } // setURL - - }; // class HTTPRequest - - // ======================================================================== - /** A http request expecting a xml return value. - */ - class XMLRequest : public HTTPRequest - { - private: - /** On a successful download contains the converted XML tree. */ - XMLNode *m_xml_data; - - /** Additional info contained the downloaded data (or an error - * message if a problem occurred). */ - irr::core::stringw m_info; - - /** True if the request was successful executed on the server. */ - bool m_success; - - protected: - virtual void afterOperation() OVERRIDE; - - public : - XMLRequest(bool manage_memory = false, int priority = 1); - virtual ~XMLRequest(); - - // ------------------------------------------------------------------------ - /** Get the downloaded XML tree. - * \pre request has to be executed. - * \return get the complete result from the request reply. - */ - const XMLNode * getXMLData() const - { - assert(hasBeenExecuted()); - return m_xml_data; - } // getXMLData - - // ------------------------------------------------------------------------ - /** Returns the additional information (or error message) contained in - * a finished request. - * \pre request had to be executed. - * \return get the info from the request reply - */ - const irr::core::stringw & getInfo() const - { - assert(hasBeenExecuted()); - return m_info; - } // getInfo - - // -------------------------------------------------------------------- - /** Returns whether the request was successfully executed on the server. - * \pre request had to be executed. - * \return whether or not the request was a success. */ - bool isSuccess() const - { - assert(hasBeenExecuted()); - return m_success; - } // isSuccess - - }; // class XMLRequest - } //namespace Online #endif diff --git a/src/online/http_manager.cpp b/src/online/request_manager.cpp similarity index 92% rename from src/online/http_manager.cpp rename to src/online/request_manager.cpp index 6400f2d07..065fd38b9 100644 --- a/src/online/http_manager.cpp +++ b/src/online/request_manager.cpp @@ -18,7 +18,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -#include "online/http_manager.hpp" +#include "online/request_manager.hpp" #include "online/current_user.hpp" #include "states_screens/state_manager.hpp" @@ -37,18 +37,19 @@ using namespace Online; -namespace Online{ +namespace Online +{ #define MENU_POLLING_INTERVAL 10.0f #define GAME_POLLING_INTERVAL 15.0f - static HTTPManager * http_singleton = NULL; + static RequestManager * http_singleton = NULL; // ------------------------------------------------------------------------ - HTTPManager* HTTPManager::get() + RequestManager* RequestManager::get() { if (http_singleton == NULL) { - http_singleton = new HTTPManager(); + http_singleton = new RequestManager(); } return http_singleton; } // get @@ -56,7 +57,7 @@ namespace Online{ // ------------------------------------------------------------------------ /** Deletes the http manager. */ - void HTTPManager::deallocate() + void RequestManager::deallocate() { if (http_singleton != NULL) { @@ -68,14 +69,14 @@ namespace Online{ // ------------------------------------------------------------------------ /** Checks if the http manager is running. */ - bool HTTPManager::isRunning() + bool RequestManager::isRunning() { return http_singleton != NULL; } // isRunning // ------------------------------------------------------------------------ - HTTPManager::HTTPManager() + RequestManager::RequestManager() { curl_global_init(CURL_GLOBAL_DEFAULT); pthread_cond_init(&m_cond_request, NULL); @@ -84,7 +85,8 @@ namespace Online{ } // ------------------------------------------------------------------------ - HTTPManager::~HTTPManager(){ + RequestManager::~RequestManager() + { m_thread_id.lock(); pthread_join(*m_thread_id.getData(), NULL); delete m_thread_id.getData(); @@ -101,7 +103,7 @@ namespace Online{ * use network_http - a very subtle race condition. So the thread can * only be started after the assignment (in main) has been done. */ - void HTTPManager::startNetworkThread() + void RequestManager::startNetworkThread() { pthread_attr_t attr; pthread_attr_init(&attr); @@ -112,7 +114,7 @@ namespace Online{ m_thread_id.setAtomic(new pthread_t()); int error = pthread_create(m_thread_id.getData(), &attr, - &HTTPManager::mainLoop, this); + &RequestManager::mainLoop, this); if(error) { m_thread_id.lock(); @@ -132,7 +134,7 @@ namespace Online{ * Separating this allows more time for the thread to finish cleanly, * before it gets cancelled in the destructor. */ - void HTTPManager::stopNetworkThread() + void RequestManager::stopNetworkThread() { // If a download should be active (which means it was cancelled by the // user, in which case it will still be ongoing in the background) @@ -150,7 +152,7 @@ namespace Online{ * cancelled. This function can also be called if there is actually no * download atm. The function progressDownload checks m_abort and will * return a non-zero value which causes libcurl to abort. */ - void HTTPManager::cancelAllDownloads() + void RequestManager::cancelAllDownloads() { m_abort.setAtomic(true); // FIXME doesn't get called at the moment. When using this again, @@ -162,7 +164,7 @@ namespace Online{ * sorted by priority. * \param request The pointer to the new request to insert. */ - void HTTPManager::addRequest(Request *request) + void RequestManager::addRequest(Request *request) { assert(request->isPreparing()); request->setBusy(); @@ -179,9 +181,9 @@ namespace Online{ * of packages to download, it will wait for commands to be issued. * \param obj: A pointer to this object, passed on by pthread_create */ - void *HTTPManager::mainLoop(void *obj) + void *RequestManager::mainLoop(void *obj) { - HTTPManager *me = (HTTPManager*) obj; + RequestManager *me = (RequestManager*) obj; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); @@ -227,7 +229,7 @@ namespace Online{ /** Inserts a request into the queue of results. * \param request The pointer to the request to insert. */ - void HTTPManager::addResult(Online::Request *request) + void RequestManager::addResult(Online::Request *request) { assert(request->hasBeenExecuted()); m_result_queue.lock(); @@ -240,7 +242,7 @@ namespace Online{ * Calls the callback method of the request and takes care of memory * management if necessary. */ - void HTTPManager::handleResultQueue() + void RequestManager::handleResultQueue() { Request * request = NULL; m_result_queue.lock(); @@ -267,7 +269,7 @@ namespace Online{ /** Should be called every frame and takes care of processing the result * queue and polling the database server if a user is signed in. */ - void HTTPManager::update(float dt) + void RequestManager::update(float dt) { handleResultQueue(); diff --git a/src/online/http_manager.hpp b/src/online/request_manager.hpp similarity index 91% rename from src/online/http_manager.hpp rename to src/online/request_manager.hpp index d9e95f47d..a8b57e8e3 100644 --- a/src/online/http_manager.hpp +++ b/src/online/request_manager.hpp @@ -18,8 +18,8 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -#ifndef HTTP_MANAGER_HPP -#define HTTP_MANAGER_HPP +#ifndef HEADER_REQUEST_MANAGER_HPP +#define HEADER_REQUEST_MANAGER_HPP #include "io/xml_node.hpp" #include "online/request.hpp" @@ -39,13 +39,14 @@ #include -namespace Online{ +namespace Online +{ /** * \brief Class to connect with a server over HTTP(S) * \ingroup online */ - class HTTPManager + class RequestManager { protected: @@ -79,14 +80,14 @@ namespace Online{ static void *mainLoop(void *obj); - HTTPManager(); //const std::string &url - ~HTTPManager(); + RequestManager(); //const std::string &url + ~RequestManager(); public: static const int HTTP_MAX_PRIORITY = 9999; // singleton - static HTTPManager* get(); + static RequestManager* get(); static void deallocate(); static bool isRunning(); @@ -98,9 +99,9 @@ namespace Online{ bool getAbort(){ return m_abort.getAtomic(); }; void update(float dt); - }; //class HTTPManager + }; //class RequestManager } // namespace Online -#endif // HTTP_MANAGER_HPP +#endif // request_manager_HPP /*EOF*/ diff --git a/src/online/servers_manager.cpp b/src/online/servers_manager.cpp index c810e01b3..248441c4c 100644 --- a/src/online/servers_manager.cpp +++ b/src/online/servers_manager.cpp @@ -78,7 +78,7 @@ namespace Online{ request->setServerURL("client-user.php"); request->addParameter("action",std::string("get_server_list")); if (request_now) - HTTPManager::get()->addRequest(request); + RequestManager::get()->addRequest(request); } return request; } diff --git a/src/online/servers_manager.hpp b/src/online/servers_manager.hpp index 808ae6b1b..3c0d26a40 100644 --- a/src/online/servers_manager.hpp +++ b/src/online/servers_manager.hpp @@ -22,7 +22,8 @@ #include "utils/ptr_vector.hpp" #include "utils/types.hpp" #include "online/server.hpp" -#include "http_manager.hpp" +#include "online/request_manager.hpp" +#include "online/xml_request.hpp" #include "utils/synchronised.hpp" diff --git a/src/online/xml_request.cpp b/src/online/xml_request.cpp new file mode 100644 index 000000000..d1a663886 --- /dev/null +++ b/src/online/xml_request.cpp @@ -0,0 +1,82 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 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 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "online/xml_request.hpp" + +#include "config/user_config.hpp" +#include "online/request_manager.hpp" +#include "utils/constants.hpp" +#include "utils/translation.hpp" + +#ifdef WIN32 +# include +#endif + +#include + +#include + + +namespace Online +{ + + /** Creates a HTTP(S) request that will automatically parse the answer into + * a XML structure. + * \param manage_memory whether or not the RequestManager should take care of + * deleting the object after all callbacks have been done. + * \param priority by what priority should the RequestManager take care of + * this request. + */ + XMLRequest::XMLRequest(bool manage_memory, int priority) + : HTTPRequest(manage_memory, priority) + { + m_info = ""; + m_success = false; + m_xml_data = NULL; + } // XMLRequest + + // ------------------------------------------------------------------------ + /** Cleans up the XML tree. */ + XMLRequest::~XMLRequest() + { + delete m_xml_data; + } // ~XMLRequest + + // ------------------------------------------------------------------------ + /** On a successful download converts the string into an XML tree. + */ + void XMLRequest::afterOperation() + { + m_xml_data = file_manager->createXMLTreeFromString(getData()); + if(getResult() != CURLE_OK) + Log::error("XMLRequest::afterOperation", + "curl_easy_perform() failed: %s", + curl_easy_strerror(getResult())); + m_success = false; + std::string rec_success; + if(m_xml_data->get("success", &rec_success)) + { + m_success = rec_success =="yes"; + m_xml_data->get("info", &m_info); + } + else + m_info = _("Unable to connect to the server. Check your internet " + "connection or try again later."); + HTTPRequest::afterOperation(); + } // afterOperation + + +} // namespace Online diff --git a/src/online/xml_request.hpp b/src/online/xml_request.hpp new file mode 100644 index 000000000..120bb1691 --- /dev/null +++ b/src/online/xml_request.hpp @@ -0,0 +1,97 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2011-2013 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 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HEADER_XML_REQUEST_HPP +#define HEADER_XML_REQUEST_HPP + +#include "io/file_manager.hpp" +#include "online/http_request.hpp" +#include "utils/cpp2011.h" +#include "utils/string_utils.hpp" +#include "utils/synchronised.hpp" + +#ifdef WIN32 +# include +#endif +#include +#include +#include + +namespace Online +{ + /** A http request expecting a xml return value. + */ + class XMLRequest : public HTTPRequest + { + private: + /** On a successful download contains the converted XML tree. */ + XMLNode *m_xml_data; + + /** Additional info contained the downloaded data (or an error + * message if a problem occurred). */ + irr::core::stringw m_info; + + /** True if the request was successful executed on the server. */ + bool m_success; + + protected: + virtual void afterOperation() OVERRIDE; + + public : + XMLRequest(bool manage_memory = false, int priority = 1); + virtual ~XMLRequest(); + + // ------------------------------------------------------------------------ + /** Get the downloaded XML tree. + * \pre request has to be executed. + * \return get the complete result from the request reply. + */ + const XMLNode * getXMLData() const + { + assert(hasBeenExecuted()); + return m_xml_data; + } // getXMLData + + // ------------------------------------------------------------------------ + /** Returns the additional information (or error message) contained in + * a finished request. + * \pre request had to be executed. + * \return get the info from the request reply + */ + const irr::core::stringw & getInfo() const + { + assert(hasBeenExecuted()); + return m_info; + } // getInfo + + // -------------------------------------------------------------------- + /** Returns whether the request was successfully executed on the server. + * \pre request had to be executed. + * \return whether or not the request was a success. */ + bool isSuccess() const + { + assert(hasBeenExecuted()); + return m_success; + } // isSuccess + + }; // class XMLRequest + +} //namespace Online + +#endif +