socket.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. * Copyright (C)2005-2016 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. */
  22. #define _GNU_SOURCE
  23. #include "socket.h"
  24. #include <string.h>
  25. #ifdef OS_WINDOWS
  26. static int init_done = 0;
  27. static WSADATA init_data;
  28. # define POSIX_LABEL(x)
  29. # define HANDLE_EINTR(x)
  30. #else
  31. # include <sys/types.h>
  32. # include <sys/socket.h>
  33. # include <sys/time.h>
  34. # include <netinet/in.h>
  35. # include <netinet/tcp.h>
  36. # include <arpa/inet.h>
  37. # include <unistd.h>
  38. # include <netdb.h>
  39. # include <fcntl.h>
  40. # include <errno.h>
  41. # include <stdio.h>
  42. # include <poll.h>
  43. # define closesocket close
  44. # define SOCKET_ERROR (-1)
  45. # define POSIX_LABEL(x) x:
  46. # define HANDLE_EINTR(x) if( errno == EINTR ) goto x
  47. #endif
  48. #if defined(OS_WINDOWS) || defined(OS_MAC)
  49. # define MSG_NOSIGNAL 0
  50. #endif
  51. static int block_error() {
  52. #ifdef OS_WINDOWS
  53. int err = WSAGetLastError();
  54. if( err == WSAEWOULDBLOCK || err == WSAEALREADY )
  55. #else
  56. if( errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == EALREADY )
  57. #endif
  58. return PS_BLOCK;
  59. return PS_ERROR;
  60. }
  61. void psock_init() {
  62. #ifdef OS_WINDOWS
  63. if( !init_done ) {
  64. WSAStartup(MAKEWORD(2,0),&init_data);
  65. init_done = 1;
  66. }
  67. #endif
  68. }
  69. PSOCK psock_create() {
  70. PSOCK s = socket(AF_INET,SOCK_STREAM,0);
  71. # if defined(OS_MAC) || defined(OS_BSD)
  72. if( s != INVALID_SOCKET )
  73. setsockopt(s,SOL_SOCKET,SO_NOSIGPIPE,NULL,0);
  74. # endif
  75. # ifdef OS_POSIX
  76. // we don't want sockets to be inherited in case of exec
  77. {
  78. int old = fcntl(s,F_GETFD,0);
  79. if( old >= 0 ) fcntl(s,F_SETFD,old|FD_CLOEXEC);
  80. }
  81. # endif
  82. return s;
  83. }
  84. void psock_close( PSOCK s ) {
  85. POSIX_LABEL(close_again);
  86. if( closesocket(s) ) {
  87. HANDLE_EINTR(close_again);
  88. }
  89. }
  90. int psock_send( PSOCK s, const char *buf, int size ) {
  91. int ret;
  92. POSIX_LABEL(send_again);
  93. ret = send(s,buf,size,MSG_NOSIGNAL);
  94. if( ret == SOCKET_ERROR ) {
  95. HANDLE_EINTR(send_again);
  96. return block_error();
  97. }
  98. return ret;
  99. }
  100. int psock_recv( PSOCK s, char *buf, int size ) {
  101. int ret;
  102. POSIX_LABEL(recv_again);
  103. ret = recv(s,buf,size,MSG_NOSIGNAL);
  104. if( ret == SOCKET_ERROR ) {
  105. HANDLE_EINTR(recv_again);
  106. return block_error();
  107. }
  108. return ret;
  109. }
  110. PHOST phost_resolve( const char *host ) {
  111. PHOST ip = inet_addr(host);
  112. if( ip == INADDR_NONE ) {
  113. struct hostent *h;
  114. # if defined(OS_WINDOWS) || defined(OS_MAC) || defined(OS_CYGWIN)
  115. h = gethostbyname(host);
  116. # else
  117. struct hostent hbase;
  118. char buf[1024];
  119. int errcode;
  120. gethostbyname_r(host,&hbase,buf,1024,&h,&errcode);
  121. # endif
  122. if( h == NULL )
  123. return UNRESOLVED_HOST;
  124. ip = *((unsigned int*)h->h_addr_list[0]);
  125. }
  126. return ip;
  127. }
  128. SERR psock_connect( PSOCK s, PHOST host, int port ) {
  129. struct sockaddr_in addr;
  130. memset(&addr,0,sizeof(addr));
  131. addr.sin_family = AF_INET;
  132. addr.sin_port = htons(port);
  133. *(int*)&addr.sin_addr.s_addr = host;
  134. if( connect(s,(struct sockaddr*)&addr,sizeof(addr)) != 0 )
  135. return block_error();
  136. return PS_OK;
  137. }
  138. SERR psock_set_timeout( PSOCK s, double t ) {
  139. #ifdef OS_WINDOWS
  140. int time = (int)(t * 1000);
  141. #else
  142. struct timeval time;
  143. time.tv_usec = (int)((t - (int)t)*1000000);
  144. time.tv_sec = (int)t;
  145. #endif
  146. if( setsockopt(s,SOL_SOCKET,SO_SNDTIMEO,(char*)&time,sizeof(time)) != 0 )
  147. return PS_ERROR;
  148. if( setsockopt(s,SOL_SOCKET,SO_RCVTIMEO,(char*)&time,sizeof(time)) != 0 )
  149. return PS_ERROR;
  150. return PS_OK;
  151. }
  152. SERR psock_set_blocking( PSOCK s, int block ) {
  153. #ifdef OS_WINDOWS
  154. {
  155. unsigned long arg = !block;
  156. if( ioctlsocket(s,FIONBIO,&arg) != 0 )
  157. return PS_ERROR;
  158. }
  159. #else
  160. {
  161. int rights = fcntl(s,F_GETFL);
  162. if( rights == -1 )
  163. return PS_ERROR;
  164. if( block )
  165. rights &= ~O_NONBLOCK;
  166. else
  167. rights |= O_NONBLOCK;
  168. if( fcntl(s,F_SETFL,rights) == -1 )
  169. return PS_ERROR;
  170. }
  171. #endif
  172. return PS_OK;
  173. }
  174. SERR psock_set_fastsend( PSOCK s, int fast ) {
  175. if( setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char*)&fast,sizeof(fast)) )
  176. return block_error();
  177. return PS_OK;
  178. }
  179. void psock_wait( PSOCK s ) {
  180. # ifdef OS_WINDOWS
  181. fd_set set;
  182. FD_ZERO(&set);
  183. FD_SET(s,&set);
  184. select((int)s+1,&set,NULL,NULL,NULL);
  185. # else
  186. struct pollfd fds;
  187. POSIX_LABEL(poll_again);
  188. fds.fd = s;
  189. fds.events = POLLIN;
  190. fds.revents = 0;
  191. if( poll(&fds,1,-1) < 0 ) {
  192. HANDLE_EINTR(poll_again);
  193. }
  194. # endif
  195. }
  196. /* ************************************************************************ */