OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 using cricket::PRFLX_PORT_TYPE; | 54 using cricket::PRFLX_PORT_TYPE; |
55 | 55 |
56 namespace webrtc { | 56 namespace webrtc { |
57 | 57 |
58 // Error messages | 58 // Error messages |
59 const char kBundleWithoutRtcpMux[] = "RTCP-MUX must be enabled when BUNDLE " | 59 const char kBundleWithoutRtcpMux[] = "RTCP-MUX must be enabled when BUNDLE " |
60 "is enabled."; | 60 "is enabled."; |
61 const char kCreateChannelFailed[] = "Failed to create channels."; | 61 const char kCreateChannelFailed[] = "Failed to create channels."; |
62 const char kInvalidCandidates[] = "Description contains invalid candidates."; | 62 const char kInvalidCandidates[] = "Description contains invalid candidates."; |
63 const char kInvalidSdp[] = "Invalid session description."; | 63 const char kInvalidSdp[] = "Invalid session description."; |
64 const char kMlineMismatch[] = | 64 const char kMlineMismatchInAnswer[] = |
65 "Offer and answer descriptions m-lines are not matching. Rejecting answer."; | 65 "The order of m-lines in answer doesn't match order in offer. Rejecting " |
| 66 "answer."; |
| 67 const char kMlineMismatchInSubsequentOffer[] = |
| 68 "The order of m-lines in subsequent offer doesn't match order from " |
| 69 "previous offer/answer."; |
66 const char kPushDownTDFailed[] = | 70 const char kPushDownTDFailed[] = |
67 "Failed to push down transport description:"; | 71 "Failed to push down transport description:"; |
68 const char kSdpWithoutDtlsFingerprint[] = | 72 const char kSdpWithoutDtlsFingerprint[] = |
69 "Called with SDP without DTLS fingerprint."; | 73 "Called with SDP without DTLS fingerprint."; |
70 const char kSdpWithoutSdesCrypto[] = | 74 const char kSdpWithoutSdesCrypto[] = |
71 "Called with SDP without SDES crypto."; | 75 "Called with SDP without SDES crypto."; |
72 const char kSdpWithoutIceUfragPwd[] = | 76 const char kSdpWithoutIceUfragPwd[] = |
73 "Called with SDP without ice-ufrag and ice-pwd."; | 77 "Called with SDP without ice-ufrag and ice-pwd."; |
74 const char kSessionError[] = "Session error code: "; | 78 const char kSessionError[] = "Session error code: "; |
75 const char kSessionErrorDesc[] = "Session error description: "; | 79 const char kSessionErrorDesc[] = "Session error description: "; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 return kIceCandidatePairRelayPrflx; | 133 return kIceCandidatePairRelayPrflx; |
130 if (l == prflx && r == host) | 134 if (l == prflx && r == host) |
131 return kIceCandidatePairPrflxHost; | 135 return kIceCandidatePairPrflxHost; |
132 if (l == prflx && r == srflx) | 136 if (l == prflx && r == srflx) |
133 return kIceCandidatePairPrflxSrflx; | 137 return kIceCandidatePairPrflxSrflx; |
134 if (l == prflx && r == relay) | 138 if (l == prflx && r == relay) |
135 return kIceCandidatePairPrflxRelay; | 139 return kIceCandidatePairPrflxRelay; |
136 return kIceCandidatePairMax; | 140 return kIceCandidatePairMax; |
137 } | 141 } |
138 | 142 |
139 // Compares |answer| against |offer|. Comparision is done | 143 // Verify that the order of media sections in |desc1| matches |desc2|. The |
140 // for number of m-lines in answer against offer. If matches true will be | 144 // number of m= sections could be different. |
141 // returned otherwise false. | 145 static bool MediaSectionsInSameOrder(const SessionDescription* desc1, |
142 static bool VerifyMediaDescriptions( | 146 const SessionDescription* desc2) { |
143 const SessionDescription* answer, const SessionDescription* offer) { | 147 if (!desc1 || !desc2) { |
144 if (offer->contents().size() != answer->contents().size()) | |
145 return false; | 148 return false; |
146 | 149 } |
147 for (size_t i = 0; i < offer->contents().size(); ++i) { | 150 for (size_t i = 0; |
148 if ((offer->contents()[i].name) != answer->contents()[i].name) { | 151 i < desc1->contents().size() && i < desc2->contents().size(); ++i) { |
| 152 if ((desc2->contents()[i].name) != desc1->contents()[i].name) { |
149 return false; | 153 return false; |
150 } | 154 } |
151 const MediaContentDescription* offer_mdesc = | 155 const MediaContentDescription* desc2_mdesc = |
152 static_cast<const MediaContentDescription*>( | 156 static_cast<const MediaContentDescription*>( |
153 offer->contents()[i].description); | 157 desc2->contents()[i].description); |
154 const MediaContentDescription* answer_mdesc = | 158 const MediaContentDescription* desc1_mdesc = |
155 static_cast<const MediaContentDescription*>( | 159 static_cast<const MediaContentDescription*>( |
156 answer->contents()[i].description); | 160 desc1->contents()[i].description); |
157 if (offer_mdesc->type() != answer_mdesc->type()) { | 161 if (desc2_mdesc->type() != desc1_mdesc->type()) { |
158 return false; | 162 return false; |
159 } | 163 } |
160 } | 164 } |
161 return true; | 165 return true; |
162 } | 166 } |
163 | 167 |
| 168 static bool MediaSectionsHaveSameCount(const SessionDescription* desc1, |
| 169 const SessionDescription* desc2) { |
| 170 if (!desc1 || !desc2) { |
| 171 return false; |
| 172 } |
| 173 return desc1->contents().size() == desc2->contents().size(); |
| 174 } |
| 175 |
164 // Checks that each non-rejected content has SDES crypto keys or a DTLS | 176 // Checks that each non-rejected content has SDES crypto keys or a DTLS |
165 // fingerprint, unless it's in a BUNDLE group, in which case only the | 177 // fingerprint, unless it's in a BUNDLE group, in which case only the |
166 // BUNDLE-tag section (first media section/description in the BUNDLE group) | 178 // BUNDLE-tag section (first media section/description in the BUNDLE group) |
167 // needs a ufrag and pwd. Mismatches, such as replying with a DTLS fingerprint | 179 // needs a ufrag and pwd. Mismatches, such as replying with a DTLS fingerprint |
168 // to SDES keys, will be caught in JsepTransport negotiation, and backstopped | 180 // to SDES keys, will be caught in JsepTransport negotiation, and backstopped |
169 // by Channel's |srtp_required| check. | 181 // by Channel's |srtp_required| check. |
170 static bool VerifyCrypto(const SessionDescription* desc, | 182 static bool VerifyCrypto(const SessionDescription* desc, |
171 bool dtls_enabled, | 183 bool dtls_enabled, |
172 std::string* error) { | 184 std::string* error) { |
173 const cricket::ContentGroup* bundle = | 185 const cricket::ContentGroup* bundle = |
(...skipping 1972 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2146 } | 2158 } |
2147 | 2159 |
2148 if (!ValidateBundleSettings(sdesc->description())) { | 2160 if (!ValidateBundleSettings(sdesc->description())) { |
2149 return BadSdp(source, type, kBundleWithoutRtcpMux, err_desc); | 2161 return BadSdp(source, type, kBundleWithoutRtcpMux, err_desc); |
2150 } | 2162 } |
2151 | 2163 |
2152 // TODO(skvlad): When the local rtcp-mux policy is Require, reject any | 2164 // TODO(skvlad): When the local rtcp-mux policy is Require, reject any |
2153 // m-lines that do not rtcp-mux enabled. | 2165 // m-lines that do not rtcp-mux enabled. |
2154 | 2166 |
2155 // Verify m-lines in Answer when compared against Offer. | 2167 // Verify m-lines in Answer when compared against Offer. |
2156 if (action == kAnswer) { | 2168 if (action == kAnswer || action == kPrAnswer) { |
2157 const cricket::SessionDescription* offer_desc = | 2169 const cricket::SessionDescription* offer_desc = |
2158 (source == cricket::CS_LOCAL) ? remote_description()->description() | 2170 (source == cricket::CS_LOCAL) ? remote_description()->description() |
2159 : local_description()->description(); | 2171 : local_description()->description(); |
2160 if (!VerifyMediaDescriptions(sdesc->description(), offer_desc)) { | 2172 if (!MediaSectionsHaveSameCount(sdesc->description(), offer_desc) || |
2161 return BadAnswerSdp(source, kMlineMismatch, err_desc); | 2173 !MediaSectionsInSameOrder(sdesc->description(), offer_desc)) { |
| 2174 return BadAnswerSdp(source, kMlineMismatchInAnswer, err_desc); |
| 2175 } |
| 2176 } else { |
| 2177 // The re-offers should respect the order of m= sections in current local |
| 2178 // description. See RFC3264 Section 8 paragraph 4 for more details. |
| 2179 if (local_description() && |
| 2180 !MediaSectionsInSameOrder(sdesc->description(), |
| 2181 local_description()->description())) { |
| 2182 return BadOfferSdp(source, kMlineMismatchInSubsequentOffer, err_desc); |
2162 } | 2183 } |
2163 } | 2184 } |
2164 | 2185 |
2165 return true; | 2186 return true; |
2166 } | 2187 } |
2167 | 2188 |
2168 bool WebRtcSession::ExpectSetLocalDescription(Action action) { | 2189 bool WebRtcSession::ExpectSetLocalDescription(Action action) { |
2169 return ((action == kOffer && state() == STATE_INIT) || | 2190 return ((action == kOffer && state() == STATE_INIT) || |
2170 // update local offer | 2191 // update local offer |
2171 (action == kOffer && state() == STATE_SENTOFFER) || | 2192 (action == kOffer && state() == STATE_SENTOFFER) || |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2483 (rtp_data_channel_->rtcp_dtls_transport() != nullptr); | 2504 (rtp_data_channel_->rtcp_dtls_transport() != nullptr); |
2484 channel_manager_->DestroyRtpDataChannel(rtp_data_channel_.release()); | 2505 channel_manager_->DestroyRtpDataChannel(rtp_data_channel_.release()); |
2485 transport_controller_->DestroyDtlsTransport( | 2506 transport_controller_->DestroyDtlsTransport( |
2486 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP); | 2507 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP); |
2487 if (need_to_delete_rtcp) { | 2508 if (need_to_delete_rtcp) { |
2488 transport_controller_->DestroyDtlsTransport( | 2509 transport_controller_->DestroyDtlsTransport( |
2489 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP); | 2510 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP); |
2490 } | 2511 } |
2491 } | 2512 } |
2492 } // namespace webrtc | 2513 } // namespace webrtc |
OLD | NEW |