mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-10 21:10:06 -04:00
use FormatMessage for winsock errors
as discussed here: http://archives.seul.org/libevent/users/Feb-2013/msg00004.html
This commit is contained in:
parent
729651260d
commit
0c6ec5d816
2
event.c
2
event.c
@ -3468,6 +3468,8 @@ event_global_setup_locks_(const int enable_locks)
|
|||||||
#endif
|
#endif
|
||||||
if (evsig_global_setup_locks_(enable_locks) < 0)
|
if (evsig_global_setup_locks_(enable_locks) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (evutil_global_setup_locks_(enable_locks) < 0)
|
||||||
|
return -1;
|
||||||
if (evutil_secure_rng_global_setup_locks_(enable_locks) < 0)
|
if (evutil_secure_rng_global_setup_locks_(enable_locks) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -373,6 +373,7 @@ void *evthread_setup_global_lock_(void *lock_, unsigned locktype,
|
|||||||
|
|
||||||
int event_global_setup_locks_(const int enable_locks);
|
int event_global_setup_locks_(const int enable_locks);
|
||||||
int evsig_global_setup_locks_(const int enable_locks);
|
int evsig_global_setup_locks_(const int enable_locks);
|
||||||
|
int evutil_global_setup_locks_(const int enable_locks);
|
||||||
int evutil_secure_rng_global_setup_locks_(const int enable_locks);
|
int evutil_secure_rng_global_setup_locks_(const int enable_locks);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
191
evutil.c
191
evutil.c
@ -81,6 +81,7 @@
|
|||||||
#include "util-internal.h"
|
#include "util-internal.h"
|
||||||
#include "log-internal.h"
|
#include "log-internal.h"
|
||||||
#include "mm-internal.h"
|
#include "mm-internal.h"
|
||||||
|
#include "evthread-internal.h"
|
||||||
|
|
||||||
#include "strlcpy-internal.h"
|
#include "strlcpy-internal.h"
|
||||||
#include "ipv6-internal.h"
|
#include "ipv6-internal.h"
|
||||||
@ -1597,80 +1598,137 @@ evutil_gai_strerror(int err)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define E(code, s) { code, (s " [" #code " ]") }
|
/* destructively remove a trailing line terminator from s */
|
||||||
static struct { int code; const char *msg; } windows_socket_errors[] = {
|
static void
|
||||||
E(WSAEINTR, "Interrupted function call"),
|
chomp (char *s)
|
||||||
E(WSAEACCES, "Permission denied"),
|
{
|
||||||
E(WSAEFAULT, "Bad address"),
|
size_t len;
|
||||||
E(WSAEINVAL, "Invalid argument"),
|
if (s && (len = strlen (s)) > 0 && s[len - 1] == '\n') {
|
||||||
E(WSAEMFILE, "Too many open files"),
|
s[--len] = 0;
|
||||||
E(WSAEWOULDBLOCK, "Resource temporarily unavailable"),
|
if (len > 0 && s[len - 1] == '\r')
|
||||||
E(WSAEINPROGRESS, "Operation now in progress"),
|
s[--len] = 0;
|
||||||
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. */
|
/* FormatMessage returns allocated strings, but evutil_socket_error_to_string
|
||||||
E(WSASYSNOTREADY, "Network subsystem is unavailable"),
|
* is supposed to return a string which is good indefinitely without having
|
||||||
E(WSAVERNOTSUPPORTED, "Winsock.dll out of range"),
|
* to be freed. To make this work without leaking memory, we cache the
|
||||||
E(WSANOTINITIALISED, "Successful WSAStartup not yet performed"),
|
* string the first time FormatMessage is called on a particular error
|
||||||
E(WSAEDISCON, "Graceful shutdown now in progress"),
|
* code, and then return the cached string on subsequent calls with the
|
||||||
#ifdef WSATYPE_NOT_FOUND
|
* same code. The strings aren't freed until libevent_global_shutdown
|
||||||
E(WSATYPE_NOT_FOUND, "Class type not found"),
|
* (or never). We use a linked list to cache the errors, because we
|
||||||
#endif
|
* only expect there to be a few dozen, and that should be fast enough.
|
||||||
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
|
struct cached_sock_errs {
|
||||||
* <b>OS dependent</b>. They start with WSA_, apparently for the same
|
DWORD code;
|
||||||
* reason that practitioners of some craft traditions deliberately
|
char *msg; /* allocated with LocalAlloc; free with LocalFree */
|
||||||
* introduce imperfections into their baskets and rugs "to allow the
|
struct cached_sock_errs *next;
|
||||||
* 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 },
|
|
||||||
};
|
};
|
||||||
#undef E
|
|
||||||
|
#ifndef EVENT__DISABLE_THREAD_SUPPORT
|
||||||
|
static void *windows_socket_errors_lock_ = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct cached_sock_errs *windows_socket_errors;
|
||||||
|
|
||||||
/** Equivalent to strerror, but for windows socket errors. */
|
/** Equivalent to strerror, but for windows socket errors. */
|
||||||
const char *
|
const char *
|
||||||
evutil_socket_error_to_string(int errcode)
|
evutil_socket_error_to_string(int errcode)
|
||||||
{
|
{
|
||||||
/* XXXX Is there really no built-in function to do this? */
|
struct cached_sock_errs *errs, *newerr;
|
||||||
int i;
|
char *msg = NULL;
|
||||||
for (i=0; windows_socket_errors[i].code >= 0; ++i) {
|
|
||||||
if (errcode == windows_socket_errors[i].code)
|
EVLOCK_LOCK(windows_socket_errors_lock_, 0);
|
||||||
return windows_socket_errors[i].msg;
|
|
||||||
}
|
for (errs = windows_socket_errors; errs != NULL; errs = errs->next)
|
||||||
return strerror(errcode);
|
if (errs->code == errcode) {
|
||||||
|
msg = errs->msg;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
|
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||||||
|
NULL, errcode, 0, (LPTSTR)&msg, 0, NULL))
|
||||||
|
chomp (msg); /* because message has trailing newline */
|
||||||
|
else {
|
||||||
|
size_t len = 50;
|
||||||
|
/* use LocalAlloc because FormatMessage does */
|
||||||
|
msg = LocalAlloc(LMEM_FIXED, len);
|
||||||
|
if (!msg) {
|
||||||
|
msg = "winsock error";
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
evutil_snprintf(msg, len, "winsock error 0x%08x", errcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
newerr = (struct cached_sock_errs *)
|
||||||
|
mm_malloc(sizeof (struct cached_sock_errs));
|
||||||
|
|
||||||
|
if (!newerr) {
|
||||||
|
LocalFree(msg);
|
||||||
|
msg = "winsock error";
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
newerr->code = errcode;
|
||||||
|
newerr->msg = msg;
|
||||||
|
newerr->next = windows_socket_errors;
|
||||||
|
windows_socket_errors = newerr;
|
||||||
|
|
||||||
|
done:
|
||||||
|
EVLOCK_UNLOCK(windows_socket_errors_lock_, 0);
|
||||||
|
|
||||||
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef EVENT__DISABLE_THREAD_SUPPORT
|
||||||
|
int
|
||||||
|
evutil_global_setup_locks_(const int enable_locks)
|
||||||
|
{
|
||||||
|
EVTHREAD_SETUP_GLOBAL_LOCK(windows_socket_errors_lock_, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
evutil_free_sock_err_globals(void)
|
||||||
|
{
|
||||||
|
struct cached_sock_errs *errs, *tofree;
|
||||||
|
|
||||||
|
for (errs = windows_socket_errors; errs != NULL; ) {
|
||||||
|
LocalFree (errs->msg);
|
||||||
|
tofree = errs;
|
||||||
|
errs = errs->next;
|
||||||
|
mm_free (tofree);
|
||||||
|
}
|
||||||
|
|
||||||
|
windows_socket_errors = NULL;
|
||||||
|
|
||||||
|
#ifndef EVENT__DISABLE_THREAD_SUPPORT
|
||||||
|
if (windows_socket_errors_lock_ != NULL) {
|
||||||
|
EVTHREAD_FREE_LOCK(windows_socket_errors_lock_, 0);
|
||||||
|
windows_socket_errors_lock_ = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef EVENT__DISABLE_THREAD_SUPPORT
|
||||||
|
int
|
||||||
|
evutil_global_setup_locks_(const int enable_locks)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
evutil_free_sock_err_globals(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -2529,4 +2587,5 @@ void
|
|||||||
evutil_free_globals_(void)
|
evutil_free_globals_(void)
|
||||||
{
|
{
|
||||||
evutil_free_secure_rng_globals_();
|
evutil_free_secure_rng_globals_();
|
||||||
|
evutil_free_sock_err_globals();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user