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