diff --git a/src/challenges/challenge_data.hpp b/src/challenges/challenge_data.hpp index c357141f1..59e065b0a 100644 --- a/src/challenges/challenge_data.hpp +++ b/src/challenges/challenge_data.hpp @@ -42,8 +42,8 @@ public: UNLOCK_GP, UNLOCK_MODE, UNLOCK_KART, - UNLOCK_DIFFICULTY} - ; + UNLOCK_DIFFICULTY + }; // ------------------------------------------------------------------------ class UnlockableFeature { diff --git a/src/config/player_manager.hpp b/src/config/player_manager.hpp index 5ebbf68c0..a4a6e1f22 100644 --- a/src/config/player_manager.hpp +++ b/src/config/player_manager.hpp @@ -156,8 +156,4 @@ public: } // increaseAchievement // ------------------------------------------------------------------------ }; // PlayerManager - - #endif - -/*EOF*/ diff --git a/src/network/protocols/get_peer_address.cpp b/src/network/protocols/get_peer_address.cpp index 056e3e0df..e03eac2ff 100644 --- a/src/network/protocols/get_peer_address.cpp +++ b/src/network/protocols/get_peer_address.cpp @@ -45,8 +45,7 @@ void GetPeerAddress::asynchronousUpdate() if (m_state == NONE) { m_request = new Online::XMLRequest(); - PlayerManager::setUserDetails(m_request, "get", - "address-management.php"); + PlayerManager::setUserDetails(m_request, "get", API_ADDRESS_PATH); m_request->addParameter("peer_id",m_peer_id); Online::RequestManager::get()->addRequest(m_request); diff --git a/src/network/protocols/hide_public_address.cpp b/src/network/protocols/hide_public_address.cpp index e235e57fc..e64571c7d 100644 --- a/src/network/protocols/hide_public_address.cpp +++ b/src/network/protocols/hide_public_address.cpp @@ -42,8 +42,7 @@ void HidePublicAddress::asynchronousUpdate() if (m_state == NONE) { m_request = new Online::XMLRequest(); - PlayerManager::setUserDetails(m_request, "unset", - "address-management.php"); + PlayerManager::setUserDetails(m_request, "unset", API_ADDRESS_PATH); Online::RequestManager::get()->addRequest(m_request); m_state = REQUEST_PENDING; diff --git a/src/network/protocols/quick_join_protocol.cpp b/src/network/protocols/quick_join_protocol.cpp index 9352ce35b..837794c9c 100644 --- a/src/network/protocols/quick_join_protocol.cpp +++ b/src/network/protocols/quick_join_protocol.cpp @@ -45,7 +45,7 @@ void QuickJoinProtocol::asynchronousUpdate() TransportAddress addr = NetworkManager::getInstance()->getPublicAddress(); m_request = new Online::XMLRequest(); PlayerManager::setUserDetails(m_request, "quick-join"); - m_request->setServerURL("address-management.php"); + m_request->setServerURL(API_ADDRESS_PATH); Online::RequestManager::get()->addRequest(m_request); m_state = REQUEST_PENDING; diff --git a/src/network/protocols/request_connection.cpp b/src/network/protocols/request_connection.cpp index 49449e517..94670a3cf 100644 --- a/src/network/protocols/request_connection.cpp +++ b/src/network/protocols/request_connection.cpp @@ -72,8 +72,7 @@ void RequestConnection::asynchronousUpdate() case NONE: { m_request = new ServerJoinRequest(); - PlayerManager::setUserDetails(m_request, "request-connection", - "address-management.php"); + PlayerManager::setUserDetails(m_request, "request-connection", API_ADDRESS_PATH); m_request->addParameter("server_id",m_server_id); m_request->queue(); m_state = REQUEST_PENDING; diff --git a/src/network/protocols/server_lobby_room_protocol.cpp b/src/network/protocols/server_lobby_room_protocol.cpp index d067ccecf..61ee15f53 100644 --- a/src/network/protocols/server_lobby_room_protocol.cpp +++ b/src/network/protocols/server_lobby_room_protocol.cpp @@ -183,8 +183,7 @@ void ServerLobbyRoomProtocol::checkIncomingConnectionRequests() last_poll_time = StkTime::getRealTime(); TransportAddress addr = NetworkManager::getInstance()->getPublicAddress(); Online::XMLRequest* request = new Online::XMLRequest(); - PlayerManager::setUserDetails(request, "poll-connection-requests", - "address-management.php"); + PlayerManager::setUserDetails(request, "poll-connection-requests", API_ADDRESS_PATH); request->addParameter("address",addr.ip); request->addParameter("port",addr.port); @@ -564,7 +563,7 @@ void ServerLobbyRoomProtocol::playerMinorVote(Event* event) * Byte 0 1 5 6 N+6 N+7 N+8 * ----------------------------------------------------------- * Size | 1 | 4 | 1 | N | 1 | 1 | - * Data | 4 | priv token | N | track name | 1 | track number (gp) | + * Data | 4 | priv token | N | track name | 1 | track number (gp) | * ----------------------------------------------------------- */ void ServerLobbyRoomProtocol::playerTrackVote(Event* event) @@ -597,7 +596,7 @@ void ServerLobbyRoomProtocol::playerTrackVote(Event* event) * Byte 0 1 5 6 7 8 9 * --------------------------------------------------------- * Size | 1 | 4 | 1 | 1 | 1 | 1 | - * Data | 4 | priv token | 1 | reversed | 1 | track number (gp) | + * Data | 4 | priv token | 1 | reversed | 1 | track number (gp) | * --------------------------------------------------------- */ void ServerLobbyRoomProtocol::playerReversedVote(Event* event) @@ -630,7 +629,7 @@ void ServerLobbyRoomProtocol::playerReversedVote(Event* event) * Byte 0 1 5 6 7 8 9 * ----------------------------------------------------- * Size | 1 | 4 | 1 | 1 | 1 | 1 | - * Data | 4 | priv token | 1 | laps | 1 | track number (gp) | + * Data | 4 | priv token | 1 | laps | 1 | track number (gp) | * ----------------------------------------------------- */ void ServerLobbyRoomProtocol::playerLapsVote(Event* event) diff --git a/src/network/protocols/show_public_address.cpp b/src/network/protocols/show_public_address.cpp index 8694e9ab6..7920b3557 100644 --- a/src/network/protocols/show_public_address.cpp +++ b/src/network/protocols/show_public_address.cpp @@ -43,8 +43,7 @@ void ShowPublicAddress::asynchronousUpdate() { TransportAddress addr = NetworkManager::getInstance()->getPublicAddress(); m_request = new Online::XMLRequest(); - PlayerManager::setUserDetails(m_request, "set", - "address-management.php"); + PlayerManager::setUserDetails(m_request, "set", API_ADDRESS_PATH); m_request->addParameter("address",addr.ip); m_request->addParameter("port",addr.port); m_request->addParameter("private_port",NetworkManager::getInstance()->getHost()->getPort()); diff --git a/src/network/protocols/start_server.cpp b/src/network/protocols/start_server.cpp index 6641f410c..41bc34d6c 100644 --- a/src/network/protocols/start_server.cpp +++ b/src/network/protocols/start_server.cpp @@ -42,8 +42,7 @@ void StartServer::asynchronousUpdate() { TransportAddress addr = NetworkManager::getInstance()->getPublicAddress(); m_request = new Online::XMLRequest(); - PlayerManager::setUserDetails(m_request, "start-server", - "address-management.php"); + PlayerManager::setUserDetails(m_request, "start-server", API_ADDRESS_PATH); m_request->addParameter("address",addr.ip); m_request->addParameter("port",addr.port); m_request->addParameter("private_port",NetworkManager::getInstance()->getHost()->getPort()); diff --git a/src/network/protocols/stop_server.cpp b/src/network/protocols/stop_server.cpp index 19216596a..eb2efb5f2 100644 --- a/src/network/protocols/stop_server.cpp +++ b/src/network/protocols/stop_server.cpp @@ -47,8 +47,7 @@ void StopServer::asynchronousUpdate() { TransportAddress addr = NetworkManager::getInstance()->getPublicAddress(); m_request = new Online::XMLRequest(); - PlayerManager::setUserDetails(m_request, "stop-server", - "address-management.php"); + PlayerManager::setUserDetails(m_request, "stop-server", API_ADDRESS_PATH); m_request->addParameter("address",addr.ip); m_request->addParameter("port",addr.port); Log::info("StopServer", "address %u, port %d", addr.ip, addr.port); diff --git a/src/online/http_request.cpp b/src/online/http_request.cpp index 6b24f7f1b..d0bd90c13 100644 --- a/src/online/http_request.cpp +++ b/src/online/http_request.cpp @@ -26,10 +26,8 @@ #endif #include - #include - namespace Online { /** Creates a HTTP(S) request that will have a raw string as result. (Can @@ -60,7 +58,8 @@ namespace Online // A http request should not even be created when internet is disabled assert(UserConfigParams::m_internet_status == RequestManager::IPERM_ALLOWED); - assert(filename.size()>0); + assert(filename.size() > 0); + init(); m_filename = file_manager->getAddonsFile(filename); } // HTTPRequest(filename ...) @@ -76,6 +75,7 @@ namespace Online // A http request should not even be created when internet is disabled assert(UserConfigParams::m_internet_status == RequestManager::IPERM_ALLOWED); + init(); m_filename = file_manager->getAddonsFile(filename); } // HTTPRequest(filename ...) @@ -100,20 +100,20 @@ namespace Online */ void HTTPRequest::setServerURL(const std::string& path) { - setURL((std::string)UserConfigParams::m_server_multiplayer+path); + setURL((std::string)UserConfigParams::m_server_multiplayer + path); } // setServerURL // ------------------------------------------------------------------------ /** A handy shortcut that appends the given path to the URL of the addons * server. - * \param path The path to add to the server. + * \param path The path to add to the server, without the trailing slash */ void HTTPRequest::setAddonsURL(const std::string& path) { - setURL((std::string)UserConfigParams::m_server_addons - + "/" + path); + setURL((std::string)UserConfigParams::m_server_addons + "/" + path); } // set AddonsURL - // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ /** Checks the request if it has enough (correct) information to be * executed (and thus allowed to add to the queue). */ @@ -128,7 +128,7 @@ namespace Online void HTTPRequest::prepareOperation() { m_curl_session = curl_easy_init(); - if(!m_curl_session) + if (!m_curl_session) { Log::error("HTTPRequest::prepareOperation", "LibCurl session not initialized."); @@ -145,9 +145,9 @@ namespace Online curl_easy_setopt(m_curl_session, CURLOPT_LOW_SPEED_LIMIT, 10); curl_easy_setopt(m_curl_session, CURLOPT_LOW_SPEED_TIME, 20); //curl_easy_setopt(m_curl_session, CURLOPT_VERBOSE, 1L); - if(m_filename.size()==0) + if (m_filename.size() == 0) { - //https + // https, load certificate info struct curl_slist *chunk = NULL; chunk = curl_slist_append(chunk, "Host: api.stkaddons.net"); curl_easy_setopt(m_curl_session, CURLOPT_HTTPHEADER, chunk); @@ -163,15 +163,15 @@ namespace Online */ void HTTPRequest::operation() { - if(!m_curl_session) + if (!m_curl_session) return; FILE *fout = NULL; - if(m_filename.size()>0) + if (m_filename.size() > 0) { fout = fopen((m_filename+".part").c_str(), "wb"); - if(!fout) + if (!fout) { Log::error("HTTPRequest", "Can't open '%s' for writing, ignored.", @@ -190,23 +190,26 @@ namespace Online } // All parameters added have a '&' added - if(m_parameters.size()>0) + if (m_parameters.size() > 0) { m_parameters.erase(m_parameters.size()-1); } - if(m_parameters.size()==0) + if (m_parameters.size() == 0) + { Log::info("HTTPRequest", "Downloading %s", m_url.c_str()); - else if (Log::getLogLevel()<=Log::LL_INFO) + } + else if (Log::getLogLevel() <= Log::LL_INFO) { // Avoid printing the password or token, just replace them with *s std::string param = m_parameters; + // List of strings whose values should not be printed. "" is the // end indicator. static std::string dont_print[] = { "&password=", "&token=", "¤t=", "&new1=", "&new2=", ""}; unsigned int j = 0; - while (dont_print[j].size()>0) + while (dont_print[j].size() > 0) { // Get the string that should be replaced. std::size_t pos = param.find(dont_print[j]); @@ -221,11 +224,11 @@ namespace Online } // if string found j++; } // while dont_print[j].size()>0 - Log::info("HTTPRequest", "Sending %s to %s", - param.c_str(), m_url.c_str()); - } - curl_easy_setopt(m_curl_session, CURLOPT_POSTFIELDS, - m_parameters.c_str()); + + Log::info("HTTPRequest", "Sending %s to %s", param.c_str(), m_url.c_str()); + } // end log http request + + curl_easy_setopt(m_curl_session, CURLOPT_POSTFIELDS, m_parameters.c_str()); std::string uagent( std::string("SuperTuxKart/") + STK_VERSION ); #ifdef WIN32 uagent += (std::string)" (Windows)"; @@ -243,17 +246,18 @@ namespace Online m_curl_code = curl_easy_perform(m_curl_session); Request::operation(); - if(fout) + if (fout) { fclose(fout); - if(m_curl_code==CURLE_OK) + if (m_curl_code == CURLE_OK) { if(UserConfigParams::logAddons()) Log::info("HTTPRequest", "Download successful."); + // The behaviour of rename is unspecified if the target // file should already exist - so remove it. bool ok = file_manager->removeFile(m_filename); - if(!ok) + if (!ok) { Log::error("addons", "Could not removed existing addons.xml file."); @@ -261,8 +265,9 @@ namespace Online } int ret = rename((m_filename+".part").c_str(), m_filename.c_str() ); + // In case of an error, set the status to indicate this - if(ret!=0) + if (ret != 0) { Log::error("addons", "Could not rename downloaded addons.xml file!"); @@ -279,10 +284,11 @@ namespace Online */ void HTTPRequest::afterOperation() { - if(m_curl_code == CURLE_OK) + if (m_curl_code == CURLE_OK) setProgress(1.0f); else setProgress(-1.0f); + Request::afterOperation(); curl_easy_cleanup(m_curl_session); } // afterOperation @@ -322,7 +328,7 @@ namespace Online // 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()) && + if ((request_manager->getAbort() || request->isCancelled()) && request->isAbortable() ) { // Indicates to abort the current download, which means that this @@ -331,23 +337,24 @@ namespace Online } float f; - if(download_now < download_total) + 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; + 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; + 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 index 114487c95..4eec9636a 100644 --- a/src/online/http_request.hpp +++ b/src/online/http_request.hpp @@ -32,6 +32,10 @@ #include #include +#define API_VERSION "v2" +#define API_USER_PATH "client-user.php" +#define API_ADDRESS_PATH "address-management.php" + namespace Online { /** A http request. @@ -78,22 +82,20 @@ namespace Online void init(); public : - HTTPRequest(bool manage_memory = false, - int priority = 1); - HTTPRequest(const std::string &filename, - bool manage_memory = false, - int priority = 1); - HTTPRequest(const char * const filename, - bool manage_memory = false, - int priority = 1); - virtual ~HTTPRequest() {}; + HTTPRequest(bool manage_memory = false, int priority = 1); + HTTPRequest(const std::string &filename, bool manage_memory = false, + int priority = 1); + HTTPRequest(const char * const filename, bool manage_memory = false, + int priority = 1); + virtual ~HTTPRequest() {} virtual bool isAllowedToAdd() const OVERRIDE; void setServerURL(const std::string& url); void setAddonsURL(const std::string& path); + // ------------------------------------------------------------------------ - /** Returns true if there was an error downloading the file. - */ + /** Returns true if there was an error downloading the file. */ bool hadDownloadError() const { return m_curl_code!=CURLE_OK; } + // ------------------------------------------------------------------------ /** Returns the curl error message if an error has occurred. * \pre m_curl_code!=CURLE_OK @@ -116,47 +118,50 @@ namespace Online } // getData // -------------------------------------------------------------------- - /** Sets a parameter to 'value' (std::string). - */ + /** Sets a parameter to 'value' (std::string). */ void addParameter(const std::string & name, const std::string &value) { // Call the template, so that the strings are escaped properly addParameter(name, value.c_str()); - }; // addParameter + } // addParameter + // -------------------------------------------------------------------- - /** Sets a parameter to 'value' (stringw). - */ + /** Sets a parameter to 'value' (stringw). */ void addParameter(const std::string & name, const irr::core::stringw &value) { core::stringc s = core::stringc(value.c_str()); + // Call the template to escape strings properly addParameter(name, s.c_str()); } // addParameter // -------------------------------------------------------------------- - /** Sets a parameter to 'value' (arbitrary types). - */ + /** Sets a parameter to 'value' (arbitrary types). */ template void addParameter(const std::string & name, const T& value) { assert(isPreparing()); std::string s = StringUtils::toString(value); - char *s1 = curl_easy_escape(m_curl_session, name.c_str(), - name.size() ); + + char *s1 = curl_easy_escape(m_curl_session, name.c_str(), name.size()); char *s2 = curl_easy_escape(m_curl_session, s.c_str(), s.size()); - m_parameters.append(std::string(s1)+"="+s2+"&"); + m_parameters.append(std::string(s1) + "=" + s2 + "&"); curl_free(s1); curl_free(s2); } // addParameter + // -------------------------------------------------------------------- /** Returns the current progress. */ float getProgress() const { return m_progress.getAtomic(); } + // -------------------------------------------------------------------- /** Sets the current progress. */ - void setProgress(float f) { m_progress.setAtomic(f); } + 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) @@ -166,8 +171,5 @@ namespace Online } // setURL }; // class HTTPRequest - } //namespace Online - -#endif - +#endif // HEADER_HTTP_REQUEST_HPP diff --git a/src/online/online_player_profile.cpp b/src/online/online_player_profile.cpp index 389805754..aff207a2d 100644 --- a/src/online/online_player_profile.cpp +++ b/src/online/online_player_profile.cpp @@ -16,7 +16,6 @@ // 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/online_player_profile.hpp" #include "achievements/achievements_manager.hpp" @@ -55,14 +54,18 @@ namespace Online const std::string &action, const std::string &php_script) const { - if (php_script.size()>0) + if (php_script.size() > 0) + { request->setServerURL(php_script); - else - request->setServerURL("client-user.php"); + } + else // default path + { + request->setServerURL(API_USER_PATH); + } if (m_profile) request->addParameter("userid", m_profile->getID()); - if(m_online_state == OS_SIGNED_IN) + if (m_online_state == OS_SIGNED_IN) request->addParameter("token", m_token); if (action.size() > 0) request->addParameter("action", action); @@ -86,16 +89,17 @@ namespace Online m_profile = NULL; } // OnlinePlayerProfile + // ------------------------------------------------------------------------ - /** Request a login using the saved credentials of the user. - */ + /** Request a login using the saved credentials of the user. */ void OnlinePlayerProfile::requestSavedSession() { - SignInRequest * request = NULL; + SignInRequest *request = NULL; if (m_online_state == OS_SIGNED_OUT && hasSavedSession()) { request = new SignInRequest(true); setUserDetails(request, "saved-session"); + // The userid must be taken from the saved data, // setUserDetails takes it from current data. request->addParameter("userid", getSavedUserId()); @@ -117,18 +121,20 @@ namespace Online // If the player changes the online account, there can be a // logout stil happening. assert(m_online_state == OS_SIGNED_OUT || - m_online_state == OS_SIGNING_OUT ); + m_online_state == OS_SIGNING_OUT); SignInRequest * request = new SignInRequest(false); + // We can't use setUserDetail here, since there is no token yet - request->setServerURL("client-user.php"); - request->addParameter("action","connect"); - request->addParameter("username",username); - request->addParameter("password",password); + request->setServerURL(API_USER_PATH); + request->addParameter("action", "connect"); + request->addParameter("username", username); + request->addParameter("password", password); request->addParameter("save-session", rememberPassword() ? "true" : "false"); request->queue(); m_online_state = OS_SIGNING_IN; + return request; } // requestSignIn @@ -143,13 +149,13 @@ namespace Online // If the login is successful, reset any saved session of other // local players using the same online account (which are now invalid) - if(isSuccess()) + if (isSuccess()) { PlayerProfile *current = PlayerManager::getCurrentPlayer(); - for(unsigned int i=0; igetNumPlayers(); i++) + for (unsigned int i = 0; i < PlayerManager::get()->getNumPlayers(); i++) { PlayerProfile *player = PlayerManager::get()->getPlayer(i); - if(player!=current && + if(player != current && player->hasSavedSession() && player->getLastOnlineName() == current->getLastOnlineName()) { @@ -157,7 +163,7 @@ namespace Online } } } - if(login) + if (login) { if(isSuccess()) login->loginSuccessful(); @@ -178,12 +184,14 @@ namespace Online { if (success) { - int token_fetched = input->get("token", &m_token); core::stringw username(""); - int username_fetched = input->get("username", &username); uint32_t userid(0); + + int token_fetched = input->get("token", &m_token); + int username_fetched = input->get("username", &username); int userid_fetched = input->get("userid", &userid); setLastOnlineName(username); + m_profile = new OnlineProfile(userid, username, true); assert(token_fetched && username_fetched && userid_fetched); m_online_state = OS_SIGNED_IN; @@ -191,8 +199,10 @@ namespace Online { saveSession(getOnlineId(), getToken()); } + ProfileManager::get()->addPersistent(m_profile); std::string achieved_string(""); + // Even if no achievements were sent, we have to call sync // in order to upload local achievements to the server input->get("achieved", &achieved_string); @@ -260,6 +270,7 @@ namespace Online { GUIEngine::Screen *screen = GUIEngine::getCurrentScreen(); BaseUserScreen *user_screen = dynamic_cast(screen); + // We can't do much of error handling here, no screen waits for // a logout to finish, so we can only log the message to screen, // and otherwise mark the player logged out internally. @@ -269,20 +280,21 @@ namespace Online "There were some connection issues while signing out. " "Report a bug if this caused issues."); Log::warn("OnlinePlayerProfile::signOut", core::stringc(info.c_str()).c_str()); - if(user_screen) + if (user_screen) user_screen->logoutError(info); } else { - if(user_screen) + if (user_screen) user_screen->logoutSuccessful(); } ProfileManager::get()->clearPersistent(); m_profile = NULL; m_online_state = OS_SIGNED_OUT; + // Discard token if session should not be saved. - if(!rememberPassword()) + if (!rememberPassword()) clearSession(); } // signOut @@ -293,6 +305,7 @@ namespace Online void OnlinePlayerProfile::requestPoll() const { assert(m_online_state == OS_SIGNED_IN); + OnlinePlayerProfile::PollRequest * request = new OnlinePlayerProfile::PollRequest(); setUserDetails(request, "poll"); request->queue(); @@ -304,127 +317,137 @@ namespace Online */ void OnlinePlayerProfile::PollRequest::callback() { - if(isSuccess()) + // connection error + if (!isSuccess()) { - if (!PlayerManager::getCurrentPlayer()->isLoggedIn()) - return; - if (PlayerManager::getCurrentPlayer()->getProfile()->hasFetchedFriends()) + Log::error("Online Player Profile", "Poll request failed"); + return; + } + + if (!PlayerManager::getCurrentPlayer()->isLoggedIn()) + return; + + if (PlayerManager::getCurrentPlayer()->getProfile()->hasFetchedFriends()) + { + std::string online_friends_string(""); + if (getXMLData()->get("online", &online_friends_string) == 1) { - std::string online_friends_string(""); - if(getXMLData()->get("online", &online_friends_string) == 1) + std::vector online_friends = + StringUtils::splitToUInt(online_friends_string, ' '); + + // flag that indicates if a current online friend went offline + bool went_offline = false; + + // iterate over all friends and find out if they come online or not + // filling the notification messages + std::vector friends = + PlayerManager::getCurrentPlayer()->getProfile()->getFriends(); + std::vector to_notify; + for (unsigned int i = 0; i < friends.size(); ++i) { - std::vector online_friends = - StringUtils::splitToUInt(online_friends_string, ' '); - bool went_offline = false; - std::vector friends = - PlayerManager::getCurrentPlayer()->getProfile()->getFriends(); - std::vector to_notify; - for(unsigned int i = 0; i < friends.size(); ++i) - { - bool now_online = false; - std::vector::iterator iter = - std::find(online_friends.begin(), - online_friends.end(), friends[i]); - if (iter != online_friends.end()) - { - now_online = true; - online_friends.erase(iter); - } - OnlineProfile * profile = - ProfileManager::get()->getProfileByID(friends[i]); - OnlineProfile::RelationInfo * relation_info = - profile->getRelationInfo(); - if( relation_info->isOnline() ) - { - if (!now_online) - { - relation_info->setOnline(false); - went_offline = true; - } - } - else - { - if (now_online) - { - //User came online - relation_info->setOnline(true); - // Do this because a user might have accepted - // a pending friend request. - profile->setFriend(); - to_notify.push_back(profile->getUserName()); - } - } + bool now_online = false; + std::vector::iterator found_friend = + std::find(online_friends.begin(), + online_friends.end(), friends[i]); + if (found_friend != online_friends.end()) + { + now_online = true; + online_friends.erase(found_friend); + } - } + OnlineProfile * profile = + ProfileManager::get()->getProfileByID(friends[i]); + OnlineProfile::RelationInfo * relation_info = + profile->getRelationInfo(); - if(to_notify.size() > 0) - { - core::stringw message(""); - if(to_notify.size() == 1) - { - message = _("%s is now online.", to_notify[0]); - } - else if(to_notify.size() == 2) - { - message = _("%s and %s are now online.", - to_notify[0], to_notify[1] ); - } - else if(to_notify.size() == 3) - { - message = _("%s, %s and %s are now online.", - to_notify[0], to_notify[1], to_notify[2]); - } - else if(to_notify.size() > 3) - { - message = _("%d friends are now online.", - to_notify.size()); - } - MessageQueue::add(MessageQueue::MT_FRIEND, message); - } - else if(went_offline) - { - OnlineProfileFriends::getInstance()->refreshFriendsList(); - } + if (relation_info->isOnline()) + { + if (!now_online) // the friend went offline + { + relation_info->setOnline(false); + went_offline = true; + } + } + else + { + if (now_online) // friend came online + { + relation_info->setOnline(true); + + // Do this because a user might have accepted + // a pending friend request. + profile->setFriend(); + to_notify.push_back(profile->getUserName()); + } + } } + + if (to_notify.size() > 0) + { + core::stringw message(""); + if(to_notify.size() == 1) + { + message = _("%s is now online.", to_notify[0]); + } + else if(to_notify.size() == 2) + { + message = _("%s and %s are now online.", + to_notify[0], to_notify[1] ); + } + else if(to_notify.size() == 3) + { + message = _("%s, %s and %s are now online.", + to_notify[0], to_notify[1], to_notify[2]); + } + else if(to_notify.size() > 3) + { + message = _("%d friends are now online.", + to_notify.size()); + } + MessageQueue::add(MessageQueue::MT_FRIEND, message); + } + else if (went_offline) + { + OnlineProfileFriends::getInstance()->refreshFriendsList(); + } + } + } + else + { + PlayerManager::getCurrentPlayer()->getProfile()->fetchFriends(); + } + + int friend_request_count = 0; + for (unsigned int i = 0; i < getXMLData()->getNumNodes(); i++) + { + const XMLNode * node = getXMLData()->getNode(i); + if (node->getName() == "new_friend_request") + { + OnlineProfile::RelationInfo * ri = + new OnlineProfile::RelationInfo("New", false, true, true); + OnlineProfile * p = new OnlineProfile(node); + p->setRelationInfo(ri); + ProfileManager::get()->addPersistent(p); + friend_request_count++; + } + } + + if (friend_request_count > 0) + { + core::stringw message(""); + if (friend_request_count > 1) + { + message = _("You have %d new friend requests!", + friend_request_count); } else { - PlayerManager::getCurrentPlayer()->getProfile()->fetchFriends(); + message = _("You have a new friend request!"); } - int friend_request_count = 0; - for(unsigned int i = 0; i < getXMLData()->getNumNodes(); i++) - { - const XMLNode * node = getXMLData()->getNode(i); - if(node->getName() == "new_friend_request") - { - OnlineProfile::RelationInfo * ri = - new OnlineProfile::RelationInfo("New", false, true, true); - OnlineProfile * p = new OnlineProfile(node); - p->setRelationInfo(ri); - ProfileManager::get()->addPersistent(p); - friend_request_count++; - } - } - if(friend_request_count > 0) - { - core::stringw message(""); - if(friend_request_count > 1) - { - message = _("You have %d new friend requests!", - friend_request_count); - } - else - { - message = _("You have a new friend request!"); - } - MessageQueue::add(MessageQueue::MT_FRIEND, message); - OnlineProfileFriends::getInstance()->refreshFriendsList(); - } + MessageQueue::add(MessageQueue::MT_FRIEND, message); + OnlineProfileFriends::getInstance()->refreshFriendsList(); } - // FIXME show connection error?? - // Perhaps show something after 2 misses. - } // PollRequest::callback // ------------------------------------------------------------------------ @@ -432,11 +455,12 @@ namespace Online */ uint32_t OnlinePlayerProfile::getOnlineId() const { - if((m_online_state == OS_SIGNED_IN )) + if (m_online_state == OS_SIGNED_IN) { assert(m_profile != NULL); return m_profile->getID(); } + return 0; } // getOnlineId diff --git a/src/online/online_player_profile.hpp b/src/online/online_player_profile.hpp index 58c8353f2..52a249daa 100644 --- a/src/online/online_player_profile.hpp +++ b/src/online/online_player_profile.hpp @@ -37,7 +37,6 @@ class PlayerManager; namespace Online { - class OnlineProfile; // ============================================================================ @@ -48,75 +47,73 @@ namespace Online */ class OnlinePlayerProfile : public PlayerProfile { + public: + // ---------------------------------------------------------------- + class SignInRequest : public XMLRequest + { + virtual void callback (); public: - // ---------------------------------------------------------------- - class SignInRequest : public XMLRequest - { - virtual void callback (); - public: - SignInRequest(bool manage_memory = false) - : XMLRequest(manage_memory, /*priority*/10) {} - }; // SignInRequest - - // ---------------------------------------------------------------- - class PollRequest : public XMLRequest { - virtual void callback (); - public: - PollRequest() : XMLRequest(true) {} - }; // PollRequest - - private: - std::string m_token; - OnlineProfile *m_profile; - - /** The state of the player (logged in, logging in, ...) */ - PlayerProfile::OnlineState m_online_state; - - virtual void signIn(bool success, const XMLNode * input); - virtual void signOut(bool success, const XMLNode * input, - const irr::core::stringw &info); - virtual uint32_t getOnlineId() const; - virtual void setUserDetails(Online::HTTPRequest *request, - const std::string &action, - const std::string &php_script = "") const; - - virtual void requestPoll() const; - // ---------------------------------------------------------------- - /** Returns if this user is logged in. */ - virtual bool isLoggedIn() const - { - return m_online_state == PlayerProfile::OS_SIGNED_IN; - } // isLoggedIn - - // ---------------------------------------------------------------- - /** The online state of the player (i.e. logged out, logging in, - * logged in, ...). */ - PlayerProfile::OnlineState getOnlineState() const - { - return m_online_state; - } // getOnlineState - // ---------------------------------------------------------------- - /** Returns a pointer to the profile associated with the current - * user. */ - OnlineProfile* getProfile() const { return m_profile; } - // ---------------------------------------------------------------- - /** Returns the session token of the signed in user. */ - const std::string& getToken() const { return m_token; } - virtual void requestSavedSession(); - virtual void requestSignOut(); - virtual SignInRequest *requestSignIn(const irr::core::stringw &username, - const irr::core::stringw &password); + SignInRequest(bool manage_memory = false) + : XMLRequest(manage_memory, /*priority*/10) {} + }; // SignInRequest + // ---------------------------------------------------------------- + class PollRequest : public XMLRequest + { + virtual void callback (); public: - OnlinePlayerProfile(const XMLNode *player); - OnlinePlayerProfile(const core::stringw &name, bool is_guest = false); - virtual ~OnlinePlayerProfile() {}; - // ---------------------------------------------------------------- + PollRequest() : XMLRequest(true) {} + }; // PollRequest - }; // class OnlinePlayerProfile + private: + std::string m_token; + OnlineProfile *m_profile; + /** The state of the player (logged in, logging in, ...) */ + PlayerProfile::OnlineState m_online_state; + + virtual void signIn(bool success, const XMLNode * input); + virtual void signOut(bool success, const XMLNode * input, + const irr::core::stringw &info); + virtual uint32_t getOnlineId() const; + virtual void setUserDetails(Online::HTTPRequest *request, + const std::string &action, + const std::string &php_script = "") const; + + virtual void requestPoll() const; + + // ---------------------------------------------------------------- + /** Returns if this user is logged in. */ + virtual bool isLoggedIn() const + { + return m_online_state == PlayerProfile::OS_SIGNED_IN; + } // isLoggedIn + + // ---------------------------------------------------------------- + /** The online state of the player (i.e. logged out, logging in, + * logged in, ...). */ + PlayerProfile::OnlineState getOnlineState() const + { + return m_online_state; + } // getOnlineState + + // ---------------------------------------------------------------- + /** Returns a pointer to the profile associated with the current user. */ + OnlineProfile* getProfile() const { return m_profile; } + + // ---------------------------------------------------------------- + /** Returns the session token of the signed in user. */ + const std::string& getToken() const { return m_token; } + virtual void requestSavedSession(); + virtual void requestSignOut(); + virtual SignInRequest *requestSignIn(const irr::core::stringw &username, + const irr::core::stringw &password); + + public: + OnlinePlayerProfile(const XMLNode *player); + OnlinePlayerProfile(const core::stringw &name, bool is_guest = false); + virtual ~OnlinePlayerProfile() {} + // ---------------------------------------------------------------- + }; // class OnlinePlayerProfile } // namespace Online - -#endif - -/*EOF*/ +#endif // HEADER_CURRENT_ONLINE_USER_HPP diff --git a/src/online/online_profile.cpp b/src/online/online_profile.cpp index d3213d57c..0b1496aa1 100644 --- a/src/online/online_profile.cpp +++ b/src/online/online_profile.cpp @@ -16,7 +16,6 @@ // 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/online_profile.hpp" #include "config/player_manager.hpp" @@ -39,10 +38,10 @@ OnlineProfile::RelationInfo::RelationInfo(const irr::core::stringw & date, bool is_online, bool is_pending, bool is_asker) { - m_date = date; - m_is_online = is_online; - m_is_pending = is_pending; - m_is_asker = is_asker; + m_date = date; + m_is_online = is_online; + m_is_pending = is_pending; + m_is_asker = is_asker; } // RelationInfo::RelationInfo // ---------------------------------------------------------------------------- @@ -91,12 +90,11 @@ OnlineProfile::OnlineProfile(const XMLNode * xml, ConstructorType type) if (type == C_RELATION_INFO) { irr::core::stringw date(""); + bool is_pending = false, is_asker = false, is_online = false; + xml->get("date", &date); - std::string is_pending_string(""); - bool is_pending = false; xml->get("is_pending", &is_pending); - bool is_asker = false; - bool is_online = false; + if (is_pending) { xml->get("is_asker", &is_asker); @@ -113,7 +111,7 @@ OnlineProfile::OnlineProfile(const XMLNode * xml, ConstructorType type) xml->get("id", &m_id ); xml->get("user_name", &m_username); - m_is_current_user = (m_id == PlayerManager::getCurrentOnlineId()); + m_is_current_user = (m_id == PlayerManager::getCurrentOnlineId()); m_state = S_READY; } // OnlineProfile(XMLNode) @@ -133,6 +131,7 @@ void OnlineProfile::fetchAchievements() assert(PlayerManager::isCurrentLoggedIn()); if (m_has_fetched_achievements || m_is_current_user) return; + m_state = S_FETCHING; // ------------------------------------------------------------------------ @@ -187,6 +186,7 @@ void OnlineProfile::fetchFriends() assert(PlayerManager::isCurrentLoggedIn()); if (m_has_fetched_friends) return; + m_state = S_FETCHING; // ------------------------------------------------------------------------ @@ -258,9 +258,11 @@ void OnlineProfile::removeFriend(const uint32_t id) break; } else + { ++iter; - } -} // removeFriend + } + } // for friend in friends +} // removeFriend // ---------------------------------------------------------------------------- /** Adds a friend to the friend list. @@ -269,9 +271,14 @@ void OnlineProfile::removeFriend(const uint32_t id) void OnlineProfile::addFriend(const uint32_t id) { assert(m_has_fetched_friends); + + // find if friend id is is already in the user list for (unsigned int i = 0; i < m_friends.size(); i++) - if (m_friends[i] == id) - return; + { + if (m_friends[i] == id) + return; + } + m_friends.push_back(id); } // addFriend @@ -310,18 +317,25 @@ const OnlineProfile::IDList& OnlineProfile::getAchievements() void OnlineProfile::merge(OnlineProfile *profile) { assert(profile != NULL); - if (!this->m_has_fetched_friends && profile->m_has_fetched_friends) - this->m_friends = profile->m_friends; - if (!this->m_has_fetched_achievements && profile->m_has_fetched_achievements) - this->m_achievements = profile->m_achievements; - if (this->m_relation_info == NULL && profile->m_relation_info != NULL) + + // profile has fetched friends, use that instead + if (!m_has_fetched_friends && profile->m_has_fetched_friends) + m_friends = profile->m_friends; + + // profile has fetched achievements, use that instead + if (!m_has_fetched_achievements && profile->m_has_fetched_achievements) + m_achievements = profile->m_achievements; + + // current relation is not set, use the profile one + if (m_relation_info == NULL && profile->m_relation_info != NULL) { - this->m_relation_info = profile->m_relation_info; + m_relation_info = profile->m_relation_info; + // We don't want the destructor of the profile instance to destroy // the relation info profile->m_relation_info = NULL; } - delete profile; -} // merge + delete profile; +} // merge } // namespace Online diff --git a/src/online/online_profile.hpp b/src/online/online_profile.hpp index 01bcb975d..0ad3b86e4 100644 --- a/src/online/online_profile.hpp +++ b/src/online/online_profile.hpp @@ -24,9 +24,7 @@ #include "utils/types.hpp" #include "utils/ptr_vector.hpp" - #include - #include namespace Online @@ -54,16 +52,21 @@ public: bool m_is_pending; bool m_is_asker; irr::core::stringw m_date; + public: RelationInfo(const irr::core::stringw & date, bool is_online, bool is_pending, bool is_asker = false); void setOnline(bool online); + // -------------------------------------------------------------------- bool isPending() const { return m_is_pending; } + // -------------------------------------------------------------------- bool isAsker() const { return m_is_asker; } + // -------------------------------------------------------------------- const irr::core::stringw & getDate() const { return m_date; } + // -------------------------------------------------------------------- bool isOnline() const { return m_is_online; } }; // class RelationInfo @@ -104,12 +107,11 @@ private: void storeAchievements(const XMLNode * input); public: - OnlineProfile(const uint32_t & userid, - const irr::core::stringw & username, - bool is_current_user = false ); - OnlineProfile(const XMLNode * xml, - ConstructorType type = C_DEFAULT); - ~OnlineProfile(); + OnlineProfile(const uint32_t & userid, + const irr::core::stringw & username, + bool is_current_user = false ); + OnlineProfile(const XMLNode * xml, ConstructorType type = C_DEFAULT); + ~OnlineProfile(); void fetchFriends(); const IDList& getFriends(); void fetchAchievements(); @@ -118,49 +120,55 @@ public: void deleteRelationalInfo(); const IDList& getAchievements(); void merge(OnlineProfile * profile); + // ------------------------------------------------------------------------ /** Returns true if the achievements for this profile have been fetched. */ bool hasFetchedAchievements() const { return m_has_fetched_achievements; } + // ------------------------------------------------------------------------ /** Returns true if the friend list for this profile has been fetched. */ bool hasFetchedFriends() const { return m_has_fetched_friends; } + // ------------------------------------------------------------------------ /** True if the profile is not fetching data atm. */ bool isReady() const { return m_state == S_READY; } + // ------------------------------------------------------------------------ /** Returns true if this item is the current user. */ bool isCurrentUser() const { return m_is_current_user; } + // ------------------------------------------------------------------------ bool isFriend() const { return m_is_friend; } + // ------------------------------------------------------------------------ void setFriend() { m_is_friend = true; } + // ------------------------------------------------------------------------ RelationInfo* getRelationInfo() { return m_relation_info; } + // ------------------------------------------------------------------------ void setRelationInfo(RelationInfo * r) { delete m_relation_info; m_relation_info = r; } // setRelationInfo + // ------------------------------------------------------------------------ /** Sets the cache bit of this profile. Used by the cache eviction * algorithm. */ void setCacheBit(bool cache_bit) { m_cache_bit = cache_bit; } + // ------------------------------------------------------------------------ /** Returns the cache bit for this profile. Used by the cache eviction * algorithm. */ bool getCacheBit() const { return m_cache_bit; } + // ------------------------------------------------------------------------ /** Returns the online id of this profile. */ uint32_t getID() const { return m_id; } + // ------------------------------------------------------------------------ /** Returns the user name of this profile. */ const irr::core::stringw& getUserName() const { return m_username; } - // ------------------------------------------------------------------------ - }; // class OnlineProfile - } // namespace Online - -#endif - -/*EOF*/ +#endif // HEADER_ONLINE_PROFILE_HPP diff --git a/src/online/profile_manager.cpp b/src/online/profile_manager.cpp index b180b338a..f8099f3c5 100644 --- a/src/online/profile_manager.cpp +++ b/src/online/profile_manager.cpp @@ -16,7 +16,6 @@ // 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/profile_manager.hpp" #include "online/online_profile.hpp" @@ -50,7 +49,8 @@ ProfileManager::~ProfileManager() { clearPersistent(); ProfilesMap::iterator it; - for (it = m_profiles_cache.begin(); it != m_profiles_cache.end(); ++it) { + for (it = m_profiles_cache.begin(); it != m_profiles_cache.end(); ++it) + { delete it->second; } } // ~ProfileManager @@ -72,8 +72,8 @@ int ProfileManager::guaranteeCacheSize(unsigned int min_num) min_num = 100; m_max_cache_size = min_num; } - return m_max_cache_size; + return m_max_cache_size; } // guaranteeCacheSize // ------------------------------------------------------------------------ @@ -88,7 +88,8 @@ OnlineProfile* ProfileManager::getProfileByID(const uint32_t id) return m_profiles_persistent[id]; if (isInCache(id)) return m_profiles_cache[id]; - //FIXME not able to get! Now this should actually fetch the info from the + + // FIXME not able to get! Now this should actually fetch the info from the // server, but I haven't come up with a good asynchronous idea yet. return NULL; } // getProfileByID @@ -135,12 +136,14 @@ void ProfileManager::addDirectToCache(OnlineProfile* profile) break; } else + { ++iter; - } + } + } // for profile in cache } + m_profiles_cache[profile->getID()] = profile; assert(m_profiles_cache.size() <= m_max_cache_size); - } // addDirectToCache // ------------------------------------------------------------------------ @@ -155,6 +158,7 @@ bool ProfileManager::isInCache(const uint32_t id) updateCacheBits(i->second); return true; } + return false; } // isInCache @@ -180,6 +184,7 @@ void ProfileManager::updateCacheBits(OnlineProfile * profile) if (!iter->second->getCacheBit()) return; } + // All cache bits are set! Set them all to zero except the one // currently being visited for (iter = m_profiles_cache.begin(); @@ -189,7 +194,6 @@ void ProfileManager::updateCacheBits(OnlineProfile * profile) } profile->setCacheBit(true); } - } // updateCacheBits // ------------------------------------------------------------------------ @@ -232,11 +236,14 @@ void ProfileManager::deleteFromPersistent(const uint32_t id) m_profiles_persistent.erase(id); } else + { Log::warn("ProfileManager", "Tried to remove profile with id %d from persistent while " "not present", id); + } } // deleteFromPersistent + // ------------------------------------------------------------------------ /** Deletes all persistent profiles. */ @@ -265,10 +272,11 @@ void ProfileManager::moveToCache(const uint32_t id) addToCache(profile); } else + { Log::warn("ProfileManager", "Tried to move profile with id %d from persistent to " "cache while not present", id); + } } // moveToCache - } // namespace Online diff --git a/src/online/profile_manager.hpp b/src/online/profile_manager.hpp index c13f16bea..4798488f7 100644 --- a/src/online/profile_manager.hpp +++ b/src/online/profile_manager.hpp @@ -29,7 +29,6 @@ namespace Online { - class OnlineProfile; /** Class that manages all online profiles. Profiles are used for storing @@ -81,6 +80,7 @@ public: assert(!m_profile_manager); m_profile_manager = new ProfileManager(); } // create + // ---------------------------------------------------------------- /** Returns the singleton. * \pre create has been called to create the singleton. @@ -109,6 +109,7 @@ public: bool isInCache(const uint32_t id); bool inPersistent(const uint32_t id); OnlineProfile* getProfileByID(const uint32_t id); + // ---------------------------------------------------------------- /** Marks a given profile to be the currently visited one. This * is used to mark the profiles that ave its data display (e.g. @@ -117,15 +118,12 @@ public: { m_currently_visiting = getProfileByID(id); } // setVisiting + // ---------------------------------------------------------------- /** \return the instance of the profile that's currently being * visited */ OnlineProfile* getVisitingProfile() { return m_currently_visiting; } }; // class CurrentUser - } // namespace Online - -#endif - -/*EOF*/ +#endif // HEADER_ONLINE_PROFILE_MANAGER_HPP diff --git a/src/online/request.cpp b/src/online/request.cpp index 8fc8672ed..48919a159 100644 --- a/src/online/request.cpp +++ b/src/online/request.cpp @@ -25,10 +25,8 @@ #include - namespace Online { - // ======================================================================== /** * Creates a request that can be handled by the RequestManager @@ -67,6 +65,7 @@ namespace Online setExecuted(); afterOperation(); } // execute + // ------------------------------------------------------------------------ /** Executes the request now, i.e. in the main thread and without involving * the manager thread.. This calles prepareOperation, operation, and @@ -81,5 +80,4 @@ namespace Online setDone(); } // executeNow - } // namespace Online diff --git a/src/online/request.hpp b/src/online/request.hpp index 4c29f457a..7443583bc 100644 --- a/src/online/request.hpp +++ b/src/online/request.hpp @@ -35,7 +35,6 @@ 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 * this state determines which thread can access it. This allows @@ -119,9 +118,11 @@ namespace Online /** The actual operation to be executed. Empty as default, which * allows to create a 'quit' request without any additional code. */ virtual void operation() {} + // -------------------------------------------------------------------- /** Virtual function to be called before an operation. */ virtual void prepareOperation() {} + // -------------------------------------------------------------------- /** Virtual function to be called after an operation. */ virtual void afterOperation() {} @@ -132,71 +133,87 @@ namespace Online RT_QUIT = 1 }; - Request(bool manage_memory, int priority, int type); + Request(bool manage_memory, int priority, int type); virtual ~Request() {} void execute(); void executeNow(); void queue(); + // -------------------------------------------------------------------- /** Executed when a request has finished. */ virtual void callback() {} + // -------------------------------------------------------------------- /** Returns the type of the request. */ int getType() const { return m_type; } + // -------------------------------------------------------------------- /** Returns if the memory for this object should be managed by * by network_http (i.e. freed once the request is handled). */ bool manageMemory() const { return m_manage_memory; } + // -------------------------------------------------------------------- /** Sets the memory management flag of this request. This function * must only be called by the main thread, since it is only tested by * the main thread. */ void setManageMemory(bool m) { m_manage_memory = m; } + // -------------------------------------------------------------------- /** Returns the priority of this request. */ int getPriority() const { return m_priority; } + // -------------------------------------------------------------------- /** Signals that this request should be canceled. */ void cancel() { m_cancel.setAtomic(true); } + // -------------------------------------------------------------------- /** Returns if this request is to be canceled. */ bool isCancelled() const { return m_cancel.getAtomic(); } + // -------------------------------------------------------------------- /** Returns if this request can be aborted. */ bool isAbortable() const { return m_is_abortable.getAtomic(); } + // -------------------------------------------------------------------- /** Sets if this request is abortable or not. */ void setAbortable(bool b) { m_is_abortable.setAtomic(b); } + // -------------------------------------------------------------------- /** Sets the request state to busy. */ void setBusy() { - assert(m_state.getAtomic()==S_PREPARING); + assert(m_state.getAtomic() == S_PREPARING); m_state.setAtomic(S_BUSY); } // setBusy + // -------------------------------------------------------------------- /** Sets the request to be completed. */ void setExecuted() { - assert(m_state.getAtomic()==S_BUSY); + assert(m_state.getAtomic() == S_BUSY); m_state.setAtomic(S_EXECUTED); } // setExecuted + // -------------------------------------------------------------------- /** Should only be called by the manager */ void setDone() { - assert(m_state.getAtomic()==S_EXECUTED); + assert(m_state.getAtomic() == S_EXECUTED); m_state.setAtomic(S_DONE); } // setDone + // -------------------------------------------------------------------- /** Returns if this request is done. */ bool isDone() const { return m_state.getAtomic() == S_DONE; } + // -------------------------------------------------------------------- /** Returns if this request is being prepared. */ bool isPreparing() const { return m_state.getAtomic() == S_PREPARING; } + // -------------------------------------------------------------------- /** Returns if this request is busy. */ bool isBusy() const { return m_state.getAtomic() == S_BUSY; } + // -------------------------------------------------------------------- /** Checks if the request has completed or done (i.e. callbacks were * executed). @@ -204,8 +221,9 @@ namespace Online bool hasBeenExecuted() const { State s = m_state.getAtomic(); - return s==S_EXECUTED || s==S_DONE; + return s == S_EXECUTED || s == S_DONE; } // hasBeenExecuted + // -------------------------------------------------------------------- /** Virtual method to check if a request has initialized all needed * members to a valid value. */ @@ -226,9 +244,5 @@ namespace Online } }; // class Compare }; // class Request - - } //namespace Online - -#endif - +#endif // HEADER_ONLINE_REQUEST_HPP diff --git a/src/online/request_manager.cpp b/src/online/request_manager.cpp index f285431bc..7dea5ab8e 100644 --- a/src/online/request_manager.cpp +++ b/src/online/request_manager.cpp @@ -111,6 +111,7 @@ namespace Online pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + // Should be the default, but just in case: pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); //pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); @@ -118,7 +119,7 @@ namespace Online m_thread_id.setAtomic(new pthread_t()); int error = pthread_create(m_thread_id.getData(), &attr, &RequestManager::mainLoop, this); - if(error) + if (error) { m_thread_id.lock(); delete m_thread_id.getData(); @@ -128,10 +129,11 @@ namespace Online errno); } pthread_attr_destroy(&attr); + // In case that login id was not saved (or first start of stk), // current player would not be defined at this stage. PlayerProfile *player = PlayerManager::getCurrentPlayer(); - if(player && player->wasOnlineLastTime() && + if (player && player->wasOnlineLastTime() && !UserConfigParams::m_always_show_login_screen) { PlayerManager::resumeSavedSession(); @@ -178,6 +180,7 @@ namespace Online request->setBusy(); m_request_queue.lock(); m_request_queue.getData().push(request); + // Wake up the network http thread pthread_cond_signal(&m_cond_request); m_request_queue.unlock(); @@ -197,27 +200,30 @@ namespace Online me->m_current_request = NULL; me->m_request_queue.lock(); - while( me->m_request_queue.getData().empty() || + while (me->m_request_queue.getData().empty() || me->m_request_queue.getData().top()->getType() != Request::RT_QUIT) { bool empty = me->m_request_queue.getData().empty(); + // Wait in cond_wait for a request to arrive. The 'while' is necessary // since "spurious wakeups from the pthread_cond_wait ... may occur" // (pthread_cond_wait man page)! - while(empty) + while (empty) { pthread_cond_wait(&me->m_cond_request, me->m_request_queue.getMutex()); empty = me->m_request_queue.getData().empty(); } me->m_current_request = me->m_request_queue.getData().top(); me->m_request_queue.getData().pop(); - if(me->m_current_request->getType()==Request::RT_QUIT) + + if (me->m_current_request->getType() == Request::RT_QUIT) break; + me->m_request_queue.unlock(); me->m_current_request->execute(); me->addResult(me->m_current_request); me->m_request_queue.lock(); - } // while + } // while handle all requests // Signal that the request manager can now be deleted. // We signal this even before cleaning up memory, since there's no @@ -225,16 +231,18 @@ namespace Online me->setCanBeDeleted(); // At this stage we have the lock for m_request_queue - while(!me->m_request_queue.getData().empty()) + while (!me->m_request_queue.getData().empty()) { - Online::Request * request = me->m_request_queue.getData().top(); + Online::Request *request = me->m_request_queue.getData().top(); me->m_request_queue.getData().pop(); + // Manage memory can be ignored here, all requests // need to be freed. delete request; } me->m_request_queue.unlock(); pthread_exit(NULL); + return 0; } // mainLoop @@ -259,13 +267,13 @@ namespace Online { Request * request = NULL; m_result_queue.lock(); - if(!m_result_queue.getData().empty()) + if (!m_result_queue.getData().empty()) { request = m_result_queue.getData().front(); m_result_queue.getData().pop(); } m_result_queue.unlock(); - if(request != NULL) + if (request != NULL) { request->callback(); if(request->manageMemory()) @@ -298,7 +306,8 @@ namespace Online float interval = GAME_POLLING_INTERVAL; if (StateManager::get()->getGameState() == GUIEngine::MENU) interval = MENU_POLLING_INTERVAL; - if(m_time_since_poll > interval) + + if (m_time_since_poll > interval) { m_time_since_poll = 0; PlayerManager::requestOnlinePoll(); @@ -306,7 +315,3 @@ namespace Online } // update } // namespace Online - - - - diff --git a/src/online/request_manager.hpp b/src/online/request_manager.hpp index e6fafc0b2..b6cc478f8 100644 --- a/src/online/request_manager.hpp +++ b/src/online/request_manager.hpp @@ -39,10 +39,8 @@ #include #include - namespace Online { - /** A class to execute requests in a separate thread. Typically the * requests involve a http(s) requests to be sent to the stk server, and * receive an answer (e.g. to sign in; or to download an addon). The @@ -86,11 +84,14 @@ namespace Online * grant permission * IPERM_ALLOWED: STK is allowed to access server. * IPERM_NOT_ALLOWED: STK must not access external servers. */ - enum InternetPermission {IPERM_NOT_ASKED =0, - IPERM_ALLOWED =1, - IPERM_NOT_ALLOWED=2 }; + enum InternetPermission + { + IPERM_NOT_ASKED = 0, + IPERM_ALLOWED = 1, + IPERM_NOT_ALLOWED = 2 + }; protected: - + /** Time passed since the last poll request. */ float m_time_since_poll; /** The current requested being worked on. */ @@ -119,7 +120,7 @@ namespace Online void addResult(Online::Request *request); void handleResultQueue(); - static void *mainLoop(void *obj); + static void *mainLoop(void *obj); RequestManager(); //const std::string &url ~RequestManager(); @@ -136,12 +137,9 @@ namespace Online void startNetworkThread(); void stopNetworkThread(); - bool getAbort(){ return m_abort.getAtomic(); }; + bool getAbort(){ return m_abort.getAtomic(); } void update(float dt); }; //class RequestManager } // namespace Online - #endif // request_manager_HPP - -/*EOF*/ diff --git a/src/online/server.cpp b/src/online/server.cpp index 24ec5ff63..db72dad4c 100644 --- a/src/online/server.cpp +++ b/src/online/server.cpp @@ -24,12 +24,14 @@ #include "utils/constants.hpp" #include "utils/string_utils.hpp" -namespace Online{ - Server::SortOrder Server::m_sort_order=Server::SO_NAME; //FIXME change to some other default +namespace Online +{ + Server::SortOrder Server::m_sort_order = Server::SO_NAME; Server::Server(const XMLNode & xml) { assert(xml.getName() == "server"); + m_name = ""; m_satisfaction_score = 0; m_server_id = 0; @@ -45,7 +47,7 @@ namespace Online{ xml.get("max_players", &m_max_players); xml.get("current_players", &m_current_players); - }; // Server(const XML&) + } // Server(const XML&) // ---------------------------------------------------------------------------- /** diff --git a/src/online/server.hpp b/src/online/server.hpp index c719cd618..f9576056a 100644 --- a/src/online/server.hpp +++ b/src/online/server.hpp @@ -31,7 +31,8 @@ class XMLNode; -namespace Online{ +namespace Online +{ /** * \ingroup online */ @@ -40,54 +41,64 @@ namespace Online{ public: /** Set the sort order used in the comparison function. */ - enum SortOrder { SO_SCORE = 1, // Sorted on satisfaction score - SO_NAME = 2, // Sorted alphabetically by name - SO_PLAYERS = 4 + enum SortOrder + { + SO_SCORE = 1, // Sorted on satisfaction score + SO_NAME = 2, // Sorted alphabetically by name + SO_PLAYERS = 4 }; protected: - /** The name to be displayed. */ + /** The server name to be displayed. */ irr::core::stringw m_name; - std::string m_lower_case_name; //Used for comparison + std::string m_lower_case_name; // Used for comparison uint32_t m_server_id; uint32_t m_host_id; + /** The maximum number of players that the server supports */ int m_max_players; + /** The number of players currently on the server */ int m_current_players; + /** The score/rating given */ float m_satisfaction_score; /** The sort order to be used in the comparison. */ static SortOrder m_sort_order; - Server() {}; + Server() {} public: /** Initialises the object from an XML node. */ Server(const XMLNode & xml); - // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ /** Sets the sort order used in the comparison function. It is static, so * that each instance can access the sort order. */ static void setSortOrder(SortOrder so) { m_sort_order = so; } + // ------------------------------------------------------------------------ /** Returns the name of the server. */ const irr::core::stringw& getName() const { return m_name; } const std::string & getLowerCaseName() const { return m_lower_case_name; } + // ------------------------------------------------------------------------ const float getScore() const { return m_satisfaction_score; } + // ------------------------------------------------------------------------ /** Returns the ID of this server. */ const uint32_t getServerId() const { return m_server_id; } const uint32_t getHostId() const { return m_host_id; } const int getMaxPlayers() const { return m_max_players; } const int getCurrentPlayers() const { return m_current_players; } + // ------------------------------------------------------------------------ bool filterByWords(const irr::core::stringw words) const; - // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ /** Compares two servers according to the sort order currently defined. * \param a The addon to compare this addon to. */ @@ -106,10 +117,10 @@ namespace Online{ return m_current_players < server.getCurrentPlayers(); break; } // switch + return true; } // operator< }; // Server } // namespace Online - -#endif +#endif // HEADER_SERVER_HPP diff --git a/src/online/servers_manager.cpp b/src/online/servers_manager.cpp index 9f47739f4..c3a27b143 100644 --- a/src/online/servers_manager.cpp +++ b/src/online/servers_manager.cpp @@ -16,7 +16,6 @@ // 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/servers_manager.hpp" #include @@ -28,14 +27,15 @@ #define SERVER_REFRESH_INTERVAL 5.0f -namespace Online{ - +namespace Online +{ static ServersManager* manager_singleton(NULL); ServersManager* ServersManager::get() { if (manager_singleton == NULL) manager_singleton = new ServersManager(); + return manager_singleton; } @@ -46,12 +46,14 @@ namespace Online{ } // deallocate // ============================================================================ - ServersManager::ServersManager(){ + ServersManager::ServersManager() + { m_last_load_time.setAtomic(0.0f); m_joined_server.setAtomic(NULL); } - ServersManager::~ServersManager(){ + ServersManager::~ServersManager() + { cleanUpServers(); MutexLocker(m_joined_server); delete m_joined_server.getData(); @@ -75,27 +77,31 @@ namespace Online{ if(StkTime::getRealTime() - m_last_load_time.getAtomic() > SERVER_REFRESH_INTERVAL) { request = new RefreshRequest(); - request->setServerURL("client-user.php"); - request->addParameter("action","get_server_list"); + request->setServerURL(API_USER_PATH); + request->addParameter("action", "get_server_list"); + if (request_now) RequestManager::get()->addRequest(request); } + return request; } void ServersManager::refresh(bool success, const XMLNode * input) { - if (success) + if (!success) { - const XMLNode * servers_xml = input->getNode("servers"); - cleanUpServers(); - for (unsigned int i = 0; i < servers_xml->getNumNodes(); i++) - { - addServer(new Server(*servers_xml->getNode(i))); - } - m_last_load_time.setAtomic((float)StkTime::getRealTime()); + Log::error("Server Manager", "Could not refresh server list"); + return; } - //FIXME error message + + const XMLNode * servers_xml = input->getNode("servers"); + cleanUpServers(); + for (unsigned int i = 0; i < servers_xml->getNumNodes(); i++) + { + addServer(new Server(*servers_xml->getNode(i))); + } + m_last_load_time.setAtomic((float)StkTime::getRealTime()); } void ServersManager::RefreshRequest::callback() @@ -117,7 +123,8 @@ namespace Online{ { MutexLocker(m_joined_server); delete m_joined_server.getData(); - //It's a copy! + + // It's a copy! m_joined_server.getData() = new Server(*getServerByID(id)); } @@ -135,6 +142,7 @@ namespace Online{ m_sorted_servers.lock(); m_sorted_servers.getData().push_back(server); m_sorted_servers.unlock(); + m_mapped_servers.lock(); m_mapped_servers.getData()[server->getServerId()] = server; m_mapped_servers.unlock(); @@ -168,7 +176,8 @@ namespace Online{ } // ============================================================================ - void ServersManager::sort(bool sort_desc){ + void ServersManager::sort(bool sort_desc) + { MutexLocker(m_sorted_servers); m_sorted_servers.getData().insertionSort(0, sort_desc); } diff --git a/src/online/servers_manager.hpp b/src/online/servers_manager.hpp index 3c0d26a40..fe0c8f76b 100644 --- a/src/online/servers_manager.hpp +++ b/src/online/servers_manager.hpp @@ -26,11 +26,8 @@ #include "online/xml_request.hpp" #include "utils/synchronised.hpp" - - - -namespace Online { - +namespace Online +{ /** * \brief * \ingroup online @@ -51,8 +48,10 @@ namespace Online { ~ServersManager(); /** Sorted vector of servers */ Synchronised > m_sorted_servers; + /** Maps server id's to the same servers*/ Synchronised > m_mapped_servers; + /** This is a pointer to a copy of the server, the moment it got joined */ Synchronised m_joined_server; @@ -74,14 +73,10 @@ namespace Online { const Server * getServerBySort (int index) const; void sort(bool sort_desc); Server * getJoinedServer() const; - //Returns the best server to join + + // Returns the best server to join const Server * getQuickPlay() const; + }; // class ServersManager - - } // namespace Online - - -#endif - -/*EOF*/ +#endif // HEADER_SERVERS_MANAGER_HPP diff --git a/src/online/xml_request.cpp b/src/online/xml_request.cpp index d7058dcd6..3bb742c84 100644 --- a/src/online/xml_request.cpp +++ b/src/online/xml_request.cpp @@ -24,15 +24,12 @@ #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 @@ -61,22 +58,26 @@ namespace Online void XMLRequest::afterOperation() { m_xml_data = file_manager->createXMLTreeFromString(getData()); - if(hadDownloadError()) + if (hadDownloadError()) + { Log::error("XMLRequest::afterOperation", "curl_easy_perform() failed: %s", getDownloadErrorMessage()); + } + m_success = false; std::string rec_success; - if(m_xml_data->get("success", &rec_success)) + if (m_xml_data->get("success", &rec_success)) { - m_success = rec_success =="yes"; + 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 index 0ddc0ef63..1e2f6089d 100644 --- a/src/online/xml_request.hpp +++ b/src/online/xml_request.hpp @@ -53,7 +53,7 @@ namespace Online virtual void afterOperation() OVERRIDE; public : - XMLRequest(bool manage_memory = false, int priority = 1); + XMLRequest(bool manage_memory = false, int priority = 1); virtual ~XMLRequest(); // ------------------------------------------------------------------------ @@ -73,7 +73,7 @@ namespace Online * \pre request had to be executed. * \return get the info from the request reply */ - const irr::core::stringw & getInfo() const + const irr::core::stringw & getInfo() const { assert(hasBeenExecuted()); return m_info; @@ -90,8 +90,5 @@ namespace Online } // isSuccess }; // class XMLRequest - } //namespace Online - -#endif - +#endif // HEADER_XML_REQUEST_HPP diff --git a/src/states_screens/online_screen.cpp b/src/states_screens/online_screen.cpp index bcfc746e0..42f3fafe9 100644 --- a/src/states_screens/online_screen.cpp +++ b/src/states_screens/online_screen.cpp @@ -191,7 +191,7 @@ void OnlineScreen::doQuickPlay() } PlayerManager::setUserDetails(request2, "request-connection"); - request2->setServerURL("address-management.php"); + request2->setServerURL(API_ADDRESS_PATH); request2->addParameter("server_id", server->getServerId()); request2->executeNow(); diff --git a/src/states_screens/register_screen.cpp b/src/states_screens/register_screen.cpp index 556ee832c..e63b7bafd 100644 --- a/src/states_screens/register_screen.cpp +++ b/src/states_screens/register_screen.cpp @@ -72,9 +72,9 @@ void RegisterScreen::init() getWidget("local_username")->setText(username); TextBoxWidget *password_widget = getWidget("password"); - password_widget->setPasswordBox(true,L'*'); + password_widget->setPasswordBox(true, L'*'); password_widget = getWidget("password_confirm"); - password_widget->setPasswordBox(true,L'*'); + password_widget->setPasswordBox(true, L'*'); m_info_widget = getWidget("info"); assert(m_info_widget); @@ -147,7 +147,7 @@ void RegisterScreen::makeEntryFieldsVisible(bool online) */ void RegisterScreen::handleLocalName(const stringw &local_name) { - if (local_name.size()==0) + if (local_name.size() == 0) return; // If a local player with that name does not exist, create one @@ -267,8 +267,8 @@ void RegisterScreen::acceptTerms() core::stringw password_confirm= getWidget("password_confirm")->getText().trim(); core::stringw email = getWidget("email")->getText().trim(); - m_signup_request = new XMLRequest(); - m_signup_request->setServerURL("client-user.php"); + m_signup_request = new XMLRequest(); + m_signup_request->setServerURL(API_USER_PATH); m_signup_request->addParameter("action", "register" ); m_signup_request->addParameter("username", username ); m_signup_request->addParameter("password", password );