Initial work on client server within same process

This commit is contained in:
Benau 2020-02-28 09:41:07 +08:00
parent b7f2a9614d
commit c8ea01d264
18 changed files with 392 additions and 151 deletions

View File

@ -687,6 +687,7 @@ namespace GUIEngine
#include "tips/tips_manager.hpp"
#include "utils/debug.hpp"
#include "utils/string_utils.hpp"
#include "utils/stk_process.hpp"
#include "utils/translation.hpp"
#include <algorithm>
@ -755,7 +756,7 @@ namespace GUIEngine
std::vector<MenuMessage> gui_messages;
bool g_is_no_graphics;
bool g_is_no_graphics[PT_COUNT];
// ------------------------------------------------------------------------
void showMessage(const core::stringw& message, const float time)
{
@ -1052,7 +1053,8 @@ namespace GUIEngine
#ifdef ANDROID
m_gui_functions.clear();
#endif
g_is_no_graphics = false;
g_is_no_graphics[PT_MAIN] = false;
g_is_no_graphics[PT_CHILD] = false;
} // resetGlobalVariables
// -----------------------------------------------------------------------
@ -1556,13 +1558,13 @@ namespace GUIEngine
// -----------------------------------------------------------------------
void disableGraphics()
{
g_is_no_graphics = true;
g_is_no_graphics[STKProcess::getType()] = true;
} // disableGraphics
// -----------------------------------------------------------------------
bool isNoGraphics()
{
return g_is_no_graphics;
return g_is_no_graphics[STKProcess::getType()];
} // isNoGraphics
#endif

View File

@ -222,6 +222,9 @@
#include "network/network.hpp"
#include "network/network_config.hpp"
#include "network/network_string.hpp"
#include "network/protocols/connect_to_server.hpp"
#include "network/protocols/client_lobby.hpp"
#include "network/protocols/server_lobby.hpp"
#include "network/rewind_manager.hpp"
#include "network/rewind_queue.hpp"
#include "network/server.hpp"
@ -1731,6 +1734,9 @@ void clearGlobalVariables()
// In android sometimes global variables is not reset when restart the app
// we clear it here as much as possible
STKProcess::reset();
StateManager::clear();
NetworkConfig::clear();
STKHost::clear();
race_manager = NULL;
music_manager = NULL;
irr_driver = NULL;

140
src/network/child_loop.cpp Normal file
View File

