GYINT32 GYNetAddress::SetAddr(GYINT32 addr, GYBOOL is_net_order) { GYINT32 err = 0; m_sockAddr.sin_addr.s_addr = GYTRUE == is_net_order ? addr :htonl(addr); GYCHAR address[MaxAddrStringLengh] = {0}; if(0 != GetAddressString(address, sizeof(address))) { err = INVALID_VALUE; GYMemset(&m_sockAddr, 0, sizeof(m_sockAddr)); } else { #ifdef _DEBUG GYMemcpy(m_addressString, address, sizeof(m_addressString)); #endif // _DEBUG } return err; }
// Realm List command handler bool AuthSocket::_HandleRealmList() { sLog->outDebug(LOG_FILTER_AUTHSERVER, "Entering _HandleRealmList"); if (socket().recv_len() < 5) return false; socket().recv_skip(5); // Get the user id (else close the connection) // No SQL injection (prepared statement) PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME); stmt->setString(0, _login); PreparedQueryResult result = LoginDatabase.Query(stmt); if (!result) { sLog->outError(LOG_FILTER_AUTHSERVER, "'%s:%d' [ERROR] user %s tried to login but we cannot find him in the database.", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _login.c_str()); socket().shutdown(); return false; } Field* fields = result->Fetch(); uint32 id = fields[0].GetUInt32(); // Update realm list if need sRealmList->UpdateIfNeed(); ACE_INET_Addr clientAddr; socket().peer().get_remote_addr(clientAddr); // Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm) ByteBuffer pkt; size_t RealmListSize = 0; for (RealmList::RealmMap::const_iterator i = sRealmList->begin(); i != sRealmList->end(); ++i) { // don't work with realms which not compatible with the client bool okBuild = ((_expversion & POST_BC_EXP_FLAG) && i->second.gamebuild == _build) || ((_expversion & PRE_BC_EXP_FLAG) && !AuthHelper::IsPreBCAcceptedClientBuild(i->second.gamebuild)); // No SQL injection. id of realm is controlled by the database. uint32 flag = i->second.flag; RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(i->second.gamebuild); if (!okBuild) { if (!buildInfo) continue; flag |= REALM_FLAG_OFFLINE | REALM_FLAG_SPECIFYBUILD; // tell the client what build the realm is for } if (!buildInfo) flag &= ~REALM_FLAG_SPECIFYBUILD; std::string name = i->first; if (_expversion & PRE_BC_EXP_FLAG && flag & REALM_FLAG_SPECIFYBUILD) { std::ostringstream ss; ss << name << " (" << buildInfo->MajorVersion << '.' << buildInfo->MinorVersion << '.' << buildInfo->BugfixVersion << ')'; name = ss.str(); } // We don't need the port number from which client connects with but the realm's port clientAddr.set_port_number(i->second.ExternalAddress.get_port_number()); uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; uint8 AmountOfCharacters = 0; stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_NUM_CHARS_ON_REALM); stmt->setUInt32(0, i->second.m_ID); stmt->setUInt32(1, id); result = LoginDatabase.Query(stmt); if (result) AmountOfCharacters = (*result)[0].GetUInt8(); pkt << i->second.icon; // realm type if (_expversion & POST_BC_EXP_FLAG) // only 2.x and 3.x clients pkt << lock; // if 1, then realm locked pkt << uint8(flag); // RealmFlags pkt << name; pkt << GetAddressString(GetAddressForClient(i->second, clientAddr)); pkt << i->second.populationLevel; pkt << AmountOfCharacters; pkt << i->second.timezone; // realm category if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients pkt << uint8(0x2C); // unk, may be realm number/id? else pkt << uint8(0x0); // 1.12.1 and 1.12.2 clients if (_expversion & POST_BC_EXP_FLAG && flag & REALM_FLAG_SPECIFYBUILD) { pkt << uint8(buildInfo->MajorVersion); pkt << uint8(buildInfo->MinorVersion); pkt << uint8(buildInfo->BugfixVersion); pkt << uint16(buildInfo->Build); } ++RealmListSize; } if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients { pkt << uint8(0x10); pkt << uint8(0x00); } else // 1.12.1 and 1.12.2 clients { pkt << uint8(0x00); pkt << uint8(0x02); } // make a ByteBuffer which stores the RealmList's size ByteBuffer RealmListSizeBuffer; RealmListSizeBuffer << uint32(0); if (_expversion & POST_BC_EXP_FLAG) // only 2.x and 3.x clients RealmListSizeBuffer << uint16(RealmListSize); else RealmListSizeBuffer << uint32(RealmListSize); ByteBuffer hdr; hdr << uint8(REALM_LIST); hdr << uint16(pkt.size() + RealmListSizeBuffer.size()); hdr.append(RealmListSizeBuffer); // append RealmList's size buffer hdr.append(pkt); // append realms in the realmlist socket().send((char const*)hdr.contents(), hdr.size()); return true; }
void AuthSocket::LoadRealmlist(ByteBuffer& pkt, uint32 acctid) { RealmList::RealmListIterators iters; iters = sRealmList.GetIteratorsForBuild(_build); uint32 numRealms = sRealmList.NumRealmsForBuild(_build); ACE_INET_Addr clientAddr; peer().get_remote_addr(clientAddr); switch (_build) { case 5875: // 1.12.1 case 6005: // 1.12.2 case 6141: // 1.12.3 { pkt << uint32(0); // unused value pkt << uint8(numRealms); for (RealmList::RealmStlList::const_iterator itr = iters.first; itr != iters.second; ++itr) { clientAddr.set_port_number((*itr)->ExternalAddress.get_port_number()); uint8 AmountOfCharacters; // No SQL injection. id of realm is controlled by the database. QueryResult* result = LoginDatabase.PQuery("SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'", (*itr)->m_ID, acctid); if (result) { Field* fields = result->Fetch(); AmountOfCharacters = fields[0].GetUInt8(); delete result; } else AmountOfCharacters = 0; bool ok_build = std::find((*itr)->realmbuilds.begin(), (*itr)->realmbuilds.end(), _build) != (*itr)->realmbuilds.end(); RealmBuildInfo const* buildInfo = ok_build ? FindBuildInfo(_build) : NULL; if (!buildInfo) buildInfo = &(*itr)->realmBuildInfo; RealmFlags realmflags = (*itr)->realmflags; // 1.x clients not support explicitly REALM_FLAG_SPECIFYBUILD, so manually form similar name as show in more recent clients std::string name = (*itr)->name; if (realmflags & REALM_FLAG_SPECIFYBUILD) { char buf[20]; snprintf(buf, 20, " (%u,%u,%u)", buildInfo->major_version, buildInfo->minor_version, buildInfo->bugfix_version); name += buf; } // Show offline state for unsupported client builds and locked realms (1.x clients not support locked state show) if (!ok_build || ((*itr)->allowedSecurityLevel > _accountSecurityLevel)) realmflags = RealmFlags(realmflags | REALM_FLAG_OFFLINE); pkt << uint32((*itr)->icon); // realm type pkt << uint8(realmflags); // realmflags pkt << name; // name pkt << GetAddressString(GetAddressForClient((**itr), clientAddr)); // address pkt << float((*itr)->populationLevel); pkt << uint8(AmountOfCharacters); pkt << uint8((*itr)->timezone); // realm category pkt << uint8(0x00); // unk, may be realm number/id? } pkt << uint16(0x0002); // unused value (why 2?) break; } case 8606: // 2.4.3 case 10505: // 3.2.2a case 11159: // 3.3.0a case 11403: // 3.3.2 case 11723: // 3.3.3a case 12340: // 3.3.5a case 13623: // 4.0.6a case 15050: // 4.3.0 case 15595: // 4.3.4 case 16357: // 5.1.0 case 16992: // 5.3.0 case 17055: // 5.3.0 case 17116: // 5.3.0 case 17128: // 5.3.0 case 17538: // 5.4.1 case 17658: // 5.4.2 case 17688: // 5.4.2a case 17898: // 5.4.7 case 17930: // 5.4.7 case 17956: // 5.4.7 case 18019: // 5.4.7 case 18291: // 5.4.8 case 18414: // 5.4.8 default: // and later { pkt << uint32(0); // unused value pkt << uint16(numRealms); for (RealmList::RealmStlList::const_iterator itr = iters.first; itr != iters.second; ++itr) { clientAddr.set_port_number((*itr)->ExternalAddress.get_port_number()); uint8 AmountOfCharacters; // No SQL injection. id of realm is controlled by the database. QueryResult* result = LoginDatabase.PQuery("SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'", (*itr)->m_ID, acctid); if (result) { Field* fields = result->Fetch(); AmountOfCharacters = fields[0].GetUInt8(); delete result; } else { AmountOfCharacters = 0; } bool ok_build = std::find((*itr)->realmbuilds.begin(), (*itr)->realmbuilds.end(), _build) != (*itr)->realmbuilds.end(); RealmBuildInfo const* buildInfo = ok_build ? FindBuildInfo(_build) : NULL; if (!buildInfo) { buildInfo = &(*itr)->realmBuildInfo; } uint8 lock = ((*itr)->allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; RealmFlags realmFlags = (*itr)->realmflags; // Show offline state for unsupported client builds if (!ok_build) { realmFlags = RealmFlags(realmFlags | REALM_FLAG_OFFLINE); } if (!buildInfo) { realmFlags = RealmFlags(realmFlags & ~REALM_FLAG_SPECIFYBUILD); } pkt << uint8((*itr)->icon); // realm type (this is second column in Cfg_Configs.dbc) pkt << uint8(lock); // flags, if 0x01, then realm locked pkt << uint8(realmFlags); // see enum RealmFlags pkt << (*itr)->name; // name pkt << GetAddressString(GetAddressForClient((**itr), clientAddr)); // address pkt << float((*itr)->populationLevel); pkt << uint8(AmountOfCharacters); pkt << uint8((*itr)->timezone); // realm category (Cfg_Categories.dbc) pkt << uint8(0x2C); // unk, may be realm number/id? if (realmFlags & REALM_FLAG_SPECIFYBUILD) { pkt << uint8(buildInfo->major_version); pkt << uint8(buildInfo->minor_version); pkt << uint8(buildInfo->bugfix_version); pkt << uint16(_build); } } pkt << uint16(0x0010); // unused value (why 10?) break; } } }