// **********************************************************************
//
// Copyright (c) 1998
// Object-Oriented Concepts, Inc.
// Billerica, MA, USA
//
// Copyright (c) 1998
// Object-Oriented Concepts GmbH
// Ettlingen, Germany
//
// All Rights Reserved
//
// **********************************************************************

#ifndef OB_NET_H
#define OB_NET_H

#ifdef HAVE_WINSOCK_H

#   include <winsock.h>

inline int OBGetError()
{
    return WSAGetLastError();
}

inline void OBSetError(int err)
{
    WSASetLastError(err);
}

inline int OBCreateSocket()
{
    return socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
}

inline int OBCloseSocket(int fd)
{
    return closesocket(fd);
}

inline bool OBConnectionDown()
{
    return OBGetError() == WSAECONNRESET;
}

inline bool OBWouldBlock()
{
    return OBGetError() == WSAEWOULDBLOCK;
}

inline bool OBInProgress()
{
    return OBGetError() == WSAEWOULDBLOCK;
}

inline bool OBIsInterrupted()
{
    return OBGetError() == WSAEINTR;
}

inline void OBSetBlock(int fd)
{
    unsigned long arg = 0;
    ioctlsocket(fd, FIONBIO, &arg);
}

inline void OBSetNoBlock(int fd)
{
    unsigned long arg = 1;
    ioctlsocket(fd, FIONBIO, &arg);
}

#else

#   include <stdlib.h>
#   include <stdio.h>
#   include <unistd.h>
#   include <errno.h>
#   include <signal.h>
#   include <fcntl.h>
#   include <sys/types.h>
#   include <sys/param.h>
#   include <sys/time.h>
#   include <sys/socket.h>
#   ifdef HAVE_BSTRING_H
#       include <bstring.h>
#   endif
#   ifdef HAVE_STRINGS_H
#       include <strings.h>
#   endif
#   ifdef HAVE_SYS_SELECT_H
/*#	include <sys/select.h>*/
#   endif
#   include <netinet/in.h>
#   include <netinet/tcp.h>
#   include <netdb.h>
#   include <arpa/inet.h>

inline int OBGetError()
{
    return errno;
}

inline void OBSetError(int err)
{
    errno = err;
}

inline int OBCreateSocket()
{
    return socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
}

inline int OBCloseSocket(int fd)
{
    return close(fd);
}

inline bool OBConnectionDown()
{
    return OBGetError() == ECONNRESET || OBGetError() == EPIPE;
}

inline bool OBWouldBlock()
{
    return OBGetError() == EAGAIN || OBGetError() == EWOULDBLOCK;
}

inline bool OBInProgress()
{
    return OBGetError() == EINPROGRESS;
}

inline bool OBIsInterrupted()
{
    return OBGetError() == EINTR;
}

inline void OBSetBlock(int fd)
{
    int flags = fcntl(fd, F_GETFL);
    flags &= ~O_NONBLOCK;
    fcntl(fd, F_SETFL, flags);
}

inline void OBSetNoBlock(int fd)
{
    int flags = fcntl(fd, F_GETFL);
    flags |= O_NONBLOCK;
    fcntl(fd, F_SETFL, flags);
}

#endif

#ifdef HAVE_NO_GETHOSTNAME_PROTOTYPE
extern "C"
{
    int gethostname(char*,  int);
}
#endif

#ifdef HAVE_NO_H_ERRNO_DECLARATION
extern "C"
{
    extern int h_errno;
}
#endif

#ifndef MAXHOSTNAMELEN
#   define MAXHOSTNAMELEN 1024
#endif

#ifndef IPPORT_MAXPORT
#   define IPPORT_MAXPORT 65535
#endif

#ifndef IPPORT_USERRESERVED
#   define IPPORT_USERRESERVED 5000
#endif

#ifndef INADDR_NONE
#   define INADDR_NONE ((unsigned long int) 0xffffffff)
#endif

#define OB_GETHOSTBYNAME_RETRY 3

//
// Get an error message for a given errno (hides differences between
// Unix and NT)
//
const char* OBLastError(); // For "regular" errors
const char* OBLastHError(); // For gethostbyname()-related errors

//
// Get internet address
//
void OBGetInAddr(const char*, struct sockaddr_in&);

#endif
