/// \file socket.h /// A handy Socket wrapper library. /// Written by Jaron Vietor in 2010 for DDVTech #pragma once #include #include #include #include #include #include #include #include #include #include #include #include //for being friendly with Socket::Connection down below namespace Buffer { class user; } ///Holds Socket tools. namespace Socket { /// A buffer made out of std::string objects that can be efficiently read from and written to. class Buffer { private: std::deque data; public: unsigned int size(); unsigned int bytes(unsigned int max); void append(const std::string & newdata); void append(const char * newdata, const unsigned int newdatasize); void prepend(const std::string & newdata); void prepend(const char * newdata, const unsigned int newdatasize); std::string & get(); bool available(unsigned int count); std::string remove(unsigned int count); std::string copy(unsigned int count); void clear(); }; //Buffer /// This class is for easy communicating through sockets, either TCP or Unix. class Connection { private: int sock; ///< Internally saved socket number. int pipes[2]; ///< Internally saved file descriptors for pipe socket simulation. std::string remotehost; ///< Stores remote host address. unsigned int up; unsigned int down; long long int conntime; Buffer downbuffer; ///< Stores temporary data coming in. int iread(void * buffer, int len, int flags = 0); ///< Incremental read call. unsigned int iwrite(const void * buffer, int len); ///< Incremental write call. bool iread(Buffer & buffer, int flags = 0); ///< Incremental write call that is compatible with Socket::Buffer. bool iwrite(std::string & buffer); ///< Write call that is compatible with std::string. public: //friends friend class ::Buffer::user; //constructors Connection(); ///< Create a new disconnected base socket. Connection(int sockNo); ///< Create a new base socket. Connection(std::string hostname, int port, bool nonblock); ///< Create a new TCP socket. Connection(std::string adres, bool nonblock = false); ///< Create a new Unix Socket. Connection(int write, int read); ///< Simulate a socket using two file descriptors. //generic methods void close(); ///< Close connection. void drop(); ///< Close connection without shutdown. void setBlocking(bool blocking); ///< Set this socket to be blocking (true) or nonblocking (false). bool isBlocking(); ///< Check if this socket is blocking (true) or nonblocking (false). std::string getHost() const; ///< Gets hostname for connection, if available. std::string getBinHost(); void setHost(std::string host); ///< Sets hostname for connection manually. int getSocket(); ///< Returns internal socket number. int getPureSocket(); ///< Returns non-piped internal socket number. std::string getError(); ///< Returns a string describing the last error that occured. bool connected() const; ///< Returns the connected-state for this socket. bool isAddress(std::string addr); //buffered i/o methods bool spool(); ///< Updates the downbufferinternal variables. bool peek(); ///< Clears the downbuffer and fills it with peek Buffer & Received(); ///< Returns a reference to the download buffer. void SendNow(const std::string & data); ///< Will not buffer anything but always send right away. Blocks. void SendNow(const char * data); ///< Will not buffer anything but always send right away. Blocks. void SendNow(const char * data, size_t len); ///< Will not buffer anything but always send right away. Blocks. //stats related methods unsigned int connTime();///< Returns the time this socket has been connected. unsigned int dataUp(); ///< Returns total amount of bytes sent. unsigned int dataDown(); ///< Returns total amount of bytes received. std::string getStats(std::string C); ///< Returns a std::string of stats, ended by a newline. friend class Server; bool Error; ///< Set to true if a socket error happened. bool Blocking; ///< Set to true if a socket is currently or wants to be blocking. //overloaded operators bool operator==(const Connection & B) const; bool operator!=(const Connection & B) const; operator bool() const; }; /// This class is for easily setting up listening socket, either TCP or Unix. class Server { private: std::string errors; ///< Stores errors that may have occured. int sock; ///< Internally saved socket number. bool IPv6bind(int port, std::string hostname, bool nonblock); ///< Attempt to bind an IPv6 socket bool IPv4bind(int port, std::string hostname, bool nonblock); ///< Attempt to bind an IPv4 socket public: Server(); ///< Create a new base Server. Server(int port, std::string hostname = "0.0.0.0", bool nonblock = false); ///< Create a new TCP Server. Server(std::string adres, bool nonblock = false); ///< Create a new Unix Server. Connection accept(bool nonblock = false); ///< Accept any waiting connections. void setBlocking(bool blocking); ///< Set this socket to be blocking (true) or nonblocking (false). bool connected() const; ///< Returns the connected-state for this socket. bool isBlocking(); ///< Check if this socket is blocking (true) or nonblocking (false). void close(); ///< Close connection. void drop(); ///< Close connection without shutdown. int getSocket(); ///< Returns internal socket number. }; class UDPConnection { private: int sock; ///< Internally saved socket number. std::string remotehost;///< Stores remote host address void * destAddr;///< Destination address pointer. unsigned int destAddr_size;///< Size of the destination address pointer. unsigned int up;///< Amount of bytes transferred up. unsigned int down;///< Amount of bytes transferred down. unsigned int data_size;///< The size in bytes of the allocated space in the data pointer. bool isIPv6;//<<< True if IPv6 socket, false otherwise. public: char * data;///< Holds the last received packet. unsigned int data_len; ///< The size in bytes of the last received packet. UDPConnection(const UDPConnection & o); UDPConnection(bool nonblock = false); ~UDPConnection(); int getSock(); int bind(int port, std::string iface = ""); void setBlocking(bool blocking); void SetDestination(std::string hostname, uint32_t port); void GetDestination(std::string & hostname, uint32_t & port); bool Receive(); void SendNow(const std::string & data); void SendNow(const char * data); void SendNow(const char * data, size_t len); }; }