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 continue;
00286
00287
00288 errno = sockerr;
00289 ret = -1;
00290 break;
00291 }
00292
00293 if ((revents & (RB_WAITFD_IN|RB_WAITFD_OUT)) == RB_WAITFD_OUT) {
00294 ret = 0;
00295 break;
00296 }
00297 }
00298
00299 return ret;
00300 }
00301
00302 #ifdef __CYGWIN__
00303 #define WAIT_IN_PROGRESS 10
00304 #endif
00305 #ifdef __APPLE__
00306 #define WAIT_IN_PROGRESS 10
00307 #endif
00308 #ifdef __linux__
00309
00310 #define WAIT_IN_PROGRESS 0
00311 #endif
00312 #ifndef WAIT_IN_PROGRESS
00313
00314 #define WAIT_IN_PROGRESS 1
00315 #endif
00316
00317 struct connect_arg {
00318 int fd;
00319 const struct sockaddr *sockaddr;
00320 socklen_t len;
00321 };
00322
00323 static VALUE
00324 connect_blocking(void *data)
00325 {
00326 struct connect_arg *arg = data;
00327 return (VALUE)connect(arg->fd, arg->sockaddr, arg->len);
00328 }
00329
00330 #if defined(SOCKS) && !defined(SOCKS5)
00331 static VALUE
00332 socks_connect_blocking(void *data)
00333 {
00334 struct connect_arg *arg = data;
00335 return (VALUE)Rconnect(arg->fd, arg->sockaddr, arg->len);
00336 }
00337 #endif
00338
00339 int
00340 rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks)
00341 {
00342 int status;
00343 rb_blocking_function_t *func = connect_blocking;
00344 struct connect_arg arg;
00345 #if WAIT_IN_PROGRESS > 0
00346 int wait_in_progress = -1;
00347 int sockerr;
00348 socklen_t sockerrlen;
00349 #endif
00350
00351 arg.fd = fd;
00352 arg.sockaddr = sockaddr;
00353 arg.len = len;
00354 #if defined(SOCKS) && !defined(SOCKS5)
00355 if (socks) func = socks_connect_blocking;
00356 #endif
00357 for (;;) {
00358 status = (int)BLOCKING_REGION_FD(func, &arg);
00359 if (status < 0) {
00360 switch (errno) {
00361 case EINTR:
00362 #if defined(ERESTART)
00363 case ERESTART:
00364 #endif
00365 continue;
00366
00367 case EAGAIN:
00368 #ifdef EINPROGRESS
00369 case EINPROGRESS:
00370 #endif
00371 #if WAIT_IN_PROGRESS > 0
00372 sockerrlen = (socklen_t)sizeof(sockerr);
00373 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
00374 if (status) break;
00375 if (sockerr) {
00376 status = -1;
00377 errno = sockerr;
00378 break;
00379 }
00380 #endif
00381 #ifdef EALREADY
00382 case EALREADY:
00383 #endif
00384 #if WAIT_IN_PROGRESS > 0
00385 wait_in_progress = WAIT_IN_PROGRESS;
00386 #endif
00387 status = wait_connectable(fd);
00388 if (status) {
00389 break;
00390 }
00391 errno = 0;
00392 continue;
00393
00394 #if WAIT_IN_PROGRESS > 0
00395 case EINVAL:
00396 if (wait_in_progress-- > 0) {
00397
00398
00399
00400
00401
00402 sockerrlen = (socklen_t)sizeof(sockerr);
00403 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
00404 if (!status && !sockerr) {
00405 struct timeval tv = {0, 100000};
00406 rb_thread_wait_for(tv);
00407 continue;
00408 }
00409 status = -1;
00410 errno = sockerr;
00411 }
00412 break;
00413 #endif
00414
00415 #ifdef EISCONN
00416 case EISCONN:
00417 status = 0;
00418 errno = 0;
00419 break;
00420 #endif
00421 default:
00422 break;
00423 }
00424 }
00425 return status;
00426 }
00427 }
00428
00429 static void
00430 make_fd_nonblock(int fd)
00431 {
00432 int flags;
00433 #ifdef F_GETFL
00434 flags = fcntl(fd, F_GETFL);
00435 if (flags == -1) {
00436 rb_sys_fail(0);
00437 }
00438 #else
00439 flags = 0;
00440 #endif
00441 flags |= O_NONBLOCK;
00442 if (fcntl(fd, F_SETFL, flags) == -1) {
00443 rb_sys_fail(0);
00444 }
00445 }
00446
00447 VALUE
00448 rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
00449 {
00450 int fd2;
00451
00452 rb_secure(3);
00453 rb_io_set_nonblock(fptr);
00454 fd2 = accept(fptr->fd, (struct sockaddr*)sockaddr, len);
00455 if (fd2 < 0) {
00456 switch (errno) {
00457 case EAGAIN:
00458 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
00459 case EWOULDBLOCK:
00460 #endif
00461 case ECONNABORTED:
00462 #if defined EPROTO
00463 case EPROTO:
00464 #endif
00465 rb_mod_sys_fail(rb_mWaitReadable, "accept(2) would block");
00466 }
00467 rb_sys_fail("accept(2)");
00468 }
00469 rb_update_max_fd(fd2);
00470 make_fd_nonblock(fd2);
00471 return rsock_init_sock(rb_obj_alloc(klass), fd2);
00472 }
00473
00474 struct accept_arg {
00475 int fd;
00476 struct sockaddr *sockaddr;
00477 socklen_t *len;
00478 };
00479
00480 static VALUE
00481 accept_blocking(void *data)
00482 {
00483 struct accept_arg *arg = data;
00484 return (VALUE)accept(arg->fd, arg->sockaddr, arg->len);
00485 }
00486
00487 VALUE
00488 rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len)
00489 {
00490 int fd2;
00491 int retry = 0;
00492 struct accept_arg arg;
00493
00494 rb_secure(3);
00495 arg.fd = fd;
00496 arg.sockaddr = sockaddr;
00497 arg.len = len;
00498 retry:
00499 rb_thread_wait_fd(fd);
00500 fd2 = (int)BLOCKING_REGION_FD(accept_blocking, &arg);
00501 if (fd2 < 0) {
00502 switch (errno) {
00503 case EMFILE:
00504 case ENFILE:
00505 if (retry) break;
00506 rb_gc();
00507 retry = 1;
00508 goto retry;
00509 default:
00510 if (!rb_io_wait_readable(fd)) break;
00511 retry = 0;
00512 goto retry;
00513 }
00514 rb_sys_fail(0);
00515 }
00516 rb_update_max_fd(fd2);
00517 if (!klass) return INT2NUM(fd2);
00518 return rsock_init_sock(rb_obj_alloc(klass), fd2);
00519 }
00520
00521 int
00522 rsock_getfamily(int sockfd)
00523 {
00524 struct sockaddr_storage ss;
00525 socklen_t sslen = (socklen_t)sizeof(ss);
00526
00527 ss.ss_family = AF_UNSPEC;
00528 if (getsockname(sockfd, (struct sockaddr*)&ss, &sslen) < 0)
00529 return AF_UNSPEC;
00530
00531 return ss.ss_family;
00532 }
00533
00534 void
00535 rsock_init_socket_init()
00536 {
00537
00538
00539
00540 rb_eSocket = rb_define_class("SocketError", rb_eStandardError);
00541 rsock_init_ipsocket();
00542 rsock_init_tcpsocket();
00543 rsock_init_tcpserver();
00544 rsock_init_sockssocket();
00545 rsock_init_udpsocket();
00546 rsock_init_unixsocket();
00547 rsock_init_unixserver();
00548 rsock_init_sockopt();
00549 rsock_init_ancdata();
00550 rsock_init_addrinfo();
00551 rsock_init_socket_constants();
00552 }
00553