Conversation
This DNS lookup prefer IPv6, and return an IPv4 as fallback. If the client doesnt have IPv6 compatibility, then the DNS probe gonna return IPv4 only
|
Re, the PR in link for IPv6 support, on the server side: |
lionkor
left a comment
There was a problem hiding this comment.
Generally great job, please see if you can address the comments I made.
Could you also explain to my what the rationale is behind adding so many comments and doing so many unrelated changes? I'm just curious.
src/Network/Core.cpp
Outdated
| Terminate = true; | ||
| return; | ||
|
|
||
| const std::regex ipv4v6Pattern(R"(((^\h*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\h*(|/([0-9]|[1-2][0-9]|3[0-2]))$)|(^\h*((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\h*(|/([0-9]|[0-9][0-9]|1[0-1][0-9]|12[0-8]))$)))"); |
There was a problem hiding this comment.
Can we not just let the connect() / bind() syscalls handle the validation check of ipv6's? :)
src/Network/Core.cpp
Outdated
| Data = Code + HTTP::Get("https://backend.beammp.com/servers-info"); | ||
| break; | ||
| case 'C': | ||
| //TODO StartSync Here |
There was a problem hiding this comment.
please either do or remove the todo, or create an issue
| info("Game Connected!"); | ||
| info("Game Connected to LUA interface!"); | ||
| GameHandler(CSocket); | ||
| warn("Game Reconnecting..."); | ||
| warn("Game reconnecting to LUA interface..."); |
There was a problem hiding this comment.
I think this was fine, why the change?
| LSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | ||
| if (LSocket == -1) { | ||
| debug("(Core) socket failed with error: " + std::to_string(WSAGetLastError())); | ||
| freeaddrinfo(res); |
There was a problem hiding this comment.
Is there a reason we don't need freeaddrinfo anymore?
| //Loop all and return it by prefeence ipv6 | ||
| for (struct addrinfo* ptr = addresses; ptr != nullptr; ptr = ptr->ai_next) { | ||
| char ipstr[INET6_ADDRSTRLEN] = { 0 }; | ||
|
|
||
| if (ptr->ai_family == AF_INET6) { | ||
| struct sockaddr_in6* ipv6 = (struct sockaddr_in6*)ptr->ai_addr; | ||
| inet_ntop(AF_INET6, &(ipv6->sin6_addr), ipstr, sizeof(ipstr)); | ||
| resolved = ipstr; | ||
| break; //Break if IPv6 finded | ||
| } | ||
| else if (ptr->ai_family == AF_INET) { | ||
| struct sockaddr_in* ipv4 = (struct sockaddr_in*)ptr->ai_addr; | ||
| inet_ntop(AF_INET, &(ipv4->sin_addr), ipstr, sizeof(ipstr)); | ||
| resolved = ipstr; | ||
| } | ||
| } |
There was a problem hiding this comment.
Usually you just loop over resolved addresses, attempt to connect, and take the first one that connects. Is there a good reason why we don't just do that here?
src/Network/VehicleData.cpp
Outdated
| if (AF == AF_INET) { | ||
| // IPv4 | ||
| struct sockaddr_in serverAddrV4; | ||
| memset(&serverAddrV4, 0, sizeof(sockaddr_in)); | ||
| serverAddrV4.sin_family = AF_INET; | ||
| serverAddrV4.sin_port = htons(Port); | ||
| inet_pton(AF_INET, IP.c_str(), &serverAddrV4.sin_addr); | ||
| memcpy(ToServer, &serverAddrV4, sizeof(sockaddr_in)); | ||
| addrLen = sizeof(sockaddr_in); | ||
| } else { | ||
| // IPv6 | ||
| struct sockaddr_in6 serverAddrV6; | ||
| memset(&serverAddrV6, 0, sizeof(sockaddr_in6)); | ||
| serverAddrV6.sin6_family = AF_INET6; | ||
| serverAddrV6.sin6_port = htons(Port); | ||
| inet_pton(AF_INET6, IP.c_str(), &serverAddrV6.sin6_addr); | ||
| memcpy(ToServer, &serverAddrV6, sizeof(sockaddr_in6)); | ||
| addrLen = sizeof(sockaddr_in6); | ||
| } |
There was a problem hiding this comment.
this is almost duplicated down in VehicleEvent, could we pull this out into a function maybe?
I'have tested the behavior waited
Based on Windows's documentation, the entire app need at least one WSAStarup call, other gonna juste increment a counter, for wich the app need the same number of WSACleanup. https://learn.microsoft.com/fr-fr/windows/win32/api/winsock/nf-winsock-wsastartup To simplify, and to increase a lot the visibility, the app will call one WSAStartup, and one WSACleanup at all. This is done on CoreNetwork function.
Hello, I worked on the client side to fully support IPv6 (and still IPv4 of course)
And I changed some mechanisms that don't break everything:
The DNS resolver can now return IPv4 or IPv6, and prefer IPv6 (as OS like Windows do)
I think I have tested everything:
I have also added vcpkg, as beamng-server has, it is simpler for me to "clone and go" this project.
The server side has needed some modification, which I let you check it on the server repo! (ill add the PR link after)
I hope everything is good to go!