github.com/sagernet/quic-go@v0.43.1-beta.1/ech/multiplexer.go (about) 1 package quic 2 3 import ( 4 "fmt" 5 "net" 6 "sync" 7 8 "github.com/sagernet/quic-go/internal/utils" 9 ) 10 11 var ( 12 connMuxerOnce sync.Once 13 connMuxer multiplexer 14 ) 15 16 type indexableConn interface{ LocalAddr() net.Addr } 17 18 type multiplexer interface { 19 AddConn(conn indexableConn) 20 RemoveConn(indexableConn) error 21 } 22 23 // The connMultiplexer listens on multiple net.PacketConns and dispatches 24 // incoming packets to the connection handler. 25 type connMultiplexer struct { 26 mutex sync.Mutex 27 28 conns map[string] /* LocalAddr().String() */ indexableConn 29 logger utils.Logger 30 } 31 32 var _ multiplexer = &connMultiplexer{} 33 34 func getMultiplexer() multiplexer { 35 connMuxerOnce.Do(func() { 36 connMuxer = &connMultiplexer{ 37 conns: make(map[string]indexableConn), 38 logger: utils.DefaultLogger.WithPrefix("muxer"), 39 } 40 }) 41 return connMuxer 42 } 43 44 func (m *connMultiplexer) index(addr net.Addr) string { 45 return addr.Network() + " " + addr.String() 46 } 47 48 func (m *connMultiplexer) AddConn(c indexableConn) { 49 m.mutex.Lock() 50 defer m.mutex.Unlock() 51 52 connIndex := m.index(c.LocalAddr()) 53 p, ok := m.conns[connIndex] 54 if ok { 55 // Panics if we're already listening on this connection. 56 // This is a safeguard because we're introducing a breaking API change, see 57 // https://github.com/sagernet/quic-go/issues/3727 for details. 58 // We'll remove this at a later time, when most users of the library have made the switch. 59 panic("connection already exists") // TODO: write a nice message 60 } 61 m.conns[connIndex] = p 62 } 63 64 func (m *connMultiplexer) RemoveConn(c indexableConn) error { 65 m.mutex.Lock() 66 defer m.mutex.Unlock() 67 68 connIndex := m.index(c.LocalAddr()) 69 if _, ok := m.conns[connIndex]; !ok { 70 return fmt.Errorf("cannote remove connection, connection is unknown") 71 } 72 73 delete(m.conns, connIndex) 74 return nil 75 }