udp_mux_multi.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package ice
  4. import (
  5. "fmt"
  6. "net"
  7. "github.com/pion/logging"
  8. "github.com/pion/transport/v2"
  9. "github.com/pion/transport/v2/stdnet"
  10. )
  11. // MultiUDPMuxDefault implements both UDPMux and AllConnsGetter,
  12. // allowing users to pass multiple UDPMux instances to the ICE agent
  13. // configuration.
  14. type MultiUDPMuxDefault struct {
  15. muxes []UDPMux
  16. localAddrToMux map[string]UDPMux
  17. }
  18. // NewMultiUDPMuxDefault creates an instance of MultiUDPMuxDefault that
  19. // uses the provided UDPMux instances.
  20. func NewMultiUDPMuxDefault(muxes ...UDPMux) *MultiUDPMuxDefault {
  21. addrToMux := make(map[string]UDPMux)
  22. for _, mux := range muxes {
  23. for _, addr := range mux.GetListenAddresses() {
  24. addrToMux[addr.String()] = mux
  25. }
  26. }
  27. return &MultiUDPMuxDefault{
  28. muxes: muxes,
  29. localAddrToMux: addrToMux,
  30. }
  31. }
  32. // GetConn returns a PacketConn given the connection's ufrag and network
  33. // creates the connection if an existing one can't be found.
  34. func (m *MultiUDPMuxDefault) GetConn(ufrag string, addr net.Addr) (net.PacketConn, error) {
  35. mux, ok := m.localAddrToMux[addr.String()]
  36. if !ok {
  37. return nil, errNoUDPMuxAvailable
  38. }
  39. return mux.GetConn(ufrag, addr)
  40. }
  41. // RemoveConnByUfrag stops and removes the muxed packet connection
  42. // from all underlying UDPMux instances.
  43. func (m *MultiUDPMuxDefault) RemoveConnByUfrag(ufrag string) {
  44. for _, mux := range m.muxes {
  45. mux.RemoveConnByUfrag(ufrag)
  46. }
  47. }
  48. // Close the multi mux, no further connections could be created
  49. func (m *MultiUDPMuxDefault) Close() error {
  50. var err error
  51. for _, mux := range m.muxes {
  52. if e := mux.Close(); e != nil {
  53. err = e
  54. }
  55. }
  56. return err
  57. }
  58. // GetListenAddresses returns the list of addresses that this mux is listening on
  59. func (m *MultiUDPMuxDefault) GetListenAddresses() []net.Addr {
  60. addrs := make([]net.Addr, 0, len(m.localAddrToMux))
  61. for _, mux := range m.muxes {
  62. addrs = append(addrs, mux.GetListenAddresses()...)
  63. }
  64. return addrs
  65. }
  66. // NewMultiUDPMuxFromPort creates an instance of MultiUDPMuxDefault that
  67. // listen all interfaces on the provided port.
  68. func NewMultiUDPMuxFromPort(port int, opts ...UDPMuxFromPortOption) (*MultiUDPMuxDefault, error) {
  69. params := multiUDPMuxFromPortParam{
  70. networks: []NetworkType{NetworkTypeUDP4, NetworkTypeUDP6},
  71. }
  72. for _, opt := range opts {
  73. opt.apply(&params)
  74. }
  75. if params.net == nil {
  76. var err error
  77. if params.net, err = stdnet.NewNet(); err != nil {
  78. return nil, fmt.Errorf("failed to get create network: %w", err)
  79. }
  80. }
  81. ips, err := localInterfaces(params.net, params.ifFilter, params.ipFilter, params.networks, params.includeLoopback)
  82. if err != nil {
  83. return nil, err
  84. }
  85. conns := make([]net.PacketConn, 0, len(ips))
  86. for _, ip := range ips {
  87. conn, listenErr := params.net.ListenUDP("udp", &net.UDPAddr{IP: ip, Port: port})
  88. if listenErr != nil {
  89. err = listenErr
  90. break
  91. }
  92. if params.readBufferSize > 0 {
  93. _ = conn.SetReadBuffer(params.readBufferSize)
  94. }
  95. if params.writeBufferSize > 0 {
  96. _ = conn.SetWriteBuffer(params.writeBufferSize)
  97. }
  98. conns = append(conns, conn)
  99. }
  100. if err != nil {
  101. for _, conn := range conns {
  102. _ = conn.Close()
  103. }
  104. return nil, err
  105. }
  106. muxes := make([]UDPMux, 0, len(conns))
  107. for _, conn := range conns {
  108. mux := NewUDPMuxDefault(UDPMuxParams{
  109. Logger: params.logger,
  110. UDPConn: conn,
  111. Net: params.net,
  112. })
  113. muxes = append(muxes, mux)
  114. }
  115. return NewMultiUDPMuxDefault(muxes...), nil
  116. }
  117. // UDPMuxFromPortOption provide options for NewMultiUDPMuxFromPort
  118. type UDPMuxFromPortOption interface {
  119. apply(*multiUDPMuxFromPortParam)
  120. }
  121. type multiUDPMuxFromPortParam struct {
  122. ifFilter func(string) bool
  123. ipFilter func(ip net.IP) bool
  124. networks []NetworkType
  125. readBufferSize int
  126. writeBufferSize int
  127. logger logging.LeveledLogger
  128. includeLoopback bool
  129. net transport.Net
  130. }
  131. type udpMuxFromPortOption struct {
  132. f func(*multiUDPMuxFromPortParam)
  133. }
  134. func (o *udpMuxFromPortOption) apply(p *multiUDPMuxFromPortParam) {
  135. o.f(p)
  136. }
  137. // UDPMuxFromPortWithInterfaceFilter set the filter to filter out interfaces that should not be used
  138. func UDPMuxFromPortWithInterfaceFilter(f func(string) bool) UDPMuxFromPortOption {
  139. return &udpMuxFromPortOption{
  140. f: func(p *multiUDPMuxFromPortParam) {
  141. p.ifFilter = f
  142. },
  143. }
  144. }
  145. // UDPMuxFromPortWithIPFilter set the filter to filter out IP addresses that should not be used
  146. func UDPMuxFromPortWithIPFilter(f func(ip net.IP) bool) UDPMuxFromPortOption {
  147. return &udpMuxFromPortOption{
  148. f: func(p *multiUDPMuxFromPortParam) {
  149. p.ipFilter = f
  150. },
  151. }
  152. }
  153. // UDPMuxFromPortWithNetworks set the networks that should be used. default is both IPv4 and IPv6
  154. func UDPMuxFromPortWithNetworks(networks ...NetworkType) UDPMuxFromPortOption {
  155. return &udpMuxFromPortOption{
  156. f: func(p *multiUDPMuxFromPortParam) {
  157. p.networks = networks
  158. },
  159. }
  160. }
  161. // UDPMuxFromPortWithReadBufferSize set the UDP connection read buffer size
  162. func UDPMuxFromPortWithReadBufferSize(size int) UDPMuxFromPortOption {
  163. return &udpMuxFromPortOption{
  164. f: func(p *multiUDPMuxFromPortParam) {
  165. p.readBufferSize = size
  166. },
  167. }
  168. }
  169. // UDPMuxFromPortWithWriteBufferSize set the UDP connection write buffer size
  170. func UDPMuxFromPortWithWriteBufferSize(size int) UDPMuxFromPortOption {
  171. return &udpMuxFromPortOption{
  172. f: func(p *multiUDPMuxFromPortParam) {
  173. p.writeBufferSize = size
  174. },
  175. }
  176. }
  177. // UDPMuxFromPortWithLogger set the logger for the created UDPMux
  178. func UDPMuxFromPortWithLogger(logger logging.LeveledLogger) UDPMuxFromPortOption {
  179. return &udpMuxFromPortOption{
  180. f: func(p *multiUDPMuxFromPortParam) {
  181. p.logger = logger
  182. },
  183. }
  184. }
  185. // UDPMuxFromPortWithLoopback set loopback interface should be included
  186. func UDPMuxFromPortWithLoopback() UDPMuxFromPortOption {
  187. return &udpMuxFromPortOption{
  188. f: func(p *multiUDPMuxFromPortParam) {
  189. p.includeLoopback = true
  190. },
  191. }
  192. }
  193. // UDPMuxFromPortWithNet sets the network transport to use.
  194. func UDPMuxFromPortWithNet(n transport.Net) UDPMuxFromPortOption {
  195. return &udpMuxFromPortOption{
  196. f: func(p *multiUDPMuxFromPortParam) {
  197. p.net = n
  198. },
  199. }
  200. }