moonbitstack/moonnet/udp does not have a README file

    QuicRefused

    pub(all) suberror QuicRefused {
    Timeout
    Broken(String)
    Closed
    Reset(UInt64)
    Stopped(UInt64)
    } derive(Eq,
    Debug
    )

    What a QUIC connection will not do.

    QuicRefused::equal

    fn QuicRefused::equal(QuicRefused, QuicRefused) -> Bool

    QuicRefused::not_equal

    fn QuicRefused::not_equal(x : QuicRefused, y : QuicRefused) -> Bool

    Quic

    pub struct Quic {
    socket : Socket
    to :
    Addr

    client :
    Client

    bi : UInt64
    uni : UInt64
    dead : Bool
    seen : Map[UInt64, Bool]
    sent : Map[UInt64, UInt64]
    errors : Map[UInt64, QuicRefused]
    abandoned : Map[UInt64, UInt64]
    }

    A QUIC connection driven by one task: the client half of what moonquic states and this package puts on a datagram socket. Reading is a poll, because a connection that also carries control and QPACK streams cannot hand every arrival to one caller.

    Quic::alpn

    fn Quic::alpn(self : Quic) -> String?

    The ALPN the handshake settled on.

    Quic::close

    fn Quic::close(self : Quic) -> Unit

    Close the socket the connection runs on.

    Quic::ended

    fn Quic::ended(self : Quic, stream : UInt64) -> Bool

    Whether the peer has ended stream, with every octet of it read. A stream the peer reset is over too, however much of it arrived.

    Quic::open_bi

    fn Quic::open_bi(self : Quic) -> UInt64

    The next bidirectional stream this side opens: 0, 4, 8, … as RFC 9000 §2.1 numbers them.

    Quic::open_uni

    fn Quic::open_uni(self : Quic) -> UInt64

    The next unidirectional stream, from 2 upwards.

    Quic::refused

    fn Quic::refused(self : Quic, stream : UInt64) -> QuicRefused?

    How the peer ended stream abruptly, if it did: Reset for a stream this side was reading, Stopped for one it was writing. None while the stream is live, and after a clean FIN — which is what ended reports.

    Quic::reset

    fn Quic::reset(self : Quic, stream : UInt64, code? : UInt64) -> Unit raise QuicRefused

    Abandon stream as a sender: send RESET_STREAM carrying code, and drop what the send loop still holds for it (RFC 9000 §3.5, §19.4). Zero, the default, is NO_ERROR (§20.1). Writing on the stream afterwards raises Reset. A stream this side only reads may be reset too: it closes this side's sending half, which is what a reply abandoned half way needs.

    Quic::step

    async fn Quic::step(self : Quic, timeout? : Int) -> Bool raise QuicRefused

    Send what the connection has queued and take one datagram in, which is one turn of a handshake or of an exchange. False when nothing arrived within timeout.

    Quic::stop

    fn Quic::stop(self : Quic, stream : UInt64, code? : UInt64) -> Unit raise QuicRefused

    Ask the peer to stop sending on stream, with STOP_SENDING carrying code (RFC 9000 §19.5): the octets already on their way are dropped when they arrive, and take raises Reset if the peer answers with one. Zero, the default, is NO_ERROR (§20.1).

    Quic::take

    fn Quic::take(self : Quic, stream : UInt64) -> Bytes raise QuicRefused

    The octets that arrived on stream since the last call; empty when none have. What arrived before a reset is still handed over first: RFC 9000 §3.2 keeps the octets received up to the final size readable, and it is the end that is an error. An empty read raises Reset once the peer has abandoned the stream.

    Quic::write

    fn Quic::write(self : Quic, stream : UInt64, bytes : Bytes, fin? : Bool) -> Unit raise QuicRefused

    Put bytes on stream, and end it when fin. Raises Stopped when the peer has asked this side to stop sending on the stream, and Reset when this side abandoned it.

    Socket

    A datagram socket. One task may receive while others send; two tasks receiving at once would each take half the datagrams, so a connection that needs one reader keeps one.

    Socket::addr

    The address bound; with port 0 asked for, the port the system chose.

    Socket::close

    fn Socket::close(self : Socket) -> Unit

    Stop using the socket.

    Socket::recv

    async fn Socket::recv(self : Socket, max? : Int, timeout? : Int) -> (Bytes,
    Addr
    )?

    The next datagram, or None when timeout milliseconds pass first. Without a timeout it waits for one, which is what a server does and a client polling a handshake does not.

    Socket::send

    async fn Socket::send(self : Socket, to :
    Addr
    , bytes : Bytes) -> Unit

    Send one datagram.

    attempt_delay

    let attempt_delay : Int

    How long a QUIC dial gives one address before it tries the next one as well: the connection attempt delay of RFC 8305 §5, at the 250 ms §8 recommends.

    bind

    async fn bind(host? : String, port? : Int) -> Socket

    Bind host:port. Port 0 asks the system for a free one, which addr reports.

    dial

    async fn dial(host : String, port~ : Int, tls~ :
    Client
    , idle? : UInt64, attempt_delay? : Int) -> Quic raise QuicRefused

    Connect to host:port and shake hands. The connection is returned once the handshake is confirmed; tls offers h3 or whatever ALPN the peer is expected to choose.

    A name with both an IPv6 and an IPv4 address is dialled as RFC 8305 says: IPv6 first, IPv4 as well once attempt_delay milliseconds pass without an answer or the first attempt fails, and the first handshake to complete is kept. A path that drops datagrams costs one delay, not a handshake timeout. A name with one address is dialled as it always was.

    dial_addrs

    async fn dial_addrs(addrs : ArrayView[
    Addr
    ], host~ : String, tls~ :
    Client
    , idle? : UInt64, attempt_delay? : Int) -> Quic raise QuicRefused

    dial to addresses already looked up, such as the ones a service registry gives: they are tried in the order given, with the same delay between attempts, and host is the name the certificate is checked against.

    now

    fn now() -> Int64

    The clock a QUIC connection counts in: microseconds since the epoch, which is the unit the recovery, idle and closing-period timers are measured in (RFC 9002 §6). Reading it in milliseconds leaves every timer a thousand times too long, so a lost packet is never sent again.

    Source Files