Update networking layer w/ CURL and emscripten impl
This commit is contained in:
+361
@@ -0,0 +1,361 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "../curl_setup.h"
|
||||
|
||||
#ifdef HAVE_STRERROR_R
|
||||
# if (!defined(HAVE_POSIX_STRERROR_R) && \
|
||||
!defined(HAVE_GLIBC_STRERROR_R)) || \
|
||||
(defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R))
|
||||
# error "strerror_r MUST be either POSIX, glibc style"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#ifndef WITHOUT_LIBCURL
|
||||
#include <curl/mprintf.h>
|
||||
#define SNPRINTF curl_msnprintf
|
||||
#else
|
||||
/* when built for the test servers */
|
||||
|
||||
/* adjust for old MSVC */
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
||||
#define SNPRINTF _snprintf
|
||||
#else
|
||||
#define SNPRINTF snprintf
|
||||
#endif
|
||||
#endif /* !WITHOUT_LIBCURL */
|
||||
|
||||
#include "winapi.h"
|
||||
#include "strerr.h"
|
||||
/* The last 2 #include files should be in this order */
|
||||
#include "../curl_memory.h"
|
||||
#include "../memdebug.h"
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
/* This is a helper function for curlx_strerror that converts Winsock error
|
||||
* codes (WSAGetLastError) to error messages.
|
||||
* Returns NULL if no error message was found for error code.
|
||||
*/
|
||||
static const char *
|
||||
get_winsock_error(int err, char *buf, size_t len)
|
||||
{
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
const char *p;
|
||||
size_t alen;
|
||||
#endif
|
||||
|
||||
if(!len)
|
||||
return NULL;
|
||||
|
||||
*buf = '\0';
|
||||
|
||||
#ifdef CURL_DISABLE_VERBOSE_STRINGS
|
||||
(void)err;
|
||||
return NULL;
|
||||
#else
|
||||
switch(err) {
|
||||
case WSAEINTR:
|
||||
p = "Call interrupted";
|
||||
break;
|
||||
case WSAEBADF:
|
||||
p = "Bad file";
|
||||
break;
|
||||
case WSAEACCES:
|
||||
p = "Bad access";
|
||||
break;
|
||||
case WSAEFAULT:
|
||||
p = "Bad argument";
|
||||
break;
|
||||
case WSAEINVAL:
|
||||
p = "Invalid arguments";
|
||||
break;
|
||||
case WSAEMFILE:
|
||||
p = "Out of file descriptors";
|
||||
break;
|
||||
case WSAEWOULDBLOCK:
|
||||
p = "Call would block";
|
||||
break;
|
||||
case WSAEINPROGRESS:
|
||||
case WSAEALREADY:
|
||||
p = "Blocking call in progress";
|
||||
break;
|
||||
case WSAENOTSOCK:
|
||||
p = "Descriptor is not a socket";
|
||||
break;
|
||||
case WSAEDESTADDRREQ:
|
||||
p = "Need destination address";
|
||||
break;
|
||||
case WSAEMSGSIZE:
|
||||
p = "Bad message size";
|
||||
break;
|
||||
case WSAEPROTOTYPE:
|
||||
p = "Bad protocol";
|
||||
break;
|
||||
case WSAENOPROTOOPT:
|
||||
p = "Protocol option is unsupported";
|
||||
break;
|
||||
case WSAEPROTONOSUPPORT:
|
||||
p = "Protocol is unsupported";
|
||||
break;
|
||||
case WSAESOCKTNOSUPPORT:
|
||||
p = "Socket is unsupported";
|
||||
break;
|
||||
case WSAEOPNOTSUPP:
|
||||
p = "Operation not supported";
|
||||
break;
|
||||
case WSAEAFNOSUPPORT:
|
||||
p = "Address family not supported";
|
||||
break;
|
||||
case WSAEPFNOSUPPORT:
|
||||
p = "Protocol family not supported";
|
||||
break;
|
||||
case WSAEADDRINUSE:
|
||||
p = "Address already in use";
|
||||
break;
|
||||
case WSAEADDRNOTAVAIL:
|
||||
p = "Address not available";
|
||||
break;
|
||||
case WSAENETDOWN:
|
||||
p = "Network down";
|
||||
break;
|
||||
case WSAENETUNREACH:
|
||||
p = "Network unreachable";
|
||||
break;
|
||||
case WSAENETRESET:
|
||||
p = "Network has been reset";
|
||||
break;
|
||||
case WSAECONNABORTED:
|
||||
p = "Connection was aborted";
|
||||
break;
|
||||
case WSAECONNRESET:
|
||||
p = "Connection was reset";
|
||||
break;
|
||||
case WSAENOBUFS:
|
||||
p = "No buffer space";
|
||||
break;
|
||||
case WSAEISCONN:
|
||||
p = "Socket is already connected";
|
||||
break;
|
||||
case WSAENOTCONN:
|
||||
p = "Socket is not connected";
|
||||
break;
|
||||
case WSAESHUTDOWN:
|
||||
p = "Socket has been shut down";
|
||||
break;
|
||||
case WSAETOOMANYREFS:
|
||||
p = "Too many references";
|
||||
break;
|
||||
case WSAETIMEDOUT:
|
||||
p = "Timed out";
|
||||
break;
|
||||
case WSAECONNREFUSED:
|
||||
p = "Connection refused";
|
||||
break;
|
||||
case WSAELOOP:
|
||||
p = "Loop??";
|
||||
break;
|
||||
case WSAENAMETOOLONG:
|
||||
p = "Name too long";
|
||||
break;
|
||||
case WSAEHOSTDOWN:
|
||||
p = "Host down";
|
||||
break;
|
||||
case WSAEHOSTUNREACH:
|
||||
p = "Host unreachable";
|
||||
break;
|
||||
case WSAENOTEMPTY:
|
||||
p = "Not empty";
|
||||
break;
|
||||
case WSAEPROCLIM:
|
||||
p = "Process limit reached";
|
||||
break;
|
||||
case WSAEUSERS:
|
||||
p = "Too many users";
|
||||
break;
|
||||
case WSAEDQUOT:
|
||||
p = "Bad quota";
|
||||
break;
|
||||
case WSAESTALE:
|
||||
p = "Something is stale";
|
||||
break;
|
||||
case WSAEREMOTE:
|
||||
p = "Remote error";
|
||||
break;
|
||||
case WSAEDISCON:
|
||||
p = "Disconnected";
|
||||
break;
|
||||
/* Extended Winsock errors */
|
||||
case WSASYSNOTREADY:
|
||||
p = "Winsock library is not ready";
|
||||
break;
|
||||
case WSANOTINITIALISED:
|
||||
p = "Winsock library not initialised";
|
||||
break;
|
||||
case WSAVERNOTSUPPORTED:
|
||||
p = "Winsock version not supported";
|
||||
break;
|
||||
|
||||
/* getXbyY() errors (already handled in herrmsg):
|
||||
* Authoritative Answer: Host not found */
|
||||
case WSAHOST_NOT_FOUND:
|
||||
p = "Host not found";
|
||||
break;
|
||||
|
||||
/* Non-Authoritative: Host not found, or SERVERFAIL */
|
||||
case WSATRY_AGAIN:
|
||||
p = "Host not found, try again";
|
||||
break;
|
||||
|
||||
/* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
|
||||
case WSANO_RECOVERY:
|
||||
p = "Unrecoverable error in call to nameserver";
|
||||
break;
|
||||
|
||||
/* Valid name, no data record of requested type */
|
||||
case WSANO_DATA:
|
||||
p = "No data record of requested type";
|
||||
break;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
alen = strlen(p);
|
||||
if(alen < len)
|
||||
strcpy(buf, p);
|
||||
return buf;
|
||||
#endif
|
||||
}
|
||||
#endif /* USE_WINSOCK */
|
||||
|
||||
/*
|
||||
* Our thread-safe and smart strerror() replacement.
|
||||
*
|
||||
* The 'err' argument passed in to this function MUST be a true errno number
|
||||
* as reported on this system. We do no range checking on the number before
|
||||
* we pass it to the "number-to-message" conversion function and there might
|
||||
* be systems that do not do proper range checking in there themselves.
|
||||
*
|
||||
* We do not do range checking (on systems other than Windows) since there is
|
||||
* no good reliable and portable way to do it.
|
||||
*
|
||||
* On Windows different types of error codes overlap. This function has an
|
||||
* order of preference when trying to match error codes:
|
||||
* CRT (errno), Winsock (WSAGetLastError), Windows API (GetLastError).
|
||||
*
|
||||
* It may be more correct to call one of the variant functions instead:
|
||||
* Call Curl_sspi_strerror if the error code is definitely Windows SSPI.
|
||||
* Call curlx_winapi_strerror if the error code is definitely Windows API.
|
||||
*/
|
||||
const char *curlx_strerror(int err, char *buf, size_t buflen)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DWORD old_win_err = GetLastError();
|
||||
#endif
|
||||
int old_errno = errno;
|
||||
char *p;
|
||||
|
||||
if(!buflen)
|
||||
return NULL;
|
||||
|
||||
#ifndef _WIN32
|
||||
DEBUGASSERT(err >= 0);
|
||||
#endif
|
||||
|
||||
*buf = '\0';
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef UNDER_CE
|
||||
/* 'sys_nerr' is the maximum errno number, it is not widely portable */
|
||||
if(err >= 0 && err < sys_nerr)
|
||||
SNPRINTF(buf, buflen, "%s", sys_errlist[err]);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if(
|
||||
#ifdef USE_WINSOCK
|
||||
!get_winsock_error(err, buf, buflen) &&
|
||||
#endif
|
||||
!curlx_get_winapi_error((DWORD)err, buf, buflen))
|
||||
SNPRINTF(buf, buflen, "Unknown error %d (%#x)", err, err);
|
||||
}
|
||||
#else /* !_WIN32 */
|
||||
|
||||
#if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R)
|
||||
/*
|
||||
* The POSIX-style strerror_r() may set errno to ERANGE if insufficient
|
||||
* storage is supplied via 'strerrbuf' and 'buflen' to hold the generated
|
||||
* message string, or EINVAL if 'errnum' is not a valid error number.
|
||||
*/
|
||||
if(strerror_r(err, buf, buflen) &&
|
||||
buflen > sizeof("Unknown error ") + 20) {
|
||||
if(buf[0] == '\0')
|
||||
SNPRINTF(buf, buflen, "Unknown error %d", err);
|
||||
}
|
||||
#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
|
||||
/*
|
||||
* The glibc-style strerror_r() only *might* use the buffer we pass to
|
||||
* the function, but it always returns the error message as a pointer,
|
||||
* so we must copy that string unconditionally (if non-NULL).
|
||||
*/
|
||||
{
|
||||
char buffer[256];
|
||||
char *msg = strerror_r(err, buffer, sizeof(buffer));
|
||||
if(msg && buflen > 1)
|
||||
SNPRINTF(buf, buflen, "%s", msg);
|
||||
else if(buflen > sizeof("Unknown error ") + 20)
|
||||
SNPRINTF(buf, buflen, "Unknown error %d", err);
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* !checksrc! disable BANNEDFUNC 1 */
|
||||
const char *msg = strerror(err);
|
||||
if(msg && buflen > 1)
|
||||
SNPRINTF(buf, buflen, "%s", msg);
|
||||
else if(buflen > sizeof("Unknown error ") + 20)
|
||||
SNPRINTF(buf, buflen, "Unknown error %d", err);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/* strip trailing '\r\n' or '\n'. */
|
||||
p = strrchr(buf, '\n');
|
||||
if(p && (p - buf) >= 2)
|
||||
*p = '\0';
|
||||
p = strrchr(buf, '\r');
|
||||
if(p && (p - buf) >= 1)
|
||||
*p = '\0';
|
||||
|
||||
if(errno != old_errno)
|
||||
CURL_SETERRNO(old_errno);
|
||||
|
||||
#ifdef _WIN32
|
||||
if(old_win_err != GetLastError())
|
||||
SetLastError(old_win_err);
|
||||
#endif
|
||||
|
||||
return buf;
|
||||
}
|
||||
Reference in New Issue
Block a user