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