Hi John,
On Jul 29 22:41, John Scott via Cygwin wrote:
> Hi,
>
> I was wondering why my daytime server doesn't work when built for
> Cygwin, and I have been able to narrow it down to this reproducible
> test case:
> [...]
> This code fails with "Failed to create socket: Invalid argument". Does
> anyone have an idea why this happens, given that the arguments to
> socket() come directly from the call to getaddrinfo()?
Welcome to the Windows implementation of getaddrinfo.
Assuming you call getaddrinfo (NULL, "daytime", NULL, &result), you get
the following return from Linux:
family: 2 socktype 1 protocol 6 AF_INET, STREAM, TCP
family: 2 socktype 2 protocol 17 AF_INET, DGRAM, UCP
family: 10 socktype 1 protocol 6 AF_INET6, STREAM, TCP
family: 10 socktype 2 protocol 17 AF_INET6, DGRAM, UCP
The same call on Windows returns:
family: 23 socktype 0 protocol 0 AF_INET6, any, any
family: 2 socktype 0 protocol 0 AF_INET, any, any
If the service supports both, TCP and UDP, then socktype and protocol
are always 0 on Windows. The restriction from the hints parameter
*only* restricts the output for that very field!
I.e., your hints with .ai_protocol = IPPROTO_TCP only restricts the
output of the ai_protocol field, not the output of the ai_socktype
field:
family: 23 socktype 0 protocol 6 AF_INET6, any, TCP
family: 2 socktype 0 protocol 6 AF_INET, any, TCP
On Linux you get the less surprising result
family: 2 socktype 1 protocol 6 AF_INET, STREAM, TCP
family: 10 socktype 1 protocol 6 AF_INET6, STREAM, TCP
> Remarkably,
> changing the service from "daytime" to "http" seems to fix it, which
> seems quite strange.
Yeah, that's a bad joke as well. The reason is that the http service is
defined for TCP only. Not for UDP. As a result, Windows' getaddrinfo
suddenly returns a valid ai_socktype field:
family: 23 socktype 1 protocol 6 AF_INET6, STREAM, TCP
family: 2 socktype 1 protocol 6 AF_INET, STREAM, TCP
Cygwin implements a shallow (~300 lines) wrapper over the WinSock
GetAddrInfoW function and otherwise relies on the values returned by the
OS. However, it already duplicates the returned list to self-allocated
memory, which is required for fork(2) semantics. It should be possible
to improve the wrapper to duplicate entries with socktype and protocol
0-entries, but that would be in the next Cygwin version earliest.
Back to your problem. For the time being, you can easily "fix" your
code by changing the hints:
- int s = getaddrinfo(NULL, "daytime", &(const struct addrinfo){.ai_flags
= AI_PASSIVE, .ai_protocol = IPPROTO_TCP}, &res);
+ int s = getaddrinfo(NULL, "daytime", &(const struct addrinfo){.ai_flags
= AI_PASSIVE, .ai_socktype = SOCK_STREAM}, &res);
This returns
family: 23 socktype 1 protocol 0 AF_INET6, STREAM, any
family: 2 socktype 1 protocol 0 AF_INET, STREAM, any
The content of the protocol parameter doesn't really matter to socket(2),
so it will work on Cygwin as well as on Linux and others.
HTH,
Corinna
--
Problem reports: https://cygwin.com/problems.html
FAQ: https://cygwin.com/faq/
Documentation: https://cygwin.com/docs.html
Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple