Class: Async::IO::Endpoint

Inherits:
Object
  • Object
show all
Defined in:
lib/async/io/endpoint.rb,
lib/async/io/ssl_endpoint.rb,
lib/async/io/endpoint/each.rb,
lib/async/io/host_endpoint.rb,
lib/async/io/unix_endpoint.rb,
lib/async/io/socket_endpoint.rb

Overview

Endpoints represent a way of connecting or binding to an address.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**options) ⇒ Endpoint



32
33
34
# File 'lib/async/io/endpoint.rb', line 32

def initialize(**options)
  @options = options.freeze
end

Instance Attribute Details

#optionsObject

Returns the value of attribute options.



44
45
46
# File 'lib/async/io/endpoint.rb', line 44

def options
  @options
end

Class Method Details

.each(specifications, &block) ⇒ Object

Generate a list of endpoints from an array.



47
48
49
50
51
52
53
# File 'lib/async/io/endpoint/each.rb', line 47

def self.each(specifications, &block)
  return to_enum(:each, specifications) unless block_given?
  
  specifications.each do |specification|
    yield try_convert(specification)
  end
end

.parse(string, **options) ⇒ Object

Create an Endpoint instance by URI scheme. The host and port of the URI will be passed to the Endpoint factory method, along with any options.



123
124
125
126
127
# File 'lib/async/io/endpoint.rb', line 123

def self.parse(string, **options)
  uri = URI.parse(string)
  
  self.public_send(uri.scheme, uri.host, uri.port, **options)
end

.socket(socket, **options) ⇒ Object



68
69
70
# File 'lib/async/io/socket_endpoint.rb', line 68

def self.socket(socket, **options)
  SocketEndpoint.new(socket, **options)
end

.ssl(*args, ssl_context: nil, hostname: nil, **options) ⇒ SSLEndpoint



114
115
116
# File 'lib/async/io/ssl_endpoint.rb', line 114

def self.ssl(*args, ssl_context: nil, hostname: nil, **options)
  SSLEndpoint.new(self.tcp(*args, **options), ssl_context: ssl_context, hostname: hostname)
end

.tcp(*args, **options) ⇒ HostEndpoint



100
101
102
103
104
# File 'lib/async/io/host_endpoint.rb', line 100

def self.tcp(*args, **options)
  args[3] = ::Socket::SOCK_STREAM
  
  HostEndpoint.new(args, **options)
end

.try_convert(specification) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/async/io/endpoint/each.rb', line 30

def self.try_convert(specification)
  if specification.is_a? self
    specification
  elsif specification.is_a? Array
    self.send(*specification)
  elsif specification.is_a? String
    self.parse(specification)
  elsif specification.is_a? ::BasicSocket
    self.socket(specification)
  elsif specification.is_a? Generic
    self.new(specification)
  else
    raise ArgumentError.new("Not sure how to convert #{specification} to endpoint!")
  end
end

.udp(*args, **options) ⇒ HostEndpoint



110
111
112
113
114
# File 'lib/async/io/host_endpoint.rb', line 110

def self.udp(*args, **options)
  args[3] = ::Socket::SOCK_DGRAM
  
  HostEndpoint.new(args, **options)
end

.unix(path = "", type = ::Socket::SOCK_STREAM, **options) ⇒ UNIXEndpoint



69
70
71
# File 'lib/async/io/unix_endpoint.rb', line 69

def self.unix(path = "", type = ::Socket::SOCK_STREAM, **options)
  UNIXEndpoint.new(path, type, **options)
end

Instance Method Details

#accept(backlog = Socket::SOMAXCONN, &block) ⇒ Object

Accept connections from the specified endpoint.



89
90
91
92
93
94
95
# File 'lib/async/io/endpoint.rb', line 89

def accept(backlog = Socket::SOMAXCONN, &block)
  bind do |server|
    server.listen(backlog)
    
    server.accept_each(&block)
  end
end

#bound { ... } ⇒ Object

Map all endpoints by invoking #bind.

Yields:

  • the bound wrapper.



99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/async/io/endpoint.rb', line 99

def bound
  wrappers = []
  
  self.each do |endpoint|
    wrapper = endpoint.bind
    wrappers << wrapper
    
    yield wrapper
  end
  
  return wrappers
ensure
  wrappers.each(&:close) if $!
end

#each {|Endpoint| ... } ⇒ Object

Endpoints sometimes have multiple paths.

Yields:

  • (Endpoint)

    Enumerate all discrete paths as endpoints.



81
82
83
84
85
# File 'lib/async/io/endpoint.rb', line 81

def each
  return to_enum unless block_given?
  
  yield self
end

#hostnameString



47
48
49
# File 'lib/async/io/endpoint.rb', line 47

def hostname
  @options[:hostname]
end

#lingerInteger?

Controls SO_LINGER. The amount of time the socket will stay in the TIME_WAIT state after being closed.



65
66
67
# File 'lib/async/io/endpoint.rb', line 65

def linger
  @options[:linger]
end

#local_addressAddress



75
76
77
# File 'lib/async/io/endpoint.rb', line 75

def local_address
  @options[:local_address]
end

#reuse_addressBoolean

If SO_REUSEADDR is enabled on a socket prior to binding it, the socket can be successfully bound unless there is a conflict with another socket bound to exactly the same combination of source address and port. Additionally, when set, binding a socket to the address of an existing socket in TIME_WAIT is not an error.



59
60
61
# File 'lib/async/io/endpoint.rb', line 59

def reuse_address
  @options[:reuse_address]
end

#reuse_portBoolean?

If SO_REUSEPORT is enabled on a socket, the socket can be successfully bound even if there are existing sockets bound to the same address, as long as all prior bound sockets also had SO_REUSEPORT set before they were bound.



53
54
55
# File 'lib/async/io/endpoint.rb', line 53

def reuse_port
  @options[:reuse_port]
end

#timeoutNumeric



70
71
72
# File 'lib/async/io/endpoint.rb', line 70

def timeout
  @options[:timeout]
end

#with(**options) ⇒ Object



36
37
38
39
40
41
42
# File 'lib/async/io/endpoint.rb', line 36

def with(**options)
  dup = self.dup
  
  dup.options = @options.merge(options)
  
  return dup
end