| 269 | |
| 270 | |
| 271 | void CServerList::ServerStats() |
| 272 | { |
| 273 | uint64 tNow = ::GetTickCount64(); |
| 274 | time_t currentTime = time(NULL); |
| 275 | |
| 276 | if (theApp->IsConnectedED2K() && !m_servers.empty()) { |
| 277 | CServer* ping_server = GetNextStatServer(); |
| 278 | CServer* test = ping_server; |
| 279 | if (!ping_server) { |
| 280 | return; |
| 281 | } |
| 282 | |
| 283 | while (ping_server->GetLastPingedTime() && currentTime < (ping_server->GetLastPingedTime() + UDPSERVSTATREASKTIME)) { |
| 284 | ping_server = GetNextStatServer(); |
| 285 | if (ping_server == test) { |
| 286 | return; |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | if (ping_server->GetFailedCount() >= thePrefs::GetDeadserverRetries() && thePrefs::DeadServer() && !ping_server->IsStaticMember()) { |
| 291 | RemoveServer(ping_server); |
| 292 | return; |
| 293 | } |
| 294 | |
| 295 | srand((unsigned)time(NULL)); |
| 296 | ping_server->SetRealLastPingedTime(currentTime); // this is not used to calculate the next ping, but only to ensure a minimum delay for premature pings |
| 297 | if (!ping_server->GetCryptPingReplyPending() && (!ping_server->GetLastPingedTime() || currentTime >= (ping_server->GetLastPingedTime() + UDPSERVSTATREASKTIME)) && theApp->GetPublicIP() && thePrefs::IsServerCryptLayerUDPEnabled()) { |
| 298 | // We try a obfsucation ping first and wait 20 seconds for an answer |
| 299 | // if it doesn't get responded to, we don't count it as error but continue with a normal ping |
| 300 | ping_server->SetCryptPingReplyPending(true); |
| 301 | uint32 nPacketLen = 4 + (uint8)(rand() % 16); // max padding 16 bytes |
| 302 | CScopedArray<uint8_t> pRawPacket(nPacketLen); |
| 303 | uint32 dwChallenge = (rand() << 17) | (rand() << 2) | (rand() & 0x03); |
| 304 | if (dwChallenge == 0) { |
| 305 | dwChallenge++; |
| 306 | } |
| 307 | |
| 308 | memcpy(pRawPacket.get(), &dwChallenge, sizeof(uint32)); |
| 309 | for (uint32 i = 4; i < nPacketLen; i++) { // fillng up the remaining bytes with random data |
| 310 | pRawPacket[i] = (uint8)rand(); |
| 311 | } |
| 312 | |
| 313 | ping_server->SetChallenge(dwChallenge); |
| 314 | ping_server->SetLastPinged(tNow); //in milliseconds, to calculate the ping |
| 315 | ping_server->SetLastPingedTime((currentTime - UDPSERVSTATREASKTIME) + 20); //in seconds, give it 20 extra seconds to respond |
| 316 | |
| 317 | AddDebugLogLineN(logServerUDP, CFormat(">> Sending OP__GlobServStatReq (obfuscated) to server %s:%u") % ping_server->GetAddress() % ping_server->GetPort()); |
| 318 | |
| 319 | CPacket* packet = new CPacket(pRawPacket[1], nPacketLen - 2, pRawPacket[0]); |
| 320 | packet->CopyToDataBuffer(0, pRawPacket.get() + 2, nPacketLen - 2); |
| 321 | |
| 322 | theStats::AddUpOverheadServer(packet->GetPacketSize()); |
| 323 | theApp->serverconnect->SendUDPPacket(packet, ping_server, true, true /*raw packet*/, 12 /* Port offset is 12 for obfuscated encryption*/); |
| 324 | } else if (ping_server->GetCryptPingReplyPending() || theApp->GetPublicIP() == 0 || !thePrefs::IsServerCryptLayerUDPEnabled()){ |
| 325 | // our obfsucation ping request was not answered, so probably the server doesn'T supports obfuscation |
| 326 | // continue with a normal request |
| 327 | if (ping_server->GetCryptPingReplyPending() && thePrefs::IsServerCryptLayerUDPEnabled()) { |
| 328 | AddDebugLogLineN(logServerUDP, "CryptPing failed for server " + ping_server->GetListName()); |
no test coverage detected