Esempio n. 1
0
/*
 * call-seq:
 *   TCPSocket.gethostbyname(hostname) => [official_hostname, alias_hostnames, address_family, *address_list]
 *
 * Use Addrinfo.getaddrinfo instead.
 * This method is deprecated for the following reasons:
 *
 * - The 3rd element of the result is the address family of the first address.
 *   The address families of the rest of the addresses are not returned.
 * - gethostbyname() may take a long time and it may block other threads.
 *   (GVL cannot be released since gethostbyname() is not thread safe.)
 * - This method uses gethostbyname() function already removed from POSIX.
 *
 * This method lookups host information by _hostname_.
 *
 *   TCPSocket.gethostbyname("localhost")
 *   #=> ["localhost", ["hal"], 2, "127.0.0.1"]
 *
 */
static VALUE
tcp_s_gethostbyname(VALUE obj, VALUE host)
{
    struct rb_addrinfo *res =
	rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME);
    return rsock_make_hostent(host, res, tcp_sockaddr);
}
Esempio n. 2
0
/*
 * call-seq:
 *   TCPSocket.gethostbyname(hostname) => [official_hostname, alias_hostnames, address_family, *address_list]
 *
 * Lookups host information by _hostname_.
 *
 *   TCPSocket.gethostbyname("localhost")
 *   #=> ["localhost", ["hal"], 2, "127.0.0.1"]
 *
 */
static VALUE
tcp_s_gethostbyname(VALUE obj, VALUE host)
{
    rb_secure(3);
    return rsock_make_hostent(host, rsock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME),
			tcp_sockaddr);
}
Esempio n. 3
0
/*
 * call-seq:
 *   IPSocket.getaddress(host)        => ipaddress
 *
 * Lookups the IP address of _host_.
 *
 *   IPSocket.getaddress("localhost")     #=> "127.0.0.1"
 *   IPSocket.getaddress("ip6-localhost") #=> "::1"
 *
 */
static VALUE
ip_s_getaddress(VALUE obj, VALUE host)
{
    struct sockaddr_storage addr;
    struct addrinfo *res = rsock_addrinfo(host, Qnil, SOCK_STREAM, 0);

    /* just take the first one */
    memcpy(&addr, res->ai_addr, res->ai_addrlen);
    freeaddrinfo(res);

    return rsock_make_ipaddr((struct sockaddr*)&addr);
}
Esempio n. 4
0
/*
 * call-seq:
 *   IPSocket.getaddress(host)        => ipaddress
 *
 * Lookups the IP address of _host_.
 *
 *   IPSocket.getaddress("localhost")     #=> "127.0.0.1"
 *   IPSocket.getaddress("ip6-localhost") #=> "::1"
 *
 */
static VALUE
ip_s_getaddress(VALUE obj, VALUE host)
{
    union_sockaddr addr;
    struct rb_addrinfo *res = rsock_addrinfo(host, Qnil, SOCK_STREAM, 0);
    socklen_t len = res->ai->ai_addrlen;

    /* just take the first one */
    memcpy(&addr, res->ai->ai_addr, len);
    rb_freeaddrinfo(res);

    return rsock_make_ipaddr(&addr.addr, len);
}
Esempio n. 5
0
/*
 * call-seq:
 *   udpsocket.connect(host, port) => 0
 *
 * Connects _udpsocket_ to _host_:_port_.
 *
 * This makes possible to send without destination address.
 *
 *   u1 = UDPSocket.new
 *   u1.bind("127.0.0.1", 4913)
 *   u2 = UDPSocket.new
 *   u2.connect("127.0.0.1", 4913)
 *   u2.send "uuuu", 0
 *   p u1.recvfrom(10) #=> ["uuuu", ["AF_INET", 33230, "localhost", "127.0.0.1"]]
 *
 */
