@ -687,6 +687,7 @@ func (m *Machine) ListenPacket(ctx context.Context, network, address string) (ne
m : m ,
m : m ,
fam : fam ,
fam : fam ,
ipp : ipp ,
ipp : ipp ,
closedCh : make ( chan struct { } ) ,
in : make ( chan * Packet , 100 ) , // arbitrary
in : make ( chan * Packet , 100 ) , // arbitrary
}
}
switch c . fam {
switch c . fam {
@ -716,50 +717,14 @@ type conn struct {
fam uint8 // 0, 4, or 6
fam uint8 // 0, 4, or 6
ipp netip . AddrPort
ipp netip . AddrPort
mu sync . Mutex
closeOnce sync . Once
closed bool
closedCh chan struct { } // closed by Close
readDeadline time . Time
activeReads map [ * activeRead ] bool
in chan * Packet
}
type activeRead struct {
cancel context . CancelFunc
}
// canRead reports whether we can do a read.
func ( c * conn ) canRead ( ) error {
c . mu . Lock ( )
defer c . mu . Unlock ( )
if c . closed {
return net . ErrClosed
}
if ! c . readDeadline . IsZero ( ) && c . readDeadline . Before ( time . Now ( ) ) {
return errors . New ( "read deadline exceeded" )
}
return nil
}
func ( c * conn ) registerActiveRead ( ar * activeRead , active bool ) {
in chan * Packet
c . mu . Lock ( )
defer c . mu . Unlock ( )
if c . activeReads == nil {
c . activeReads = make ( map [ * activeRead ] bool )
}
if active {
c . activeReads [ ar ] = true
} else {
delete ( c . activeReads , ar )
}
}
}
func ( c * conn ) Close ( ) error {
func ( c * conn ) Close ( ) error {
c . mu . Lock ( )
c . closeOnce . Do ( func ( ) {
defer c . mu . Unlock ( )
if c . closed {
return nil
}
c . closed = true
switch c . fam {
switch c . fam {
case 0 :
case 0 :
c . m . unregisterConn4 ( c )
c . m . unregisterConn4 ( c )
@ -769,17 +734,11 @@ func (c *conn) Close() error {
case 6 :
case 6 :
c . m . unregisterConn6 ( c )
c . m . unregisterConn6 ( c )
}
}
c . breakActiveReadsLocked ( )
close ( c . closedCh )
} )
return nil
return nil
}
}
func ( c * conn ) breakActiveReadsLocked ( ) {
for ar := range c . activeReads {
ar . cancel ( )
}
c . activeReads = nil
}
func ( c * conn ) LocalAddr ( ) net . Addr {
func ( c * conn ) LocalAddr ( ) net . Addr {
return & net . UDPAddr {
return & net . UDPAddr {
IP : c . ipp . Addr ( ) . AsSlice ( ) ,
IP : c . ipp . Addr ( ) . AsSlice ( ) ,
@ -809,25 +768,13 @@ func (c *conn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
}
}
func ( c * conn ) ReadFromUDPAddrPort ( p [ ] byte ) ( n int , addr netip . AddrPort , err error ) {
func ( c * conn ) ReadFromUDPAddrPort ( p [ ] byte ) ( n int , addr netip . AddrPort , err error ) {
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
ar := & activeRead { cancel : cancel }
if err := c . canRead ( ) ; err != nil {
return 0 , netip . AddrPort { } , err
}
c . registerActiveRead ( ar , true )
defer c . registerActiveRead ( ar , false )
select {
select {
case <- c . closedCh :
return 0 , netip . AddrPort { } , net . ErrClosed
case pkt := <- c . in :
case pkt := <- c . in :
n = copy ( p , pkt . Payload )
n = copy ( p , pkt . Payload )
pkt . Trace ( "PacketConn.ReadFrom" )
pkt . Trace ( "PacketConn.ReadFrom" )
return n , pkt . Src , nil
return n , pkt . Src , nil
case <- ctx . Done ( ) :
return 0 , netip . AddrPort { } , context . DeadlineExceeded
}
}
}
}
@ -857,18 +804,5 @@ func (c *conn) SetWriteDeadline(t time.Time) error {
panic ( "SetWriteDeadline unsupported; TODO when needed" )
panic ( "SetWriteDeadline unsupported; TODO when needed" )
}
}
func ( c * conn ) SetReadDeadline ( t time . Time ) error {
func ( c * conn ) SetReadDeadline ( t time . Time ) error {
c . mu . Lock ( )
panic ( "SetReadDeadline unsupported; TODO when needed" )
defer c . mu . Unlock ( )
now := time . Now ( )
if t . After ( now ) {
panic ( "SetReadDeadline in the future not yet supported; TODO?" )
}
if ! t . IsZero ( ) && t . Before ( now ) {
c . breakActiveReadsLocked ( )
}
c . readDeadline = t
return nil
}
}