@ -0,0 +1,140 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2020 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "network/child_loop.hpp"
#include "config/user_config.hpp"
#include "guiengine/engine.hpp"
#include "network/network_config.hpp"
#include "network/protocol_manager.hpp"
#include "network/protocols/server_lobby.hpp"
#include "network/server_config.hpp"
#include "network/stk_host.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/log.hpp"
#include "utils/stk_process.hpp"
#include "utils/time.hpp"
#include "utils/vs.hpp"
// ----------------------------------------------------------------------------
float ChildLoop::getLimitedDt()
{
m_prev_time = m_curr_time;
float dt = 0;
while (1)
{
m_curr_time = StkTime::getMonoTimeMs();
if (m_prev_time > m_curr_time)
{
m_prev_time = m_curr_time;
}
dt = (float)(m_curr_time - m_prev_time);
while (dt == 0)
{
StkTime::sleep(1);
m_curr_time = StkTime::getMonoTimeMs();
if (m_prev_time > m_curr_time)
{
Log::error("MainLopp", "System clock keeps backwards!");
m_prev_time = m_curr_time;
}
dt = (float)(m_curr_time - m_prev_time);
}
const int current_fps = (int)(1000.0f / dt);
const int max_fps = UserConfigParams::m_max_fps;
if (current_fps <= max_fps)
break;
int wait_time = 1000 / max_fps - 1000 / current_fps;
if (wait_time < 1) wait_time = 1;
StkTime::sleep(wait_time);
} // while(1)
dt *= 0.001f;
return dt;
} // getLimitedDt
// ----------------------------------------------------------------------------
void ChildLoop::run()
{
VS::setThreadName("ChildLoop");
STKProcess::init(PT_CHILD);
GUIEngine::disableGraphics();
NetworkConfig::get()->setIsServer(true);
if (m_cl_config->m_lan_server)
NetworkConfig::get()->setIsLAN();
else
{
NetworkConfig::get()->setIPType(NetworkConfig::IP_V4);
NetworkConfig::get()->detectIPType();
NetworkConfig::get()->setIsWAN();
NetworkConfig::get()->setIsPublicServer();
}
NetworkConfig::get()->setCurrentUserId(m_cl_config->m_login_id);
NetworkConfig::get()->setCurrentUserToken(m_cl_config->m_token);
NetworkConfig::get()->setNumFixedAI(m_cl_config->m_server_ai);
// Unused afterwards
delete m_cl_config;
m_cl_config = NULL;
ServerConfig::loadServerLobbyFromConfig();
StateManager::get()->enterMenuState();
m_curr_time = StkTime::getMonoTimeMs();
float left_over_time = 0;
while (!m_abort)
{
if ((STKHost::existHost() && STKHost::get()->requestedShutdown()) ||
m_request_abort)
{
if (STKHost::existHost())
STKHost::get()->shutdown();
m_abort = true;
}
// Tell the main process port and server id
if (m_port == 0 && STKHost::existHost())
{
auto sl = LobbyProtocol::get<ServerLobby>();
if (sl &&
sl->getCurrentState() >= ServerLobby::WAITING_FOR_START_GAME)
{
m_port = STKHost::get()->getPrivatePort();
m_server_online_id = sl->getServerIdOnline();
}
}
left_over_time += getLimitedDt();
int num_steps = stk_config->time2Ticks(left_over_time);
float dt = stk_config->ticks2Time(1);
left_over_time -= num_steps * dt;
for (int i = 0; i < num_steps; i++)
{
if (auto pm = ProtocolManager::lock())
pm->update(1);
if (m_abort || m_request_abort)
break;
}
}
NetworkConfig::destroy();
StateManager::deallocate();
} // run

View File

@ -0,0 +1,67 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2020 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_SERVER_LOOP_HPP
#define HEADER_SERVER_LOOP_HPP
#include "utils/types.hpp"
#include <atomic>
#include <string>
struct ChildLoopConfig
{
bool m_lan_server;
uint32_t m_login_id;
std::string m_token;
unsigned m_server_ai;
};
class ChildLoop
{
private:
const ChildLoopConfig* m_cl_config;
std::atomic_bool m_abort;
std::atomic_bool m_request_abort;
std::atomic<uint16_t> m_port;
std::atomic<uint32_t> m_server_online_id;
uint64_t m_curr_time;
uint64_t m_prev_time;
float getLimitedDt();
public:
ChildLoop(const ChildLoopConfig& clc)
: m_cl_config(new ChildLoopConfig(clc))
{
m_abort = false;
m_request_abort = false;
m_prev_time = m_curr_time = 0;
m_port = 0;
m_server_online_id = 0;
}
void run();
/** Set the abort flag, causing the mainloop to be left. */
void abort() { m_abort = true; }
void requestAbort() { m_request_abort = true; }
uint16_t getPort() const { return m_port; }
uint32_t getServerOnlineId() const { return m_server_online_id; }
}; // ChildLoop
#endif

View File

