Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions stdlib/socket/0/basic_socket.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ class BasicSocket < IO
# onoff, linger = optval.unpack "ii"
# onoff = onoff == 0 ? false : true
#
def getsockopt: (Symbol | Integer, Symbol | Integer) -> (Integer | boolish | String)
def getsockopt: (interned | Integer level, interned | Integer optname) -> Socket::Option

# <!--
# rdoc-file=ext/socket/basicsocket.c
Expand Down Expand Up @@ -544,7 +544,8 @@ class BasicSocket < IO
# IPAddr.new(Socket::INADDR_ANY, Socket::AF_INET).hton
# sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval)
#
def setsockopt: (*Symbol | Integer, boolish | Integer | String) -> void
def setsockopt: (Socket::Option socketoption) -> void
| (interned | Integer level, interned | Integer optname, boolish | Integer | String optval) -> void

# <!--
# rdoc-file=ext/socket/basicsocket.c
Expand Down
314 changes: 314 additions & 0 deletions stdlib/socket/0/socket.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,73 @@ class Socket < BasicSocket
| [T] (String host, Integer port, ?String local_host, ?Integer local_port, ?resolv_timeout: Time::_Timeout, ?connect_timeout: Time::_Timeout) { (instance) -> T } -> T
| [T] (String host, Integer port, ?String local_host, ?Integer local_port, ?open_timeout: Time::_Timeout) { (instance) -> T } -> T

# <!--
# rdoc-file=ext/socket/socket.c
# - Socket.tcp_fast_fallback -> true or false
# -->
# Returns whether Happy Eyeballs Version 2 ([RFC
# 8305](https://datatracker.ietf.org/doc/html/rfc8305)), which is provided
# starting from Ruby 3.4 when using TCPSocket.new and Socket.tcp, is enabled or
# disabled.
#
# If true, it is enabled for TCPSocket.new and Socket.tcp. (Note: Happy Eyeballs
# Version 2 is not provided when using TCPSocket.new on Windows.)
#
# If false, Happy Eyeballs Version 2 is disabled.
#
# For details on Happy Eyeballs Version 2, see
# [Socket.tcp_fast_fallback=](rdoc-ref:Socket.tcp_fast_fallback=).
#
def self.tcp_fast_fallback: () -> bool

# <!--
# rdoc-file=ext/socket/socket.c
# - Socket.tcp_fast_fallback= -> true or false
# -->
# Enable or disable Happy Eyeballs Version 2 ([RFC
# 8305](https://datatracker.ietf.org/doc/html/rfc8305)) globally, which is
# provided starting from Ruby 3.4 when using TCPSocket.new and Socket.tcp.
#
# When set to true, the feature is enabled for both <code>TCPSocket.new</code>
# and <code>Socket.tcp</code>. (Note: This feature is not available when using
# TCPSocket.new on Windows.)
#
# When set to false, the behavior reverts to that of Ruby 3.3 or earlier.
#
# The default value is true if no value is explicitly set by calling this
# method. However, when the environment variable RUBY_TCP_NO_FAST_FALLBACK=1 is
# set, the default is false.
#
# To control the setting on a per-method basis, use the fast_fallback keyword
# argument for each method.
#
# ### Happy Eyeballs Version 2
# Happy Eyeballs Version 2 ([RFC
# 8305](https://datatracker.ietf.org/doc/html/rfc8305)) is an algorithm designed
# to improve client socket connectivity.
# It aims for more reliable and efficient connections by performing hostname
# resolution and connection attempts in parallel, instead of serially.
#
# Starting from Ruby 3.4, this method operates as follows with this algorithm:
#
# 1. Start resolving both IPv6 and IPv4 addresses concurrently.
# 2. Start connecting to the one of the addresses that are obtained first.
# If IPv4 addresses are obtained first, the method waits 50 ms for IPv6 name
# resolution to prioritize IPv6 connections.
# 3. After starting a connection attempt, wait 250 ms for the connection to be
# established.
# If no connection is established within this time, a new connection is
# started every 250 ms
# until a connection is established or there are no more candidate
# addresses.
# (Although RFC 8305 strictly specifies sorting addresses,
# this method only alternates between IPv6 / IPv4 addresses due to the
# performance concerns)
# 4. Once a connection is established, all remaining connection attempts are
# canceled.
#
def self.tcp_fast_fallback=: (bool value) -> bool

