PageRenderTime 95ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/xp/net/Socket.cpp

http://xpkit.googlecode.com/
C++ | 446 lines | 343 code | 62 blank | 41 comment | 91 complexity | ad09d63cc4f59a211723e896b1c098e8 MD5 | raw file
Possible License(s): Apache-2.0
  1. /*
  2. * $Id: Socket.cpp 50 2009-02-10 05:48:05Z hyunghwan.chung $
  3. *
  4. Copyright 2005-2009 Chung, Hyung-Hwan.
  5. Licensed under the Apache License, Version 2.0 (the "License");
  6. you may not use this file except in compliance with the License.
  7. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. */
  15. #include <xp/net/Socket.hpp>
  16. #include <xp/net/InetAddress.hpp>
  17. #include <xp/bas/string.h>
  18. #include <xp/bas/memory.h>
  19. #include <xp/bas/locale.h>
  20. #include <xp/bas/errno.h>
  21. #include <xp/bas/assert.h>
  22. #ifndef _WIN32
  23. #include <netinet/in.h>
  24. #include <net/if.h>
  25. #endif
  26. namespace xp
  27. {
  28. namespace net
  29. {
  30. int Socket::v6_supported = 0;
  31. Socket::Socket (int type)
  32. {
  33. // NOTICE:
  34. // The socket can't be created in the constructor
  35. // as the implementaion is intended to support both
  36. // ipv4 and ipv6 seamlessly. The new name resolution
  37. // API's don't effectively allow the creation of socket
  38. // before the successful name lookup. So the lazy creation
  39. // of sockets is empolyed.
  40. this->socket_type = type;
  41. this->sckhnd = INVALID_HANDLE;
  42. this->error_code = ERR_NONE;
  43. disableTimeout ();
  44. }
  45. Socket::~Socket ()
  46. {
  47. close ();
  48. }
  49. int Socket::startup (bool try_v6)
  50. {
  51. xp_sck_t sck;
  52. if (::xp_sckstartup() == -1) return -1;
  53. if (try_v6) {
  54. if (::xp_sck_open (&sck,
  55. InetAddress::V6, Socket::DATAGRAM, 0) == XP_NULL) {
  56. #ifdef _WIN32
  57. if (XP_NET_SOCKET_ERRNO == WSAEAFNOSUPPORT) {
  58. #else
  59. if (XP_NET_SOCKET_ERRNO == EAFNOSUPPORT ||
  60. XP_NET_SOCKET_ERRNO == ENOSYS) {
  61. #endif
  62. v6_supported = -1;
  63. }
  64. }
  65. else {
  66. ::xp_sck_close (&sck);
  67. v6_supported = 1;
  68. }
  69. }
  70. else v6_supported = -1;
  71. return 0;
  72. }
  73. int Socket::cleanup ()
  74. {
  75. return ::xp_sckcleanup ();
  76. }
  77. int Socket::open (Handle handle)
  78. {
  79. XP_NET_SOCKET_CHECK_OPEN_HANDLE(this->sckhnd);
  80. int tmp;
  81. len_t len = sizeof(tmp);
  82. if (xp_sck_openhnd(this, handle) == XP_NULL) return -1;
  83. if (xp_sck_getopt (this,
  84. SOL_SOCKET, SO_TYPE, (char*)&tmp, &len) == -1) {
  85. this->error_code = ERR_TYPE_RETRIEVAL;
  86. xp_sck_forfeit (this);
  87. this->sckhnd = INVALID_HANDLE;
  88. return -1;
  89. }
  90. if (this->socket_type != 0 &&
  91. this->socket_type != tmp) {
  92. xp_sck_forfeit (this);
  93. this->error_code = ERR_TYPE_MISMATCH;
  94. return -1;
  95. }
  96. this->socket_type = tmp;
  97. return 0;
  98. }
  99. int Socket::close ()
  100. {
  101. XP_NET_SOCKET_CHECK_CLOSED_HANDLE(this->sckhnd);
  102. int n = ::xp_sck_close (this);
  103. if (n == -1) {
  104. this->error_code = translate_errno (
  105. XP_NET_SOCKET_ERRNO, ERR_GENERAL);
  106. }
  107. else this->sckhnd = INVALID_HANDLE;
  108. return n;
  109. }
  110. int Socket::shutdown (int how)
  111. {
  112. XP_NET_SOCKET_CHECK_CLOSED_HANDLE(this->sckhnd);
  113. int n = ::xp_sck_shtdwn (this, how);
  114. if (n == -1) {
  115. this->error_code = translate_errno (
  116. XP_NET_SOCKET_ERRNO, ERR_GENERAL);
  117. }
  118. return n;
  119. }
  120. xp_ssize_t Socket::send (
  121. const void* data, xp_size_t size, int flags)
  122. {
  123. XP_NET_SOCKET_CHECK_CLOSED_HANDLE(this->sckhnd);
  124. int n = ::xp_sck_send (this, data, size, flags);
  125. if (n == -1) {
  126. this->error_code = translate_errno (
  127. XP_NET_SOCKET_ERRNO, ERR_GENERAL);
  128. }
  129. return n;
  130. }
  131. xp_ssize_t Socket::sendAll (const void* data, xp_size_t size, int flags)
  132. {
  133. XP_NET_SOCKET_CHECK_CLOSED_HANDLE(this->sckhnd);
  134. int n = ::xp_sck_sendall (this, data, size, flags);
  135. if (n == -1) {
  136. this->error_code = translate_errno (
  137. XP_NET_SOCKET_ERRNO, ERR_GENERAL);
  138. }
  139. return n;
  140. }
  141. xp_ssize_t Socket::receive (void* buf, xp_size_t size, int flags)
  142. {
  143. XP_NET_SOCKET_CHECK_CLOSED_HANDLE(this->sckhnd);
  144. int n = ::xp_sck_recv (this, buf, size, flags);
  145. if (n == -1) {
  146. this->error_code = translate_errno (
  147. XP_NET_SOCKET_ERRNO, ERR_GENERAL);
  148. }
  149. return n;
  150. }
  151. xp_ssize_t Socket::receiveAll (void* buf, xp_size_t size, int flags)
  152. {
  153. XP_NET_SOCKET_CHECK_CLOSED_HANDLE(this->sckhnd);
  154. int n = ::xp_sck_recvall (this, buf, size, flags);
  155. if (n == -1) {
  156. this->error_code = translate_errno (
  157. XP_NET_SOCKET_ERRNO, ERR_GENERAL);
  158. }
  159. return n;
  160. }
  161. int Socket::getOption (
  162. int level, int optname, void* optval, len_t* optlen)
  163. {
  164. XP_NET_SOCKET_CHECK_CLOSED_HANDLE(this->sckhnd);
  165. int n = ::xp_sck_getopt (
  166. this, level, optname, (char*)optval, optlen);
  167. if (n == -1) {
  168. this->error_code = translate_errno (
  169. XP_NET_SOCKET_ERRNO, ERR_SOCKOPT);
  170. }
  171. return n;
  172. }
  173. int Socket::setOption (
  174. int level, int optname, const void* optval, len_t optlen)
  175. {
  176. XP_NET_SOCKET_CHECK_CLOSED_HANDLE(this->sckhnd);
  177. int n = ::xp_sck_setopt (
  178. this, level, optname, (const char*)optval, optlen);
  179. if (n == -1) {
  180. this->error_code = translate_errno (
  181. XP_NET_SOCKET_ERRNO, ERR_SOCKOPT);
  182. }
  183. return n;
  184. }
  185. int Socket::setDebug (int n)
  186. {
  187. return setOption (
  188. SOL_SOCKET, SO_DEBUG, (char*)&n, xp_sizeof(n));
  189. };
  190. int Socket::setReuseAddr (int n)
  191. {
  192. return setOption (
  193. SOL_SOCKET, SO_REUSEADDR, (char*)&n, xp_sizeof(n));
  194. }
  195. int Socket::setKeepAlive (int n)
  196. {
  197. return setOption (
  198. SOL_SOCKET, SO_KEEPALIVE, (char*)&n, xp_sizeof(n));
  199. }
  200. int Socket::setBroadcast (int n)
  201. {
  202. return setOption (
  203. SOL_SOCKET, SO_BROADCAST, (char*)&n, xp_sizeof(n));
  204. }
  205. int Socket::setSendBuf (unsigned int size)
  206. {
  207. return setOption (
  208. SOL_SOCKET, SO_SNDBUF, (char*)&size, xp_sizeof(size));
  209. }
  210. int Socket::setRecvBuf (unsigned int size)
  211. {
  212. return setOption (
  213. SOL_SOCKET, SO_RCVBUF, (char*)&size, xp_sizeof(size));
  214. }
  215. int Socket::setLingerOn (int sec)
  216. {
  217. struct linger lng;
  218. lng.l_onoff = 1;
  219. lng.l_linger = sec;
  220. return setOption (
  221. SOL_SOCKET, SO_LINGER, (char*)&lng, xp_sizeof(lng));
  222. }
  223. int Socket::setLingerOff ()
  224. {
  225. struct linger lng;
  226. lng.l_onoff = 0;
  227. lng.l_linger = 0;
  228. return setOption (SOL_SOCKET,
  229. SO_LINGER, (char*)&lng, xp_sizeof(lng));
  230. }
  231. int Socket::setTcpNodelay (int n)
  232. {
  233. #ifdef TCP_NODELAY
  234. return setOption (IPPROTO_TCP,
  235. TCP_NODELAY, (char*)&n, xp_sizeof(n));
  236. #else
  237. this->error_code = ERR_NOSUPPORT;
  238. return -1;
  239. #endif
  240. }
  241. int Socket::setOobInline (int n)
  242. {
  243. #ifdef SO_OOBINLINE
  244. return setOption (SOL_SOCKET,
  245. SO_OOBINLINE, (char*)&n, xp_sizeof(n));
  246. #else
  247. this->error_code = ERR_NOSUPPORT;
  248. return -1;
  249. #endif
  250. }
  251. int Socket::setIpv6Only (int n)
  252. {
  253. #ifdef IPV6_V6ONLY
  254. return setOption (IPPROTO_IPV6,
  255. IPV6_V6ONLY, (char*)&n, xp_sizeof(n));
  256. #else
  257. this->error_code = ERR_NOSUPPORT;
  258. return -1;
  259. #endif
  260. }
  261. int Socket::bindToDevice (const xp_char_t* device)
  262. {
  263. #ifdef SO_BINDTODEVICE
  264. if (device == XP_NULL) {
  265. return setOption (SOL_SOCKET,
  266. SO_BINDTODEVICE, XP_NULL, 0);
  267. }
  268. else {
  269. struct ifreq iface;
  270. xp_memset (&iface, 0, xp_sizeof(iface));
  271. #ifdef XP_CHAR_IS_MCHAR
  272. xp_strxcpy (iface.ifr_name, xp_countof(iface.ifr_name), device);
  273. #else
  274. if (xp_wcstomcs(device, iface.ifr_name,
  275. xp_countof(iface.ifr_name)) < xp_strlen(device)) {
  276. this->error_code = ERR_INVALID;
  277. return -1;
  278. };
  279. #endif
  280. return setOption (SOL_SOCKET,
  281. SO_BINDTODEVICE, (char*)&iface, xp_sizeof(iface));
  282. }
  283. #else
  284. this->error_code = ERR_NOSUPPORT;
  285. return -1;
  286. #endif
  287. }
  288. int Socket::unbindToDevice ()
  289. {
  290. return bindToDevice (XP_NULL);
  291. }
  292. int Socket::create_socket (int domain, int type, int proto)
  293. {
  294. xp_assert (this->sckhnd == INVALID_HANDLE);
  295. // domain adjustment
  296. if (domain == InetAddress::V0 &&
  297. v6_supported == -1) domain = InetAddress::V4;
  298. if (::xp_sck_open(this, domain, type, proto) == XP_NULL) {
  299. this->error_code = translate_errno (
  300. XP_NET_SOCKET_ERRNO, ERR_CREATE);
  301. return -1;
  302. }
  303. return 0;
  304. }
  305. int Socket::bind_socket (addr_t* addr, len_t len)
  306. {
  307. xp_assert (this->sckhnd != INVALID_HANDLE);
  308. int n = ::xp_sck_bind (this, addr, len);
  309. if (n == -1) {
  310. this->error_code = translate_errno (
  311. XP_NET_SOCKET_ERRNO, ERR_GENERAL);
  312. }
  313. return n;
  314. }
  315. int Socket::connect_socket (addr_t* addr, len_t len)
  316. {
  317. xp_assert (this->sckhnd != INVALID_HANDLE);
  318. xp_sck_setcancel (this, XP_SCK_CONN, NULL, NULL);
  319. int n = ::xp_sck_conn (this, addr, len);
  320. if (n == -1) {
  321. this->error_code = translate_errno (
  322. XP_NET_SOCKET_ERRNO, ERR_GENERAL);
  323. }
  324. return n;
  325. }
  326. int Socket::connect_socket (addr_t* addr, len_t len, xp_bool_t (*cancel) (void*))
  327. {
  328. xp_assert (this->sckhnd != INVALID_HANDLE);
  329. xp_sck_setcancel (this, XP_SCK_CONN, cancel, this);
  330. int n = ::xp_sck_conn (this, addr, len);
  331. if (n == -1) {
  332. this->error_code = translate_errno (
  333. XP_NET_SOCKET_ERRNO, ERR_GENERAL);
  334. }
  335. return n;
  336. }
  337. int Socket::listen_socket (int backlog)
  338. {
  339. xp_assert (this->sckhnd != INVALID_HANDLE);
  340. int n = ::xp_sck_lstn (this, backlog);
  341. if (n == -1) {
  342. this->error_code = translate_errno (
  343. XP_NET_SOCKET_ERRNO, ERR_GENERAL);
  344. }
  345. return n;
  346. }
  347. int Socket::translate_errno (int num, int def_err)
  348. {
  349. /*#ifdef _WIN32
  350. if (num == WSAETIMEDOUT) return ERR_TIMEDOUT;
  351. if (num == WSAECANCELED) return ERR_CANCELED;
  352. if (num == WSAEINVAL || num == WSAENOTSOCK)
  353. return ERR_INVALID;
  354. if (num == WSAEAFNOSUPPORT || num == WSAEPROTONOSUPPORT)
  355. return ERR_NOSUPPORT;
  356. if (num == WSAENOBUFS || num == WSAEMFILE)
  357. return ERR_NORESOURCE;
  358. if (num == WSAEACCES) return ERR_ACCESS;
  359. if (num == WSAEADDRINUSE) return ERR_ADDRINUSE;
  360. if (num == WSAECONNREFUSED) return ERR_REFUSED;
  361. if (num == WSAENOTCONN) return ERR_NOTCONNECTED;
  362. if (num == WSAENETUNREACH) return ERR_UNREACHABLE;
  363. #else*/
  364. if (num == XP_ETIMEDOUT) return ERR_TIMEDOUT;
  365. if (num == XP_ECANCELED) return ERR_CANCELED;
  366. if (num == XP_EBADF || num == XP_EINVAL || num == XP_ENOTSOCK)
  367. return ERR_INVALID;
  368. if (num == XP_EAFNOSUPPORT || num == XP_EPROTONOSUPPORT)
  369. return ERR_NOSUPPORT;
  370. if (num == XP_ENOMEM || num == XP_EMFILE || num == XP_EAGAIN)
  371. return ERR_NORESOURCE;
  372. if (num == XP_EACCES) return ERR_ACCESS;
  373. if (num == XP_EADDRINUSE) return ERR_ADDRINUSE;
  374. if (num == XP_ECONNREFUSED) return ERR_REFUSED;
  375. if (num == XP_ENOTCONN) return ERR_NOTCONNECTED;
  376. if (num == XP_ENETUNREACH) return ERR_UNREACHABLE;
  377. /*#endif*/
  378. return def_err;
  379. }
  380. }
  381. }