tcp_mux_multi.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package ice
  4. import "net"
  5. // AllConnsGetter allows multiple fixed TCP ports to be used,
  6. // each of which is multiplexed like TCPMux. AllConnsGetter also acts as
  7. // a TCPMux, in which case it will return a single connection for one
  8. // of the ports.
  9. type AllConnsGetter interface {
  10. GetAllConns(ufrag string, isIPv6 bool, localIP net.IP) ([]net.PacketConn, error)
  11. }
  12. // MultiTCPMuxDefault implements both TCPMux and AllConnsGetter,
  13. // allowing users to pass multiple TCPMux instances to the ICE agent
  14. // configuration.
  15. type MultiTCPMuxDefault struct {
  16. muxes []TCPMux
  17. }
  18. // NewMultiTCPMuxDefault creates an instance of MultiTCPMuxDefault that
  19. // uses the provided TCPMux instances.
  20. func NewMultiTCPMuxDefault(muxes ...TCPMux) *MultiTCPMuxDefault {
  21. return &MultiTCPMuxDefault{
  22. muxes: muxes,
  23. }
  24. }
  25. // GetConnByUfrag returns a PacketConn given the connection's ufrag, network and local address
  26. // creates the connection if an existing one can't be found. This, unlike
  27. // GetAllConns, will only return a single PacketConn from the first mux that was
  28. // passed in to NewMultiTCPMuxDefault.
  29. func (m *MultiTCPMuxDefault) GetConnByUfrag(ufrag string, isIPv6 bool, local net.IP) (net.PacketConn, error) {
  30. // NOTE: We always use the first element here in order to maintain the
  31. // behavior of using an existing connection if one exists.
  32. if len(m.muxes) == 0 {
  33. return nil, errNoTCPMuxAvailable
  34. }
  35. return m.muxes[0].GetConnByUfrag(ufrag, isIPv6, local)
  36. }
  37. // RemoveConnByUfrag stops and removes the muxed packet connection
  38. // from all underlying TCPMux instances.
  39. func (m *MultiTCPMuxDefault) RemoveConnByUfrag(ufrag string) {
  40. for _, mux := range m.muxes {
  41. mux.RemoveConnByUfrag(ufrag)
  42. }
  43. }
  44. // GetAllConns returns a PacketConn for each underlying TCPMux
  45. func (m *MultiTCPMuxDefault) GetAllConns(ufrag string, isIPv6 bool, local net.IP) ([]net.PacketConn, error) {
  46. if len(m.muxes) == 0 {
  47. // Make sure that we either return at least one connection or an error.
  48. return nil, errNoTCPMuxAvailable
  49. }
  50. var conns []net.PacketConn
  51. for _, mux := range m.muxes {
  52. conn, err := mux.GetConnByUfrag(ufrag, isIPv6, local)
  53. if err != nil {
  54. // For now, this implementation is all or none.
  55. return nil, err
  56. }
  57. if conn != nil {
  58. conns = append(conns, conn)
  59. }
  60. }
  61. return conns, nil
  62. }
  63. // Close the multi mux, no further connections could be created
  64. func (m *MultiTCPMuxDefault) Close() error {
  65. var err error
  66. for _, mux := range m.muxes {
  67. if e := mux.Close(); e != nil {
  68. err = e
  69. }
  70. }
  71. return err
  72. }