OLD | NEW |
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
(...skipping 10 matching lines...) Expand all Loading... |
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 */ | 26 */ |
27 | 27 |
28 #include "talk/app/webrtc/peerconnection.h" | 28 #include "talk/app/webrtc/peerconnection.h" |
29 | 29 |
30 #include <vector> | 30 #include <vector> |
| 31 #include <cctype> // for isdigit |
31 | 32 |
32 #include "talk/app/webrtc/dtmfsender.h" | 33 #include "talk/app/webrtc/dtmfsender.h" |
33 #include "talk/app/webrtc/jsepicecandidate.h" | 34 #include "talk/app/webrtc/jsepicecandidate.h" |
34 #include "talk/app/webrtc/jsepsessiondescription.h" | 35 #include "talk/app/webrtc/jsepsessiondescription.h" |
35 #include "talk/app/webrtc/mediaconstraintsinterface.h" | 36 #include "talk/app/webrtc/mediaconstraintsinterface.h" |
36 #include "talk/app/webrtc/rtpreceiver.h" | 37 #include "talk/app/webrtc/rtpreceiver.h" |
37 #include "talk/app/webrtc/rtpsender.h" | 38 #include "talk/app/webrtc/rtpsender.h" |
38 #include "talk/app/webrtc/streamcollection.h" | 39 #include "talk/app/webrtc/streamcollection.h" |
39 #include "webrtc/p2p/client/basicportallocator.h" | 40 #include "webrtc/p2p/client/basicportallocator.h" |
40 #include "talk/session/media/channelmanager.h" | 41 #include "talk/session/media/channelmanager.h" |
41 #include "webrtc/base/logging.h" | 42 #include "webrtc/base/logging.h" |
42 #include "webrtc/base/stringencode.h" | 43 #include "webrtc/base/stringencode.h" |
43 #include "webrtc/system_wrappers/interface/field_trial.h" | 44 #include "webrtc/system_wrappers/interface/field_trial.h" |
44 | 45 |
45 namespace { | 46 namespace { |
46 | 47 |
47 using webrtc::PeerConnectionInterface; | 48 using webrtc::PeerConnectionInterface; |
| 49 using webrtc::StunConfigurations; |
| 50 using webrtc::TurnConfigurations; |
| 51 typedef webrtc::PortAllocatorFactoryInterface::StunConfiguration |
| 52 StunConfiguration; |
| 53 typedef webrtc::PortAllocatorFactoryInterface::TurnConfiguration |
| 54 TurnConfiguration; |
48 | 55 |
49 // The min number of tokens must present in Turn host uri. | 56 // The min number of tokens must present in Turn host uri. |
50 // e.g. user@turn.example.org | 57 // e.g. user@turn.example.org |
51 static const size_t kTurnHostTokensNum = 2; | 58 static const size_t kTurnHostTokensNum = 2; |
52 // Number of tokens must be preset when TURN uri has transport param. | 59 // Number of tokens must be preset when TURN uri has transport param. |
53 static const size_t kTurnTransportTokensNum = 2; | 60 static const size_t kTurnTransportTokensNum = 2; |
54 // The default stun port. | 61 // The default stun port. |
55 static const int kDefaultStunPort = 3478; | 62 static const int kDefaultStunPort = 3478; |
56 static const int kDefaultStunTlsPort = 5349; | 63 static const int kDefaultStunTlsPort = 5349; |
57 static const char kTransport[] = "transport"; | 64 static const char kTransport[] = "transport"; |
58 static const char kUdpTransportType[] = "udp"; | 65 static const char kUdpTransportType[] = "udp"; |
59 static const char kTcpTransportType[] = "tcp"; | 66 static const char kTcpTransportType[] = "tcp"; |
60 | 67 |
61 // NOTE: Must be in the same order as the ServiceType enum. | 68 // NOTE: Must be in the same order as the ServiceType enum. |
62 static const char* kValidIceServiceTypes[] = { | 69 static const char* kValidIceServiceTypes[] = {"stun", "stuns", "turn", "turns"}; |
63 "stun", "stuns", "turn", "turns", "invalid" }; | |
64 | 70 |
| 71 // NOTE: A loop below assumes that the first value of this enum is 0 and all |
| 72 // other values are incremental. |
65 enum ServiceType { | 73 enum ServiceType { |
66 STUN, // Indicates a STUN server. | 74 STUN = 0, // Indicates a STUN server. |
67 STUNS, // Indicates a STUN server used with a TLS session. | 75 STUNS, // Indicates a STUN server used with a TLS session. |
68 TURN, // Indicates a TURN server | 76 TURN, // Indicates a TURN server |
69 TURNS, // Indicates a TURN server used with a TLS session. | 77 TURNS, // Indicates a TURN server used with a TLS session. |
70 INVALID, // Unknown. | 78 INVALID, // Unknown. |
71 }; | 79 }; |
| 80 static_assert(INVALID == ARRAY_SIZE(kValidIceServiceTypes), |
| 81 "kValidIceServiceTypes must have as many strings as ServiceType " |
| 82 "has values."); |
72 | 83 |
73 enum { | 84 enum { |
74 MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0, | 85 MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0, |
75 MSG_SET_SESSIONDESCRIPTION_FAILED, | 86 MSG_SET_SESSIONDESCRIPTION_FAILED, |
76 MSG_GETSTATS, | 87 MSG_GETSTATS, |
77 }; | 88 }; |
78 | 89 |
79 struct SetSessionDescriptionMsg : public rtc::MessageData { | 90 struct SetSessionDescriptionMsg : public rtc::MessageData { |
80 explicit SetSessionDescriptionMsg( | 91 explicit SetSessionDescriptionMsg( |
81 webrtc::SetSessionDescriptionObserver* observer) | 92 webrtc::SetSessionDescriptionObserver* observer) |
(...skipping 11 matching lines...) Expand all Loading... |
93 } | 104 } |
94 rtc::scoped_refptr<webrtc::StatsObserver> observer; | 105 rtc::scoped_refptr<webrtc::StatsObserver> observer; |
95 rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track; | 106 rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track; |
96 }; | 107 }; |
97 | 108 |
98 // |in_str| should be of format | 109 // |in_str| should be of format |
99 // stunURI = scheme ":" stun-host [ ":" stun-port ] | 110 // stunURI = scheme ":" stun-host [ ":" stun-port ] |
100 // scheme = "stun" / "stuns" | 111 // scheme = "stun" / "stuns" |
101 // stun-host = IP-literal / IPv4address / reg-name | 112 // stun-host = IP-literal / IPv4address / reg-name |
102 // stun-port = *DIGIT | 113 // stun-port = *DIGIT |
103 | 114 // |
104 // draft-petithuguenin-behave-turn-uris-01 | 115 // draft-petithuguenin-behave-turn-uris-01 |
105 // turnURI = scheme ":" turn-host [ ":" turn-port ] | 116 // turnURI = scheme ":" turn-host [ ":" turn-port ] |
106 // turn-host = username@IP-literal / IPv4address / reg-name | 117 // turn-host = username@IP-literal / IPv4address / reg-name |
107 bool GetServiceTypeAndHostnameFromUri(const std::string& in_str, | 118 bool GetServiceTypeAndHostnameFromUri(const std::string& in_str, |
108 ServiceType* service_type, | 119 ServiceType* service_type, |
109 std::string* hostname) { | 120 std::string* hostname) { |
110 const std::string::size_type colonpos = in_str.find(':'); | 121 const std::string::size_type colonpos = in_str.find(':'); |
111 if (colonpos == std::string::npos || (colonpos + 1) == in_str.length()) { | 122 if (colonpos == std::string::npos) { |
| 123 LOG(LS_WARNING) << "Missing ':' in ICE URI: " << in_str; |
112 return false; | 124 return false; |
113 } | 125 } |
114 std::string type = in_str.substr(0, colonpos); | 126 if ((colonpos + 1) == in_str.length()) { |
| 127 LOG(LS_WARNING) << "Empty hostname in ICE URI: " << in_str; |
| 128 return false; |
| 129 } |
| 130 *service_type = INVALID; |
115 for (size_t i = 0; i < ARRAY_SIZE(kValidIceServiceTypes); ++i) { | 131 for (size_t i = 0; i < ARRAY_SIZE(kValidIceServiceTypes); ++i) { |
116 if (type.compare(kValidIceServiceTypes[i]) == 0) { | 132 if (in_str.compare(0, colonpos, kValidIceServiceTypes[i]) == 0) { |
117 *service_type = static_cast<ServiceType>(i); | 133 *service_type = static_cast<ServiceType>(i); |
118 break; | 134 break; |
119 } | 135 } |
120 } | 136 } |
121 if (*service_type == INVALID) { | 137 if (*service_type == INVALID) { |
122 return false; | 138 return false; |
123 } | 139 } |
124 *hostname = in_str.substr(colonpos + 1, std::string::npos); | 140 *hostname = in_str.substr(colonpos + 1, std::string::npos); |
125 return true; | 141 return true; |
126 } | 142 } |
127 | 143 |
| 144 bool ParsePort(const std::string& in_str, int* port) { |
| 145 // Make sure port only contains digits. FromString doesn't check this. |
| 146 for (const char& c : in_str) { |
| 147 if (!std::isdigit(c)) { |
| 148 return false; |
| 149 } |
| 150 } |
| 151 return rtc::FromString(in_str, port); |
| 152 } |
| 153 |
128 // This method parses IPv6 and IPv4 literal strings, along with hostnames in | 154 // This method parses IPv6 and IPv4 literal strings, along with hostnames in |
129 // standard hostname:port format. | 155 // standard hostname:port format. |
130 // Consider following formats as correct. | 156 // Consider following formats as correct. |
131 // |hostname:port|, |[IPV6 address]:port|, |IPv4 address|:port, | 157 // |hostname:port|, |[IPV6 address]:port|, |IPv4 address|:port, |
132 // |hostname|, |[IPv6 address]|, |IPv4 address| | 158 // |hostname|, |[IPv6 address]|, |IPv4 address|. |
133 bool ParseHostnameAndPortFromString(const std::string& in_str, | 159 bool ParseHostnameAndPortFromString(const std::string& in_str, |
134 std::string* host, | 160 std::string* host, |
135 int* port) { | 161 int* port) { |
| 162 RTC_DCHECK(host->empty()); |
136 if (in_str.at(0) == '[') { | 163 if (in_str.at(0) == '[') { |
137 std::string::size_type closebracket = in_str.rfind(']'); | 164 std::string::size_type closebracket = in_str.rfind(']'); |
138 if (closebracket != std::string::npos) { | 165 if (closebracket != std::string::npos) { |
139 *host = in_str.substr(1, closebracket - 1); | |
140 std::string::size_type colonpos = in_str.find(':', closebracket); | 166 std::string::size_type colonpos = in_str.find(':', closebracket); |
141 if (std::string::npos != colonpos) { | 167 if (std::string::npos != colonpos) { |
142 if (!rtc::FromString( | 168 if (!ParsePort(in_str.substr(closebracket + 2, std::string::npos), |
143 in_str.substr(closebracket + 2, std::string::npos), port)) { | 169 port)) { |
144 return false; | 170 return false; |
145 } | 171 } |
146 } | 172 } |
| 173 *host = in_str.substr(1, closebracket - 1); |
147 } else { | 174 } else { |
148 return false; | 175 return false; |
149 } | 176 } |
150 } else { | 177 } else { |
151 std::string::size_type colonpos = in_str.find(':'); | 178 std::string::size_type colonpos = in_str.find(':'); |
152 if (std::string::npos != colonpos) { | 179 if (std::string::npos != colonpos) { |
153 *host = in_str.substr(0, colonpos); | 180 if (!ParsePort(in_str.substr(colonpos + 1, std::string::npos), port)) { |
154 if (!rtc::FromString( | |
155 in_str.substr(colonpos + 1, std::string::npos), port)) { | |
156 return false; | 181 return false; |
157 } | 182 } |
| 183 *host = in_str.substr(0, colonpos); |
158 } else { | 184 } else { |
159 *host = in_str; | 185 *host = in_str; |
160 } | 186 } |
161 } | 187 } |
162 return true; | 188 return !host->empty(); |
163 } | 189 } |
164 | 190 |
165 typedef webrtc::PortAllocatorFactoryInterface::StunConfiguration | 191 // Adds a StunConfiguration or TurnConfiguration to the appropriate list, |
166 StunConfiguration; | 192 // by parsing |url| and using the username/password in |server|. |
167 typedef webrtc::PortAllocatorFactoryInterface::TurnConfiguration | |
168 TurnConfiguration; | |
169 | |
170 bool ParseIceServerUrl(const PeerConnectionInterface::IceServer& server, | 193 bool ParseIceServerUrl(const PeerConnectionInterface::IceServer& server, |
171 const std::string& url, | 194 const std::string& url, |
172 std::vector<StunConfiguration>* stun_config, | 195 StunConfigurations* stun_config, |
173 std::vector<TurnConfiguration>* turn_config) { | 196 TurnConfigurations* turn_config) { |
174 // draft-nandakumar-rtcweb-stun-uri-01 | 197 // draft-nandakumar-rtcweb-stun-uri-01 |
175 // stunURI = scheme ":" stun-host [ ":" stun-port ] | 198 // stunURI = scheme ":" stun-host [ ":" stun-port ] |
176 // scheme = "stun" / "stuns" | 199 // scheme = "stun" / "stuns" |
177 // stun-host = IP-literal / IPv4address / reg-name | 200 // stun-host = IP-literal / IPv4address / reg-name |
178 // stun-port = *DIGIT | 201 // stun-port = *DIGIT |
179 | 202 |
180 // draft-petithuguenin-behave-turn-uris-01 | 203 // draft-petithuguenin-behave-turn-uris-01 |
181 // turnURI = scheme ":" turn-host [ ":" turn-port ] | 204 // turnURI = scheme ":" turn-host [ ":" turn-port ] |
182 // [ "?transport=" transport ] | 205 // [ "?transport=" transport ] |
183 // scheme = "turn" / "turns" | 206 // scheme = "turn" / "turns" |
184 // transport = "udp" / "tcp" / transport-ext | 207 // transport = "udp" / "tcp" / transport-ext |
185 // transport-ext = 1*unreserved | 208 // transport-ext = 1*unreserved |
186 // turn-host = IP-literal / IPv4address / reg-name | 209 // turn-host = IP-literal / IPv4address / reg-name |
187 // turn-port = *DIGIT | 210 // turn-port = *DIGIT |
| 211 RTC_DCHECK(stun_config != nullptr); |
| 212 RTC_DCHECK(turn_config != nullptr); |
188 std::vector<std::string> tokens; | 213 std::vector<std::string> tokens; |
189 std::string turn_transport_type = kUdpTransportType; | 214 std::string turn_transport_type = kUdpTransportType; |
190 ASSERT(!url.empty()); | 215 RTC_DCHECK(!url.empty()); |
191 rtc::tokenize(url, '?', &tokens); | 216 rtc::tokenize(url, '?', &tokens); |
192 std::string uri_without_transport = tokens[0]; | 217 std::string uri_without_transport = tokens[0]; |
193 // Let's look into transport= param, if it exists. | 218 // Let's look into transport= param, if it exists. |
194 if (tokens.size() == kTurnTransportTokensNum) { // ?transport= is present. | 219 if (tokens.size() == kTurnTransportTokensNum) { // ?transport= is present. |
195 std::string uri_transport_param = tokens[1]; | 220 std::string uri_transport_param = tokens[1]; |
196 rtc::tokenize(uri_transport_param, '=', &tokens); | 221 rtc::tokenize(uri_transport_param, '=', &tokens); |
197 if (tokens[0] == kTransport) { | 222 if (tokens[0] == kTransport) { |
198 // As per above grammar transport param will be consist of lower case | 223 // As per above grammar transport param will be consist of lower case |
199 // letters. | 224 // letters. |
200 if (tokens[1] != kUdpTransportType && tokens[1] != kTcpTransportType) { | 225 if (tokens[1] != kUdpTransportType && tokens[1] != kTcpTransportType) { |
201 LOG(LS_WARNING) << "Transport param should always be udp or tcp."; | 226 LOG(LS_WARNING) << "Transport param should always be udp or tcp."; |
202 return true; | 227 return false; |
203 } | 228 } |
204 turn_transport_type = tokens[1]; | 229 turn_transport_type = tokens[1]; |
205 } | 230 } |
206 } | 231 } |
207 | 232 |
208 std::string hoststring; | 233 std::string hoststring; |
209 ServiceType service_type = INVALID; | 234 ServiceType service_type; |
210 if (!GetServiceTypeAndHostnameFromUri(uri_without_transport, | 235 if (!GetServiceTypeAndHostnameFromUri(uri_without_transport, |
211 &service_type, | 236 &service_type, |
212 &hoststring)) { | 237 &hoststring)) { |
213 LOG(LS_WARNING) << "Invalid transport parameter in ICE URI: " | 238 LOG(LS_WARNING) << "Invalid transport parameter in ICE URI: " << url; |
214 << uri_without_transport; | 239 return false; |
215 return true; | |
216 } | 240 } |
217 | 241 |
218 ASSERT(!hoststring.empty()); | 242 // GetServiceTypeAndHostnameFromUri should never give an empty hoststring |
| 243 RTC_DCHECK(!hoststring.empty()); |
219 | 244 |
220 // Let's break hostname. | 245 // Let's break hostname. |
221 tokens.clear(); | 246 tokens.clear(); |
222 rtc::tokenize(hoststring, '@', &tokens); | 247 rtc::tokenize_with_empty_tokens(hoststring, '@', &tokens); |
223 ASSERT(!tokens.empty()); | 248 |
224 std::string username(server.username); | 249 std::string username(server.username); |
225 // TODO(pthatcher): What's the right thing to do if tokens.size() is >2? | 250 if (tokens.size() > kTurnHostTokensNum) { |
226 // E.g. a string like "foo@bar@bat". | 251 LOG(LS_WARNING) << "Invalid user@hostname format: " << hoststring; |
227 if (tokens.size() >= kTurnHostTokensNum) { | 252 return false; |
| 253 } |
| 254 if (tokens.size() == kTurnHostTokensNum) { |
| 255 if (tokens[0].empty() || tokens[1].empty()) { |
| 256 LOG(LS_WARNING) << "Invalid user@hostname format: " << hoststring; |
| 257 return false; |
| 258 } |
228 username.assign(rtc::s_url_decode(tokens[0])); | 259 username.assign(rtc::s_url_decode(tokens[0])); |
229 hoststring = tokens[1]; | 260 hoststring = tokens[1]; |
230 } else { | 261 } else { |
231 hoststring = tokens[0]; | 262 hoststring = tokens[0]; |
232 } | 263 } |
233 | 264 |
234 int port = kDefaultStunPort; | 265 int port = kDefaultStunPort; |
235 if (service_type == TURNS) { | 266 if (service_type == TURNS) { |
236 port = kDefaultStunTlsPort; | 267 port = kDefaultStunTlsPort; |
237 turn_transport_type = kTcpTransportType; | 268 turn_transport_type = kTcpTransportType; |
238 } | 269 } |
239 | 270 |
240 std::string address; | 271 std::string address; |
241 if (!ParseHostnameAndPortFromString(hoststring, &address, &port)) { | 272 if (!ParseHostnameAndPortFromString(hoststring, &address, &port)) { |
242 LOG(WARNING) << "Invalid Hostname format: " << uri_without_transport; | 273 LOG(WARNING) << "Invalid hostname format: " << uri_without_transport; |
243 return true; | 274 return false; |
244 } | 275 } |
245 | 276 |
246 if (port <= 0 || port > 0xffff) { | 277 if (port <= 0 || port > 0xffff) { |
247 LOG(WARNING) << "Invalid port: " << port; | 278 LOG(WARNING) << "Invalid port: " << port; |
248 return true; | 279 return false; |
249 } | 280 } |
250 | 281 |
251 switch (service_type) { | 282 switch (service_type) { |
252 case STUN: | 283 case STUN: |
253 case STUNS: | 284 case STUNS: |
254 stun_config->push_back(StunConfiguration(address, port)); | 285 stun_config->push_back(StunConfiguration(address, port)); |
255 break; | 286 break; |
256 case TURN: | 287 case TURN: |
257 case TURNS: { | 288 case TURNS: { |
258 if (username.empty()) { | |
259 // Turn url example from the spec |url:"turn:user@turn.example.org"|. | |
260 std::vector<std::string> turn_tokens; | |
261 rtc::tokenize(address, '@', &turn_tokens); | |
262 if (turn_tokens.size() == kTurnHostTokensNum) { | |
263 username.assign(rtc::s_url_decode(turn_tokens[0])); | |
264 address = turn_tokens[1]; | |
265 } | |
266 } | |
267 | |
268 bool secure = (service_type == TURNS); | 289 bool secure = (service_type == TURNS); |
269 | |
270 turn_config->push_back(TurnConfiguration(address, port, | 290 turn_config->push_back(TurnConfiguration(address, port, |
271 username, | 291 username, |
272 server.password, | 292 server.password, |
273 turn_transport_type, | 293 turn_transport_type, |
274 secure)); | 294 secure)); |
275 break; | 295 break; |
276 } | 296 } |
277 case INVALID: | 297 case INVALID: |
278 default: | 298 default: |
279 LOG(WARNING) << "Configuration not supported: " << url; | 299 LOG(WARNING) << "Configuration not supported: " << url; |
280 return false; | 300 return false; |
281 } | 301 } |
282 return true; | 302 return true; |
283 } | 303 } |
284 | 304 |
| 305 } // namespace |
| 306 |
| 307 namespace webrtc { |
| 308 |
285 bool ParseIceServers(const PeerConnectionInterface::IceServers& servers, | 309 bool ParseIceServers(const PeerConnectionInterface::IceServers& servers, |
286 std::vector<StunConfiguration>* stun_config, | 310 StunConfigurations* stun_config, |
287 std::vector<TurnConfiguration>* turn_config) { | 311 TurnConfigurations* turn_config) { |
288 for (const webrtc::PeerConnectionInterface::IceServer& server : servers) { | 312 for (const webrtc::PeerConnectionInterface::IceServer& server : servers) { |
289 if (!server.urls.empty()) { | 313 if (!server.urls.empty()) { |
290 for (const std::string& url : server.urls) { | 314 for (const std::string& url : server.urls) { |
291 if (url.empty()) { | 315 if (url.empty()) { |
292 LOG(WARNING) << "Empty uri."; | 316 LOG(LS_ERROR) << "Empty uri."; |
293 continue; | 317 return false; |
294 } | 318 } |
295 if (!ParseIceServerUrl(server, url, stun_config, turn_config)) { | 319 if (!ParseIceServerUrl(server, url, stun_config, turn_config)) { |
296 return false; | 320 return false; |
297 } | 321 } |
298 } | 322 } |
299 } else if (!server.uri.empty()) { | 323 } else if (!server.uri.empty()) { |
300 // Fallback to old .uri if new .urls isn't present. | 324 // Fallback to old .uri if new .urls isn't present. |
301 if (!ParseIceServerUrl(server, server.uri, stun_config, turn_config)) { | 325 if (!ParseIceServerUrl(server, server.uri, stun_config, turn_config)) { |
302 return false; | 326 return false; |
303 } | 327 } |
304 } else { | 328 } else { |
305 LOG(WARNING) << "Empty uri."; | 329 LOG(LS_ERROR) << "Empty uri."; |
| 330 return false; |
306 } | 331 } |
307 } | 332 } |
308 return true; | 333 return true; |
309 } | 334 } |
310 | 335 |
311 // Check if we can send |new_stream| on a PeerConnection. | 336 // Check if we can send |new_stream| on a PeerConnection. |
312 // Currently only one audio but multiple video track is supported per | 337 // Currently only one audio but multiple video track is supported per |
313 // PeerConnection. | 338 // PeerConnection. |
314 bool CanAddLocalMediaStream(webrtc::StreamCollectionInterface* current_streams, | 339 bool CanAddLocalMediaStream(webrtc::StreamCollectionInterface* current_streams, |
315 webrtc::MediaStreamInterface* new_stream) { | 340 webrtc::MediaStreamInterface* new_stream) { |
316 if (!new_stream || !current_streams) | 341 if (!new_stream || !current_streams) |
317 return false; | 342 return false; |
318 if (current_streams->find(new_stream->label()) != NULL) { | 343 if (current_streams->find(new_stream->label()) != NULL) { |
319 LOG(LS_ERROR) << "MediaStream with label " << new_stream->label() | 344 LOG(LS_ERROR) << "MediaStream with label " << new_stream->label() |
320 << " is already added."; | 345 << " is already added."; |
321 return false; | 346 return false; |
322 } | 347 } |
323 | 348 |
324 return true; | 349 return true; |
325 } | 350 } |
326 | 351 |
327 } // namespace | |
328 | |
329 namespace webrtc { | |
330 | |
331 PeerConnection::PeerConnection(PeerConnectionFactory* factory) | 352 PeerConnection::PeerConnection(PeerConnectionFactory* factory) |
332 : factory_(factory), | 353 : factory_(factory), |
333 observer_(NULL), | 354 observer_(NULL), |
334 uma_observer_(NULL), | 355 uma_observer_(NULL), |
335 signaling_state_(kStable), | 356 signaling_state_(kStable), |
336 ice_state_(kIceNew), | 357 ice_state_(kIceNew), |
337 ice_connection_state_(kIceConnectionNew), | 358 ice_connection_state_(kIceConnectionNew), |
338 ice_gathering_state_(kIceGatheringNew) { | 359 ice_gathering_state_(kIceGatheringNew) { |
339 } | 360 } |
340 | 361 |
341 PeerConnection::~PeerConnection() { | 362 PeerConnection::~PeerConnection() { |
342 ASSERT(signaling_thread()->IsCurrent()); | 363 RTC_DCHECK(signaling_thread()->IsCurrent()); |
343 if (mediastream_signaling_) { | 364 if (mediastream_signaling_) { |
344 mediastream_signaling_->TearDown(); | 365 mediastream_signaling_->TearDown(); |
345 } | 366 } |
346 // Need to detach RTP senders/receivers from WebRtcSession, | 367 // Need to detach RTP senders/receivers from WebRtcSession, |
347 // since it's about to be destroyed. | 368 // since it's about to be destroyed. |
348 for (const auto& sender : senders_) { | 369 for (const auto& sender : senders_) { |
349 sender->Stop(); | 370 sender->Stop(); |
350 } | 371 } |
351 for (const auto& receiver : receivers_) { | 372 for (const auto& receiver : receivers_) { |
352 receiver->Stop(); | 373 receiver->Stop(); |
353 } | 374 } |
354 } | 375 } |
355 | 376 |
356 bool PeerConnection::Initialize( | 377 bool PeerConnection::Initialize( |
357 const PeerConnectionInterface::RTCConfiguration& configuration, | 378 const PeerConnectionInterface::RTCConfiguration& configuration, |
358 const MediaConstraintsInterface* constraints, | 379 const MediaConstraintsInterface* constraints, |
359 PortAllocatorFactoryInterface* allocator_factory, | 380 PortAllocatorFactoryInterface* allocator_factory, |
360 rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, | 381 rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, |
361 PeerConnectionObserver* observer) { | 382 PeerConnectionObserver* observer) { |
362 ASSERT(observer != NULL); | 383 RTC_DCHECK(observer != NULL); |
363 if (!observer) | 384 if (!observer) |
364 return false; | 385 return false; |
365 observer_ = observer; | 386 observer_ = observer; |
366 | 387 |
367 std::vector<PortAllocatorFactoryInterface::StunConfiguration> stun_config; | 388 std::vector<PortAllocatorFactoryInterface::StunConfiguration> stun_config; |
368 std::vector<PortAllocatorFactoryInterface::TurnConfiguration> turn_config; | 389 std::vector<PortAllocatorFactoryInterface::TurnConfiguration> turn_config; |
369 if (!ParseIceServers(configuration.servers, &stun_config, &turn_config)) { | 390 if (!ParseIceServers(configuration.servers, &stun_config, &turn_config)) { |
370 return false; | 391 return false; |
371 } | 392 } |
372 port_allocator_.reset( | 393 port_allocator_.reset( |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 for (const auto& receiver : receivers_) { | 512 for (const auto& receiver : receivers_) { |
492 receivers.push_back( | 513 receivers.push_back( |
493 RtpReceiverProxy::Create(signaling_thread(), receiver.get())); | 514 RtpReceiverProxy::Create(signaling_thread(), receiver.get())); |
494 } | 515 } |
495 return receivers; | 516 return receivers; |
496 } | 517 } |
497 | 518 |
498 bool PeerConnection::GetStats(StatsObserver* observer, | 519 bool PeerConnection::GetStats(StatsObserver* observer, |
499 MediaStreamTrackInterface* track, | 520 MediaStreamTrackInterface* track, |
500 StatsOutputLevel level) { | 521 StatsOutputLevel level) { |
501 ASSERT(signaling_thread()->IsCurrent()); | 522 RTC_DCHECK(signaling_thread()->IsCurrent()); |
502 if (!VERIFY(observer != NULL)) { | 523 if (!VERIFY(observer != NULL)) { |
503 LOG(LS_ERROR) << "GetStats - observer is NULL."; | 524 LOG(LS_ERROR) << "GetStats - observer is NULL."; |
504 return false; | 525 return false; |
505 } | 526 } |
506 | 527 |
507 stats_->UpdateStats(level); | 528 stats_->UpdateStats(level); |
508 signaling_thread()->Post(this, MSG_GETSTATS, | 529 signaling_thread()->Post(this, MSG_GETSTATS, |
509 new GetStatsMsg(observer, track)); | 530 new GetStatsMsg(observer, track)); |
510 return true; | 531 return true; |
511 } | 532 } |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
813 } | 834 } |
814 case MSG_GETSTATS: { | 835 case MSG_GETSTATS: { |
815 GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata); | 836 GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata); |
816 StatsReports reports; | 837 StatsReports reports; |
817 stats_->GetStats(param->track, &reports); | 838 stats_->GetStats(param->track, &reports); |
818 param->observer->OnComplete(reports); | 839 param->observer->OnComplete(reports); |
819 delete param; | 840 delete param; |
820 break; | 841 break; |
821 } | 842 } |
822 default: | 843 default: |
823 ASSERT(false && "Not implemented"); | 844 RTC_DCHECK(false && "Not implemented"); |
824 break; | 845 break; |
825 } | 846 } |
826 } | 847 } |
827 | 848 |
828 void PeerConnection::OnAddRemoteStream(MediaStreamInterface* stream) { | 849 void PeerConnection::OnAddRemoteStream(MediaStreamInterface* stream) { |
829 stats_->AddStream(stream); | 850 stats_->AddStream(stream); |
830 observer_->OnAddStream(stream); | 851 observer_->OnAddStream(stream); |
831 } | 852 } |
832 | 853 |
833 void PeerConnection::OnRemoveRemoteStream(MediaStreamInterface* stream) { | 854 void PeerConnection::OnRemoveRemoteStream(MediaStreamInterface* stream) { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
920 (*it)->Stop(); | 941 (*it)->Stop(); |
921 senders_.erase(it); | 942 senders_.erase(it); |
922 } | 943 } |
923 } | 944 } |
924 | 945 |
925 void PeerConnection::OnRemoveLocalStream(MediaStreamInterface* stream) { | 946 void PeerConnection::OnRemoveLocalStream(MediaStreamInterface* stream) { |
926 } | 947 } |
927 | 948 |
928 void PeerConnection::OnIceConnectionChange( | 949 void PeerConnection::OnIceConnectionChange( |
929 PeerConnectionInterface::IceConnectionState new_state) { | 950 PeerConnectionInterface::IceConnectionState new_state) { |
930 ASSERT(signaling_thread()->IsCurrent()); | 951 RTC_DCHECK(signaling_thread()->IsCurrent()); |
931 // After transitioning to "closed", ignore any additional states from | 952 // After transitioning to "closed", ignore any additional states from |
932 // WebRtcSession (such as "disconnected"). | 953 // WebRtcSession (such as "disconnected"). |
933 if (ice_connection_state_ == kIceConnectionClosed) { | 954 if (ice_connection_state_ == kIceConnectionClosed) { |
934 return; | 955 return; |
935 } | 956 } |
936 ice_connection_state_ = new_state; | 957 ice_connection_state_ = new_state; |
937 observer_->OnIceConnectionChange(ice_connection_state_); | 958 observer_->OnIceConnectionChange(ice_connection_state_); |
938 } | 959 } |
939 | 960 |
940 void PeerConnection::OnIceGatheringChange( | 961 void PeerConnection::OnIceGatheringChange( |
941 PeerConnectionInterface::IceGatheringState new_state) { | 962 PeerConnectionInterface::IceGatheringState new_state) { |
942 ASSERT(signaling_thread()->IsCurrent()); | 963 RTC_DCHECK(signaling_thread()->IsCurrent()); |
943 if (IsClosed()) { | 964 if (IsClosed()) { |
944 return; | 965 return; |
945 } | 966 } |
946 ice_gathering_state_ = new_state; | 967 ice_gathering_state_ = new_state; |
947 observer_->OnIceGatheringChange(ice_gathering_state_); | 968 observer_->OnIceGatheringChange(ice_gathering_state_); |
948 } | 969 } |
949 | 970 |
950 void PeerConnection::OnIceCandidate(const IceCandidateInterface* candidate) { | 971 void PeerConnection::OnIceCandidate(const IceCandidateInterface* candidate) { |
951 ASSERT(signaling_thread()->IsCurrent()); | 972 RTC_DCHECK(signaling_thread()->IsCurrent()); |
952 observer_->OnIceCandidate(candidate); | 973 observer_->OnIceCandidate(candidate); |
953 } | 974 } |
954 | 975 |
955 void PeerConnection::OnIceComplete() { | 976 void PeerConnection::OnIceComplete() { |
956 ASSERT(signaling_thread()->IsCurrent()); | 977 RTC_DCHECK(signaling_thread()->IsCurrent()); |
957 observer_->OnIceComplete(); | 978 observer_->OnIceComplete(); |
958 } | 979 } |
959 | 980 |
960 void PeerConnection::OnIceConnectionReceivingChange(bool receiving) { | 981 void PeerConnection::OnIceConnectionReceivingChange(bool receiving) { |
961 ASSERT(signaling_thread()->IsCurrent()); | 982 RTC_DCHECK(signaling_thread()->IsCurrent()); |
962 observer_->OnIceConnectionReceivingChange(receiving); | 983 observer_->OnIceConnectionReceivingChange(receiving); |
963 } | 984 } |
964 | 985 |
965 void PeerConnection::ChangeSignalingState( | 986 void PeerConnection::ChangeSignalingState( |
966 PeerConnectionInterface::SignalingState signaling_state) { | 987 PeerConnectionInterface::SignalingState signaling_state) { |
967 signaling_state_ = signaling_state; | 988 signaling_state_ = signaling_state; |
968 if (signaling_state == kClosed) { | 989 if (signaling_state == kClosed) { |
969 ice_connection_state_ = kIceConnectionClosed; | 990 ice_connection_state_ = kIceConnectionClosed; |
970 observer_->OnIceConnectionChange(ice_connection_state_); | 991 observer_->OnIceConnectionChange(ice_connection_state_); |
971 if (ice_gathering_state_ != kIceGatheringComplete) { | 992 if (ice_gathering_state_ != kIceGatheringComplete) { |
(...skipping 17 matching lines...) Expand all Loading... |
989 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>::iterator | 1010 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>::iterator |
990 PeerConnection::FindReceiverForTrack(MediaStreamTrackInterface* track) { | 1011 PeerConnection::FindReceiverForTrack(MediaStreamTrackInterface* track) { |
991 return std::find_if( | 1012 return std::find_if( |
992 receivers_.begin(), receivers_.end(), | 1013 receivers_.begin(), receivers_.end(), |
993 [track](const rtc::scoped_refptr<RtpReceiverInterface>& receiver) { | 1014 [track](const rtc::scoped_refptr<RtpReceiverInterface>& receiver) { |
994 return receiver->track() == track; | 1015 return receiver->track() == track; |
995 }); | 1016 }); |
996 } | 1017 } |
997 | 1018 |
998 } // namespace webrtc | 1019 } // namespace webrtc |
OLD | NEW |