github.com/pion/webrtc/v4@v4.0.1/ortc_test.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 //go:build !js 5 // +build !js 6 7 package webrtc 8 9 import ( 10 "github.com/pion/webrtc/v4/internal/util" 11 ) 12 13 type testORTCStack struct { 14 api *API 15 gatherer *ICEGatherer 16 ice *ICETransport 17 dtls *DTLSTransport 18 sctp *SCTPTransport 19 } 20 21 func (s *testORTCStack) setSignal(sig *testORTCSignal, isOffer bool) error { 22 iceRole := ICERoleControlled 23 if isOffer { 24 iceRole = ICERoleControlling 25 } 26 27 err := s.ice.SetRemoteCandidates(sig.ICECandidates) 28 if err != nil { 29 return err 30 } 31 32 // Start the ICE transport 33 err = s.ice.Start(nil, sig.ICEParameters, &iceRole) 34 if err != nil { 35 return err 36 } 37 38 // Start the DTLS transport 39 err = s.dtls.Start(sig.DTLSParameters) 40 if err != nil { 41 return err 42 } 43 44 // Start the SCTP transport 45 err = s.sctp.Start(sig.SCTPCapabilities) 46 if err != nil { 47 return err 48 } 49 50 return nil 51 } 52 53 func (s *testORTCStack) getSignal() (*testORTCSignal, error) { 54 gatherFinished := make(chan struct{}) 55 s.gatherer.OnLocalCandidate(func(i *ICECandidate) { 56 if i == nil { 57 close(gatherFinished) 58 } 59 }) 60 61 if err := s.gatherer.Gather(); err != nil { 62 return nil, err 63 } 64 65 <-gatherFinished 66 iceCandidates, err := s.gatherer.GetLocalCandidates() 67 if err != nil { 68 return nil, err 69 } 70 71 iceParams, err := s.gatherer.GetLocalParameters() 72 if err != nil { 73 return nil, err 74 } 75 76 dtlsParams, err := s.dtls.GetLocalParameters() 77 if err != nil { 78 return nil, err 79 } 80 81 sctpCapabilities := s.sctp.GetCapabilities() 82 83 return &testORTCSignal{ 84 ICECandidates: iceCandidates, 85 ICEParameters: iceParams, 86 DTLSParameters: dtlsParams, 87 SCTPCapabilities: sctpCapabilities, 88 }, nil 89 } 90 91 func (s *testORTCStack) close() error { 92 var closeErrs []error 93 94 if err := s.sctp.Stop(); err != nil { 95 closeErrs = append(closeErrs, err) 96 } 97 98 if err := s.ice.Stop(); err != nil { 99 closeErrs = append(closeErrs, err) 100 } 101 102 return util.FlattenErrs(closeErrs) 103 } 104 105 type testORTCSignal struct { 106 ICECandidates []ICECandidate 107 ICEParameters ICEParameters 108 DTLSParameters DTLSParameters 109 SCTPCapabilities SCTPCapabilities 110 } 111 112 func newORTCPair() (stackA *testORTCStack, stackB *testORTCStack, err error) { 113 sa, err := newORTCStack() 114 if err != nil { 115 return nil, nil, err 116 } 117 118 sb, err := newORTCStack() 119 if err != nil { 120 return nil, nil, err 121 } 122 123 return sa, sb, nil 124 } 125 126 func newORTCStack() (*testORTCStack, error) { 127 // Create an API object 128 api := NewAPI() 129 130 // Create the ICE gatherer 131 gatherer, err := api.NewICEGatherer(ICEGatherOptions{}) 132 if err != nil { 133 return nil, err 134 } 135 136 // Construct the ICE transport 137 ice := api.NewICETransport(gatherer) 138 139 // Construct the DTLS transport 140 dtls, err := api.NewDTLSTransport(ice, nil) 141 if err != nil { 142 return nil, err 143 } 144 145 // Construct the SCTP transport 146 sctp := api.NewSCTPTransport(dtls) 147 148 return &testORTCStack{ 149 api: api, 150 gatherer: gatherer, 151 ice: ice, 152 dtls: dtls, 153 sctp: sctp, 154 }, nil 155 } 156 157 func signalORTCPair(stackA *testORTCStack, stackB *testORTCStack) error { 158 sigA, err := stackA.getSignal() 159 if err != nil { 160 return err 161 } 162 sigB, err := stackB.getSignal() 163 if err != nil { 164 return err 165 } 166 167 a := make(chan error) 168 b := make(chan error) 169 170 go func() { 171 a <- stackB.setSignal(sigA, false) 172 }() 173 174 go func() { 175 b <- stackA.setSignal(sigB, true) 176 }() 177 178 errA := <-a 179 errB := <-b 180 181 closeErrs := []error{errA, errB} 182 183 return util.FlattenErrs(closeErrs) 184 }