mirror of
https://github.com/golang/net.git
synced 2026-03-31 18:37:08 +09:00
quic: add the ability to create an endpoint with a fake network
Add a NewEndpoint function to create an *Endpoint using a net.PacketConn. We rely on a number of features of *net.UDPConn which aren't provided by PacketConn, so an Endpoint using anything other than a UDPConn will be limited. The main use case for providing a non-UDPConn connection is testing, in particular tests which use testing/synctest and cannot use a concrete network connection. Change-Id: I9e62cb8d7d545f64d99103beb9a32f149d4119bf Reviewed-on: https://go-review.googlesource.com/c/net/+/641498 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Jonathan Amsterdam <jba@google.com> Auto-Submit: Damien Neil <dneil@google.com>
This commit is contained in:
committed by
Gopher Robot
parent
97dd44e201
commit
5566b43feb
@@ -73,6 +73,25 @@ func Listen(network, address string, listenConfig *Config) (*Endpoint, error) {
|
||||
return newEndpoint(pc, listenConfig, nil)
|
||||
}
|
||||
|
||||
// NewEndpoint creates an endpoint using a net.PacketConn as the underlying transport.
|
||||
//
|
||||
// If the PacketConn is not a *net.UDPConn, the endpoint may be slower and lack
|
||||
// access to some features of the network.
|
||||
func NewEndpoint(conn net.PacketConn, config *Config) (*Endpoint, error) {
|
||||
var pc packetConn
|
||||
var err error
|
||||
switch conn := conn.(type) {
|
||||
case *net.UDPConn:
|
||||
pc, err = newNetUDPConn(conn)
|
||||
default:
|
||||
pc, err = newNetPacketConn(conn)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newEndpoint(pc, config, nil)
|
||||
}
|
||||
|
||||
func newEndpoint(pc packetConn, config *Config, hooks endpointTestHooks) (*Endpoint, error) {
|
||||
e := &Endpoint{
|
||||
listenConfig: config,
|
||||
|
||||
69
quic/udp_packetconn.go
Normal file
69
quic/udp_packetconn.go
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.21
|
||||
|
||||
package quic
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
)
|
||||
|
||||
// netPacketConn is a packetConn implementation wrapping a net.PacketConn.
|
||||
//
|
||||
// This is mostly useful for tests, since PacketConn doesn't provide access to
|
||||
// important features such as identifying the local address packets were received on.
|
||||
type netPacketConn struct {
|
||||
c net.PacketConn
|
||||
localAddr netip.AddrPort
|
||||
}
|
||||
|
||||
func newNetPacketConn(pc net.PacketConn) (*netPacketConn, error) {
|
||||
addr, err := addrPortFromAddr(pc.LocalAddr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &netPacketConn{
|
||||
c: pc,
|
||||
localAddr: addr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *netPacketConn) Close() error {
|
||||
return c.c.Close()
|
||||
}
|
||||
|
||||
func (c *netPacketConn) LocalAddr() netip.AddrPort {
|
||||
return c.localAddr
|
||||
}
|
||||
|
||||
func (c *netPacketConn) Read(f func(*datagram)) {
|
||||
for {
|
||||
dgram := newDatagram()
|
||||
n, peerAddr, err := c.c.ReadFrom(dgram.b)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
dgram.peerAddr, err = addrPortFromAddr(peerAddr)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
dgram.b = dgram.b[:n]
|
||||
f(dgram)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *netPacketConn) Write(dgram datagram) error {
|
||||
_, err := c.c.WriteTo(dgram.b, net.UDPAddrFromAddrPort(dgram.peerAddr))
|
||||
return err
|
||||
}
|
||||
|
||||
func addrPortFromAddr(addr net.Addr) (netip.AddrPort, error) {
|
||||
switch a := addr.(type) {
|
||||
case *net.UDPAddr:
|
||||
return a.AddrPort(), nil
|
||||
}
|
||||
return netip.ParseAddrPort(addr.String())
|
||||
}
|
||||
Reference in New Issue
Block a user