/*<ATGCOPYRIGHT>
 * Copyright (C) 2001 Art Technology Group, Inc.
 * All Rights Reserved.  No use, copying or distribution of this
 * work may be made except in accordance with a valid license
 * agreement from Art Technology Group.  This notice must be
 * included on all copies, modifications and derivatives of this
 * work.
 *
 * Art Technology Group (ATG) MAKES NO REPRESENTATIONS OR WARRANTIES 
 * ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, 
 * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ATG SHALL NOT BE
 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, 
 * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 *
 * "Dynamo" is a trademark of Art Technology Group, Inc.
 </ATGCOPYRIGHT>*/

/*
 * sockerrs.c -- provides a method for getting human-readable strings from 
 *  error codes (errno on Unix, WSAGetLastError on NT)
 */

#ifdef WIN32
/* NT */
#include <windows.h>
#else
/* UNIXEN */
#include <string.h>
#endif

#include "sockerrs.h"

/*
 * Return the appropriate message string for the error
 * pErrno is errno on Unix, the return from WSAGetLastError() on NT
 */
const char *getMessageStringForSocketError(int pErrno)
{
#if (defined (WIN32))
    char *message;
    switch (pErrno) {
    case WSAEINTR:
        message = "A blocking operation was cancelled (WASEINTR)";
        break;
    case WSAEBADF:
        message = "Bad file number (WSAEBADF)";
        break;
    case WSAEACCES:
        message =
            "Permission to access socket forbidden by its access permissions (WSAEACCES)";
        break;
    case WSAEFAULT:
        message =
            "Invalid pointer address specified in function call (WSAEFAULT)";
        break;
    case WSAEINVAL:
        message = "Invalid argument passed to a function (WSAEINVAL)";
        break;
    case WSAEMFILE:
        message = "Too many open sockets (WSAEMFILE)";
        break;
    case WSAEWOULDBLOCK:
        message = "Resources temporarily unavailable (WSAEWOULDBLOCK)";
        break;
    case WSAEINPROGRESS:
        message = "Blocking operation now in progress (WSAEINPROGRESS)";
        break;
    case WSAEALREADY:
        message =
            "Operation already in progress on a non-binding socket (WSAEALREADY)";
        break;
    case WSAENOTSOCK:
        message =
            "Socket operation attempted on a non-socket (WSAENOTSOCK)";
        break;
    case WSAEDESTADDRREQ:
        message = "Destination address required (WSAEDESTADDRREQ)";
        break;
    case WSAEMSGSIZE:
        message = "Message too long (WSAEMSGSIZE)";
        break;
    case WSAEPROTOTYPE:
        message = "Protocol wrong type for socket (WSAEPROTOTYPE)";
        break;
    case WSAENOPROTOOPT:
        message =
            "Unknown, invalid, or unsupported protocol option or level was specified (WSAENOPROTOOPT)";
        break;
    case WSAEPROTONOSUPPORT:
        message = "Protocol not supported (WSAEPROTONOSUPPORT)";
        break;
    case WSAESOCKTNOSUPPORT:
        message =
            "Socket type not supported in the address family (WSAESOCKTNOSUPPORT)";
        break;
    case WSAEOPNOTSUPP:
        message = "Operation not supported on socket (WSAEOPNOTSUPP)";
        break;
    case WSAEPFNOSUPPORT:
        message = "Protocol family not supported (WSAEPFNOSUPPORT)";
        break;
    case WSAEAFNOSUPPORT:
        message =
            "Address family not supported by protocol family (WSAEAFNOSUPPORT)";
        break;
    case WSAEADDRINUSE:
        message = "Address already in use (WSAEADDRINUSE)";
        break;
    case WSAEADDRNOTAVAIL:
        message = "Cannot assign requested address (WSAEADDRNOTAVAIL)";
        break;
    case WSAENETDOWN:
        message = "Network is down (WSAENETDOWN)";
        break;
    case WSAENETUNREACH:
        message = "Network is unreachable (WSAENETUNREACH)";
        break;
    case WSAENETRESET:
        message = "Network dropped connection on reset (WSAENETRESET)";
        break;
    case WSAECONNABORTED:
        message = "Software caused connection abort (WSAECONNABORTED)";
        break;
    case WSAECONNRESET:
        message = "Connection reset by peer (WSAECONNRESET)";
        break;
    case WSAENOBUFS:
        message = "No buffer space available (WSAENOBUFS)";
        break;
    case WSAEISCONN:
        message = "Socket is already connected (WSAEISCONN)";
        break;
    case WSAENOTCONN:
        message = "Socket is not connected (WSAENOTCONN)";
        break;
    case WSAESHUTDOWN:
        message = "Cannot send after socket shutdown (WSAESHUTDOWN)";
        break;
    case WSAETOOMANYREFS:
        message = "Too many references, cannot splice (WSAETOOMANYREFS)";
        break;
    case WSAETIMEDOUT:
        message = "Connection timed out (WSAETIMEDOUT)";
        break;
    case WSAECONNREFUSED:
        message = "Connection refused (WSAECONNREFUSED)";
        break;
    case WSAELOOP:
        message = "Too many levles of symbolic links (WSAELOOP)";
        break;
    case WSAENAMETOOLONG:
        message = "File name is too long (WSAENAMETOOLONG)";
        break;
    case WSAEHOSTDOWN:
        message = "Host is down (WSAEHOSTDOWN)";
        break;
    case WSAEHOSTUNREACH:
        message = "No route to host (WSAEHOSTUNREACH)";
        break;
    case WSAENOTEMPTY:
        message = "Directory not empty (WSAENOTEMPTY)";
        break;
    case WSAEPROCLIM:
        message = "Too many processes (WSAEPROCLIM)";
        break;
    case WSAEUSERS:
        message = "Too many users (WSAEUSERS)";
        break;
    case WSAEDQUOT:
        message = "Disc quota exceeded (WSAEDQUOT)";
        break;
    case WSAESTALE:
        message = "Stale NFS file handle (WSAESTALE)";
        break;
    case WSAEREMOTE:
        message = "Too many levels of remote in path (WSAEREMOTE)";
        break;
    case WSAEDISCON:
        message = "Graceful shutdown in progress (WSAEDISCON)";
        break;
    case WSASYSNOTREADY:
        message = "Network subsystem is unavailable (WSASYSNOTREADY)";
        break;
    case WSAVERNOTSUPPORTED:
        message = "Winsock.dll version out of range (WSAVERNOTSUPPORTED)";
        break;
    case WSANOTINITIALISED:
        message =
            "Successful WSASTARTUP not yet performed (WSANOTINITIALISED)";
        break;
    case 10109:                /* case WSATYPE_NOT_FOUND */
        message = "Class type not found (WSATYPE_NOT_FOUND)";
        break;
    case WSAHOST_NOT_FOUND:
        message = "Host not found (WSA_HOST_NOT_FOUND)";
        break;
    case WSATRY_AGAIN:
        message = "Non-authoritative host not found (WSATRY_AGAIN)";
        break;
    case WSANO_RECOVERY:
        message = "Non-recoverable error (WSANO_RECOVERY)";
        break;
    case WSANO_DATA:
        message =
            "Valid name, no data record or requested name (WSANO_DATA)";
        break;
    default:
        message = "WSA error not recognized";
    }
    return (message);
#else
    if (pErrno == 0) {
        const char *message = "Uninterpretable socket error occurred.";
        return message;
    } else {
        return (strerror(pErrno));
    }
#endif
}