# <!--
# rdoc-file=ext/socket/lib/socket.rb
# - tcp_server_loop(host=nil, port) { |socket, client_addrinfo| ... }
Expand Down Expand Up @@ -4156,3 +4223,250 @@ class Socket::AncillaryData
#
def initialize: (interned | Integer family, interned | Integer cmsg_level, interned | Integer cmsg_data, String cmsg_data) -> untyped
end

# <!-- rdoc-file=ext/socket/option.c -->
# Socket::Option represents a socket option used by BasicSocket#getsockopt and
# BasicSocket#setsockopt. A socket option contains the socket #family, protocol
# #level, option name #optname and option value #data.
#
class Socket::Option
# <!--
# rdoc-file=ext/socket/option.c
# - Socket::Option.new(family, level, optname, data) => sockopt
# -->
# Returns a new Socket::Option object.
#
# sockopt = Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [1].pack("i"))
# p sockopt #=> #<Socket::Option: INET SOCKET KEEPALIVE 1>
#
def initialize: (interned | Integer family, interned | Integer level, interned | Integer optname, String data) -> void

# <!--
# rdoc-file=ext/socket/option.c
# - Socket::Option.bool(family, level, optname, bool) => sockopt
# -->
# Creates a new Socket::Option object which contains boolean as data. Actually 0
# or 1 as int is used.
#
# require 'socket'
#
# p Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, true)
# #=> #<Socket::Option: INET SOCKET KEEPALIVE 1>
#
# p Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, false)
# #=> #<Socket::Option: AF_INET SOCKET KEEPALIVE 0>
#
def self.bool: (interned | Integer family, interned | Integer level, interned | Integer optname, boolish bool) -> instance

# <!--
# rdoc-file=ext/socket/option.c
# - Socket::Option.byte(family, level, optname, integer) => sockopt
# -->
# Creates a new Socket::Option object which contains a byte as data.
#
# p Socket::Option.byte(:INET, :SOCKET, :KEEPALIVE, 1)
# #=> #<Socket::Option: INET SOCKET KEEPALIVE 1>
#
def self.byte: (interned | Integer family, interned | Integer level, interned | Integer optname, Integer integer) -> instance

# <!--
# rdoc-file=ext/socket/option.c
# - Socket::Option.int(family, level, optname, integer) => sockopt
# -->
# Creates a new Socket::Option object which contains an int as data.
#
# The size and endian is dependent on the platform.
#
# p Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
# #=> #<Socket::Option: INET SOCKET KEEPALIVE 1>
#
def self.int: (interned | Integer family, interned | Integer level, interned | Integer optname, Integer integer) -> instance

# <!--
# rdoc-file=ext/socket/option.c
# - Socket::Option.ipv4_multicast_loop(integer) => sockopt
# -->
# Creates a new Socket::Option object for IP_MULTICAST_LOOP.
#
# The size is dependent on the platform.
#
# sockopt = Socket::Option.int(:INET, :IPPROTO_IP, :IP_MULTICAST_LOOP, 1)
# p sockopt.int => 1
#
# p Socket::Option.ipv4_multicast_loop(10)
# #=> #<Socket::Option: INET IP MULTICAST_LOOP 10>
#
def self.ipv4_multicast_loop: (Integer integer) -> instance

# <!--
# rdoc-file=ext/socket/option.c
# - Socket::Option.ipv4_multicast_ttl(integer) => sockopt
# -->
# Creates a new Socket::Option object for IP_MULTICAST_TTL.
#
# The size is dependent on the platform.
#
# p Socket::Option.ipv4_multicast_ttl(10)
# #=> #<Socket::Option: INET IP MULTICAST_TTL 10>
#
def self.ipv4_multicast_ttl: (Integer integer) -> instance

# <!--
# rdoc-file=ext/socket/option.c
# - Socket::Option.linger(onoff, secs) => sockopt
# -->
# Creates a new Socket::Option object for SOL_SOCKET/SO_LINGER.
#
# *onoff* should be an integer or a boolean.
#
# *secs* should be the number of seconds.
#
# p Socket::Option.linger(true, 10)
# #=> #<Socket::Option: UNSPEC SOCKET LINGER on 10sec>
#
def self.linger: (boolish | Integer onoff, Integer secs) -> instance

# <!--
# rdoc-file=ext/socket/option.c
# - sockopt.bool => true or false
# -->
# Returns the data in *sockopt* as an boolean value.
#
# sockopt = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
# p sockopt.bool => true
#
def bool: () -> bool

