| 265 | } |
| 266 | |
| 267 | std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync( |
| 268 | const INetworkEndpoint& broadcastEndpoint) const |
| 269 | { |
| 270 | auto broadcastAddress = broadcastEndpoint.GetHostname(); |
| 271 | return std::async(std::launch::async, [broadcastAddress] { |
| 272 | constexpr auto kReceiveDelayInMs = 10; |
| 273 | constexpr auto kReceiveWaitInMs = 2000; |
| 274 | |
| 275 | std::string_view msg = kLanBroadcastMsg; |
| 276 | auto udpSocket = CreateUdpSocket(); |
| 277 | |
| 278 | LOG_VERBOSE("Broadcasting %zu bytes to the LAN (%s)", msg.size(), broadcastAddress.c_str()); |
| 279 | auto len = udpSocket->SendData(broadcastAddress, kLanBroadcastPort, msg.data(), msg.size()); |
| 280 | if (len != msg.size()) |
| 281 | { |
| 282 | throw std::runtime_error("Unable to broadcast server query."); |
| 283 | } |
| 284 | |
| 285 | std::vector<ServerListEntry> entries; |
| 286 | for (int i = 0; i < (kReceiveWaitInMs / kReceiveDelayInMs); i++) |
| 287 | { |
| 288 | try |
| 289 | { |
| 290 | // Start with initialised buffer in case we receive a non-terminated string |
| 291 | char buffer[1024]{}; |
| 292 | size_t receivedLen{}; |
| 293 | std::unique_ptr<INetworkEndpoint> endpoint; |
| 294 | auto p = udpSocket->ReceiveData(buffer, sizeof(buffer) - 1, &receivedLen, &endpoint); |
| 295 | if (p == ReadPacket::success) |
| 296 | { |
| 297 | auto sender = endpoint->GetHostname(); |
| 298 | LOG_VERBOSE("Received %zu bytes back from %s", receivedLen, sender.c_str()); |
| 299 | auto jinfo = Json::FromString(std::string_view(buffer)); |
| 300 | |
| 301 | if (jinfo.is_object()) |
| 302 | { |
| 303 | jinfo["ip"] = { { "v4", { sender } } }; |
| 304 | |
| 305 | auto entry = ServerListEntry::FromJson(jinfo); |
| 306 | if (entry.has_value()) |
| 307 | { |
| 308 | entry->Local = true; |
| 309 | entries.push_back(std::move(*entry)); |
| 310 | } |
| 311 | } |
| 312 | } |
| 313 | } |
| 314 | catch (const std::exception& e) |
| 315 | { |
| 316 | LOG_WARNING("Error receiving data: %s", e.what()); |
| 317 | } |
| 318 | Platform::Sleep(kReceiveDelayInMs); |
| 319 | } |
| 320 | return entries; |
| 321 | }); |
| 322 | } |
| 323 | |
| 324 | std::future<std::vector<ServerListEntry>> ServerList::FetchLocalServerListAsync() const |
no test coverage detected