PageRenderTime 31ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/mordor/socket.h

http://github.com/mozy/mordor
C Header | 361 lines | 277 code | 58 blank | 26 comment | 0 complexity | c1f5f89cff6dc96b83f70a2939945506 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. #ifndef __MORDOR_SOCKET_H__
  2. #define __MORDOR_SOCKET_H__
  3. // Copyright (c) 2009 - Mozy, Inc.
  4. #include <vector>
  5. #include <boost/enable_shared_from_this.hpp>
  6. #include <boost/noncopyable.hpp>
  7. #include <boost/shared_ptr.hpp>
  8. #include <boost/signals2/signal.hpp>
  9. #include "endian.h"
  10. #include "exception.h"
  11. #include "version.h"
  12. #ifdef WINDOWS
  13. #include <ws2tcpip.h>
  14. #include "iomanager.h"
  15. #else
  16. #include <stdint.h>
  17. #include <sys/socket.h>
  18. #include <sys/types.h>
  19. #include <netinet/in.h>
  20. #ifndef OSX
  21. # include <netinet/in_systm.h>
  22. # include <netinet/ip.h>
  23. #endif
  24. #include <sys/un.h>
  25. #endif
  26. namespace Mordor {
  27. class IOManager;
  28. #ifdef WINDOWS
  29. struct iovec
  30. {
  31. union
  32. {
  33. WSABUF wsabuf;
  34. struct {
  35. u_long iov_len;
  36. void *iov_base;
  37. };
  38. };
  39. };
  40. #define SHUT_RD SD_RECEIVE
  41. #define SHUT_WR SD_SEND
  42. #define SHUT_RDWR SD_BOTH
  43. typedef u_long iov_len_t;
  44. typedef SOCKET socket_t;
  45. #else
  46. typedef size_t iov_len_t;
  47. typedef int socket_t;
  48. #endif
  49. struct SocketException : virtual NativeException {};
  50. struct AddressInUseException : virtual SocketException {};
  51. struct ConnectionAbortedException : virtual SocketException {};
  52. struct ConnectionResetException : virtual SocketException {};
  53. struct ConnectionRefusedException : virtual SocketException {};
  54. struct HostDownException : virtual SocketException {};
  55. struct HostUnreachableException : virtual SocketException {};
  56. struct NetworkDownException : virtual SocketException {};
  57. struct NetworkResetException : virtual SocketException {};
  58. struct NetworkUnreachableException : virtual SocketException {};
  59. struct TimedOutException : virtual SocketException {};
  60. struct Address;
  61. class Socket : public boost::enable_shared_from_this<Socket>, boost::noncopyable
  62. {
  63. public:
  64. typedef boost::shared_ptr<Socket> ptr;
  65. typedef boost::weak_ptr<Socket> weak_ptr;
  66. private:
  67. Socket(IOManager *ioManager, int family, int type, int protocol, int initialize);
  68. public:
  69. Socket(int family, int type, int protocol = 0);
  70. Socket(IOManager &ioManager, int family, int type, int protocol = 0);
  71. ~Socket();
  72. unsigned long long receiveTimeout() { return m_receiveTimeout; }
  73. void receiveTimeout(unsigned long long us) { m_receiveTimeout = us; }
  74. unsigned long long sendTimeout() { return m_sendTimeout; }
  75. void sendTimeout(unsigned long long us) { m_sendTimeout = us; }
  76. void bind(const Address &addr);
  77. void bind(const boost::shared_ptr<Address> addr);
  78. void connect(const Address &to);
  79. void connect(const boost::shared_ptr<Address> addr)
  80. { connect(*addr.get()); }
  81. void listen(int backlog = SOMAXCONN);
  82. Socket::ptr accept();
  83. void shutdown(int how = SHUT_RDWR);
  84. void getOption(int level, int option, void *result, size_t *len);
  85. template <class T>
  86. T getOption(int level, int option)
  87. {
  88. T result;
  89. size_t length = sizeof(T);
  90. getOption(level, option, &result, &length);
  91. return result;
  92. }
  93. void setOption(int level, int option, const void *value, size_t len);
  94. template <class T>
  95. void setOption(int level, int option, const T &value)
  96. {
  97. setOption(level, option, &value, sizeof(T));
  98. }
  99. void cancelAccept();
  100. void cancelConnect();
  101. void cancelSend();
  102. void cancelReceive();
  103. size_t send(const void *buffer, size_t length, int flags = 0);
  104. size_t send(const iovec *buffers, size_t length, int flags = 0);
  105. size_t sendTo(const void *buffer, size_t length, int flags, const Address &to);
  106. size_t sendTo(const void *buffer, size_t length, int flags, const boost::shared_ptr<Address> to)
  107. { return sendTo(buffer, length, flags, *to.get()); }
  108. size_t sendTo(const iovec *buffers, size_t length, int flags, const Address &to);
  109. size_t sendTo(const iovec *buffers, size_t length, int flags, const boost::shared_ptr<Address> to)
  110. { return sendTo(buffers, length, flags, *to.get()); }
  111. size_t receive(void *buffer, size_t length, int *flags = NULL);
  112. size_t receive(iovec *buffers, size_t length, int *flags = NULL);
  113. size_t receiveFrom(void *buffer, size_t length, Address &from, int *flags = NULL);
  114. size_t receiveFrom(iovec *buffers, size_t length, Address &from, int *flags = NULL);
  115. boost::shared_ptr<Address> emptyAddress();
  116. boost::shared_ptr<Address> remoteAddress();
  117. boost::shared_ptr<Address> localAddress();
  118. int family() { return m_family; }
  119. int type();
  120. int protocol() { return m_protocol; }
  121. /// Event triggered when the remote end of the connection closes the
  122. /// virtual circuit
  123. ///
  124. /// Only triggered for connected stream sockets. This event is trigerred
  125. /// out-of-band of any receive operations (i.e. there may still be data on
  126. /// the socket to be read after this event has been received)
  127. boost::signals2::connection onRemoteClose(
  128. const boost::signals2::slot<void ()> &slot);
  129. private:
  130. template <bool isSend>
  131. size_t doIO(iovec *buffers, size_t length, int &flags, Address *address = NULL);
  132. static void callOnRemoteClose(weak_ptr self);
  133. void registerForRemoteClose();
  134. void accept(Socket &target);
  135. #ifdef WINDOWS
  136. // For WSAEventSelect
  137. void cancelIo(error_t &cancelled, error_t error);
  138. #else
  139. void cancelIo(int event, error_t &cancelled, error_t error);
  140. #endif
  141. private:
  142. socket_t m_sock;
  143. int m_family, m_protocol;
  144. IOManager *m_ioManager;
  145. unsigned long long m_receiveTimeout, m_sendTimeout;
  146. error_t m_cancelledSend, m_cancelledReceive;
  147. boost::shared_ptr<Address> m_localAddress, m_remoteAddress;
  148. #ifdef WINDOWS
  149. bool m_skipCompletionPortOnSuccess;
  150. // All this, just so a connect/accept can be cancelled on win2k
  151. bool m_unregistered;
  152. HANDLE m_hEvent;
  153. boost::shared_ptr<Fiber> m_fiber;
  154. Scheduler *m_scheduler;
  155. AsyncEvent m_sendEvent, m_receiveEvent;
  156. bool m_useAcceptEx; //Cache the values in case they are changed in the registry at
  157. bool m_useConnectEx; //runtime
  158. #endif
  159. bool m_isConnected, m_isRegisteredForRemoteClose;
  160. boost::signals2::signal<void ()> m_onRemoteClose;
  161. };
  162. #ifdef WINDOWS
  163. typedef errinfo_lasterror errinfo_gaierror;
  164. #else
  165. typedef boost::error_info<struct tag_gaierror, int> errinfo_gaierror;
  166. std::string to_string( errinfo_gaierror const & e );
  167. #endif
  168. struct NameLookupException : virtual SocketException {};
  169. struct TemporaryNameServerFailureException : virtual NameLookupException {};
  170. struct PermanentNameServerFailureException : virtual NameLookupException {};
  171. struct NoNameServerDataException : virtual NameLookupException {};
  172. struct HostNotFoundException : virtual NameLookupException {};
  173. struct Address
  174. {
  175. public:
  176. typedef boost::shared_ptr<Address> ptr;
  177. protected:
  178. Address() {}
  179. public:
  180. virtual ~Address() {}
  181. static std::vector<ptr>
  182. lookup(const std::string& host, int family = AF_UNSPEC,
  183. int type = 0, int protocol = 0);
  184. /// @returns interface => (address, prefixLength)
  185. static std::multimap<std::string, std::pair<ptr, unsigned int> >
  186. getInterfaceAddresses(int family = AF_UNSPEC);
  187. // @param iface Interface name, or "*" to indicate all interfaces
  188. static std::vector<std::pair<ptr, unsigned int> >
  189. getInterfaceAddresses(const std::string &iface,
  190. int family = AF_UNSPEC);
  191. static ptr create(const sockaddr *name, socklen_t nameLen);
  192. ptr clone();
  193. Socket::ptr createSocket(int type, int protocol = 0);
  194. Socket::ptr createSocket(IOManager &ioManager, int type, int protocol = 0);
  195. int family() const { return name()->sa_family; }
  196. virtual const sockaddr *name() const = 0;
  197. virtual sockaddr *name() = 0;
  198. virtual socklen_t nameLen() const = 0;
  199. virtual std::ostream & insert(std::ostream &os) const;
  200. bool operator<(const Address &rhs) const;
  201. bool operator==(const Address &rhs) const;
  202. bool operator!=(const Address &rhs) const;
  203. };
  204. struct IPAddress : public Address
  205. {
  206. public:
  207. typedef boost::shared_ptr<IPAddress> ptr;
  208. public:
  209. /// Create an IPAddress from a numeric string
  210. /// @note port should be provided in native-endian format
  211. /// @note std::invalid_argument may be thrown if it is an IPv6 address and
  212. /// IPv6 is not supported
  213. static ptr create(const char *address, unsigned short port = 0);
  214. ptr clone();
  215. virtual ptr broadcastAddress(unsigned int prefixLength) = 0;
  216. virtual ptr networkAddress(unsigned int prefixLength) = 0;
  217. virtual ptr subnetMask(unsigned int prefixLength) = 0;
  218. virtual unsigned short port() const = 0;
  219. virtual void port(unsigned short p) = 0;
  220. };
  221. struct IPv4Address : public IPAddress
  222. {
  223. public:
  224. /// @note address and port should be provided in native-endian format
  225. IPv4Address(unsigned int address = INADDR_ANY, unsigned short port = 0);
  226. /// @note port should be provided in native-endian format
  227. IPv4Address(const char *address, unsigned short port = 0);
  228. ptr broadcastAddress(unsigned int prefixLength);
  229. ptr networkAddress(unsigned int prefixLength);
  230. ptr subnetMask(unsigned int prefixLength)
  231. { return IPv4Address::createSubnetMask(prefixLength); }
  232. static ptr createSubnetMask(unsigned int prefixLength);
  233. unsigned short port() const { return byteswapOnLittleEndian(sin.sin_port); }
  234. void port(unsigned short p) { sin.sin_port = byteswapOnLittleEndian(p); }
  235. const sockaddr *name() const { return (sockaddr*)&sin; }
  236. sockaddr *name() { return (sockaddr*)&sin; }
  237. socklen_t nameLen() const { return sizeof(sockaddr_in); }
  238. std::ostream & insert(std::ostream &os) const;
  239. private:
  240. sockaddr_in sin;
  241. };
  242. struct IPv6Address : public IPAddress
  243. {
  244. public:
  245. IPv6Address();
  246. IPv6Address(const unsigned char address[16], unsigned short port = 0);
  247. IPv6Address(const char *address, unsigned short port = 0);
  248. ptr broadcastAddress(unsigned int prefixLength);
  249. ptr networkAddress(unsigned int prefixLength);
  250. ptr subnetMask(unsigned int prefixLength)
  251. { return createSubnetMask(prefixLength); }
  252. static ptr createSubnetMask(unsigned int prefixLength);
  253. unsigned short port() const { return byteswapOnLittleEndian(sin.sin6_port); }
  254. void port(unsigned short p) { sin.sin6_port = byteswapOnLittleEndian(p); }
  255. const sockaddr *name() const { return (sockaddr*)&sin; }
  256. sockaddr *name() { return (sockaddr*)&sin; }
  257. socklen_t nameLen() const { return sizeof(sockaddr_in6); }
  258. std::ostream & insert(std::ostream &os) const;
  259. private:
  260. sockaddr_in6 sin;
  261. };
  262. #ifndef WINDOWS
  263. struct UnixAddress : public Address
  264. {
  265. public:
  266. /// @pre @c path.length() is less or equal to MAX_PATH_LEN
  267. UnixAddress(const std::string &path);
  268. /// create a dummy instance of @c UnixAddress
  269. ///
  270. /// an all '\0' string sized @c MAX_PATH_LEN is used as the path for the
  271. /// address.
  272. ///
  273. /// @note one is supposed to fill the sockaddr returned by @name() before
  274. /// actually start using it, and to set the @length correctly using
  275. /// @c nameLen(size_t).
  276. UnixAddress();
  277. const sockaddr *name() const { return (sockaddr*)&sun; }
  278. sockaddr *name() { return (sockaddr*)&sun; }
  279. socklen_t nameLen() const { return length; }
  280. void nameLen(socklen_t len) { length = len; }
  281. std::ostream & insert(std::ostream &os) const;
  282. static const size_t MAX_PATH_LEN;
  283. private:
  284. socklen_t length;
  285. struct sockaddr_un sun;
  286. };
  287. #endif
  288. struct UnknownAddress : public Address
  289. {
  290. public:
  291. UnknownAddress(int family);
  292. const sockaddr *name() const { return &sa; }
  293. sockaddr *name() { return &sa; }
  294. socklen_t nameLen() const { return sizeof(sockaddr); }
  295. private:
  296. sockaddr sa;
  297. };
  298. std::ostream &operator <<(std::ostream &os, const Address &addr);
  299. bool operator<(const Address::ptr &lhs, const Address::ptr &rhs);
  300. std::ostream &includePort(std::ostream &os);
  301. std::ostream &excludePort(std::ostream &os);
  302. }
  303. #endif