PageRenderTime 859ms CodeModel.GetById 57ms RepoModel.GetById 5ms app.codeStats 0ms

/ext/socket/init.c

https://github.com/awebneck/ruby
C | 616 lines | 515 code | 69 blank | 32 comment | 93 complexity | 9387241b0d967f59e27f951c9a3738d5 MD5 | raw file
  1. /************************************************
  2. init.c -
  3. created at: Thu Mar 31 12:21:29 JST 1994
  4. Copyright (C) 1993-2007 Yukihiro Matsumoto
  5. ************************************************/
  6. #include "rubysocket.h"
  7. VALUE rb_cBasicSocket;
  8. VALUE rb_cIPSocket;
  9. VALUE rb_cTCPSocket;
  10. VALUE rb_cTCPServer;
  11. VALUE rb_cUDPSocket;
  12. #ifdef AF_UNIX
  13. VALUE rb_cUNIXSocket;
  14. VALUE rb_cUNIXServer;
  15. #endif
  16. VALUE rb_cSocket;
  17. VALUE rb_cAddrinfo;
  18. VALUE rb_eSocket;
  19. #ifdef SOCKS
  20. VALUE rb_cSOCKSSocket;
  21. #endif
  22. int rsock_do_not_reverse_lookup = 1;
  23. void
  24. rsock_raise_socket_error(const char *reason, int error)
  25. {
  26. #ifdef EAI_SYSTEM
  27. if (error == EAI_SYSTEM) rb_sys_fail(reason);
  28. #endif
  29. rb_raise(rb_eSocket, "%s: %s", reason, gai_strerror(error));
  30. }
  31. VALUE
  32. rsock_init_sock(VALUE sock, int fd)
  33. {
  34. rb_io_t *fp;
  35. #ifndef _WIN32
  36. struct stat sbuf;
  37. if (fstat(fd, &sbuf) < 0)
  38. rb_sys_fail(0);
  39. rb_update_max_fd(fd);
  40. if (!S_ISSOCK(sbuf.st_mode))
  41. rb_raise(rb_eArgError, "not a socket file descriptor");
  42. #else
  43. rb_update_max_fd(fd);
  44. if (!rb_w32_is_socket(fd))
  45. rb_raise(rb_eArgError, "not a socket file descriptor");
  46. #endif
  47. MakeOpenFile(sock, fp);
  48. fp->fd = fd;
  49. fp->mode = FMODE_READWRITE|FMODE_DUPLEX;
  50. rb_io_ascii8bit_binmode(sock);
  51. if (rsock_do_not_reverse_lookup) {
  52. fp->mode |= FMODE_NOREVLOOKUP;
  53. }
  54. rb_io_synchronized(fp);
  55. return sock;
  56. }
  57. VALUE
  58. rsock_sendto_blocking(void *data)
  59. {
  60. struct rsock_send_arg *arg = data;
  61. VALUE mesg = arg->mesg;
  62. return (VALUE)sendto(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
  63. arg->flags, arg->to, arg->tolen);
  64. }
  65. VALUE
  66. rsock_send_blocking(void *data)
  67. {
  68. struct rsock_send_arg *arg = data;
  69. VALUE mesg = arg->mesg;
  70. return (VALUE)send(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
  71. arg->flags);
  72. }
  73. struct recvfrom_arg {
  74. int fd, flags;
  75. VALUE str;
  76. socklen_t alen;
  77. struct sockaddr_storage buf;
  78. };
  79. static VALUE
  80. recvfrom_blocking(void *data)
  81. {
  82. struct recvfrom_arg *arg = data;
  83. return (VALUE)recvfrom(arg->fd, RSTRING_PTR(arg->str), RSTRING_LEN(arg->str),
  84. arg->flags, (struct sockaddr*)&arg->buf, &arg->alen);
  85. }
  86. VALUE
  87. rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
  88. {
  89. rb_io_t *fptr;
  90. VALUE str, klass;
  91. struct recvfrom_arg arg;
  92. VALUE len, flg;
  93. long buflen;
  94. long slen;
  95. rb_scan_args(argc, argv, "11", &len, &flg);
  96. if (flg == Qnil) arg.flags = 0;
  97. else arg.flags = NUM2INT(flg);
  98. buflen = NUM2INT(len);
  99. GetOpenFile(sock, fptr);
  100. if (rb_io_read_pending(fptr)) {
  101. rb_raise(rb_eIOError, "recv for buffered IO");
  102. }
  103. arg.fd = fptr->fd;
  104. arg.alen = (socklen_t)sizeof(arg.buf);
  105. arg.str = str = rb_tainted_str_new(0, buflen);
  106. klass = RBASIC(str)->klass;
  107. RBASIC(str)->klass = 0;
  108. while (rb_io_check_closed(fptr),
  109. rb_thread_wait_fd(arg.fd),
  110. (slen = BLOCKING_REGION_FD(recvfrom_blocking, &arg)) < 0) {
  111. if (!rb_io_wait_readable(fptr->fd)) {
  112. rb_sys_fail("recvfrom(2)");
  113. }
  114. if (RBASIC(str)->klass || RSTRING_LEN(str) != buflen) {
  115. rb_raise(rb_eRuntimeError, "buffer string modified");
  116. }
  117. }
  118. RBASIC(str)->klass = klass;
  119. if (slen < RSTRING_LEN(str)) {
  120. rb_str_set_len(str, slen);
  121. }
  122. rb_obj_taint(str);
  123. switch (from) {
  124. case RECV_RECV:
  125. return str;
  126. case RECV_IP:
  127. #if 0
  128. if (arg.alen != sizeof(struct sockaddr_in)) {
  129. rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
  130. }
  131. #endif
  132. if (arg.alen && arg.alen != sizeof(arg.buf)) /* OSX doesn't return a from result for connection-oriented sockets */
  133. return rb_assoc_new(str, rsock_ipaddr((struct sockaddr*)&arg.buf, fptr->mode & FMODE_NOREVLOOKUP));
  134. else
  135. return rb_assoc_new(str, Qnil);
  136. #ifdef HAVE_SYS_UN_H
  137. case RECV_UNIX:
  138. return rb_assoc_new(str, rsock_unixaddr((struct sockaddr_un*)&arg.buf, arg.alen));
  139. #endif
  140. case RECV_SOCKET:
  141. return rb_assoc_new(str, rsock_io_socket_addrinfo(sock, (struct sockaddr*)&arg.buf, arg.alen));
  142. default:
  143. rb_bug("rsock_s_recvfrom called with bad value");
  144. }
  145. }
  146. VALUE
  147. rsock_s_recvfrom_nonblock(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
  148. {
  149. rb_io_t *fptr;
  150. VALUE str;
  151. struct sockaddr_storage buf;
  152. socklen_t alen = (socklen_t)sizeof buf;
  153. VALUE len, flg;
  154. long buflen;
  155. long slen;
  156. int fd, flags;
  157. VALUE addr = Qnil;
  158. rb_scan_args(argc, argv, "11", &len, &flg);
  159. if (flg == Qnil) flags = 0;
  160. else flags = NUM2INT(flg);
  161. buflen = NUM2INT(len);
  162. #ifdef MSG_DONTWAIT
  163. /* MSG_DONTWAIT avoids the race condition between fcntl and recvfrom.
  164. It is not portable, though. */
  165. flags |= MSG_DONTWAIT;
  166. #endif
  167. GetOpenFile(sock, fptr);
  168. if (rb_io_read_pending(fptr)) {
  169. rb_raise(rb_eIOError, "recvfrom for buffered IO");
  170. }
  171. fd = fptr->fd;
  172. str = rb_tainted_str_new(0, buflen);
  173. rb_io_check_closed(fptr);
  174. rb_io_set_nonblock(fptr);
  175. slen = recvfrom(fd, RSTRING_PTR(str), buflen, flags, (struct sockaddr*)&buf, &alen);
  176. if (slen < 0) {
  177. switch (errno) {
  178. case EAGAIN:
  179. #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
  180. case EWOULDBLOCK:
  181. #endif
  182. rb_mod_sys_fail(rb_mWaitReadable, "recvfrom(2) would block");
  183. }
  184. rb_sys_fail("recvfrom(2)");
  185. }
  186. if (slen < RSTRING_LEN(str)) {
  187. rb_str_set_len(str, slen);
  188. }
  189. rb_obj_taint(str);
  190. switch (from) {
  191. case RECV_RECV:
  192. return str;
  193. case RECV_IP:
  194. if (alen && alen != sizeof(buf)) /* connection-oriented socket may not return a from result */
  195. addr = rsock_ipaddr((struct sockaddr*)&buf, fptr->mode & FMODE_NOREVLOOKUP);
  196. break;
  197. case RECV_SOCKET:
  198. addr = rsock_io_socket_addrinfo(sock, (struct sockaddr*)&buf, alen);
  199. break;
  200. default:
  201. rb_bug("rsock_s_recvfrom_nonblock called with bad value");
  202. }
  203. return rb_assoc_new(str, addr);
  204. }
  205. static int
  206. rsock_socket0(int domain, int type, int proto)
  207. {
  208. int ret;
  209. #ifdef SOCK_CLOEXEC
  210. static int try_sock_cloexec = 1;
  211. if (try_sock_cloexec) {
  212. ret = socket(domain, type|SOCK_CLOEXEC, proto);
  213. if (ret == -1 && errno == EINVAL) {
  214. /* SOCK_CLOEXEC is available since Linux 2.6.27. Linux 2.6.18 fails with EINVAL */
  215. ret = socket(domain, type, proto);
  216. if (ret != -1) {
  217. try_sock_cloexec = 0;
  218. }
  219. }
  220. }
  221. else {
  222. ret = socket(domain, type, proto);
  223. }
  224. #else
  225. ret = socket(domain, type, proto);
  226. #endif
  227. if (ret == -1)
  228. return -1;
  229. rb_fd_fix_cloexec(ret);
  230. return ret;
  231. }
  232. int
  233. rsock_socket(int domain, int type, int proto)
  234. {
  235. int fd;
  236. fd = rsock_socket0(domain, type, proto);
  237. if (fd < 0) {
  238. if (errno == EMFILE || errno == ENFILE) {
  239. rb_gc();
  240. fd = rsock_socket0(domain, type, proto);
  241. }
  242. }
  243. if (0 <= fd)
  244. rb_update_max_fd(fd);
  245. return fd;
  246. }
  247. static int
  248. wait_connectable(int fd)
  249. {
  250. int sockerr;
  251. socklen_t sockerrlen;
  252. int revents;
  253. int ret;
  254. for (;;) {
  255. /*
  256. * Stevens book says, succuessful finish turn on RB_WAITFD_OUT and
  257. * failure finish turn on both RB_WAITFD_IN and RB_WAITFD_OUT.
  258. */
  259. revents = rb_wait_for_single_fd(fd, RB_WAITFD_IN|RB_WAITFD_OUT, NULL);
  260. if (revents & (RB_WAITFD_IN|RB_WAITFD_OUT)) {
  261. sockerrlen = (socklen_t)sizeof(sockerr);
  262. ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
  263. /*
  264. * Solaris getsockopt(SO_ERROR) return -1 and set errno
  265. * in getsockopt(). Let's return immediately.
  266. */
  267. if (ret < 0)
  268. break;
  269. if (sockerr == 0)
  270. continue; /* workaround for winsock */
  271. /* BSD and Linux use sockerr. */
  272. errno = sockerr;
  273. ret = -1;
  274. break;
  275. }
  276. if ((revents & (RB_WAITFD_IN|RB_WAITFD_OUT)) == RB_WAITFD_OUT) {
  277. ret = 0;
  278. break;
  279. }
  280. }
  281. return ret;
  282. }
  283. #ifdef __CYGWIN__
  284. #define WAIT_IN_PROGRESS 10
  285. #endif
  286. #ifdef __APPLE__
  287. #define WAIT_IN_PROGRESS 10
  288. #endif
  289. #ifdef __linux__
  290. /* returns correct error */
  291. #define WAIT_IN_PROGRESS 0
  292. #endif
  293. #ifndef WAIT_IN_PROGRESS
  294. /* BSD origin code apparently has a problem */
  295. #define WAIT_IN_PROGRESS 1
  296. #endif
  297. struct connect_arg {
  298. int fd;
  299. const struct sockaddr *sockaddr;
  300. socklen_t len;
  301. };
  302. static VALUE
  303. connect_blocking(void *data)
  304. {
  305. struct connect_arg *arg = data;
  306. return (VALUE)connect(arg->fd, arg->sockaddr, arg->len);
  307. }
  308. #if defined(SOCKS) && !defined(SOCKS5)
  309. static VALUE
  310. socks_connect_blocking(void *data)
  311. {
  312. struct connect_arg *arg = data;
  313. return (VALUE)Rconnect(arg->fd, arg->sockaddr, arg->len);
  314. }
  315. #endif
  316. int
  317. rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks)
  318. {
  319. int status;
  320. rb_blocking_function_t *func = connect_blocking;
  321. struct connect_arg arg;
  322. #if WAIT_IN_PROGRESS > 0
  323. int wait_in_progress = -1;
  324. int sockerr;
  325. socklen_t sockerrlen;
  326. #endif
  327. arg.fd = fd;
  328. arg.sockaddr = sockaddr;
  329. arg.len = len;
  330. #if defined(SOCKS) && !defined(SOCKS5)
  331. if (socks) func = socks_connect_blocking;
  332. #endif
  333. for (;;) {
  334. status = (int)BLOCKING_REGION_FD(func, &arg);
  335. if (status < 0) {
  336. switch (errno) {
  337. case EINTR:
  338. #if defined(ERESTART)
  339. case ERESTART:
  340. #endif
  341. continue;
  342. case EAGAIN:
  343. #ifdef EINPROGRESS
  344. case EINPROGRESS:
  345. #endif
  346. #if WAIT_IN_PROGRESS > 0
  347. sockerrlen = (socklen_t)sizeof(sockerr);
  348. status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
  349. if (status) break;
  350. if (sockerr) {
  351. status = -1;
  352. errno = sockerr;
  353. break;
  354. }
  355. #endif
  356. #ifdef EALREADY
  357. case EALREADY:
  358. #endif
  359. #if WAIT_IN_PROGRESS > 0
  360. wait_in_progress = WAIT_IN_PROGRESS;
  361. #endif
  362. status = wait_connectable(fd);
  363. if (status) {
  364. break;
  365. }
  366. errno = 0;
  367. continue;
  368. #if WAIT_IN_PROGRESS > 0
  369. case EINVAL:
  370. if (wait_in_progress-- > 0) {
  371. /*
  372. * connect() after EINPROGRESS returns EINVAL on
  373. * some platforms, need to check true error
  374. * status.
  375. */
  376. sockerrlen = (socklen_t)sizeof(sockerr);
  377. status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
  378. if (!status && !sockerr) {
  379. struct timeval tv = {0, 100000};
  380. rb_thread_wait_for(tv);
  381. continue;
  382. }
  383. status = -1;
  384. errno = sockerr;
  385. }
  386. break;
  387. #endif
  388. #ifdef EISCONN
  389. case EISCONN:
  390. status = 0;
  391. errno = 0;
  392. break;
  393. #endif
  394. default:
  395. break;
  396. }
  397. }
  398. return status;
  399. }
  400. }
  401. static void
  402. make_fd_nonblock(int fd)
  403. {
  404. int flags;
  405. #ifdef F_GETFL
  406. flags = fcntl(fd, F_GETFL);
  407. if (flags == -1) {
  408. rb_sys_fail(0);
  409. }
  410. #else
  411. flags = 0;
  412. #endif
  413. flags |= O_NONBLOCK;
  414. if (fcntl(fd, F_SETFL, flags) == -1) {
  415. rb_sys_fail(0);
  416. }
  417. }
  418. static int
  419. cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len)
  420. {
  421. int ret;
  422. #ifdef HAVE_ACCEPT4
  423. static int try_accept4 = 1;
  424. if (try_accept4) {
  425. ret = accept4(socket, address, address_len, SOCK_CLOEXEC);
  426. /* accept4 is available since Linux 2.6.28, glibc 2.10. */
  427. if (ret != -1) {
  428. if (ret <= 2)
  429. rb_maygvl_fd_fix_cloexec(ret);
  430. return ret;
  431. }
  432. if (errno == ENOSYS) {
  433. try_accept4 = 0;
  434. ret = accept(socket, address, address_len);
  435. }
  436. }
  437. else {
  438. ret = accept(socket, address, address_len);
  439. }
  440. #else
  441. ret = accept(socket, address, address_len);
  442. #endif
  443. if (ret == -1) return -1;
  444. rb_maygvl_fd_fix_cloexec(ret);
  445. return ret;
  446. }
  447. VALUE
  448. rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
  449. {
  450. int fd2;
  451. rb_secure(3);
  452. rb_io_set_nonblock(fptr);
  453. fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len);
  454. if (fd2 < 0) {
  455. switch (errno) {
  456. case EAGAIN:
  457. #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
  458. case EWOULDBLOCK:
  459. #endif
  460. case ECONNABORTED:
  461. #if defined EPROTO
  462. case EPROTO:
  463. #endif
  464. rb_mod_sys_fail(rb_mWaitReadable, "accept(2) would block");
  465. }
  466. rb_sys_fail("accept(2)");
  467. }
  468. rb_update_max_fd(fd2);
  469. make_fd_nonblock(fd2);
  470. return rsock_init_sock(rb_obj_alloc(klass), fd2);
  471. }
  472. struct accept_arg {
  473. int fd;
  474. struct sockaddr *sockaddr;
  475. socklen_t *len;
  476. };
  477. static VALUE
  478. accept_blocking(void *data)
  479. {
  480. struct accept_arg *arg = data;
  481. return (VALUE)cloexec_accept(arg->fd, arg->sockaddr, arg->len);
  482. }
  483. VALUE
  484. rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len)
  485. {
  486. int fd2;
  487. int retry = 0;
  488. struct accept_arg arg;
  489. rb_secure(3);
  490. arg.fd = fd;
  491. arg.sockaddr = sockaddr;
  492. arg.len = len;
  493. retry:
  494. rb_thread_wait_fd(fd);
  495. fd2 = (int)BLOCKING_REGION_FD(accept_blocking, &arg);
  496. if (fd2 < 0) {
  497. switch (errno) {
  498. case EMFILE:
  499. case ENFILE:
  500. if (retry) break;
  501. rb_gc();
  502. retry = 1;
  503. goto retry;
  504. default:
  505. if (!rb_io_wait_readable(fd)) break;
  506. retry = 0;
  507. goto retry;
  508. }
  509. rb_sys_fail(0);
  510. }
  511. rb_update_max_fd(fd2);
  512. if (!klass) return INT2NUM(fd2);
  513. return rsock_init_sock(rb_obj_alloc(klass), fd2);
  514. }
  515. int
  516. rsock_getfamily(int sockfd)
  517. {
  518. struct sockaddr_storage ss;
  519. socklen_t sslen = (socklen_t)sizeof(ss);
  520. ss.ss_family = AF_UNSPEC;
  521. if (getsockname(sockfd, (struct sockaddr*)&ss, &sslen) < 0)
  522. return AF_UNSPEC;
  523. return ss.ss_family;
  524. }
  525. void
  526. rsock_init_socket_init()
  527. {
  528. /*
  529. * SocketError is the error class for socket.
  530. */
  531. rb_eSocket = rb_define_class("SocketError", rb_eStandardError);
  532. rsock_init_ipsocket();
  533. rsock_init_tcpsocket();
  534. rsock_init_tcpserver();
  535. rsock_init_sockssocket();
  536. rsock_init_udpsocket();
  537. rsock_init_unixsocket();
  538. rsock_init_unixserver();
  539. rsock_init_sockopt();
  540. rsock_init_ancdata();
  541. rsock_init_addrinfo();
  542. rsock_init_socket_constants();
  543. }