* Introduction of Happy Eyeballs Version 2 (RFC8305) in TCPSocket.new This is an implementation of Happy Eyeballs version 2 (RFC 8305) in `TCPSocket.new`. See https://github.com/ruby/ruby/pull/11653 1. Background Prior to this implementation, I implemented Happy Eyeballs Version 2 (HEv2) for `Socket.tcp` in https://github.com/ruby/ruby/pull/9374. HEv2 is an algorithm defined in [RFC 8305](https://datatracker.ietf.org/doc/html/rfc8305), aimed at improving network connectivity. For more details on the specific cases that HEv2 helps, please refer to https://bugs.ruby-lang.org/issues/20108. 2. Proposal & Outcome This proposal implements the same HEv2 algorithm in `TCPSocket.new`. Since `TCPSocket.new` is used more widely than `Socket.tcp`, this change is expected to broaden the impact of HEv2's benefits. Like `Socket.tcp`, I have also added `fast_fallback` keyword argument to `TCPSocket.new`. This option is set to true by default, enabling the HEv2 functionality. However, users can explicitly set it to false to disable HEv2 and use the previous behavior of `TCPSocket.new`. It should be noted that HEv2 is enabled only in environments where pthreads are available. This specification follows the approach taken in https://bugs.ruby-lang.org/issues/19965 , where name resolution can be interrupted. (In environments where pthreads are not available, the `fast_fallback` option is ignored.) 3. Performance Below is the benchmark of 100 requests to `www.ruby-lang.org` with the fast_fallback option set to true and false, respectively. While there is a slight performance degradation when HEv2 is enabled, the degradation is smaller compared to that seen in `Socket.tcp`. ``` ~/s/build ❯❯❯ ../install/bin/ruby ../ruby/test.rb Rehearsal -------------------------------------------------------- fast_fallback: true 0.017588 0.097045 0.114633 ( 1.460664) fast_fallback: false 0.014033 0.078984 0.093017 ( 1.413951) ----------------------------------------------- total: 0.207650sec user system total real fast_fallback: true 0.020891 0.124054 0.144945 ( 1.473816) fast_fallback: false 0.018392 0.110852 0.129244 ( 1.466014) ``` * Update debug prints Co-authored-by: Nobuyoshi Nakada <nobu.nakada@gmail.com> * Remove debug prints * misc * Disable HEv2 in Win * Raise resolution error with hostname resolution * Fix to handle errors * Remove warnings * Errors that do not need to be handled * misc * Improve doc * Fix bug on cancellation * Avoid EAI_ADDRFAMILY for resolving IPv6 * Follow upstream * misc * Refactor connection_attempt_fds management - Introduced allocate_connection_attempt_fds and reallocate_connection_attempt_fds for improved memory allocation of connection_attempt_fds - Added remove_connection_attempt_fd to resize connection_attempt_fds dynamically. - Simplified the in_progress_fds function to only check the size of connection_attempt_fds. * Rename do_pthread_create to raddrinfo_pthread_create to avoid conflicting --------- Co-authored-by: Nobuyoshi Nakada <nobu.nakada@gmail.com>
75 lines
1.7 KiB
C
75 lines
1.7 KiB
C
/************************************************
|
|
|
|
sockssocket.c -
|
|
|
|
created at: Thu Mar 31 12:21:29 JST 1994
|
|
|
|
Copyright (C) 1993-2007 Yukihiro Matsumoto
|
|
|
|
************************************************/
|
|
|
|
#include "rubysocket.h"
|
|
|
|
#ifdef SOCKS
|
|
/*
|
|
* call-seq:
|
|
* SOCKSSocket.new(host, port) => socket
|
|
*
|
|
* Opens a SOCKS connection to +host+ via the SOCKS server.
|
|
*
|
|
* The SOCKS server configuration varies by implementation
|
|
*
|
|
* When using the Dante libsocks/libsocksd implementation it is configured as SOCKS_SERVER env var.
|
|
*
|
|
* See: https://manpages.debian.org/testing/dante-client/socksify.1.en.html for full env variable support.
|
|
*
|
|
*/
|
|
static VALUE
|
|
socks_init(VALUE sock, VALUE host, VALUE port)
|
|
{
|
|
static int init = 0;
|
|
|
|
if (init == 0) {
|
|
SOCKSinit("ruby");
|
|
init = 1;
|
|
}
|
|
|
|
return rsock_init_inetsock(sock, host, port, Qnil, Qnil, INET_SOCKS, Qnil, Qnil, Qfalse, Qnil);
|
|
}
|
|
|
|
#ifdef SOCKS5
|
|
/*
|
|
* Closes the SOCKS connection.
|
|
*
|
|
*/
|
|
static VALUE
|
|
socks_s_close(VALUE sock)
|
|
{
|
|
rb_io_t *fptr;
|
|
|
|
GetOpenFile(sock, fptr);
|
|
shutdown(fptr->fd, SHUT_RDWR);
|
|
return rb_io_close(sock);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
void
|
|
rsock_init_sockssocket(void)
|
|
{
|
|
#ifdef SOCKS
|
|
/*
|
|
* Document-class: SOCKSSocket < TCPSocket
|
|
*
|
|
* SOCKS is an Internet protocol that routes packets between a client and
|
|
* a server through a proxy server. SOCKS5, if supported, additionally
|
|
* provides authentication so only authorized users may access a server.
|
|
*/
|
|
rb_cSOCKSSocket = rb_define_class("SOCKSSocket", rb_cTCPSocket);
|
|
rb_define_method(rb_cSOCKSSocket, "initialize", socks_init, 2);
|
|
#ifdef SOCKS5
|
|
rb_define_method(rb_cSOCKSSocket, "close", socks_s_close, 0);
|
|
#endif
|
|
#endif
|
|
}
|