From 416b10792dd364288154212ea14be1dac9865f19 Mon Sep 17 00:00:00 2001 From: jyyi1 Date: Thu, 10 Aug 2023 16:14:26 -0400 Subject: [PATCH 01/10] doc: incorporate Go reference document changes for Alpha release --- network/delegate_packet_proxy.go | 12 ++++++------ network/device.go | 8 ++++---- network/doc.go | 8 ++++---- network/errors.go | 6 +++--- network/packet_proxy.go | 24 ++++++++++++------------ transport/address.go | 10 +++++----- transport/packet.go | 18 +++++++++--------- transport/stream.go | 19 ++++++++++--------- 8 files changed, 53 insertions(+), 52 deletions(-) diff --git a/network/delegate_packet_proxy.go b/network/delegate_packet_proxy.go index 5574ba56..22940ec4 100644 --- a/network/delegate_packet_proxy.go +++ b/network/delegate_packet_proxy.go @@ -19,14 +19,14 @@ import ( "sync/atomic" ) -// DelegatePacketProxy is a PacketProxy that forwards calls (like NewSession) to another PacketProxy. To create a -// DelegatePacketProxy with the default PacketProxy, use NewDelegatePacketProxy. To change the underlying PacketProxy, -// use SetProxy. +// DelegatePacketProxy is a [PacketProxy] that forwards calls (like NewSession) to another [PacketProxy]. To create a +// DelegatePacketProxy with the default PacketProxy, use [NewDelegatePacketProxy]. To change the underlying +// [PacketProxy], use SetProxy. // -// Note: After changing the underlying PacketProxy, only new NewSession calls will be routed to the new PacketProxy. -// Existing sessions will not be affected. +// Note: After the underlying [PacketProxy] is changed, only new NewSession calls will be routed to the new +// [PacketProxy]. Existing sessions will not be affected. // -// Multiple goroutines may invoke methods on a DelegatePacketProxy simultaneously. +// Multiple goroutines can simultaneously invoke methods on a DelegatePacketProxy. type DelegatePacketProxy interface { PacketProxy diff --git a/network/device.go b/network/device.go index bb51e59b..4596ff48 100644 --- a/network/device.go +++ b/network/device.go @@ -20,14 +20,14 @@ import ( ) var ( - // ErrMsgSize is the error returned by a Write on a network device that the size of the message to be sent is bigger - // than the maximum message size the device can process. + // ErrMsgSize is the error returned by a Write on a network device. It means that the size of the message to be + // sent is bigger than the maximum message size the device can process. ErrMsgSize = fmt.Errorf("packet size is too big: %w", syscall.EMSGSIZE) ) // IPDevice is a generic network device that reads and writes IP packets. It extends the [io.ReadWriteCloser] -// interface. For better memory efficiency, we also recommend implementing the [io.ReaderFrom] and -// [io.WriterTo] interfaces if possible. +// interface. For better memory efficiency, we also recommend that you implement the [io.ReaderFrom] and [io.WriterTo] +// interfaces if possible. // // Some examples of IPDevices are a virtual network adapter or a local IP proxy. type IPDevice interface { diff --git a/network/doc.go b/network/doc.go index 96a91b32..cac1767b 100644 --- a/network/doc.go +++ b/network/doc.go @@ -14,10 +14,10 @@ /* The network package defines interfaces and provides utilities for network layer (OSI layer 3) functionalities. For -example, the [IPDevice] interface can be used to read and write IP packets from a physical or virtual network device. +example, you can use the [IPDevice] interface to read and write IP packets from a physical or virtual network device. -In addition, user-space network stack implementations are also included in the sub-packages (such as -network/lwip2transport) that can translate raw IP packets into TCP/UDP flows. You can implement a [PacketProxy] -to handle UDP traffic, and a [transport.StreamDialer] to handle TCP traffic. +In addition, the sub-packages include user-space network stack implementations (such as network/lwip2transport) that +can translate raw IP packets into TCP/UDP flows. You can implement a [PacketProxy] to handle UDP traffic, and a +[transport.StreamDialer] to handle TCP traffic. */ package network diff --git a/network/errors.go b/network/errors.go index 8b706eec..f5e17edd 100644 --- a/network/errors.go +++ b/network/errors.go @@ -20,14 +20,14 @@ import ( // Portable analogs of some common errors. // -// Errors returned from this package and all sub-packages may be tested against these errors with [errors.Is]. +// Errors returned from this package and all sub-packages can be tested against these errors using [errors.Is]. var ( // ErrClosed is the error returned by an I/O call on a network device or proxy that has already been closed, or that is - // closed by another goroutine before the I/O is completed. This may be wrapped in another error, and should normally + // closed by another goroutine before the I/O is completed. This can be wrapped in another error, and should normally // be tested using errors.Is(err, network.ErrClosed). ErrClosed = errors.New("network device already closed") - // ErrPortUnreachable is an error that indicates a remote server's port cannot be reached. This may be wrapped in + // ErrPortUnreachable is an error that indicates a remote server's port cannot be reached. This can be wrapped in // another error, and should normally be tested using errors.Is(err, network.ErrPortUnreachable). ErrPortUnreachable = errors.New("port is not reachable") ) diff --git a/network/packet_proxy.go b/network/packet_proxy.go index 7de13ea0..57f500f1 100644 --- a/network/packet_proxy.go +++ b/network/packet_proxy.go @@ -22,7 +22,7 @@ import ( // PacketProxy handles UDP traffic from the upstream network stack. The upstream network stack uses the NewSession // function to create a new UDP session that can send or receive UDP packets from PacketProxy. // -// Multiple goroutines may invoke methods on a PacketProxy simultaneously. +// Multiple goroutines can simultaneously invoke methods on a PacketProxy. type PacketProxy interface { // NewSession function tells the PacketProxy that a new UDP socket session has been started (using socket as an // example, a session will be started by calling the bind() function). The PacketProxy then creates a @@ -34,14 +34,14 @@ type PacketProxy interface { } // PacketRequestSender sends UDP request packets to the [PacketProxy]. It should be implemented by the [PacketProxy], -// who must implement the WriteTo method to process the request packets. PacketRequestSender is typically called by an -// upstream component (such as a network stack). Once the Close method is called, there will be no more requests sent -// to the sender, and all resources can be freed. +// which must implement the WriteTo method to process the request packets. PacketRequestSender is typically called by +// an upstream component (such as a network stack). After the Close method is called, there will be no more requests +// sent to the sender, and all resources can be freed. // -// Multiple goroutines may invoke methods on a PacketRequestSender simultaneously. +// Multiple goroutines can simultaneously invoke methods on a PacketRequestSender. type PacketRequestSender interface { // WriteTo sends a UDP request packet to the [PacketProxy]. The packet is destined for the remote server identified - // by `destination`; and the payload of the packet is stored in `p`. If `p` is empty, the request packet will be + // by `destination` and the payload of the packet is stored in `p`. If `p` is empty, the request packet will be // ignored. WriteTo returns the number of bytes written from `p` and any error encountered that caused the function // to stop early. // @@ -53,13 +53,13 @@ type PacketRequestSender interface { Close() error } -// PacketResponseReceiver receives UDP response packets from the [PacketProxy]. It is usually implemented by the -// upstream component (such as a network stack). When creating a new UDP session, a valid instance -// PacketResponseReceiver is passed to the PacketProxy.NewSession function. Then the [PacketProxy] must use this -// instance to send UDP responses all the time; and it must call the Close function to indicate there will be no more -// responses send to this receiver. +// PacketResponseReceiver receives UDP response packets from the [PacketProxy]. It is usually implemented by an +// upstream component (such as a network stack). When a new UDP session is created, a valid instance of +// PacketResponseReceiver is passed to the PacketProxy.NewSession function. The [PacketProxy] must then use this +// instance to send UDP responses. It must then call the Close function to indicate that there will be no more +// responses sent to this receiver. // -// Multiple goroutines may invoke methods on a PacketResponseReceiver simultaneously. +// Multiple goroutines can simultaneously invoke methods on a PacketResponseReceiver. type PacketResponseReceiver interface { // WriteFrom is a callback function that is called by a PacketProxy when a UDP response packet is received. The // `source` identifies the remote server that sent the packet; and the `p` contains the packet payload. WriteFrom diff --git a/transport/address.go b/transport/address.go index 844a495c..97d1f5be 100644 --- a/transport/address.go +++ b/transport/address.go @@ -35,12 +35,12 @@ func (a *domainAddr) String() string { var _ net.Addr = (*domainAddr)(nil) // MakeNetAddr returns a [net.Addr] based on the network and address. -// This is a helper for code that need to return or provide a net.Addr -// The address must be in host:port format, with the host being a domain name, IPv4 or IPv6. -// Network must be "tcp" or "udp". +// This is a helper for code that needs to return or provide a [net.Addr]. +// The address must be in "host:port" format with the host being a domain name, IPv4 or IPv6. +// The network must be "tcp" or "udp". // For IP hosts, the returned address will be of type [*net.TCPAddr] or [*net.UDPAddr], based on the network argument. -// This is important because some of the standard library functions inspect the type of the address and may return an -// "invalid argument" error if the type is not the right one. +// This is important because some of the standard library functions inspect the type of the address and might return an +// "invalid argument" error if the type is not the correct one. func MakeNetAddr(network, address string) (net.Addr, error) { host, port, err := net.SplitHostPort(address) if err != nil { diff --git a/transport/packet.go b/transport/packet.go index d612f970..087b6dbc 100644 --- a/transport/packet.go +++ b/transport/packet.go @@ -26,11 +26,11 @@ type PacketEndpoint interface { Connect(ctx context.Context) (net.Conn, error) } -// UDPEndpoint is a [PacketEndpoint] that connects to the given address via UDP +// UDPEndpoint is a [PacketEndpoint] that connects to the specified address using UDP type UDPEndpoint struct { // The Dialer used to create the net.Conn on Connect(). Dialer net.Dialer - // The endpoint address (host:port) to pass to Dial. + // The endpoint address ("host:port") to pass to Dial. // If the host is a domain name, consider pre-resolving it to avoid resolution calls. Address string } @@ -42,7 +42,7 @@ func (e UDPEndpoint) Connect(ctx context.Context) (net.Conn, error) { return e.Dialer.DialContext(ctx, "udp", e.Address) } -// PacketDialerEndpoint is a [PacketEndpoint] that connects to the given address using the given [PacketDialer]. +// PacketDialerEndpoint is a [PacketEndpoint] that connects to the given address using the specified [PacketDialer]. type PacketDialerEndpoint struct { Dialer PacketDialer Address string @@ -57,8 +57,8 @@ func (e *PacketDialerEndpoint) Connect(ctx context.Context) (net.Conn, error) { // PacketDialer provides a way to dial a destination and establish datagram connections. type PacketDialer interface { - // Dial connects to `raddr`. - // `raddr` has the form `host:port`, where `host` can be a domain name or IP address. + // Dial connects to `addr`. + // `addr` has the form "host:port", where "host" can be a domain name or IP address. Dial(ctx context.Context, addr string) (net.Conn, error) } @@ -91,9 +91,9 @@ type boundPacketConn struct { var _ net.Conn = (*boundPacketConn)(nil) // Dial implements [PacketDialer].Dial. -// The address is a host:port and the host must be a full IP address (not [::]) or a domain -// The address must be supported by the WriteTo call of the PacketConn -// returned by the PacketListener. For instance, a [net.UDPConn] only supports IP addresses, not domain names. +// The address is in "host:port" format and the host must be either a full IP address (not "[::]") or a domain. +// The address must be supported by the WriteTo call of the [net.PacketConn] returned by the [PacketListener]. +// For example, a [net.UDPConn] only supports IP addresses, not domain names. // If the host is a domain name, consider pre-resolving it to avoid resolution calls. func (e PacketListenerDialer) Dial(ctx context.Context, address string) (net.Conn, error) { packetConn, err := e.Listener.ListenPacket(ctx) @@ -138,7 +138,7 @@ func (c *boundPacketConn) RemoteAddr() net.Addr { // PacketListener provides a way to create a local unbound packet connection to send packets to different destinations. type PacketListener interface { - // ListenPacket creates a PacketConn that can be used to relay packets (such as UDP) through some proxy. + // ListenPacket creates a PacketConn that can be used to relay packets (such as UDP) through a proxy. ListenPacket(ctx context.Context) (net.PacketConn, error) } diff --git a/transport/stream.go b/transport/stream.go index 6b5a4c9f..5d279308 100644 --- a/transport/stream.go +++ b/transport/stream.go @@ -20,14 +20,13 @@ import ( "net" ) -// StreamConn is a net.Conn that allows for closing only the reader or writer end of -// it, supporting half-open state. +// StreamConn is a [net.Conn] that allows for closing only the reader or writer end of it, supporting half-open state. type StreamConn interface { net.Conn // Closes the Read end of the connection, allowing for the release of resources. // No more reads should happen. CloseRead() error - // Closes the Write end of the connection. An EOF or FIN signal may be + // Closes the Write end of the connection. An EOF or FIN signal can be // sent to the connection target. CloseWrite() error } @@ -59,8 +58,8 @@ func (dc *duplexConnAdaptor) CloseWrite() error { return dc.StreamConn.CloseWrite() } -// WrapDuplexConn wraps an existing [StreamConn] with new Reader and Writer, but -// preserving the original [StreamConn.CloseRead] and [StreamConn.CloseWrite]. +// WrapConn wraps an existing [StreamConn] with a new [io.Reader] and [io.Writer], but preserves the original +// [StreamConn].CloseRead and [StreamConn].CloseWrite. func WrapConn(c StreamConn, r io.Reader, w io.Writer) StreamConn { conn := c // We special-case duplexConnAdaptor to avoid multiple levels of nesting. @@ -70,13 +69,14 @@ func WrapConn(c StreamConn, r io.Reader, w io.Writer) StreamConn { return &duplexConnAdaptor{StreamConn: conn, r: r, w: w} } -// StreamEndpoint represents an endpoint that can be used to established stream connections (like TCP) to a fixed destination. +// StreamEndpoint represents an endpoint that can be used to establish stream connections (like TCP) to a fixed +// destination. type StreamEndpoint interface { // Connect establishes a connection with the endpoint, returning the connection. Connect(ctx context.Context) (StreamConn, error) } -// TCPEndpoint is a [StreamEndpoint] that connects to the given address using the given [StreamDialer]. +// TCPEndpoint is a [StreamEndpoint] that connects to the specified address using the specified [StreamDialer]. type TCPEndpoint struct { // The Dialer used to create the net.Conn on Connect(). Dialer net.Dialer @@ -96,7 +96,8 @@ func (e *TCPEndpoint) Connect(ctx context.Context) (StreamConn, error) { return conn.(*net.TCPConn), nil } -// StreamDialerEndpoint is a [StreamEndpoint] that connects to the given address using the given [StreamDialer]. +// StreamDialerEndpoint is a [StreamEndpoint] that connects to the specified address using the specified +// [StreamDialer]. type StreamDialerEndpoint struct { Dialer StreamDialer Address string @@ -112,7 +113,7 @@ func (e *StreamDialerEndpoint) Connect(ctx context.Context) (StreamConn, error) // StreamDialer provides a way to dial a destination and establish stream connections. type StreamDialer interface { // Dial connects to `raddr`. - // `raddr` has the form `host:port`, where `host` can be a domain name or IP address. + // `raddr` has the form "host:port", where "host" can be a domain name or IP address. Dial(ctx context.Context, raddr string) (StreamConn, error) } From a2fe53cfa64dc4cbac59dfb42c1f034993f23a48 Mon Sep 17 00:00:00 2001 From: jyyi1 Date: Fri, 11 Aug 2023 16:29:05 -0400 Subject: [PATCH 02/10] code review (round 1) --- network/delegate_packet_proxy.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/network/delegate_packet_proxy.go b/network/delegate_packet_proxy.go index 22940ec4..c9c60751 100644 --- a/network/delegate_packet_proxy.go +++ b/network/delegate_packet_proxy.go @@ -19,9 +19,10 @@ import ( "sync/atomic" ) -// DelegatePacketProxy is a [PacketProxy] that forwards calls (like NewSession) to another [PacketProxy]. To create a -// DelegatePacketProxy with the default PacketProxy, use [NewDelegatePacketProxy]. To change the underlying -// [PacketProxy], use SetProxy. +// DelegatePacketProxy is a [PacketProxy] that forwards calls (like NewSession) to another [PacketProxy], +// so that the caller can replace the underlying [PacketProxy] without changing the original reference. +// To create a DelegatePacketProxy with the default PacketProxy, use [NewDelegatePacketProxy]. To change +// the underlying [PacketProxy], use SetProxy. // // Note: After the underlying [PacketProxy] is changed, only new NewSession calls will be routed to the new // [PacketProxy]. Existing sessions will not be affected. From ef1f28f1313eb55c7a965de428c8042de89be47e Mon Sep 17 00:00:00 2001 From: "J. Yi" <93548144+jyyi1@users.noreply.github.com> Date: Tue, 15 Aug 2023 18:53:22 -0400 Subject: [PATCH 03/10] Update network/doc.go --- network/doc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/doc.go b/network/doc.go index cac1767b..2891b769 100644 --- a/network/doc.go +++ b/network/doc.go @@ -16,7 +16,7 @@ The network package defines interfaces and provides utilities for network layer (OSI layer 3) functionalities. For example, you can use the [IPDevice] interface to read and write IP packets from a physical or virtual network device. -In addition, the sub-packages include user-space network stack implementations (such as network/lwip2transport) that +In addition, the sub-packages include user-space network stack implementations (such as [network/lwip2transport]) that can translate raw IP packets into TCP/UDP flows. You can implement a [PacketProxy] to handle UDP traffic, and a [transport.StreamDialer] to handle TCP traffic. */ From a1c2834e1776fc0d0cbd3093d0b2b1851b7524a4 Mon Sep 17 00:00:00 2001 From: "J. Yi" <93548144+jyyi1@users.noreply.github.com> Date: Tue, 15 Aug 2023 18:53:38 -0400 Subject: [PATCH 04/10] Update transport/packet.go --- transport/packet.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport/packet.go b/transport/packet.go index 087b6dbc..be942cd3 100644 --- a/transport/packet.go +++ b/transport/packet.go @@ -26,7 +26,7 @@ type PacketEndpoint interface { Connect(ctx context.Context) (net.Conn, error) } -// UDPEndpoint is a [PacketEndpoint] that connects to the specified address using UDP +// UDPEndpoint is a [PacketEndpoint] that connects to the specified address using UDP. type UDPEndpoint struct { // The Dialer used to create the net.Conn on Connect(). Dialer net.Dialer From d232cf91d35f319019d7debe492ab603a8c3b5df Mon Sep 17 00:00:00 2001 From: "J. Yi" <93548144+jyyi1@users.noreply.github.com> Date: Wed, 16 Aug 2023 18:04:39 -0400 Subject: [PATCH 05/10] Update delegate_packet_proxy.go --- network/delegate_packet_proxy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/delegate_packet_proxy.go b/network/delegate_packet_proxy.go index c9c60751..48c5d38e 100644 --- a/network/delegate_packet_proxy.go +++ b/network/delegate_packet_proxy.go @@ -31,7 +31,7 @@ import ( type DelegatePacketProxy interface { PacketProxy - // SetProxy updates the underlying PacketProxy to `proxy`. And `proxy` must not be nil. After this function + // SetProxy updates the underlying PacketProxy to `proxy`; `proxy` must not be nil. After this function // returns, all new PacketProxy calls will be forwarded to the `proxy`. Existing sessions will not be affected. SetProxy(proxy PacketProxy) error } From 9a2babfc4338d919763be2542384398c250f0883 Mon Sep 17 00:00:00 2001 From: "J. Yi" <93548144+jyyi1@users.noreply.github.com> Date: Wed, 16 Aug 2023 18:06:25 -0400 Subject: [PATCH 06/10] Update packet_proxy.go --- network/packet_proxy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/packet_proxy.go b/network/packet_proxy.go index 57f500f1..ab2ee37a 100644 --- a/network/packet_proxy.go +++ b/network/packet_proxy.go @@ -29,7 +29,7 @@ type PacketProxy interface { // PacketRequestSender object to handle requests from this session, and it also uses the PacketResponseReceiver // to send responses back to the upstream network stack. // - // Note that, it is possible for a session to receive UDP packets without sending any requests. + // Note that it is possible for a session to receive UDP packets without sending any requests. NewSession(PacketResponseReceiver) (PacketRequestSender, error) } From 731a5940a55eecd183896dde7291b12c4a26b749 Mon Sep 17 00:00:00 2001 From: "J. Yi" <93548144+jyyi1@users.noreply.github.com> Date: Wed, 16 Aug 2023 18:08:20 -0400 Subject: [PATCH 07/10] Update packet_proxy.go --- network/packet_proxy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/packet_proxy.go b/network/packet_proxy.go index ab2ee37a..52766b6d 100644 --- a/network/packet_proxy.go +++ b/network/packet_proxy.go @@ -40,7 +40,7 @@ type PacketProxy interface { // // Multiple goroutines can simultaneously invoke methods on a PacketRequestSender. type PacketRequestSender interface { - // WriteTo sends a UDP request packet to the [PacketProxy]. The packet is destined for the remote server identified + // WriteTo sends a UDP request packet to the PacketProxy. The packet is destined for the remote server identified // by `destination` and the payload of the packet is stored in `p`. If `p` is empty, the request packet will be // ignored. WriteTo returns the number of bytes written from `p` and any error encountered that caused the function // to stop early. From eace34631c95c6b283bf090daca22fb51a7a065b Mon Sep 17 00:00:00 2001 From: "J. Yi" <93548144+jyyi1@users.noreply.github.com> Date: Wed, 16 Aug 2023 18:09:54 -0400 Subject: [PATCH 08/10] Update packet_proxy.go --- network/packet_proxy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/packet_proxy.go b/network/packet_proxy.go index 52766b6d..a9a69df4 100644 --- a/network/packet_proxy.go +++ b/network/packet_proxy.go @@ -62,7 +62,7 @@ type PacketRequestSender interface { // Multiple goroutines can simultaneously invoke methods on a PacketResponseReceiver. type PacketResponseReceiver interface { // WriteFrom is a callback function that is called by a PacketProxy when a UDP response packet is received. The - // `source` identifies the remote server that sent the packet; and the `p` contains the packet payload. WriteFrom + // `source` identifies the remote server that sent the packet and the `p` contains the packet payload. WriteFrom // returns the number of bytes written from `p` and any error encountered that caused the function to stop early. // // `p` must not be modified, and it must not be referenced after WriteFrom returns. From 3f978ba9a4094a4a750d10ad91f1711134dc7b00 Mon Sep 17 00:00:00 2001 From: "J. Yi" <93548144+jyyi1@users.noreply.github.com> Date: Wed, 16 Aug 2023 18:13:37 -0400 Subject: [PATCH 09/10] Update packet.go --- transport/packet.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport/packet.go b/transport/packet.go index be942cd3..c7862ae2 100644 --- a/transport/packet.go +++ b/transport/packet.go @@ -20,7 +20,7 @@ import ( "net" ) -// PacketEndpoint represents an endpoint that can be used to established packet connections (like UDP) to a fixed destination. +// PacketEndpoint represents an endpoint that can be used to establish packet connections (like UDP) to a fixed destination. type PacketEndpoint interface { // Connect creates a connection bound to an endpoint, returning the connection. Connect(ctx context.Context) (net.Conn, error) From ccd9d06d80aae6ce7a53da4a16fc55b5ff1dc36c Mon Sep 17 00:00:00 2001 From: "J. Yi" <93548144+jyyi1@users.noreply.github.com> Date: Wed, 16 Aug 2023 18:14:52 -0400 Subject: [PATCH 10/10] Update packet.go --- transport/packet.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport/packet.go b/transport/packet.go index c7862ae2..cbdc4dca 100644 --- a/transport/packet.go +++ b/transport/packet.go @@ -75,7 +75,7 @@ func (d *UDPPacketDialer) Dial(ctx context.Context, addr string) (net.Conn, erro return d.Dialer.DialContext(ctx, "udp", addr) } -// PacketListenerDialer is a [PacketDialer] that connects to the destination using the given [PacketListener]. +// PacketListenerDialer is a [PacketDialer] that connects to the destination using the specified [PacketListener]. type PacketListenerDialer struct { // The PacketListener that is used to create the net.PacketConn to bind on Dial. Must be non nil. Listener PacketListener