The following cmsgs contain a native-endian 32-bit integer:
- IP_TOS, passed to sendmsg
- IPV6_TCLASS, always
IP_TOS received from recvmsg contains a single byte, because why not.
We were inadvertently assuming little-endian integers in all cases.
Add endianness conversion as appropriate.
Disable tests that rely on IPv4-in-IPv6 mapped sockets on dragonfly
and openbsd, which don't support this feature. (A "udp" socket cannot
receive IPv6 packets on these platforms.)
Disable IPv6 tests on wasm, where the simulated networking appears
to generally not support IPv6.
Fixesgolang/go#65906Fixesgolang/go#65907
Change-Id: Ie50af12e182a1a5d685ce4fbdf008748f6aee339
Reviewed-on: https://go-review.googlesource.com/c/net/+/566296
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Client connections must set tls.Config.ServerName to authenticate
the identity of the server. (RFC 9001, Section 4.4.)
Previously, we specified a single tls.Config per Endpoint.
Change the Config passed to Listen to only apply to
client connections accepted by the endpoint.
Add a Config parameter to Listener.Dial to allow specifying a
separate config per outbound connection, allowing the user
to set the ServerName field.
When the user does not set ServerName, set it ourselves.
For golang/go#58547
Change-Id: Ie2500ae7c7a85400e6cc1c10cefa2bd4c746e313
Reviewed-on: https://go-review.googlesource.com/c/net/+/565796
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
We do not support path migration yet, and will ignore packets
sent from anything other than the peer's original address.
Handle PATH_CHALLENGE frames by sending a PATH_RESPONSE.
Handle PATH_RESPONSE frames by closing the connection
(since we never send a challenge to respond to).
For golang/go#58547
Change-Id: I828b9dcb23e17f5edf3d605b8f04efdafb392807
Reviewed-on: https://go-review.googlesource.com/c/net/+/565795
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Make the abstraction over UDP connections higher level,
and add support for setting the source address and ECN
bits in sent packets, and receving the destination
address and ECN bits in received packets.
There is no good way that I can find to identify the
source IP address of packets we send. Look up the
destination IP address of the first packet received on
each connection, and use this as the source address
for all future packets we send. This avoids unexpected
path migration, where the address we send from changes
without our knowing it.
Reject received packets sent from an unexpected peer
address.
In the future, when we support path migration, we will want
to relax these restrictions.
ECN bits may be used to detect network congestion.
We don't make use of them at this time, but this CL adds
the necessary UDP layer support to do so in the future.
This CL also lays the groundwork for using more efficient
platform APIs to send/receive packets in the future.
(sendmmsg/recvmmsg/GSO/GRO)
These features require platform-specific APIs.
Add support for Darwin and Linux to start with,
with a graceful fallback on other OSs.
For golang/go#58547
Change-Id: I1c97cc0d3e52fff18e724feaaac4a50d3df671bc
Reviewed-on: https://go-review.googlesource.com/c/net/+/565255
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
When appendStreamFrame is provided with the last chunk of data
for a stream, doesn't have enough space in the packet to include
all the data, don't incorrectly record the packet as including
a FIN bit. We were correctly sending a STREAM frame with no FIN
bit--it's just the sent packet accounting that was off.
No test, because I can't figure out a scenario where this
actually has an observable effect, since we're always going
to send the FIN when the remaining stream data is sent.
Change-Id: I0ee81273165fcf10a52da76b33d2bf1b9c4f3523
Reviewed-on: https://go-review.googlesource.com/c/net/+/564796
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Keep a reference to the next chunk of bytes available for reading
in an unsynchronized buffer. Read and ReadByte calls read from this
buffer when possible, avoiding the need to lock the stream.
This change makes it unnecessary to wrap a stream in a *bytes.Buffer
when making small reads, at the expense of making reads
concurrency-unsafe. Since the quic package is a low-level one and
this lets us avoid an extra buffer in the HTTP/3 implementation,
the tradeoff seems worthwhile.
For golang/go#58547
Change-Id: Ib3ca446311974571c2367295b302f36a6349b00d
Reviewed-on: https://go-review.googlesource.com/c/net/+/564495
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
RFC 9000 recommends sending an ack for every second ack-eliciting
packet received. This frequency is high enough to have a noticeable
impact on performance.
Follow the approach used by Google QUICHE: Ack every other packet
for the first 100 packets, and then switch to acking every 10th
packet.
(Various other implementations also use a reduced ack frequency;
see Custura et al., 2022.)
For golang/go#58547
Change-Id: Idc7051cec23c279811030eb555bc49bb888d6795
Reviewed-on: https://go-review.googlesource.com/c/net/+/564476
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Auto-Submit: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
The ReadContext, WriteContext, and CloseContext Stream methods are
difficult to use in conjunction with functions that operate on an
io.Reader, io.Writer, or io.Closer. For example, it's reasonable
to want to use io.ReadFull with a Stream, but doing so with a context
is cumbersome.
Drop the Stream methods that take a Context in favor of stateful
methods that set the Context to use for read and write operations.
(Close counts as a write operation, since it blocks waiting for
data to be sent.)
Intentionally make Set{Read,Write}Context not concurrency safe,
to allow the race detector to catch misuse. This shouldn't be a
problem for correct programs, since reads and writes are
inherently not concurrency-safe.
For golang/go#58547
Change-Id: I41378eb552d89a720921fc8644d3637c1a545676
Reviewed-on: https://go-review.googlesource.com/c/net/+/550795
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
This test assumed that creating a stream and flushing it on the
client ensured the server had accepted the stream. This isn't
the case; the stream has been delivered to the server, but there's
no guarantee that it been accepted by the user layer.
Change the test to make a full loop: The client creates a stream,
and then waits for the server to close it.
Fixesgolang/go#64788
Change-Id: I24f08502e9f5d8bd5a17e680b0aa19dcc2623841
Reviewed-on: https://go-review.googlesource.com/c/net/+/554175
Reviewed-by: Bryan Mills <bcmills@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
The streams map contains nil entries for implicitly-created streams.
(Receiving a packet for stream N implicitly creates all streams of the
same type <N.)
We weren't checking for nil entries when iterating the map on PTO,
resulting in a panic.
Change the map value to be a wrapper type to make it more explicit that
nil entries exist.
Change-Id: I070c6d60631744018a6e6f2645c95a2f3d3d24b6
Reviewed-on: https://go-review.googlesource.com/c/net/+/550798
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
QUIC packet numbers are truncated to include only the least
significant bits of the packet number. The number of bits
which must be retained is computed based on the largest
packet number known to have been received by the peer.
See RFC 9000, section 17.1.
We were incorrectly using the largest packet number
we have received *from* the peer. Oops.
(Test infrastructure change: Include the header byte
in the testPacket structure, so we can see how many
bytes the packet number was encoded with. Ignore this
byte when comparing packets.)
Change-Id: Iec17c69f007f8b39d14d24b0ca216c6a0018ae22
Reviewed-on: https://go-review.googlesource.com/c/net/+/545575
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
We were failing to hold streamsState.streamsMu when removing
a closed stream from the conn's stream map.
Rework this to remove the mutex entirely.
The only access to the map that isn't on the conn's loop is
during stream creation. Send a message to the loop to
register the stream instead of using a mutex.
Change-Id: I2e87089e87c61a6ade8219dfb8acec3809bf95de
Reviewed-on: https://go-review.googlesource.com/c/net/+/545217
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
A receiver that is sending only non-ack-eliciting packets
(for example, a connection reading data from a stream but not sending
anything other than ACKs in response) can accumulate a large amount
of state for in-flight, unacknowledged packets.
Add an occasional PING frame when in this state, to cause the peer
to send an ACK for our outstanding packets.
Change-Id: Iaf6b5a9735fa356fdebaff24200420a280b0c9a5
Reviewed-on: https://go-review.googlesource.com/c/net/+/545215
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Do not commit data written to a stream to the network until
the user explicitly flushes the stream, the stream output
buffer fills, or the output buffer contains enough data to
fill a packet.
We could write data immediately (as net.TCPConn does),
but this can require the user to put their own buffer in
front of the stream. Since we necessarily need to maintain
a retransmit buffer in the stream, this is redundant.
We could do something like Nagle's algorithm, but nobody
wants that.
So make flushes explicit.
For golang/go#58547
Change-Id: I29dc9d79556c7a358a360ef79beb38b45040b6bc
Reviewed-on: https://go-review.googlesource.com/c/net/+/543083
Auto-Submit: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Negotiate the connection idle timeout based on the sent and received
max_idle_timeout transport parameter values.
Set a configurable limit on how long a handshake can take to complete.
Add a configuration option to send keep-alive PING frames to avoid
connection closure due to the idle timeout.
RFC 9000, Section 10.1.
For golang/go#58547
Change-Id: If6a611090ab836cd6937fcfbb1360a0f07425102
Reviewed-on: https://go-review.googlesource.com/c/net/+/540895
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
After receiving a stateless reset, we must enter the draining
state and send no further packets (including CONNECTION_CLOSE).
We were sending one last CONNECTION_CLOSE after the user
closed the Conn; fix this.
RFC 9000, Section 10.3.1.
Change-Id: I6a9cc6019470a25476df518022a32eefe0c50fcd
Reviewed-on: https://go-review.googlesource.com/c/net/+/540117
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
New server-side conns need to know a variety of connection IDs,
such as the Initial DCID used to create Initial encryption keys.
We've been providing these as an ever-growing list of []byte
parameters to newConn. Bundle them all up into a struct.
Add the client's SCID to the set of IDs we pass to newConn.
Up until now, we've been setting this when processing the
first Initial packet from the client. Passing it to newConn
will makes it available when logging the connection_started event.
Update some test infrastructure to deal with the fact that
we need to know the peer's SCID earlier in the test now.
Change-Id: I760ee94af36125acf21c5bf135f1168830ba1ab8
Reviewed-on: https://go-review.googlesource.com/c/net/+/539341
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
UDP datagrams containing Initial packets are expanded to 1200 bytes
to validate that the path is capable of supporting the smallest
allowed maximum QUIC datagram size.
(In addition, client Initial packets must be sent in datagrams
of at least 1200 bytes, to defend against amplification attacks.)
We were expanding client datagrams containing Initial packets,
but not server datagrams. Fix this. (More specifically, server
datagrams must be expanded to 1200 bytes when they contain
ack-eliciting Initial packets.)
RFC 9000, Section 14.1.
Change-Id: I0c0c36321c055e960be3e29a49d7cb7620640b82
Reviewed-on: https://go-review.googlesource.com/c/net/+/538776
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
When pipe.discardBefore was called with an offset greater
than the current pipe.end position, we would update
pipe.start but not pipe.end, leaving the pipe in an
inconsistent state where start > end. This could then
subsequently cause a panic when writing data that
lies before pipe.start.
This sequence occurs when handling several in-order
CRYPTO frames (where we skip writing in-order data
to the pipe, but still call discardBefore), followed
by an out-of-order frame containing resent data.
Change-Id: Ibac0caad53cd30dac1cd4719a825226809872d96
Reviewed-on: https://go-review.googlesource.com/c/net/+/538775
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>