// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>// SPDX-License-Identifier: MITpackage vnetimport ()const ( maxReadQueueSize = 1024)var ( errObsCannotBeNil = errors.New("obs cannot be nil") errUseClosedNetworkConn = errors.New("use of closed network connection") errAddrNotUDPAddr = errors.New("addr is not a net.UDPAddr") errLocAddr = errors.New("something went wrong with locAddr") errAlreadyClosed = errors.New("already closed") errNoRemAddr = errors.New("no remAddr defined"))// vNet implements thistype connObserver interface { write(c Chunk) error onClosed(addr net.Addr) determineSourceIP(locIP, dstIP net.IP) net.IP}// UDPConn is the implementation of the Conn and PacketConn interfaces for UDP network connections.// compatible with net.PacketConn and net.ConntypeUDPConnstruct { locAddr *net.UDPAddr// read-only remAddr *net.UDPAddr// read-only obs connObserver// read-only readCh chanChunk// thread-safe closed bool// requires mutex mu sync.Mutex// to mutex closed flag readTimer *time.Timer// thread-safe}var _ transport.UDPConn = &UDPConn{}func newUDPConn(, *net.UDPAddr, connObserver) (*UDPConn, error) {if == nil {returnnil, errObsCannotBeNil }return &UDPConn{locAddr: ,remAddr: ,obs: ,readCh: make(chanChunk, maxReadQueueSize),readTimer: time.NewTimer(time.Duration(math.MaxInt64)), }, nil}// Close closes the connection.// Any blocked ReadFrom or WriteTo operations will be unblocked and return errors.func ( *UDPConn) () error { .mu.Lock()defer .mu.Unlock()if .closed {returnerrAlreadyClosed } .closed = trueclose(.readCh) .obs.onClosed(.locAddr)returnnil}// LocalAddr returns the local network address.func ( *UDPConn) () net.Addr {return .locAddr}// RemoteAddr returns the remote network address.func ( *UDPConn) () net.Addr {return .remAddr}// SetDeadline sets the read and write deadlines associated// with the connection. It is equivalent to calling both// SetReadDeadline and SetWriteDeadline.//// A deadline is an absolute time after which I/O operations// fail with a timeout (see type Error) instead of// blocking. The deadline applies to all future and pending// I/O, not just the immediately following call to ReadFrom or// WriteTo. After a deadline has been exceeded, the connection// can be refreshed by setting a deadline in the future.//// An idle timeout can be implemented by repeatedly extending// the deadline after successful ReadFrom or WriteTo calls.//// A zero value for t means I/O operations will not time out.func ( *UDPConn) ( time.Time) error {return .SetReadDeadline()}// SetReadDeadline sets the deadline for future ReadFrom calls// and any currently-blocked ReadFrom call.// A zero value for t means ReadFrom will not time out.func ( *UDPConn) ( time.Time) error {vartime.Durationvartime.Timeif == { = time.Duration(math.MaxInt64) } else { = time.Until() } .readTimer.Reset()returnnil}// SetWriteDeadline sets the deadline for future WriteTo calls// and any currently-blocked WriteTo call.// Even if write times out, it may return n > 0, indicating that// some of the data was successfully written.// A zero value for t means WriteTo will not time out.func ( *UDPConn) (time.Time) error {// Write never blocks.returnnil}// Read reads data from the connection.// Read can be made to time out and return an Error with Timeout() == true// after a fixed time limit; see SetDeadline and SetReadDeadline.func ( *UDPConn) ( []byte) (int, error) { , , := .ReadFrom()return , }// ReadFrom reads a packet from the connection,// copying the payload into p. It returns the number of// bytes copied into p and the return address that// was on the packet.// It returns the number of bytes read (0 <= n <= len(p))// and any error encountered. Callers should always process// the n > 0 bytes returned before considering the error err.// ReadFrom can be made to time out and return// an Error with Timeout() == true after a fixed time limit;// see SetDeadline and SetReadDeadline.func ( *UDPConn) ( []byte) ( int, net.Addr, error) {:for {select {case , := <-.readCh:if ! {break }varerror := copy(, .UserData()) := .SourceAddr()if < len(.UserData()) { = io.ErrShortBuffer }if .remAddr != nil {if .String() != .remAddr.String() {break// discard (shouldn't happen) } }return , , case<-.readTimer.C:return0, nil, &net.OpError{Op: "read",Net: .locAddr.Network(),Addr: .locAddr,Err: newTimeoutError("i/o timeout"), } } }return0, nil, &net.OpError{Op: "read",Net: .locAddr.Network(),Addr: .locAddr,Err: errUseClosedNetworkConn, }}// ReadFromUDP acts like ReadFrom but returns a UDPAddr.func ( *UDPConn) ( []byte) (int, *net.UDPAddr, error) { , , := .ReadFrom() , := .(*net.UDPAddr)if ! {return -1, nil, fmt.Errorf("%w: %s", transport.ErrNotUDPAddress, ) }return , , }// ReadMsgUDP reads a message from c, copying the payload into b and// the associated out-of-band data into oob. It returns the number of// bytes copied into b, the number of bytes copied into oob, the flags// that were set on the message and the source address of the message.//// The packages golang.org/x/net/ipv4 and golang.org/x/net/ipv6 can be// used to manipulate IP-level socket options in oob.func ( *UDPConn) ([]byte, []byte) (, , int, *net.UDPAddr, error) {return -1, -1, -1, nil, transport.ErrNotSupported}// Write writes data to the connection.// Write can be made to time out and return an Error with Timeout() == true// after a fixed time limit; see SetDeadline and SetWriteDeadline.func ( *UDPConn) ( []byte) (int, error) {if .remAddr == nil {return0, errNoRemAddr }return .WriteTo(, .remAddr)}// WriteTo writes a packet with payload p to addr.// WriteTo can be made to time out and return// an Error with Timeout() == true after a fixed time limit;// see SetDeadline and SetWriteDeadline.// On packet-oriented connections, write timeouts are rare.func ( *UDPConn) ( []byte, net.Addr) ( int, error) { , := .(*net.UDPAddr)if ! {return0, errAddrNotUDPAddr } := .obs.determineSourceIP(.locAddr.IP, .IP)if == nil {return0, errLocAddr } := &net.UDPAddr{IP: ,Port: .locAddr.Port, } := newChunkUDP(, ) .userData = make([]byte, len())copy(.userData, )if := .obs.write(); != nil {return0, }returnlen(), nil}// WriteToUDP acts like WriteTo but takes a UDPAddr.func ( *UDPConn) ( []byte, *net.UDPAddr) (int, error) {return .WriteTo(, )}// WriteMsgUDP writes a message to addr via c if c isn't connected, or// to c's remote address if c is connected (in which case addr must be// nil). The payload is copied from b and the associated out-of-band// data is copied from oob. It returns the number of payload and// out-of-band bytes written.//// The packages golang.org/x/net/ipv4 and golang.org/x/net/ipv6 can be// used to manipulate IP-level socket options in oob.func ( *UDPConn) ([]byte, []byte, *net.UDPAddr) (, int, error) {return -1, -1, transport.ErrNotSupported}// SetReadBuffer sets the size of the operating system's// receive buffer associated with the connection.func ( *UDPConn) (int) error {returntransport.ErrNotSupported}// SetWriteBuffer sets the size of the operating system's// transmit buffer associated with the connection.func ( *UDPConn) (int) error {returntransport.ErrNotSupported}func ( *UDPConn) ( Chunk) { .mu.Lock()defer .mu.Unlock()if .closed {return }select {case .readCh<- :default: }}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.