1 /*
2  * libjingle
3  * Copyright 2011, Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
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,
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
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "talk/app/webrtc/peerconnectionimpl.h"
29 
30 #include <vector>
31 
32 #include "talk/app/webrtc/mediastreamhandler.h"
33 #include "talk/app/webrtc/streamcollectionimpl.h"
34 #include "talk/base/logging.h"
35 #include "talk/base/stringencode.h"
36 #include "talk/session/phone/channelmanager.h"
37 #include "talk/session/phone/webrtcvideocapturer.h"
38 
39 namespace {
40 
41 // The number of the tokens in the config string.
42 static const size_t kConfigTokens = 2;
43 // Only the STUN or TURN server address appears in the config string.
44 static const size_t kConfigAddress = 1;
45 // Both of the STUN or TURN server address and port appear in the config string.
46 static const size_t kConfigAddressAndPort = 2;
47 static const size_t kServiceCount = 5;
48 // The default stun port.
49 static const int kDefaultPort = 3478;
50 
51 // NOTE: Must be in the same order as the ServiceType enum.
52 static const char* kValidServiceTypes[kServiceCount] = {
53     "STUN", "STUNS", "TURN", "TURNS", "INVALID" };
54 
55 enum ServiceType {
56   STUN,     // Indicates a STUN server.
57   STUNS,    // Indicates a STUN server used with a TLS session.
58   TURN,     // Indicates a TURN server
59   TURNS,    // Indicates a TURN server used with a TLS session.
60   INVALID,  // Unknown.
61 };
62 
63 enum {
64   MSG_ADDSTREAM = 1,
65   MSG_REMOVESTREAM = 2,
66   MSG_COMMITSTREAMCHANGES = 3,
67   MSG_PROCESSSIGNALINGMESSAGE = 4,
68   MSG_RETURNLOCALMEDIASTREAMS = 5,
69   MSG_RETURNREMOTEMEDIASTREAMS = 6,
70   MSG_CLOSE = 7,
71   MSG_READYSTATE = 8,
72   MSG_SDPSTATE = 9,
73   MSG_TERMINATE = 10,
74   MSG_STARTICE = 11,
75   MSG_CREATEOFFER = 12,
76   MSG_CREATEANSWER = 13,
77   MSG_SETLOCALDESCRIPTION = 14,
78   MSG_SETREMOTEDESCRIPTION = 15,
79   MSG_PROCESSICEMESSAGE = 16,
80   MSG_GETLOCALDESCRIPTION = 17,
81   MSG_GETREMOTEDESCRIPTION = 18,
82 };
83 
84 typedef webrtc::PortAllocatorFactoryInterface::StunConfiguration
85     StunConfiguration;
86 typedef webrtc::PortAllocatorFactoryInterface::TurnConfiguration
87     TurnConfiguration;
88 
ParseConfigString(const std::string & config,std::vector<StunConfiguration> * stun_config,std::vector<TurnConfiguration> * turn_config)89 bool static ParseConfigString(const std::string& config,
90                               std::vector<StunConfiguration>* stun_config,
91                               std::vector<TurnConfiguration>* turn_config) {
92   std::vector<std::string> tokens;
93   talk_base::tokenize(config, ' ', &tokens);
94 
95   if (tokens.size() != kConfigTokens) {
96     LOG(WARNING) << "Invalid config string";
97     return false;
98   }
99 
100   ServiceType service_type = INVALID;
101 
102   const std::string& type = tokens[0];
103   for (size_t i = 0; i < kServiceCount; ++i) {
104     if (type.compare(kValidServiceTypes[i]) == 0) {
105       service_type = static_cast<ServiceType>(i);
106       break;
107     }
108   }
109 
110   if (service_type == INVALID) {
111     LOG(WARNING) << "Invalid service type: " << type;
112     return false;
113   }
114   std::string service_address = tokens[1];
115 
116   std::string address;
117   int port;
118   tokens.clear();
119   talk_base::tokenize(service_address, ':', &tokens);
120   if (tokens.size() != kConfigAddress &&
121       tokens.size() != kConfigAddressAndPort) {
122     LOG(WARNING) << "Invalid server address and port: " << service_address;
123     return false;
124   }
125 
126   if (tokens.size() == kConfigAddress) {
127     address = tokens[0];
128     port = kDefaultPort;
129   } else {
130     address = tokens[0];
131     port = talk_base::FromString<int>(tokens[1]);
132     if (port <= 0 || port > 0xffff) {
133       LOG(WARNING) << "Invalid port: " << tokens[1];
134       return false;
135     }
136   }
137 
138   // TODO: Currently the specification does not tell us how to parse
139   // multiple addresses, username and password from the configuration string.
140   switch (service_type) {
141     case STUN:
142       stun_config->push_back(StunConfiguration(address, port));
143       break;
144     case TURN:
145       turn_config->push_back(TurnConfiguration(address, port, "", ""));
146       break;
147     case TURNS:
148     case STUNS:
149     case INVALID:
150     default:
151       LOG(WARNING) << "Configuration not supported";
152       return false;
153   }
154   return true;
155 }
156 
157 typedef talk_base::TypedMessageData<webrtc::LocalMediaStreamInterface*>
158     LocalMediaStreamParams;
159 
160 typedef talk_base::TypedMessageData<std::string> RoapSignalingParams;
161 
162 struct IceOptionsParams : public talk_base::MessageData {
IceOptionsParams__anone447ef7e0111::IceOptionsParams163   explicit IceOptionsParams(webrtc::JsepInterface::IceOptions options)
164       : options(options),
165         result(false) {
166   }
167   webrtc::JsepInterface::IceOptions options;
168   bool result;
169 };
170 
171 struct JsepSessionDescriptionParams : public talk_base::MessageData {
JsepSessionDescriptionParams__anone447ef7e0111::JsepSessionDescriptionParams172   JsepSessionDescriptionParams()
173       : result(false),
174         desc(NULL),
175         const_desc(NULL) {}
176   bool result;
177   webrtc::MediaHints hints;
178   webrtc::JsepInterface::Action action;
179   webrtc::SessionDescriptionInterface* desc;
180   const webrtc::SessionDescriptionInterface* const_desc;
181 };
182 
183 struct JsepIceCandidateParams : public talk_base::MessageData {
JsepIceCandidateParams__anone447ef7e0111::JsepIceCandidateParams184   explicit JsepIceCandidateParams(
185       const webrtc::IceCandidateInterface* candidate)
186       : result(false),
187         candidate(candidate) {}
188   bool result;
189   const webrtc::IceCandidateInterface* candidate;
190 };
191 
192 struct StreamCollectionParams : public talk_base::MessageData {
StreamCollectionParams__anone447ef7e0111::StreamCollectionParams193   explicit StreamCollectionParams(webrtc::StreamCollectionInterface* streams)
194       : streams(streams) {}
195   talk_base::scoped_refptr<webrtc::StreamCollectionInterface> streams;
196 };
197 
198 struct MediaStreamParams : public talk_base::MessageData {
MediaStreamParams__anone447ef7e0111::MediaStreamParams199   explicit MediaStreamParams(webrtc::MediaStreamInterface* stream)
200       : stream(stream) {}
201   talk_base::scoped_refptr<webrtc::MediaStreamInterface> stream;
202 };
203 
204 struct ReadyStateMessage : public talk_base::MessageData {
ReadyStateMessage__anone447ef7e0111::ReadyStateMessage205   ReadyStateMessage() : state(webrtc::PeerConnectionInterface::kNew) {}
206   webrtc::PeerConnectionInterface::ReadyState state;
207 };
208 
209 struct SdpStateMessage : public talk_base::MessageData {
SdpStateMessage__anone447ef7e0111::SdpStateMessage210   SdpStateMessage() : state(webrtc::PeerConnectionInterface::kSdpNew) {}
211   webrtc::PeerConnectionInterface::SdpState state;
212 };
213 
214 }  // namespace
215 
216 namespace webrtc {
217 
CreateVideoCapturer(VideoCaptureModule * vcm)218 cricket::VideoCapturer* CreateVideoCapturer(VideoCaptureModule* vcm) {
219   cricket::WebRtcVideoCapturer* video_capturer =
220       new cricket::WebRtcVideoCapturer;
221   if (!video_capturer->Init(vcm)) {
222     delete video_capturer;
223     video_capturer = NULL;
224   }
225   return video_capturer;
226 }
227 
PeerConnection(PeerConnectionFactory * factory)228 PeerConnection::PeerConnection(PeerConnectionFactory* factory)
229     : factory_(factory),
230       observer_(NULL),
231       ready_state_(kNew),
232       sdp_state_(kSdpNew),
233       local_media_streams_(StreamCollection::Create()) {
234 }
235 
~PeerConnection()236 PeerConnection::~PeerConnection() {
237   signaling_thread()->Clear(this);
238   signaling_thread()->Send(this, MSG_TERMINATE);
239 }
240 
241 // Clean up what needs to be cleaned up on the signaling thread.
Terminate_s()242 void PeerConnection::Terminate_s() {
243   stream_handler_.reset();
244   roap_signaling_.reset();
245   mediastream_signaling_.reset();
246   session_.reset();
247   port_allocator_.reset();
248 }
249 
Initialize(bool use_roap,const std::string & configuration,PeerConnectionObserver * observer)250 bool PeerConnection::Initialize(bool use_roap,
251                                 const std::string& configuration,
252                                 PeerConnectionObserver* observer) {
253   ASSERT(observer != NULL);
254   if (!observer)
255     return false;
256   observer_ = observer;
257   std::vector<PortAllocatorFactoryInterface::StunConfiguration> stun_config;
258   std::vector<PortAllocatorFactoryInterface::TurnConfiguration> turn_config;
259 
260   ParseConfigString(configuration, &stun_config, &turn_config);
261 
262   port_allocator_.reset(factory_->port_allocator_factory()->CreatePortAllocator(
263       stun_config, turn_config));
264 
265   mediastream_signaling_.reset(new MediaStreamSignaling(
266       factory_->signaling_thread(), this));
267 
268   session_.reset(new WebRtcSession(factory_->channel_manager(),
269                                    factory_->signaling_thread(),
270                                    factory_->worker_thread(),
271                                    port_allocator_.get(),
272                                    mediastream_signaling_.get()));
273   stream_handler_.reset(new MediaStreamHandlers(session_.get()));
274 
275   // Initialize the WebRtcSession. It creates transport channels etc.
276   if (!session_->Initialize())
277     return false;
278 
279   if (use_roap) {
280     roap_signaling_.reset(new RoapSignaling(
281         mediastream_signaling_.get(),
282         session_.get()));
283     // Register Roap as receiver of local ice candidates.
284     session_->RegisterObserver(roap_signaling_.get());
285     roap_signaling_->SignalNewPeerConnectionMessage.connect(
286         this, &PeerConnection::OnNewPeerConnectionMessage);
287     roap_signaling_->SignalStateChange.connect(
288         this, &PeerConnection::OnSignalingStateChange);
289     ChangeReadyState(PeerConnectionInterface::kNegotiating);
290   } else {
291     // Register PeerConnection observer as receiver of local ice candidates.
292     session_->RegisterObserver(observer_);
293     session_->SignalState.connect(this, &PeerConnection::OnSessionStateChange);
294   }
295   return true;
296 }
297 
298 talk_base::scoped_refptr<StreamCollectionInterface>
local_streams()299 PeerConnection::local_streams() {
300   StreamCollectionParams msg(NULL);
301   signaling_thread()->Send(this, MSG_RETURNLOCALMEDIASTREAMS, &msg);
302   return msg.streams;
303 }
304 
305 talk_base::scoped_refptr<StreamCollectionInterface>
remote_streams()306 PeerConnection::remote_streams() {
307   StreamCollectionParams msg(NULL);
308   signaling_thread()->Send(this, MSG_RETURNREMOTEMEDIASTREAMS, &msg);
309   return msg.streams;
310 }
311 
ProcessSignalingMessage(const std::string & msg)312 void PeerConnection::ProcessSignalingMessage(const std::string& msg) {
313   RoapSignalingParams parameter(msg);
314   signaling_thread()->Send(this, MSG_PROCESSSIGNALINGMESSAGE, &parameter);
315 }
316 
AddStream(LocalMediaStreamInterface * local_stream)317 void PeerConnection::AddStream(LocalMediaStreamInterface* local_stream) {
318   LocalMediaStreamParams msg(local_stream);
319   signaling_thread()->Send(this, MSG_ADDSTREAM, &msg);
320 }
321 
RemoveStream(LocalMediaStreamInterface * remove_stream)322 void PeerConnection::RemoveStream(LocalMediaStreamInterface* remove_stream) {
323   LocalMediaStreamParams msg(remove_stream);
324   signaling_thread()->Send(this, MSG_REMOVESTREAM, &msg);
325 }
326 
CommitStreamChanges()327 void PeerConnection::CommitStreamChanges() {
328   signaling_thread()->Send(this, MSG_COMMITSTREAMCHANGES);
329 }
330 
Close()331 void PeerConnection::Close() {
332   signaling_thread()->Send(this, MSG_CLOSE);
333 }
334 
ready_state()335 PeerConnectionInterface::ReadyState PeerConnection::ready_state() {
336   ReadyStateMessage msg;
337   signaling_thread()->Send(this, MSG_READYSTATE, &msg);
338   return msg.state;
339 }
340 
sdp_state()341 PeerConnectionInterface::SdpState PeerConnection::sdp_state() {
342   SdpStateMessage msg;
343   signaling_thread()->Send(this, MSG_SDPSTATE, &msg);
344   return msg.state;
345 }
346 
StartIce(IceOptions options)347 bool PeerConnection::StartIce(IceOptions options) {
348   IceOptionsParams msg(options);
349   signaling_thread()->Send(this, MSG_STARTICE, &msg);
350   return msg.result;
351 }
352 
CreateOffer(const MediaHints & hints)353 SessionDescriptionInterface* PeerConnection::CreateOffer(
354     const MediaHints& hints) {
355   JsepSessionDescriptionParams msg;
356   msg.hints = hints;
357   signaling_thread()->Send(this, MSG_CREATEOFFER, &msg);
358   return msg.desc;
359 }
360 
CreateAnswer(const MediaHints & hints,const SessionDescriptionInterface * offer)361 SessionDescriptionInterface* PeerConnection::CreateAnswer(
362     const MediaHints& hints,
363     const SessionDescriptionInterface* offer) {
364   JsepSessionDescriptionParams msg;
365   msg.hints = hints;
366   msg.const_desc = offer;
367   signaling_thread()->Send(this, MSG_CREATEANSWER, &msg);
368   return msg.desc;
369 }
370 
SetLocalDescription(Action action,SessionDescriptionInterface * desc)371 bool PeerConnection::SetLocalDescription(Action action,
372                                          SessionDescriptionInterface* desc) {
373   JsepSessionDescriptionParams msg;
374   msg.action = action;
375   msg.desc = desc;
376   signaling_thread()->Send(this, MSG_SETLOCALDESCRIPTION, &msg);
377   return msg.result;
378 }
379 
SetRemoteDescription(Action action,SessionDescriptionInterface * desc)380 bool PeerConnection::SetRemoteDescription(Action action,
381                                           SessionDescriptionInterface* desc) {
382   JsepSessionDescriptionParams msg;
383   msg.action = action;
384   msg.desc = desc;
385   signaling_thread()->Send(this, MSG_SETREMOTEDESCRIPTION, &msg);
386   return msg.result;
387 }
388 
ProcessIceMessage(const IceCandidateInterface * ice_candidate)389 bool PeerConnection::ProcessIceMessage(
390     const IceCandidateInterface* ice_candidate) {
391   JsepIceCandidateParams msg(ice_candidate);
392   signaling_thread()->Send(this, MSG_PROCESSICEMESSAGE, &msg);
393   return msg.result;
394 }
395 
local_description() const396 const SessionDescriptionInterface* PeerConnection::local_description() const {
397   JsepSessionDescriptionParams msg;
398   signaling_thread()->Send(const_cast<PeerConnection*>(this),
399                            MSG_GETLOCALDESCRIPTION, &msg);
400   return msg.const_desc;
401 }
402 
remote_description() const403 const SessionDescriptionInterface* PeerConnection::remote_description() const {
404   JsepSessionDescriptionParams msg;
405   signaling_thread()->Send(const_cast<PeerConnection*>(this),
406                            MSG_GETREMOTEDESCRIPTION, &msg);
407   return msg.const_desc;
408 }
409 
OnMessage(talk_base::Message * msg)410 void PeerConnection::OnMessage(talk_base::Message* msg) {
411   talk_base::MessageData* data = msg->pdata;
412   switch (msg->message_id) {
413     case MSG_ADDSTREAM: {
414       LocalMediaStreamParams* msg(static_cast<LocalMediaStreamParams*> (data));
415       local_media_streams_->AddStream(msg->data());
416       break;
417     }
418     case MSG_REMOVESTREAM: {
419       LocalMediaStreamParams* msg(static_cast<LocalMediaStreamParams*> (data));
420       local_media_streams_->RemoveStream(msg->data());
421       break;
422     }
423     case MSG_COMMITSTREAMCHANGES: {
424       if (ready_state_ != PeerConnectionInterface::kClosed ||
425           ready_state_ != PeerConnectionInterface::kClosing) {
426         mediastream_signaling_->SetLocalStreams(local_media_streams_);
427         // If we use ROAP an offer is created and we setup the local
428         // media streams.
429         if (roap_signaling_.get() != NULL) {
430           roap_signaling_->CreateOffer(local_media_streams_);
431           stream_handler_->CommitLocalStreams(local_media_streams_);
432         }
433       }
434       break;
435     }
436     case MSG_PROCESSSIGNALINGMESSAGE: {
437       if (ready_state_ != PeerConnectionInterface::kClosed &&
438           roap_signaling_.get() != NULL)  {
439         RoapSignalingParams* params(static_cast<RoapSignalingParams*> (data));
440         roap_signaling_->ProcessSignalingMessage(params->data(),
441                                                  local_media_streams_);
442       }
443       break;
444     }
445     case MSG_RETURNLOCALMEDIASTREAMS: {
446       StreamCollectionParams* param(
447           static_cast<StreamCollectionParams*> (data));
448       param->streams = StreamCollection::Create(local_media_streams_);
449       break;
450     }
451     case MSG_RETURNREMOTEMEDIASTREAMS: {
452       StreamCollectionParams* param(
453           static_cast<StreamCollectionParams*> (data));
454       param->streams = mediastream_signaling_->remote_streams();
455       break;
456     }
457     case MSG_CLOSE: {
458       if (ready_state_ != PeerConnectionInterface::kClosed &&
459           roap_signaling_.get() != NULL)  {
460         ChangeReadyState(PeerConnectionInterface::kClosing);
461         roap_signaling_->SendShutDown();
462       }
463       break;
464     }
465     case MSG_READYSTATE: {
466       ReadyStateMessage* msg(static_cast<ReadyStateMessage*> (data));
467       msg->state = ready_state_;
468       break;
469     }
470     case MSG_SDPSTATE: {
471       SdpStateMessage* msg(static_cast<SdpStateMessage*> (data));
472       msg->state = sdp_state_;
473       break;
474     }
475     case MSG_STARTICE: {
476       if (ready_state_ != PeerConnectionInterface::kClosed &&
477           ready_state_ != PeerConnectionInterface::kClosing) {
478         IceOptionsParams* param(
479                     static_cast<IceOptionsParams*> (data));
480         param->result = session_->StartIce(param->options);
481       }
482       break;
483     }
484     case MSG_CREATEOFFER: {
485       if (ready_state_ != PeerConnectionInterface::kClosed &&
486           ready_state_ != PeerConnectionInterface::kClosing) {
487         JsepSessionDescriptionParams* param(
488             static_cast<JsepSessionDescriptionParams*> (data));
489         param->desc = session_->CreateOffer(param->hints);
490       }
491       break;
492     }
493     case MSG_CREATEANSWER: {
494       if (ready_state_ != PeerConnectionInterface::kClosed &&
495           ready_state_ != PeerConnectionInterface::kClosing) {
496         JsepSessionDescriptionParams* param(
497             static_cast<JsepSessionDescriptionParams*> (data));
498         param->desc = session_->CreateAnswer(param->hints,
499                                              param->const_desc);
500       }
501       break;
502     }
503     case MSG_SETLOCALDESCRIPTION: {
504       if (ready_state_ != PeerConnectionInterface::kClosed &&
505           ready_state_ != PeerConnectionInterface::kClosing) {
506         JsepSessionDescriptionParams* param(
507             static_cast<JsepSessionDescriptionParams*> (data));
508         param->result  = session_->SetLocalDescription(param->action,
509                                                        param->desc);
510         stream_handler_->CommitLocalStreams(local_media_streams_);
511       }
512       break;
513     }
514     case MSG_SETREMOTEDESCRIPTION: {
515       if (ready_state_ != PeerConnectionInterface::kClosed &&
516           ready_state_ != PeerConnectionInterface::kClosing) {
517         JsepSessionDescriptionParams* param(
518             static_cast<JsepSessionDescriptionParams*> (data));
519         param->result  = session_->SetRemoteDescription(param->action,
520                                                         param->desc);
521       }
522       break;
523     }
524     case MSG_PROCESSICEMESSAGE: {
525       if (ready_state_ != PeerConnectionInterface::kClosed ||
526           ready_state_ != PeerConnectionInterface::kClosing) {
527         JsepIceCandidateParams * param(
528             static_cast<JsepIceCandidateParams*> (data));
529         param->result  = session_->ProcessIceMessage(param->candidate);
530       }
531       break;
532     }
533     case MSG_GETLOCALDESCRIPTION: {
534       JsepSessionDescriptionParams* param(
535           static_cast<JsepSessionDescriptionParams*> (data));
536       param->const_desc  = session_->local_description();
537       break;
538     }
539     case  MSG_GETREMOTEDESCRIPTION: {
540       JsepSessionDescriptionParams* param(
541           static_cast<JsepSessionDescriptionParams*> (data));
542       param->const_desc  = session_->remote_description();
543       break;
544     }
545     case MSG_TERMINATE: {
546       Terminate_s();
547       break;
548     }
549     default:
550       ASSERT(!"NOT IMPLEMENTED");
551       break;
552   }
553 }
554 
OnNewPeerConnectionMessage(const std::string & message)555 void PeerConnection::OnNewPeerConnectionMessage(const std::string& message) {
556   observer_->OnSignalingMessage(message);
557 }
558 
OnSignalingStateChange(RoapSignaling::State state)559 void PeerConnection::OnSignalingStateChange(
560     RoapSignaling::State state) {
561   switch (state) {
562     case RoapSignaling::kInitializing:
563       break;
564     case RoapSignaling::kIdle:
565       if (ready_state_ == PeerConnectionInterface::kNegotiating)
566         ChangeReadyState(PeerConnectionInterface::kActive);
567       ChangeSdpState(PeerConnectionInterface::kSdpIdle);
568       break;
569     case RoapSignaling::kWaitingForAnswer:
570       ChangeSdpState(PeerConnectionInterface::kSdpWaiting);
571       break;
572     case RoapSignaling::kWaitingForOK:
573       ChangeSdpState(PeerConnectionInterface::kSdpWaiting);
574       break;
575     case RoapSignaling::kShutingDown:
576       ChangeReadyState(PeerConnectionInterface::kClosing);
577       break;
578     case RoapSignaling::kShutdownComplete:
579       ChangeReadyState(PeerConnectionInterface::kClosed);
580       signaling_thread()->Post(this, MSG_TERMINATE);
581       break;
582     default:
583       ASSERT(!"NOT IMPLEMENTED");
584       break;
585   }
586 }
587 
OnSessionStateChange(cricket::BaseSession *,cricket::BaseSession::State state)588 void PeerConnection::OnSessionStateChange(cricket::BaseSession* /*session*/,
589                                           cricket::BaseSession::State state) {
590   switch (state) {
591     case cricket::BaseSession::STATE_INIT:
592       ChangeReadyState(PeerConnectionInterface::kNew);
593     case cricket::BaseSession::STATE_SENTINITIATE:
594     case cricket::BaseSession::STATE_RECEIVEDINITIATE:
595       ChangeReadyState(PeerConnectionInterface::kNegotiating);
596       break;
597     case cricket::BaseSession::STATE_SENTACCEPT:
598     case cricket::BaseSession::STATE_RECEIVEDACCEPT:
599       ChangeReadyState(PeerConnectionInterface::kActive);
600       break;
601     default:
602       break;
603   }
604 }
605 
OnAddStream(MediaStreamInterface * stream)606 void PeerConnection::OnAddStream(MediaStreamInterface* stream) {
607   stream_handler_->AddRemoteStream(stream);
608   observer_->OnAddStream(stream);
609 }
610 
OnRemoveStream(MediaStreamInterface * stream)611 void PeerConnection::OnRemoveStream(MediaStreamInterface* stream) {
612   stream_handler_->RemoveRemoteStream(stream);
613   observer_->OnRemoveStream(stream);
614 }
615 
ChangeReadyState(PeerConnectionInterface::ReadyState ready_state)616 void PeerConnection::ChangeReadyState(
617     PeerConnectionInterface::ReadyState ready_state) {
618   ready_state_ = ready_state;
619   observer_->OnStateChange(PeerConnectionObserver::kReadyState);
620 }
621 
ChangeSdpState(PeerConnectionInterface::SdpState sdp_state)622 void PeerConnection::ChangeSdpState(
623     PeerConnectionInterface::SdpState sdp_state) {
624   sdp_state_ = sdp_state;
625   observer_->OnStateChange(PeerConnectionObserver::kSdpState);
626 }
627 
628 }  // namespace webrtc
629