Move socket-errno code into lib/net

This commit is contained in:
Nick Mathewson 2018-06-28 11:20:31 -04:00
parent 315e6b59dd
commit 84b8dfe635
2 changed files with 103 additions and 102 deletions

View File

@ -550,108 +550,6 @@ compute_num_cpus(void)
return num_cpus;
}
/**
* On Windows, WSAEWOULDBLOCK is not always correct: when you see it,
* you need to ask the socket for its actual errno. Also, you need to
* get your errors from WSAGetLastError, not errno. (If you supply a
* socket of -1, we check WSAGetLastError, but don't correct
* WSAEWOULDBLOCKs.)
*
* The upshot of all of this is that when a socket call fails, you
* should call tor_socket_errno <em>at most once</em> on the failing
* socket to get the error.
*/
#if defined(_WIN32)
int
tor_socket_errno(tor_socket_t sock)
{
int optval, optvallen=sizeof(optval);
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK && SOCKET_OK(sock)) {
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen))
return err;
if (optval)
return optval;
}
return err;
}
#endif /* defined(_WIN32) */
#if defined(_WIN32)
#define E(code, s) { code, (s " [" #code " ]") }
struct { int code; const char *msg; } windows_socket_errors[] = {
E(WSAEINTR, "Interrupted function call"),
E(WSAEACCES, "Permission denied"),
E(WSAEFAULT, "Bad address"),
E(WSAEINVAL, "Invalid argument"),
E(WSAEMFILE, "Too many open files"),
E(WSAEWOULDBLOCK, "Resource temporarily unavailable"),
E(WSAEINPROGRESS, "Operation now in progress"),
E(WSAEALREADY, "Operation already in progress"),
E(WSAENOTSOCK, "Socket operation on nonsocket"),
E(WSAEDESTADDRREQ, "Destination address required"),
E(WSAEMSGSIZE, "Message too long"),
E(WSAEPROTOTYPE, "Protocol wrong for socket"),
E(WSAENOPROTOOPT, "Bad protocol option"),
E(WSAEPROTONOSUPPORT, "Protocol not supported"),
E(WSAESOCKTNOSUPPORT, "Socket type not supported"),
/* What's the difference between NOTSUPP and NOSUPPORT? :) */
E(WSAEOPNOTSUPP, "Operation not supported"),
E(WSAEPFNOSUPPORT, "Protocol family not supported"),
E(WSAEAFNOSUPPORT, "Address family not supported by protocol family"),
E(WSAEADDRINUSE, "Address already in use"),
E(WSAEADDRNOTAVAIL, "Cannot assign requested address"),
E(WSAENETDOWN, "Network is down"),
E(WSAENETUNREACH, "Network is unreachable"),
E(WSAENETRESET, "Network dropped connection on reset"),
E(WSAECONNABORTED, "Software caused connection abort"),
E(WSAECONNRESET, "Connection reset by peer"),
E(WSAENOBUFS, "No buffer space available"),
E(WSAEISCONN, "Socket is already connected"),
E(WSAENOTCONN, "Socket is not connected"),
E(WSAESHUTDOWN, "Cannot send after socket shutdown"),
E(WSAETIMEDOUT, "Connection timed out"),
E(WSAECONNREFUSED, "Connection refused"),
E(WSAEHOSTDOWN, "Host is down"),
E(WSAEHOSTUNREACH, "No route to host"),
E(WSAEPROCLIM, "Too many processes"),
/* Yes, some of these start with WSA, not WSAE. No, I don't know why. */
E(WSASYSNOTREADY, "Network subsystem is unavailable"),
E(WSAVERNOTSUPPORTED, "Winsock.dll out of range"),
E(WSANOTINITIALISED, "Successful WSAStartup not yet performed"),
E(WSAEDISCON, "Graceful shutdown now in progress"),
#ifdef WSATYPE_NOT_FOUND
E(WSATYPE_NOT_FOUND, "Class type not found"),
#endif
E(WSAHOST_NOT_FOUND, "Host not found"),
E(WSATRY_AGAIN, "Nonauthoritative host not found"),
E(WSANO_RECOVERY, "This is a nonrecoverable error"),
E(WSANO_DATA, "Valid name, no data record of requested type)"),
/* There are some more error codes whose numeric values are marked
* <b>OS dependent</b>. They start with WSA_, apparently for the same
* reason that practitioners of some craft traditions deliberately
* introduce imperfections into their baskets and rugs "to allow the
* evil spirits to escape." If we catch them, then our binaries
* might not report consistent results across versions of Windows.
* Thus, I'm going to let them all fall through.
*/
{ -1, NULL },
};
/** There does not seem to be a strerror equivalent for Winsock errors.
* Naturally, we have to roll our own.
*/
const char *
tor_socket_strerror(int e)
{
int i;
for (i=0; windows_socket_errors[i].code >= 0; ++i) {
if (e == windows_socket_errors[i].code)
return windows_socket_errors[i].msg;
}
return strerror(e);
}
#endif /* defined(_WIN32) */
/** Called before we make any calls to network-related functions.
* (Some operating systems require their network libraries to be

View File

@ -691,3 +691,106 @@ write_all_to_socket(tor_socket_t fd, const char *buf, size_t count)
}
return (ssize_t)count;
}
/**
* On Windows, WSAEWOULDBLOCK is not always correct: when you see it,
* you need to ask the socket for its actual errno. Also, you need to
* get your errors from WSAGetLastError, not errno. (If you supply a
* socket of -1, we check WSAGetLastError, but don't correct
* WSAEWOULDBLOCKs.)
*
* The upshot of all of this is that when a socket call fails, you
* should call tor_socket_errno <em>at most once</em> on the failing
* socket to get the error.
*/
#if defined(_WIN32)
int
tor_socket_errno(tor_socket_t sock)
{
int optval, optvallen=sizeof(optval);
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK && SOCKET_OK(sock)) {
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen))
return err;
if (optval)
return optval;
}
return err;
}
#endif /* defined(_WIN32) */
#if defined(_WIN32)
#define E(code, s) { code, (s " [" #code " ]") }
struct { int code; const char *msg; } windows_socket_errors[] = {
E(WSAEINTR, "Interrupted function call"),
E(WSAEACCES, "Permission denied"),
E(WSAEFAULT, "Bad address"),
E(WSAEINVAL, "Invalid argument"),
E(WSAEMFILE, "Too many open files"),
E(WSAEWOULDBLOCK, "Resource temporarily unavailable"),
E(WSAEINPROGRESS, "Operation now in progress"),
E(WSAEALREADY, "Operation already in progress"),
E(WSAENOTSOCK, "Socket operation on nonsocket"),
E(WSAEDESTADDRREQ, "Destination address required"),
E(WSAEMSGSIZE, "Message too long"),
E(WSAEPROTOTYPE, "Protocol wrong for socket"),
E(WSAENOPROTOOPT, "Bad protocol option"),
E(WSAEPROTONOSUPPORT, "Protocol not supported"),
E(WSAESOCKTNOSUPPORT, "Socket type not supported"),
/* What's the difference between NOTSUPP and NOSUPPORT? :) */
E(WSAEOPNOTSUPP, "Operation not supported"),
E(WSAEPFNOSUPPORT, "Protocol family not supported"),
E(WSAEAFNOSUPPORT, "Address family not supported by protocol family"),
E(WSAEADDRINUSE, "Address already in use"),
E(WSAEADDRNOTAVAIL, "Cannot assign requested address"),
E(WSAENETDOWN, "Network is down"),
E(WSAENETUNREACH, "Network is unreachable"),
E(WSAENETRESET, "Network dropped connection on reset"),
E(WSAECONNABORTED, "Software caused connection abort"),
E(WSAECONNRESET, "Connection reset by peer"),
E(WSAENOBUFS, "No buffer space available"),
E(WSAEISCONN, "Socket is already connected"),
E(WSAENOTCONN, "Socket is not connected"),
E(WSAESHUTDOWN, "Cannot send after socket shutdown"),
E(WSAETIMEDOUT, "Connection timed out"),
E(WSAECONNREFUSED, "Connection refused"),
E(WSAEHOSTDOWN, "Host is down"),
E(WSAEHOSTUNREACH, "No route to host"),
E(WSAEPROCLIM, "Too many processes"),
/* Yes, some of these start with WSA, not WSAE. No, I don't know why. */
E(WSASYSNOTREADY, "Network subsystem is unavailable"),
E(WSAVERNOTSUPPORTED, "Winsock.dll out of range"),
E(WSANOTINITIALISED, "Successful WSAStartup not yet performed"),
E(WSAEDISCON, "Graceful shutdown now in progress"),
#ifdef WSATYPE_NOT_FOUND
E(WSATYPE_NOT_FOUND, "Class type not found"),
#endif
E(WSAHOST_NOT_FOUND, "Host not found"),
E(WSATRY_AGAIN, "Nonauthoritative host not found"),
E(WSANO_RECOVERY, "This is a nonrecoverable error"),
E(WSANO_DATA, "Valid name, no data record of requested type)"),
/* There are some more error codes whose numeric values are marked
* <b>OS dependent</b>. They start with WSA_, apparently for the same
* reason that practitioners of some craft traditions deliberately
* introduce imperfections into their baskets and rugs "to allow the
* evil spirits to escape." If we catch them, then our binaries
* might not report consistent results across versions of Windows.
* Thus, I'm going to let them all fall through.
*/
{ -1, NULL },
};
/** There does not seem to be a strerror equivalent for Winsock errors.
* Naturally, we have to roll our own.
*/
const char *
tor_socket_strerror(int e)
{
int i;
for (i=0; windows_socket_errors[i].code >= 0; ++i) {
if (e == windows_socket_errors[i].code)
return windows_socket_errors[i].msg;
}
return strerror(e);
}
#endif /* defined(_WIN32) */