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