Add support for specifying family

This commit is contained in:
Omar Roth 2019-11-27 11:53:14 -06:00
parent 31ad3664a5
commit 32aee44d8e

View file

@ -124,6 +124,8 @@ module QUIC
ENGINE_FLAGS = LibLsquic::LSENG_HTTP ENGINE_FLAGS = LibLsquic::LSENG_HTTP
LibLsquic.global_init(ENGINE_FLAGS & LibLsquic::LSENG_SERVER ? LibLsquic::GLOBAL_SERVER : LibLsquic::GLOBAL_CLIENT) LibLsquic.global_init(ENGINE_FLAGS & LibLsquic::LSENG_SERVER ? LibLsquic::GLOBAL_SERVER : LibLsquic::GLOBAL_CLIENT)
property family : Socket::Family = Socket::Family::UNSPEC
# The set of possible valid body types. # The set of possible valid body types.
alias BodyType = String | Bytes | IO | Nil alias BodyType = String | Bytes | IO | Nil
@ -135,6 +137,7 @@ module QUIC
@dns_timeout : Float64? @dns_timeout : Float64?
@connect_timeout : Float64? @connect_timeout : Float64?
@read_timeout : Float64? @read_timeout : Float64?
@socket : UDPSocket?
def initialize(@host : String, port = nil, tls : Bool | OpenSSL::SSL::Context::Client = false) def initialize(@host : String, port = nil, tls : Bool | OpenSSL::SSL::Context::Client = false)
check_host_only(@host) check_host_only(@host)
@ -150,7 +153,7 @@ module QUIC
@port = (port || 443).to_i @port = (port || 443).to_i
@stream_channel = Channel(StreamCtx?).new(20) @stream_channel = Channel(StreamCtx?).new(20)
spawn run_engine @engine_open = false
end end
def run_engine def run_engine
@ -182,17 +185,7 @@ module QUIC
engine = LibLsquic.engine_new(ENGINE_FLAGS, pointerof(engine_api)) engine = LibLsquic.engine_new(ENGINE_FLAGS, pointerof(engine_api))
hostname = host.starts_with?('[') && host.ends_with?(']') ? host[1..-2] : host hostname = host.starts_with?('[') && host.ends_with?(']') ? host[1..-2] : host
@engine_open = true
socket = UDPSocket.new
socket.bind Socket::IPAddress.new("0.0.0.0", 0)
socket.read_timeout = @read_timeout if @read_timeout
Socket::Addrinfo.udp(@host, @port, timeout: @dns_timeout) do |addrinfo|
socket.connect(addrinfo, timeout: @connect_timeout) do |error|
error
end
end
socket.sync = false
engine_closed = false
conn = LibLsquic.engine_connect(engine, LibLsquic::Version::Lsqver046, socket.local_address, socket.remote_address, Box.box(socket), nil, hostname, 0, nil, 0, nil, 0) conn = LibLsquic.engine_connect(engine, LibLsquic::Version::Lsqver046, socket.local_address, socket.remote_address, Box.box(socket), nil, hostname, 0, nil, 0, nil, 0)
spawn do spawn do
@ -201,18 +194,38 @@ module QUIC
LibLsquic.conn_make_stream(conn) LibLsquic.conn_make_stream(conn)
LibLsquic.engine_process_conns(engine) LibLsquic.engine_process_conns(engine)
end end
engine_closed = true @engine_open = false
LibLsquic.engine_destroy(engine) LibLsquic.engine_destroy(engine)
end end
buffer = Bytes.new(0x600) buffer = Bytes.new(0x600)
loop do loop do
bytes_read = socket.read buffer bytes_read = socket.read buffer
break if engine_closed break if !@engine_open
LibLsquic.engine_packet_in(engine, buffer[0, bytes_read], bytes_read, socket.local_address, socket.remote_address, Box.box(socket), 0) if bytes_read != 0 LibLsquic.engine_packet_in(engine, buffer[0, bytes_read], bytes_read, socket.local_address, socket.remote_address, Box.box(socket), 0) if bytes_read != 0
LibLsquic.engine_process_conns(engine) LibLsquic.engine_process_conns(engine)
end end
socket.close @socket.try &.close
@socket = nil
end
def socket : UDPSocket
socket = @socket
return socket.not_nil! if @socket
socket = UDPSocket.new
socket.bind Socket::IPAddress.new("0.0.0.0", 0)
Socket::Addrinfo.udp(@host, @port, timeout: @dns_timeout, family: @family) do |addrinfo|
socket.connect(addrinfo, timeout: @connect_timeout) do |error|
close
error
end
end
socket.read_timeout = @read_timeout if @read_timeout
socket.sync = false
@socket = socket
end end
private def check_host_only(string : String) private def check_host_only(string : String)
@ -410,6 +423,8 @@ module QUIC
set_defaults request set_defaults request
run_before_request_callbacks(request) run_before_request_callbacks(request)
spawn run_engine if !@engine_open
reader, writer = IO::ChanneledPipe.new reader, writer = IO::ChanneledPipe.new
stream_ctx = StreamCtx.new(request, writer) stream_ctx = StreamCtx.new(request, writer)
@stream_channel.send stream_ctx @stream_channel.send stream_ctx
@ -460,12 +475,8 @@ module QUIC
end end
end end
def destroy_engine
@stream_channel.send nil
end
def close def close
# TODO @stream_channel.send nil
end end
private def new_request(method, path, headers, body : BodyType) private def new_request(method, path, headers, body : BodyType)