@ -44,7 +44,7 @@
# include <netdb.h>
#endif
NetworkConfig *NetworkConfig::m_network_config = NULL;
NetworkConfig *NetworkConfig::m_network_config[PT_COUNT];
/** \class NetworkConfig
* This class is the interface between STK and the online code, particularly

View File

@ -23,11 +23,13 @@
#define HEADER_NETWORK_CONFIG
#include "race/race_manager.hpp"
#include "utils/stk_process.hpp"
#include "utils/no_copy.hpp"
#include "irrString.h"
#include <array>
#include <atomic>
#include <cstring>
#include <memory>
#include <set>
#include <tuple>
@ -55,7 +57,7 @@ public:
};
private:
/** The singleton instance. */
static NetworkConfig *m_network_config;
static NetworkConfig *m_network_config[PT_COUNT];
enum NetworkType
{
@ -122,18 +124,23 @@ public:
/** Singleton get, which creates this object if necessary. */
static NetworkConfig *get()
{
if (!m_network_config)
m_network_config = new NetworkConfig();
return m_network_config;
ProcessType type = STKProcess::getType();
if (!m_network_config[type])
m_network_config[type] = new NetworkConfig();
return m_network_config[type];
} // get
// ------------------------------------------------------------------------
static void destroy()
{
delete m_network_config; // It's ok to delete NULL
m_network_config = NULL;
ProcessType type = STKProcess::getType();
delete m_network_config[type]; // It's ok to delete NULL
m_network_config[type] = NULL;
} // destroy
// ------------------------------------------------------------------------
static void clear()
{
memset(m_network_config, 0, sizeof(m_network_config));
} // clear
// ------------------------------------------------------------------------
/** Sets if this instance is a server or client. */
void setIsServer(bool b)

View File

@ -37,7 +37,7 @@
#include <typeinfo>
// ============================================================================
std::weak_ptr<ProtocolManager> ProtocolManager::m_protocol_manager;
std::weak_ptr<ProtocolManager> ProtocolManager::m_protocol_manager[PT_COUNT];
// ============================================================================
std::shared_ptr<ProtocolManager> ProtocolManager::createInstance()
{
@ -47,10 +47,17 @@ std::shared_ptr<ProtocolManager> ProtocolManager::createInstance()
"Create only 1 instance of ProtocolManager!");
return NULL;
}
// This is called in STKHost creation, so its process type will be told
// here
ProcessType pt = STKProcess::getType();
auto pm = std::make_shared<ProtocolManager>();
pm->m_asynchronous_update_thread = std::thread([pm]()
pm->m_asynchronous_update_thread = std::thread([pm, pt]()
{
VS::setThreadName("ProtocolManager");
std::string thread_name = "PtlMgr";
if (pt == PT_CHILD)
thread_name += "_child";
VS::setThreadName(thread_name.c_str());
STKProcess::init(pt);
while(!pm->m_exit.load())
{
pm->asynchronousUpdate();
@ -61,9 +68,10 @@ std::shared_ptr<ProtocolManager> ProtocolManager::createInstance()
});
if (NetworkConfig::get()->isServer())
{
pm->m_game_protocol_thread = std::thread([pm]()
pm->m_game_protocol_thread = std::thread([pm, pt]()
{
VS::setThreadName("CtrlEvents");
STKProcess::init(pt);
while (true)
{
std::unique_lock<std::mutex> ul(pm->m_game_protocol_mutex);
@ -94,7 +102,7 @@ std::shared_ptr<ProtocolManager> ProtocolManager::createInstance()
}
});
}
m_protocol_manager = pm;
m_protocol_manager[pt] = pm;
return pm;
} // createInstance

View File

@ -27,6 +27,7 @@
#include "network/protocol.hpp"
#include "utils/no_copy.hpp"
#include "utils/singleton.hpp"
#include "utils/stk_process.hpp"
#include "utils/synchronised.hpp"
#include "utils/types.hpp"
@ -174,7 +175,7 @@ private:
EventList m_controller_events_list;
/*! Single instance of protocol manager.*/
static std::weak_ptr<ProtocolManager> m_protocol_manager;
static std::weak_ptr<ProtocolManager> m_protocol_manager[PT_COUNT];
bool sendEvent(Event* event,
std::array<OneProtocolType, PROTOCOL_MAX>& protocols);
@ -205,12 +206,12 @@ public:
// ------------------------------------------------------------------------
static bool emptyInstance()
{
return m_protocol_manager.expired();
return m_protocol_manager[STKProcess::getType()].expired();
} // emptyInstance
// ------------------------------------------------------------------------
static std::shared_ptr<ProtocolManager> lock()
{
return m_protocol_manager.lock();
return m_protocol_manager[STKProcess::getType()].lock();
} // lock
}; // class ProtocolManager

View File

@ -30,6 +30,7 @@
#include "network/protocol_manager.hpp"
#include "network/servers_manager.hpp"
#include "network/server.hpp"
#include "network/child_loop.hpp"
#include "network/socket_address.hpp"
#include "network/stk_ipv6.hpp"
#include "network/stk_host.hpp"
@ -113,42 +114,22 @@ void ConnectToServer::getClientServerInfo()
{
assert(m_server);
// Allow up to 10 seconds for the separate process to fully start-up
bool server_ipv6_socket = false;
bool started = false;
uint64_t timeout = StkTime::getMonoTimeMs() + 10000;
const std::string& sid = NetworkConfig::get()->getServerIdFile();
assert(!sid.empty());
const std::string dir = StringUtils::getPath(sid);
const std::string server_id_file = StringUtils::getBasename(sid);
uint16_t port = 0;
unsigned server_id = 0;
ChildLoop* sl = STKHost::get()->getChildLoop();
assert(sl);
while (!ProtocolManager::lock()->isExiting() &&
StkTime::getMonoTimeMs() < timeout)
{
std::set<std::string> files;
file_manager->listFiles(files, dir);
for (auto& f : files)
{
if (f.find(server_id_file) != std::string::npos)
{
auto split = StringUtils::split(f, '_');
if (split.size() != 4)
continue;
if (!StringUtils::fromString(split[1], server_id))
continue;
if (!StringUtils::fromString(split[2], port))
continue;
server_ipv6_socket = split[3] == "v6";
file_manager->removeFile(dir + "/" + f);
started = true;
break;
}
}
port = sl->getPort();
server_id = sl->getServerOnlineId();
started = port != 0;
if (started)
break;
StkTime::sleep(10);
StkTime::sleep(1);
}
NetworkConfig::get()->setServerIdFile("");
if (!started)
{
Log::error("ConnectToServer",
@ -161,7 +142,8 @@ void ConnectToServer::getClientServerInfo()
assert(port != 0);
m_server->setAddress(SocketAddress("127.0.0.1", port));
m_server->setPrivatePort(port);
if (server_ipv6_socket)
// The server will decide if to use IPv6 socket
if (isIPv6Socket())
{
m_server->setIPV6Address(SocketAddress("::1", port));
m_server->setIPV6Connection(true);
@ -178,7 +160,7 @@ void ConnectToServer::getClientServerInfo()
void ConnectToServer::asynchronousUpdate()
{
if (STKHost::get()->isClientServer() &&
!NetworkConfig::get()->getServerIdFile().empty())
m_server->getAddress().getPort() == 0)
{
getClientServerInfo();
}

View File

@ -44,7 +44,7 @@
#include "utils/time.hpp"
#include "utils/translation.hpp"
std::weak_ptr<LobbyProtocol> LobbyProtocol::m_lobby;
std::weak_ptr<LobbyProtocol> LobbyProtocol::m_lobby[PT_COUNT];
LobbyProtocol::LobbyProtocol()
: Protocol(PROTOCOL_LOBBY_ROOM)

View File

@ -20,6 +20,7 @@
#define LOBBY_PROTOCOL_HPP
#include "network/protocol.hpp"
#include "utils/stk_process.hpp"
class GameSetup;
class NetworkPlayerProfile;
@ -113,7 +114,7 @@ protected:
std::thread m_start_game_thread;
static std::weak_ptr<LobbyProtocol> m_lobby;
static std::weak_ptr<LobbyProtocol> m_lobby[PT_COUNT];
/** Estimated current started game remaining time,
* uint32_t max if not available. */
@ -157,9 +158,10 @@ public:
template<typename Singleton, typename... Types>
static std::shared_ptr<Singleton> create(Types ...args)
{
assert(m_lobby.expired());
ProcessType pt = STKProcess::getType();
assert(m_lobby[pt].expired());
auto ret = std::make_shared<Singleton>(args...);
m_lobby = ret;
m_lobby[pt] = ret;
return std::dynamic_pointer_cast<Singleton>(ret);
} // create
@ -167,7 +169,8 @@ public:
/** Returns the singleton client or server lobby protocol. */
template<class T> static std::shared_ptr<T> get()
{
if (std::shared_ptr<LobbyProtocol> lp = m_lobby.lock())
ProcessType pt = STKProcess::getType();
if (std::shared_ptr<LobbyProtocol> lp = m_lobby[pt].lock())
{
std::shared_ptr<T> new_type = std::dynamic_pointer_cast<T>(lp);
if (new_type)

View File

@ -388,6 +388,7 @@ public:
void initServerStatsTable();
bool isAIProfile(const std::shared_ptr<NetworkPlayerProfile>& npp) const
{ return m_ai_profiles.find(npp) != m_ai_profiles.end(); }
uint32_t getServerIdOnline() const { return m_server_id_online; }
}; // class ServerLobby
#endif // SERVER_LOBBY_HPP

View File

@ -33,6 +33,7 @@
#include "network/protocols/server_lobby.hpp"
#include "network/protocol_manager.hpp"
#include "network/server_config.hpp"
#include "network/child_loop.hpp"
#include "network/stk_ipv6.hpp"
#include "network/stk_peer.hpp"
#include "utils/log.hpp"
@ -71,31 +72,37 @@
#include <string>
#include <utility>
STKHost *STKHost::m_stk_host = NULL;
STKHost *STKHost::m_stk_host[PT_COUNT];
bool STKHost::m_enable_console = false;
std::shared_ptr<LobbyProtocol> STKHost::create(SeparateProcess* p)
std::shared_ptr<LobbyProtocol> STKHost::create(ChildLoop* cl)
{
assert(m_stk_host == NULL);
ProcessType pt = STKProcess::getType();
assert(m_stk_host[pt] == NULL);
std::shared_ptr<LobbyProtocol> lp;
if (NetworkConfig::get()->isServer())
{
std::shared_ptr<ServerLobby> sl =
LobbyProtocol::create<ServerLobby>();
m_stk_host = new STKHost(true/*server*/);
m_stk_host[pt] = new STKHost(true/*server*/);
sl->initServerStatsTable();
lp = sl;
}
else
{
m_stk_host = new STKHost(false/*server*/);
m_stk_host[pt] = new STKHost(false/*server*/);
}
// Separate process for client-server gui if exists
m_stk_host->m_separate_process = p;
if (!m_stk_host->m_network)
m_stk_host[pt]->m_client_loop = cl;
if (cl)
{
delete m_stk_host;
m_stk_host = NULL;
m_stk_host[pt]->m_client_loop_thread = std::thread(
std::bind(&ChildLoop::run, cl));
}
if (!m_stk_host[pt]->m_network)
{
delete m_stk_host[pt];
m_stk_host[pt] = NULL;
}
return lp;
} // create
@ -342,6 +349,11 @@ void STKHost::init()
*/
STKHost::~STKHost()
{
// Abort the server loop earlier so it can be stopped in background as
// soon as possible
if (m_client_loop)
m_client_loop->requestAbort();
NetworkConfig::get()->clearActivePlayersForClient();
requestShutdown();
if (m_network_console.joinable())
@ -362,7 +374,11 @@ STKHost::~STKHost()
}
delete m_network;
enet_deinitialize();
delete m_separate_process;
if (m_client_loop)
{
m_client_loop_thread.join();
delete m_client_loop;
}
} // ~STKHost
//-----------------------------------------------------------------------------
@ -721,7 +737,8 @@ void STKHost::setErrorMessage(const irr::core::stringw &message)
void STKHost::startListening()
{
m_exit_timeout.store(std::numeric_limits<uint64_t>::max());
m_listening_thread = std::thread(std::bind(&STKHost::mainLoop, this));
m_listening_thread = std::thread(std::bind(&STKHost::mainLoop, this,
STKProcess::getType()));
} // startListening
// ----------------------------------------------------------------------------
@ -741,11 +758,16 @@ void STKHost::stopListening()
* This function tries to get data from network low-level functions as
* often as possible. When something is received, it generates an
* event and passes it to the Network Manager.
* \param self : used to pass the ENet host to the function.
* \param pt : Used to register to different singleton.
*/
void STKHost::mainLoop()
void STKHost::mainLoop(ProcessType pt)
{
VS::setThreadName("STKHost");
std::string thread_name = "STKHost";
if (pt == PT_CHILD)
thread_name += "_child";
VS::setThreadName(thread_name.c_str());
STKProcess::init(pt);
Log::info("STKHost", "Listening has been started.");
ENetEvent event;
ENetHost* host = m_network->getENetHost();
@ -1529,15 +1551,9 @@ void STKHost::updatePlayers(unsigned* ingame, unsigned* waiting,
* creation screen. */
bool STKHost::isClientServer() const
{
return NetworkConfig::get()->isClient() && m_separate_process != NULL;
return m_client_loop != NULL;
} // isClientServer
// ----------------------------------------------------------------------------
bool STKHost::hasServerAI() const
{
return NetworkConfig::get()->isServer() && m_separate_process != NULL;
} // hasServerAI
// ----------------------------------------------------------------------------
/** Return an valid public IPv4 or IPv6 address with port, empty if both are
* unset, IPv6 will come first if both exists. */

View File

@ -22,6 +22,7 @@
#ifndef STK_HOST_HPP
#define STK_HOST_HPP
#include "utils/stk_process.hpp"
#include "utils/synchronised.hpp"
#include "utils/time.hpp"
@ -35,6 +36,7 @@
#include <atomic>
#include <cassert>
#include <cstring>
#include <list>
#include <functional>
#include <map>
@ -54,7 +56,7 @@ class NetworkString;
class NetworkTimerSynchronizer;
class Server;
class ServerLobby;
class SeparateProcess;
class ChildLoop;
class SocketAddress;
class STKPeer;
@ -71,10 +73,12 @@ class STKHost
{
private:
/** Singleton pointer to the instance. */
static STKHost* m_stk_host;
static STKHost* m_stk_host[PT_COUNT];
/** Separate process of server instance. */
SeparateProcess* m_separate_process;
ChildLoop* m_client_loop;
std::thread m_client_loop_thread;
/** ENet host interfacing sockets. */
Network* m_network;
@ -164,7 +168,7 @@ private:
std::shared_ptr<ServerLobby> sl,
std::map<std::string, uint64_t>& ctp);
// ------------------------------------------------------------------------
void mainLoop();
void mainLoop(ProcessType pt);
// ------------------------------------------------------------------------
void getIPFromStun(int socket, const std::string& stun_address,
short family, SocketAddress* result);
@ -175,24 +179,29 @@ public:
/** Creates the STKHost. It takes all confifguration parameters from
* NetworkConfig. This STKHost can either be a client or a server.
*/
static std::shared_ptr<LobbyProtocol> create(SeparateProcess* p = NULL);
static std::shared_ptr<LobbyProtocol> create(ChildLoop* cl = NULL);
// ------------------------------------------------------------------------
/** Returns the instance of STKHost. */
static STKHost *get()
{
assert(m_stk_host != NULL);
return m_stk_host;
ProcessType pt = STKProcess::getType();
assert(m_stk_host[pt] != NULL);
return m_stk_host[pt];
} // get
// ------------------------------------------------------------------------
static void destroy()
{
assert(m_stk_host != NULL);
delete m_stk_host;
m_stk_host = NULL;
ProcessType pt = STKProcess::getType();
assert(m_stk_host[pt] != NULL);
delete m_stk_host[pt];
m_stk_host[pt] = NULL;
} // destroy
// ------------------------------------------------------------------------
/** Checks if the STKHost has been created. */
static bool existHost() { return m_stk_host != NULL; }
static bool existHost()
{ return m_stk_host[STKProcess::getType()] != NULL; }
// ------------------------------------------------------------------------
static void clear() { memset(m_stk_host, 0, sizeof(m_stk_host)); }
// ------------------------------------------------------------------------
const SocketAddress& getPublicAddress() const
{ return *m_public_address.get(); }
@ -332,14 +341,6 @@ public:
// ------------------------------------------------------------------------
bool isClientServer() const;
// ------------------------------------------------------------------------
bool hasServerAI() const;
// ------------------------------------------------------------------------
void setSeparateProcess(SeparateProcess* p)
{
assert(m_separate_process == NULL);
m_separate_process = p;
}
// ------------------------------------------------------------------------
void initClientNetwork(ENetEvent& event, Network* new_network);
// ------------------------------------------------------------------------
std::map<uint32_t, uint32_t> getPeerPings()
@ -387,6 +388,8 @@ public:
}
// ------------------------------------------------------------------------
static BareNetworkString getStunRequest(uint8_t* stun_tansaction_id);
// ------------------------------------------------------------------------
ChildLoop* getChildLoop() const { return m_client_loop; }
}; // class STKHost
#endif // STK_HOST_HPP

View File

@ -346,19 +346,20 @@ extern "C" void setIPv6Socket(int val)
} // setIPV6
#else
#include <atomic>
// ============================================================================
int g_ipv6;
// For client and server in same process using different thread
std::atomic<int> g_ipv6(0);
// ============================================================================
extern "C" int isIPv6Socket()
{
return g_ipv6;
return g_ipv6.load();
} // isIPV6
// ----------------------------------------------------------------------------
extern "C" void setIPv6Socket(int val)
{
g_ipv6 = val;
g_ipv6.store(val);
} // setIPV6
#endif

View File

@ -24,12 +24,13 @@
#include "network/network_config.hpp"
#include "network/server.hpp"
#include "network/server_config.hpp"
#include "network/child_loop.hpp"
#include "network/socket_address.hpp"
#include "network/stk_host.hpp"
#include "online/online_profile.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/online/networking_lobby.hpp"
#include "utils/separate_process.hpp"
#include "utils/stk_process.hpp"
#include "utils/string_utils.hpp"
#include "utils/translation.hpp"
@ -294,10 +295,7 @@ void CreateServerScreen::createServer()
const bool private_server = !password.empty();
ServerConfig::m_private_server_password = password;
password = std::string(" --server-password=") + password;
SocketAddress server_address(0x7f000001,
stk_config->m_server_discovery_port);
SocketAddress server_address(0x7f000001, 0);
auto server = std::make_shared<Server>(0/*server_id*/, name,
max_players, /*current_player*/0, (RaceManager::Difficulty)
@ -333,43 +331,32 @@ void CreateServerScreen::createServer()
#else
NetworkConfig::get()->setIsServer(false);
std::ostringstream server_cfg;
const std::string server_name = StringUtils::xmlEncode(name);
if (NetworkConfig::get()->isWAN())
ServerConfig::m_server_name = StringUtils::xmlEncode(name);
// Server always configurable if created with this screen
ServerConfig::m_server_configurable = true;
struct ChildLoopConfig clc;
clc.m_lan_server = NetworkConfig::get()->isLAN();
clc.m_login_id = NetworkConfig::get()->getCurrentUserId();
clc.m_token = NetworkConfig::get()->getCurrentUserToken();
clc.m_server_ai = 0;
switch (gamemode_widget->getSelection(PLAYER_ID_GAME_MASTER))
{
server_cfg << "--public-server --wan-server=" <<
server_name << " --login-id=" <<
NetworkConfig::get()->getCurrentUserId() << " --token=" <<
NetworkConfig::get()->getCurrentUserToken();
}
else
{
server_cfg << "--lan-server=" << server_name;
case 0:
ServerConfig::m_server_mode = 3;
break;
case 1:
ServerConfig::m_server_mode = 4;
break;
case 3:
ServerConfig::m_server_mode = 6;
break;
}
// Clear previous stk-server-id-file_*
std::set<std::string> files;
const std::string server_id_file = "stk-server-id-file_";
file_manager->listFiles(files, file_manager->getUserConfigDir());
for (auto& f : files)
{
if (f.find(server_id_file) != std::string::npos)
{
file_manager->removeFile(file_manager->getUserConfigDir() + "/" +
f);
}
}
NetworkConfig::get()->setServerIdFile(
file_manager->getUserConfigFile(server_id_file));
server_cfg << " --stdout=server.log --mode=" <<
gamemode_widget->getSelection(PLAYER_ID_GAME_MASTER) <<
" --difficulty=" <<
difficulty_widget->getSelection(PLAYER_ID_GAME_MASTER) <<
" --max-players=" << max_players <<
" --server-id-file=" << server_id_file <<
" --log=1 --no-console-log";
ServerConfig::m_server_difficulty =
difficulty_widget->getSelection(PLAYER_ID_GAME_MASTER);
ServerConfig::m_server_max_players = max_players;
if (m_more_options_spinner->isVisible())
{
@ -378,14 +365,17 @@ void CreateServerScreen::createServer()
3/*is soccer*/)
{
if (esi == 0)
server_cfg << " --soccer-timed";
ServerConfig::m_soccer_goal_target = false;
else
server_cfg << " --soccer-goals";
ServerConfig::m_soccer_goal_target = true;
}
else if (gamemode_widget->getSelection(PLAYER_ID_GAME_MASTER) ==
2/*is battle*/)
{
server_cfg << " --battle-mode=" << esi;
if (esi == 0)
ServerConfig::m_server_mode = 7;
else
ServerConfig::m_server_mode = 8;
}
else
{
@ -393,7 +383,7 @@ void CreateServerScreen::createServer()
{
if (esi > 0)
{
server_cfg << " --server-ai=" << esi;
clc.m_server_ai = esi;
NetworkAIController::setAIFrequency(10);
}
}
@ -401,7 +391,13 @@ void CreateServerScreen::createServer()
{
// Grand prix track count
if (esi > 0)
server_cfg << " --network-gp=" << esi;
{
ServerConfig::m_gp_track_count = esi;
if (ServerConfig::m_server_mode == 3)
ServerConfig::m_server_mode = 0;
else
ServerConfig::m_server_mode = 1;
}
}
}
m_prev_mode = gamemode_widget->getSelection(PLAYER_ID_GAME_MASTER);
@ -412,10 +408,8 @@ void CreateServerScreen::createServer()
m_prev_mode = m_prev_value = 0;
}
SeparateProcess* sp =
new SeparateProcess(SeparateProcess::getCurrentExecutableLocation(),
server_cfg.str() + password);
STKHost::create(sp);
ChildLoop* cl = new ChildLoop(clc);
STKHost::create(cl);
NetworkingLobby::getInstance()->setJoinedServer(server);
#endif
} // createServer

View File

@ -32,24 +32,33 @@
#include "modes/world.hpp"
#include "modes/profile_world.hpp"
#include "utils/log.hpp"
#include "utils/stk_process.hpp"
#include <cstring>
using namespace GUIEngine;
static StateManager* state_manager_singleton = NULL;
static StateManager* state_manager_singleton[PT_COUNT];
StateManager* StateManager::get()
{
if (state_manager_singleton == NULL)
state_manager_singleton = new StateManager();
return state_manager_singleton;
ProcessType type = STKProcess::getType();
if (state_manager_singleton[type] == NULL)
state_manager_singleton[type] = new StateManager();
return state_manager_singleton[type];
} // get
void StateManager::deallocate()
{
delete state_manager_singleton;
state_manager_singleton = NULL;
ProcessType type = STKProcess::getType();
delete state_manager_singleton[type];
state_manager_singleton[type] = NULL;
} // deallocate
void StateManager::clear()
{
memset(state_manager_singleton, 0, sizeof(state_manager_singleton));
} // clear
// ============================================================================

View File

@ -210,6 +210,7 @@ public:
// singleton
static StateManager* get();
static void deallocate();
static void clear();
void clearMenuStack() { m_menu_stack.clear(); }
private:
/**