class IO::Endpoint::SharedEndpoint
Pre-connect and pre-bind sockets so that it can be used between processes.
def self.bound(endpoint, backlog: Socket::SOMAXCONN, close_on_exec: false, **options)
def self.bound(endpoint, backlog: Socket::SOMAXCONN, close_on_exec: false, **options) sockets = [] endpoint.each do |server_endpoint| server = server_endpoint.bind(**options) # This is somewhat optional. We want to have a generic interface as much as possible so that users of this interface can just call it without knowing a lot of internal details. Therefore, we ignore errors here if it's because the underlying socket does not support the operation. begin server.listen(backlog) rescue Errno::EOPNOTSUPP # Ignore. end server.close_on_exec = close_on_exec sockets << server end return self.new(endpoint, sockets) end
def self.connected(endpoint, close_on_exec: false)
def self.connected(endpoint, close_on_exec: false) wrapper = endpoint.connect wrapper.close_on_exec = close_on_exec return self.new(endpoint, [wrapper]) end
def accept(**options, &block)
def accept(**options, &block) bind do |server| server.accept(&block) end end
def bind(wrapper = Wrapper.default, &block)
def bind(wrapper = Wrapper.default, &block) @sockets.each.map do |server| server = server.dup if block_given? wrapper.async do begin yield server ensure server.close end end else server end end end
def close
def close @sockets.each(&:close) @sockets.clear end
def connect(wrapper = Wrapper.default, &block)
def connect(wrapper = Wrapper.default, &block) @sockets.each do |socket| socket = socket.dup return socket unless block_given? begin return yield(socket) ensure socket.close end end end
def each(&block)
def each(&block) return to_enum unless block_given? @sockets.each do |socket| yield SocketEndpoint.new(socket.dup) end end
def initialize(endpoint, sockets, **options)
def initialize(endpoint, sockets, **options) super(**options) raise TypeError, "sockets must be an Array" unless sockets.is_a?(Array) @endpoint = endpoint @sockets = sockets end
def local_address_endpoint(**options)
def local_address_endpoint(**options) endpoints = @sockets.map do |wrapper| AddressEndpoint.new(wrapper.to_io.local_address) end return CompositeEndpoint.new(endpoints, **options) end
def remote_address_endpoint(**options)
def remote_address_endpoint(**options) endpoints = @sockets.map do |wrapper| AddressEndpoint.new(wrapper.to_io.remote_address) end return CompositeEndpoint.new(endpoints, **options) end
def to_s
def to_s "\#<#{self.class} #{@sockets.size} descriptors for #{@endpoint}>" end