00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "rubysocket.h"
00012
00013 VALUE rb_cBasicSocket;
00014 VALUE rb_cIPSocket;
00015 VALUE rb_cTCPSocket;
00016 VALUE rb_cTCPServer;
00017 VALUE rb_cUDPSocket;
00018 #ifdef AF_UNIX
00019 VALUE rb_cUNIXSocket;
00020 VALUE rb_cUNIXServer;
00021 #endif
00022 VALUE rb_cSocket;
00023 VALUE rb_cAddrinfo;
00024
00025 VALUE rb_eSocket;
00026
00027 #ifdef SOCKS
00028 VALUE rb_cSOCKSSocket;
00029 #endif
00030
00031 int rsock_do_not_reverse_lookup = 1;
00032
00033 void
00034 rsock_raise_socket_error(const char *reason, int error)
00035 {
00036 #ifdef EAI_SYSTEM
00037 if (error == EAI_SYSTEM) rb_sys_fail(reason);
00038 #endif
00039 rb_raise(rb_eSocket, "%s: %s", reason, gai_strerror(error));
00040 }
00041
00042 VALUE
00043 rsock_init_sock(VALUE sock, int fd)
00044 {
00045 rb_io_t *fp;
00046 struct stat sbuf;
00047
00048 #ifndef _WIN32
00049 if (fstat(fd, &sbuf) < 0)
00050 rb_sys_fail(0);
00051 if (!S_ISSOCK(sbuf.st_mode))
00052 rb_raise(rb_eArgError, "not a socket file descriptor");
00053 #else
00054 if (!rb_w32_is_socket(fd))
00055 rb_raise(rb_eArgError, "not a socket file descriptor");
00056 #endif
00057
00058 MakeOpenFile(sock, fp);
00059 fp->fd = fd;
00060 fp->mode = FMODE_READWRITE|FMODE_DUPLEX;
00061 rb_io_ascii8bit_binmode(sock);
00062 if (rsock_do_not_reverse_lookup) {
00063 fp->mode |= FMODE_NOREVLOOKUP;
00064 }
00065 rb_io_synchronized(fp);
00066
00067 return sock;
00068 }
00069
00070 VALUE
00071 rsock_sendto_blocking(void *data)
00072 {
00073 struct rsock_send_arg *arg = data;
00074 VALUE mesg = arg->mesg;
00075 return (VALUE)sendto(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
00076 arg->flags, arg->to, arg->tolen);
00077 }
00078
00079 VALUE
00080 rsock_send_blocking(void *data)
00081 {
00082 struct rsock_send_arg *arg = data;
00083 VALUE mesg = arg->mesg;
00084 return (VALUE)send(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
00085 arg->flags);
00086 }
00087
00088 struct recvfrom_arg {
00089 int fd, flags;
00090 VALUE str;
00091 socklen_t alen;
00092 struct sockaddr_storage buf;
00093 };
00094
00095 static VALUE
00096 recvfrom_blocking(void *data)
00097 {
00098 struct recvfrom_arg *arg = data;
00099 return (VALUE)recvfrom(arg->fd, RSTRING_PTR(arg->str), RSTRING_LEN(arg->str),
00100 arg->flags, (struct sockaddr*)&arg->buf, &arg->alen);
00101 }
00102
00103 VALUE
00104 rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
00105 {
00106 rb_io_t *fptr;
00107 VALUE str, klass;
00108 struct recvfrom_arg arg;
00109 VALUE len, flg;
00110 long buflen;
00111 long slen;
00112
00113 rb_scan_args(argc, argv, "11", &len, &flg);
00114
00115 if (flg == Qnil) arg.flags = 0;
00116 else arg.flags = NUM2INT(flg);
00117 buflen = NUM2INT(len);
00118
00119 GetOpenFile(sock, fptr);
00120 if (rb_io_read_pending(fptr)) {
00121 rb_raise(rb_eIOError, "recv for buffered IO");
00122 }
00123 arg.fd = fptr->fd;
00124 arg.alen = (socklen_t)sizeof(arg.buf);
00125
00126 arg.str = str = rb_tainted_str_new(0, buflen);
00127 klass = RBASIC(str)->klass;
00128 RBASIC(str)->klass = 0;
00129
00130 while (rb_io_check_closed(fptr),
00131 rb_thread_wait_fd(arg.fd),
00132 (slen = BLOCKING_REGION(recvfrom_blocking, &arg)) < 0) {
00133 if (!rb_io_wait_readable(fptr->fd)) {
00134 rb_sys_fail("recvfrom(2)");
00135 }
00136 if (RBASIC(str)->klass || RSTRING_LEN(str) != buflen) {
00137 rb_raise(rb_eRuntimeError, "buffer string modified");
00138 }
00139 }
00140
00141 RBASIC(str)->klass = klass;
00142 if (slen < RSTRING_LEN(str)) {
00143 rb_str_set_len(str, slen);
00144 }
00145 rb_obj_taint(str);
00146 switch (from) {
00147 case RECV_RECV:
00148 return str;
00149 case RECV_IP:
00150 #if 0
00151 if (arg.alen != sizeof(struct sockaddr_in)) {
00152 rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
00153 }
00154 #endif
00155 if (arg.alen && arg.alen != sizeof(arg.buf))
00156 return rb_assoc_new(str, rsock_ipaddr((struct sockaddr*)&arg.buf, fptr->mode & FMODE_NOREVLOOKUP));
00157 else
00158 return rb_assoc_new(str, Qnil);
00159
00160 #ifdef HAVE_SYS_UN_H
00161 case RECV_UNIX:
00162 return rb_assoc_new(str, rsock_unixaddr((struct sockaddr_un*)&arg.buf, arg.alen));
00163 #endif
00164 case RECV_SOCKET:
00165 return rb_assoc_new(str, rsock_io_socket_addrinfo(sock, (struct sockaddr*)&arg.buf, arg.alen));
00166 default:
00167 rb_bug("rsock_s_recvfrom called with bad value");
00168 }
00169 }
00170
00171 VALUE
00172 rsock_s_recvfrom_nonblock(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
00173 {
00174 rb_io_t *fptr;
00175 VALUE str;
00176 struct sockaddr_storage buf;
00177 socklen_t alen = (socklen_t)sizeof buf;
00178 VALUE len, flg;
00179 long buflen;
00180 long slen;
00181 int fd, flags;
00182 VALUE addr = Qnil;
00183
00184 rb_scan_args(argc, argv, "11", &len, &flg);
00185
00186 if (flg == Qnil) flags = 0;
00187 else flags = NUM2INT(flg);
00188 buflen = NUM2INT(len);
00189
00190 #ifdef MSG_DONTWAIT
00191
00192
00193 flags |= MSG_DONTWAIT;
00194 #endif
00195
00196 GetOpenFile(sock, fptr);
00197 if (rb_io_read_pending(fptr)) {
00198 rb_raise(rb_eIOError, "recvfrom for buffered IO");
00199 }
00200 fd = fptr->fd;
00201
00202 str = rb_tainted_str_new(0, buflen);
00203
00204 rb_io_check_closed(fptr);
00205 rb_io_set_nonblock(fptr);
00206 slen = recvfrom(fd, RSTRING_PTR(str), buflen, flags, (struct sockaddr*)&buf, &alen);
00207
00208 if (slen < 0) {
00209 switch (errno) {
00210 case EAGAIN:
00211 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
00212 case EWOULDBLOCK:
00213 #endif
00214 rb_mod_sys_fail(rb_mWaitReadable, "recvfrom(2) would block");
00215 }
00216 rb_sys_fail("recvfrom(2)");
00217 }
00218 if (slen < RSTRING_LEN(str)) {
00219 rb_str_set_len(str, slen);
00220 }
00221 rb_obj_taint(str);
00222 switch (from) {
00223 case RECV_RECV:
00224 return str;
00225
00226 case RECV_IP:
00227 if (alen && alen != sizeof(buf))
00228 addr = rsock_ipaddr((struct sockaddr*)&buf, fptr->mode & FMODE_NOREVLOOKUP);
00229 break;
00230
00231 case RECV_SOCKET:
00232 addr = rsock_io_socket_addrinfo(sock, (struct sockaddr*)&buf, alen);
00233 break;
00234
00235 default:
00236 rb_bug("rsock_s_recvfrom_nonblock called with bad value");
00237 }
00238 return rb_assoc_new(str, addr);
00239 }
00240
00241 int
00242 rsock_socket(int domain, int type, int proto)
00243 {
00244 int fd;
00245
00246 fd = socket(domain, type, proto);
00247 if (fd < 0) {
00248 if (errno == EMFILE || errno == ENFILE) {
00249 rb_gc();
00250 fd = socket(domain, type, proto);
00251 }
00252 }
00253 return fd;
00254 }
00255
00256 static int
00257 wait_connectable0(int fd, rb_fdset_t *fds_w, rb_fdset_t *fds_e)
00258 {
00259 int sockerr;
00260 socklen_t sockerrlen;
00261
00262 for (;;) {
00263 rb_fd_zero(fds_w);
00264 rb_fd_zero(fds_e);
00265
00266 rb_fd_set(fd, fds_w);
00267 rb_fd_set(fd, fds_e);
00268
00269 rb_thread_select(fd+1, 0, rb_fd_ptr(fds_w), rb_fd_ptr(fds_e), 0);
00270
00271 if (rb_fd_isset(fd, fds_w)) {
00272 return 0;
00273 }
00274 else if (rb_fd_isset(fd, fds_e)) {
00275 sockerrlen = (socklen_t)sizeof(sockerr);
00276 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr,
00277 &sockerrlen) == 0) {
00278 if (sockerr == 0)
00279 continue;
00280 errno = sockerr;
00281 }
00282 return -1;
00283 }
00284 }
00285 }
00286
00287 struct wait_connectable_arg {
00288 int fd;
00289 rb_fdset_t fds_w;
00290 rb_fdset_t fds_e;
00291 };
00292
00293 #ifdef HAVE_RB_FD_INIT
00294 static VALUE
00295 try_wait_connectable(VALUE arg)
00296 {
00297 struct wait_connectable_arg *p = (struct wait_connectable_arg *)arg;
00298 return (VALUE)wait_connectable0(p->fd, &p->fds_w, &p->fds_e);
00299 }
00300
00301 static VALUE
00302 wait_connectable_ensure(VALUE arg)
00303 {
00304 struct wait_connectable_arg *p = (struct wait_connectable_arg *)arg;
00305 rb_fd_term(&p->fds_w);
00306 rb_fd_term(&p->fds_e);
00307 return Qnil;
00308 }
00309 #endif
00310
00311 static int
00312 wait_connectable(int fd)
00313 {
00314 struct wait_connectable_arg arg;
00315
00316 rb_fd_init(&arg.fds_w);
00317 rb_fd_init(&arg.fds_e);
00318 #ifdef HAVE_RB_FD_INIT
00319 arg.fd = fd;
00320 return (int)rb_ensure(try_wait_connectable, (VALUE)&arg,
00321 wait_connectable_ensure,(VALUE)&arg);
00322 #else
00323 return wait_connectable0(fd, &arg.fds_w, &arg.fds_e);
00324 #endif
00325 }
00326
00327 #ifdef __CYGWIN__
00328 #define WAIT_IN_PROGRESS 10
00329 #endif
00330 #ifdef __APPLE__
00331 #define WAIT_IN_PROGRESS 10
00332 #endif
00333 #ifdef __linux__
00334
00335 #define WAIT_IN_PROGRESS 0
00336 #endif
00337 #ifndef WAIT_IN_PROGRESS
00338
00339 #define WAIT_IN_PROGRESS 1
00340 #endif
00341
00342 struct connect_arg {
00343 int fd;
00344 const struct sockaddr *sockaddr;
00345 socklen_t len;
00346 };
00347
00348 static VALUE
00349 connect_blocking(void *data)
00350 {
00351 struct connect_arg *arg = data;
00352 return (VALUE)connect(arg->fd, arg->sockaddr, arg->len);
00353 }
00354
00355 #if defined(SOCKS) && !defined(SOCKS5)
00356 static VALUE
00357 socks_connect_blocking(void *data)
00358 {
00359 struct connect_arg *arg = data;
00360 return (VALUE)Rconnect(arg->fd, arg->sockaddr, arg->len);
00361 }
00362 #endif
00363
00364 int
00365 rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks)
00366 {
00367 int status;
00368 rb_blocking_function_t *func = connect_blocking;
00369 struct connect_arg arg;
00370 #if WAIT_IN_PROGRESS > 0
00371 int wait_in_progress = -1;
00372 int sockerr;
00373 socklen_t sockerrlen;
00374 #endif
00375
00376 arg.fd = fd;
00377 arg.sockaddr = sockaddr;
00378 arg.len = len;
00379 #if defined(SOCKS) && !defined(SOCKS5)
00380 if (socks) func = socks_connect_blocking;
00381 #endif
00382 for (;;) {
00383 status = (int)BLOCKING_REGION(func, &arg);
00384 if (status < 0) {
00385 switch (errno) {
00386 case EINTR:
00387 #if defined(ERESTART)
00388 case ERESTART:
00389 #endif
00390 continue;
00391
00392 case EAGAIN:
00393 #ifdef EINPROGRESS
00394 case EINPROGRESS:
00395 #endif
00396 #if WAIT_IN_PROGRESS > 0
00397 sockerrlen = (socklen_t)sizeof(sockerr);
00398 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
00399 if (status) break;
00400 if (sockerr) {
00401 status = -1;
00402 errno = sockerr;
00403 break;
00404 }
00405 #endif
00406 #ifdef EALREADY
00407 case EALREADY:
00408 #endif
00409 #if WAIT_IN_PROGRESS > 0
00410 wait_in_progress = WAIT_IN_PROGRESS;
00411 #endif
00412 status = wait_connectable(fd);
00413 if (status) {
00414 break;
00415 }
00416 errno = 0;
00417 continue;
00418
00419 #if WAIT_IN_PROGRESS > 0
00420 case EINVAL:
00421 if (wait_in_progress-- > 0) {
00422
00423
00424
00425
00426
00427 sockerrlen = (socklen_t)sizeof(sockerr);
00428 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
00429 if (!status && !sockerr) {
00430 struct timeval tv = {0, 100000};
00431 rb_thread_wait_for(tv);
00432 continue;
00433 }
00434 status = -1;
00435 errno = sockerr;
00436 }
00437 break;
00438 #endif
00439
00440 #ifdef EISCONN
00441 case EISCONN:
00442 status = 0;
00443 errno = 0;
00444 break;
00445 #endif
00446 default:
00447 break;
00448 }
00449 }
00450 return status;
00451 }
00452 }
00453
00454 static void
00455 make_fd_nonblock(int fd)
00456 {
00457 int flags;
00458 #ifdef F_GETFL
00459 flags = fcntl(fd, F_GETFL);
00460 if (flags == -1) {
00461 rb_sys_fail(0);
00462 }
00463 #else
00464 flags = 0;
00465 #endif
00466 flags |= O_NONBLOCK;
00467 if (fcntl(fd, F_SETFL, flags) == -1) {
00468 rb_sys_fail(0);
00469 }
00470 }
00471
00472 VALUE
00473 rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
00474 {
00475 int fd2;
00476
00477 rb_secure(3);
00478 rb_io_set_nonblock(fptr);
00479 fd2 = accept(fptr->fd, (struct sockaddr*)sockaddr, len);
00480 if (fd2 < 0) {
00481 switch (errno) {
00482 case EAGAIN:
00483 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
00484 case EWOULDBLOCK:
00485 #endif
00486 case ECONNABORTED:
00487 #if defined EPROTO
00488 case EPROTO:
00489 #endif
00490 rb_mod_sys_fail(rb_mWaitReadable, "accept(2) would block");
00491 }
00492 rb_sys_fail("accept(2)");
00493 }
00494 make_fd_nonblock(fd2);
00495 return rsock_init_sock(rb_obj_alloc(klass), fd2);
00496 }
00497
00498 struct accept_arg {
00499 int fd;
00500 struct sockaddr *sockaddr;
00501 socklen_t *len;
00502 };
00503
00504 static VALUE
00505 accept_blocking(void *data)
00506 {
00507 struct accept_arg *arg = data;
00508 return (VALUE)accept(arg->fd, arg->sockaddr, arg->len);
00509 }
00510
00511 VALUE
00512 rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len)
00513 {
00514 int fd2;
00515 int retry = 0;
00516 struct accept_arg arg;
00517
00518 rb_secure(3);
00519 arg.fd = fd;
00520 arg.sockaddr = sockaddr;
00521 arg.len = len;
00522 retry:
00523 rb_thread_wait_fd(fd);
00524 fd2 = (int)BLOCKING_REGION(accept_blocking, &arg);
00525 if (fd2 < 0) {
00526 switch (errno) {
00527 case EMFILE:
00528 case ENFILE:
00529 if (retry) break;
00530 rb_gc();
00531 retry = 1;
00532 goto retry;
00533 default:
00534 if (!rb_io_wait_readable(fd)) break;
00535 retry = 0;
00536 goto retry;
00537 }
00538 rb_sys_fail(0);
00539 }
00540 if (!klass) return INT2NUM(fd2);
00541 return rsock_init_sock(rb_obj_alloc(klass), fd2);
00542 }
00543
00544 int
00545 rsock_getfamily(int sockfd)
00546 {
00547 struct sockaddr_storage ss;
00548 socklen_t sslen = (socklen_t)sizeof(ss);
00549
00550 ss.ss_family = AF_UNSPEC;
00551 if (getsockname(sockfd, (struct sockaddr*)&ss, &sslen) < 0)
00552 return AF_UNSPEC;
00553
00554 return ss.ss_family;
00555 }
00556
00557
00558
00559
00560 void
00561 rsock_init_socket_init()
00562 {
00563 rb_eSocket = rb_define_class("SocketError", rb_eStandardError);
00564 rsock_init_ipsocket();
00565 rsock_init_tcpsocket();
00566 rsock_init_tcpserver();
00567 rsock_init_sockssocket();
00568 rsock_init_udpsocket();
00569 rsock_init_unixsocket();
00570 rsock_init_unixserver();
00571 rsock_init_sockopt();
00572 rsock_init_ancdata();
00573 rsock_init_addrinfo();
00574 rsock_init_socket_constants();
00575 }
00576