static VALUE
udp_connect(VALUE sock, VALUE host, VALUE port)
{
    rb_io_t *fptr;
    struct udp_arg arg;
    VALUE ret;

    rb_secure(3);
    arg.res = rsock_addrinfo(host, port, SOCK_DGRAM, 0);
    GetOpenFile(sock, fptr);
    arg.fd = fptr->fd;
    ret = rb_ensure(udp_connect_internal, (VALUE)&arg,
		    rsock_freeaddrinfo, (VALUE)arg.res);
    if (!ret) rsock_sys_fail_host_port("connect(2)", host, port);
    return INT2FIX(0);
}
Esempio n. 6
0
/*
 * call-seq:
 *   udpsocket.bind(host, port) #=> 0
 *
 * Binds _udpsocket_ to _host_:_port_.
 *
 *   u1 = UDPSocket.new
 *   u1.bind("127.0.0.1", 4913)
 *   u1.send "message-to-self", 0, "127.0.0.1", 4913
 *   p u1.recvfrom(10) #=> ["message-to", ["AF_INET", 4913, "localhost", "127.0.0.1"]]
 *
 */
static VALUE
udp_bind(VALUE sock, VALUE host, VALUE port)
{
    rb_io_t *fptr;
    struct addrinfo *res0, *res;

    rb_secure(3);
    res0 = rsock_addrinfo(host, port, SOCK_DGRAM, 0);
    GetOpenFile(sock, fptr);
    for (res = res0; res; res = res->ai_next) {
	if (bind(fptr->fd, res->ai_addr, res->ai_addrlen) < 0) {
	    continue;
	}
	freeaddrinfo(res0);
	return INT2FIX(0);
    }
    freeaddrinfo(res0);

    rsock_sys_fail_host_port("bind(2)", host, port);

    return INT2FIX(0);
}
Esempio n. 7
0
/*
 * call-seq:
 *   udpsocket.send(mesg, flags, host, port)  => numbytes_sent
 *   udpsocket.send(mesg, flags, sockaddr_to) => numbytes_sent
 *   udpsocket.send(mesg, flags)              => numbytes_sent
 *
 * Sends _mesg_ via _udpsocket_.
 *
 * _flags_ should be a bitwise OR of Socket::MSG_* constants.
 *
 *   u1 = UDPSocket.new
 *   u1.bind("127.0.0.1", 4913)
 *
 *   u2 = UDPSocket.new
 *   u2.send "hi", 0, "127.0.0.1", 4913
 *
 *   mesg, addr = u1.recvfrom(10)
 *   u1.send mesg, 0, addr[3], addr[1]
 *
 *   p u2.recv(100) #=> "hi"
 *
 */
static VALUE
udp_send(int argc, VALUE *argv, VALUE sock)
{
    VALUE flags, host, port;
    rb_io_t *fptr;
    int n;
    struct addrinfo *res0, *res;
    struct rsock_send_arg arg;

    if (argc == 2 || argc == 3) {
	return rsock_bsock_send(argc, argv, sock);
    }
    rb_scan_args(argc, argv, "4", &arg.mesg, &flags, &host, &port);

    StringValue(arg.mesg);
    res0 = rsock_addrinfo(host, port, SOCK_DGRAM, 0);
    GetOpenFile(sock, fptr);
    arg.fd = fptr->fd;
    arg.flags = NUM2INT(flags);
    for (res = res0; res; res = res->ai_next) {
      retry:
	arg.to = res->ai_addr;
	arg.tolen = res->ai_addrlen;
	rb_thread_fd_writable(arg.fd);
	n = (int)BLOCKING_REGION_FD(rsock_sendto_blocking, &arg);
	if (n >= 0) {
	    freeaddrinfo(res0);
	    return INT2FIX(n);
	}
	if (rb_io_wait_writable(fptr->fd)) {
	    goto retry;
	}
    }
    freeaddrinfo(res0);
    rsock_sys_fail_host_port("sendto(2)", host, port);
    return INT2FIX(n);
}
Esempio n. 8
0
static VALUE
init_inetsock_internal(struct inetsock_arg *arg)
{
    int type = arg->type;
    struct addrinfo *res;
    int fd, status = 0;
    const char *syscall = 0;

    arg->remote.res = rsock_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(arg->local.host) || !NIL_P(arg->local.serv))) {
	arg->local.res = rsock_addrinfo(arg->local.host, arg->local.serv, SOCK_STREAM, 0);
    }

    arg->fd = fd = -1;
    for (res = arg->remote.res; res; res = res->ai_next) {
#if !defined(INET6) && defined(AF_INET6)
	if (res->ai_family == AF_INET6)
	    continue;
#endif
	status = rsock_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) {
#if !defined(_WIN32) && !defined(__CYGWIN__)
	    status = 1;
	    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
		       (char*)&status, (socklen_t)sizeof(status));
