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 EAGAIN:
00387 #ifdef EINPROGRESS
00388 case EINPROGRESS:
00389 #endif
00390 #if WAIT_IN_PROGRESS > 0
00391 sockerrlen = (socklen_t)sizeof(sockerr);
00392 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
00393 if (status) break;
00394 if (sockerr) {
00395 status = -1;
00396 errno = sockerr;
00397 break;
00398 }
00399 #endif
00400 #ifdef EALREADY
00401 case EALREADY:
00402 #endif
00403 #if WAIT_IN_PROGRESS > 0
00404 wait_in_progress = WAIT_IN_PROGRESS;
00405 #endif
00406 status = wait_connectable(fd);
00407 if (status) {
00408 break;
00409 }
00410 errno = 0;
00411 continue;
00412
00413 #if WAIT_IN_PROGRESS > 0
00414 case EINVAL:
00415 if (wait_in_progress-- > 0) {
00416
00417
00418
00419
00420
00421 sockerrlen = (socklen_t)sizeof(sockerr);
00422 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
00423 if (!status && !sockerr) {
00424 struct timeval tv = {0, 100000};
00425 rb_thread_wait_for(tv);
00426 continue;
00427 }
00428 status = -1;
00429 errno = sockerr;
00430 }
00431 break;
00432 #endif
00433
00434 #ifdef EISCONN
00435 case EISCONN:
00436 status = 0;
00437 errno = 0;
00438 break;
00439 #endif
00440 default:
00441 break;
00442 }
00443 }
00444 return status;
00445 }
00446 }
00447
00448 static void
00449 make_fd_nonblock(int fd)
00450 {
00451 int flags;
00452 #ifdef F_GETFL
00453 flags = fcntl(fd, F_GETFL);
00454 if (flags == -1) {
00455 rb_sys_fail(0);
00456 }
00457 #else
00458 flags = 0;
00459 #endif
00460 flags |= O_NONBLOCK;
00461 if (fcntl(fd, F_SETFL, flags) == -1) {
00462 rb_sys_fail(0);
00463 }
00464 }
00465
00466 VALUE
00467 rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
00468 {
00469 int fd2;
00470
00471 rb_secure(3);
00472 rb_io_set_nonblock(fptr);
00473 fd2 = accept(fptr->fd, (struct sockaddr*)sockaddr, len);
00474 if (fd2 < 0) {
00475 switch (errno) {
00476 case EAGAIN:
00477 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
00478 case EWOULDBLOCK:
00479 #endif
00480 case ECONNABORTED:
00481 #if defined EPROTO
00482 case EPROTO:
00483 #endif
00484 rb_mod_sys_fail(rb_mWaitReadable, "accept(2) would block");
00485 }
00486 rb_sys_fail("accept(2)");
00487 }
00488 make_fd_nonblock(fd2);
00489 return rsock_init_sock(rb_obj_alloc(klass), fd2);
00490 }
00491
00492 struct accept_arg {
00493 int fd;
00494 struct sockaddr *sockaddr;
00495 socklen_t *len;
00496 };
00497
00498 static VALUE
00499 accept_blocking(void *data)
00500 {
00501 struct accept_arg *arg = data;
00502 return (VALUE)accept(arg->fd, arg->sockaddr, arg->len);
00503 }
00504
00505 VALUE
00506 rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len)
00507 {
00508 int fd2;
00509 int retry = 0;
00510 struct accept_arg arg;
00511
00512 rb_secure(3);
00513 arg.fd = fd;
00514 arg.sockaddr = sockaddr;
00515 arg.len = len;
00516 retry:
00517 rb_thread_wait_fd(fd);
00518 fd2 = (int)BLOCKING_REGION(accept_blocking, &arg);
00519 if (fd2 < 0) {
00520 switch (errno) {
00521 case EMFILE:
00522 case ENFILE:
00523 if (retry) break;
00524 rb_gc();
00525 retry = 1;
00526 goto retry;
00527 default:
00528 if (!rb_io_wait_readable(fd)) break;
00529 retry = 0;
00530 goto retry;
00531 }
00532 rb_sys_fail(0);
00533 }
00534 if (!klass) return INT2NUM(fd2);
00535 return rsock_init_sock(rb_obj_alloc(klass), fd2);
00536 }
00537
00538 int
00539 rsock_getfamily(int sockfd)
00540 {
00541 struct sockaddr_storage ss;
00542 socklen_t sslen = (socklen_t)sizeof(ss);
00543
00544 ss.ss_family = AF_UNSPEC;
00545 if (getsockname(sockfd, (struct sockaddr*)&ss, &sslen) < 0)
00546 return AF_UNSPEC;
00547
00548 return ss.ss_family;
00549 }
00550
00551
00552
00553
00554 void
00555 rsock_init_socket_init()
00556 {
00557 rb_eSocket = rb_define_class("SocketError", rb_eStandardError);
00558 rsock_init_ipsocket();
00559 rsock_init_tcpsocket();
00560 rsock_init_tcpserver();
00561 rsock_init_sockssocket();
00562 rsock_init_udpsocket();
00563 rsock_init_unixsocket();
00564 rsock_init_unixserver();
00565 rsock_init_sockopt();
00566 rsock_init_ancdata();
00567 rsock_init_addrinfo();
00568 rsock_init_socket_constants();
00569 }
00570