socket.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /*
  2. Copyright (c) 2013 Daniele Bartolini, Michele Rossi
  3. Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
  4. Permission is hereby granted, free of charge, to any person
  5. obtaining a copy of this software and associated documentation
  6. files (the "Software"), to deal in the Software without
  7. restriction, including without limitation the rights to use,
  8. copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. copies of the Software, and to permit persons to whom the
  10. Software is furnished to do so, subject to the following
  11. conditions:
  12. The above copyright notice and this permission notice shall be
  13. included in all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  15. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  16. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  19. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  21. OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #pragma once
  24. #include "config.h"
  25. #include "types.h"
  26. #include "assert.h"
  27. #include "macros.h"
  28. #include "net_address.h"
  29. #if CROWN_PLATFORM_POSIX
  30. #include <sys/socket.h>
  31. #include <sys/types.h>
  32. #include <netinet/in.h>
  33. #include <fcntl.h>
  34. #include <unistd.h>
  35. #include <errno.h>
  36. #elif CROWN_PLATFORM_WINDOWS
  37. //Undefined in WinHeaders.h, but winsock2 ecc need it.
  38. #ifndef NEAR
  39. #define NEAR
  40. #endif
  41. #ifndef FAR
  42. #define FAR
  43. #endif
  44. #include <winsock2.h>
  45. #include "win_headers.h"
  46. #pragma comment(lib, "Ws2_32.lib")
  47. #endif
  48. namespace crown
  49. {
  50. struct ConnectResult
  51. {
  52. enum { NO_ERROR, BAD_SOCKET, REFUSED, TIMEOUT, UNKNOWN } error;
  53. };
  54. struct ReadResult
  55. {
  56. enum { NO_ERROR, BAD_SOCKET, REMOTE_CLOSED, TIMEOUT, UNKNOWN } error;
  57. size_t bytes_read;
  58. };
  59. struct WriteResult
  60. {
  61. enum { NO_ERROR, BAD_SOCKET, REMOTE_CLOSED, TIMEOUT, UNKNOWN } error;
  62. size_t bytes_wrote;
  63. };
  64. struct AcceptResult
  65. {
  66. enum { NO_ERROR, BAD_SOCKET, NO_CONNECTION, UNKNOWN } error;
  67. };
  68. /// TCP socket
  69. ///
  70. /// @ingroup Network
  71. struct TCPSocket
  72. {
  73. TCPSocket()
  74. #if CROWN_PLATFORM_POSIX
  75. : m_socket(0)
  76. #elif CROWN_PLATFORM_WINDOWS
  77. : m_socket(INVALID_SOCKET)
  78. #endif
  79. {
  80. }
  81. void open()
  82. {
  83. #if CROWN_PLATFORM_POSIX
  84. m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  85. CE_ASSERT(m_socket >= 0, "socket: errno = %d", errno);
  86. #elif CROWN_PLATFORM_WINDOWS
  87. m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  88. CE_ASSERT(m_socket >= 0, "socket: WSAGetLastError = %d", WSAGetLastError());
  89. #endif
  90. }
  91. ConnectResult connect(const NetAddress& ip, uint16_t port)
  92. {
  93. close();
  94. open();
  95. ConnectResult cr;
  96. cr.error = ConnectResult::NO_ERROR;
  97. #if CROWN_PLATFORM_POSIX
  98. sockaddr_in addr_in;
  99. addr_in.sin_family = AF_INET;
  100. addr_in.sin_addr.s_addr = htonl(ip.address());
  101. addr_in.sin_port = htons(port);
  102. int err = ::connect(m_socket, (const sockaddr*)&addr_in, sizeof(sockaddr_in));
  103. if (err == 0)
  104. return cr;
  105. if (errno == ECONNREFUSED)
  106. cr.error = ConnectResult::REFUSED;
  107. else if (errno == ETIMEDOUT)
  108. cr.error = ConnectResult::TIMEOUT;
  109. else
  110. cr.error = ConnectResult::UNKNOWN;
  111. return cr;
  112. #elif CROWN_PLATFORM_WINDOWS
  113. sockaddr_in addr_in;
  114. addr_in.sin_family = AF_INET;
  115. addr_in.sin_addr.s_addr = ::htonl(ip.address());
  116. addr_in.sin_port = ::htons(port);
  117. int err = ::connect(m_socket, (const sockaddr*)&addr_in, sizeof(sockaddr_in));
  118. if (err == 0)
  119. return cr;
  120. int wsaerr = WSAGetLastError();
  121. if (wsaerr == WSAECONNREFUSED)
  122. cr.error = ConnectResult::REFUSED;
  123. else if (wsaerr == WSAETIMEDOUT)
  124. cr.error = ConnectResult::TIMEOUT;
  125. else
  126. cr.error = ConnectResult::UNKNOWN;
  127. return cr;
  128. #endif
  129. }
  130. bool bind(uint16_t port)
  131. {
  132. close();
  133. open();
  134. set_reuse_address(true);
  135. #if CROWN_PLATFORM_POSIX
  136. sockaddr_in address;
  137. address.sin_family = AF_INET;
  138. address.sin_addr.s_addr = htonl(INADDR_ANY);
  139. address.sin_port = htons(port);
  140. int err = ::bind(m_socket, (const sockaddr*) &address, sizeof(sockaddr_in));
  141. CE_ASSERT(err == 0, "bind: errno = %d", errno);
  142. CE_UNUSED(err);
  143. return true;
  144. #elif CROWN_PLATFORM_WINDOWS
  145. sockaddr_in address;
  146. address.sin_family = AF_INET;
  147. address.sin_addr.s_addr = htonl(INADDR_ANY);
  148. address.sin_port = htons(port);
  149. int err = ::bind(m_socket, (const sockaddr*) &address, sizeof(sockaddr_in));
  150. CE_ASSERT(err == 0, "bind: WSAGetLastError = %d", WSAGetLastError());
  151. CE_UNUSED(err);
  152. return true;
  153. #endif
  154. }
  155. void listen(uint32_t max)
  156. {
  157. #if CROWN_PLATFORM_POSIX
  158. int err = ::listen(m_socket, max);
  159. CE_ASSERT(err == 0, "listen: errno = %d", errno);
  160. CE_UNUSED(err);
  161. #elif CROWN_PLATFORM_WINDOWS
  162. int err = ::listen(m_socket, max);
  163. CE_ASSERT(err == 0, "listen: WSAGetLastError = %d", WSAGetLastError());
  164. CE_UNUSED(err);
  165. #endif
  166. }
  167. AcceptResult accept_internal(TCPSocket& c)
  168. {
  169. AcceptResult ar;
  170. ar.error = AcceptResult::NO_ERROR;
  171. #if CROWN_PLATFORM_POSIX
  172. int err = ::accept(m_socket, NULL, NULL);
  173. if (err >= 0)
  174. c.m_socket = err;
  175. else if (err == -1 && errno == EBADF)
  176. ar.error = AcceptResult::BAD_SOCKET;
  177. else if (err == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
  178. ar.error = AcceptResult::NO_CONNECTION;
  179. else
  180. ar.error = AcceptResult::UNKNOWN;
  181. return ar;
  182. #elif CROWN_PLATFORM_WINDOWS
  183. int err = ::accept(m_socket, NULL, NULL);
  184. if (err != INVALID_SOCKET)
  185. {
  186. c.m_socket = err;
  187. return ar;
  188. }
  189. int wsaerr = WSAGetLastError();
  190. if (wsaerr == WSAEWOULDBLOCK)
  191. ar.error = AcceptResult::NO_CONNECTION;
  192. else
  193. ar.error = AcceptResult::UNKNOWN;
  194. return ar;
  195. #endif
  196. }
  197. AcceptResult accept_nonblock(TCPSocket& c)
  198. {
  199. set_blocking(false);
  200. return accept_internal(c);
  201. }
  202. AcceptResult accept(TCPSocket& c)
  203. {
  204. set_blocking(true);
  205. return accept_internal(c);
  206. }
  207. void close()
  208. {
  209. #if CROWN_PLATFORM_POSIX
  210. if (m_socket != 0)
  211. {
  212. ::close(m_socket);
  213. m_socket = 0;
  214. }
  215. #elif CROWN_PLATFORM_WINDOWS
  216. if (m_socket != INVALID_SOCKET)
  217. {
  218. ::closesocket(m_socket);
  219. m_socket = INVALID_SOCKET;
  220. }
  221. #endif
  222. }
  223. ReadResult read_internal(void* data, size_t size)
  224. {
  225. ReadResult rr;
  226. rr.error = ReadResult::NO_ERROR;
  227. rr.bytes_read = 0;
  228. #if CROWN_PLATFORM_POSIX
  229. char* buf = (char*) data;
  230. size_t to_read = size;
  231. while (to_read > 0)
  232. {
  233. ssize_t read_bytes = ::recv(m_socket, buf, to_read, 0);
  234. if (read_bytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
  235. {
  236. return rr;
  237. }
  238. else if (read_bytes == -1 && errno == ETIMEDOUT)
  239. {
  240. rr.error = ReadResult::TIMEOUT;
  241. return rr;
  242. }
  243. else if (read_bytes == 0)
  244. {
  245. rr.error = ReadResult::REMOTE_CLOSED;
  246. return rr;
  247. }
  248. buf += read_bytes;
  249. to_read -= read_bytes;
  250. rr.bytes_read += read_bytes;
  251. }
  252. return rr;
  253. #elif CROWN_PLATFORM_WINDOWS
  254. char* buf = (char*) data;
  255. size_t to_read = size;
  256. while (to_read > 0)
  257. {
  258. int read_bytes = ::recv(m_socket, buf, to_read, 0);
  259. if (read_bytes == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
  260. return rr;
  261. else if (read_bytes == SOCKET_ERROR && WSAGetLastError() == WSAETIMEDOUT)
  262. {
  263. rr.error = ReadResult::TIMEOUT;
  264. return rr;
  265. }
  266. else if (read_bytes == 0)
  267. {
  268. rr.error = ReadResult::REMOTE_CLOSED;
  269. return rr;
  270. }
  271. buf += read_bytes;
  272. to_read -= read_bytes;
  273. rr.bytes_read += read_bytes;
  274. }
  275. return rr;
  276. #endif
  277. }
  278. ReadResult read_nonblock(void* data, size_t size)
  279. {
  280. set_blocking(false);
  281. return read_internal(data, size);
  282. }
  283. ReadResult read(void* data, size_t size)
  284. {
  285. set_blocking(true);
  286. return read_internal(data, size);
  287. }
  288. WriteResult write_internal(const void* data, size_t size)
  289. {
  290. WriteResult wr;
  291. wr.error = WriteResult::NO_ERROR;
  292. wr.bytes_wrote = 0;
  293. #if CROWN_PLATFORM_POSIX
  294. const char* buf = (const char*) data;
  295. size_t to_send = size;
  296. while (to_send > 0)
  297. {
  298. ssize_t bytes_wrote = ::send(m_socket, (const char*) buf, to_send, 0);
  299. if (bytes_wrote == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
  300. return wr;
  301. else if (bytes_wrote == -1 && errno == ETIMEDOUT)
  302. {
  303. wr.error = WriteResult::TIMEOUT;
  304. return wr;
  305. }
  306. else if (bytes_wrote == 0)
  307. {
  308. wr.error = WriteResult::REMOTE_CLOSED;
  309. return wr;
  310. }
  311. else
  312. {
  313. wr.error = WriteResult::UNKNOWN;
  314. return wr;
  315. }
  316. buf += bytes_wrote;
  317. to_send -= bytes_wrote;
  318. wr.bytes_wrote += bytes_wrote;
  319. }
  320. return wr;
  321. #elif CROWN_PLATFORM_WINDOWS
  322. const char* buf = (const char*) data;
  323. size_t to_send = size;
  324. while (to_send > 0)
  325. {
  326. int bytes_wrote = ::send(m_socket, (const char*) buf, to_send, 0);
  327. if (bytes_wrote == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
  328. {
  329. return wr;
  330. }
  331. else if (bytes_wrote == SOCKET_ERROR && WSAGetLastError() == WSAETIMEDOUT)
  332. {
  333. wr.error = WriteResult::TIMEOUT;
  334. return wr;
  335. }
  336. else if (bytes_wrote == 0)
  337. {
  338. wr.error = WriteResult::REMOTE_CLOSED;
  339. return wr;
  340. }
  341. else
  342. {
  343. wr.error = WriteResult::UNKNOWN;
  344. return wr;
  345. }
  346. buf += bytes_wrote;
  347. to_send -= bytes_wrote;
  348. wr.bytes_wrote += bytes_wrote;
  349. }
  350. return wr;
  351. #endif
  352. }
  353. WriteResult write_nonblock(const void* data, size_t size)
  354. {
  355. set_blocking(false);
  356. return write_internal(data, size);
  357. }
  358. WriteResult write(const void* data, size_t size)
  359. {
  360. set_blocking(true);
  361. return write_internal(data, size);
  362. }
  363. void set_blocking(bool blocking)
  364. {
  365. #if CROWN_PLATFORM_POSIX
  366. int flags = fcntl(m_socket, F_GETFL, 0);
  367. fcntl(m_socket, F_SETFL, blocking ? (flags & ~O_NONBLOCK) : O_NONBLOCK);
  368. #elif CROWN_PLATFORM_WINDOWS
  369. //Warning! http://www.sockets.com/winsock.htm#IoctlSocket
  370. u_long non_blocking = blocking ? 0 : 1;
  371. ioctlsocket(m_socket, FIONBIO, &non_blocking);
  372. #endif
  373. }
  374. void set_reuse_address(bool reuse)
  375. {
  376. #if CROWN_PLATFORM_POSIX
  377. int optval = (int) reuse;
  378. int err = setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
  379. CE_ASSERT(err == 0, "setsockopt: errno = %d", errno);
  380. #elif CROWN_PLATFORM_WINDOWS
  381. int optval = (int) reuse;
  382. int err = setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (const char*) &optval, sizeof(optval));
  383. CE_ASSERT(err == 0, "setsockopt: WSAGetLastError = %d", WSAGetLastError());
  384. #endif
  385. }
  386. void set_timeout(uint32_t seconds)
  387. {
  388. #if CROWN_PLATFORM_POSIX
  389. struct timeval timeout;
  390. timeout.tv_sec = seconds;
  391. timeout.tv_usec = 0;
  392. int err;
  393. err = setsockopt (m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(timeout));
  394. CE_ASSERT(err == 0, "setsockopt: errno: %d", errno);
  395. err = setsockopt (m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, sizeof(timeout));
  396. CE_ASSERT(err == 0, "setsockopt: errno: %d", errno);
  397. #elif CROWN_PLATFORM_WINDOWS
  398. struct timeval timeout;
  399. timeout.tv_sec = seconds;
  400. timeout.tv_usec = 0;
  401. int err;
  402. err = setsockopt (m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(timeout));
  403. CE_ASSERT(err == 0, "setsockopt: WSAGetLastError: %d", WSAGetLastError());
  404. err = setsockopt (m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, sizeof(timeout));
  405. CE_ASSERT(err == 0, "setsockopt: WSAGetLastError: %d", WSAGetLastError());
  406. #endif
  407. }
  408. private:
  409. #if CROWN_PLATFORM_POSIX
  410. int m_socket;
  411. #elif CROWN_PLATFORM_WINDOWS
  412. SOCKET m_socket;
  413. #endif
  414. };
  415. } // namespace crown