#endif
	    status = bind(fd, res->ai_addr, res->ai_addrlen);
	    syscall = "bind(2)";
	}
	else {
	    if (arg->local.res) {
		status = bind(fd, arg->local.res->ai_addr, arg->local.res->ai_addrlen);
		syscall = "bind(2)";
	    }

	    if (status >= 0) {
		status = rsock_connect(fd, res->ai_addr, res->ai_addrlen,
				       (type == INET_SOCKS));
		syscall = "connect(2)";
	    }
	}

	if (status < 0) {
	    close(fd);
	    arg->fd = fd = -1;
	    continue;
	} else
	    break;
    }
    if (status < 0) {
	rb_sys_fail(syscall);
    }

    arg->fd = -1;

    if (type == INET_SERVER) {
	status = listen(fd, SOMAXCONN);
	if (status < 0) {
	    close(fd);
            rb_sys_fail("listen(2)");
	}
    }

    /* create new instance */
    return rsock_init_sock(arg->sock, fd);
}
Esempio n. 9
0
static VALUE
init_inetsock_internal(struct inetsock_arg *arg)
{
    int error = 0;
    int type = arg->type;
    struct addrinfo *res, *lres;
    int fd, status = 0, local = 0;
    const char *syscall = 0;

    arg->remote.res = rsock_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(arg->local.host) || !NIL_P(arg->local.serv))) {
	arg->local.res = rsock_addrinfo(arg->local.host, arg->local.serv, SOCK_STREAM, 0);
    }

    arg->fd = fd = -1;
    for (res = arg->remote.res->ai; res; res = res->ai_next) {
#if !defined(INET6) && defined(AF_INET6)
	if (res->ai_family == AF_INET6)
	    continue;
#endif
        lres = NULL;
        if (arg->local.res) {
            for (lres = arg->local.res->ai; lres; lres = lres->ai_next) {
                if (lres->ai_family == res->ai_family)
                    break;
            }
            if (!lres) {
                if (res->ai_next || status < 0)
                    continue;
                /* Use a different family local address if no choice, this
                 * will cause EAFNOSUPPORT. */
                lres = arg->local.res->ai;
            }
        }
	status = rsock_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
	syscall = "socket(2)";
	fd = status;
	if (fd < 0) {
	    error = errno;
	    continue;
	}
	arg->fd = fd;
	if (type == INET_SERVER) {
#if !defined(_WIN32) && !defined(__CYGWIN__)
	    status = 1;
	    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
		       (char*)&status, (socklen_t)sizeof(status));
#endif
	    status = bind(fd, res->ai_addr, res->ai_addrlen);
	    syscall = "bind(2)";
	}
	else {
	    if (lres) {
		status = bind(fd, lres->ai_addr, lres->ai_addrlen);
		local = status;
		syscall = "bind(2)";
	    }

	    if (status >= 0) {
		status = rsock_connect(fd, res->ai_addr, res->ai_addrlen,
				       (type == INET_SOCKS));
		syscall = "connect(2)";
	    }
	}

	if (status < 0) {
	    error = errno;
	    close(fd);
	    arg->fd = fd = -1;
	    continue;
	} else
	    break;
    }
    if (status < 0) {
	VALUE host, port;

	if (local < 0) {
	    host = arg->local.host;
	    port = arg->local.serv;
	} else {
	    host = arg->remote.host;
	    port = arg->remote.serv;
	}

	rsock_syserr_fail_host_port(error, syscall, host, port);
    }

    arg->fd = -1;

    if (type == INET_SERVER) {
	status = listen(fd, SOMAXCONN);
	if (status < 0) {
	    error = errno;
	    close(fd);
	    rb_syserr_fail(error, "listen(2)");
	}
    }

    /* create new instance */
    return rsock_init_sock(arg->sock, fd);
}