mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-12-26 08:35:17 +00:00
113 lines
2.2 KiB
Go
113 lines
2.2 KiB
Go
|
package udpmux
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"errors"
|
||
|
"net"
|
||
|
"time"
|
||
|
|
||
|
pool "github.com/libp2p/go-buffer-pool"
|
||
|
)
|
||
|
|
||
|
type packet struct {
|
||
|
buf []byte
|
||
|
addr net.Addr
|
||
|
}
|
||
|
|
||
|
var _ net.PacketConn = &muxedConnection{}
|
||
|
|
||
|
const queueLen = 128
|
||
|
|
||
|
// muxedConnection provides a net.PacketConn abstraction
|
||
|
// over packetQueue and adds the ability to store addresses
|
||
|
// from which this connection (indexed by ufrag) received
|
||
|
// data.
|
||
|
type muxedConnection struct {
|
||
|
ctx context.Context
|
||
|
cancel context.CancelFunc
|
||
|
onClose func()
|
||
|
queue chan packet
|
||
|
mux *UDPMux
|
||
|
}
|
||
|
|
||
|
var _ net.PacketConn = &muxedConnection{}
|
||
|
|
||
|
func newMuxedConnection(mux *UDPMux, onClose func()) *muxedConnection {
|
||
|
ctx, cancel := context.WithCancel(mux.ctx)
|
||
|
return &muxedConnection{
|
||
|
ctx: ctx,
|
||
|
cancel: cancel,
|
||
|
queue: make(chan packet, queueLen),
|
||
|
onClose: onClose,
|
||
|
mux: mux,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (c *muxedConnection) Push(buf []byte, addr net.Addr) error {
|
||
|
select {
|
||
|
case <-c.ctx.Done():
|
||
|
return errors.New("closed")
|
||
|
default:
|
||
|
}
|
||
|
select {
|
||
|
case c.queue <- packet{buf: buf, addr: addr}:
|
||
|
return nil
|
||
|
default:
|
||
|
return errors.New("queue full")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (c *muxedConnection) ReadFrom(buf []byte) (int, net.Addr, error) {
|
||
|
select {
|
||
|
case p := <-c.queue:
|
||
|
n := copy(buf, p.buf) // This might discard parts of the packet, if p is too short
|
||
|
if n < len(p.buf) {
|
||
|
log.Debugf("short read, had %d, read %d", len(p.buf), n)
|
||
|
}
|
||
|
pool.Put(p.buf)
|
||
|
return n, p.addr, nil
|
||
|
case <-c.ctx.Done():
|
||
|
return 0, nil, c.ctx.Err()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (c *muxedConnection) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||
|
return c.mux.writeTo(p, addr)
|
||
|
}
|
||
|
|
||
|
func (c *muxedConnection) Close() error {
|
||
|
select {
|
||
|
case <-c.ctx.Done():
|
||
|
return nil
|
||
|
default:
|
||
|
}
|
||
|
c.onClose()
|
||
|
c.cancel()
|
||
|
// drain the packet queue
|
||
|
for {
|
||
|
select {
|
||
|
case p := <-c.queue:
|
||
|
pool.Put(p.buf)
|
||
|
default:
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (c *muxedConnection) LocalAddr() net.Addr { return c.mux.socket.LocalAddr() }
|
||
|
|
||
|
func (*muxedConnection) SetDeadline(t time.Time) error {
|
||
|
// no deadline is desired here
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (*muxedConnection) SetReadDeadline(t time.Time) error {
|
||
|
// no read deadline is desired here
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (*muxedConnection) SetWriteDeadline(t time.Time) error {
|
||
|
// no write deadline is desired here
|
||
|
return nil
|
||
|
}
|