github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/quic/gquic-go/multiplexer.go (about) 1 package gquic 2 3 import ( 4 "fmt" 5 "net" 6 "sync" 7 8 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/utils" 9 ) 10 11 var ( 12 connMuxerOnce sync.Once 13 connMuxer multiplexer 14 ) 15 16 type multiplexer interface { 17 AddConn(net.PacketConn, int) (packetHandlerManager, error) 18 } 19 20 type connManager struct { 21 connIDLen int 22 manager packetHandlerManager 23 } 24 25 // The connMultiplexer listens on multiple net.PacketConns and dispatches 26 // incoming packets to the session handler. 27 type connMultiplexer struct { 28 mutex sync.Mutex 29 30 conns map[net.PacketConn]connManager 31 newPacketHandlerManager func(net.PacketConn, int, utils.Logger) packetHandlerManager // so it can be replaced in the tests 32 33 logger utils.Logger 34 } 35 36 var _ multiplexer = &connMultiplexer{} 37 38 func getMultiplexer() multiplexer { 39 connMuxerOnce.Do(func() { 40 connMuxer = &connMultiplexer{ 41 conns: make(map[net.PacketConn]connManager), 42 logger: utils.DefaultLogger.WithPrefix("muxer"), 43 newPacketHandlerManager: newPacketHandlerMap, 44 } 45 }) 46 return connMuxer 47 } 48 49 func (m *connMultiplexer) AddConn(c net.PacketConn, connIDLen int) (packetHandlerManager, error) { 50 m.mutex.Lock() 51 defer m.mutex.Unlock() 52 53 p, ok := m.conns[c] 54 if !ok { 55 manager := m.newPacketHandlerManager(c, connIDLen, m.logger) 56 p = connManager{connIDLen: connIDLen, manager: manager} 57 m.conns[c] = p 58 } 59 if p.connIDLen != connIDLen { 60 return nil, fmt.Errorf("cannot use %d byte connection IDs on a connection that is already using %d byte connction IDs", connIDLen, p.connIDLen) 61 } 62 return p.manager, nil 63 }