barrier/lib/net/CNetwork.h

316 lines
9.6 KiB
C++

/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2002 Chris Schoeneman
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef CNETWORK_H
#define CNETWORK_H
#include "BasicTypes.h"
#include "CString.h"
#include "stdvector.h"
// Darwin is so unsure what to use for socklen_t it makes us choose
#if defined(__APPLE__)
# if !defined(_BSD_SOCKLEN_T_)
# define _BSD_SOCKLEN_T_ int
# endif
#endif
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#if HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#if HAVE_POLL
# include <sys/poll.h>
#endif
#if WINDOWS_LIKE
// declare no functions in winsock2
# define INCL_WINSOCK_API_PROTOTYPES 0
# define INCL_WINSOCK_API_TYPEDEFS 0
# include <winsock2.h>
typedef int ssize_t;
#else
# undef FAR
# undef PASCAL
# define FAR
# define PASCAL
#endif
#if UNIX_LIKE
# include <netinet/in.h>
# include <netdb.h>
# include <errno.h>
#endif
//! Networking functions
class CNetwork {
public:
// platform dependent types
#if WINDOWS_LIKE
typedef SOCKET Socket;
typedef struct sockaddr Address;
typedef int AddressLength;
typedef short AddressType;
typedef struct in_addr InternetAddress;
#elif UNIX_LIKE
typedef int Socket;
typedef struct sockaddr Address;
typedef socklen_t AddressLength;
typedef int AddressType;
typedef struct in_addr InternetAddress;
#endif
#if WINDOWS_LIKE || !HAVE_POLL
class PollEntry {
public:
Socket fd;
short events;
short revents;
};
enum {
kPOLLIN = 1,
kPOLLOUT = 2,
kPOLLERR = 4,
kPOLLNVAL = 8
};
#else
typedef struct pollfd PollEntry;
enum {
kPOLLIN = POLLIN,
kPOLLOUT = POLLOUT,
kPOLLERR = POLLERR,
kPOLLNVAL = POLLNVAL
};
#endif
//! Host name information
class CHostInfo {
public:
CHostInfo() { }
CHostInfo(const struct hostent*);
void swap(CHostInfo&);
public:
typedef std::vector<CString> AliasList;
typedef std::vector<const char*> AddressList;
CString m_name;
AliasList m_aliases;
AddressType m_addressType;
int m_addressLength;
AddressList m_addresses;
private:
std::string m_addressData;
};
//! Network service information
class CServiceInfo {
public:
CServiceInfo() { }
CServiceInfo(const struct servent*);
void swap(CServiceInfo&);
public:
typedef std::vector<CString> AliasList;
CString m_name;
AliasList m_aliases;
int m_port;
CString m_protocol;
};
//! Network protocol information
class CProtocolInfo {
public:
CProtocolInfo() { }
CProtocolInfo(const struct protoent*);
void swap(CProtocolInfo&);
public:
typedef std::vector<CString> AliasList;
CString m_name;
AliasList m_aliases;
int m_protocol;
};
//! @name manipulators
//@{
//! Initialize network subsystem
/*!
This \b must be called before any other calls to the network subsystem.
*/
static void init();
//! Clean up network subsystem
/*!
This should be called when the network subsystem is no longer needed
and no longer in use.
*/
static void cleanup();
// byte swapping functions
//! Swap bytes to network order
static UInt32 swaphtonl(UInt32 hostlong);
//! Swap bytes to network order
static UInt16 swaphtons(UInt16 hostshort);
//! Swap bytes to host order
static UInt32 swapntohl(UInt32 netlong);
//! Swap bytes to host order
static UInt16 swapntohs(UInt16 netshort);
//@}
//! @name constants
//@{
//! The error type
static const int Error;
//! The non-socket
static const Socket Null;
// getsockerror() constants
enum {
#if WINDOWS_LIKE
kEADDRINUSE = WSAEADDRINUSE,
kECONNECTING = WSAEWOULDBLOCK,
kEINTR = WSAEINTR,
#elif UNIX_LIKE
kEADDRINUSE = EADDRINUSE,
kECONNECTING = EINPROGRESS,
kEINTR = EINTR,
#endif
kNone = 0
};
// gethosterror() constants
enum {
#if WINDOWS_LIKE
kHOST_NOT_FOUND = WSAHOST_NOT_FOUND,
kNO_DATA = WSANO_DATA,
kNO_RECOVERY = WSANO_RECOVERY,
kTRY_AGAIN = WSATRY_AGAIN,
#elif UNIX_LIKE
kHOST_NOT_FOUND = HOST_NOT_FOUND,
kNO_DATA = NO_DATA,
kNO_RECOVERY = NO_RECOVERY,
kTRY_AGAIN = TRY_AGAIN,
#endif
kHOST_OK = 0
};
//@}
// socket interface (only available after init())
static Socket (PASCAL FAR *accept)(Socket s, Address FAR *addr, AddressLength FAR *addrlen);
static int (PASCAL FAR *bind)(Socket s, const Address FAR *addr, AddressLength namelen);
static int (PASCAL FAR *close)(Socket s);
static int (PASCAL FAR *connect)(Socket s, const Address FAR *name, AddressLength namelen);
static int (PASCAL FAR *ioctl)(Socket s, int cmd, void FAR *);
static int (PASCAL FAR *getpeername)(Socket s, Address FAR *name, AddressLength FAR * namelen);
static int (PASCAL FAR *getsockname)(Socket s, Address FAR *name, AddressLength FAR * namelen);
static int (PASCAL FAR *getsockopt)(Socket s, int level, int optname, void FAR * optval, AddressLength FAR *optlen);
static int PASCAL FAR inet_aton(const char FAR * cp, InternetAddress FAR * addr);
static CString PASCAL FAR inet_ntoa(struct in_addr in);
static int (PASCAL FAR *listen)(Socket s, int backlog);
static ssize_t (PASCAL FAR *read)(Socket s, void FAR * buf, size_t len);
static ssize_t (PASCAL FAR *recv)(Socket s, void FAR * buf, size_t len, int flags);
static ssize_t (PASCAL FAR *recvfrom)(Socket s, void FAR * buf, size_t len, int flags, Address FAR *from, AddressLength FAR * fromlen);
static int (PASCAL FAR *poll)(PollEntry[], int nfds, int timeout);
static ssize_t (PASCAL FAR *send)(Socket s, const void FAR * buf, size_t len, int flags);
static ssize_t (PASCAL FAR *sendto)(Socket s, const void FAR * buf, size_t len, int flags, const Address FAR *to, AddressLength tolen);
static int (PASCAL FAR *setsockopt)(Socket s, int level, int optname, const void FAR * optval, AddressLength optlen);
static int (PASCAL FAR *shutdown)(Socket s, int how);
static Socket (PASCAL FAR *socket)(int af, int type, int protocol);
static ssize_t (PASCAL FAR *write)(Socket s, const void FAR * buf, size_t len);
static int (PASCAL FAR *gethostname)(char FAR * name, int namelen);
static int PASCAL FAR gethostbyaddr(CHostInfo* hostinfo, const char FAR * addr, int len, int type);
static int PASCAL FAR gethostbyname(CHostInfo* hostinfo, const char FAR * name);
static int PASCAL FAR getservbyport(CServiceInfo* servinfo, int port, const char FAR * proto);
static int PASCAL FAR getservbyname(CServiceInfo* servinfo, const char FAR * name, const char FAR * proto);
static int PASCAL FAR getprotobynumber(CProtocolInfo* protoinfo, int proto);
static int PASCAL FAR getprotobyname(CProtocolInfo* protoinfo, const char FAR * name);
static int (PASCAL FAR *getsockerror)(void);
// convenience functions (only available after init())
//! Set socket to (non-)blocking operation
static int PASCAL FAR setblocking(CNetwork::Socket s, bool blocking);
//! Turn Nagle algorithm on or off on socket
/*!
Set socket to send messages immediately (true) or to collect small
messages into one packet (false).
*/
static int PASCAL FAR setnodelay(CNetwork::Socket s, bool nodelay);
private:
#if WINDOWS_LIKE
#define SELECT_TYPE_ARG1 int
#define SELECT_TYPE_ARG234 (fd_set *)
#define SELECT_TYPE_ARG5 (struct timeval *)
static void init2(HMODULE);
static ssize_t PASCAL FAR read2(Socket s, void FAR * buf, size_t len);
static ssize_t PASCAL FAR write2(Socket s, const void FAR * buf, size_t len);
static int (PASCAL FAR *WSACleanup)(void);
static int (PASCAL FAR *__WSAFDIsSet)(CNetwork::Socket, fd_set FAR *);
static int (PASCAL FAR *select)(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, const struct timeval FAR *timeout);
static char FAR * (PASCAL FAR *inet_ntoa_n)(struct in_addr in);
static unsigned long (PASCAL FAR *inet_addr_n)(const char FAR * cp);
static struct hostent FAR * (PASCAL FAR *gethostbyaddr_n)(const char FAR * addr, int len, int type);
static struct hostent FAR * (PASCAL FAR *gethostbyname_n)(const char FAR * name);
static struct servent FAR * (PASCAL FAR *getservbyport_n)(int port, const char FAR * proto);
static struct servent FAR * (PASCAL FAR *getservbyname_n)(const char FAR * name, const char FAR * proto);
static struct protoent FAR * (PASCAL FAR *getprotobynumber_n)(int proto);
static struct protoent FAR * (PASCAL FAR *getprotobyname_n)(const char FAR * name);
#endif
#if UNIX_LIKE
static int PASCAL FAR gethostname2(char FAR * name, int namelen);
static int PASCAL FAR getsockerror2(void);
#endif
#if WINDOWS_LIKE || UNIX_LIKE
/* FIXME -- reentrant netdb stuff
create classes for hostent, servent, protoent.
each class can clean itself up automatically.
inside CNetwork we'll convert from netdb structs to classes.
clients will pass a class pointer which CNetwork will assign to (or swap into).
won't need free...() functions to clean up structs.
each class should know how to copy from respective netdb struct.
will need to fix CNetworkAddress to use classes.
*/
static void copyhostent(struct hostent FAR * dst, const struct hostent FAR * src);
static void copyservent(struct servent FAR * dst, const struct servent FAR * src);
static void copyprotoent(struct protoent FAR * dst, const struct protoent FAR * src);
static void freehostent(struct hostent FAR * ent);
static void freeservent(struct servent FAR * ent);
static void freeprotoent(struct protoent FAR * ent);
#endif
#if WINDOWS_LIKE || !HAVE_POLL
static int PASCAL FAR poll2(PollEntry[], int nfds, int timeout);
#endif
};
#endif