PageRenderTime 85ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 2ms

/ext/socket/socket.c

http://github.com/MacRuby/MacRuby
C | 6607 lines | 3911 code | 575 blank | 2121 comment | 708 complexity | 3e0615e38a3c23a30f1ec0a06234c95d MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. /************************************************
  2. socket.c -
  3. $Author: akr $
  4. created at: Thu Mar 31 12:21:29 JST 1994
  5. Copyright (C) 1993-2007 Yukihiro Matsumoto
  6. ************************************************/
  7. #include "macruby_internal.h"
  8. #include "ruby/io.h"
  9. #include "ruby/signal.h"
  10. #include "ruby/util.h"
  11. #include <stdio.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #ifdef HAVE_UNISTD_H
  15. #include <unistd.h>
  16. #endif
  17. #ifdef HAVE_SYS_UIO_H
  18. #include <sys/uio.h>
  19. #endif
  20. #ifdef HAVE_XTI_H
  21. #include <xti.h>
  22. #endif
  23. #ifndef _WIN32
  24. #if defined(__BEOS__)
  25. # include <net/socket.h>
  26. #else
  27. # include <sys/socket.h>
  28. #endif
  29. #include <netinet/in.h>
  30. #ifdef HAVE_NETINET_IN_SYSTM_H
  31. # include <netinet/in_systm.h>
  32. #endif
  33. #ifdef HAVE_NETINET_TCP_H
  34. # include <netinet/tcp.h>
  35. #endif
  36. #ifdef HAVE_NETINET_UDP_H
  37. # include <netinet/udp.h>
  38. #endif
  39. #ifdef HAVE_ARPA_INET_H
  40. # include <arpa/inet.h>
  41. #endif
  42. #include <netdb.h>
  43. #endif
  44. #include <errno.h>
  45. #ifdef HAVE_SYS_UN_H
  46. #include <sys/un.h>
  47. #endif
  48. #if defined(HAVE_FCNTL)
  49. #ifdef HAVE_SYS_SELECT_H
  50. #include <sys/select.h>
  51. #endif
  52. #ifdef HAVE_SYS_TYPES_H
  53. #include <sys/types.h>
  54. #endif
  55. #ifdef HAVE_SYS_TIME_H
  56. #include <sys/time.h>
  57. #endif
  58. #ifdef HAVE_FCNTL_H
  59. #include <fcntl.h>
  60. #endif
  61. #endif
  62. #ifdef HAVE_IFADDRS_H
  63. #include <ifaddrs.h>
  64. #endif
  65. #ifdef HAVE_SYS_IOCTL_H
  66. #include <sys/ioctl.h>
  67. #endif
  68. #ifdef HAVE_SYS_SOCKIO_H
  69. #include <sys/sockio.h>
  70. #endif
  71. #ifdef HAVE_NET_IF_H
  72. #include <net/if.h>
  73. #endif
  74. #ifdef HAVE_SYS_PARAM_H
  75. #include <sys/param.h>
  76. #endif
  77. #ifdef HAVE_SYS_UCRED_H
  78. #include <sys/ucred.h>
  79. #endif
  80. #ifdef HAVE_UCRED_H
  81. #include <ucred.h>
  82. #endif
  83. #ifndef EWOULDBLOCK
  84. #define EWOULDBLOCK EAGAIN
  85. #endif
  86. #ifndef HAVE_GETADDRINFO
  87. # include "addrinfo.h"
  88. #endif
  89. #include "sockport.h"
  90. static int do_not_reverse_lookup = 1;
  91. #define FMODE_NOREVLOOKUP 0x100
  92. VALUE rb_cBasicSocket;
  93. VALUE rb_cIPSocket;
  94. VALUE rb_cTCPSocket;
  95. VALUE rb_cTCPServer;
  96. VALUE rb_cUDPSocket;
  97. #ifdef AF_UNIX
  98. VALUE rb_cUNIXSocket;
  99. VALUE rb_cUNIXServer;
  100. #endif
  101. VALUE rb_cSocket;
  102. static VALUE rb_cAddrinfo;
  103. static VALUE rb_eSocket;
  104. #define INET_CLIENT 0
  105. #define INET_SERVER 1
  106. #define INET_SOCKS 2
  107. #ifndef NI_MAXHOST
  108. # define NI_MAXHOST 1025
  109. #endif
  110. #ifndef NI_MAXSERV
  111. # define NI_MAXSERV 32
  112. #endif
  113. #ifdef AF_INET6
  114. # define IS_IP_FAMILY(af) ((af) == AF_INET || (af) == AF_INET6)
  115. #else
  116. # define IS_IP_FAMILY(af) ((af) == AF_INET)
  117. #endif
  118. #ifndef HAVE_SOCKADDR_STORAGE
  119. /*
  120. * RFC 2553: protocol-independent placeholder for socket addresses
  121. */
  122. #define _SS_MAXSIZE 128
  123. #define _SS_ALIGNSIZE (sizeof(double))
  124. #define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(unsigned char) * 2)
  125. #define _SS_PAD2SIZE (_SS_MAXSIZE - sizeof(unsigned char) * 2 - \
  126. _SS_PAD1SIZE - _SS_ALIGNSIZE)
  127. struct sockaddr_storage {
  128. #ifdef HAVE_SA_LEN
  129. unsigned char ss_len; /* address length */
  130. unsigned char ss_family; /* address family */
  131. #else
  132. unsigned short ss_family;
  133. #endif
  134. char __ss_pad1[_SS_PAD1SIZE];
  135. double __ss_align; /* force desired structure storage alignment */
  136. char __ss_pad2[_SS_PAD2SIZE];
  137. };
  138. #endif
  139. static void sock_define_const(char *name, int value);
  140. static void sock_define_uconst(const char *name, unsigned int value);
  141. #include "constants.h"
  142. static int str_is_number(const char *);
  143. /* fix [ruby-core:29427] */
  144. static int
  145. ruby_getaddrinfo__darwin(const char *nodename, const char *servname,
  146. struct addrinfo *hints, struct addrinfo **res)
  147. {
  148. const char *tmp_servname;
  149. struct addrinfo tmp_hints;
  150. tmp_servname = servname;
  151. MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
  152. if (nodename && servname) {
  153. if (str_is_number(tmp_servname) && atoi(servname) == 0) {
  154. tmp_servname = NULL;
  155. #ifdef AI_NUMERICSERV
  156. if (tmp_hints.ai_flags) tmp_hints.ai_flags &= ~AI_NUMERICSERV;
  157. #endif
  158. }
  159. }
  160. int error = getaddrinfo(nodename, tmp_servname, &tmp_hints, res);
  161. return error;
  162. }
  163. #undef getaddrinfo
  164. #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__darwin((node),(serv),(hints),(res))
  165. #if defined(INET6) && (defined(LOOKUP_ORDER_HACK_INET) || defined(LOOKUP_ORDER_HACK_INET6))
  166. #define LOOKUP_ORDERS 3
  167. static int lookup_order_table[LOOKUP_ORDERS] = {
  168. #if defined(LOOKUP_ORDER_HACK_INET)
  169. PF_INET, PF_INET6, PF_UNSPEC,
  170. #elif defined(LOOKUP_ORDER_HACK_INET6)
  171. PF_INET6, PF_INET, PF_UNSPEC,
  172. #else
  173. /* should not happen */
  174. #endif
  175. };
  176. static int
  177. ruby_getaddrinfo(char *nodename, char *servname,
  178. struct addrinfo *hints, struct addrinfo **res)
  179. {
  180. struct addrinfo tmp_hints;
  181. int i, af, error;
  182. if (hints->ai_family != PF_UNSPEC) {
  183. return getaddrinfo(nodename, servname, hints, res);
  184. }
  185. for (i = 0; i < LOOKUP_ORDERS; i++) {
  186. af = lookup_order_table[i];
  187. MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
  188. tmp_hints.ai_family = af;
  189. error = getaddrinfo(nodename, servname, &tmp_hints, res);
  190. if (error) {
  191. if (tmp_hints.ai_family == PF_UNSPEC) {
  192. break;
  193. }
  194. }
  195. else {
  196. break;
  197. }
  198. }
  199. return error;
  200. }
  201. #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo((node),(serv),(hints),(res))
  202. #endif
  203. #if defined(_AIX)
  204. static int
  205. ruby_getaddrinfo__aix(char *nodename, char *servname,
  206. struct addrinfo *hints, struct addrinfo **res)
  207. {
  208. int error = getaddrinfo(nodename, servname, hints, res);
  209. struct addrinfo *r;
  210. if (error)
  211. return error;
  212. for (r = *res; r != NULL; r = r->ai_next) {
  213. if (r->ai_addr->sa_family == 0)
  214. r->ai_addr->sa_family = r->ai_family;
  215. if (r->ai_addr->sa_len == 0)
  216. r->ai_addr->sa_len = r->ai_addrlen;
  217. }
  218. return 0;
  219. }
  220. #undef getaddrinfo
  221. #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__aix((node),(serv),(hints),(res))
  222. static int
  223. ruby_getnameinfo__aix(const struct sockaddr *sa, size_t salen,
  224. char *host, size_t hostlen,
  225. char *serv, size_t servlen, int flags)
  226. {
  227. struct sockaddr_in6 *sa6;
  228. u_int32_t *a6;
  229. if (sa->sa_family == AF_INET6) {
  230. sa6 = (struct sockaddr_in6 *)sa;
  231. a6 = sa6->sin6_addr.u6_addr.u6_addr32;
  232. if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) {
  233. strncpy(host, "::", hostlen);
  234. snprintf(serv, servlen, "%d", sa6->sin6_port);
  235. return 0;
  236. }
  237. }
  238. return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
  239. }
  240. #undef getnameinfo
  241. #define getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \
  242. ruby_getnameinfo__aix((sa), (salen), (host), (hostlen), (serv), (servlen), (flags))
  243. #ifndef CMSG_SPACE
  244. # define CMSG_SPACE(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len))
  245. #endif
  246. #ifndef CMSG_LEN
  247. # define CMSG_LEN(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
  248. #endif
  249. #endif
  250. #ifdef __BEOS__
  251. #undef close
  252. #define close closesocket
  253. #endif
  254. #define MakeOpenFile(obj, fp) \
  255. do { \
  256. fp = ALLOC(rb_io_t); \
  257. GC_WB(&RFILE(obj)->fptr, fp); \
  258. fp->fd = fp->read_fd = fp->write_fd = -1; \
  259. fp->pid = -1; \
  260. } \
  261. while (0)
  262. static int
  263. constant_arg(VALUE arg, int (*str_to_int)(char*, int, int*), const char *errmsg)
  264. {
  265. VALUE tmp;
  266. char *ptr;
  267. int ret;
  268. if (SYMBOL_P(arg)) {
  269. arg = rb_sym_to_s(arg);
  270. goto str;
  271. }
  272. else if (!NIL_P(tmp = rb_check_string_type(arg))) {
  273. arg = tmp;
  274. str:
  275. rb_check_safe_obj(arg);
  276. ptr = RSTRING_PTR(arg);
  277. if (str_to_int(ptr, RSTRING_LEN(arg), &ret) == -1)
  278. rb_raise(rb_eSocket, "%s: %s", errmsg, ptr);
  279. }
  280. else {
  281. ret = NUM2INT(arg);
  282. }
  283. return ret;
  284. }
  285. static int
  286. family_arg(VALUE domain)
  287. {
  288. /* convert AF_INET, etc. */
  289. return constant_arg(domain, family_to_int, "unknown socket domain");
  290. }
  291. static int
  292. socktype_arg(VALUE type)
  293. {
  294. /* convert SOCK_STREAM, etc. */
  295. return constant_arg(type, socktype_to_int, "unknown socket type");
  296. }
  297. static int
  298. level_arg(VALUE level)
  299. {
  300. /* convert SOL_SOCKET, IPPROTO_TCP, etc. */
  301. return constant_arg(level, level_to_int, "unknown protocol level");
  302. }
  303. static int
  304. optname_arg(int level, VALUE optname)
  305. {
  306. switch (level) {
  307. case SOL_SOCKET:
  308. return constant_arg(optname, so_optname_to_int, "unknown socket level option name");
  309. case IPPROTO_IP:
  310. return constant_arg(optname, ip_optname_to_int, "unknown IP level option name");
  311. #ifdef IPPROTO_IPV6
  312. case IPPROTO_IPV6:
  313. return constant_arg(optname, ipv6_optname_to_int, "unknown IPv6 level option name");
  314. #endif
  315. case IPPROTO_TCP:
  316. return constant_arg(optname, tcp_optname_to_int, "unknown TCP level option name");
  317. case IPPROTO_UDP:
  318. return constant_arg(optname, udp_optname_to_int, "unknown UDP level option name");
  319. default:
  320. return NUM2INT(optname);
  321. }
  322. }
  323. static int
  324. shutdown_how_arg(VALUE how)
  325. {
  326. /* convert SHUT_RD, SHUT_WR, SHUT_RDWR. */
  327. return constant_arg(how, shutdown_how_to_int, "unknown shutdown argument");
  328. }
  329. static VALUE
  330. init_sock(VALUE sock, int fd)
  331. {
  332. rb_io_t *fp;
  333. #ifdef S_ISSOCK
  334. struct stat sbuf;
  335. if (fstat(fd, &sbuf) < 0) {
  336. rb_sys_fail(0);
  337. }
  338. if (!S_ISSOCK(sbuf.st_mode)) {
  339. rb_raise(rb_eArgError, "not a socket file descriptor");
  340. }
  341. #endif
  342. MakeOpenFile(sock, fp);
  343. fp->fd = fp->read_fd = fp->write_fd = fd;
  344. fp->mode = FMODE_READWRITE|FMODE_DUPLEX;
  345. rb_io_ascii8bit_binmode(sock);
  346. if (do_not_reverse_lookup) {
  347. fp->mode |= FMODE_NOREVLOOKUP;
  348. }
  349. fp->mode |= FMODE_SYNC;
  350. return sock;
  351. }
  352. /*
  353. * call-seq:
  354. * BasicSocket.for_fd(fd) => basicsocket
  355. *
  356. * Returns a socket object which contains the file descriptor, _fd_.
  357. *
  358. * # If invoked by inetd, STDIN/STDOUT/STDERR is a socket.
  359. * STDIN_SOCK = Socket.for_fd(STDIN.fileno)
  360. * p STDIN_SOCK.remote_address
  361. *
  362. */
  363. static VALUE
  364. bsock_s_for_fd(VALUE klass, SEL sel, VALUE fd)
  365. {
  366. rb_io_t *fptr;
  367. VALUE sock = init_sock(rb_obj_alloc(klass), NUM2INT(fd));
  368. GetOpenFile(sock, fptr);
  369. return sock;
  370. }
  371. /*
  372. * call-seq:
  373. * basicsocket.shutdown([how]) => 0
  374. *
  375. * Calls shutdown(2) system call.
  376. *
  377. * s.shutdown(Socket::SHUT_RD) disallows further read.
  378. *
  379. * s.shutdown(Socket::SHUT_WR) disallows further write.
  380. *
  381. * s.shutdown(Socket::SHUT_RDWR) disallows further read and write.
  382. *
  383. * _how_ can be symbol or string:
  384. * - :RD, :SHUT_RD, "RD" and "SHUT_RD" are accepted as Socket::SHUT_RD.
  385. * - :WR, :SHUT_WR, "WR" and "SHUT_WR" are accepted as Socket::SHUT_WR.
  386. * - :RDWR, :SHUT_RDWR, "RDWR" and "SHUT_RDWR" are accepted as Socket::SHUT_RDWR.
  387. *
  388. * UNIXSocket.pair {|s1, s2|
  389. * s1.puts "ping"
  390. * s1.shutdown(:WR)
  391. * p s2.read #=> "ping\n"
  392. * s2.puts "pong"
  393. * s2.close
  394. * p s1.read #=> "pong\n"
  395. * }
  396. *
  397. */
  398. static VALUE
  399. bsock_shutdown(VALUE sock, SEL sel, int argc, VALUE *argv)
  400. {
  401. VALUE howto;
  402. int how;
  403. rb_io_t *fptr;
  404. if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
  405. rb_raise(rb_eSecurityError, "Insecure: can't shutdown socket");
  406. }
  407. rb_scan_args(argc, argv, "01", &howto);
  408. if (howto == Qnil)
  409. how = SHUT_RDWR;
  410. else {
  411. how = shutdown_how_arg(howto);
  412. if (how != SHUT_WR && how != SHUT_RD && how != SHUT_RDWR) {
  413. rb_raise(rb_eArgError, "`how' should be either :SHUT_RD, :SHUT_WR, :SHUT_RDWR");
  414. }
  415. }
  416. GetOpenFile(sock, fptr);
  417. if (shutdown(fptr->fd, how) == -1)
  418. rb_sys_fail(0);
  419. return INT2FIX(0);
  420. }
  421. /*
  422. * call-seq:
  423. * basicsocket.close_read => nil
  424. *
  425. * Disallows further read using shutdown system call.
  426. *
  427. * s1, s2 = UNIXSocket.pair
  428. * s1.close_read
  429. * s2.puts #=> Broken pipe (Errno::EPIPE)
  430. */
  431. static VALUE
  432. bsock_close_read(VALUE sock, SEL sel)
  433. {
  434. rb_io_t *fptr;
  435. if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
  436. rb_raise(rb_eSecurityError, "Insecure: can't close socket");
  437. }
  438. GetOpenFile(sock, fptr);
  439. shutdown(fptr->fd, 0);
  440. if (!(fptr->mode & FMODE_WRITABLE)) {
  441. return rb_io_close(sock);
  442. }
  443. fptr->mode &= ~FMODE_READABLE;
  444. fptr->read_fd = -1;
  445. return Qnil;
  446. }
  447. /*
  448. * call-seq:
  449. * basicsocket.close_write => nil
  450. *
  451. * Disallows further write using shutdown system call.
  452. *
  453. * UNIXSocket.pair {|s1, s2|
  454. * s1.print "ping"
  455. * s1.close_write
  456. * p s2.read #=> "ping"
  457. * s2.print "pong"
  458. * s2.close
  459. * p s1.read #=> "pong"
  460. * }
  461. */
  462. static VALUE
  463. bsock_close_write(VALUE sock, SEL sel)
  464. {
  465. rb_io_t *fptr;
  466. if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
  467. rb_raise(rb_eSecurityError, "Insecure: can't close socket");
  468. }
  469. GetOpenFile(sock, fptr);
  470. if (!(fptr->mode & FMODE_READABLE)) {
  471. return rb_io_close(sock);
  472. }
  473. shutdown(fptr->fd, 1);
  474. fptr->mode &= ~FMODE_WRITABLE;
  475. fptr->write_fd = -1;
  476. return Qnil;
  477. }
  478. /*
  479. * Document-method: setsockopt
  480. * call-seq:
  481. * setsockopt(level, optname, optval)
  482. * setsockopt(socketoption)
  483. *
  484. * Sets a socket option. These are protocol and system specific, see your
  485. * local system documentation for details.
  486. *
  487. * === Parameters
  488. * * +level+ is an integer, usually one of the SOL_ constants such as
  489. * Socket::SOL_SOCKET, or a protocol level.
  490. * A string or symbol of the name, possibly without prefix, is also
  491. * accepted.
  492. * * +optname+ is an integer, usually one of the SO_ constants, such
  493. * as Socket::SO_REUSEADDR.
  494. * A string or symbol of the name, possibly without prefix, is also
  495. * accepted.
  496. * * +optval+ is the value of the option, it is passed to the underlying
  497. * setsockopt() as a pointer to a certain number of bytes. How this is
  498. * done depends on the type:
  499. * - Fixnum: value is assigned to an int, and a pointer to the int is
  500. * passed, with length of sizeof(int).
  501. * - true or false: 1 or 0 (respectively) is assigned to an int, and the
  502. * int is passed as for a Fixnum. Note that +false+ must be passed,
  503. * not +nil+.
  504. * - String: the string's data and length is passed to the socket.
  505. * * +socketoption+ is an instance of Socket::Option
  506. *
  507. * === Examples
  508. *
  509. * Some socket options are integers with boolean values, in this case
  510. * #setsockopt could be called like this:
  511. * sock.setsockopt(:SOCKET, :REUSEADDR, true)
  512. * sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
  513. * sock.setsockopt(Socket::Option.bool(:INET, :SOCKET, :REUSEADDR, true))
  514. *
  515. * Some socket options are integers with numeric values, in this case
  516. * #setsockopt could be called like this:
  517. * sock.setsockopt(:IP, :TTL, 255)
  518. * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255)
  519. * sock.setsockopt(Socket::Option.int(:INET, :IP, :TTL, 255))
  520. *
  521. * Option values may be structs. Passing them can be complex as it involves
  522. * examining your system headers to determine the correct definition. An
  523. * example is an +ip_mreq+, which may be defined in your system headers as:
  524. * struct ip_mreq {
  525. * struct in_addr imr_multiaddr;
  526. * struct in_addr imr_interface;
  527. * };
  528. *
  529. * In this case #setsockopt could be called like this:
  530. * optval = IPAddr.new("224.0.0.251").hton +
  531. * IPAddr.new(Socket::INADDR_ANY, Socket::AF_INET).hton
  532. * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval)
  533. *
  534. */
  535. static VALUE
  536. bsock_setsockopt(VALUE sock, SEL sel, VALUE lev, VALUE optname, VALUE val)
  537. {
  538. int level, option;
  539. rb_io_t *fptr;
  540. int i;
  541. const char *v;
  542. int vlen;
  543. rb_secure(2);
  544. level = level_arg(lev);
  545. option = optname_arg(level, optname);
  546. switch (TYPE(val)) {
  547. case T_FIXNUM:
  548. i = FIX2INT(val);
  549. goto numval;
  550. case T_FALSE:
  551. i = 0;
  552. goto numval;
  553. case T_TRUE:
  554. i = 1;
  555. numval:
  556. v = (char*)&i; vlen = (int)sizeof(i);
  557. break;
  558. default:
  559. StringValue(val);
  560. v = RSTRING_PTR(val);
  561. vlen = RSTRING_LENINT(val);
  562. break;
  563. }
  564. #define rb_sys_fail_path(path) rb_sys_fail(path == 0 ? NULL : RSTRING_PTR(path));
  565. GetOpenFile(sock, fptr);
  566. if (setsockopt(fptr->fd, level, option, v, vlen) < 0)
  567. rb_sys_fail_path(fptr->path);
  568. return INT2FIX(0);
  569. }
  570. /*
  571. * Document-method: getsockopt
  572. * call-seq:
  573. * getsockopt(level, optname) => socketoption
  574. *
  575. * Gets a socket option. These are protocol and system specific, see your
  576. * local system documentation for details. The option is returned as
  577. * a Socket::Option object.
  578. *
  579. * === Parameters
  580. * * +level+ is an integer, usually one of the SOL_ constants such as
  581. * Socket::SOL_SOCKET, or a protocol level.
  582. * A string or symbol of the name, possibly without prefix, is also
  583. * accepted.
  584. * * +optname+ is an integer, usually one of the SO_ constants, such
  585. * as Socket::SO_REUSEADDR.
  586. * A string or symbol of the name, possibly without prefix, is also
  587. * accepted.
  588. *
  589. * === Examples
  590. *
  591. * Some socket options are integers with boolean values, in this case
  592. * #getsockopt could be called like this:
  593. *
  594. * reuseaddr = sock.getsockopt(:SOCKET, :REUSEADDR).bool
  595. *
  596. * optval = sock.getsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR)
  597. * optval = optval.unpack "i"
  598. * reuseaddr = optval[0] == 0 ? false : true
  599. *
  600. * Some socket options are integers with numeric values, in this case
  601. * #getsockopt could be called like this:
  602. *
  603. * ipttl = sock.getsockopt(:IP, :TTL).int
  604. *
  605. * optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL)
  606. * ipttl = optval.unpack("i")[0]
  607. *
  608. * Option values may be structs. Decoding them can be complex as it involves
  609. * examining your system headers to determine the correct definition. An
  610. * example is a +struct linger+, which may be defined in your system headers
  611. * as:
  612. * struct linger {
  613. * int l_onoff;
  614. * int l_linger;
  615. * };
  616. *
  617. * In this case #getsockopt could be called like this:
  618. *
  619. * # Socket::Option knows linger structure.
  620. * onoff, linger = sock.getsockopt(:SOCKET, :LINGER).linger
  621. *
  622. * optval = sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER)
  623. * onoff, linger = optval.unpack "ii"
  624. * onoff = onoff == 0 ? false : true
  625. */
  626. static VALUE
  627. bsock_getsockopt(VALUE sock, SEL sel, VALUE lev, VALUE optname)
  628. {
  629. #if !defined(__BEOS__)
  630. int level, option;
  631. socklen_t len;
  632. char *buf;
  633. rb_io_t *fptr;
  634. level = level_arg(lev);
  635. option = optname_arg(level, optname);
  636. len = 256;
  637. buf = ALLOCA_N(char,len);
  638. GetOpenFile(sock, fptr);
  639. if (getsockopt(fptr->fd, level, option, buf, &len) < 0)
  640. rb_sys_fail_path(fptr->path);
  641. return rb_str_new(buf, len);
  642. #else
  643. rb_notimplement();
  644. #endif
  645. }
  646. /*
  647. * call-seq:
  648. * basicsocket.getsockname => sockaddr
  649. *
  650. * Returns the local address of the socket as a sockaddr string.
  651. *
  652. * TCPServer.open("127.0.0.1", 15120) {|serv|
  653. * p serv.getsockname #=> "\x02\x00;\x10\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
  654. * }
  655. *
  656. * If Addrinfo object is preferred over the binary string,
  657. * use BasicSocket#local_address.
  658. */
  659. static VALUE
  660. bsock_getsockname(VALUE sock, SEL sel)
  661. {
  662. struct sockaddr_storage buf;
  663. socklen_t len = (socklen_t)sizeof buf;
  664. rb_io_t *fptr;
  665. GetOpenFile(sock, fptr);
  666. if (getsockname(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
  667. rb_sys_fail("getsockname(2)");
  668. return rb_str_new((char*)&buf, len);
  669. }
  670. /*
  671. * call-seq:
  672. * basicsocket.getpeername => sockaddr
  673. *
  674. * Returns the remote address of the socket as a sockaddr string.
  675. *
  676. * TCPServer.open("127.0.0.1", 1440) {|serv|
  677. * c = TCPSocket.new("127.0.0.1", 1440)
  678. * s = serv.accept
  679. * p s.getpeername #=> "\x02\x00\x82u\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
  680. * }
  681. *
  682. * If Addrinfo object is preferred over the binary string,
  683. * use BasicSocket#remote_address.
  684. *
  685. */
  686. static VALUE
  687. bsock_getpeername(VALUE sock, SEL sel)
  688. {
  689. struct sockaddr_storage buf;
  690. socklen_t len = (socklen_t)sizeof buf;
  691. rb_io_t *fptr;
  692. GetOpenFile(sock, fptr);
  693. if (getpeername(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
  694. rb_sys_fail("getpeername(2)");
  695. return rb_str_new((char*)&buf, len);
  696. }
  697. #if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(HAVE_GETPEERUCRED)
  698. /*
  699. * call-seq:
  700. * basicsocket.getpeereid => [euid, egid]
  701. *
  702. * Returns the user and group on the peer of the UNIX socket.
  703. * The result is a two element array which contains the effective uid and the effective gid.
  704. *
  705. * Socket.unix_server_loop("/tmp/sock") {|s|
  706. * begin
  707. * euid, egid = s.getpeereid
  708. *
  709. * # Check the connected client is myself or not.
  710. * next if euid != Process.uid
  711. *
  712. * # do something about my resource.
  713. *
  714. * ensure
  715. * s.close
  716. * end
  717. * }
  718. *
  719. */
  720. static VALUE
  721. bsock_getpeereid(VALUE self, SEL sel)
  722. {
  723. #if defined(HAVE_GETPEEREID)
  724. rb_io_t *fptr;
  725. uid_t euid;
  726. gid_t egid;
  727. GetOpenFile(self, fptr);
  728. if (getpeereid(fptr->fd, &euid, &egid) == -1)
  729. rb_sys_fail("getpeereid");
  730. return rb_assoc_new(UIDT2NUM(euid), GIDT2NUM(egid));
  731. #elif defined(SO_PEERCRED) /* GNU/Linux */
  732. rb_io_t *fptr;
  733. struct ucred cred;
  734. socklen_t len = sizeof(cred);
  735. GetOpenFile(self, fptr);
  736. if (getsockopt(fptr->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1)
  737. rb_sys_fail("getsockopt(SO_PEERCRED)");
  738. return rb_assoc_new(UIDT2NUM(cred.uid), GIDT2NUM(cred.gid));
  739. #elif defined(HAVE_GETPEERUCRED) /* Solaris */
  740. rb_io_t *fptr;
  741. ucred_t *uc = NULL;
  742. VALUE ret;
  743. GetOpenFile(self, fptr);
  744. if (getpeerucred(fptr->fd, &uc) == -1)
  745. rb_sys_fail("getpeerucred");
  746. ret = rb_assoc_new(UIDT2NUM(ucred_geteuid(uc)), GIDT2NUM(ucred_getegid(uc)));
  747. ucred_free(uc);
  748. return ret;
  749. #endif
  750. }
  751. #else
  752. #define bsock_getpeereid rb_f_notimplement
  753. #endif
  754. static VALUE addrinfo_new(struct sockaddr *addr, socklen_t len, int family, int socktype, int protocol, VALUE canonname, VALUE inspectname);
  755. static VALUE fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len);
  756. static VALUE io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len);
  757. /*
  758. * call-seq:
  759. * bsock.local_address => addrinfo
  760. *
  761. * Returns an Addrinfo object for local address obtained by getsockname.
  762. *
  763. * Note that addrinfo.protocol is filled by 0.
  764. *
  765. * TCPSocket.open("www.ruby-lang.org", 80) {|s|
  766. * p s.local_address #=> #<Addrinfo: 192.168.0.129:36873 TCP>
  767. * }
  768. *
  769. * TCPServer.open("127.0.0.1", 1512) {|serv|
  770. * p serv.local_address #=> #<Addrinfo: 127.0.0.1:1512 TCP>
  771. * }
  772. *
  773. */
  774. static VALUE
  775. bsock_local_address(VALUE sock, SEL sel)
  776. {
  777. struct sockaddr_storage buf;
  778. socklen_t len = (socklen_t)sizeof buf;
  779. rb_io_t *fptr;
  780. GetOpenFile(sock, fptr);
  781. if (getsockname(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
  782. rb_sys_fail("getsockname(2)");
  783. return fd_socket_addrinfo(fptr->fd, (struct sockaddr *)&buf, len);
  784. }
  785. /*
  786. * call-seq:
  787. * bsock.remote_address => addrinfo
  788. *
  789. * Returns an Addrinfo object for remote address obtained by getpeername.
  790. *
  791. * Note that addrinfo.protocol is filled by 0.
  792. *
  793. * TCPSocket.open("www.ruby-lang.org", 80) {|s|
  794. * p s.remote_address #=> #<Addrinfo: 221.186.184.68:80 TCP>
  795. * }
  796. *
  797. * TCPServer.open("127.0.0.1", 1728) {|serv|
  798. * c = TCPSocket.new("127.0.0.1", 1728)
  799. * s = serv.accept
  800. * p s.remote_address #=> #<Addrinfo: 127.0.0.1:36504 TCP>
  801. * }
  802. *
  803. */
  804. static VALUE
  805. bsock_remote_address(VALUE sock, SEL sel)
  806. {
  807. struct sockaddr_storage buf;
  808. socklen_t len = (socklen_t)sizeof buf;
  809. rb_io_t *fptr;
  810. GetOpenFile(sock, fptr);
  811. if (getpeername(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
  812. rb_sys_fail("getpeername(2)");
  813. return fd_socket_addrinfo(fptr->fd, (struct sockaddr *)&buf, len);
  814. }
  815. #define SockAddrStringValue(v) sockaddr_string_value(&(v))
  816. #define SockAddrStringValuePtr(v) sockaddr_string_value_ptr(&(v))
  817. static VALUE sockaddr_string_value(volatile VALUE *);
  818. static char *sockaddr_string_value_ptr(volatile VALUE *);
  819. /*
  820. * call-seq:
  821. * basicsocket.send(mesg, flags [, dest_sockaddr]) => numbytes_sent
  822. *
  823. * send _mesg_ via _basicsocket_.
  824. *
  825. * _mesg_ should be a string.
  826. *
  827. * _flags_ should be a bitwise OR of Socket::MSG_* constants.
  828. *
  829. * _dest_sockaddr_ should be a packed sockaddr string or an addrinfo.
  830. *
  831. * TCPSocket.open("localhost", 80) {|s|
  832. * s.send "GET / HTTP/1.0\r\n\r\n", 0
  833. * p s.read
  834. * }
  835. */
  836. static VALUE
  837. bsock_send(VALUE sock, SEL sel, int argc, VALUE *argv)
  838. {
  839. VALUE mesg, to;
  840. VALUE flags;
  841. rb_io_t *fptr;
  842. int fd, n;
  843. rb_secure(4);
  844. rb_scan_args(argc, argv, "21", &mesg, &flags, &to);
  845. StringValue(mesg);
  846. if (!NIL_P(to)) SockAddrStringValue(to);
  847. GetOpenFile(sock, fptr);
  848. fd = fptr->fd;
  849. retry:
  850. rb_thread_fd_writable(fd);
  851. if (!NIL_P(to)) {
  852. n = sendto(fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), NUM2INT(flags),
  853. (struct sockaddr*)RSTRING_PTR(to), RSTRING_LEN(to));
  854. }
  855. else {
  856. n = send(fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), NUM2INT(flags));
  857. }
  858. if (n < 0) {
  859. if (rb_io_wait_writable(fd)) {
  860. goto retry;
  861. }
  862. rb_sys_fail("send(2)");
  863. }
  864. return INT2FIX(n);
  865. }
  866. /*
  867. * call-seq:
  868. * basicsocket.do_not_reverse_lookup => true or false
  869. *
  870. * Gets the do_not_reverse_lookup flag of _basicsocket_.
  871. *
  872. * TCPSocket.open("www.ruby-lang.org", 80) {|sock|
  873. * p sock.do_not_reverse_lookup #=> false
  874. * p sock.peeraddr #=> ["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68"]
  875. * sock.do_not_reverse_lookup = true
  876. * p sock.peeraddr #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"]
  877. * }
  878. */
  879. static VALUE
  880. bsock_do_not_reverse_lookup(VALUE sock, SEL sel)
  881. {
  882. rb_io_t *fptr;
  883. GetOpenFile(sock, fptr);
  884. return (fptr->mode & FMODE_NOREVLOOKUP) ? Qtrue : Qfalse;
  885. }
  886. /*
  887. * call-seq:
  888. * basicsocket.do_not_reverse_lookup = bool
  889. *
  890. * Sets the do_not_reverse_lookup flag of _basicsocket_.
  891. *
  892. * BasicSocket.do_not_reverse_lookup = false
  893. * p TCPSocket.new("127.0.0.1", 80).do_not_reverse_lookup #=> false
  894. * BasicSocket.do_not_reverse_lookup = true
  895. * p TCPSocket.new("127.0.0.1", 80).do_not_reverse_lookup #=> true
  896. *
  897. */
  898. static VALUE
  899. bsock_do_not_reverse_lookup_set(VALUE sock, SEL sel, VALUE state)
  900. {
  901. rb_io_t *fptr;
  902. rb_secure(4);
  903. GetOpenFile(sock, fptr);
  904. if (RTEST(state)) {
  905. fptr->mode |= FMODE_NOREVLOOKUP;
  906. }
  907. else {
  908. fptr->mode &= ~FMODE_NOREVLOOKUP;
  909. }
  910. return sock;
  911. }
  912. static VALUE ipaddr(struct sockaddr*, int);
  913. #ifdef HAVE_SYS_UN_H
  914. static VALUE unixaddr(struct sockaddr_un*, socklen_t);
  915. #endif
  916. enum sock_recv_type {
  917. RECV_RECV, /* BasicSocket#recv(no from) */
  918. RECV_IP, /* IPSocket#recvfrom */
  919. RECV_UNIX, /* UNIXSocket#recvfrom */
  920. RECV_SOCKET /* Socket#recvfrom */
  921. };
  922. static VALUE
  923. s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
  924. {
  925. rb_io_t *fptr;
  926. VALUE str;
  927. struct sockaddr_storage buf;
  928. socklen_t alen = (socklen_t)sizeof buf;
  929. VALUE len, flg;
  930. long buflen;
  931. long slen;
  932. int fd, flags;
  933. rb_scan_args(argc, argv, "11", &len, &flg);
  934. if (flg == Qnil) flags = 0;
  935. else flags = NUM2INT(flg);
  936. buflen = NUM2INT(len);
  937. GetOpenFile(sock, fptr);
  938. if (rb_io_read_pending(fptr)) {
  939. rb_raise(rb_eIOError, "recv for buffered IO");
  940. }
  941. fd = fptr->fd;
  942. str = rb_bstr_new();
  943. rb_bstr_resize(str, buflen);
  944. retry:
  945. rb_thread_wait_fd(fd);
  946. rb_io_check_closed(fptr);
  947. if (rb_bstr_length(str) != buflen) {
  948. rb_raise(rb_eRuntimeError, "buffer string modified");
  949. }
  950. slen = recvfrom(fd, rb_bstr_bytes(str), buflen, flags,
  951. (struct sockaddr *)&buf, &alen);
  952. if (slen < 0) {
  953. if (rb_io_wait_readable(fd)) {
  954. goto retry;
  955. }
  956. rb_sys_fail("recvfrom(2)");
  957. }
  958. if (slen < rb_bstr_length(str)) {
  959. rb_bstr_resize(str, slen);
  960. }
  961. rb_obj_taint(str);
  962. switch (from) {
  963. case RECV_RECV:
  964. return (VALUE)str;
  965. case RECV_IP:
  966. #if 0
  967. if (alen != sizeof(struct sockaddr_in)) {
  968. rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
  969. }
  970. #endif
  971. if (alen && alen != sizeof(buf)) /* OSX doesn't return a from result for connection-oriented sockets */
  972. return rb_assoc_new(str, ipaddr((struct sockaddr*)&buf, fptr->mode & FMODE_NOREVLOOKUP));
  973. else
  974. return rb_assoc_new(str, Qnil);
  975. #ifdef HAVE_SYS_UN_H
  976. case RECV_UNIX:
  977. return rb_assoc_new(str, unixaddr((struct sockaddr_un*)&buf, alen));
  978. #endif
  979. case RECV_SOCKET:
  980. return rb_assoc_new(str, io_socket_addrinfo(sock, (struct sockaddr*)&buf, alen));
  981. default:
  982. rb_bug("s_recvfrom called with bad value");
  983. }
  984. }
  985. static VALUE
  986. s_recvfrom_nonblock(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
  987. {
  988. rb_io_t *fptr;
  989. VALUE str;
  990. struct sockaddr_storage buf;
  991. socklen_t alen = (socklen_t)sizeof buf;
  992. VALUE len, flg;
  993. long buflen;
  994. long slen;
  995. int fd, flags;
  996. VALUE addr = Qnil;
  997. rb_scan_args(argc, argv, "11", &len, &flg);
  998. if (flg == Qnil) flags = 0;
  999. else flags = NUM2INT(flg);
  1000. buflen = NUM2INT(len);
  1001. #ifdef MSG_DONTWAIT
  1002. /* MSG_DONTWAIT avoids the race condition between fcntl and recvfrom.
  1003. It is not portable, though. */
  1004. flags |= MSG_DONTWAIT;
  1005. #endif
  1006. GetOpenFile(sock, fptr);
  1007. if (rb_io_read_pending(fptr)) {
  1008. rb_raise(rb_eIOError, "recvfrom for buffered IO");
  1009. }
  1010. fd = fptr->fd;
  1011. str = rb_bstr_new();
  1012. rb_bstr_resize(str, buflen);
  1013. rb_io_check_closed(fptr);
  1014. rb_io_set_nonblock(fptr);
  1015. slen = recvfrom(fd, rb_bstr_bytes(str), buflen, flags,
  1016. (struct sockaddr *)&buf, &alen);
  1017. if (slen < 0) {
  1018. switch (errno) {
  1019. case EAGAIN:
  1020. #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
  1021. case EWOULDBLOCK:
  1022. #endif
  1023. rb_mod_sys_fail(rb_mWaitReadable, "recvfrom(2) would block");
  1024. }
  1025. rb_sys_fail("recvfrom(2)");
  1026. }
  1027. if (slen < rb_bstr_length(str)) {
  1028. rb_bstr_resize(str, slen);
  1029. }
  1030. rb_obj_taint(str);
  1031. switch (from) {
  1032. case RECV_RECV:
  1033. return str;
  1034. case RECV_IP:
  1035. if (alen && alen != sizeof(buf)) /* connection-oriented socket may not return a from result */
  1036. addr = ipaddr((struct sockaddr*)&buf, fptr->mode & FMODE_NOREVLOOKUP);
  1037. break;
  1038. case RECV_SOCKET:
  1039. addr = io_socket_addrinfo(sock, (struct sockaddr*)&buf, alen);
  1040. break;
  1041. default:
  1042. rb_bug("s_recvfrom_nonblock called with bad value");
  1043. }
  1044. return rb_assoc_new(str, addr);
  1045. }
  1046. /*
  1047. * call-seq:
  1048. * basicsocket.recv(maxlen) => mesg
  1049. * basicsocket.recv(maxlen, flags) => mesg
  1050. *
  1051. * Receives a message.
  1052. *
  1053. * _maxlen_ is the maximum number of bytes to receive.
  1054. *
  1055. * _flags_ should be a bitwise OR of Socket::MSG_* constants.
  1056. *
  1057. * UNIXSocket.pair {|s1, s2|
  1058. * s1.puts "Hello World"
  1059. * p s2.recv(4) #=> "Hell"
  1060. * p s2.recv(4, Socket::MSG_PEEK) #=> "o Wo"
  1061. * p s2.recv(4) #=> "o Wo"
  1062. * p s2.recv(10) #=> "rld\n"
  1063. * }
  1064. */
  1065. static VALUE
  1066. bsock_recv(VALUE sock, SEL sel, int argc, VALUE *argv)
  1067. {
  1068. return s_recvfrom(sock, argc, argv, RECV_RECV);
  1069. }
  1070. /*
  1071. * call-seq:
  1072. * basicsocket.recv_nonblock(maxlen) => mesg
  1073. * basicsocket.recv_nonblock(maxlen, flags) => mesg
  1074. *
  1075. * Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
  1076. * O_NONBLOCK is set for the underlying file descriptor.
  1077. * _flags_ is zero or more of the +MSG_+ options.
  1078. * The result, _mesg_, is the data received.
  1079. *
  1080. * When recvfrom(2) returns 0, Socket#recv_nonblock returns
  1081. * an empty string as data.
  1082. * The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
  1083. *
  1084. * === Parameters
  1085. * * +maxlen+ - the number of bytes to receive from the socket
  1086. * * +flags+ - zero or more of the +MSG_+ options
  1087. *
  1088. * === Example
  1089. * serv = TCPServer.new("127.0.0.1", 0)
  1090. * af, port, host, addr = serv.addr
  1091. * c = TCPSocket.new(addr, port)
  1092. * s = serv.accept
  1093. * c.send "aaa", 0
  1094. * begin # emulate blocking recv.
  1095. * p s.recv_nonblock(10) #=> "aaa"
  1096. * rescue IO::WaitReadable
  1097. * IO.select([s])
  1098. * retry
  1099. * end
  1100. *
  1101. * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
  1102. * to _recv_nonblock_ fails.
  1103. *
  1104. * BasicSocket#recv_nonblock may raise any error corresponding to recvfrom(2) failure,
  1105. * including Errno::EWOULDBLOCK.
  1106. *
  1107. * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
  1108. * it is extended by IO::WaitReadable.
  1109. * So IO::WaitReadable can be used to rescue the exceptions for retrying recv_nonblock.
  1110. *
  1111. * === See
  1112. * * Socket#recvfrom
  1113. */
  1114. static VALUE
  1115. bsock_recv_nonblock(VALUE sock, SEL sel, int argc, VALUE *argv)
  1116. {
  1117. return s_recvfrom_nonblock(sock, argc, argv, RECV_RECV);
  1118. }
  1119. /*
  1120. * call-seq:
  1121. * BasicSocket.do_not_reverse_lookup => true or false
  1122. *
  1123. * Gets the global do_not_reverse_lookup flag.
  1124. *
  1125. * BasicSocket.do_not_reverse_lookup #=> false
  1126. */
  1127. static VALUE
  1128. bsock_do_not_rev_lookup(VALUE self, SEL sel)
  1129. {
  1130. return do_not_reverse_lookup ? Qtrue : Qfalse;
  1131. }
  1132. /*
  1133. * call-seq:
  1134. * BasicSocket.do_not_reverse_lookup = bool
  1135. *
  1136. * Sets the global do_not_reverse_lookup flag.
  1137. *
  1138. * The flag is used for initial value of do_not_reverse_lookup for each socket.
  1139. *
  1140. * s1 = TCPSocket.new("localhost", 80)
  1141. * p s1.do_not_reverse_lookup #=> true
  1142. * BasicSocket.do_not_reverse_lookup = false
  1143. * s2 = TCPSocket.new("localhost", 80)
  1144. * p s2.do_not_reverse_lookup #=> false
  1145. * p s1.do_not_reverse_lookup #=> true
  1146. *
  1147. */
  1148. static VALUE
  1149. bsock_do_not_rev_lookup_set(VALUE self, SEL sel, VALUE val)
  1150. {
  1151. rb_secure(4);
  1152. do_not_reverse_lookup = RTEST(val);
  1153. return val;
  1154. }
  1155. NORETURN(static void raise_socket_error(char *, int));
  1156. static void
  1157. raise_socket_error(char *reason, int error)
  1158. {
  1159. #ifdef EAI_SYSTEM
  1160. if (error == EAI_SYSTEM) rb_sys_fail(reason);
  1161. #endif
  1162. rb_raise(rb_eSocket, "%s: %s", reason, gai_strerror(error));
  1163. }
  1164. static void
  1165. make_ipaddr0(struct sockaddr *addr, char *buf, size_t len)
  1166. {
  1167. int error;
  1168. error = getnameinfo(addr, SA_LEN(addr), buf, len, NULL, 0, NI_NUMERICHOST);
  1169. if (error) {
  1170. raise_socket_error("getnameinfo", error);
  1171. }
  1172. }
  1173. static VALUE
  1174. make_ipaddr(struct sockaddr *addr)
  1175. {
  1176. char hbuf[1024];
  1177. make_ipaddr0(addr, hbuf, sizeof(hbuf));
  1178. return rb_str_new2(hbuf);
  1179. }
  1180. static void
  1181. make_inetaddr(long host, char *buf, size_t len)
  1182. {
  1183. struct sockaddr_in sin;
  1184. MEMZERO(&sin, struct sockaddr_in, 1);
  1185. sin.sin_family = AF_INET;
  1186. SET_SIN_LEN(&sin, sizeof(sin));
  1187. sin.sin_addr.s_addr = host;
  1188. make_ipaddr0((struct sockaddr*)&sin, buf, len);
  1189. }
  1190. static int
  1191. str_is_number(const char *p)
  1192. {
  1193. char *ep;
  1194. if (!p || *p == '\0')
  1195. return 0;
  1196. ep = NULL;
  1197. (void)STRTOUL(p, &ep, 10);
  1198. if (ep && *ep == '\0')
  1199. return 1;
  1200. else
  1201. return 0;
  1202. }
  1203. static char*
  1204. host_str(VALUE host, char *hbuf, size_t len, int *flags_ptr)
  1205. {
  1206. if (NIL_P(host)) {
  1207. return NULL;
  1208. }
  1209. else if (rb_obj_is_kind_of(host, rb_cInteger)) {
  1210. unsigned int i = NUM2UINT(host);
  1211. make_inetaddr(htonl(i), hbuf, len);
  1212. if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
  1213. return hbuf;
  1214. }
  1215. else {
  1216. const char *name;
  1217. SafeStringValue(host);
  1218. name = RSTRING_PTR(host);
  1219. if (!name || *name == 0 || (name[0] == '<' && strcmp(name, "<any>") == 0)) {
  1220. make_inetaddr(INADDR_ANY, hbuf, len);
  1221. if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
  1222. }
  1223. else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) {
  1224. make_inetaddr(INADDR_BROADCAST, hbuf, len);
  1225. if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
  1226. }
  1227. else if (strlen(name) >= len) {
  1228. rb_raise(rb_eArgError, "hostname too long (%ld)", strlen(name));
  1229. }
  1230. else {
  1231. strcpy(hbuf, name);
  1232. }
  1233. return hbuf;
  1234. }
  1235. }
  1236. static char*
  1237. port_str(VALUE port, char *pbuf, size_t len, int *flags_ptr)
  1238. {
  1239. if (NIL_P(port)) {
  1240. return 0;
  1241. }
  1242. else if (FIXNUM_P(port)) {
  1243. snprintf(pbuf, len, "%ld", FIX2LONG(port));
  1244. #ifdef AI_NUMERICSERV
  1245. if (flags_ptr) *flags_ptr |= AI_NUMERICSERV;
  1246. #endif
  1247. return pbuf;
  1248. }
  1249. else {
  1250. const char *serv;
  1251. SafeStringValue(port);
  1252. serv = RSTRING_PTR(port);
  1253. if (strlen(serv) >= len) {
  1254. rb_raise(rb_eArgError, "service name too long (%ld)", strlen(serv));
  1255. }
  1256. strcpy(pbuf, serv);
  1257. return pbuf;
  1258. }
  1259. }
  1260. static struct addrinfo*
  1261. sock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack)
  1262. {
  1263. struct addrinfo* res = NULL;
  1264. char *hostp, *portp;
  1265. int error;
  1266. char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
  1267. int additional_flags = 0;
  1268. hostp = host_str(host, hbuf, sizeof(hbuf), &additional_flags);
  1269. portp = port_str(port, pbuf, sizeof(pbuf), &additional_flags);
  1270. if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) {
  1271. hints->ai_socktype = SOCK_DGRAM;
  1272. }
  1273. hints->ai_flags |= additional_flags;
  1274. error = getaddrinfo(hostp, portp, hints, &res);
  1275. if (error) {
  1276. if (hostp && hostp[strlen(hostp)-1] == '\n') {
  1277. rb_raise(rb_eSocket, "newline at the end of hostname");
  1278. }
  1279. raise_socket_error("getaddrinfo", error);
  1280. }
  1281. #if defined(__APPLE__) && defined(__MACH__)
  1282. {
  1283. struct addrinfo *r;
  1284. r = res;
  1285. while (r) {
  1286. if (! r->ai_socktype) r->ai_socktype = hints->ai_socktype;
  1287. if (! r->ai_protocol) {
  1288. if (r->ai_socktype == SOCK_DGRAM) {
  1289. r->ai_protocol = IPPROTO_UDP;
  1290. }
  1291. else if (r->ai_socktype == SOCK_STREAM) {
  1292. r->ai_protocol = IPPROTO_TCP;
  1293. }
  1294. }
  1295. r = r->ai_next;
  1296. }
  1297. }
  1298. #endif
  1299. return res;
  1300. }
  1301. static struct addrinfo*
  1302. sock_addrinfo(VALUE host, VALUE port, int socktype, int flags)
  1303. {
  1304. struct addrinfo hints;
  1305. MEMZERO(&hints, struct addrinfo, 1);
  1306. hints.ai_family = AF_UNSPEC;
  1307. hints.ai_socktype = socktype;
  1308. hints.ai_flags = flags;
  1309. return sock_getaddrinfo(host, port, &hints, 1);
  1310. }
  1311. static VALUE
  1312. ipaddr(struct sockaddr *sockaddr, int norevlookup)
  1313. {
  1314. VALUE family, port, addr1, addr2;
  1315. VALUE ary;
  1316. int error;
  1317. char hbuf[1024], pbuf[1024];
  1318. ID id;
  1319. id = intern_family(sockaddr->sa_family);
  1320. if (id) {
  1321. family = rb_str_dup(rb_id2str(id));
  1322. }
  1323. else {
  1324. sprintf(pbuf, "unknown:%d", sockaddr->sa_family);
  1325. family = rb_str_new2(pbuf);
  1326. }
  1327. addr1 = Qnil;
  1328. if (!norevlookup) {
  1329. error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
  1330. NULL, 0, 0);
  1331. if (! error) {
  1332. addr1 = rb_str_new2(hbuf);
  1333. }
  1334. }
  1335. error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
  1336. pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
  1337. if (error) {
  1338. raise_socket_error("getnameinfo", error);
  1339. }
  1340. addr2 = rb_str_new2(hbuf);
  1341. if (addr1 == Qnil) {
  1342. addr1 = addr2;
  1343. }
  1344. port = INT2FIX(atoi(pbuf));
  1345. ary = rb_ary_new3(4, family, port, addr1, addr2);
  1346. return ary;
  1347. }
  1348. static int
  1349. ruby_socket(int domain, int type, int proto)
  1350. {
  1351. int fd;
  1352. fd = socket(domain, type, proto);
  1353. if (fd < 0) {
  1354. if (errno == EMFILE || errno == ENFILE) {
  1355. rb_gc();
  1356. fd = socket(domain, type, proto);
  1357. }
  1358. }
  1359. return fd;
  1360. }
  1361. static int
  1362. wait_connectable0(int fd, rb_fdset_t *fds_w, rb_fdset_t *fds_e)
  1363. {
  1364. int sockerr;
  1365. socklen_t sockerrlen;
  1366. for (;;) {
  1367. rb_fd_zero(fds_w);
  1368. rb_fd_zero(fds_e);
  1369. rb_fd_set(fd, fds_w);
  1370. rb_fd_set(fd, fds_e);
  1371. rb_thread_select(fd+1, 0, rb_fd_ptr(fds_w), rb_fd_ptr(fds_e), 0);
  1372. if (rb_fd_isset(fd, fds_w)) {
  1373. return 0;
  1374. }
  1375. else if (rb_fd_isset(fd, fds_e)) {
  1376. sockerrlen = (socklen_t)sizeof(sockerr);
  1377. if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr,
  1378. &sockerrlen) == 0) {
  1379. if (sockerr == 0)
  1380. continue; /* workaround for winsock */
  1381. errno = sockerr;
  1382. }
  1383. return -1;
  1384. }
  1385. }
  1386. }
  1387. struct wait_connectable_arg {
  1388. int fd;
  1389. rb_fdset_t *fds_w;
  1390. rb_fdset_t *fds_e;
  1391. };
  1392. #ifdef HAVE_RB_FD_INIT
  1393. static VALUE
  1394. try_wait_connectable(VALUE arg)
  1395. {
  1396. struct wait_connectable_arg *p = (struct wait_connectable_arg *)arg;
  1397. return (VALUE)wait_connectable0(p->fd, p->fds_w, p->fds_e);
  1398. }
  1399. static VALUE
  1400. wait_connectable_ensure(VALUE arg)
  1401. {
  1402. struct wait_connectable_arg *p = (struct wait_connectable_arg *)arg;
  1403. rb_fd_term(p->fds_w);
  1404. rb_fd_term(p->fds_e);
  1405. return Qnil;
  1406. }
  1407. #endif
  1408. static int
  1409. wait_connectable(int fd)
  1410. {
  1411. struct wait_connectable_arg *arg;
  1412. arg = (void *)xmalloc(sizeof(struct wait_connectable_arg));
  1413. GC_WB(&arg->fds_w, xmalloc(sizeof(rb_fdset_t)));
  1414. GC_WB(&arg->fds_e, xmalloc(sizeof(rb_fdset_t)));
  1415. rb_fd_init(arg->fds_w);
  1416. rb_fd_init(arg->fds_e);
  1417. #ifdef HAVE_RB_FD_INIT
  1418. arg->fd = fd;
  1419. return (int)rb_ensure(try_wait_connectable, (VALUE)arg,
  1420. wait_connectable_ensure,(VALUE)arg);
  1421. #else
  1422. return wait_connectable0(fd, arg->fds_w, arg->fds_e);
  1423. #endif
  1424. }
  1425. #ifdef __CYGWIN__
  1426. #define WAIT_IN_PROGRESS 10
  1427. #endif
  1428. #ifdef __APPLE__
  1429. #define WAIT_IN_PROGRESS 10
  1430. #endif
  1431. #ifdef __linux__
  1432. /* returns correct error */
  1433. #define WAIT_IN_PROGRESS 0
  1434. #endif
  1435. #ifndef WAIT_IN_PROGRESS
  1436. /* BSD origin code apparently has a problem */
  1437. #define WAIT_IN_PROGRESS 1
  1438. #endif
  1439. static int
  1440. ruby_connect(int fd, struct sockaddr *sockaddr, int len, int socks)
  1441. {
  1442. int status;
  1443. #if WAIT_IN_PROGRESS > 0
  1444. int wait_in_progress = -1;
  1445. int sockerr;
  1446. socklen_t sockerrlen;
  1447. #endif
  1448. for (;;) {
  1449. status = connect(fd, sockaddr, len);
  1450. if (status < 0) {
  1451. switch (errno) {
  1452. case EINTR:
  1453. #if defined(ERESTART)
  1454. case ERESTART:
  1455. #endif
  1456. continue;
  1457. case EAGAIN:
  1458. #ifdef EINPROGRESS
  1459. case EINPROGRESS:
  1460. #endif
  1461. #if WAIT_IN_PROGRESS > 0
  1462. sockerrlen = (socklen_t)sizeof(sockerr);
  1463. status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
  1464. if (status) break;
  1465. if (sockerr) {
  1466. status = -1;
  1467. errno = sockerr;
  1468. break;
  1469. }
  1470. #endif
  1471. #ifdef EALREADY
  1472. case EALREADY:
  1473. #endif
  1474. #if WAIT_IN_PROGRESS > 0
  1475. wait_in_progress = WAIT_IN_PROGRESS;
  1476. #endif
  1477. status = wait_connectable(fd);
  1478. if (status) {
  1479. break;
  1480. }
  1481. errno = 0;
  1482. continue;
  1483. #if WAIT_IN_PROGRESS > 0
  1484. case EINVAL:
  1485. if (wait_in_progress-- > 0) {
  1486. /*
  1487. * connect() after EINPROGRESS returns EINVAL on
  1488. * some platforms, need to check true error
  1489. * status.
  1490. */
  1491. sockerrlen = (socklen_t)sizeof(sockerr);
  1492. status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
  1493. if (!status && !sockerr) {
  1494. struct timeval tv = {0, 100000};
  1495. rb_thread_wait_for(tv);
  1496. continue;
  1497. }
  1498. status = -1;
  1499. errno = sockerr;
  1500. }
  1501. break;
  1502. #endif
  1503. #ifdef EISCONN
  1504. case EISCONN:
  1505. status = 0;
  1506. errno = 0;
  1507. break;
  1508. #endif
  1509. default:
  1510. break;
  1511. }
  1512. }
  1513. return status;
  1514. }
  1515. }
  1516. struct inetsock_arg
  1517. {
  1518. VALUE sock;
  1519. struct {
  1520. VALUE host, serv;
  1521. struct addrinfo *res;
  1522. } remote, local;
  1523. int type;
  1524. int fd;
  1525. };
  1526. static VALUE
  1527. inetsock_cleanup(struct inetsock_arg *arg)
  1528. {
  1529. if (arg->remote.res) {
  1530. freeaddrinfo(arg->remote.res);
  1531. arg->remote.res = 0;
  1532. }
  1533. if (arg->local.res) {
  1534. freeaddrinfo(arg->local.res);
  1535. arg->local.res = 0;
  1536. }
  1537. if (arg->fd >= 0) {
  1538. close(arg->fd);
  1539. }
  1540. return Qnil;
  1541. }
  1542. static VALUE
  1543. init_inetsock_internal(struct inetsock_arg *arg)
  1544. {
  1545. int type = arg->type;
  1546. struct addrinfo *res;
  1547. int fd, status = 0;
  1548. char *syscall = NULL;
  1549. arg->remote.res = sock_addrinfo(arg->remote.host, arg->remote.serv, SOCK_STREAM,
  1550. (type == INET_SERVER) ? AI_PASSIVE : 0);
  1551. /*
  1552. * Maybe also accept a local address
  1553. */
  1554. if (type != INET_SERVER && (!NIL_P(arg->local.host) || !NIL_P(arg->local.serv))) {
  1555. arg->local.res = sock_addrinfo(arg->local.host, arg->local.serv, SOCK_STREAM, 0);
  1556. }
  1557. arg->fd = fd = -1;
  1558. for (res = arg->remote.res; res; res = res->ai_next) {
  1559. #if !defined(INET6) && defined(AF_INET6)
  1560. if (res->ai_family == AF_INET6)
  1561. continue;
  1562. #endif
  1563. status = ruby_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
  1564. syscall = "socket(2)";
  1565. fd = status;
  1566. if (fd < 0) {
  1567. continue;
  1568. }
  1569. arg->fd = fd;
  1570. if (type == INET_SERVER) {
  1571. #if !defined(_WIN32) && !defined(__CYGWIN__)
  1572. status = 1;
  1573. setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
  1574. (char*)&status, sizeof(status));
  1575. #endif
  1576. status = bind(fd, res->ai_addr, res->ai_addrlen);
  1577. syscall = "bind(2)";
  1578. }
  1579. else {
  1580. if (arg->local.res) {
  1581. status = bind(fd, arg->local.res->ai_addr, arg->local.res->ai_addrlen);
  1582. syscall = "bind(2)";
  1583. }
  1584. if (status >= 0) {
  1585. status = ruby_connect(fd, res->ai_addr, res->ai_addrlen,
  1586. (type == INET_SOCKS));
  1587. syscall = "connect(2)";
  1588. }
  1589. }
  1590. if (status < 0) {
  1591. close(fd);
  1592. arg->fd = fd = -1;
  1593. continue;
  1594. } else
  1595. break;
  1596. }
  1597. if (status < 0) {
  1598. rb_sys_fail(syscall);
  1599. }
  1600. arg->fd = -1;
  1601. if (type == INET_SERVER) {
  1602. status = listen(fd, 5);
  1603. if (status < 0) {
  1604. close(fd);
  1605. syscall = "listen(2)";
  1606. }
  1607. }
  1608. /* create new instance */
  1609. return init_sock(arg->sock, fd);
  1610. }
  1611. static VALUE
  1612. init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv,
  1613. VALUE local_host, VALUE local_serv, int type)
  1614. {
  1615. struct inetsock_arg arg;
  1616. arg.sock = sock;
  1617. arg.remote.host = remote_host;
  1618. arg.remote.serv = remote_serv;
  1619. arg.remote.res = 0;
  1620. arg.local.host = local_host;
  1621. arg.local.serv = local_serv;
  1622. arg.local.res = 0;
  1623. arg.type = type;
  1624. arg.fd = -1;
  1625. return rb_ensure(init_inetsock_internal, (VALUE)&arg,
  1626. inetsock_cleanup, (VALUE)&arg);
  1627. }
  1628. /*
  1629. * call-seq:
  1630. * TCPSocket.new(remote_host, remote_port, local_host=nil, local_port=nil)
  1631. *
  1632. * Opens a TCP connection to +remote_host+ on +remote_port+. If +local_host+
  1633. * and +local_port+ are specified, then those parameters are used on the local
  1634. * end to establish the connection.
  1635. */
  1636. static VALUE
  1637. tcp_init(VALUE sock, SEL sel, int argc, VALUE *argv)
  1638. {
  1639. VALUE remote_host, remote_serv;
  1640. VALUE local_host, local_serv;
  1641. rb_scan_args(argc, argv, "22", &remote_host, &remote_serv,
  1642. &local_host, &local_serv);
  1643. return init_inetsock(sock, remote_host, remote_serv,
  1644. local_host, local_serv, INET_CLIENT);
  1645. }
  1646. struct hostent_arg {
  1647. VALUE host;
  1648. struct addrinfo* addr;
  1649. VALUE (*ipaddr)(struct sockaddr*, size_t);
  1650. };
  1651. static VALUE
  1652. make_hostent_internal(struct hostent_arg *arg)
  1653. {
  1654. VALUE host = arg->host;
  1655. struct addrinfo* addr = arg->addr;
  1656. VALUE (*ipaddr)(struct sockaddr*, size_t) = arg->ipaddr;
  1657. struct addrinfo *ai;
  1658. struct hostent *h;
  1659. VALUE ary, names;
  1660. char **pch;
  1661. const char* hostp;
  1662. char hbuf[NI_MAXHOST];
  1663. ary = rb_ary_new();
  1664. if (addr->ai_canonname) {
  1665. hostp = addr->ai_canonname;
  1666. }
  1667. else {
  1668. hostp = host_str(host, hbuf, sizeof(hbuf), NULL);
  1669. }
  1670. rb_ary_push(ary, rb_str_new2(hostp));
  1671. if (addr->ai_canonname && (h = gethostbyname(addr->ai_canonname))) {
  1672. names = rb_ary_new();
  1673. if (h->h_aliases != NULL) {
  1674. for (pch = h->h_aliases; *pch; pch++) {
  1675. rb_ary_push(names, rb_str_new2(*pch));
  1676. }
  1677. }
  1678. }
  1679. else {
  1680. names = rb_ary_new2(0);
  1681. }
  1682. rb_ary_push(ary, names);
  1683. rb_ary_push(ary, INT2NUM(addr->ai_family));
  1684. for (ai = addr; ai; ai = ai->ai_next) {
  1685. rb_ary_push(ary, (*ipaddr)(ai->ai_addr, ai->ai_addrlen));
  1686. }
  1687. return ary;
  1688. }
  1689. static VALUE
  1690. make_hostent(VALUE host, struct addrinfo *addr, VALUE (*ipaddr)(struct sockaddr *, size_t))
  1691. {
  1692. struct hostent_arg arg;
  1693. arg.host = host;
  1694. arg.addr = addr;
  1695. arg.ipaddr = ipaddr;
  1696. return rb_ensure(make_hostent_internal, (VALUE)&arg,
  1697. RUBY_METHOD_FUNC(freeaddrinfo), (VALUE)addr);
  1698. }
  1699. static VALUE
  1700. tcp_sockaddr(struct sockaddr *addr, size_t len)
  1701. {
  1702. return make_ipaddr(addr);
  1703. }
  1704. /*
  1705. * call-seq:
  1706. * TCPSocket.gethostbyname(hostname) => [official_hostname, alias_hostnames, address_family, *address_list]
  1707. *
  1708. * Lookups host information by _hostname_.
  1709. *
  1710. * TCPSocket.gethostbyname("localhost")
  1711. * #=> ["localhost", ["hal"], 2, "127.0.0.1"]
  1712. *
  1713. */
  1714. static VALUE
  1715. tcp_s_gethostbyname(VALUE obj, SEL sel, VALUE host)
  1716. {
  1717. rb_secure(3);
  1718. return make_hostent(host, sock_addrinfo(host, Qnil, SOCK_STREAM,
  1719. AI_CANONNAME), tcp_sockaddr);
  1720. }
  1721. /*
  1722. * call-seq:
  1723. * TCPServer.new([hostname,] port) => tcpserver
  1724. *
  1725. * Creates a new server socket bound to _port_.
  1726. *
  1727. * If _hostname_ is given, the socket is bound to it.
  1728. *
  1729. * serv = TCPServer.new("127.0.0.1", 28561)
  1730. * s = serv.accept
  1731. * s.puts Time.now
  1732. * s.close
  1733. */
  1734. static VALUE
  1735. tcp_svr_init(VALUE sock, SEL sel, int argc, VALUE *argv)
  1736. {
  1737. VALUE arg1, arg2;
  1738. if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2)
  1739. return init_inetsock(sock, arg1, arg2, Qnil, Qnil, INET_SERVER);
  1740. else
  1741. return init_inetsock(sock, Qnil, arg1, Qnil, Qnil, INET_SERVER);
  1742. }
  1743. static void
  1744. make_fd_nonblock(int fd)
  1745. {
  1746. int flags;
  1747. #ifdef F_GETFL
  1748. flags = fcntl(fd, F_GETFL);
  1749. if (flags == -1) {
  1750. rb_sys_fail(0);
  1751. }
  1752. #else
  1753. flags = 0;
  1754. #endif
  1755. flags |= O_NONBLOCK;
  1756. if (fcntl(fd, F_SETFL, flags) == -1) {
  1757. rb_sys_fail(0);
  1758. }
  1759. }
  1760. static VALUE
  1761. s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
  1762. {
  1763. int fd2;
  1764. rb_secure(3);
  1765. rb_io_set_nonblock(fptr);
  1766. fd2 = accept(fptr->fd, (struct sockaddr*)sockaddr, len);
  1767. if (fd2 < 0) {
  1768. switch (errno) {
  1769. case EAGAIN:
  1770. #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
  1771. case EWOULDBLOCK:
  1772. #endif
  1773. case ECONNABORTED:
  1774. #if defined EPROTO
  1775. case EPROTO:
  1776. #endif
  1777. rb_mod_sys_fail(rb_mWaitReadable, "accept(2) would block");
  1778. }
  1779. rb_sys_fail("accept(2)");
  1780. }
  1781. make_fd_nonblock(fd2);
  1782. return init_sock(rb_obj_alloc(klass), fd2);
  1783. }
  1784. static VALUE
  1785. s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len)
  1786. {
  1787. int fd2;
  1788. int retry = 0;
  1789. rb_secure(3);
  1790. retry:
  1791. rb_thread_wait_fd(fd);
  1792. #if defined(_nec_ews)
  1793. fd2 = accept(fd, sockaddr, len);
  1794. #else
  1795. fd2 = accept(fd, sockaddr, len);
  1796. #endif
  1797. if (fd2 < 0) {
  1798. switch (errno) {
  1799. case EMFILE:
  1800. case ENFILE:
  1801. if (retry) break;
  1802. rb_gc();
  1803. retry = 1;
  1804. goto retry;
  1805. default:
  1806. if (!rb_io_wait_readable(fd)) break;
  1807. retry = 0;
  1808. goto retry;
  1809. }
  1810. rb_sys_fail(0);
  1811. }
  1812. if (!klass) return INT2NUM(fd2);
  1813. return init_sock(rb_obj_alloc(klass), fd2);
  1814. }
  1815. /*
  1816. * call-seq:
  1817. * tcpserver.accept => tcpsocket
  1818. *
  1819. * TCPServer.open("127.0.0.1", 14641) {|serv|
  1820. * s = serv.accept
  1821. * s.puts Time.now
  1822. * s.close
  1823. * }
  1824. *
  1825. */
  1826. static VALUE
  1827. tcp_accept(VALUE soc

Large files files are truncated, but you can click here to view the full file