mirror of https://github.com/OpenRCT2/OpenRCT2.git
Get and broadcast to all broadcast address
This commit is contained in:
parent
51117432f0
commit
59ddd7e1ea
|
@ -233,16 +233,16 @@ bool ServerList::WriteFavourites(const std::vector<ServerListEntry>& entries)
|
|||
}
|
||||
}
|
||||
|
||||
std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync()
|
||||
std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync(const INetworkEndpoint& broadcastEndpoint)
|
||||
{
|
||||
return std::async([] {
|
||||
auto broadcastAddress = broadcastEndpoint.GetHostname();
|
||||
return std::async([broadcastAddress] {
|
||||
constexpr auto RECV_DELAY_MS = 10;
|
||||
constexpr auto RECV_WAIT_MS = 2000;
|
||||
|
||||
auto broadcastAddress = "192.168.1.255";
|
||||
|
||||
std::string msg = "Are you an OpenRCT2 server?";
|
||||
auto udpSocket = CreateUdpSocket();
|
||||
|
||||
log_verbose("Broadcasting %zu bytes to the LAN (%s)", msg.size(), broadcastAddress);
|
||||
auto len = udpSocket->SendData(broadcastAddress, NETWORK_LAN_BROADCAST_PORT, msg.data(), msg.size());
|
||||
if (len != msg.size())
|
||||
|
@ -280,11 +280,42 @@ std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync(
|
|||
}
|
||||
platform_sleep(RECV_DELAY_MS);
|
||||
}
|
||||
|
||||
return entries;
|
||||
});
|
||||
}
|
||||
|
||||
std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync()
|
||||
{
|
||||
return std::async([&] {
|
||||
// Get all possible LAN broadcast addresses
|
||||
auto broadcastEndpoints = GetBroadcastAddresses();
|
||||
|
||||
// Spin off a fetch for each broadcast address
|
||||
std::vector<std::future<std::vector<ServerListEntry>>> futures;
|
||||
for (const auto& broadcastEndpoint : broadcastEndpoints)
|
||||
{
|
||||
auto f = FetchLocalServerListAsync(*broadcastEndpoint);
|
||||
futures.push_back(std::move(f));
|
||||
}
|
||||
|
||||
// Wait and merge all results
|
||||
std::vector<ServerListEntry> mergedEntries;
|
||||
for (auto& f : futures)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto entries = std::move(f.get());
|
||||
mergedEntries.insert(mergedEntries.begin(), entries.begin(), entries.end());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Ignore any exceptions from a particular broadcast fetch
|
||||
}
|
||||
}
|
||||
return mergedEntries;
|
||||
});
|
||||
}
|
||||
|
||||
std::future<std::vector<ServerListEntry>> ServerList::FetchOnlineServerListAsync()
|
||||
{
|
||||
#ifdef DISABLE_HTTP
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <vector>
|
||||
|
||||
struct json_t;
|
||||
struct INetworkEndpoint;
|
||||
|
||||
struct ServerListEntry
|
||||
{
|
||||
|
@ -45,6 +46,7 @@ private:
|
|||
void Sort();
|
||||
std::vector<ServerListEntry> ReadFavourites();
|
||||
bool WriteFavourites(const std::vector<ServerListEntry>& entries);
|
||||
std::future<std::vector<ServerListEntry>> FetchLocalServerListAsync(const INetworkEndpoint& broadcastEndpoint);
|
||||
|
||||
public:
|
||||
ServerListEntry& GetServer(size_t index);
|
||||
|
|
|
@ -36,13 +36,15 @@
|
|||
#endif
|
||||
#define FLAG_NO_PIPE 0
|
||||
#else
|
||||
#include <cerrno>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <cerrno>
|
||||
#include <fcntl.h>
|
||||
#include <net/if.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include "../common.h"
|
||||
using SOCKET = int32_t;
|
||||
#define SOCKET_ERROR -1
|
||||
|
@ -116,7 +118,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
std::string GetHostname() override
|
||||
std::string GetHostname() const override
|
||||
{
|
||||
char hostname[256];
|
||||
int res = getnameinfo(&_address, _addressLen, hostname, sizeof(hostname), nullptr, 0, NI_NUMERICHOST);
|
||||
|
@ -395,4 +397,99 @@ std::unique_ptr<IUdpSocket> CreateUdpSocket()
|
|||
return std::make_unique<UdpSocket>();
|
||||
}
|
||||
|
||||
# ifdef _WIN32
|
||||
std::vector<INTERFACE_INFO> GetNetworkInterfaces()
|
||||
{
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock == -1)
|
||||
{
|
||||
printf("socket returned -1\n");
|
||||
return {};
|
||||
}
|
||||
|
||||
DWORD len = 0;
|
||||
size_t capacity = 2;
|
||||
std::vector<INTERFACE_INFO> interfaces;
|
||||
for (;;)
|
||||
{
|
||||
interfaces.resize(capacity);
|
||||
if (WSAIoctl(
|
||||
sock, SIO_GET_INTERFACE_LIST, nullptr, 0, interfaces.data(), capacity * sizeof(INTERFACE_INFO), &len, nullptr,
|
||||
nullptr)
|
||||
== 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (WSAGetLastError() != WSAEFAULT)
|
||||
{
|
||||
closesocket(sock);
|
||||
return {};
|
||||
}
|
||||
capacity *= 2;
|
||||
}
|
||||
interfaces.resize(len / sizeof(INTERFACE_INFO));
|
||||
interfaces.shrink_to_fit();
|
||||
return interfaces;
|
||||
}
|
||||
# endif
|
||||
|
||||
std::vector<std::unique_ptr<INetworkEndpoint>> GetBroadcastAddresses()
|
||||
{
|
||||
std::vector<std::unique_ptr<INetworkEndpoint>> baddresses;
|
||||
# ifdef _WIN32
|
||||
auto interfaces = GetNetworkInterfaces();
|
||||
for (const auto& ifo : interfaces)
|
||||
{
|
||||
if (ifo.iiFlags & IFF_LOOPBACK)
|
||||
continue;
|
||||
if (!(ifo.iiFlags & IFF_BROADCAST))
|
||||
continue;
|
||||
|
||||
// iiBroadcast is unusable, because it always seems to be set to 255.255.255.255.
|
||||
sockaddr_storage address{};
|
||||
memcpy(&address, &ifo.iiAddress.Address, sizeof(sockaddr));
|
||||
((sockaddr_in*)&address)->sin_addr.s_addr = ifo.iiAddress.AddressIn.sin_addr.s_addr
|
||||
| ~ifo.iiNetmask.AddressIn.sin_addr.s_addr;
|
||||
baddresses.push_back(std::make_unique<NetworkEndpoint>(address, sizeof(sockaddr)));
|
||||
}
|
||||
# else
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock == -1)
|
||||
{
|
||||
return baddresses;
|
||||
}
|
||||
|
||||
char buf[4 * 1024]{};
|
||||
ifconf ifconfx{};
|
||||
ifconfx.ifc_len = sizeof(buf);
|
||||
ifconfx.ifc_buf = buf;
|
||||
if (ioctl(sock, SIOCGIFCONF, &ifconfx) == -1)
|
||||
{
|
||||
close(sock);
|
||||
return baddresses;
|
||||
}
|
||||
|
||||
const char* buf_end = buf + ifconfx.ifc_len;
|
||||
for (const char* p = buf; p < buf_end;)
|
||||
{
|
||||
auto req = (const ifreq*)p;
|
||||
if (req->ifr_addr.sa_family == AF_INET)
|
||||
{
|
||||
ifreq r;
|
||||
strcpy(r.ifr_name, req->ifr_name);
|
||||
if (ioctl(sock, SIOCGIFFLAGS, &r) != -1 && (r.ifr_flags & IFF_BROADCAST) && ioctl(sock, SIOCGIFBRDADDR, &r) != -1)
|
||||
{
|
||||
baddresses.push_back(std::make_unique<NetworkEndpoint>(&r.ifr_broadaddr, sizeof(sockaddr)));
|
||||
}
|
||||
}
|
||||
p += sizeof(ifreq);
|
||||
# if defined(AF_LINK) && !defined(SUNOS)
|
||||
p += req->ifr_addr.sa_len - sizeof(struct sockaddr);
|
||||
# endif
|
||||
}
|
||||
close(sock);
|
||||
# endif
|
||||
return baddresses;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
enum SOCKET_STATUS
|
||||
{
|
||||
|
@ -40,7 +41,7 @@ interface INetworkEndpoint
|
|||
{
|
||||
}
|
||||
|
||||
virtual std::string GetHostname() abstract;
|
||||
virtual std::string GetHostname() const abstract;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -69,3 +70,4 @@ public:
|
|||
};
|
||||
|
||||
std::unique_ptr<IUdpSocket> CreateUdpSocket();
|
||||
std::vector<std::unique_ptr<INetworkEndpoint>> GetBroadcastAddresses();
|
||||
|
|
Loading…
Reference in New Issue