blob: 90feed8f0aa0adee642d0d7f7f78c4ee398c9af4 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
Donald E Curtisa8736442015-08-05 15:48:13 -07002 * Copyright 2012 The WebRTC Project Authors. All rights reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
Donald E Curtisa8736442015-08-05 15:48:13 -07004 * 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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "examples/peerconnection/client/conductor.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012
kwibergbfefb032016-05-01 14:53:46 -070013#include <memory>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000014#include <utility>
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +000015#include <vector>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000016
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "api/test/fakeconstraints.h"
18#include "examples/peerconnection/client/defaults.h"
19#include "media/engine/webrtcvideocapturerfactory.h"
20#include "modules/video_capture/video_capture_factory.h"
21#include "rtc_base/checks.h"
22#include "rtc_base/json.h"
23#include "rtc_base/logging.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000024
25// Names used for a IceCandidate JSON object.
26const char kCandidateSdpMidName[] = "sdpMid";
27const char kCandidateSdpMlineIndexName[] = "sdpMLineIndex";
28const char kCandidateSdpName[] = "candidate";
29
30// Names used for a SessionDescription JSON object.
31const char kSessionDescriptionTypeName[] = "type";
32const char kSessionDescriptionSdpName[] = "sdp";
33
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +000034#define DTLS_ON true
35#define DTLS_OFF false
36
henrike@webrtc.org28e20752013-07-10 00:45:36 +000037class DummySetSessionDescriptionObserver
38 : public webrtc::SetSessionDescriptionObserver {
39 public:
40 static DummySetSessionDescriptionObserver* Create() {
41 return
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000042 new rtc::RefCountedObject<DummySetSessionDescriptionObserver>();
henrike@webrtc.org28e20752013-07-10 00:45:36 +000043 }
44 virtual void OnSuccess() {
45 LOG(INFO) << __FUNCTION__;
46 }
47 virtual void OnFailure(const std::string& error) {
48 LOG(INFO) << __FUNCTION__ << " " << error;
49 }
50
51 protected:
52 DummySetSessionDescriptionObserver() {}
53 ~DummySetSessionDescriptionObserver() {}
54};
55
56Conductor::Conductor(PeerConnectionClient* client, MainWindow* main_wnd)
57 : peer_id_(-1),
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +000058 loopback_(false),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000059 client_(client),
60 main_wnd_(main_wnd) {
61 client_->RegisterObserver(this);
62 main_wnd->RegisterObserver(this);
63}
64
65Conductor::~Conductor() {
nisseede5da42017-01-12 05:15:36 -080066 RTC_DCHECK(peer_connection_.get() == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000067}
68
69bool Conductor::connection_active() const {
70 return peer_connection_.get() != NULL;
71}
72
73void Conductor::Close() {
74 client_->SignOut();
75 DeletePeerConnection();
76}
77
78bool Conductor::InitializePeerConnection() {
nisseede5da42017-01-12 05:15:36 -080079 RTC_DCHECK(peer_connection_factory_.get() == NULL);
80 RTC_DCHECK(peer_connection_.get() == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000081
82 peer_connection_factory_ = webrtc::CreatePeerConnectionFactory();
83
84 if (!peer_connection_factory_.get()) {
85 main_wnd_->MessageBox("Error",
86 "Failed to initialize PeerConnectionFactory", true);
87 DeletePeerConnection();
88 return false;
89 }
90
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +000091 if (!CreatePeerConnection(DTLS_ON)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000092 main_wnd_->MessageBox("Error",
93 "CreatePeerConnection failed", true);
94 DeletePeerConnection();
95 }
96 AddStreams();
97 return peer_connection_.get() != NULL;
98}
99
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000100bool Conductor::ReinitializePeerConnectionForLoopback() {
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000101 loopback_ = true;
102 rtc::scoped_refptr<webrtc::StreamCollectionInterface> streams(
103 peer_connection_->local_streams());
104 peer_connection_ = NULL;
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000105 if (CreatePeerConnection(DTLS_OFF)) {
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000106 for (size_t i = 0; i < streams->count(); ++i)
107 peer_connection_->AddStream(streams->at(i));
108 peer_connection_->CreateOffer(this, NULL);
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000109 }
110 return peer_connection_.get() != NULL;
111}
112
113bool Conductor::CreatePeerConnection(bool dtls) {
nisseede5da42017-01-12 05:15:36 -0800114 RTC_DCHECK(peer_connection_factory_.get() != NULL);
115 RTC_DCHECK(peer_connection_.get() == NULL);
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000116
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800117 webrtc::PeerConnectionInterface::RTCConfiguration config;
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000118 webrtc::PeerConnectionInterface::IceServer server;
119 server.uri = GetPeerConnectionString();
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800120 config.servers.push_back(server);
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000121
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000122 webrtc::FakeConstraints constraints;
123 if (dtls) {
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000124 constraints.AddOptional(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
125 "true");
jbauch70625e52015-12-09 14:18:14 -0800126 } else {
braveyao@webrtc.org9bfa5f02015-03-11 03:20:59 +0000127 constraints.AddOptional(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
128 "false");
129 }
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000130
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800131 peer_connection_ = peer_connection_factory_->CreatePeerConnection(
hbosd7973cc2016-05-27 06:08:53 -0700132 config, &constraints, NULL, NULL, this);
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000133 return peer_connection_.get() != NULL;
134}
135
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000136void Conductor::DeletePeerConnection() {
137 peer_connection_ = NULL;
138 active_streams_.clear();
139 main_wnd_->StopLocalRenderer();
140 main_wnd_->StopRemoteRenderer();
141 peer_connection_factory_ = NULL;
142 peer_id_ = -1;
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000143 loopback_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000144}
145
146void Conductor::EnsureStreamingUI() {
nisseede5da42017-01-12 05:15:36 -0800147 RTC_DCHECK(peer_connection_.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000148 if (main_wnd_->IsWindow()) {
149 if (main_wnd_->current_ui() != MainWindow::STREAMING)
150 main_wnd_->SwitchToStreamingUI();
151 }
152}
153
154//
155// PeerConnectionObserver implementation.
156//
157
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000158// Called when a remote stream is added
Taylor Brandstetter98cde262016-05-31 13:02:21 -0700159void Conductor::OnAddStream(
160 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000161 LOG(INFO) << __FUNCTION__ << " " << stream->label();
Taylor Brandstetter98cde262016-05-31 13:02:21 -0700162 main_wnd_->QueueUIThreadCallback(NEW_STREAM_ADDED, stream.release());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000163}
164
Taylor Brandstetter98cde262016-05-31 13:02:21 -0700165void Conductor::OnRemoveStream(
166 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000167 LOG(INFO) << __FUNCTION__ << " " << stream->label();
Taylor Brandstetter98cde262016-05-31 13:02:21 -0700168 main_wnd_->QueueUIThreadCallback(STREAM_REMOVED, stream.release());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000169}
170
171void Conductor::OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
172 LOG(INFO) << __FUNCTION__ << " " << candidate->sdp_mline_index();
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000173 // For loopback test. To save some connecting delay.
174 if (loopback_) {
175 if (!peer_connection_->AddIceCandidate(candidate)) {
176 LOG(WARNING) << "Failed to apply the received candidate";
177 }
178 return;
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000179 }
180
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000181 Json::StyledWriter writer;
182 Json::Value jmessage;
183
184 jmessage[kCandidateSdpMidName] = candidate->sdp_mid();
185 jmessage[kCandidateSdpMlineIndexName] = candidate->sdp_mline_index();
186 std::string sdp;
187 if (!candidate->ToString(&sdp)) {
188 LOG(LS_ERROR) << "Failed to serialize candidate";
189 return;
190 }
191 jmessage[kCandidateSdpName] = sdp;
192 SendMessage(writer.write(jmessage));
193}
194
195//
196// PeerConnectionClientObserver implementation.
197//
198
199void Conductor::OnSignedIn() {
200 LOG(INFO) << __FUNCTION__;
201 main_wnd_->SwitchToPeerList(client_->peers());
202}
203
204void Conductor::OnDisconnected() {
205 LOG(INFO) << __FUNCTION__;
206
207 DeletePeerConnection();
208
209 if (main_wnd_->IsWindow())
210 main_wnd_->SwitchToConnectUI();
211}
212
213void Conductor::OnPeerConnected(int id, const std::string& name) {
214 LOG(INFO) << __FUNCTION__;
215 // Refresh the list if we're showing it.
216 if (main_wnd_->current_ui() == MainWindow::LIST_PEERS)
217 main_wnd_->SwitchToPeerList(client_->peers());
218}
219
220void Conductor::OnPeerDisconnected(int id) {
221 LOG(INFO) << __FUNCTION__;
222 if (id == peer_id_) {
223 LOG(INFO) << "Our peer disconnected";
224 main_wnd_->QueueUIThreadCallback(PEER_CONNECTION_CLOSED, NULL);
225 } else {
226 // Refresh the list if we're showing it.
227 if (main_wnd_->current_ui() == MainWindow::LIST_PEERS)
228 main_wnd_->SwitchToPeerList(client_->peers());
229 }
230}
231
232void Conductor::OnMessageFromPeer(int peer_id, const std::string& message) {
nisseede5da42017-01-12 05:15:36 -0800233 RTC_DCHECK(peer_id_ == peer_id || peer_id_ == -1);
234 RTC_DCHECK(!message.empty());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000235
236 if (!peer_connection_.get()) {
nisseede5da42017-01-12 05:15:36 -0800237 RTC_DCHECK(peer_id_ == -1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000238 peer_id_ = peer_id;
239
240 if (!InitializePeerConnection()) {
241 LOG(LS_ERROR) << "Failed to initialize our PeerConnection instance";
242 client_->SignOut();
243 return;
244 }
245 } else if (peer_id != peer_id_) {
nisseede5da42017-01-12 05:15:36 -0800246 RTC_DCHECK(peer_id_ != -1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000247 LOG(WARNING) << "Received a message from unknown peer while already in a "
248 "conversation with a different peer.";
249 return;
250 }
251
252 Json::Reader reader;
253 Json::Value jmessage;
254 if (!reader.parse(message, jmessage)) {
255 LOG(WARNING) << "Received unknown message. " << message;
256 return;
257 }
258 std::string type;
259 std::string json_object;
260
Thiago Farinacb76b892015-04-02 09:59:15 +0000261 rtc::GetStringFromJsonObject(jmessage, kSessionDescriptionTypeName, &type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000262 if (!type.empty()) {
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000263 if (type == "offer-loopback") {
264 // This is a loopback call.
265 // Recreate the peerconnection with DTLS disabled.
266 if (!ReinitializePeerConnectionForLoopback()) {
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000267 LOG(LS_ERROR) << "Failed to initialize our PeerConnection instance";
268 DeletePeerConnection();
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000269 client_->SignOut();
270 }
271 return;
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000272 }
273
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000274 std::string sdp;
Thiago Farinacb76b892015-04-02 09:59:15 +0000275 if (!rtc::GetStringFromJsonObject(jmessage, kSessionDescriptionSdpName,
276 &sdp)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000277 LOG(WARNING) << "Can't parse received session description message.";
278 return;
279 }
jbauchfabe2c92015-07-16 13:43:14 -0700280 webrtc::SdpParseError error;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000281 webrtc::SessionDescriptionInterface* session_description(
jbauchfabe2c92015-07-16 13:43:14 -0700282 webrtc::CreateSessionDescription(type, sdp, &error));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000283 if (!session_description) {
jbauchfabe2c92015-07-16 13:43:14 -0700284 LOG(WARNING) << "Can't parse received session description message. "
285 << "SdpParseError was: " << error.description;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000286 return;
287 }
288 LOG(INFO) << " Received session description :" << message;
289 peer_connection_->SetRemoteDescription(
290 DummySetSessionDescriptionObserver::Create(), session_description);
291 if (session_description->type() ==
292 webrtc::SessionDescriptionInterface::kOffer) {
293 peer_connection_->CreateAnswer(this, NULL);
294 }
295 return;
296 } else {
297 std::string sdp_mid;
298 int sdp_mlineindex = 0;
299 std::string sdp;
Thiago Farinacb76b892015-04-02 09:59:15 +0000300 if (!rtc::GetStringFromJsonObject(jmessage, kCandidateSdpMidName,
301 &sdp_mid) ||
302 !rtc::GetIntFromJsonObject(jmessage, kCandidateSdpMlineIndexName,
303 &sdp_mlineindex) ||
304 !rtc::GetStringFromJsonObject(jmessage, kCandidateSdpName, &sdp)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000305 LOG(WARNING) << "Can't parse received message.";
306 return;
307 }
jbauchfabe2c92015-07-16 13:43:14 -0700308 webrtc::SdpParseError error;
kwibergbfefb032016-05-01 14:53:46 -0700309 std::unique_ptr<webrtc::IceCandidateInterface> candidate(
jbauchfabe2c92015-07-16 13:43:14 -0700310 webrtc::CreateIceCandidate(sdp_mid, sdp_mlineindex, sdp, &error));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000311 if (!candidate.get()) {
jbauchfabe2c92015-07-16 13:43:14 -0700312 LOG(WARNING) << "Can't parse received candidate message. "
313 << "SdpParseError was: " << error.description;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000314 return;
315 }
316 if (!peer_connection_->AddIceCandidate(candidate.get())) {
317 LOG(WARNING) << "Failed to apply the received candidate";
318 return;
319 }
320 LOG(INFO) << " Received candidate :" << message;
321 return;
322 }
323}
324
325void Conductor::OnMessageSent(int err) {
326 // Process the next pending message if any.
327 main_wnd_->QueueUIThreadCallback(SEND_MESSAGE_TO_PEER, NULL);
328}
329
330void Conductor::OnServerConnectionFailure() {
331 main_wnd_->MessageBox("Error", ("Failed to connect to " + server_).c_str(),
332 true);
333}
334
335//
336// MainWndCallback implementation.
337//
338
339void Conductor::StartLogin(const std::string& server, int port) {
340 if (client_->is_connected())
341 return;
342 server_ = server;
343 client_->Connect(server, port, GetPeerName());
344}
345
346void Conductor::DisconnectFromServer() {
347 if (client_->is_connected())
348 client_->SignOut();
349}
350
351void Conductor::ConnectToPeer(int peer_id) {
nisseede5da42017-01-12 05:15:36 -0800352 RTC_DCHECK(peer_id_ == -1);
353 RTC_DCHECK(peer_id != -1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000354
355 if (peer_connection_.get()) {
356 main_wnd_->MessageBox("Error",
357 "We only support connecting to one peer at a time", true);
358 return;
359 }
360
361 if (InitializePeerConnection()) {
362 peer_id_ = peer_id;
363 peer_connection_->CreateOffer(this, NULL);
364 } else {
365 main_wnd_->MessageBox("Error", "Failed to initialize PeerConnection", true);
366 }
367}
368
deadbeef112b2e92017-02-10 20:13:37 -0800369std::unique_ptr<cricket::VideoCapturer> Conductor::OpenVideoCaptureDevice() {
solenberg8ad582d2016-03-16 09:34:56 -0700370 std::vector<std::string> device_names;
371 {
372 std::unique_ptr<webrtc::VideoCaptureModule::DeviceInfo> info(
nisseb29b9c82016-12-12 00:22:56 -0800373 webrtc::VideoCaptureFactory::CreateDeviceInfo());
solenberg8ad582d2016-03-16 09:34:56 -0700374 if (!info) {
375 return nullptr;
376 }
377 int num_devices = info->NumberOfDevices();
378 for (int i = 0; i < num_devices; ++i) {
379 const uint32_t kSize = 256;
380 char name[kSize] = {0};
381 char id[kSize] = {0};
382 if (info->GetDeviceName(i, name, kSize, id, kSize) != -1) {
383 device_names.push_back(name);
384 }
385 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000386 }
solenberg8ad582d2016-03-16 09:34:56 -0700387
388 cricket::WebRtcVideoDeviceCapturerFactory factory;
deadbeef112b2e92017-02-10 20:13:37 -0800389 std::unique_ptr<cricket::VideoCapturer> capturer;
solenberg8ad582d2016-03-16 09:34:56 -0700390 for (const auto& name : device_names) {
391 capturer = factory.Create(cricket::Device(name, 0));
392 if (capturer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000393 break;
solenberg8ad582d2016-03-16 09:34:56 -0700394 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000395 }
396 return capturer;
397}
398
399void Conductor::AddStreams() {
400 if (active_streams_.find(kStreamLabel) != active_streams_.end())
401 return; // Already added.
402
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000403 rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000404 peer_connection_factory_->CreateAudioTrack(
405 kAudioLabel, peer_connection_factory_->CreateAudioSource(NULL)));
406
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000407 rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000408 peer_connection_factory_->CreateVideoTrack(
409 kVideoLabel,
410 peer_connection_factory_->CreateVideoSource(OpenVideoCaptureDevice(),
411 NULL)));
412 main_wnd_->StartLocalRenderer(video_track);
413
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000414 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream =
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000415 peer_connection_factory_->CreateLocalMediaStream(kStreamLabel);
416
417 stream->AddTrack(audio_track);
418 stream->AddTrack(video_track);
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +0000419 if (!peer_connection_->AddStream(stream)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000420 LOG(LS_ERROR) << "Adding stream to PeerConnection failed";
421 }
422 typedef std::pair<std::string,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000423 rtc::scoped_refptr<webrtc::MediaStreamInterface> >
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000424 MediaStreamPair;
425 active_streams_.insert(MediaStreamPair(stream->label(), stream));
426 main_wnd_->SwitchToStreamingUI();
427}
428
429void Conductor::DisconnectFromCurrentPeer() {
430 LOG(INFO) << __FUNCTION__;
431 if (peer_connection_.get()) {
432 client_->SendHangUp(peer_id_);
433 DeletePeerConnection();
434 }
435
436 if (main_wnd_->IsWindow())
437 main_wnd_->SwitchToPeerList(client_->peers());
438}
439
440void Conductor::UIThreadCallback(int msg_id, void* data) {
441 switch (msg_id) {
442 case PEER_CONNECTION_CLOSED:
443 LOG(INFO) << "PEER_CONNECTION_CLOSED";
444 DeletePeerConnection();
445
nisseede5da42017-01-12 05:15:36 -0800446 RTC_DCHECK(active_streams_.empty());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000447
448 if (main_wnd_->IsWindow()) {
449 if (client_->is_connected()) {
450 main_wnd_->SwitchToPeerList(client_->peers());
451 } else {
452 main_wnd_->SwitchToConnectUI();
453 }
454 } else {
455 DisconnectFromServer();
456 }
457 break;
458
459 case SEND_MESSAGE_TO_PEER: {
460 LOG(INFO) << "SEND_MESSAGE_TO_PEER";
461 std::string* msg = reinterpret_cast<std::string*>(data);
462 if (msg) {
463 // For convenience, we always run the message through the queue.
464 // This way we can be sure that messages are sent to the server
465 // in the same order they were signaled without much hassle.
466 pending_messages_.push_back(msg);
467 }
468
469 if (!pending_messages_.empty() && !client_->IsSendingMessage()) {
470 msg = pending_messages_.front();
471 pending_messages_.pop_front();
472
473 if (!client_->SendToPeer(peer_id_, *msg) && peer_id_ != -1) {
474 LOG(LS_ERROR) << "SendToPeer failed";
475 DisconnectFromServer();
476 }
477 delete msg;
478 }
479
480 if (!peer_connection_.get())
481 peer_id_ = -1;
482
483 break;
484 }
485
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000486 case NEW_STREAM_ADDED: {
487 webrtc::MediaStreamInterface* stream =
488 reinterpret_cast<webrtc::MediaStreamInterface*>(
489 data);
490 webrtc::VideoTrackVector tracks = stream->GetVideoTracks();
491 // Only render the first track.
492 if (!tracks.empty()) {
493 webrtc::VideoTrackInterface* track = tracks[0];
494 main_wnd_->StartRemoteRenderer(track);
495 }
496 stream->Release();
497 break;
498 }
499
500 case STREAM_REMOVED: {
501 // Remote peer stopped sending a stream.
502 webrtc::MediaStreamInterface* stream =
503 reinterpret_cast<webrtc::MediaStreamInterface*>(
504 data);
505 stream->Release();
506 break;
507 }
508
509 default:
nissec80e7412017-01-11 05:56:46 -0800510 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000511 break;
512 }
513}
514
515void Conductor::OnSuccess(webrtc::SessionDescriptionInterface* desc) {
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000516 peer_connection_->SetLocalDescription(
517 DummySetSessionDescriptionObserver::Create(), desc);
518
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000519 std::string sdp;
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000520 desc->ToString(&sdp);
521
522 // For loopback test. To save some connecting delay.
523 if (loopback_) {
524 // Replace message type from "offer" to "answer"
525 webrtc::SessionDescriptionInterface* session_description(
jbauchfabe2c92015-07-16 13:43:14 -0700526 webrtc::CreateSessionDescription("answer", sdp, nullptr));
braveyao@webrtc.orgc68e0c92015-02-27 09:51:25 +0000527 peer_connection_->SetRemoteDescription(
528 DummySetSessionDescriptionObserver::Create(), session_description);
529 return;
530 }
braveyao@webrtc.orga742cb12015-01-29 04:23:01 +0000531
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000532 Json::StyledWriter writer;
533 Json::Value jmessage;
534 jmessage[kSessionDescriptionTypeName] = desc->type();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000535 jmessage[kSessionDescriptionSdpName] = sdp;
536 SendMessage(writer.write(jmessage));
537}
538
539void Conductor::OnFailure(const std::string& error) {
540 LOG(LERROR) << error;
541}
542
543void Conductor::SendMessage(const std::string& json_object) {
544 std::string* msg = new std::string(json_object);
545 main_wnd_->QueueUIThreadCallback(SEND_MESSAGE_TO_PEER, msg);
546}