2013-07-12 19:12:31 -04:00
|
|
|
//
|
|
|
|
// SuperTuxKart - a fun racing game with go-kart
|
2015-03-29 20:31:42 -04:00
|
|
|
// Copyright (C) 2013-2015 Glenn De Jonghe
|
2013-07-12 19:12:31 -04:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
|
2015-11-12 01:52:04 -05:00
|
|
|
#include "network/servers_manager.hpp"
|
|
|
|
|
2018-04-15 23:57:45 -04:00
|
|
|
#include "config/stk_config.hpp"
|
2013-07-12 19:12:31 -04:00
|
|
|
#include "config/user_config.hpp"
|
2019-06-15 01:52:28 -04:00
|
|
|
#include "io/xml_node.hpp"
|
2015-11-11 17:53:12 -05:00
|
|
|
#include "network/network.hpp"
|
|
|
|
#include "network/network_config.hpp"
|
|
|
|
#include "network/network_string.hpp"
|
2018-03-04 12:54:44 -05:00
|
|
|
#include "network/server.hpp"
|
2020-01-27 00:48:57 -05:00
|
|
|
#include "network/socket_address.hpp"
|
2016-11-07 17:52:39 -05:00
|
|
|
#include "network/stk_host.hpp"
|
2020-01-27 00:48:57 -05:00
|
|
|
#include "network/stk_ipv6.hpp"
|
2015-11-12 01:52:04 -05:00
|
|
|
#include "online/xml_request.hpp"
|
2018-03-04 12:54:44 -05:00
|
|
|
#include "online/request_manager.hpp"
|
2013-07-12 19:12:31 -04:00
|
|
|
#include "utils/translation.hpp"
|
2013-07-21 13:41:02 -04:00
|
|
|
#include "utils/time.hpp"
|
|
|
|
|
2015-10-09 01:47:18 -04:00
|
|
|
#include <assert.h>
|
2020-01-18 21:20:25 -05:00
|
|
|
#include <functional>
|
2020-01-27 00:48:57 -05:00
|
|
|
#include <set>
|
2015-10-09 01:47:18 -04:00
|
|
|
#include <string>
|
2020-01-18 21:20:25 -05:00
|
|
|
#include <thread>
|
2015-10-09 01:47:18 -04:00
|
|
|
|
2018-04-25 14:26:23 -04:00
|
|
|
#if defined(WIN32)
|
|
|
|
# undef _WIN32_WINNT
|
|
|
|
# define _WIN32_WINNT 0x600
|
|
|
|
# include <iphlpapi.h>
|
|
|
|
#else
|
2021-03-03 20:23:23 -05:00
|
|
|
#ifndef __SWITCH__
|
2018-04-25 14:26:23 -04:00
|
|
|
# include <ifaddrs.h>
|
2021-03-03 22:23:03 -05:00
|
|
|
#else
|
|
|
|
extern "C" {
|
|
|
|
#define u64 uint64_t
|
|
|
|
#define u32 uint32_t
|
|
|
|
#define s64 int64_t
|
|
|
|
#define s32 int32_t
|
|
|
|
#define Event libnx_Event
|
|
|
|
#include <switch/services/nifm.h>
|
|
|
|
#undef Event
|
|
|
|
#undef u64
|
|
|
|
#undef u32
|
|
|
|
#undef s32
|
|
|
|
#undef s64
|
|
|
|
}
|
2021-03-03 20:23:23 -05:00
|
|
|
#endif
|
2020-01-27 00:48:57 -05:00
|
|
|
# include <net/if.h>
|
2018-04-25 14:26:23 -04:00
|
|
|
#endif
|
|
|
|
|
2018-03-04 12:54:44 -05:00
|
|
|
static ServersManager* g_manager_singleton(NULL);
|
2013-07-12 19:12:31 -04:00
|
|
|
|
2018-03-04 12:54:44 -05:00
|
|
|
// ============================================================================
|
2015-11-06 00:50:58 -05:00
|
|
|
ServersManager* ServersManager::get()
|
|
|
|
{
|
2018-03-04 12:54:44 -05:00
|
|
|
if (g_manager_singleton == NULL)
|
|
|
|
g_manager_singleton = new ServersManager();
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2018-03-04 12:54:44 -05:00
|
|
|
return g_manager_singleton;
|
2015-11-06 00:50:58 -05:00
|
|
|
} // get
|
2013-07-12 19:12:31 -04:00
|
|
|
|
2018-03-04 12:54:44 -05:00
|
|
|
// ============================================================================
|
2015-11-06 00:50:58 -05:00
|
|
|
void ServersManager::deallocate()
|
|
|
|
{
|
2018-03-04 12:54:44 -05:00
|
|
|
delete g_manager_singleton;
|
|
|
|
g_manager_singleton = NULL;
|
2015-11-06 00:50:58 -05:00
|
|
|
} // deallocate
|
2013-07-12 19:12:31 -04:00
|
|
|
|
2018-03-04 12:54:44 -05:00
|
|
|
// ----------------------------------------------------------------------------
|
2015-11-06 00:50:58 -05:00
|
|
|
ServersManager::ServersManager()
|
|
|
|
{
|
|
|
|
} // ServersManager
|
2013-07-22 16:00:08 -04:00
|
|
|
|
2018-03-04 12:54:44 -05:00
|
|
|
// ----------------------------------------------------------------------------
|
2015-11-06 00:50:58 -05:00
|
|
|
ServersManager::~ServersManager()
|
|
|
|
{
|
|
|
|
} // ~ServersManager
|
2013-07-12 19:12:31 -04:00
|
|
|
|
2015-11-09 16:31:07 -05:00
|
|
|
// ----------------------------------------------------------------------------
|
2015-11-09 04:51:00 -05:00
|
|
|
/** Returns a WAN update-list-of-servers request. It queries the
|
|
|
|
* STK server for an up-to-date list of servers.
|
|
|
|
*/
|
2020-05-09 01:24:07 -04:00
|
|
|
std::shared_ptr<ServerList> ServersManager::getWANRefreshRequest() const
|
2015-11-06 00:50:58 -05:00
|
|
|
{
|
2015-11-09 04:51:00 -05:00
|
|
|
// ========================================================================
|
|
|
|
/** A small local class that triggers an update of the ServersManager
|
|
|
|
* when the request is finished. */
|
2015-11-12 01:52:04 -05:00
|
|
|
class WANRefreshRequest : public Online::XMLRequest
|
2013-07-21 13:41:02 -04:00
|
|
|
{
|
2020-01-18 21:20:25 -05:00
|
|
|
private:
|
2020-05-09 01:24:07 -04:00
|
|
|
std::weak_ptr<ServerList> m_server_list;
|
2020-01-18 21:20:25 -05:00
|
|
|
// Run the ip detect in separate thread, so it can be done parallel
|
|
|
|
// with the wan server request (which takes few seconds too)
|
2020-09-03 01:24:49 -04:00
|
|
|
uint64_t m_creation_time;
|
2015-11-09 04:51:00 -05:00
|
|
|
public:
|
2020-05-09 01:24:07 -04:00
|
|
|
WANRefreshRequest(std::shared_ptr<ServerList> server_list)
|
|
|
|
: Online::XMLRequest(/*priority*/100)
|
2020-01-18 21:20:25 -05:00
|
|
|
{
|
2020-09-03 01:24:49 -04:00
|
|
|
NetworkConfig::queueIPDetection();
|
|
|
|
m_creation_time = StkTime::getMonoTimeMs();
|
2020-05-09 01:24:07 -04:00
|
|
|
m_server_list = server_list;
|
2020-01-18 21:20:25 -05:00
|
|
|
}
|
2015-11-09 04:51:00 -05:00
|
|
|
// --------------------------------------------------------------------
|
2018-03-04 12:54:44 -05:00
|
|
|
virtual void afterOperation() OVERRIDE
|
2013-07-12 19:12:31 -04:00
|
|
|
{
|
2018-03-04 12:54:44 -05:00
|
|
|
Online::XMLRequest::afterOperation();
|
2020-09-03 01:24:49 -04:00
|
|
|
// Wait at most 2 seconds for ip detection
|
|
|
|
uint64_t timeout = StkTime::getMonoTimeMs() - m_creation_time;
|
|
|
|
if (timeout > 2000)
|
|
|
|
timeout = 0;
|
2020-09-03 01:35:46 -04:00
|
|
|
else
|
|
|
|
timeout = 2000 - timeout;
|
2020-09-03 01:24:49 -04:00
|
|
|
NetworkConfig::get()->getIPDetectionResult(timeout);
|
2020-05-09 01:24:07 -04:00
|
|
|
auto server_list = m_server_list.lock();
|
|
|
|
if (!server_list)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!isSuccess())
|
|
|
|
{
|
|
|
|
Log::error("ServersManager", "Could not refresh server list");
|
|
|
|
server_list->m_list_updated = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const XMLNode *servers_xml = getXMLData()->getNode("servers");
|
|
|
|
for (unsigned int i = 0; i < servers_xml->getNumNodes(); i++)
|
|
|
|
{
|
|
|
|
const XMLNode* s = servers_xml->getNode(i);
|
|
|
|
assert(s);
|
|
|
|
const XMLNode* si = s->getNode("server-info");
|
|
|
|
assert(si);
|
|
|
|
int version = 0;
|
|
|
|
si->get("version", &version);
|
|
|
|
assert(version != 0);
|
|
|
|
if (version < stk_config->m_max_server_version ||
|
|
|
|
version > stk_config->m_max_server_version)
|
|
|
|
{
|
|
|
|
Log::verbose("ServersManager", "Skipping a server");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
std::shared_ptr<Server> ser = std::make_shared<Server>(*s);
|
|
|
|
if (ser->getAddress().isUnset() &&
|
|
|
|
NetworkConfig::get()->getIPType() == NetworkConfig::IP_V4)
|
|
|
|
{
|
|
|
|
Log::verbose("ServersManager",
|
|
|
|
"Skipping an IPv6 only server");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
server_list->m_servers.emplace_back(ser);
|
|
|
|
}
|
|
|
|
server_list->m_list_updated = true;
|
2020-01-18 21:20:25 -05:00
|
|
|
} // afterOperation
|
2015-11-09 04:51:00 -05:00
|
|
|
// --------------------------------------------------------------------
|
2015-11-06 00:50:58 -05:00
|
|
|
}; // RefreshRequest
|
2015-11-09 04:51:00 -05:00
|
|
|
// ========================================================================
|
2015-11-06 00:50:58 -05:00
|
|
|
|
2020-05-09 01:24:07 -04:00
|
|
|
auto server_list = std::make_shared<ServerList>();
|
|
|
|
auto request = std::make_shared<WANRefreshRequest>(server_list);
|
2015-11-12 01:52:04 -05:00
|
|
|
request->setApiURL(Online::API::SERVER_PATH, "get-all");
|
2020-05-09 01:24:07 -04:00
|
|
|
Online::RequestManager::get()->addRequest(request);
|
|
|
|
return server_list;
|
2015-11-09 04:51:00 -05:00
|
|
|
} // getWANRefreshRequest
|
|
|
|
|
2015-11-09 16:31:07 -05:00
|
|
|
// ----------------------------------------------------------------------------
|
2015-11-09 04:51:00 -05:00
|
|
|
/** Returns a LAN update-list-of-servers request. It uses UDP broadcasts
|
|
|
|
* to find LAN servers, and waits for a certain amount of time fr
|
|
|
|
* answers.
|
|
|
|
*/
|
2020-05-09 01:24:07 -04:00
|
|
|
std::shared_ptr<ServerList> ServersManager::getLANRefreshRequest() const
|
2015-11-09 04:51:00 -05:00
|
|
|
{
|
|
|
|
/** A simple class that uses LAN broadcasts to find local servers.
|
|
|
|
* It is based on XML request, but actually does not use any of the
|
|
|
|
* XML/HTTP based infrastructure, but implements the same interface.
|
|
|
|
* This way the already existing request thread can be used.
|
|
|
|
*/
|
2015-11-12 01:52:04 -05:00
|
|
|
class LANRefreshRequest : public Online::XMLRequest
|
2015-11-09 04:51:00 -05:00
|
|
|
{
|
2020-05-09 01:24:07 -04:00
|
|
|
private:
|
|
|
|
std::weak_ptr<ServerList> m_server_list;
|
2015-11-09 04:51:00 -05:00
|
|
|
public:
|
|
|
|
|
|
|
|
/** High priority for this request. */
|
2020-05-09 01:24:07 -04:00
|
|
|
LANRefreshRequest(std::shared_ptr<ServerList> server_list)
|
|
|
|
: XMLRequest(/*priority*/100)
|
|
|
|
{
|
|
|
|
m_success = false;
|
|
|
|
m_server_list = server_list;
|
|
|
|
}
|
2015-11-09 04:51:00 -05:00
|
|
|
// --------------------------------------------------------------------
|
|
|
|
virtual ~LANRefreshRequest() {}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
/** Get the downloaded XML tree.
|
|
|
|
* \pre request has to be executed.
|
|
|
|
* \return get the complete result from the request reply. */
|
|
|
|
virtual const XMLNode * getXMLData() const
|
|
|
|
{
|
|
|
|
assert(hasBeenExecuted());
|
|
|
|
return NULL;
|
|
|
|
} // getXMLData
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
virtual void prepareOperation() OVERRIDE
|
|
|
|
{
|
|
|
|
} // prepareOperation
|
|
|
|
// --------------------------------------------------------------------
|
2016-02-20 19:21:43 -05:00
|
|
|
virtual void operation() OVERRIDE
|
2015-11-09 04:51:00 -05:00
|
|
|
{
|
2020-05-09 01:24:07 -04:00
|
|
|
auto server_list = m_server_list.lock();
|
|
|
|
if (!server_list)
|
|
|
|
return;
|
|
|
|
|
2020-02-27 11:59:37 -05:00
|
|
|
ENetAddress addr = {};
|
2020-01-27 00:48:57 -05:00
|
|
|
setIPv6Socket(UserConfigParams::m_ipv6_lan ? 1 : 0);
|
2020-02-04 22:37:05 -05:00
|
|
|
NetworkConfig::get()->setIPType(UserConfigParams::m_ipv6_lan ?
|
|
|
|
NetworkConfig::IP_DUAL_STACK : NetworkConfig::IP_V4);
|
2016-11-07 17:52:39 -05:00
|
|
|
Network *broadcast = new Network(1, 1, 0, 0, &addr);
|
2020-04-13 23:35:43 -04:00
|
|
|
if (!broadcast->getENetHost())
|
|
|
|
{
|
|
|
|
setIPv6Socket(0);
|
|
|
|
m_success = true;
|
|
|
|
delete broadcast;
|
2020-05-09 01:24:07 -04:00
|
|
|
server_list->m_list_updated = true;
|
2020-04-13 23:35:43 -04:00
|
|
|
return;
|
|
|
|
}
|
2020-01-27 00:48:57 -05:00
|
|
|
const std::vector<SocketAddress> &all_bcast =
|
2020-01-29 22:25:03 -05:00
|
|
|
ServersManager::get()->getBroadcastAddresses(
|
|
|
|
UserConfigParams::m_ipv6_lan);
|
2018-04-23 09:30:48 -04:00
|
|
|
for (auto &bcast_addr : all_bcast)
|
|
|
|
{
|
|
|
|
Log::info("Server Discovery", "Broadcasting to %s",
|
|
|
|
bcast_addr.toString().c_str());
|
|
|
|
broadcast->sendRawPacket(std::string("stk-server"), bcast_addr);
|
|
|
|
}
|
2015-11-09 04:51:00 -05:00
|
|
|
|
|
|
|
Log::info("ServersManager", "Sent broadcast message.");
|
|
|
|
|
|
|
|
const int LEN=2048;
|
|
|
|
char buffer[LEN];
|
|
|
|
// Wait for up to 0.5 seconds to receive an answer from
|
|
|
|
// any local servers.
|
2019-05-06 03:17:19 -04:00
|
|
|
uint64_t start_time = StkTime::getMonoTimeMs();
|
2018-08-27 01:49:11 -04:00
|
|
|
const uint64_t DURATION = 1000;
|
2020-05-09 01:24:07 -04:00
|
|
|
int cur_server_id = 0;
|
2018-04-23 09:30:48 -04:00
|
|
|
// Use a map with the server name as key to automatically remove
|
|
|
|
// duplicated answers from a server (since we potentially do
|
|
|
|
// multiple broadcasts). We can not use the sender ip address,
|
|
|
|
// because e.g. a local client would answer as 127.0.0.1 and
|
|
|
|
// 192.168.**.
|
|
|
|
std::map<irr::core::stringw, std::shared_ptr<Server> > servers_now;
|
2019-05-06 03:17:19 -04:00
|
|
|
while (StkTime::getMonoTimeMs() - start_time < DURATION)
|
2015-11-09 04:51:00 -05:00
|
|
|
{
|
2020-01-27 00:48:57 -05:00
|
|
|
SocketAddress sender;
|
2015-11-09 04:51:00 -05:00
|
|
|
int len = broadcast->receiveRawPacket(buffer, LEN, &sender, 1);
|
2018-03-06 11:51:59 -05:00
|
|
|
if (len > 0)
|
2015-11-09 04:51:00 -05:00
|
|
|
{
|
2016-02-24 17:48:47 -05:00
|
|
|
BareNetworkString s(buffer, len);
|
2018-08-03 02:01:36 -04:00
|
|
|
int version = s.getUInt32();
|
2018-04-15 23:57:45 -04:00
|
|
|
if (version < stk_config->m_max_server_version ||
|
|
|
|
version > stk_config->m_max_server_version)
|
2018-03-13 02:39:20 -04:00
|
|
|
{
|
|
|
|
Log::verbose("ServersManager", "Skipping a server");
|
|
|
|
continue;
|
|
|
|
}
|
2015-11-26 16:55:21 -05:00
|
|
|
irr::core::stringw name;
|
2016-02-24 17:48:47 -05:00
|
|
|
// bytes_read is the number of bytes read
|
2018-03-06 11:51:59 -05:00
|
|
|
s.decodeStringW(&name);
|
2016-03-12 21:49:43 -05:00
|
|
|
uint8_t max_players = s.getUInt8();
|
|
|
|
uint8_t players = s.getUInt8();
|
2018-03-06 11:51:59 -05:00
|
|
|
uint16_t port = s.getUInt16();
|
2016-03-12 21:49:43 -05:00
|
|
|
uint8_t difficulty = s.getUInt8();
|
2018-03-02 02:21:27 -05:00
|
|
|
uint8_t mode = s.getUInt8();
|
2018-03-06 11:51:59 -05:00
|
|
|
sender.setPort(port);
|
2018-03-13 02:39:20 -04:00
|
|
|
uint8_t password = s.getUInt8();
|
2018-08-28 02:43:48 -04:00
|
|
|
uint8_t game_started = s.getUInt8();
|
2019-01-04 04:40:25 -05:00
|
|
|
std::string current_track;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
s.decodeString(¤t_track);
|
|
|
|
}
|
|
|
|
catch (std::exception& e)
|
|
|
|
{
|
|
|
|
(void)e;
|
|
|
|
}
|
2020-01-27 00:48:57 -05:00
|
|
|
auto server = std::make_shared<Server>(cur_server_id++,
|
|
|
|
name, max_players, players, difficulty, mode,
|
2020-01-31 20:30:40 -05:00
|
|
|
SocketAddress(sender.getIP(), sender.getPort()),
|
2020-01-27 00:48:57 -05:00
|
|
|
password == 1, game_started == 1, current_track);
|
|
|
|
if (sender.isIPv6())
|
|
|
|
{
|
|
|
|
server->setIPV6Address(sender);
|
|
|
|
server->setIPV6Connection(true);
|
|
|
|
}
|
|
|
|
servers_now.insert(std::make_pair(name, server));
|
2018-04-23 09:30:48 -04:00
|
|
|
//all_servers.[name] = servers_now.back();
|
2015-11-09 04:51:00 -05:00
|
|
|
} // if received_data
|
|
|
|
} // while still waiting
|
2020-01-27 00:48:57 -05:00
|
|
|
setIPv6Socket(0);
|
2016-06-27 19:47:56 -04:00
|
|
|
delete broadcast;
|
2020-05-09 01:24:07 -04:00
|
|
|
m_success = true;
|
|
|
|
for (auto& i : servers_now)
|
|
|
|
server_list->m_servers.emplace_back(i.second);
|
|
|
|
server_list->m_list_updated = true;
|
2015-11-09 04:51:00 -05:00
|
|
|
} // operation
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
/** This function is necessary, otherwise the XML- and HTTP-Request
|
|
|
|
* functions are called, which will cause a crash. */
|
|
|
|
virtual void afterOperation() OVERRIDE {}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
}; // LANRefreshRequest
|
|
|
|
// ========================================================================
|
|
|
|
|
2020-05-09 01:24:07 -04:00
|
|
|
auto server_list = std::make_shared<ServerList>();
|
|
|
|
auto request = std::make_shared<LANRefreshRequest>(server_list);
|
|
|
|
Online::RequestManager::get()->addRequest(request);
|
|
|
|
return server_list;
|
2015-11-09 04:51:00 -05:00
|
|
|
|
|
|
|
} // getLANRefreshRequest
|
|
|
|
|
2018-04-25 14:26:23 -04:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/** Sets a list of default broadcast addresses which is used in case no valid
|
|
|
|
* broadcast address is found. This list includes default private network
|
|
|
|
* addresses.
|
|
|
|
*/
|
2020-01-29 22:25:03 -05:00
|
|
|
std::vector<SocketAddress> ServersManager::getDefaultBroadcastAddresses()
|
2018-04-25 14:26:23 -04:00
|
|
|
{
|
|
|
|
// Add some common LAN addresses
|
2020-01-29 22:25:03 -05:00
|
|
|
std::vector<SocketAddress> result;
|
|
|
|
uint16_t port = stk_config->m_server_discovery_port;
|
|
|
|
result.emplace_back(std::string("192.168.255.255"), port);
|
|
|
|
result.emplace_back(std::string("192.168.0.255"), port);
|
|
|
|
result.emplace_back(std::string("192.168.1.255"), port);
|
|
|
|
result.emplace_back(std::string("172.31.255.255"), port);
|
|
|
|
result.emplace_back(std::string("172.16.255.255"), port);
|
|
|
|
result.emplace_back(std::string("172.16.0.255"), port);
|
|
|
|
result.emplace_back(std::string("10.255.255.255"), port);
|
|
|
|
result.emplace_back(std::string("10.0.255.255"), port);
|
|
|
|
result.emplace_back(std::string("10.0.0.255"), port);
|
|
|
|
result.emplace_back(std::string("255.255.255.255"), port);
|
|
|
|
result.emplace_back(std::string("127.0.0.255"), port);
|
|
|
|
result.emplace_back(std::string("127.0.0.1"), port);
|
|
|
|
return result;
|
|
|
|
} // getDefaultBroadcastAddresses
|
2018-04-25 14:26:23 -04:00
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/** This masks various possible broadcast addresses. For example, in a /16
|
|
|
|
* network it would first use *.*.255.255, then *.*.*.255. Also if the
|
|
|
|
* length of the mask is not a multiple of 8, the original value will
|
|
|
|
* be used, before multiple of 8 are create: /22 (*.3f.ff.ff), then
|
|
|
|
* /16 (*.*.ff.ff), /8 (*.*.*.ff). While this is usually an overkill,
|
|
|
|
* it can help in the case that the router does not forward a broadcast
|
|
|
|
* as expected (this problem often happens with 255.255.255.255, which is
|
|
|
|
* why this broadcast address creation code was added).
|
|
|
|
* \param a The transport address for which the broadcast addresses need
|
|
|
|
* to be created.
|
|
|
|
* \param len Number of bits to be or'ed.
|
2020-01-29 22:25:03 -05:00
|
|
|
* \param result Location to put address.
|
2018-04-25 14:26:23 -04:00
|
|
|
*/
|
2020-01-29 22:25:03 -05:00
|
|
|
void ServersManager::addAllBroadcastAddresses(const SocketAddress &a, int len,
|
|
|
|
std::vector<SocketAddress>* result)
|
2018-04-25 14:26:23 -04:00
|
|
|
{
|
|
|
|
// Try different broadcast addresses - by masking on
|
|
|
|
// byte boundaries
|
|
|
|
while (len > 0)
|
|
|
|
{
|
|
|
|
unsigned int mask = (1 << len) - 1;
|
2020-01-27 00:48:57 -05:00
|
|
|
SocketAddress bcast(a.getIP() | mask,
|
2018-09-11 02:06:30 -04:00
|
|
|
stk_config->m_server_discovery_port);
|
2018-04-25 14:26:23 -04:00
|
|
|
Log::info("Broadcast", "address %s length %d mask %x --> %s",
|
|
|
|
a.toString().c_str(),
|
|
|
|
len, mask,
|
|
|
|
bcast.toString().c_str());
|
2020-01-29 22:25:03 -05:00
|
|
|
result->push_back(bcast);
|
2018-04-25 14:26:23 -04:00
|
|
|
if (len % 8 != 0)
|
|
|
|
len -= (len % 8);
|
|
|
|
else
|
|
|
|
len = len - 8;
|
|
|
|
} // while len > 0
|
|
|
|
} // addAllBroadcastAddresses
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2020-01-29 22:25:03 -05:00
|
|
|
/** Returns a list of all possible broadcast addresses on this machine.
|
2019-09-03 15:24:03 -04:00
|
|
|
* It queries all adapters for active IPv4 interfaces, determines their
|
2018-04-25 14:26:23 -04:00
|
|
|
* netmask to create the broadcast addresses. It will also add 'smaller'
|
|
|
|
* broadcast addesses, e.g. in a /16 network, it will add *.*.255.255 and
|
|
|
|
* *.*.*.255, since it was sometimes observed that routers would not let
|
|
|
|
* all broadcast addresses through. Duplicated answers (from the same server
|
|
|
|
* to different addersses) will be filtered out in ServersManager.
|
|
|
|
*/
|
2020-01-29 22:25:03 -05:00
|
|
|
std::vector<SocketAddress> ServersManager::getBroadcastAddresses(bool ipv6)
|
2018-04-25 14:26:23 -04:00
|
|
|
{
|
2020-01-27 00:48:57 -05:00
|
|
|
std::vector<SocketAddress> result;
|
2021-03-03 20:23:23 -05:00
|
|
|
#ifdef __SWITCH__
|
2021-03-03 22:23:03 -05:00
|
|
|
uint32_t addr;
|
|
|
|
uint32_t u;
|
|
|
|
|
|
|
|
Result resultCode = nifmGetCurrentIpConfigInfo(&addr, &u, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
if(R_SUCCEEDED(resultCode))
|
|
|
|
{
|
|
|
|
u = htonl(u);
|
|
|
|
// Convert mask to #bits: SWAT algorithm
|
|
|
|
u = u - ((u >> 1) & 0x55555555);
|
|
|
|
u = (u & 0x33333333) + ((u >> 2) & 0x33333333);
|
|
|
|
u = (((u + (u >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
|
|
|
|
SocketAddress saddr(htonl(addr));
|
|
|
|
addAllBroadcastAddresses(saddr, u, &result);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Log::warn("ServersManager", "Failed to get broadcast address! Error 0x%x", resultCode);
|
|
|
|
result = getDefaultBroadcastAddresses();
|
|
|
|
}
|
2021-03-03 20:23:23 -05:00
|
|
|
#elif !defined(WIN32)
|
2018-04-25 14:26:23 -04:00
|
|
|
struct ifaddrs *addresses, *p;
|
|
|
|
|
2019-01-13 13:26:30 -05:00
|
|
|
if (getifaddrs(&addresses) == -1)
|
|
|
|
{
|
2020-01-27 00:48:57 -05:00
|
|
|
Log::warn("SocketAddress", "Error in getifaddrs");
|
2020-01-29 22:25:03 -05:00
|
|
|
return result;
|
2019-01-13 13:26:30 -05:00
|
|
|
}
|
2020-01-27 00:48:57 -05:00
|
|
|
std::set<uint32_t> used_scope_id;
|
2018-04-25 14:26:23 -04:00
|
|
|
for (p = addresses; p; p = p->ifa_next)
|
|
|
|
{
|
2020-01-27 00:48:57 -05:00
|
|
|
SocketAddress socket_address;
|
|
|
|
if (p->ifa_addr == NULL)
|
|
|
|
continue;
|
|
|
|
if (p->ifa_addr->sa_family == AF_INET)
|
2018-04-25 14:26:23 -04:00
|
|
|
{
|
|
|
|
struct sockaddr_in *sa = (struct sockaddr_in *) p->ifa_addr;
|
2020-01-27 00:48:57 -05:00
|
|
|
uint32_t addr = htonl(sa->sin_addr.s_addr);
|
|
|
|
|
|
|
|
// Skip 169.254.*.* local link address
|
|
|
|
if (((addr >> 24) & 0xff) == 169 &&
|
|
|
|
((addr >> 16) & 0xff) == 254)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
SocketAddress saddr(addr, 0);
|
2018-04-25 14:26:23 -04:00
|
|
|
uint32_t u = ((sockaddr_in*)(p->ifa_netmask))->sin_addr.s_addr;
|
|
|
|
// Convert mask to #bits: SWAT algorithm
|
|
|
|
u = u - ((u >> 1) & 0x55555555);
|
|
|
|
u = (u & 0x33333333) + ((u >> 2) & 0x33333333);
|
|
|
|
u = (((u + (u >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
|
|
|
|
|
2018-05-10 23:13:42 -04:00
|
|
|
Log::debug("ServerManager",
|
|
|
|
"Interface: %s\tAddress: %s\tmask: %x\n", p->ifa_name,
|
2020-01-27 00:48:57 -05:00
|
|
|
saddr.toString().c_str(), u);
|
2020-01-29 22:25:03 -05:00
|
|
|
addAllBroadcastAddresses(saddr, u, &result);
|
2020-01-27 00:48:57 -05:00
|
|
|
}
|
2020-01-29 22:25:03 -05:00
|
|
|
else if (p->ifa_addr->sa_family == AF_INET6 && ipv6)
|
2020-01-27 00:48:57 -05:00
|
|
|
{
|
|
|
|
uint32_t idx = if_nametoindex(p->ifa_name);
|
|
|
|
if (used_scope_id.find(idx) != used_scope_id.end())
|
|
|
|
continue;
|
|
|
|
used_scope_id.insert(idx);
|
|
|
|
SocketAddress socket_address("ff02::1",
|
|
|
|
stk_config->m_server_discovery_port);
|
|
|
|
sockaddr_in6* in6 = (sockaddr_in6*)socket_address.getSockaddr();
|
|
|
|
in6->sin6_scope_id = idx;
|
2020-01-29 22:25:03 -05:00
|
|
|
result.push_back(socket_address);
|
2018-04-25 14:26:23 -04:00
|
|
|
}
|
|
|
|
}
|
2018-07-11 01:49:01 -04:00
|
|
|
freeifaddrs(addresses);
|
2020-01-27 00:48:57 -05:00
|
|
|
#else
|
|
|
|
// From docs from microsoft it recommends 15k size
|
|
|
|
const int WORKING_BUFFER_SIZE = 15000;
|
|
|
|
PIP_ADAPTER_ADDRESSES paddr = NULL;
|
|
|
|
unsigned long len = WORKING_BUFFER_SIZE;
|
|
|
|
int return_code = 0;
|
|
|
|
int iteration = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
paddr = (IP_ADAPTER_ADDRESSES*)malloc(len);
|
|
|
|
if (paddr == NULL)
|
2020-01-29 22:25:03 -05:00
|
|
|
return result;
|
2020-01-27 00:48:57 -05:00
|
|
|
long flags = 0;
|
|
|
|
return_code = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, paddr,
|
|
|
|
&len);
|
|
|
|
if (return_code == ERROR_BUFFER_OVERFLOW)
|
|
|
|
{
|
|
|
|
free(paddr);
|
|
|
|
paddr = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
iteration++;
|
|
|
|
} while ((return_code == ERROR_BUFFER_OVERFLOW) && (iteration < 10));
|
|
|
|
|
|
|
|
if (return_code == ERROR_BUFFER_OVERFLOW)
|
|
|
|
{
|
|
|
|
Log::warn("ServerManager", "Can not get broadcast addresses.");
|
2020-01-29 22:25:03 -05:00
|
|
|
result = getDefaultBroadcastAddresses();
|
|
|
|
paddr = NULL;
|
2020-01-27 00:48:57 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
for (IP_ADAPTER_ADDRESSES *p = paddr; p; p = p->Next)
|
|
|
|
{
|
|
|
|
if (p->OperStatus != IfOperStatusUp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
std::set<uint32_t> used_scope_id;
|
|
|
|
for (PIP_ADAPTER_UNICAST_ADDRESS unicast = p->FirstUnicastAddress;
|
|
|
|
unicast != NULL; unicast = unicast->Next)
|
|
|
|
{
|
|
|
|
SocketAddress socket_address;
|
|
|
|
if (unicast->Address.lpSockaddr->sa_family == AF_INET)
|
|
|
|
{
|
|
|
|
const sockaddr_in *sa =
|
|
|
|
(const sockaddr_in*)unicast->Address.lpSockaddr;
|
|
|
|
|
|
|
|
// Skip 169.254.*.* local link address
|
|
|
|
if (sa->sin_addr.S_un.S_un_b.s_b1 == 169 &&
|
|
|
|
sa->sin_addr.S_un.S_un_b.s_b2 == 254)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Use sa->sin_addr.S_un.S_addr and htonl?
|
|
|
|
SocketAddress ta(sa->sin_addr.S_un.S_un_b.s_b1,
|
|
|
|
sa->sin_addr.S_un.S_un_b.s_b2,
|
|
|
|
sa->sin_addr.S_un.S_un_b.s_b3,
|
|
|
|
sa->sin_addr.S_un.S_un_b.s_b4);
|
|
|
|
int len = 32 - unicast->OnLinkPrefixLength;
|
2020-01-29 22:25:03 -05:00
|
|
|
addAllBroadcastAddresses(ta, len, &result);
|
2020-01-27 00:48:57 -05:00
|
|
|
}
|
2020-01-29 22:25:03 -05:00
|
|
|
if (unicast->Address.lpSockaddr->sa_family == AF_INET6 && ipv6)
|
2020-01-27 00:48:57 -05:00
|
|
|
{
|
|
|
|
sockaddr_in6* in6 =
|
|
|
|
(sockaddr_in6*)unicast->Address.lpSockaddr;
|
|
|
|
const uint32_t scope_id = in6->sin6_scope_id;
|
|
|
|
if (used_scope_id.find(scope_id) !=
|
|
|
|
used_scope_id.end())
|
|
|
|
continue;
|
|
|
|
used_scope_id.insert(scope_id);
|
|
|
|
SocketAddress socket_address("ff02::1",
|
|
|
|
stk_config->m_server_discovery_port);
|
|
|
|
in6 = (sockaddr_in6*)socket_address.getSockaddr();
|
|
|
|
in6->sin6_scope_id = scope_id;
|
2020-01-29 22:25:03 -05:00
|
|
|
result.push_back(socket_address);
|
2020-01-27 00:48:57 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(paddr);
|
2018-04-25 14:26:23 -04:00
|
|
|
#endif
|
2020-01-29 22:25:03 -05:00
|
|
|
if (ipv6)
|
2020-01-28 22:04:02 -05:00
|
|
|
{
|
|
|
|
// Convert IPv4 socket address to ::ffff:x.y.z.w
|
2020-01-29 22:25:03 -05:00
|
|
|
for (auto& addr : result)
|
|
|
|
addr.convertForIPv6Socket(ipv6);
|
2018-04-25 14:26:23 -04:00
|
|
|
}
|
2020-01-29 22:25:03 -05:00
|
|
|
return result;
|
2018-04-25 14:26:23 -04:00
|
|
|
} // getBroadcastAddresses
|