On Windows, when will a 'socket()' call return WSAEPROVIDERFAILEDINIT? - sockets

Suppose our client application does as below:
WSADATA wsa_data;
int ret;
SOCKET sock;
ret = WSAStartup (MAKEWORD (2, 2), &wsa_data);
if (ret ==0) {
sock = socket (AF_INET6, SOCK_DGRAM, IPROTO_UDP);
}
When will it happen that sock == INVALID_SOCKET and WSAGetLastError() would return WSAEPROVIDERFAILEDINIT?
Microsoft's documentation for the socket() function says it can return WSAEPROVIDERFAILEDINIT when:
The service provider failed to initialize. This error is returned if a layered service provider (LSP) or namespace provider was improperly installed or the provider fails to operate correctly.
Can a TCP/IP transport service provider, that is not a custom service provider, fail to initialize during a socket() call? If yes, why? Under what circumstances? And how can it be remedied?

It will probably never happen with the default provider and unlikely with a 3rd-party provider.
WSAEPROVIDERFAILEDINIT can be returned by Windows itself if it cannot load the provider or if it can't find the WSPStartup or more likely NSPStartup exported function. I'm not sure if this can only happen during WSAStartup or if Windows is allowed to delay this call until the provider is needed.
A provider itself can presumably fail with WSAEPROVIDERFAILEDINIT at any time. Imagine a LSP that logs every connection but for whatever reason there is a problem with the database it is using and it might choose to fail the socket with this error.
(All of this is speculation and you should not handle each possible error in a specific way unless you have a reason to.)

Related

JNI/C socket connection error on Solaris 11