# <!--
# rdoc-file=ext/socket/option.c
# - sockopt.byte => integer
# -->
# Returns the data in *sockopt* as an byte.
#
# sockopt = Socket::Option.byte(:INET, :SOCKET, :KEEPALIVE, 1)
# p sockopt.byte => 1
#
def byte: () -> Integer

# <!--
# rdoc-file=ext/socket/option.c
# - sockopt.data => string
# - sockopt.to_s => string
# -->
# returns the socket option data as a string.
#
# p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).data
# #=> "\x01\x00\x00\x00"
#
def data: () -> String

# <!--
# rdoc-file=ext/socket/option.c
# - sockopt.family => integer
# -->
# returns the socket family as an integer.
#
# p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).family
# #=> 10
#
def family: () -> Integer

# <!--
# rdoc-file=ext/socket/option.c
# - sockopt.inspect => string
# -->
# Returns a string which shows sockopt in human-readable form.
#
# p Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [1].pack("i")).inspect
# #=> "#<Socket::Option: INET SOCKET KEEPALIVE 1>"
#
def inspect: () -> String

# <!--
# rdoc-file=ext/socket/option.c
# - sockopt.int => integer
# -->
# Returns the data in *sockopt* as an int.
#
# The size and endian is dependent on the platform.
#
# sockopt = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
# p sockopt.int => 1
#
def int: () -> Integer

# <!--
# rdoc-file=ext/socket/option.c
# - sockopt.ipv4_multicast_loop => integer
# -->
# Returns the ipv4_multicast_loop data in *sockopt* as an integer.
#
# sockopt = Socket::Option.ipv4_multicast_loop(10)
# p sockopt.ipv4_multicast_loop => 10
#
def ipv4_multicast_loop: () -> Integer

# <!--
# rdoc-file=ext/socket/option.c
# - sockopt.ipv4_multicast_ttl => integer
# -->
# Returns the ipv4_multicast_ttl data in *sockopt* as an integer.
#
# sockopt = Socket::Option.ipv4_multicast_ttl(10)
# p sockopt.ipv4_multicast_ttl => 10
#
def ipv4_multicast_ttl: () -> Integer

# <!--
# rdoc-file=ext/socket/option.c
# - sockopt.level => integer
# -->
# returns the socket level as an integer.
#
# p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).level
# #=> 41
#
def level: () -> Integer

# <!--
# rdoc-file=ext/socket/option.c
# - sockopt.linger => [bool, seconds]
# -->
# Returns the linger data in *sockopt* as a pair of boolean and integer.
#
# sockopt = Socket::Option.linger(true, 10)
# p sockopt.linger => [true, 10]
#
def linger: () -> [ bool, Integer ]

# <!--
# rdoc-file=ext/socket/option.c
# - sockopt.optname => integer
# -->
# returns the socket option name as an integer.
#
# p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).optname
# #=> 2
#
def optname: () -> Integer

# <!-- rdoc-file=ext/socket/option.c -->
# returns the socket option data as a string.
#
# p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).data
# #=> "\x01\x00\x00\x00"
#
alias to_s data

# <!--
# rdoc-file=ext/socket/option.c
# - sockopt.unpack(template) => array
# -->
# Calls String#unpack on sockopt.data.
#
# sockopt = Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [1].pack("i"))
# p sockopt.unpack("i") #=> [1]
# p sockopt.data.unpack("i") #=> [1]
#
def unpack: (String template) -> Array[untyped]
end
24 changes: 24 additions & 0 deletions stdlib/socket/0/socket_error.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,27 @@
#
class SocketError < StandardError
end

# <!-- rdoc-file=ext/socket/init.c -->
# Socket::ResolutionError is the error class for hostname resolution.
#
class Socket::ResolutionError < SocketError
# <!--
# rdoc-file=ext/socket/init.c
# - error_code -> integer
# -->
# Returns the raw error code indicating the cause of the hostname resolution
# failure.
#
# begin
# Addrinfo.getaddrinfo("ruby-lang.org", nil)
# rescue Socket::ResolutionError => e
# if e.error_code == Socket::EAI_AGAIN
# puts "Temporary failure in name resolution."
# end
# end
#
# Note that error codes depend on the operating system.
#
def error_code: () -> Integer
end
Loading
Loading