Class: Quic::Connection::Client
- Inherits:
-
Object
- Object
- Quic::Connection::Client
- Defined in:
- lib/quic/connection.rb
Class Method Summary collapse
Instance Method Summary collapse
-
#bind(sock) ⇒ Object
Attach an IO.select / #send / #recvfrom-compatible UDP socket so that #run and Stream blocking I/O can drive the wire transparently.
- #bound_socket ⇒ Object
-
#pump_once(timeout: nil) ⇒ Object
One iteration of the I/O loop: drain any outgoing packets via #write_pkt, then wait up to ‘timeout` (or the next ngtcp2 expiry, whichever is sooner) for either an incoming datagram or the timer to fire.
-
#pump_until(&pred) ⇒ Object
Iterate pump_once until ‘pred` returns truthy.
-
#run ⇒ Object
Drive the handshake to completion using the bound socket.
Class Method Details
.new(host:, port:, transport_params: nil, settings: nil) ⇒ Object
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/quic/connection.rb', line 8 def self.new(host:, port:, transport_params: nil, settings: nil) remote_sockaddr = Addrinfo.udp(host, port).to_sockaddr local_sockaddr = Addrinfo.udp("0.0.0.0", 0).to_sockaddr client = _open( local_sockaddr: local_sockaddr, remote_sockaddr: remote_sockaddr, server_name: host, transport_params: transport_params || Quic::TransportParams.default, settings: settings || Quic::Settings.default ) client.instance_variable_set(:@host, host) client.instance_variable_set(:@port, port) client end |
Instance Method Details
#bind(sock) ⇒ Object
Attach an IO.select / #send / #recvfrom-compatible UDP socket so that #run and Stream blocking I/O can drive the wire transparently. Caller is responsible for socket lifetime; we do not close it. The socket must already be #connect’d to the peer (we read #remote_address).
28 29 30 31 |
# File 'lib/quic/connection.rb', line 28 def bind(sock) @sock = sock self end |
#bound_socket ⇒ Object
33 34 35 |
# File 'lib/quic/connection.rb', line 33 def bound_socket @sock end |
#pump_once(timeout: nil) ⇒ Object
One iteration of the I/O loop: drain any outgoing packets via #write_pkt, then wait up to ‘timeout` (or the next ngtcp2 expiry, whichever is sooner) for either an incoming datagram or the timer to fire. Public-ish so Stream blocking ops can share it; documented as “internal” for users.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/quic/connection.rb', line 51 def pump_once(timeout: nil) raise Quic::Error::NotBound, "Quic::Connection::Client#bind(sock) has not been called" if @sock.nil? while (pkt = write_pkt) @sock.send(pkt, 0) end wait_for = pump_timeout(timeout) ready = IO.select([@sock], nil, nil, wait_for) if ready data, _addr = @sock.recvfrom(2048) # Reuse the same path tuple that Client.new / Client._open passed to # ngtcp2_conn_client_new so the read_pkt path matches the stored # connection path. local is 0.0.0.0:0 (Client.new convention) and # remote comes from the connected socket (assumes #connect was used). read_pkt( data, local_sockaddr: pump_local_sockaddr, remote_sockaddr: pump_remote_sockaddr ) else handle_expiry end end |
#pump_until(&pred) ⇒ Object
Iterate pump_once until ‘pred` returns truthy. Public so Stream blocking methods can share it.
78 79 80 |
# File 'lib/quic/connection.rb', line 78 def pump_until(&pred) pump_once until pred.call end |
#run ⇒ Object
Drive the handshake to completion using the bound socket. Raises Quic::Error::NotBound if #bind has not been called. Propagates any Quic::Error subclass raised by #read_pkt / #handle_expiry.
40 41 42 43 44 |
# File 'lib/quic/connection.rb', line 40 def run raise Quic::Error::NotBound, "Quic::Connection::Client#bind(sock) has not been called" if @sock.nil? pump_until { handshake_completed? } end |