From 5df72288f8ec3d6f2047273281fb6abfff47cc97 Mon Sep 17 00:00:00 2001 From: nobu Date: Mon, 3 Jun 2002 15:52:28 +0000 Subject: * ext/socket/addrinfo.h: typo. * ext/socket/getaddrinfo.c (gai_strerror): get rid of warning. * ext/socket/socket.c (init_inetsock): ensures resources are freed at exceptions. * ext/socket/socket.c (init_unixsock): ditto. * ext/socket/socket.c (udp_connect): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2511 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 13 ++++ ext/socket/addrinfo.h | 2 +- ext/socket/getaddrinfo.c | 2 +- ext/socket/socket.c | 169 +++++++++++++++++++++++++++++++++-------------- 4 files changed, 135 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6fa1c375c1..b70a62711f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +Tue Jun 4 00:45:50 2002 Nobuyoshi Nakada + + * ext/socket/addrinfo.h: typo. + + * ext/socket/getaddrinfo.c (gai_strerror): get rid of warning. + + * ext/socket/socket.c (init_inetsock): ensures resources are + freed at exceptions. + + * ext/socket/socket.c (init_unixsock): ditto. + + * ext/socket/socket.c (udp_connect): ditto. + Mon Jun 3 20:39:51 2002 Masaki Suketa * ext/win32ole/extconf.rb : change PLATFORM with RUBY_PLATFORM. diff --git a/ext/socket/addrinfo.h b/ext/socket/addrinfo.h index bd3de72e10..5beea2cec6 100644 --- a/ext/socket/addrinfo.h +++ b/ext/socket/addrinfo.h @@ -153,7 +153,7 @@ extern int getnameinfo __P(( int flags)); extern void freehostent __P((struct hostent *)); -extern void freeaddrent __P((struct addrinfo *)); +extern void freeaddrinfo __P((struct addrinfo *)); #if defined __UCLIBC__ const #endif diff --git a/ext/socket/getaddrinfo.c b/ext/socket/getaddrinfo.c index fa060ad171..eddb67e333 100644 --- a/ext/socket/getaddrinfo.c +++ b/ext/socket/getaddrinfo.c @@ -200,7 +200,7 @@ gai_strerror(ecode) { if (ecode < 0 || ecode > EAI_MAX) ecode = EAI_MAX; - return ai_errlist[ecode]; + return (char *)ai_errlist[ecode]; } void diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 30ddc69d4b..2fcb4a5a76 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -158,6 +158,11 @@ ruby_getaddrinfo(nodename, servname, hints, res) #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo((node),(serv),(hints),(res)) #endif +#ifdef HAVE_CLOSESOCKET +#undef close +#define close closesocket +#endif + #ifdef NT static void sock_finalize _((OpenFile *fptr)); @@ -844,34 +849,63 @@ load_addr_info(h, serv, type, res) } } -static VALUE -init_inetsock(sock, remote_host, remote_serv, local_host, local_serv, type) - VALUE sock, remote_host, remote_serv, local_host, local_serv; +struct inetsock_arg +{ + VALUE sock; + struct { + VALUE host, serv; + struct addrinfo *res; + } remote, local; int type; + int fd; +}; + +static VALUE +inetsock_cleanup(arg) + struct inetsock_arg *arg; { - struct addrinfo hints, *res, *res_remote, *res_local = NULL; + if (arg->remote.res) { + freeaddrinfo(arg->remote.res); + arg->remote.res = 0; + } + if (arg->local.res) { + freeaddrinfo(arg->local.res); + arg->local.res = 0; + } + if (arg->fd >= 0) { + close(arg->fd); + } + return Qnil; +} + +static VALUE +init_inetsock_internal(arg) + struct inetsock_arg *arg; +{ + int type = arg->type; + struct addrinfo hints, *res; int fd, status; char *syscall; - res_remote = sock_addrinfo(remote_host, remote_serv, SOCK_STREAM, - (type == INET_SERVER) ? AI_PASSIVE : 0); + arg->remote.res = sock_addrinfo(arg->remote.host, arg->remote.serv, SOCK_STREAM, + (type == INET_SERVER) ? AI_PASSIVE : 0); /* * Maybe also accept a local address */ - if (type != INET_SERVER && (!NIL_P(local_host) || !NIL_P(local_serv))) { - res_local = sock_addrinfo(local_host, local_serv, SOCK_STREAM, - (type == INET_SERVER) ? AI_PASSIVE : 0); + if (type != INET_SERVER && (!NIL_P(arg->local.host) || !NIL_P(arg->local.serv))) { + arg->local.res = sock_addrinfo(arg->local.host, arg->local.serv, SOCK_STREAM, 0); } - fd = -1; - for (res = res_remote; res; res = res->ai_next) { + arg->fd = fd = -1; + for (res = arg->remote.res; res; res = res->ai_next) { status = ruby_socket(res->ai_family,res->ai_socktype,res->ai_protocol); syscall = "socket(2)"; fd = status; if (fd < 0) { continue; } + arg->fd = fd; if (type == INET_SERVER) { #ifndef NT status = 1; @@ -882,8 +916,8 @@ init_inetsock(sock, remote_host, remote_serv, local_host, local_serv, type) syscall = "bind(2)"; } else { - if (res_local) { - status = bind(fd, res_local->ai_addr, res_local->ai_addrlen); + if (arg->local.res) { + status = bind(fd, arg->local.res->ai_addr, arg->local.res->ai_addrlen); syscall = "bind(2)"; } @@ -895,38 +929,42 @@ init_inetsock(sock, remote_host, remote_serv, local_host, local_serv, type) } if (status < 0) { -#if defined(HAVE_CLOSESOCKET) - closesocket(fd); -#else close(fd); -#endif - fd = -1; + arg->fd = fd = -1; continue; } else break; } if (status < 0) { - if (fd >= 0) -#if defined(HAVE_CLOSESOCKET) - closesocket(fd); -#else - close(fd); -#endif - freeaddrinfo(res_remote); - if (res_local) { - freeaddrinfo(res_local); - } rb_sys_fail(syscall); } + arg->fd = -1; + if (type == INET_SERVER) listen(fd, 5); /* create new instance */ - if (res_local) - freeaddrinfo(res_local); - freeaddrinfo(res_remote); - return init_sock(sock, fd); + return init_sock(arg->sock, fd); +} + +static VALUE +init_inetsock(sock, remote_host, remote_serv, local_host, local_serv, type) + VALUE sock, remote_host, remote_serv, local_host, local_serv; + int type; +{ + struct inetsock_arg arg; + arg.sock = sock; + arg.remote.host = remote_host; + arg.remote.serv = remote_serv; + arg.remote.res = 0; + arg.local.host = local_host; + arg.local.serv = local_serv; + arg.local.res = 0; + arg.type = type; + arg.fd = -1; + return rb_ensure(init_inetsock_internal, (VALUE)&arg, + inetsock_cleanup, (VALUE)&arg); } static VALUE @@ -1166,6 +1204,19 @@ tcp_sysaccept(sock) } #ifdef HAVE_SYS_UN_H +struct unixsock_arg { + struct sockaddr_un *sockaddr; + int fd; +}; + +static VALUE +unixsock_connect_internal(arg) + struct unixsock_arg *arg; +{ + return (VALUE)ruby_connect(arg->fd, arg->sockaddr, sizeof(*arg->sockaddr), + 0); +} + static VALUE init_unixsock(sock, path, server) VALUE sock; @@ -1191,15 +1242,19 @@ init_unixsock(sock, path, server) status = bind(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)); } else { - status = ruby_connect(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr), 0); + int prot; + struct unixsock_arg arg; + arg.sockaddr = &sockaddr; + arg.fd = fd; + status = rb_protect(unixsock_connect_internal, (VALUE)&arg, &prot); + if (prot) { + close(fd); + rb_jump_tag(prot); + } } if (status < 0) { -#if defined(HAVE_CLOSESOCKET) - closesocket(fd); -#else close(fd); -#endif rb_sys_fail(sockaddr.sun_path); } @@ -1284,27 +1339,43 @@ udp_init(argc, argv, sock) return init_sock(sock, fd); } +struct udp_arg +{ + struct addrinfo *res; + int fd; +}; + +static VALUE +udp_connect_internal(arg) + struct udp_arg *arg; +{ + int fd = arg->fd; + struct addrinfo *res; + + for (res = arg->res; res; res = res->ai_next) { + if (ruby_connect(fd, res->ai_addr, res->ai_addrlen, 0) >= 0) { + return Qtrue; + } + } + return Qfalse; +} + static VALUE udp_connect(sock, host, port) VALUE sock, host, port; { OpenFile *fptr; int fd; - struct addrinfo *res0, *res; + struct udp_arg arg; + VALUE ret; rb_secure(3); GetOpenFile(sock, fptr); - fd = fileno(fptr->f); - res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0); - for (res = res0; res; res = res->ai_next) { - if (ruby_connect(fd, res->ai_addr, res->ai_addrlen, 0) >= 0) { - freeaddrinfo(res0); - return INT2FIX(0); - } - } - - freeaddrinfo(res0); - rb_sys_fail("connect(2)"); + arg.res = sock_addrinfo(host, port, SOCK_DGRAM, 0); + arg.fd = fileno(fptr->f); + ret = rb_ensure(udp_connect_internal, (VALUE)&arg, + RUBY_METHOD_FUNC(freeaddrinfo), (VALUE)arg.res); + if (!ret) rb_sys_fail("connect(2)"); return INT2FIX(0); } -- cgit v1.2.3