summaryrefslogtreecommitdiff
path: root/ext/socket/rubysocket.h
diff options
context:
space:
mode:
authorMisaki Shioi <[email protected]>2024-11-12 10:06:48 +0900
committerGitHub <[email protected]>2024-11-12 10:06:48 +0900
commit4c270200dbc2a3a4511e8b793a033078afd6fb31 (patch)
tree75c802ceff5051e434701bba83dd965c1357a05d /ext/socket/rubysocket.h
parent821a5b966fbc2926dc3bf88b6ba09879fa35318e (diff)
[Feature #120782] Introduction of Happy Eyeballs Version 2 (RFC8305) in TCPSocket.new (#11653)
* 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 <[email protected]> * 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 <[email protected]>
Notes
Notes: Merged-By: shioimm <[email protected]>
Diffstat (limited to 'ext/socket/rubysocket.h')
-rw-r--r--ext/socket/rubysocket.h41
1 files changed, 40 insertions, 1 deletions
diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h
index b4daa66071..97f3bc55d7 100644
--- a/ext/socket/rubysocket.h
+++ b/ext/socket/rubysocket.h
@@ -354,7 +354,7 @@ int rsock_socket(int domain, int type, int proto);
int rsock_detect_cloexec(int fd);
VALUE rsock_init_sock(VALUE sock, int fd);
VALUE rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass);
-VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, VALUE local_host, VALUE local_serv, int type, VALUE resolv_timeout, VALUE connect_timeout);
+VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, VALUE local_host, VALUE local_serv, int type, VALUE resolv_timeout, VALUE connect_timeout, VALUE fast_fallback, VALUE test_mode_settings);
VALUE rsock_init_unixsock(VALUE sock, VALUE path, int server);
struct rsock_send_arg {
@@ -413,6 +413,45 @@ ssize_t rsock_recvmsg(int socket, struct msghdr *message, int flags);
void rsock_discard_cmsg_resource(struct msghdr *mh, int msg_peek_p);
#endif
+char *host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr);
+char *port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr);
+
+#ifndef FAST_FALLBACK_INIT_INETSOCK_IMPL
+# if !defined(HAVE_PTHREAD_CREATE) || !defined(HAVE_PTHREAD_DETACH) || defined(__MINGW32__) || defined(__MINGW64__)
+# define FAST_FALLBACK_INIT_INETSOCK_IMPL 0
+# else
+# include "ruby/thread_native.h"
+# define FAST_FALLBACK_INIT_INETSOCK_IMPL 1
+# define IPV6_HOSTNAME_RESOLVED '1'
+# define IPV4_HOSTNAME_RESOLVED '2'
+# define SELECT_CANCELLED '3'
+
+struct fast_fallback_getaddrinfo_shared
+{
+ int wait, notify, refcount, connection_attempt_fds_size;
+ int *connection_attempt_fds, *cancelled;
+ char *node, *service;
+ rb_nativethread_lock_t *lock;
+};
+
+struct fast_fallback_getaddrinfo_entry
+{
+ int family, err, refcount;
+ struct addrinfo hints;
+ struct addrinfo *ai;
+ struct fast_fallback_getaddrinfo_shared *shared;
+ int has_syserr;
+ long test_sleep_ms;
+ int test_ecode;
+};
+
+int raddrinfo_pthread_create(pthread_t *th, void *(*start_routine) (void *), void *arg);
+void *do_fast_fallback_getaddrinfo(void *ptr);
+void free_fast_fallback_getaddrinfo_entry(struct fast_fallback_getaddrinfo_entry **entry);
+void free_fast_fallback_getaddrinfo_shared(struct fast_fallback_getaddrinfo_shared **shared);
+# endif
+#endif
+
void rsock_init_basicsocket(void);
void rsock_init_ipsocket(void);
void rsock_init_tcpsocket(void);