Skip to content
This repository was archived by the owner on Aug 29, 2024. It is now read-only.
Closed
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
15 changes: 15 additions & 0 deletions lib/async/io/endpoint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Async::IO::Endpoint

An endpoint is typically something you can connect to as a client, or bind to as a server. Sometimes the client and server endpoints need to be different, e.g. when dealing with TLS/SSL encryption where the client side needs a public key and the server side needs a private key.

## Shared Endpoints

Sometimes it's useful to bind or

endpoint = Async::HTT::Endpoint.parse("https://localhost")

endpoint.

endpoint.wrap(SharedEndpoint.bound(endpoint))


6 changes: 3 additions & 3 deletions lib/async/io/endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,12 @@ def bound
wrapper = endpoint.bind
wrappers << wrapper

yield wrapper
yield(wrapper) if block_given?
end

return wrappers
ensure
wrappers.each(&:close) if $!
rescue
wrappers.each(&:close)
end

# 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.
Expand Down
10 changes: 10 additions & 0 deletions lib/async/io/shared_endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,15 @@ def to_s
"\#<#{self.class} #{@wrappers.size} descriptors for #{@endpoint}>"
end
end

class Endpoint
def bound_endpoint(**options)
SharedEndpoint.bound(self, **options)
end

def connected_endpoint(**options)
SharedEndpoint.connected(self, **options)
end
end
end
end
15 changes: 13 additions & 2 deletions lib/async/io/ssl_endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@
module Async
module IO
class SSLEndpoint < Endpoint
def initialize(endpoint, **options)
def initialize(endpoint, context = nil, **options)
super(**options)

@endpoint = endpoint

if ssl_context = options[:ssl_context]
if context
@context = context
elsif ssl_context = options[:ssl_context]
@context = build_context(ssl_context)
else
@context = nil
Expand Down Expand Up @@ -99,6 +101,15 @@ def each
yield self.class.new(endpoint, **@options)
end
end

# I explored this idea but I'm not sure it's a good one as bound endpoints don't have the same life-time as normal endpoints.
# def bound_endpoint(**options)
# self.class.new(@endpoint.bound_endpoint(**options), @context, **@options)
# end
#
# def connected_endpoint(**options)
# self.class.new(@endpoint.connected_endpoint(**options), @context, **@options)
# end
end

# Backwards compatibility.
Expand Down
17 changes: 17 additions & 0 deletions spec/async/io/shared_endpoint_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

require 'async/io/host_endpoint'
require 'async/io/shared_endpoint'
require 'async/io/ssl_endpoint'

RSpec.describe Async::IO::SharedEndpoint do
include_context Async::RSpec::Reactor
Expand Down Expand Up @@ -74,4 +75,20 @@
server_task.stop
end
end

describe '#bound_endpoint' do
let(:endpoint) {Async::IO::Endpoint.tcp("127.0.0.1", 7001, reuse_port: true, timeout: 10)}
let(:server_endpoint) {Async::IO::SSLEndpoint.new(endpoint)}
let(:client_endpoint) {Async::IO::SSLEndpoint.new(endpoint)}

it "can create an internally shared bound endpoint" do
bound_endpoint = server_endpoint.bound_endpoint

expect(bound_endpoint).to be_kind_of(server_endpoint.class)
expect(bound_endpoint.endpoint).to be_kind_of(Async::IO::SharedEndpoint)

ensure
bound_endpoint.close
end
end
end