// Create new player instance, save it // to logging in players list. bool CLounge::addPlayer(SOCKET sd, struct in_addr* inaddr) { if (FindIPAddress(inaddr->s_addr)) { CpduNotify pdu; char s[300]; const char* saddr = inet_ntoa(*inaddr); if (saddr != NULL) sprintf(s, "Error: ip address %s is already logged in.", saddr); else sprintf(s, "Error: ip address %ld is already logged in.", inaddr->s_addr); pdu.sendNotifyMessage(sd, s); Sys_LogError(s); CPoller::Inst()->removePlayerSocket(sd); Sys_CloseSocket(sd); return false; } RegisterIPAddress(inaddr->s_addr); CLoginPlayer lp(sd, inaddr->s_addr); loggingIn_.push_back(lp); return true; }
void CLounge::processLogins(long now) { // Check if somebody's been logging in too long // - if so, log out the player list<CLoginPlayer>::iterator i = loggingIn_.begin(); while (i != loggingIn_.end()) { CLoginPlayer& p = (*i); if (now - p.loginTime_ > LOGIN_TIMEOUT) { // Login not completed withing timeout - player will // be forcibly logged out UnregisterIPAddress(p.player_.getIpAddress()); CpduNotify pdu; pdu.sendNotifyMessage(p.player_.getSocket(), "Login timed out."); printf("Login time for socket %d exceeded - terminating connection.\n", p.player_.getSocket()); CPoller::Inst()->removePlayerSocket(p.player_.getSocket()); Sys_CloseSocket(p.player_.getSocket()); // XXX the client does not react very well // to the socket being closed like this i = loggingIn_.erase(i); } else { ++i; } } }
/* ==================== Sys_CloseAllSockets Close all network sockets ==================== */ static void Sys_CloseAllSockets (void) { size_t sock_ind; for (sock_ind = 0; sock_ind < nb_sockets; sock_ind++) { listen_socket_t* sock = &listen_sockets[sock_ind]; if (sock->socket != -1) Sys_CloseSocket (sock->socket); } nb_sockets = 0; }
bool CLounge::login(SOCKET sd, const char* username, const char* password, u_int16_t platform, u_byte_t* checksum) { if (shutdown_) { CpduNotify pdu; pdu.sendNotifyMessage(sd, "The server is shutting down - please try again later."); return false; } // Find the player from the logging in list list<CLoginPlayer>::iterator pos = find_if(loggingIn_.begin(), loggingIn_.end(), same_socket(sd)); // Testing: Allow 'bot_X' players to log in without login entries string test_string(username); if (pos == loggingIn_.end() && test_string.find("bot_") != 0) { // Player was not found from logging in list. // Internal logic error - should never happen char s[128]; sprintf(s, "Internal error: player (%d %s, %s) not in logging in list\n", sd, username, password); Sys_LogError(s); CPoller::Inst()->removePlayerSocket(sd); Sys_CloseSocket(sd); return false; } bool rc = validate(sd, username, password, pos); if (rc) { // login accepted - add to loginComplete_ list // so it'll be removed from logginIn_ list // and added to main player container. // (it's done it two steps because while we're // here we're iterating over the logginIn_ list) (*pos).username_ = username; (*pos).password_ = password; loginComplete_.push_back(*pos); } return rc; }
bool CLounge::removeTable(CTable* table) { // Remove table from poller SOCKET sd = table->getSocket(); CPoller::Inst()->removeTableSocket(sd); Sys_CloseSocket(sd); // Remove table from main list Tables::iterator pos = find_if(tables_.begin(), tables_.end(), same_socket(sd)); if (pos != tables_.end()) tables_.erase(pos); return true; }
bool CLounge::validate(SOCKET sd, const char* username, const char* password, LoginIT& pos) { bool rc = dbase_->authenticate(username, password); if (!rc) { if ((*pos).retryCount_++ < MAX_LOGIN_RETRIES) { // Invalid username/password - // reject login, allow retry CpduLoginReject pdu; pdu.sendReject(sd, RF_Allow_Retry); } else { // Too many login failures UnregisterIPAddress((*pos).player_.getIpAddress()); // Remove the player from logging list loginComplete_.push_back(*pos); //This code not for production: //loggingIn_.erase(pos); // Reject login, terminate connection CpduLoginReject pdu; pdu.sendReject(sd, RF_No_Retry); CPoller::Inst()->removePlayerSocket(sd); Sys_CloseSocket(sd); } } return rc; }
void CLounge::postProcessLogins() { // Removing elements from a list while iterating // over it is tricky. // // Those CLoginPlayers who have completed their // logins are processed here by removing the // CLoginPlayer entries // list<CLoginPlayer>::iterator i = loginComplete_.begin(), e = loginComplete_.end(); while (i != e) { CLoginPlayer& p = (*i); // Remove from logging in list LoginPlayers::iterator pos = find_if(loggingIn_.begin(), loggingIn_.end(), same_socket(p.player_.getSocket())); if (pos != loggingIn_.end()) { loggingIn_.erase(pos); } // Add to main list // We also check that THE SAME NAME is not there already. // The check is case insensitive. u_long ipaddr = p.player_.getIpAddress(); SOCKET sd = p.player_.getSocket(); string checkName = p.username_; // Failed logins will have empty name if (checkName.size() > 0) { tolower(checkName); CPlayer player(p.username_, sd, ipaddr); if (players_.insert(Players::value_type(checkName.c_str(), player)).second == false) { // Player with same name is logged in already! CpduNotify pdu; char s[128]; sprintf(s, "Error: user %s is already logged in.", p.username_.c_str()); pdu.sendNotifyMessage(sd, s); UnregisterIPAddress(ipaddr); CPoller::Inst()->removePlayerSocket(sd); Sys_CloseSocket(sd); } else { // // login completed successfully // string motd; dbase_->getMotdMsg(motd); if (motd.size() == 0) motd = "Welcome to PokerSpot online cardroom!"; // Send accept to player CpduLoginAccept pduAccept(p.username_.c_str(), p.password_.c_str(), motd.c_str()); pduAccept.sendTo(sd); // Notify Load Balancer and/or other lounges notifyOthers(AddPlayer, p.username_.c_str()); } } ++i; } loginComplete_.clear(); }
void CLounge::processLogouts(long /*now*/) { bool sendUpdate = false; // // Process logging out players // list<PlayerPtr>::iterator i = loggingOut_.begin(); while (i != loggingOut_.end()) { sendUpdate = true; string username = (*i).player_->name(); SOCKET sd = (*i).player_->getSocket(); printf("Logging out player %s socket %d.\n", username.c_str(), sd); // Forget ip address UnregisterIPAddress((*i).player_->getIpAddress()); // Erase the player from the main list. tolower(username); if (players_.erase(username) == 0) { // player was not in main list - erase from // logging in list LoginPlayers::iterator it = find_if(loggingIn_.begin(), loggingIn_.end(), same_socket(sd)); if (it != loggingIn_.end()) loggingIn_.erase(it); } // Terminate the connection CPoller::Inst()->removePlayerSocket(sd); Sys_CloseSocket(sd); // Notify Load Balancer and/or lounges notifyOthers(RemovePlayer, username.c_str()); // Remove it from logging out list i = loggingOut_.erase(i); } // // Process logging out tables // list<TablePtr>::iterator ti = loggingOutTables_.begin(); while (ti != loggingOutTables_.end()) { sendUpdate = true; CTable* table = (*ti).table_; printf("*** Removing table %d socket %d.\n", table->getNumber(), table->getSocket()); removeTable(table); // NOTE: after removeTable 'table' points to destroyed data // Remove it from logging out list ti = loggingOutTables_.erase(ti); } if (sendUpdate) { // Send login stats update if something was removed CpduLoungeStats pduStats; pduStats.sendStats(players_.size(), tables_.size()); } }