tcp_mux_test.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package ice
  4. import (
  5. "io"
  6. "net"
  7. "testing"
  8. "github.com/pion/logging"
  9. "github.com/pion/stun"
  10. "github.com/pion/transport/v2/test"
  11. "github.com/stretchr/testify/assert"
  12. "github.com/stretchr/testify/require"
  13. )
  14. var _ TCPMux = &TCPMuxDefault{}
  15. func TestTCPMux_Recv(t *testing.T) {
  16. for name, bufSize := range map[string]int{
  17. "no buffer": 0,
  18. "buffered 4MB": 4 * 1024 * 1024,
  19. } {
  20. bufSize := bufSize
  21. t.Run(name, func(t *testing.T) {
  22. report := test.CheckRoutines(t)
  23. defer report()
  24. loggerFactory := logging.NewDefaultLoggerFactory()
  25. listener, err := net.ListenTCP("tcp", &net.TCPAddr{
  26. IP: net.IP{127, 0, 0, 1},
  27. Port: 0,
  28. })
  29. require.NoError(t, err, "error starting listener")
  30. defer func() {
  31. _ = listener.Close()
  32. }()
  33. tcpMux := NewTCPMuxDefault(TCPMuxParams{
  34. Listener: listener,
  35. Logger: loggerFactory.NewLogger("ice"),
  36. ReadBufferSize: 20,
  37. WriteBufferSize: bufSize,
  38. })
  39. defer func() {
  40. _ = tcpMux.Close()
  41. }()
  42. require.NotNil(t, tcpMux.LocalAddr(), "tcpMux.LocalAddr() is nil")
  43. conn, err := net.DialTCP("tcp", nil, tcpMux.LocalAddr().(*net.TCPAddr))
  44. require.NoError(t, err, "error dialing test TCP connection")
  45. msg := stun.New()
  46. msg.Type = stun.MessageType{Method: stun.MethodBinding, Class: stun.ClassRequest}
  47. msg.Add(stun.AttrUsername, []byte("myufrag:otherufrag"))
  48. msg.Encode()
  49. n, err := writeStreamingPacket(conn, msg.Raw)
  50. require.NoError(t, err, "error writing TCP STUN packet")
  51. pktConn, err := tcpMux.GetConnByUfrag("myufrag", false, listener.Addr().(*net.TCPAddr).IP)
  52. require.NoError(t, err, "error retrieving muxed connection for ufrag")
  53. defer func() {
  54. _ = pktConn.Close()
  55. }()
  56. recv := make([]byte, n)
  57. n2, rAddr, err := pktConn.ReadFrom(recv)
  58. require.NoError(t, err, "error receiving data")
  59. assert.Equal(t, conn.LocalAddr(), rAddr, "remote tcp address mismatch")
  60. assert.Equal(t, n, n2, "received byte size mismatch")
  61. assert.Equal(t, msg.Raw, recv, "received bytes mismatch")
  62. // Check echo response
  63. n, err = pktConn.WriteTo(recv, conn.LocalAddr())
  64. require.NoError(t, err, "error writing echo STUN packet")
  65. recvEcho := make([]byte, n)
  66. n3, err := readStreamingPacket(conn, recvEcho)
  67. require.NoError(t, err, "error receiving echo data")
  68. assert.Equal(t, n2, n3, "received byte size mismatch")
  69. assert.Equal(t, msg.Raw, recvEcho, "received bytes mismatch")
  70. })
  71. }
  72. }
  73. func TestTCPMux_NoDeadlockWhenClosingUnusedPacketConn(t *testing.T) {
  74. report := test.CheckRoutines(t)
  75. defer report()
  76. loggerFactory := logging.NewDefaultLoggerFactory()
  77. listener, err := net.ListenTCP("tcp", &net.TCPAddr{
  78. IP: net.IP{127, 0, 0, 1},
  79. Port: 0,
  80. })
  81. require.NoError(t, err, "error starting listener")
  82. defer func() {
  83. _ = listener.Close()
  84. }()
  85. tcpMux := NewTCPMuxDefault(TCPMuxParams{
  86. Listener: listener,
  87. Logger: loggerFactory.NewLogger("ice"),
  88. ReadBufferSize: 20,
  89. })
  90. _, err = tcpMux.GetConnByUfrag("test", false, listener.Addr().(*net.TCPAddr).IP)
  91. require.NoError(t, err, "error getting conn by ufrag")
  92. require.NoError(t, tcpMux.Close(), "error closing tcpMux")
  93. conn, err := tcpMux.GetConnByUfrag("test", false, listener.Addr().(*net.TCPAddr).IP)
  94. assert.Nil(t, conn, "should receive nil because mux is closed")
  95. assert.Equal(t, io.ErrClosedPipe, err, "should receive error because mux is closed")
  96. }