SocketHandle.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /*
  2. ** Copyright 2003-2009, Ernest Laurentin (http://www.ernzo.com/)
  3. **
  4. ** Licensed under the Apache License, Version 2.0 (the "License");
  5. ** you may not use this file except in compliance with the License.
  6. ** You may obtain a copy of the License at
  7. **
  8. ** http://www.apache.org/licenses/LICENSE-2.0
  9. **
  10. ** Unless required by applicable law or agreed to in writing, software
  11. ** distributed under the License is distributed on an "AS IS" BASIS,
  12. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. ** See the License for the specific language governing permissions and
  14. ** limitations under the License.
  15. **
  16. ** File: SocketHandle.h
  17. ** Version: 1.4 - IPv6 support
  18. ** 1.3 - Update for Asynchronous mode / Linux port
  19. ** 1.2 - Update interface for TCP remote connection
  20. ** 1.1 - Added multicast support
  21. */
  22. #ifndef SOCKETHANDLE_H
  23. #define SOCKETHANDLE_H
  24. #ifdef WIN32
  25. #include <winsock2.h>
  26. #include <ws2tcpip.h>
  27. #elif BSD_SOCKET
  28. #include "platform.h"
  29. #endif
  30. /**
  31. * @defgroup _SockHandle Socket Communication Classes
  32. * @{
  33. */
  34. /**
  35. * SockAddrIn structure
  36. * Encapsulate SOCKADDR_STORAGE (IPv4: SOCKADDR_IN, IPv6: SOCKADDR_IN6) structures
  37. */
  38. struct SockAddrIn : public sockaddr_storage {
  39. public:
  40. /**
  41. * Default constructor
  42. */
  43. SockAddrIn();
  44. /**
  45. * Copy constructor
  46. * @param sin reference object
  47. */
  48. SockAddrIn(const SockAddrIn& sin);
  49. /**
  50. * Destructor
  51. */
  52. ~SockAddrIn();
  53. /**
  54. * Copy function
  55. * @param sin reference object
  56. * @return reference of 'this' object
  57. */
  58. SockAddrIn& Copy(const SockAddrIn& sin);
  59. /**
  60. * Clear struct
  61. */
  62. void Clear();
  63. /**
  64. * Compare NetworkAddr object
  65. * @param sin reference object
  66. * @return true if equal, otherwise false
  67. */
  68. bool IsEqual(const SockAddrIn& sin) const;
  69. /**
  70. * Check if NULL
  71. * @return true if object is 'NULL' - not valid
  72. */
  73. bool IsNull() const { return IsEqual(NULLAddr); }
  74. /**
  75. * Get Socket address family
  76. * @return Socket address family (IPv4: AF_INET, IPv6: AF_INET6)
  77. */
  78. short GetFamily () const { return ss_family; }
  79. /**
  80. * Get IP address (IPv4)
  81. * @return IPv4 network address in network format
  82. */
  83. ULONG GetIPAddr() const { return ((SOCKADDR_IN*)this)->sin_addr.s_addr; }
  84. /**
  85. * Get Port
  86. * @return Port number in network format
  87. */
  88. short GetPort() const { return ((SOCKADDR_IN*)this)->sin_port; }
  89. /**
  90. * Create from string. Service is service name or port number.
  91. * @param pszAddr Hostname or IP address
  92. * @param pszService Service name or port
  93. * @param nFamily Socket address family (default: AF_INET, AF_INET6)
  94. * @return true if object is now valid
  95. */
  96. bool CreateFrom(LPCTSTR pszAddr, LPCTSTR pszService, int nFamily = AF_INET);
  97. /**
  98. * Create from number. Initialize object from host or network format values (IPv4 only).
  99. * @param lIPAddr IP Address
  100. * @param nPort Port number
  101. * @param nFamily Socket address family (default: AF_INET)
  102. * @param bFmtHost flag to indicate that IP address and port are in host (true) or network format (false)
  103. * @return true if object is now valid
  104. */
  105. bool CreateFrom(ULONG lIPAddr, USHORT nPort, int nFamily = AF_INET, bool bFmtHost = true);
  106. /**
  107. * Object copy operator
  108. * @param sin reference object to copy from
  109. * @return reference of 'this' object
  110. */
  111. SockAddrIn& operator=(const SockAddrIn& sin) { return Copy( sin ); }
  112. /**
  113. * Equality operator
  114. * @param sin reference object to test
  115. * @return true if object is equal
  116. */
  117. bool operator==(const SockAddrIn& sin) const { return IsEqual( sin ); }
  118. /**
  119. * Not Equal operator
  120. * @param sin reference object to test
  121. * @return true if object is different
  122. */
  123. bool operator!=(const SockAddrIn& sin) const { return !IsEqual( sin ); }
  124. /**
  125. * SOCKADDR conversion. Return SOCKADDR of this object.
  126. */
  127. operator LPSOCKADDR() { return reinterpret_cast<LPSOCKADDR>(this); }
  128. /**
  129. * PIN6_ADDR conversion. Return const PIN6_ADDR of this object.
  130. */
  131. operator const IN6_ADDR*() const { return reinterpret_cast<const IN6_ADDR*>(this); }
  132. /**
  133. * PIN6_ADDR conversion. Return PIN6_ADDR of this object.
  134. */
  135. operator PIN6_ADDR() { return reinterpret_cast<PIN6_ADDR>(this); }
  136. /**
  137. * Size of this struct (SOCKADDR_IN) or (SOCKADDR_STORAGE) depending on address family
  138. * @return size of this structure (SOCKADDR_IN) or (SOCKADDR_STORAGE)
  139. */
  140. size_t Size() const { return (ss_family == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_storage); }
  141. /**
  142. * Initialize this object from SOCKADDR_IN struct.
  143. * @param psin SOCKADDR_IN object pointer
  144. */
  145. void SetAddr(const sockaddr_in* psin) { SetAddr(reinterpret_cast<const sockaddr_storage*>(psin)); }
  146. /**
  147. * Initialize this object from SOCKADDR_IN6 struct.
  148. * @param psin SOCKADDR_IN6 object pointer
  149. */
  150. void SetAddr(const sockaddr_in6* psin) { SetAddr(reinterpret_cast<const sockaddr_storage*>(psin)); }
  151. /**
  152. * Initialize this object from SOCKADDR_STORAGE struct.
  153. * @param pss SOCKADDR_STORAGE object pointer
  154. */
  155. void SetAddr(const sockaddr_storage* pss) { ss_family = pss->ss_family; memcpy(this, pss, Size()); }
  156. static SockAddrIn NULLAddr; ///< Null Address
  157. };
  158. #ifdef WIN32
  159. typedef LPWSAOVERLAPPED_COMPLETION_ROUTINE LPWSACOMPLETIONROUTINE;
  160. #endif
  161. /**
  162. * CSocketHandle class
  163. * Socket communication class
  164. */
  165. class CSocketHandle
  166. {
  167. public:
  168. /**
  169. * Default constructor
  170. */
  171. CSocketHandle();
  172. /**
  173. * Destructor
  174. */
  175. ~CSocketHandle();
  176. /**
  177. * Check if socket is opened
  178. * @return true if this is opened (valid)
  179. */
  180. bool IsOpen() const;
  181. /**
  182. * Get SOCKET handle
  183. * @return SOCKET handle (handle is INVALID_SOCKET if object is closed)
  184. */
  185. SOCKET GetSocket() const;
  186. /**
  187. * Get SOCKET type
  188. * @return SOCKET type (-1 if not a valid socket)
  189. */
  190. int GetSocketType() const;
  191. /**
  192. * Attach a socket handle
  193. * This function may fail is socket handle is not valid or object already in used. Call Detach or Close to release object.
  194. * @param sock Socket handle to attach to this class
  195. * @return true if successful, otherwise false
  196. */
  197. bool Attach(SOCKET sock);
  198. /**
  199. * Detach a socket handle
  200. * @return previous socket handle or INVALID_SOCKET
  201. */
  202. SOCKET Detach();
  203. /**
  204. * Create a Socket - Server side.
  205. * @param pszHost hostname or IP address of adapter
  206. * @param pszServiceName Network service name or port number
  207. * @param nFamily address family to use (AF_INET, AF_INET6)
  208. * @param nType type of socket to create (SOCK_STREAM, SOCK_DGRAM)
  209. * @param uOptions Additional options (SO_BROADCAST, SO_REUSEADDR)
  210. * @return true if successful, otherwise false (call WSAGetLastError() to retrieve latest error)
  211. * @sa InitLibrary, ConnectTo, IsOpen
  212. */
  213. bool CreateSocket(LPCTSTR pszHost, LPCTSTR pszServiceName, int nFamily, int nType, UINT uOptions = 0);
  214. /**
  215. * Create a socket, connect to a server - Client side.
  216. * @param pszHostName Hostname or NIC address
  217. * @param pszRemote Remote network address
  218. * @param pszServiceName Network service name or port number
  219. * @param nFamily address family to use (AF_INET, AF_INET6)
  220. * @param nType type of socket to create (SOCK_STREAM, SOCK_DGRAM)
  221. * @return true if successful, otherwise false (call WSAGetLastError() to retrieve latest error)
  222. * @sa InitLibrary, CreateSocket, IsOpen
  223. */
  224. bool ConnectTo(LPCTSTR pszHostName, LPCTSTR pszRemote, LPCTSTR pszServiceName, int nFamily, int nType);
  225. /**
  226. * Close Socket
  227. * @sa InitLibrary, CreateSocket, ConnectTo, IsOpen
  228. */
  229. void Close();
  230. /**
  231. * Read from socket
  232. * @param lpBuffer Buffer to receive data
  233. * @param dwSize Size of buffer in bytes
  234. * @param lpAddrIn Peer address for UDP - this must be NULL for TCP
  235. * @param dwTimeout Read timeout in milliseconds
  236. * @return number of bytes read or (-1L) if fail
  237. * @sa InitLibrary, CreateSocket, ConnectTo, IsOpen, ReadEx, Write, WriteEx
  238. */
  239. DWORD Read(LPBYTE lpBuffer, DWORD dwSize, LPSOCKADDR lpAddrIn = NULL, DWORD dwTimeout = INFINITE);
  240. #ifdef WIN32
  241. /**
  242. * Read from socket (asynchronous mode).
  243. * @param lpBuffer Buffer to receive data
  244. * @param dwSize Size of buffer in bytes
  245. * @param lpAddrIn SockAddrIn for UDP - this must be NULL for TCP
  246. * @param lpOverlapped Windows Overlapped structure (required)
  247. * @param lpCompletionRoutine Winsock Completion routine (required)
  248. * @return number of bytes read, overlapped operation is pending or (-1L) if fail
  249. * @sa InitLibrary, CreateSocket, ConnectTo, IsOpen, Read, Write, WriteEx, IOControl, GetTransferOverlappedResult
  250. */
  251. DWORD ReadEx(LPBYTE lpBuffer, DWORD dwSize, LPSOCKADDR lpAddrIn,
  252. LPWSAOVERLAPPED lpOverlapped, LPWSACOMPLETIONROUTINE lpCompletionRoutine);
  253. #endif
  254. /**
  255. * Write to a destination socket
  256. * @param lpBuffer Buffer to send
  257. * @param dwCount Number of bytes to send
  258. * @param lpAddrIn Peer address for UDP - this must be NULL for TCP
  259. * @param dwTimeout Write timeout in milliseconds
  260. * @return number of bytes sent or (-1L) if fail
  261. * @sa InitLibrary, CreateSocket, ConnectTo, IsOpen, Read, ReadEx, WriteEx
  262. */
  263. DWORD Write(const LPBYTE lpBuffer, DWORD dwCount, const LPSOCKADDR lpAddrIn = NULL, DWORD dwTimeout = INFINITE);
  264. #ifdef WIN32
  265. /**
  266. * Write to a destination socket (asynchronous mode).
  267. * @param lpBuffer Buffer to send
  268. * @param dwCount Number of bytes to send
  269. * @param lpAddrIn SockAddrIn for UDP - this must be NULL for TCP
  270. * @param lpOverlapped Windows Overlapped structure (required)
  271. * @param lpCompletionRoutine Winsock Completion routine (required)
  272. * @return number of bytes read, overlapped operation is pending or (-1L) if fail
  273. * @sa InitLibrary, CreateSocket, ConnectTo, IsOpen, Read, ReadEx, Write, IOControl, GetTransferOverlappedResult
  274. */
  275. DWORD WriteEx(const LPBYTE lpBuffer, DWORD dwCount, const LPSOCKADDR lpAddrIn,
  276. LPWSAOVERLAPPED lpOverlapped, LPWSACOMPLETIONROUTINE lpCompletionRoutine);
  277. #endif
  278. #ifdef WIN32
  279. /**
  280. * Control the mode of a socket (asynchronous mode)
  281. * @param dwIoCode Control code of operation to perform
  282. * @param lpInBuffer Pointer to the input buffer
  283. * @param cbInBuffer Size of the input buffer, in bytes
  284. * @param lpOutBuffer Pointer to the output buffer
  285. * @param cbOutBuffer Size of the output buffer, in bytes
  286. * @param lpcbBytesReturned Pointer to actual number of bytes of output
  287. * @param lpOverlapped Winsock Overlapped structure
  288. * @param lpCompletionRoutine Winsock Completion routine
  289. * @return true if successful, otherwise false (call WSAGetLastError() to retrieve latest error)
  290. * @sa InitLibrary, CreateSocket, ConnectTo, IsOpen, ReadEx, WriteEx, GetTransferOverlappedResult
  291. */
  292. bool IOControl(DWORD dwIoCode, LPBYTE lpInBuffer, DWORD cbInBuffer,
  293. LPBYTE lpOutBuffer, DWORD cbOutBuffer,
  294. LPDWORD lpcbBytesReturned, LPWSAOVERLAPPED lpOverlapped,
  295. LPWSACOMPLETIONROUTINE lpCompletionRoutine);
  296. /**
  297. * Get Overlapped result (asynchronous mode)
  298. * @param lpOverlapped Windows Overlapped structure (required)
  299. * @param lpcbTransfer Pointer to get number of bytes transferred
  300. * @param bWait Force wait for overlapped operation to complete
  301. * @param lpdwFlags Optional flags (see MSDN on WSARecv API)
  302. * @sa InitLibrary, CreateSocket, ConnectTo, IsOpen, ReadEx, WriteEx, IOControl
  303. */
  304. bool GetTransferOverlappedResult(LPWSAOVERLAPPED lpOverlapped, LPDWORD lpcbTransfer, bool bWait = true, LPDWORD lpdwFlags = 0);
  305. #endif
  306. /**
  307. * Get Socket name - get local address
  308. * @param saddr_in current local address and port when connected
  309. * @return true if successful
  310. * @sa InitLibrary
  311. */
  312. bool GetSockName(SockAddrIn& saddr_in) const;
  313. /**
  314. * Get Peer Socket name - get peer address
  315. * @param saddr_in peer address and port (use only with TCP or client mode UDP)
  316. * @return true if successful
  317. * @sa InitLibrary
  318. */
  319. bool GetPeerName(SockAddrIn& saddr_in) const;
  320. /**
  321. * Register to multicast address
  322. * @param pszIPAddr multicast IP group
  323. * @param pszNIC interface IP address
  324. * @return true if successful
  325. * @sa InitLibrary
  326. */
  327. bool AddMembership(LPCTSTR pszIPAddr, LPCTSTR pszNIC);
  328. /**
  329. * Unregister from a multicast address
  330. * @param pszIPAddr multicast IP group
  331. * @param pszNIC interface IP address
  332. * @return true if successful
  333. * @sa InitLibrary
  334. */
  335. bool DropMembership(LPCTSTR pszIPAddr, LPCTSTR pszNIC);
  336. /**
  337. * Initialize Winsock library. This function calls WSAStartup.
  338. * @param wVersion Winsock version use MAKEWORD macro if possible (e.g.: MAKEWORD(2,2))
  339. * @return true if successful
  340. * @sa ReleaseLibrary
  341. */
  342. static bool InitLibrary(WORD wVersion);
  343. /**
  344. * Release Winsock library
  345. * @return true if successful
  346. * @sa InitLibrary
  347. */
  348. static bool ReleaseLibrary();
  349. /**
  350. * Wait for a new connection
  351. * @param sock A TCP socket handle. A new socket is return returned.
  352. * @return A new socket when a new client connects
  353. * @sa GetSocket, CreateSocket
  354. */
  355. static SOCKET WaitForConnection(SOCKET sock);
  356. /**
  357. * Shutdown a connection
  358. * @param sock Socket to shutdown communication
  359. * @return true if successful
  360. */
  361. static bool ShutdownConnection(SOCKET sock);
  362. /**
  363. * Check if IP address is unicast (network order).
  364. * @param ulAddr IP address (expected valid unicast address)
  365. * @return true if successful
  366. */
  367. static bool IsUnicastIP( ULONG ulAddr );
  368. /**
  369. * Check if IP address is multicast (network order).
  370. * @param ulAddr IP address (expected valid multicast address)
  371. * @return true if successful
  372. */
  373. static bool IsMulticastIP( ULONG ulAddr );
  374. /**
  375. * Format IP address to string
  376. * @param pszIPAddr Buffer to hold string
  377. * @param nSize Size of buffer in characters
  378. * @param ulAddr IP Address to format
  379. * @param bFmtHost Specify if address (ulAddr) is in host (true) or network format (false)
  380. * @return true if successful. Possible error could be INSUFFICIENT_BUFFER
  381. */
  382. static bool FormatIP(LPTSTR pszIPAddr, UINT nSize, ULONG ulAddr, bool bFmtHost);
  383. /**
  384. * Format IP address to string
  385. * @param pszIPAddr Buffer to hold string
  386. * @param nSize Size of buffer in characters
  387. * @param addrIn IP Address to format
  388. * @return true if successful. Possible error could be INSUFFICIENT_BUFFER
  389. */
  390. static bool FormatIP(LPTSTR pszIPAddr, UINT nSize, const SockAddrIn& addrIn);
  391. /**
  392. * Get service port number
  393. * @param pszServiceName Network service name (e.g.: "ftp", "telnet") or port number
  394. * @return port number
  395. */
  396. static USHORT GetPortNumber( LPCTSTR pszServiceName );
  397. /**
  398. * Get IP address of a host
  399. * @param pszHostName host name or IP address
  400. * @return Host IP address in host format
  401. * @sa GetAddressInfo
  402. */
  403. static ULONG GetIPAddress( LPCTSTR pszHostName );
  404. /**
  405. * Get current localname for this machine
  406. * @param pszName Buffer to receive host name
  407. * @param nSize Size of this buffer in character
  408. * @return true if successful
  409. */
  410. static bool GetLocalName(LPTSTR pszName, UINT nSize);
  411. /**
  412. * Get current (default) IP address for this machine
  413. * @param pszAddress Buffer to receive IP address (IPv4, IPv6 format)
  414. * @param nSize Size of this buffer in character
  415. * @param nFamily address family to use (AF_INET, AF_INET6)
  416. * @return true if successful
  417. */
  418. static bool GetLocalAddress(LPTSTR pszAddress, UINT nSize, int nFamily = AF_INET);
  419. /**
  420. * Get IP address info of a host (Supports: IPv4 and IPv6)
  421. * @param pszHostName host name or IP address
  422. * @param pszServiceName pszServiceName Network service name (e.g.: "ftp", "telnet") or port number
  423. * @param nFamily address family to use (AF_INET, AF_INET6)
  424. * @param sockAddr Socket address to fill in
  425. * @return true if successful
  426. */
  427. static bool GetAddressInfo( LPCTSTR pszHostName, LPCTSTR pszServiceName, int nFamily, SockAddrIn& sockAddr);
  428. // CSocketHandle - data
  429. protected:
  430. SOCKET m_hSocket; ///< socket handle
  431. };
  432. /** @}*/
  433. #endif //SOCKETHANDLE_H