> Le 28 déc. 2017 à 16:55, Olivier Mascia <[email protected]> a écrit :
>
>> I'll experiment with the fossil code here. Familiarizing with winhttp.c for
>> now.
>
> I haven't yet come to bottom of it, but using IP (IPv4) in the URL (instead
> of name) changes it all!! There seem to be a high price paid in resolving
> the server name on each round trip (from client). This or, due to dual-stack
> being the norm on Windows, client connections loose time trying IPv6
> (generally preferred by Windows when DNS reports both AAAA and A records for
> a name) before falling back to IPv4.
>
> My test now runs (the network portion, excluding rebuilding metadata and next
> things) within 50 seconds for all 250 round-trips and 102700 artifacts
> received. It was close to 1 hour and a half before.
>
> I'm further analysing http_socket.c (socket_open) following this discovery.
Okay, it revolves around g.fIPv4 which only appears in these lines:
Search "fIPv4" (3 hits in 3 files)
I:\fossil\src\http_socket.c (1 hit)
Line 154: hints.ai_family = g.fIPv4 ? AF_INET : AF_UNSPEC;
I:\fossil\src\main.c (1 hit)
Line 159: int fIPv4; /* Use only IPv4, not IPv6. --ipv4
*/
I:\fossil\src\url.c (1 hit)
Line 382: if( find_option("ipv4",0,0) ) g.fIPv4 = 1;
In http_socket.c it is tested to configure hints.ai_family with either AF_INET
or AF_UNSPEC in order to query for only IPv4 or both IPv6 and IPv4. The server
name resolution made by the client then returns both IPv6 and IPv4 because I
didn't mentioned "--ipv4" option anywhere in my commands. Further, enumerating
the IPs, the code attempts socket creation *and* connection, trying the next
returned IP if the connect fails.
Sounds good isn't it?
No. Because the server side never ever initialised a listening socket for
dual-stack. It listens on IPv4 only. Leading to long pauses from the client
trying IPv6 connections, unresponding, before trying next one which might
happen to be IPv4 and reachable.
The server code do initialize its listening socket as this:
s = socket(AF_INET, SOCK_STREAM, 0);
That (on Windows) gives you an IPv4-limited socket.
To get a proper dual-stack socket, the socket must be created with AF_INET6
first then setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,...) should be called to
remove the "only IPv6" attribute from the socket. See
https://msdn.microsoft.com/en-us/library/windows/desktop/ms738574(v=vs.85).aspx.
That is not the only thing to do because the test that follows on the validity
of the IP address would have to be adjusted to take IPv4/IPv6 into account.
So the current situation is simply that when acting as server, fossil.exe setup
an IPv4-only listening socket, while by default it will attempt dual-stack
client connections, loosing a huge amount of time re-establishing those
connections. Add to this that recent Windows will reorder the IPs returned by
getaddrinfo() as to list IPv6 first when the OS looks like having proper IPv6
internet connectivity.
The quick/easy/dirty/temporary fix before completing the proper support
(server-side) of IPv4+IPv6 would be to simply adjust the hint.ai_family
initialisation in http_socket.c::socket_open to read:
#ifdef _WIN32
hints.ai_family = AF_INET;
#else
hints.ai_family = g.fIPv4 ? AF_INET : AF_UNSPEC;
#endif
It works nicely for me. Perfectly expected performance of a large clone
(needing 250 round-trips) in about 50 seconds. Either using explicitly IPv4 in
the URL or, with that patch, the proper DNS name.
I'll see to help with proper Windows dual-stack server socket in January.
--
Best Regards, Meilleures salutations, Met vriendelijke groeten,
Olivier Mascia
_______________________________________________
fossil-users mailing list
[email protected]
http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users