#ifndef _H_SOCKSPLUSPLUS
#define _H_SOCKSPLUSPLUS
#include "ip++.h"
#include <Security/threading.h>
#include <Security/globalizer.h>
using namespace UnixPlusPlus;
namespace Security {
namespace IPPlusPlus {
class SocksServerSocket;
class SocksClientSocket;
class SocksServer {
public:
class Support; friend class Support;
private:
struct Global {
mutable Mutex lock; SocksServer *mServer; ThreadNexus<IPAddress> lastConnected;
Global() : mServer(NULL) { }
void server(SocksServer *srv) { StLock<Mutex> _(lock); mServer = srv; }
SocksServer *server() const { StLock<Mutex> _(lock); return mServer; }
};
static ModuleNexus<Global> global;
public:
typedef unsigned int Version;
static SocksServer *make(Version version, const IPSockAddress &addr);
const IPSockAddress &address() const { return mServerAddress; }
Version version() const { return mVersion; }
public:
static SocksServer *defaultServer() { return global().server(); }
static void defaultServer(SocksServer *server) { global().server(server); }
protected:
virtual void connect(SocksClientSocket &me, const IPSockAddress &peer) = 0;
virtual void connect(SocksClientSocket &me, const Host &host, IPPort port) = 0;
virtual void bind(SocksServerSocket &me, const IPAddress &peer, IPPort port) = 0;
virtual void receive(SocksServerSocket &me, SocksClientSocket &receiver) = 0;
SocksServer(Version v, const IPSockAddress &addr) : mVersion(v), mServerAddress(addr) { }
protected:
Version mVersion;
IPSockAddress mServerAddress;
protected:
class Support {
public:
SocksServer *server() const { return mServer; }
void server(SocksServer *srv) { mServer = srv; }
IPSockAddress localAddress(const Socket &me) const;
IPSockAddress peerAddress(const Socket &me) const;
protected:
Support() : mServer(defaultServer()) { }
void connect(SocksClientSocket &me, const IPSockAddress &peer)
{ mServer->connect(me, peer); }
void connect(SocksClientSocket &me, const Host &host, IPPort port)
{ mServer->connect(me, host, port); }
void bind(SocksServerSocket &me, const IPAddress &peer, IPPort port)
{ mServer->bind(me, peer, port); }
void receive(SocksServerSocket &me, SocksClientSocket &receiver)
{ mServer->receive(me, receiver); }
void lastConnected(IPAddress addr) { global().lastConnected() = addr; }
IPAddress lastConnected() const { return global().lastConnected(); }
public:
SocksServer *mServer; IPSockAddress mLocalAddress; IPSockAddress mPeerAddress; };
};
class SocksClientSocket : public TCPClientSocket, public SocksServer::Support {
public:
SocksClientSocket() { }
SocksClientSocket(const IPSockAddress &peer) { open(peer); }
SocksClientSocket(const IPAddress &addr, IPPort port) { open(addr, port); }
SocksClientSocket(const Host &host, IPPort port) { open(host, port); }
void open(const IPSockAddress &peer);
void open(const IPAddress &addr, IPPort port);
void open(const Host &host, IPPort port);
IPSockAddress localAddress() const { return Support::localAddress(*this); }
IPSockAddress peerAddress() const { return Support::peerAddress(*this); }
public:
void setFd(int fd, const IPSockAddress &local, const IPSockAddress &peer);
};
class SocksServerSocket : public TCPServerSocket, public SocksServer::Support {
public:
SocksServerSocket() { }
SocksServerSocket(const IPSockAddress &local, int = 1) { open(local); }
SocksServerSocket(IPPort port, int = 1) { open(port); }
void open(const IPSockAddress &local, int = 1);
void open(IPPort port = 0, int = 1)
{ open(IPSockAddress(IPAddress::any, port)); }
void receive(SocksClientSocket &client);
IPSockAddress localAddress() const { return Support::localAddress(*this); }
IPSockAddress peerAddress() const { return Support::peerAddress(*this); }
void setMainConnection(TCPClientSocket &main)
{ mConnectionPeer = main.peerAddress().address(); }
private:
IPAddress mConnectionPeer;
private:
void operator () (TCPClientSocket &newClient); };
} }
#endif //_H_IPPLUSPLUS