github.com/pion/webrtc/v3@v3.2.24/signalingstate.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 package webrtc 5 6 import ( 7 "fmt" 8 "sync/atomic" 9 10 "github.com/pion/webrtc/v3/pkg/rtcerr" 11 ) 12 13 type stateChangeOp int 14 15 const ( 16 stateChangeOpSetLocal stateChangeOp = iota + 1 17 stateChangeOpSetRemote 18 ) 19 20 func (op stateChangeOp) String() string { 21 switch op { 22 case stateChangeOpSetLocal: 23 return "SetLocal" 24 case stateChangeOpSetRemote: 25 return "SetRemote" 26 default: 27 return "Unknown State Change Operation" 28 } 29 } 30 31 // SignalingState indicates the signaling state of the offer/answer process. 32 type SignalingState int32 33 34 const ( 35 // SignalingStateStable indicates there is no offer/answer exchange in 36 // progress. This is also the initial state, in which case the local and 37 // remote descriptions are nil. 38 SignalingStateStable SignalingState = iota + 1 39 40 // SignalingStateHaveLocalOffer indicates that a local description, of 41 // type "offer", has been successfully applied. 42 SignalingStateHaveLocalOffer 43 44 // SignalingStateHaveRemoteOffer indicates that a remote description, of 45 // type "offer", has been successfully applied. 46 SignalingStateHaveRemoteOffer 47 48 // SignalingStateHaveLocalPranswer indicates that a remote description 49 // of type "offer" has been successfully applied and a local description 50 // of type "pranswer" has been successfully applied. 51 SignalingStateHaveLocalPranswer 52 53 // SignalingStateHaveRemotePranswer indicates that a local description 54 // of type "offer" has been successfully applied and a remote description 55 // of type "pranswer" has been successfully applied. 56 SignalingStateHaveRemotePranswer 57 58 // SignalingStateClosed indicates The PeerConnection has been closed. 59 SignalingStateClosed 60 ) 61 62 // This is done this way because of a linter. 63 const ( 64 signalingStateStableStr = "stable" 65 signalingStateHaveLocalOfferStr = "have-local-offer" 66 signalingStateHaveRemoteOfferStr = "have-remote-offer" 67 signalingStateHaveLocalPranswerStr = "have-local-pranswer" 68 signalingStateHaveRemotePranswerStr = "have-remote-pranswer" 69 signalingStateClosedStr = "closed" 70 ) 71 72 func newSignalingState(raw string) SignalingState { 73 switch raw { 74 case signalingStateStableStr: 75 return SignalingStateStable 76 case signalingStateHaveLocalOfferStr: 77 return SignalingStateHaveLocalOffer 78 case signalingStateHaveRemoteOfferStr: 79 return SignalingStateHaveRemoteOffer 80 case signalingStateHaveLocalPranswerStr: 81 return SignalingStateHaveLocalPranswer 82 case signalingStateHaveRemotePranswerStr: 83 return SignalingStateHaveRemotePranswer 84 case signalingStateClosedStr: 85 return SignalingStateClosed 86 default: 87 return SignalingState(Unknown) 88 } 89 } 90 91 func (t SignalingState) String() string { 92 switch t { 93 case SignalingStateStable: 94 return signalingStateStableStr 95 case SignalingStateHaveLocalOffer: 96 return signalingStateHaveLocalOfferStr 97 case SignalingStateHaveRemoteOffer: 98 return signalingStateHaveRemoteOfferStr 99 case SignalingStateHaveLocalPranswer: 100 return signalingStateHaveLocalPranswerStr 101 case SignalingStateHaveRemotePranswer: 102 return signalingStateHaveRemotePranswerStr 103 case SignalingStateClosed: 104 return signalingStateClosedStr 105 default: 106 return ErrUnknownType.Error() 107 } 108 } 109 110 // Get thread safe read value 111 func (t *SignalingState) Get() SignalingState { 112 return SignalingState(atomic.LoadInt32((*int32)(t))) 113 } 114 115 // Set thread safe write value 116 func (t *SignalingState) Set(state SignalingState) { 117 atomic.StoreInt32((*int32)(t), int32(state)) 118 } 119 120 func checkNextSignalingState(cur, next SignalingState, op stateChangeOp, sdpType SDPType) (SignalingState, error) { // nolint:gocognit 121 // Special case for rollbacks 122 if sdpType == SDPTypeRollback && cur == SignalingStateStable { 123 return cur, &rtcerr.InvalidModificationError{ 124 Err: errSignalingStateCannotRollback, 125 } 126 } 127 128 // 4.3.1 valid state transitions 129 switch cur { // nolint:exhaustive 130 case SignalingStateStable: 131 switch op { 132 case stateChangeOpSetLocal: 133 // stable->SetLocal(offer)->have-local-offer 134 if sdpType == SDPTypeOffer && next == SignalingStateHaveLocalOffer { 135 return next, nil 136 } 137 case stateChangeOpSetRemote: 138 // stable->SetRemote(offer)->have-remote-offer 139 if sdpType == SDPTypeOffer && next == SignalingStateHaveRemoteOffer { 140 return next, nil 141 } 142 } 143 case SignalingStateHaveLocalOffer: 144 if op == stateChangeOpSetRemote { 145 switch sdpType { // nolint:exhaustive 146 // have-local-offer->SetRemote(answer)->stable 147 case SDPTypeAnswer: 148 if next == SignalingStateStable { 149 return next, nil 150 } 151 // have-local-offer->SetRemote(pranswer)->have-remote-pranswer 152 case SDPTypePranswer: 153 if next == SignalingStateHaveRemotePranswer { 154 return next, nil 155 } 156 } 157 } 158 case SignalingStateHaveRemotePranswer: 159 if op == stateChangeOpSetRemote && sdpType == SDPTypeAnswer { 160 // have-remote-pranswer->SetRemote(answer)->stable 161 if next == SignalingStateStable { 162 return next, nil 163 } 164 } 165 case SignalingStateHaveRemoteOffer: 166 if op == stateChangeOpSetLocal { 167 switch sdpType { // nolint:exhaustive 168 // have-remote-offer->SetLocal(answer)->stable 169 case SDPTypeAnswer: 170 if next == SignalingStateStable { 171 return next, nil 172 } 173 // have-remote-offer->SetLocal(pranswer)->have-local-pranswer 174 case SDPTypePranswer: 175 if next == SignalingStateHaveLocalPranswer { 176 return next, nil 177 } 178 } 179 } 180 case SignalingStateHaveLocalPranswer: 181 if op == stateChangeOpSetLocal && sdpType == SDPTypeAnswer { 182 // have-local-pranswer->SetLocal(answer)->stable 183 if next == SignalingStateStable { 184 return next, nil 185 } 186 } 187 } 188 return cur, &rtcerr.InvalidModificationError{ 189 Err: fmt.Errorf("%w: %s->%s(%s)->%s", errSignalingStateProposedTransitionInvalid, cur, op, sdpType, next), 190 } 191 }