mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 06:13:31 +01:00
Move socket-errno code into lib/net
This commit is contained in:
parent
315e6b59dd
commit
84b8dfe635
@ -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
|
||||
|
@ -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) */
|
||||
|
Loading…
Reference in New Issue
Block a user