Changeset View
Changeset View
Standalone View
Standalone View
source/network/NetSession.cpp
/* Copyright (C) 2019 Wildfire Games. | /* Copyright (C) 2021 Wildfire Games. | ||||
* This file is part of 0 A.D. | * This file is part of 0 A.D. | ||||
* | * | ||||
* 0 A.D. is free software: you can redistribute it and/or modify | * 0 A.D. is free software: you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation, either version 2 of the License, or | * the Free Software Foundation, either version 2 of the License, or | ||||
* (at your option) any later version. | * (at your option) any later version. | ||||
* | * | ||||
* 0 A.D. is distributed in the hope that it will be useful, | * 0 A.D. is distributed in the hope that it will be useful, | ||||
Show All 10 Lines | |||||
#include "NetSession.h" | #include "NetSession.h" | ||||
#include "NetClient.h" | #include "NetClient.h" | ||||
#include "NetMessage.h" | #include "NetMessage.h" | ||||
#include "NetServer.h" | #include "NetServer.h" | ||||
#include "NetStats.h" | #include "NetStats.h" | ||||
#include "ps/CLogger.h" | #include "ps/CLogger.h" | ||||
#include "ps/Profile.h" | #include "ps/Profile.h" | ||||
#include "ps/ThreadPool.h" | |||||
#include "scriptinterface/ScriptInterface.h" | #include "scriptinterface/ScriptInterface.h" | ||||
constexpr int NETCLIENT_POLL_TIMEOUT = 50; | |||||
constexpr int CHANNEL_COUNT = 1; | constexpr int CHANNEL_COUNT = 1; | ||||
CNetClientSession::CNetClientSession(CNetClient& client) : | CNetClientSession::CNetClientSession(CNetClient& client) : | ||||
m_Client(client), m_FileTransferer(this), m_Host(nullptr), m_Server(nullptr), | m_Client(client), m_FileTransferer(this), m_Host(nullptr), m_Server(nullptr), | ||||
m_Stats(nullptr), m_IncomingMessages(16), m_OutgoingMessages(16), | m_Stats(nullptr), m_IncomingMessages(16), m_OutgoingMessages(16), | ||||
m_LoopRunning(false), m_ShouldShutdown(false), m_MeanRTT(0), m_LastReceivedTime(0) | m_LoopRunning(false), m_ShouldShutdown(false), m_MeanRTT(0), m_LastReceivedTime(0) | ||||
{ | { | ||||
} | } | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | bool CNetClientSession::Connect(const CStr& server, const u16 port, ENetHost* enetClient) | ||||
m_Stats = new CNetStatsTable(m_Server); | m_Stats = new CNetStatsTable(m_Server); | ||||
if (CProfileViewer::IsInitialised()) | if (CProfileViewer::IsInitialised()) | ||||
g_ProfileViewer.AddRootTable(m_Stats); | g_ProfileViewer.AddRootTable(m_Stats); | ||||
return true; | return true; | ||||
} | } | ||||
void CNetClientSession::RunNetLoop(CNetClientSession* session) | void CNetClientSession::StartRecurrentTask(CNetClientSession* session) | ||||
{ | { | ||||
ENSURE(!session->m_LoopRunning); | |||||
session->m_LoopRunning = true; | session->m_LoopRunning = true; | ||||
ThreadPool::TaskManager::Instance().AddRecurrentTask(30, [session, future=Future<void>()](ThreadPool::PoolExecutor& exec) mutable { | |||||
return session->RunNetUpdate(future, exec); | |||||
}); | |||||
} | |||||
debug_SetThreadName("NetClientSession loop"); | ThreadPool::RecurrentTaskStatus CNetClientSession::RunNetUpdate(Future<void>& future, ThreadPool::PoolExecutor& exec) | ||||
while (!session->m_ShouldShutdown) | |||||
{ | { | ||||
ENSURE(session->m_Host && session->m_Server); | if (future.Valid() && !future.IsReady()) | ||||
return ThreadPool::RecurrentTaskStatus::RETRY; | |||||
session->m_FileTransferer.Poll(); | if (m_ShouldShutdown) | ||||
session->Poll(); | { | ||||
session->Flush(); | m_LoopRunning = false; | ||||
delete this; | |||||
session->m_LastReceivedTime = enet_time_get() - session->m_Server->lastReceiveTime; | return ThreadPool::RecurrentTaskStatus::STOP; | ||||
session->m_MeanRTT = session->m_Server->roundTripTime; | |||||
} | } | ||||
session->m_LoopRunning = false; | ENSURE(m_Host && m_Server); | ||||
// Deleting the session is handled in this thread as it might outlive the CNetClient. | m_LastReceivedTime = enet_time_get() - m_Server->lastReceiveTime; | ||||
SAFE_DELETE(session); | m_MeanRTT = m_Server->roundTripTime; | ||||
// Check if we have some work to do, if not exit early. | |||||
ENetEvent event; | |||||
// TODO: handle errors. | |||||
bool hasWork = enet_host_service(m_Host, &event, 0) > 0; | |||||
if (!hasWork && m_FileTransferer.HasWork()) | |||||
hasWork = true; | |||||
else if (!m_OutgoingMessages.empty()) | |||||
hasWork = true; | |||||
if (hasWork) | |||||
future = exec.Submit([event, this]() mutable { | |||||
PROFILE2("NetClient - Update"); | |||||
m_FileTransferer.Poll(); | |||||
Flush(); | |||||
do | |||||
Poll(event); | |||||
while (enet_host_service(m_Host, &event, 0) > 0); | |||||
}); | |||||
return ThreadPool::RecurrentTaskStatus::OK; | |||||
} | } | ||||
void CNetClientSession::Shutdown() | void CNetClientSession::Shutdown() | ||||
{ | { | ||||
// On the next timer loop, this will clean up the net session. | |||||
m_ShouldShutdown = true; | m_ShouldShutdown = true; | ||||
} | } | ||||
void CNetClientSession::Poll() | void CNetClientSession::Poll(const ENetEvent& event) | ||||
{ | { | ||||
ENetEvent event; | |||||
// Use the timeout to make the thread wait and save CPU time. | |||||
if (enet_host_service(m_Host, &event, NETCLIENT_POLL_TIMEOUT) <= 0) | |||||
return; | |||||
if (event.type == ENET_EVENT_TYPE_CONNECT) | if (event.type == ENET_EVENT_TYPE_CONNECT) | ||||
{ | { | ||||
ENSURE(event.peer == m_Server); | ENSURE(event.peer == m_Server); | ||||
// Report the server address immediately. | // Report the server address immediately. | ||||
char hostname[256] = "(error)"; | char hostname[256] = "(error)"; | ||||
enet_address_get_host_ip(&event.peer->address, hostname, ARRAY_SIZE(hostname)); | enet_address_get_host_ip(&event.peer->address, hostname, ARRAY_SIZE(hostname)); | ||||
LOGMESSAGE("Net client: Connected to %s:%u", hostname, (unsigned int)event.peer->address.port); | LOGMESSAGE("Net client: Connected to %s:%u", hostname, (unsigned int)event.peer->address.port); | ||||
▲ Show 20 Lines • Show All 144 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator