Added ClientVersion request system to UCS server (needed to fix saylinks)

This commit is contained in:
Uleat
2018-02-25 21:40:45 -05:00
parent 361937d443
commit 6c2a8edea6
13 changed files with 175 additions and 2 deletions
+85
View File
@@ -512,7 +512,9 @@ Client::Client(std::shared_ptr<EQStreamInterface> eqs) {
AccountGrabUpdateTimer = new Timer(60000); //check every minute
GlobalChatLimiterTimer = new Timer(RuleI(Chat, IntervalDurationMS));
RawConnectionType = '\0';
TypeOfConnection = ConnectionTypeUnknown;
ClientVersion_ = EQEmu::versions::ClientVersion::Unknown;
UnderfootOrLater = false;
}
@@ -643,6 +645,10 @@ void Clientlist::Process()
database.GetAccountStatus((*it));
// give world packet a chance to arrive and be processed
if ((*it)->GetCharID())
ClientVersionRequestQueue[(*it)->GetCharID()] = (Timer::GetCurrentTime() + (RuleI(Chat, ExpireClientVersionRequests) * 1000));
if ((*it)->GetConnectionType() == ConnectionTypeCombined)
(*it)->SendFriends();
@@ -681,8 +687,35 @@ void Clientlist::Process()
it = ClientChatConnections.erase(it);
continue;
}
// initiate request if we don't already have a reply from 'world enter' (ucs crash recovery protocol)
if ((*it)->GetClientVersion() == EQEmu::versions::ClientVersion::Unknown) {
if (!CheckForClientVersionReply((*it)))
RequestClientVersion((*it)->GetCharID());
}
++it;
}
// delete expired replies
auto repiter = ClientVersionReplyQueue.begin();
while (repiter != ClientVersionReplyQueue.end()) {
if ((*repiter).second.second <= Timer::GetCurrentTime()) {
repiter = ClientVersionReplyQueue.erase(repiter);
continue;
}
++repiter;
}
// delete expired requests
auto reqiter = ClientVersionRequestQueue.begin();
while (reqiter != ClientVersionRequestQueue.end()) {
if ((*reqiter).second <= Timer::GetCurrentTime()) {
reqiter = ClientVersionRequestQueue.erase(reqiter);
continue;
}
++reqiter;
}
}
void Clientlist::ProcessOPMailCommand(Client *c, std::string CommandString)
@@ -840,6 +873,55 @@ void Clientlist::ProcessOPMailCommand(Client *c, std::string CommandString)
}
}
void Clientlist::RequestClientVersion(uint32 character_id) {
if (!character_id)
return;
if (ClientVersionRequestQueue.find(character_id) != ClientVersionRequestQueue.end()) {
if (ClientVersionRequestQueue[character_id] > Timer::GetCurrentTime())
return;
}
if (LogSys.log_settings[Logs::UCS_Server].is_category_enabled) {
Log(Logs::Detail, Logs::UCS_Server, "Requesting ClientVersion reply for character id: %u",
character_id);
}
ClientVersionRequestIDs.push_back(character_id);
ClientVersionRequestQueue[character_id] = (Timer::GetCurrentTime() + (RuleI(Chat, ExpireClientVersionRequests) * 1000));
}
bool Clientlist::QueueClientVersionReply(uint32 character_id, EQEmu::versions::ClientVersion client_version) {
if (!character_id)
return true;
if (client_version == EQEmu::versions::ClientVersion::Unknown)
return false;
if (LogSys.log_settings[Logs::UCS_Server].is_category_enabled) {
Log(Logs::Detail, Logs::UCS_Server, "Queueing ClientVersion %u reply for character id: %u",
static_cast<uint32>(client_version), character_id);
}
ClientVersionReplyQueue[character_id] = cvt_pair(client_version, (Timer::GetCurrentTime() + (RuleI(Chat, ExpireClientVersionReplies) * 1000)));
ClientVersionRequestQueue.erase(character_id);
return true;
}
bool Clientlist::CheckForClientVersionReply(Client* c) {
if (!c)
return true;
if (ClientVersionReplyQueue.find(c->GetCharID()) == ClientVersionReplyQueue.end())
return false;
if (LogSys.log_settings[Logs::UCS_Server].is_category_enabled) {
Log(Logs::General, Logs::UCS_Server, "Registering ClientVersion %s for stream %s:%u",
EQEmu::versions::ClientVersionName(ClientVersionReplyQueue[c->GetCharID()].first), c->ClientStream->GetRemoteAddr().c_str(), c->ClientStream->GetRemotePort());
}
c->SetClientVersion(ClientVersionReplyQueue[c->GetCharID()].first);
ClientVersionReplyQueue.erase(c->GetCharID());
return true;
}
void Clientlist::CloseAllConnections() {
@@ -2132,6 +2214,8 @@ void Client::AccountUpdate()
void Client::SetConnectionType(char c) {
RawConnectionType = c;
switch (c)
{
case 'S':
@@ -2161,6 +2245,7 @@ void Client::SetConnectionType(char c) {
}
default:
{
RawConnectionType = '\0';
TypeOfConnection = ConnectionTypeUnknown;
Log(Logs::Detail, Logs::UCS_Server, "Connection type is unknown.");
}
+18
View File
@@ -139,8 +139,13 @@ public:
std::string MailBoxName();
int GetMailBoxNumber() { return CurrentMailBox; }
int GetMailBoxNumber(std::string CharacterName);
char GetRawConnectionType() { return RawConnectionType; }
void SetConnectionType(char c);
ConnectionType GetConnectionType() { return TypeOfConnection; }
void SetClientVersion(EQEmu::versions::ClientVersion client_version) { ClientVersion_ = client_version; }
EQEmu::versions::ClientVersion GetClientVersion() { return ClientVersion_; }
inline bool IsMailConnection() { return (TypeOfConnection == ConnectionTypeMail) || (TypeOfConnection == ConnectionTypeCombined); }
void SendNotification(int MailBoxNumber, std::string From, std::string Subject, int MessageID);
void ChangeMailBox(int NewMailBox);
@@ -167,7 +172,10 @@ private:
Timer *GlobalChatLimiterTimer; //60 seconds
int AttemptedMessages;
bool ForceDisconnect;
char RawConnectionType;
ConnectionType TypeOfConnection;
EQEmu::versions::ClientVersion ClientVersion_;
bool UnderfootOrLater;
};
@@ -182,12 +190,22 @@ public:
Client *IsCharacterOnline(std::string CharacterName);
void ProcessOPMailCommand(Client *c, std::string CommandString);
std::list<uint32> ClientVersionRequestIDs;
void RequestClientVersion(uint32 character_id);
bool QueueClientVersionReply(uint32 character_id, EQEmu::versions::ClientVersion client_version);
bool CheckForClientVersionReply(Client* c);
private:
typedef std::pair<EQEmu::versions::ClientVersion, uint32> cvt_pair;
EQ::Net::EQStreamManager *chatsf;
std::list<Client*> ClientChatConnections;
std::map<uint32, uint32> ClientVersionRequestQueue;
std::map<uint32, cvt_pair> ClientVersionReplyQueue;
OpcodeManager *ChatOpMgr;
};
+5
View File
@@ -140,12 +140,17 @@ int main() {
worldserver = new WorldServer;
// now that we can send packets to world, see if there's a
// broadcast opcode that tells the client to relog into ucs
while(RunLoops) {
Timer::SetCurrentTime();
g_Clientlist->Process();
worldserver->ProcessClientVersionRequests(g_Clientlist->ClientVersionRequestIDs);
if(ChannelListProcessTimer.Check())
ChannelList->Process();
+18
View File
@@ -114,5 +114,23 @@ void WorldServer::ProcessMessage(uint16 opcode, EQ::Net::Packet &p)
std::string());
break;
}
case ServerOP_UCSClientVersionReply:
{
UCSClientVersionReply_Struct* cvr = (UCSClientVersionReply_Struct*)pack->pBuffer;
g_Clientlist->QueueClientVersionReply(cvr->character_id, cvr->client_version);
break;
}
}
}
void WorldServer::ProcessClientVersionRequests(std::list<uint32>& id_list) {
UCSClientVersionRequest_Struct cvr;
EQ::Net::DynamicPacket dp_cvr;
for (auto iter : id_list) {
cvr.character_id = iter;
dp_cvr.PutData(0, &cvr, sizeof(cvr));
m_connection->Send(ServerOP_UCSClientVersionRequest, dp_cvr);
}
id_list.clear();
}
+2
View File
@@ -29,6 +29,8 @@ public:
~WorldServer();
void ProcessMessage(uint16 opcode, EQ::Net::Packet &);
void ProcessClientVersionRequests(std::list<uint32>& id_list);
private:
std::unique_ptr<EQ::Net::ServertalkClient> m_connection;