/src/tcp_socket.cpp

https://github.com/bartuer/zeromq2-1 · C++ · 239 lines · 161 code · 43 blank · 35 comment · 89 complexity · 0e6f1ffc83af04ada685613283e7a960 MD5 · raw file

  1. /*
  2. Copyright (c) 2007-2011 iMatix Corporation
  3. Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
  4. This file is part of 0MQ.
  5. 0MQ is free software; you can redistribute it and/or modify it under
  6. the terms of the GNU Lesser General Public License as published by
  7. the Free Software Foundation; either version 3 of the License, or
  8. (at your option) any later version.
  9. 0MQ is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "tcp_socket.hpp"
  17. #include "platform.hpp"
  18. #include "err.hpp"
  19. #ifdef ZMQ_HAVE_WINDOWS
  20. zmq::tcp_socket_t::tcp_socket_t () :
  21. s (retired_fd)
  22. {
  23. }
  24. zmq::tcp_socket_t::~tcp_socket_t ()
  25. {
  26. if (s != retired_fd)
  27. close ();
  28. }
  29. int zmq::tcp_socket_t::open (fd_t fd_, uint64_t sndbuf_, uint64_t rcvbuf_)
  30. {
  31. zmq_assert (s == retired_fd);
  32. s = fd_;
  33. if (sndbuf_) {
  34. int sz = (int) sndbuf_;
  35. int rc = setsockopt (s, SOL_SOCKET, SO_SNDBUF,
  36. (char*) &sz, sizeof (int));
  37. errno_assert (rc == 0);
  38. }
  39. if (rcvbuf_) {
  40. int sz = (int) rcvbuf_;
  41. int rc = setsockopt (s, SOL_SOCKET, SO_RCVBUF,
  42. (char*) &sz, sizeof (int));
  43. errno_assert (rc == 0);
  44. }
  45. return 0;
  46. }
  47. int zmq::tcp_socket_t::close ()
  48. {
  49. zmq_assert (s != retired_fd);
  50. int rc = closesocket (s);
  51. wsa_assert (rc != SOCKET_ERROR);
  52. s = retired_fd;
  53. return 0;
  54. }
  55. zmq::fd_t zmq::tcp_socket_t::get_fd ()
  56. {
  57. return s;
  58. }
  59. int zmq::tcp_socket_t::write (const void *data, int size)
  60. {
  61. int nbytes = send (s, (char*) data, size, 0);
  62. // If not a single byte can be written to the socket in non-blocking mode
  63. // we'll get an error (this may happen during the speculative write).
  64. if (nbytes == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK)
  65. return 0;
  66. // Signalise peer failure.
  67. if (nbytes == -1 && (
  68. WSAGetLastError () == WSAENETDOWN ||
  69. WSAGetLastError () == WSAENETRESET ||
  70. WSAGetLastError () == WSAEHOSTUNREACH ||
  71. WSAGetLastError () == WSAECONNABORTED ||
  72. WSAGetLastError () == WSAETIMEDOUT ||
  73. WSAGetLastError () == WSAECONNRESET))
  74. return -1;
  75. wsa_assert (nbytes != SOCKET_ERROR);
  76. return (size_t) nbytes;
  77. }
  78. int zmq::tcp_socket_t::read (void *data, int size)
  79. {
  80. int nbytes = recv (s, (char*) data, size, 0);
  81. // If not a single byte can be read from the socket in non-blocking mode
  82. // we'll get an error (this may happen during the speculative read).
  83. if (nbytes == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK)
  84. return 0;
  85. // Connection failure.
  86. if (nbytes == -1 && (
  87. WSAGetLastError () == WSAENETDOWN ||
  88. WSAGetLastError () == WSAENETRESET ||
  89. WSAGetLastError () == WSAECONNABORTED ||
  90. WSAGetLastError () == WSAETIMEDOUT ||
  91. WSAGetLastError () == WSAECONNRESET ||
  92. WSAGetLastError () == WSAECONNREFUSED ||
  93. WSAGetLastError () == WSAENOTCONN))
  94. return -1;
  95. wsa_assert (nbytes != SOCKET_ERROR);
  96. // Orderly shutdown by the other peer.
  97. if (nbytes == 0)
  98. return -1;
  99. return (size_t) nbytes;
  100. }
  101. #else
  102. #include <unistd.h>
  103. #include <sys/socket.h>
  104. #include <arpa/inet.h>
  105. #include <netinet/tcp.h>
  106. #include <netinet/in.h>
  107. #include <netdb.h>
  108. #include <fcntl.h>
  109. zmq::tcp_socket_t::tcp_socket_t () :
  110. s (retired_fd)
  111. {
  112. }
  113. zmq::tcp_socket_t::~tcp_socket_t ()
  114. {
  115. if (s != retired_fd)
  116. close ();
  117. }
  118. int zmq::tcp_socket_t::open (fd_t fd_, uint64_t sndbuf_, uint64_t rcvbuf_)
  119. {
  120. assert (s == retired_fd);
  121. s = fd_;
  122. if (sndbuf_) {
  123. int sz = (int) sndbuf_;
  124. int rc = setsockopt (s, SOL_SOCKET, SO_SNDBUF, &sz, sizeof (int));
  125. errno_assert (rc == 0);
  126. }
  127. if (rcvbuf_) {
  128. int sz = (int) rcvbuf_;
  129. int rc = setsockopt (s, SOL_SOCKET, SO_RCVBUF, &sz, sizeof (int));
  130. errno_assert (rc == 0);
  131. }
  132. #if defined ZMQ_HAVE_OSX || defined ZMQ_HAVE_FREEBSD
  133. int set = 1;
  134. int rc = setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof (int));
  135. errno_assert (rc == 0);
  136. #endif
  137. return 0;
  138. }
  139. int zmq::tcp_socket_t::close ()
  140. {
  141. zmq_assert (s != retired_fd);
  142. int rc = ::close (s);
  143. if (rc != 0)
  144. return -1;
  145. s = retired_fd;
  146. return 0;
  147. }
  148. zmq::fd_t zmq::tcp_socket_t::get_fd ()
  149. {
  150. return s;
  151. }
  152. int zmq::tcp_socket_t::write (const void *data, int size)
  153. {
  154. ssize_t nbytes = send (s, data, size, 0);
  155. // Several errors are OK. When speculative write is being done we may not
  156. // be able to write a single byte to the socket. Also, SIGSTOP issued
  157. // by a debugging tool can result in EINTR error.
  158. if (nbytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK ||
  159. errno == EINTR))
  160. return 0;
  161. // Signalise peer failure.
  162. if (nbytes == -1 && (errno == ECONNRESET || errno == EPIPE))
  163. return -1;
  164. if (nbytes == 1)
  165. fprintf (stderr, "E: unhandled error on send: %d/%s\n",
  166. errno, strerror (errno));
  167. errno_assert (nbytes != -1);
  168. return (size_t) nbytes;
  169. }
  170. int zmq::tcp_socket_t::read (void *data, int size)
  171. {
  172. ssize_t nbytes = recv (s, data, size, 0);
  173. // Several errors are OK. When speculative read is being done we may not
  174. // be able to read a single byte to the socket. Also, SIGSTOP issued
  175. // by a debugging tool can result in EINTR error.
  176. if (nbytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK ||
  177. errno == EINTR))
  178. return 0;
  179. // Signalise peer failure.
  180. if (nbytes == -1 && (errno == ECONNRESET || errno == ECONNREFUSED ||
  181. errno == ETIMEDOUT || errno == EHOSTUNREACH))
  182. return -1;
  183. if (nbytes == 1)
  184. fprintf (stderr, "E: unhandled error on recv: %d/%s\n",
  185. errno, strerror (errno));
  186. errno_assert (nbytes != -1);
  187. // Orderly shutdown by the other peer.
  188. if (nbytes == 0)
  189. return -1;
  190. return (size_t) nbytes;
  191. }
  192. #endif