diff options
| author | Floogle <18466542+skyfloogle@users.noreply.github.com> | 2023-01-12 17:45:49 +0100 |
|---|---|---|
| committer | Floogle <18466542+skyfloogle@users.noreply.github.com> | 2023-05-20 17:15:07 +0200 |
| commit | 4f11b0d4c9aee98161bce08c8ff0f516ff84f524 (patch) | |
| tree | c78ea7353cf32df0fef381725caaa8a4eb9352b2 /Source/Core/Common/TraversalServer.cpp | |
| parent | 4efa10c170f6c758311d3ac607174633cb716ffc (diff) | |
Traversal: Autoconfigure TTL to use for probe packet
Diffstat (limited to 'Source/Core/Common/TraversalServer.cpp')
| -rw-r--r-- | Source/Core/Common/TraversalServer.cpp | 117 |
1 files changed, 99 insertions, 18 deletions
diff --git a/Source/Core/Common/TraversalServer.cpp b/Source/Core/Common/TraversalServer.cpp index b9b05519fa..05797b6659 100644 --- a/Source/Core/Common/TraversalServer.cpp +++ b/Source/Core/Common/TraversalServer.cpp @@ -9,8 +9,10 @@ #include <cstring> #include <fcntl.h> #include <netinet/in.h> +#include <sys/select.h> #include <sys/socket.h> #include <sys/types.h> +#include <tuple> #include <unistd.h> #include <unordered_map> #include <utility> @@ -26,6 +28,7 @@ #define DEBUG 0 #define NUMBER_OF_TRIES 5 #define PORT 6262 +#define PORT_ALT 6226 static u64 currentTime; @@ -33,6 +36,7 @@ struct OutgoingPacketInfo { Common::TraversalPacket packet; Common::TraversalRequestId misc; + bool fromAlt; sockaddr_in6 dest; int tries; u64 sendTime; @@ -119,6 +123,7 @@ using ConnectedClients = using OutgoingPackets = std::unordered_map<Common::TraversalRequestId, OutgoingPacketInfo>; static int sock; +static int sockAlt; static OutgoingPackets outgoingPackets; static ConnectedClients connectedClients; @@ -186,25 +191,27 @@ static const char* SenderName(sockaddr_in6* addr) return buf; } -static void TrySend(const void* buffer, size_t size, sockaddr_in6* addr) +static void TrySend(const void* buffer, size_t size, sockaddr_in6* addr, bool fromAlt) { #if DEBUG const auto* packet = static_cast<const Common::TraversalPacket*>(buffer); - printf("-> %d %llu %s\n", static_cast<int>(packet->type), + printf("%s-> %d %llu %s\n", fromAlt ? "alt " : "", static_cast<int>(packet->type), static_cast<long long>(packet->requestId), SenderName(addr)); #endif - if ((size_t)sendto(sock, buffer, size, 0, (sockaddr*)addr, sizeof(*addr)) != size) + if ((size_t)sendto(fromAlt ? sockAlt : sock, buffer, size, 0, (sockaddr*)addr, sizeof(*addr)) != + size) { perror("sendto"); } } -static Common::TraversalPacket* AllocPacket(const sockaddr_in6& dest, +static Common::TraversalPacket* AllocPacket(const sockaddr_in6& dest, bool fromAlt, Common::TraversalRequestId misc = 0) { Common::TraversalRequestId requestId{}; Common::Random::Generate(&requestId, sizeof(requestId)); OutgoingPacketInfo* info = &outgoingPackets[requestId]; + info->fromAlt = fromAlt; info->dest = dest; info->misc = misc; info->tries = 0; @@ -219,12 +226,13 @@ static void SendPacket(OutgoingPacketInfo* info) { info->tries++; info->sendTime = currentTime; - TrySend(&info->packet, sizeof(info->packet), &info->dest); + TrySend(&info->packet, sizeof(info->packet), &info->dest, info->fromAlt); } static void ResendPackets() { - std::vector<std::pair<Common::TraversalInetAddress, Common::TraversalRequestId>> todoFailures; + std::vector<std::tuple<Common::TraversalInetAddress, bool, Common::TraversalRequestId>> + todoFailures; todoFailures.clear(); for (auto it = outgoingPackets.begin(); it != outgoingPackets.end();) { @@ -235,7 +243,8 @@ static void ResendPackets() { if (info->packet.type == Common::TraversalPacketType::PleaseSendPacket) { - todoFailures.push_back(std::make_pair(info->packet.pleaseSendPacket.address, info->misc)); + todoFailures.push_back( + std::make_tuple(info->packet.pleaseSendPacket.address, info->fromAlt, info->misc)); } it = outgoingPackets.erase(it); continue; @@ -250,14 +259,14 @@ static void ResendPackets() for (const auto& p : todoFailures) { - Common::TraversalPacket* fail = AllocPacket(MakeSinAddr(p.first)); + Common::TraversalPacket* fail = AllocPacket(MakeSinAddr(std::get<0>(p)), std::get<1>(p)); fail->type = Common::TraversalPacketType::ConnectFailed; - fail->connectFailed.requestId = p.second; + fail->connectFailed.requestId = std::get<2>(p); fail->connectFailed.reason = Common::TraversalConnectFailedReason::ClientDidntRespond; } } -static void HandlePacket(Common::TraversalPacket* packet, sockaddr_in6* addr) +static void HandlePacket(Common::TraversalPacket* packet, sockaddr_in6* addr, bool toAlt) { #if DEBUG printf("<- %d %llu %s\n", static_cast<int>(packet->type), @@ -276,7 +285,7 @@ static void HandlePacket(Common::TraversalPacket* packet, sockaddr_in6* addr) if (info->packet.type == Common::TraversalPacketType::PleaseSendPacket) { - auto* ready = AllocPacket(MakeSinAddr(info->packet.pleaseSendPacket.address)); + auto* ready = AllocPacket(MakeSinAddr(info->packet.pleaseSendPacket.address), toAlt); if (packet->ack.ok) { ready->type = Common::TraversalPacketType::ConnectReady; @@ -303,7 +312,7 @@ static void HandlePacket(Common::TraversalPacket* packet, sockaddr_in6* addr) case Common::TraversalPacketType::HelloFromClient: { u8 ok = packet->helloFromClient.protoVersion <= Common::TraversalProtoVersion; - Common::TraversalPacket* reply = AllocPacket(*addr); + Common::TraversalPacket* reply = AllocPacket(*addr, toAlt); reply->type = Common::TraversalPacketType::HelloFromServer; reply->helloFromServer.ok = ok; if (ok) @@ -336,19 +345,35 @@ static void HandlePacket(Common::TraversalPacket* packet, sockaddr_in6* addr) auto r = EvictFind(connectedClients, hostId); if (!r.found) { - Common::TraversalPacket* reply = AllocPacket(*addr); + Common::TraversalPacket* reply = AllocPacket(*addr, toAlt); reply->type = Common::TraversalPacketType::ConnectFailed; reply->connectFailed.requestId = packet->requestId; reply->connectFailed.reason = Common::TraversalConnectFailedReason::NoSuchClient; } else { - Common::TraversalPacket* please = AllocPacket(MakeSinAddr(*r.value), packet->requestId); + Common::TraversalPacket* please = + AllocPacket(MakeSinAddr(*r.value), toAlt, packet->requestId); please->type = Common::TraversalPacketType::PleaseSendPacket; please->pleaseSendPacket.address = MakeInetAddress(*addr); } break; } + case Common::TraversalPacketType::TestPlease: + { + Common::TraversalHostId& hostId = packet->testPlease.hostId; + auto r = EvictFind(connectedClients, hostId); + if (r.found) + { + Common::TraversalPacket ack = {}; + ack.type = Common::TraversalPacketType::Ack; + ack.requestId = packet->requestId; + ack.ack.ok = true; + sockaddr_in6 mainAddr = MakeSinAddr(*r.value); + TrySend(&ack, sizeof(ack), &mainAddr, toAlt); + } + break; + } default: fprintf(stderr, "received unknown packet type %d from %s\n", static_cast<int>(packet->type), SenderName(addr)); @@ -360,7 +385,8 @@ static void HandlePacket(Common::TraversalPacket* packet, sockaddr_in6* addr) ack.type = Common::TraversalPacketType::Ack; ack.requestId = packet->requestId; ack.ack.ok = packetOk; - TrySend(&ack, sizeof(ack), addr); + TrySend(&ack, sizeof(ack), addr, + packet->type != Common::TraversalPacketType::TestPlease ? toAlt : !toAlt); } } @@ -373,6 +399,12 @@ int main() perror("socket"); return 1; } + sockAlt = socket(PF_INET6, SOCK_DGRAM, 0); + if (sockAlt == -1) + { + perror("socket alt"); + return 1; + } int no = 0; rv = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no)); if (rv < 0) @@ -380,6 +412,12 @@ int main() perror("setsockopt IPV6_V6ONLY"); return 1; } + rv = setsockopt(sockAlt, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no)); + if (rv < 0) + { + perror("setsockopt IPV6_V6ONLY alt"); + return 1; + } in6_addr any = IN6ADDR_ANY_INIT; sockaddr_in6 addr; #ifdef SIN6_LEN @@ -397,6 +435,13 @@ int main() perror("bind"); return 1; } + addr.sin6_port = htons(PORT_ALT); + rv = bind(sockAlt, (sockaddr*)&addr, sizeof(addr)); + if (rv < 0) + { + perror("bind alt"); + return 1; + } timeval tv; tv.tv_sec = 0; @@ -407,19 +452,55 @@ int main() perror("setsockopt SO_RCVTIMEO"); return 1; } + rv = setsockopt(sockAlt, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + if (rv < 0) + { + perror("setsockopt SO_RCVTIMEO alt"); + return 1; + } #ifdef HAVE_LIBSYSTEMD - sd_notifyf(0, "READY=1\nSTATUS=Listening on port %d", PORT); + sd_notifyf(0, "READY=1\nSTATUS=Listening on port %d (alt port: %d)", PORT, PORT_ALT); #endif while (true) { + tv.tv_sec = 0; + tv.tv_usec = 300000; + fd_set readSet; + FD_ZERO(&readSet); + FD_SET(sock, &readSet); + FD_SET(sockAlt, &readSet); + rv = select(std::max(sock, sockAlt) + 1, &readSet, nullptr, nullptr, &tv); + if (rv < 0) + { + if (errno != EINTR && errno != EAGAIN) + { + perror("recvfrom"); + return 1; + } + } + + int recvsock; + if (FD_ISSET(sock, &readSet)) + { + recvsock = sock; + } + else if (FD_ISSET(sockAlt, &readSet)) + { + recvsock = sockAlt; + } + else + { + ResendPackets(); + continue; + } sockaddr_in6 raddr; socklen_t addrLen = sizeof(raddr); Common::TraversalPacket packet{}; // note: switch to recvmmsg (yes, mmsg) if this becomes // expensive - rv = recvfrom(sock, &packet, sizeof(packet), 0, (sockaddr*)&raddr, &addrLen); + rv = recvfrom(recvsock, &packet, sizeof(packet), 0, (sockaddr*)&raddr, &addrLen); currentTime = std::chrono::duration_cast<std::chrono::microseconds>( std::chrono::system_clock::now().time_since_epoch()) .count(); @@ -437,7 +518,7 @@ int main() } else { - HandlePacket(&packet, &raddr); + HandlePacket(&packet, &raddr, recvsock == sockAlt); } ResendPackets(); #ifdef HAVE_LIBSYSTEMD |