Our application uses several socket connections (to localhost) implemented in c, with one connection using a jni/c socket connection. All of them call the same include to open the socket, and all are successful when we run the application on Solaris 10.
Migrating to Solaris 11, we are finding that only the socket connections built in c are working, the one jni/c connection will not. I've added output to see what exactly is being sent to the connect call and it looks like the call is getting everything it needs:
"sock_connect: socket status: 0, sock_d: 27, serv_addr: ***.***.***.***, sizeof: 16"
So for the call below, sock_d = 27
serv_addr = (it returns a good IP, but my PM said he'd kill me if I put the actual IP)
sizeof(serv_addr) = 16
which should be all the parameters connect() needs in the code snippet below.
.
.
.
.
status = connect(sock_d, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (status < 0){
fprintf(stderr, "sock_connect 4: after connect errno: %i, error %sn", errno, strerror(errno));
if (errno == EINPROGRESS){
fprintf(stderr, "sock_connect, errno == EINPROGRESS\n");
.
.
.
Truss output for the failed connection seems to indicate an EINPROGRESS error. Our code is supposed to validate for this possibility, but it does not trigger an if statement that checks to see if the error == EINPROGRESS. It never reaches the second fprintf statement. We have disabled IPv6 on the server, as we thought perhaps java was trying to force this protocol, but this didn't make a difference either.
The exact same libraries and executables will work on both servers, right up until the jni socket call is made. From that point on Solaris 10 keeps going but Solaris 11 will not.
Has anyone seen this before? Please let me know what else you need to see and I'll post it. Thanks in advance!
This code incorrectly assumes fprintf() will never modify errno:
if (status < 0){
fprintf(stderr, "sock_connect 4: after connect errno: %i, error %sn", errno, strerror(errno));
if (errno == EINPROGRESS){
fprintf(stderr, "sock_connect, errno == EINPROGRESS\n");
The POSIX standard for errno states (emphasis mine):
The value of errno shall be defined only after a call to a function for which it is explicitly stated to be set and until it is changed by the next function call or if the application assigns it a value.
And per the Solaris 11.3 fprintf() man page, fprintf() can set errno:
Errors
For the conditions under which printf(), fprintf(), and
dprintf() will fail and may fail, refer to fputc(3C) or fputwc(3C).
The snprintf() function will fail if:
EOVERFLOW
The value of n is greater than INT_MAX or the number of bytes needed
to hold the output excluding the terminating null is greater than
INT_MAX.
All forms of printf() will fail if:
EILSEQ
A wide-character code that does not correspond to a valid character
has been detected.
EINVAL
There are insufficient arguments.
The dprintf() function will fail if:
EBADF
The fildes argument is not a valid file descriptor.
The printf(), fprintf(), dprintf(), and asprintf() functions
may fail due to an underlying malloc(3C) failure if:
EAGAIN
Storage space is temporarily unavailable.
ENOMEM
Insufficient storage space is available.

When can connect() on O_NONBLOCK socket fail with something other than EINPROGRESS or EALREADY?

I read the following sample code and I am wondering if anybody can say on which platforms it is possible for connect() to fail with something other than EINPROGRESS or EALREADY.
By fail I mean execute the else branch in the sample to execute. The comment in the source suggests FreeBSD. Are there any other systems? I was not able to get it to fail on Linux.
if (connect(hostp->sockets[i],
(struct sockaddr *)res->ai_addr,
res->ai_addrlen) == -1) {
/* This is what we expect. */
if (errno == EINPROGRESS) {
printf(" connect EINPROGRESS OK "
"(expected)\n");
FD_SET(hostp->sockets[i], &wrfds);
} else {
/*
* This may happen right here, on
* localhost for example (immediate
* connection refused).
* I can see that happen on FreeBSD
* but not on Solaris, for example.
*/
printf(" connect: %s\n",
strerror(errno));
++n;
}
[...]
source: http://mff.devnull.cz/pvu/src/tcp/non-blocking-connect.c
There are many ways why connect might fail. As the comment rightly says even a non-blocking connect might fail immediately on some platforms when connecting to localhost if no listening server is there. Also connect will usually fail immediately if no route can be determined to the target, for example if the interface for the default route is down. And then there are still other ways to fail, like lack of memory, permission denied to connect when running inside a sandbox or similar.

NodeMCU crashes when attempting to call net.socket:connect()

I am attempting to send a broadcast packet to a certain port, but it seems that the code gives some weird errors for which I can't find a fix.
I've tried using net.socket:connect() and then calling the "send()" method, which didn't work, then I said that I should use the net.socket:on('connection') and send there, since I suppose net.socket:connect() isn't synchronous. But that gave a weird error too...
For this code:
function sendBroadcastPacket()
bip = wifi.sta.getbroadcast()
srv = net.createConnection(net.UDP,0)
print('Trying to connect on: ', bip)
srv:connect('9001', bip)
srv:send("Broadcast packet from: "..NODE_ID, function(sent)
print("Broadcasted packet! "..sent)
end)
end
I receive the following error:
PANIC: unprotected error in call to Lua API (init.lua:24: attempt to
call method 'connect' (a nil value))
Line 24 is the srv:connect line.
After that I tried listening for the connection event first, to see if it worked that way:
function sendBroadcastPacket()
bip = wifi.sta.getbroadcast()
srv = net.createConnection(net.UDP,0)
print('Trying to connect on: ', bip)
srv:on('connection', function(sck, c)
sck:send("Broadcast packet from: "..NODE_ID, function(sent)
print("Broadcasted packet! "..sent)
end)
end)
srv:connect('9001', bip)
end
I receive the following error:
PANIC: unprotected error in call to Lua API (init.lua:24: invalid
callback name)
Line 24 is the srv:on('connection') line.
What seems to be happening here? There aren't many google results, since a lot of other people use the Arduino-IDE version(btw, is that still nodemcu or do you need a different firmware for the ESP8266?).
I am getting a broadcast IP, and it connects to the AP. I didn't post here the wifi connection part because it works, I've used it to test mqtt and http connections which worked.
The build I'm using, Lua 5.1.4 on SDK 2.1.0(116b762), has the net module included.
Your attempts all failed because you don't seem to consider that UDP is a connection-less protocol. Hence, there's no connect() or on('connection'... for UDP.
The first attempt failed because send() needs to be called on a socket and not on the connection. The second failed because the connection callback name is only available for TCP, not for UDP.
Try something like this:
function sendBroadcastPacket()
local port = 9001
local bip = wifi.sta.getbroadcast()
print(string.format("Broadcasting to %s:%d", bip, port))
net.createUDPSocket():send(port, bip, "foo bar")
end
Documentation: https://nodemcu.readthedocs.io/en/latest/en/modules/net/#netudpsocket-module

What does 'may fail' in socket() mean?

The socket() function shall fail if:
EAFNOSUPPORT
The implementation does not support the specified address family.
EMFILE All file descriptors available to the process are currently open.
ENFILE No more file descriptors are available for the system.
EPROTONOSUPPORT
The protocol is not supported by the address family, or the protocol is not supported by the implementation.
EPROTOTYPE
The socket type is not supported by the protocol.
The socket() function may fail if:
EACCES The process does not have appropriate privileges.
ENOBUFS
Insufficient resources were available in the system to perform the operation.
ENOMEM Insufficient memory was available to fulfill the request.
(man 3 socket)
I've recently encountered the case that socket() returned a non-negative fd, while all operations(accept(), connect(), etc.) on it would fail. This error was found by valgrind --track-fds=yes -v.
Does this mean that even if socket() returns a non-negative fd, fd is still possible to be invalid?

sock = new UdpClient(ipAny) cause error > System.Net.Sockets.SocketException has been thrown. Access denied

My Environment
MacOS X 10.8.5
Unity 5.1.1f
I am trying to use code to access NTP server.
http://ftvoid.com/blog/post/847
When I try the code, I have an error at new UdpClient(ipAny)
private void Request() {
// Open socket
ipAny = new IPEndPoint(IPAddress.Any, 123);
sock = new UdpClient(ipAny);
The error message is
System.Net.Sockets.SocketException has been thrown
Access denied
Instead of the following
sock = new UdpClient(ipAny);
if I use the following, it works.
sock = new UdpClient();
My Questions are
What's the cause of the error?
Is it O.K. to use sock = new UpdClient()?
Should be fine. The constructor you are using is for local port binding. Not sure why you need that. From the docs:
You do not need to specify a local IP address and port number for sending and receiving data. If you do not, the underlying service provider will assign the most appropriate local IP address and port number.
https://msdn.microsoft.com/en-us/library/k227d11f(v=vs.110).aspx
I'd use the new UpdClient() as you suggested.