#ifndef _H_IPPLUSPLUS
#define _H_IPPLUSPLUS
#include "unix++.h"
#include "timeflow.h"
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <cstdio>
#include <cstdarg>
#include <map>
using namespace UnixPlusPlus;
namespace Security {
namespace IPPlusPlus {
class Host;
typedef uint16 IPPort;
class IPAddress : public in_addr {
public:
IPAddress() { s_addr = htonl(INADDR_ANY); }
IPAddress(const struct in_addr &addr) { s_addr = addr.s_addr; }
explicit IPAddress(uint32 addr) { s_addr = htonl(addr); }
IPAddress(const char *s);
operator uint32 () const { return ntohl(s_addr); }
operator string () const;
public:
bool operator == (const IPAddress &other) const { return s_addr == other.s_addr; }
bool operator != (const IPAddress &other) const { return s_addr != other.s_addr; }
bool operator < (const IPAddress &other) const { return s_addr < other.s_addr; }
operator bool () const { return s_addr != htonl(INADDR_ANY); }
bool operator ! () const { return s_addr == htonl(INADDR_ANY); }
public:
static const IPAddress &any;
};
class IPSockAddress : public sockaddr_in {
public:
IPSockAddress();
IPSockAddress(const struct sockaddr_in &sockaddr) { *(sockaddr_in *)this = sockaddr; }
IPSockAddress(const IPAddress &addr, IPPort port);
IPAddress address() const { return sin_addr; }
void address(IPAddress addr) { sin_addr = addr; }
IPPort port() const { return ntohs(sin_port); }
void port(IPPort p) { sin_port = htons(p); }
operator string () const;
operator struct sockaddr * ()
{ return reinterpret_cast<struct sockaddr *>(this); }
operator const struct sockaddr * () const
{ return reinterpret_cast<const struct sockaddr *>(this); }
IPSockAddress defaults(const IPSockAddress &defaultAddr) const;
IPSockAddress defaults(const IPAddress &defaultAddr, IPPort defaultPort = 0) const;
IPSockAddress defaults(IPPort defaultPort) const;
};
class UNSockAddress : public sockaddr_un {
public:
UNSockAddress();
UNSockAddress(const char *path);
UNSockAddress(const std::string &path);
string path() const;
operator string () const { return path(); }
operator struct sockaddr * ()
{ return reinterpret_cast<struct sockaddr *>(this); }
operator const struct sockaddr * () const
{ return reinterpret_cast<const struct sockaddr *>(this); }
};
class Socket : public FileDesc {
public:
Socket() { }
explicit Socket(int domain, int type, int protocol = 0);
explicit Socket(int type);
Socket &operator = (int fd) { setFd(fd); return *this; }
void open(int domain, int type, int protocol = 0);
void open(int type) { open(AF_INET, type, 0); }
void bind(const IPSockAddress &addr); void bind(const IPAddress &addr = IPAddress::any, IPPort port = 0);
void bind(const UNSockAddress &addr); void listen(int backlog = 1);
void accept(Socket &s);
void accept(Socket &s, IPSockAddress &peer);
void accept(Socket &s, UNSockAddress &peer);
bool connect(const struct sockaddr *peer);
bool connect(const IPSockAddress &peer);
bool connect(const IPAddress &addr, IPPort port);
bool connect(const UNSockAddress &peer);
void connect(const Host &host, IPPort port); void shutdown(int type);
enum { shutdownRead = 0, shutdownWrite = 1, shutdownBoth = 2 };
IPSockAddress localAddress() const;
IPSockAddress peerAddress() const;
void setOption(const void *value, int length, int name, int level = SOL_SOCKET) const;
void getOption(void *value, int &length, int name, int level = SOL_SOCKET) const;
template <class T> void setOption(const T &value, int name, int level = SOL_SOCKET) const
{ setOption(&value, sizeof(value), name, level); }
template <class T> T getOption(int name, int level = SOL_SOCKET) const
{
T value; int length = sizeof(value);
getOption(&value, length, name, level);
assert(length == sizeof(value));
return value;
}
int type() const { return getOption<int>(SO_TYPE); }
int error() const { return getOption<int>(SO_ERROR); }
public:
#if defined(SOMAXCONN)
static const int listenMaxQueue = SOMAXCONN;
#else
static const int listenMaxQueue = 5; #endif
protected:
void prepare(int fdFlags, int domain, int type, int protocol = 0);
};
class TCPClientSocket : public Socket {
NOCOPY(TCPClientSocket)
public:
TCPClientSocket() { }
~TCPClientSocket();
#if BUG_GCC
void open(int type, int protocol = 0) { Socket::open(type, protocol); }
#else
using Socket::open;
#endif
void open(const IPSockAddress &peer, int fdFlags = 0);
void open(const IPAddress &addr, IPPort port, int fdFlags = 0);
void open(const Host &host, IPPort port, int fdFlags = 0);
TCPClientSocket(const IPSockAddress &peer, int fdFlags = 0)
{ open(peer, fdFlags); }
TCPClientSocket(const IPAddress &addr, IPPort port, int fdFlags = 0)
{ open(addr, port, fdFlags); }
TCPClientSocket(const Host &host, IPPort port, int fdFlags = 0)
{ open(host, port, fdFlags); }
protected: void setFd(int fd) { Socket::setFd(fd); }
private:
TCPClientSocket(int sockfd);
};
class TCPServerSocket : public Socket {
NOCOPY(TCPServerSocket)
public:
TCPServerSocket() { }
~TCPServerSocket();
void open(const IPSockAddress &local, int depth = 1);
void open(IPPort port = 0, int depth = 1)
{ open(IPSockAddress(IPAddress::any, port), depth); }
TCPServerSocket(const IPSockAddress &local, int depth = 1) { open(local, depth); }
TCPServerSocket(IPPort port, int depth = 1) { open(port, depth); }
void operator () (TCPClientSocket &newClient); void receive(TCPClientSocket &client); };
} }
#endif //_H_IPPLUSPLUS