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

Returns a new instance of Endpoint.



30
31
32
# File 'lib/async/io/endpoint.rb', line 30

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

Instance Attribute Details

#optionsObject

Returns the value of attribute options.



42
43
44
# File 'lib/async/io/endpoint.rb', line 42

def options
  @options
end

Class Method Details

.each(specifications, &block) ⇒ Object

Generate a list of endpoints from an array.



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

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.



121
122
123
124
125
# File 'lib/async/io/endpoint.rb', line 121

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

.socket(socket, **options) ⇒ Object



66
67
68
# File 'lib/async/io/socket_endpoint.rb', line 66

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

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

Parameters:

  • args
  • ssl_context (OpenSSL::SSL::SSLContext, nil) (defaults to: nil)
  • hostname (String, nil) (defaults to: nil)
  • options

    keyword arguments passed through to tcp

Returns:



112
113
114
# File 'lib/async/io/ssl_endpoint.rb', line 112

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

Parameters:

  • args

    nodename, service, family, socktype, protocol, flags. socktype will be set to Socket::SOCK_STREAM.

  • options

    keyword arguments passed on to HostEndpoint#initialize

Returns:



98
99
100
101
102
# File 'lib/async/io/host_endpoint.rb', line 98

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

.try_convert(specification) ⇒ Object



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

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

Parameters:

  • args

    nodename, service, family, socktype, protocol, flags. socktype will be set to Socket::SOCK_DGRAM.

  • options

    keyword arguments passed on to HostEndpoint#initialize

Returns:



108
109
110
111
112
# File 'lib/async/io/host_endpoint.rb', line 108

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

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

Parameters:

  • path (String)
  • type (defaults to: ::Socket::SOCK_STREAM)

    Socket type

  • options

    keyword arguments passed through to UNIXEndpoint#initialize

Returns:



67
68
69
# File 'lib/async/io/unix_endpoint.rb', line 67

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.

Parameters:

  • backlog (Integer) (defaults to: Socket::SOMAXCONN)

    the number of connections to listen for.



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

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.



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

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.



79
80
81
82
83
# File 'lib/async/io/endpoint.rb', line 79

def each
	return to_enum unless block_given?
	
	yield self
end

#hostnameString

Returns The hostname of the bound socket.

Returns:

  • (String)

    The hostname of the bound socket.



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

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.

Returns:

  • (Integer, nil)

    The value for SO_LINGER.



63
64
65
# File 'lib/async/io/endpoint.rb', line 63

def linger
	@options[:linger]
end

#local_addressAddress

Returns the address to bind to before connecting.

Returns:

  • (Address)

    the address to bind to before connecting.



73
74
75
# File 'lib/async/io/endpoint.rb', line 73

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.

Returns:

  • (Boolean)

    The value for SO_REUSEADDR.



57
58
59
# File 'lib/async/io/endpoint.rb', line 57

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.

Returns:

  • (Boolean, nil)

    The value for SO_REUSEPORT.



51
52
53
# File 'lib/async/io/endpoint.rb', line 51

def reuse_port
	@options[:reuse_port]
end

#timeoutNumeric

Returns The default timeout for socket operations.

Returns:

  • (Numeric)

    The default timeout for socket operations.



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

def timeout
	@options[:timeout]
end

#with(**options) ⇒ Object



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

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