multiplexer.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. package quic
  2. import (
  3. "bytes"
  4. "fmt"
  5. "net"
  6. "sync"
  7. "github.com/lucas-clemente/quic-go/internal/utils"
  8. )
  9. var (
  10. connMuxerOnce sync.Once
  11. connMuxer multiplexer
  12. )
  13. type multiplexer interface {
  14. AddConn(c net.PacketConn, connIDLen int, statelessResetKey []byte) (packetHandlerManager, error)
  15. RemoveConn(net.PacketConn) error
  16. }
  17. type connManager struct {
  18. connIDLen int
  19. statelessResetKey []byte
  20. manager packetHandlerManager
  21. }
  22. // The connMultiplexer listens on multiple net.PacketConns and dispatches
  23. // incoming packets to the session handler.
  24. type connMultiplexer struct {
  25. mutex sync.Mutex
  26. conns map[net.PacketConn]connManager
  27. newPacketHandlerManager func(net.PacketConn, int, []byte, utils.Logger) packetHandlerManager // so it can be replaced in the tests
  28. logger utils.Logger
  29. }
  30. var _ multiplexer = &connMultiplexer{}
  31. func getMultiplexer() multiplexer {
  32. connMuxerOnce.Do(func() {
  33. connMuxer = &connMultiplexer{
  34. conns: make(map[net.PacketConn]connManager),
  35. logger: utils.DefaultLogger.WithPrefix("muxer"),
  36. newPacketHandlerManager: newPacketHandlerMap,
  37. }
  38. })
  39. return connMuxer
  40. }
  41. func (m *connMultiplexer) AddConn(
  42. c net.PacketConn,
  43. connIDLen int,
  44. statelessResetKey []byte,
  45. ) (packetHandlerManager, error) {
  46. m.mutex.Lock()
  47. defer m.mutex.Unlock()
  48. p, ok := m.conns[c]
  49. if !ok {
  50. manager := m.newPacketHandlerManager(c, connIDLen, statelessResetKey, m.logger)
  51. p = connManager{
  52. connIDLen: connIDLen,
  53. statelessResetKey: statelessResetKey,
  54. manager: manager,
  55. }
  56. m.conns[c] = p
  57. }
  58. if p.connIDLen != connIDLen {
  59. return nil, fmt.Errorf("cannot use %d byte connection IDs on a connection that is already using %d byte connction IDs", connIDLen, p.connIDLen)
  60. }
  61. if statelessResetKey != nil && !bytes.Equal(p.statelessResetKey, statelessResetKey) {
  62. return nil, fmt.Errorf("cannot use different stateless reset keys on the same packet conn")
  63. }
  64. return p.manager, nil
  65. }
  66. func (m *connMultiplexer) RemoveConn(c net.PacketConn) error {
  67. m.mutex.Lock()
  68. defer m.mutex.Unlock()
  69. if _, ok := m.conns[c]; !ok {
  70. return fmt.Errorf("cannote remove connection, connection is unknown")
  71. }
  72. delete(m.conns, c)
  73. return nil
  74. }