blob: 9a76d51f8bdd4d73f9275d7baa5f6284319fd6c8 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2004 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/session/media/channel.h"
29
30#include "talk/base/buffer.h"
31#include "talk/base/byteorder.h"
32#include "talk/base/common.h"
mallinath@webrtc.org1112c302013-09-23 20:34:45 +000033#include "talk/base/dscp.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000034#include "talk/base/logging.h"
35#include "talk/media/base/rtputils.h"
36#include "talk/p2p/base/transportchannel.h"
37#include "talk/session/media/channelmanager.h"
38#include "talk/session/media/mediamessages.h"
39#include "talk/session/media/rtcpmuxfilter.h"
40#include "talk/session/media/typingmonitor.h"
41
42
43namespace cricket {
44
45enum {
46 MSG_ENABLE = 1,
47 MSG_DISABLE,
48 MSG_MUTESTREAM,
49 MSG_ISSTREAMMUTED,
50 MSG_SETREMOTECONTENT,
51 MSG_SETLOCALCONTENT,
52 MSG_EARLYMEDIATIMEOUT,
53 MSG_CANINSERTDTMF,
54 MSG_INSERTDTMF,
55 MSG_GETSTATS,
56 MSG_SETRENDERER,
57 MSG_ADDRECVSTREAM,
58 MSG_REMOVERECVSTREAM,
wu@webrtc.orgcadf9042013-08-30 21:24:16 +000059 MSG_ADDSENDSTREAM,
60 MSG_REMOVESENDSTREAM,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000061 MSG_SETRINGBACKTONE,
62 MSG_PLAYRINGBACKTONE,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000063 MSG_ADDSCREENCAST,
64 MSG_REMOVESCREENCAST,
65 MSG_SENDINTRAFRAME,
66 MSG_REQUESTINTRAFRAME,
67 MSG_SCREENCASTWINDOWEVENT,
68 MSG_RTPPACKET,
69 MSG_RTCPPACKET,
70 MSG_CHANNEL_ERROR,
71 MSG_SETCHANNELOPTIONS,
72 MSG_SCALEVOLUME,
73 MSG_HANDLEVIEWREQUEST,
74 MSG_READYTOSENDDATA,
75 MSG_SENDDATA,
76 MSG_DATARECEIVED,
77 MSG_SETCAPTURER,
78 MSG_ISSCREENCASTING,
wu@webrtc.orgcadf9042013-08-30 21:24:16 +000079 MSG_GETSCREENCASTDETAILS,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000080 MSG_SETSCREENCASTFACTORY,
81 MSG_FIRSTPACKETRECEIVED,
82 MSG_SESSION_ERROR,
83};
84
85// Value specified in RFC 5764.
86static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp";
87
88static const int kAgcMinus10db = -10;
89
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000090static void SetSessionError(BaseSession* session, BaseSession::Error error,
91 const std::string& error_desc) {
92 session->SetError(error, error_desc);
93}
94
95static void SafeSetError(const std::string& message, std::string* error_desc) {
96 if (error_desc) {
97 *error_desc = message;
98 }
99}
100
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000101// TODO(hellner): use the device manager for creation of screen capturers when
102// the cl enabling it has landed.
103class NullScreenCapturerFactory : public VideoChannel::ScreenCapturerFactory {
104 public:
105 VideoCapturer* CreateScreenCapturer(const ScreencastId& window) {
106 return NULL;
107 }
108};
109
110
111VideoChannel::ScreenCapturerFactory* CreateScreenCapturerFactory() {
112 return new NullScreenCapturerFactory();
113}
114
115struct SetContentData : public talk_base::MessageData {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000116 SetContentData(const MediaContentDescription* content,
117 ContentAction action,
118 std::string* error_desc)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000119 : content(content),
120 action(action),
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000121 error_desc(error_desc),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000122 result(false) {
123 }
124 const MediaContentDescription* content;
125 ContentAction action;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000126 std::string* error_desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000127 bool result;
128};
129
130struct SetBandwidthData : public talk_base::MessageData {
131 explicit SetBandwidthData(int value) : value(value), result(false) {}
132 int value;
133 bool result;
134};
135
136struct SetRingbackToneMessageData : public talk_base::MessageData {
137 SetRingbackToneMessageData(const void* b, int l)
138 : buf(b),
139 len(l),
140 result(false) {
141 }
142 const void* buf;
143 int len;
144 bool result;
145};
146
147struct PlayRingbackToneMessageData : public talk_base::MessageData {
148 PlayRingbackToneMessageData(uint32 s, bool p, bool l)
149 : ssrc(s),
150 play(p),
151 loop(l),
152 result(false) {
153 }
154 uint32 ssrc;
155 bool play;
156 bool loop;
157 bool result;
158};
159typedef talk_base::TypedMessageData<bool> BoolMessageData;
160struct DtmfMessageData : public talk_base::MessageData {
161 DtmfMessageData(uint32 ssrc, int event, int duration, int flags)
162 : ssrc(ssrc),
163 event(event),
164 duration(duration),
165 flags(flags),
166 result(false) {
167 }
168 uint32 ssrc;
169 int event;
170 int duration;
171 int flags;
172 bool result;
173};
174struct ScaleVolumeMessageData : public talk_base::MessageData {
175 ScaleVolumeMessageData(uint32 s, double l, double r)
176 : ssrc(s),
177 left(l),
178 right(r),
179 result(false) {
180 }
181 uint32 ssrc;
182 double left;
183 double right;
184 bool result;
185};
186
187struct VoiceStatsMessageData : public talk_base::MessageData {
188 explicit VoiceStatsMessageData(VoiceMediaInfo* stats)
189 : result(false),
190 stats(stats) {
191 }
192 bool result;
193 VoiceMediaInfo* stats;
194};
195
196struct VideoStatsMessageData : public talk_base::MessageData {
197 explicit VideoStatsMessageData(VideoMediaInfo* stats)
198 : result(false),
199 stats(stats) {
200 }
201 bool result;
202 VideoMediaInfo* stats;
203};
204
205struct PacketMessageData : public talk_base::MessageData {
206 talk_base::Buffer packet;
mallinath@webrtc.org1112c302013-09-23 20:34:45 +0000207 talk_base::DiffServCodePoint dscp;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000208};
209
210struct AudioRenderMessageData: public talk_base::MessageData {
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000211 AudioRenderMessageData(uint32 s, AudioRenderer* r, bool l)
212 : ssrc(s), renderer(r), is_local(l), result(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000213 uint32 ssrc;
214 AudioRenderer* renderer;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000215 bool is_local;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000216 bool result;
217};
218
219struct VideoRenderMessageData : public talk_base::MessageData {
220 VideoRenderMessageData(uint32 s, VideoRenderer* r) : ssrc(s), renderer(r) {}
221 uint32 ssrc;
222 VideoRenderer* renderer;
223};
224
225struct AddScreencastMessageData : public talk_base::MessageData {
226 AddScreencastMessageData(uint32 s, const ScreencastId& id)
227 : ssrc(s),
228 window_id(id),
229 result(NULL) {
230 }
231 uint32 ssrc;
232 ScreencastId window_id;
233 VideoCapturer* result;
234};
235
236struct RemoveScreencastMessageData : public talk_base::MessageData {
237 explicit RemoveScreencastMessageData(uint32 s) : ssrc(s), result(false) {}
238 uint32 ssrc;
239 bool result;
240};
241
242struct ScreencastEventMessageData : public talk_base::MessageData {
243 ScreencastEventMessageData(uint32 s, talk_base::WindowEvent we)
244 : ssrc(s),
245 event(we) {
246 }
247 uint32 ssrc;
248 talk_base::WindowEvent event;
249};
250
251struct ViewRequestMessageData : public talk_base::MessageData {
252 explicit ViewRequestMessageData(const ViewRequest& r)
253 : request(r),
254 result(false) {
255 }
256 ViewRequest request;
257 bool result;
258};
259
260struct VoiceChannelErrorMessageData : public talk_base::MessageData {
261 VoiceChannelErrorMessageData(uint32 in_ssrc,
262 VoiceMediaChannel::Error in_error)
263 : ssrc(in_ssrc),
264 error(in_error) {
265 }
266 uint32 ssrc;
267 VoiceMediaChannel::Error error;
268};
269
270struct VideoChannelErrorMessageData : public talk_base::MessageData {
271 VideoChannelErrorMessageData(uint32 in_ssrc,
272 VideoMediaChannel::Error in_error)
273 : ssrc(in_ssrc),
274 error(in_error) {
275 }
276 uint32 ssrc;
277 VideoMediaChannel::Error error;
278};
279
280struct DataChannelErrorMessageData : public talk_base::MessageData {
281 DataChannelErrorMessageData(uint32 in_ssrc,
282 DataMediaChannel::Error in_error)
283 : ssrc(in_ssrc),
284 error(in_error) {}
285 uint32 ssrc;
286 DataMediaChannel::Error error;
287};
288
289struct SessionErrorMessageData : public talk_base::MessageData {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000290 SessionErrorMessageData(cricket::BaseSession::Error error,
291 const std::string& error_desc)
292 : error_(error),
293 error_desc_(error_desc) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000294
295 BaseSession::Error error_;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000296 std::string error_desc_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000297};
298
299struct SsrcMessageData : public talk_base::MessageData {
300 explicit SsrcMessageData(uint32 ssrc) : ssrc(ssrc), result(false) {}
301 uint32 ssrc;
302 bool result;
303};
304
305struct StreamMessageData : public talk_base::MessageData {
306 explicit StreamMessageData(const StreamParams& in_sp)
307 : sp(in_sp),
308 result(false) {
309 }
310 StreamParams sp;
311 bool result;
312};
313
314struct MuteStreamData : public talk_base::MessageData {
315 MuteStreamData(uint32 ssrc, bool mute)
316 : ssrc(ssrc), mute(mute), result(false) {}
317 uint32 ssrc;
318 bool mute;
319 bool result;
320};
321
322struct AudioOptionsMessageData : public talk_base::MessageData {
323 explicit AudioOptionsMessageData(const AudioOptions& options)
324 : options(options),
325 result(false) {
326 }
327 AudioOptions options;
328 bool result;
329};
330
331struct VideoOptionsMessageData : public talk_base::MessageData {
332 explicit VideoOptionsMessageData(const VideoOptions& options)
333 : options(options),
334 result(false) {
335 }
336 VideoOptions options;
337 bool result;
338};
339
340struct SetCapturerMessageData : public talk_base::MessageData {
341 SetCapturerMessageData(uint32 s, VideoCapturer* c)
342 : ssrc(s),
343 capturer(c),
344 result(false) {
345 }
346 uint32 ssrc;
347 VideoCapturer* capturer;
348 bool result;
349};
350
351struct IsScreencastingMessageData : public talk_base::MessageData {
352 IsScreencastingMessageData()
353 : result(false) {
354 }
355 bool result;
356};
357
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000358struct VideoChannel::ScreencastDetailsMessageData :
359 public talk_base::MessageData {
360 explicit ScreencastDetailsMessageData(uint32 s)
361 : ssrc(s), fps(0), screencast_max_pixels(0) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000362 }
363 uint32 ssrc;
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000364 int fps;
365 int screencast_max_pixels;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000366};
367
368struct SetScreenCaptureFactoryMessageData : public talk_base::MessageData {
369 explicit SetScreenCaptureFactoryMessageData(
370 VideoChannel::ScreenCapturerFactory* f)
371 : screencapture_factory(f) {
372 }
373 VideoChannel::ScreenCapturerFactory* screencapture_factory;
374};
375
376static const char* PacketType(bool rtcp) {
377 return (!rtcp) ? "RTP" : "RTCP";
378}
379
380static bool ValidPacket(bool rtcp, const talk_base::Buffer* packet) {
381 // Check the packet size. We could check the header too if needed.
382 return (packet &&
383 packet->length() >= (!rtcp ? kMinRtpPacketLen : kMinRtcpPacketLen) &&
384 packet->length() <= kMaxRtpPacketLen);
385}
386
387static bool IsReceiveContentDirection(MediaContentDirection direction) {
388 return direction == MD_SENDRECV || direction == MD_RECVONLY;
389}
390
391static bool IsSendContentDirection(MediaContentDirection direction) {
392 return direction == MD_SENDRECV || direction == MD_SENDONLY;
393}
394
395static const MediaContentDescription* GetContentDescription(
396 const ContentInfo* cinfo) {
397 if (cinfo == NULL)
398 return NULL;
399 return static_cast<const MediaContentDescription*>(cinfo->description);
400}
401
402BaseChannel::BaseChannel(talk_base::Thread* thread,
403 MediaEngineInterface* media_engine,
404 MediaChannel* media_channel, BaseSession* session,
405 const std::string& content_name, bool rtcp)
406 : worker_thread_(thread),
407 media_engine_(media_engine),
408 session_(session),
409 media_channel_(media_channel),
410 content_name_(content_name),
411 rtcp_(rtcp),
412 transport_channel_(NULL),
413 rtcp_transport_channel_(NULL),
414 enabled_(false),
415 writable_(false),
416 rtp_ready_to_send_(false),
417 rtcp_ready_to_send_(false),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000418 was_ever_writable_(false),
419 local_content_direction_(MD_INACTIVE),
420 remote_content_direction_(MD_INACTIVE),
421 has_received_packet_(false),
422 dtls_keyed_(false),
423 secure_required_(false) {
424 ASSERT(worker_thread_ == talk_base::Thread::Current());
425 LOG(LS_INFO) << "Created channel for " << content_name;
426}
427
428BaseChannel::~BaseChannel() {
429 ASSERT(worker_thread_ == talk_base::Thread::Current());
wu@webrtc.org78187522013-10-07 23:32:02 +0000430 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000431 StopConnectionMonitor();
432 FlushRtcpMessages(); // Send any outstanding RTCP packets.
433 Clear(); // eats any outstanding messages or packets
434 // We must destroy the media channel before the transport channel, otherwise
435 // the media channel may try to send on the dead transport channel. NULLing
436 // is not an effective strategy since the sends will come on another thread.
437 delete media_channel_;
438 set_rtcp_transport_channel(NULL);
439 if (transport_channel_ != NULL)
440 session_->DestroyChannel(content_name_, transport_channel_->component());
441 LOG(LS_INFO) << "Destroyed channel";
442}
443
444bool BaseChannel::Init(TransportChannel* transport_channel,
445 TransportChannel* rtcp_transport_channel) {
446 if (transport_channel == NULL) {
447 return false;
448 }
449 if (rtcp() && rtcp_transport_channel == NULL) {
450 return false;
451 }
452 transport_channel_ = transport_channel;
453
454 if (!SetDtlsSrtpCiphers(transport_channel_, false)) {
455 return false;
456 }
457
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000458 transport_channel_->SignalWritableState.connect(
459 this, &BaseChannel::OnWritableState);
460 transport_channel_->SignalReadPacket.connect(
461 this, &BaseChannel::OnChannelRead);
462 transport_channel_->SignalReadyToSend.connect(
463 this, &BaseChannel::OnReadyToSend);
464
465 session_->SignalNewLocalDescription.connect(
466 this, &BaseChannel::OnNewLocalDescription);
467 session_->SignalNewRemoteDescription.connect(
468 this, &BaseChannel::OnNewRemoteDescription);
469
470 set_rtcp_transport_channel(rtcp_transport_channel);
wu@webrtc.orgde305012013-10-31 15:40:38 +0000471 // Both RTP and RTCP channels are set, we can call SetInterface on
472 // media channel and it can set network options.
473 media_channel_->SetInterface(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000474 return true;
475}
476
wu@webrtc.org78187522013-10-07 23:32:02 +0000477void BaseChannel::Deinit() {
478 media_channel_->SetInterface(NULL);
479}
480
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000481// Can be called from thread other than worker thread
482bool BaseChannel::Enable(bool enable) {
483 Send(enable ? MSG_ENABLE : MSG_DISABLE);
484 return true;
485}
486
487// Can be called from thread other than worker thread
488bool BaseChannel::MuteStream(uint32 ssrc, bool mute) {
489 MuteStreamData data(ssrc, mute);
490 Send(MSG_MUTESTREAM, &data);
491 return data.result;
492}
493
494bool BaseChannel::IsStreamMuted(uint32 ssrc) {
495 SsrcMessageData data(ssrc);
496 Send(MSG_ISSTREAMMUTED, &data);
497 return data.result;
498}
499
500bool BaseChannel::AddRecvStream(const StreamParams& sp) {
501 StreamMessageData data(sp);
502 Send(MSG_ADDRECVSTREAM, &data);
503 return data.result;
504}
505
506bool BaseChannel::RemoveRecvStream(uint32 ssrc) {
507 SsrcMessageData data(ssrc);
508 Send(MSG_REMOVERECVSTREAM, &data);
509 return data.result;
510}
511
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000512bool BaseChannel::AddSendStream(const StreamParams& sp) {
513 StreamMessageData data(sp);
514 Send(MSG_ADDSENDSTREAM, &data);
515 return data.result;
516}
517
518bool BaseChannel::RemoveSendStream(uint32 ssrc) {
519 SsrcMessageData data(ssrc);
520 Send(MSG_REMOVESENDSTREAM, &data);
521 return data.result;
522}
523
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000524bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000525 ContentAction action,
526 std::string* error_desc) {
527 SetContentData data(content, action, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000528 Send(MSG_SETLOCALCONTENT, &data);
529 return data.result;
530}
531
532bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000533 ContentAction action,
534 std::string* error_desc) {
535 SetContentData data(content, action, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000536 Send(MSG_SETREMOTECONTENT, &data);
537 return data.result;
538}
539
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000540void BaseChannel::StartConnectionMonitor(int cms) {
541 socket_monitor_.reset(new SocketMonitor(transport_channel_,
542 worker_thread(),
543 talk_base::Thread::Current()));
544 socket_monitor_->SignalUpdate.connect(
545 this, &BaseChannel::OnConnectionMonitorUpdate);
546 socket_monitor_->Start(cms);
547}
548
549void BaseChannel::StopConnectionMonitor() {
550 if (socket_monitor_) {
551 socket_monitor_->Stop();
552 socket_monitor_.reset();
553 }
554}
555
556void BaseChannel::set_rtcp_transport_channel(TransportChannel* channel) {
557 if (rtcp_transport_channel_ != channel) {
558 if (rtcp_transport_channel_) {
559 session_->DestroyChannel(
560 content_name_, rtcp_transport_channel_->component());
561 }
562 rtcp_transport_channel_ = channel;
563 if (rtcp_transport_channel_) {
564 // TODO(juberti): Propagate this error code
565 VERIFY(SetDtlsSrtpCiphers(rtcp_transport_channel_, true));
566 rtcp_transport_channel_->SignalWritableState.connect(
567 this, &BaseChannel::OnWritableState);
568 rtcp_transport_channel_->SignalReadPacket.connect(
569 this, &BaseChannel::OnChannelRead);
570 rtcp_transport_channel_->SignalReadyToSend.connect(
571 this, &BaseChannel::OnReadyToSend);
572 }
573 }
574}
575
576bool BaseChannel::IsReadyToReceive() const {
577 // Receive data if we are enabled and have local content,
578 return enabled() && IsReceiveContentDirection(local_content_direction_);
579}
580
581bool BaseChannel::IsReadyToSend() const {
582 // Send outgoing data if we are enabled, have local and remote content,
583 // and we have had some form of connectivity.
584 return enabled() &&
585 IsReceiveContentDirection(remote_content_direction_) &&
586 IsSendContentDirection(local_content_direction_) &&
587 was_ever_writable();
588}
589
mallinath@webrtc.org1112c302013-09-23 20:34:45 +0000590bool BaseChannel::SendPacket(talk_base::Buffer* packet,
591 talk_base::DiffServCodePoint dscp) {
592 return SendPacket(false, packet, dscp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000593}
594
mallinath@webrtc.org1112c302013-09-23 20:34:45 +0000595bool BaseChannel::SendRtcp(talk_base::Buffer* packet,
596 talk_base::DiffServCodePoint dscp) {
597 return SendPacket(true, packet, dscp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000598}
599
600int BaseChannel::SetOption(SocketType type, talk_base::Socket::Option opt,
601 int value) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000602 TransportChannel* channel = NULL;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000603 switch (type) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000604 case ST_RTP:
605 channel = transport_channel_;
606 break;
607 case ST_RTCP:
608 channel = rtcp_transport_channel_;
609 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000610 }
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000611 return channel ? channel->SetOption(opt, value) : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000612}
613
614void BaseChannel::OnWritableState(TransportChannel* channel) {
615 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
616 if (transport_channel_->writable()
617 && (!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
618 ChannelWritable_w();
619 } else {
620 ChannelNotWritable_w();
621 }
622}
623
624void BaseChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000625 const char* data, size_t len,
626 const talk_base::PacketTime& packet_time,
627 int flags) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000628 // OnChannelRead gets called from P2PSocket; now pass data to MediaEngine
629 ASSERT(worker_thread_ == talk_base::Thread::Current());
630
631 // When using RTCP multiplexing we might get RTCP packets on the RTP
632 // transport. We feed RTP traffic into the demuxer to determine if it is RTCP.
633 bool rtcp = PacketIsRtcp(channel, data, len);
634 talk_base::Buffer packet(data, len);
wu@webrtc.orga9890802013-12-13 00:21:03 +0000635 HandlePacket(rtcp, &packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000636}
637
638void BaseChannel::OnReadyToSend(TransportChannel* channel) {
639 SetReadyToSend(channel, true);
640}
641
642void BaseChannel::SetReadyToSend(TransportChannel* channel, bool ready) {
643 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
644 if (channel == transport_channel_) {
645 rtp_ready_to_send_ = ready;
646 }
647 if (channel == rtcp_transport_channel_) {
648 rtcp_ready_to_send_ = ready;
649 }
650
651 if (!ready) {
652 // Notify the MediaChannel when either rtp or rtcp channel can't send.
653 media_channel_->OnReadyToSend(false);
654 } else if (rtp_ready_to_send_ &&
655 // In the case of rtcp mux |rtcp_transport_channel_| will be null.
656 (rtcp_ready_to_send_ || !rtcp_transport_channel_)) {
657 // Notify the MediaChannel when both rtp and rtcp channel can send.
658 media_channel_->OnReadyToSend(true);
659 }
660}
661
662bool BaseChannel::PacketIsRtcp(const TransportChannel* channel,
663 const char* data, size_t len) {
664 return (channel == rtcp_transport_channel_ ||
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000665 rtcp_mux_filter_.DemuxRtcp(data, static_cast<int>(len)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000666}
667
mallinath@webrtc.org1112c302013-09-23 20:34:45 +0000668bool BaseChannel::SendPacket(bool rtcp, talk_base::Buffer* packet,
669 talk_base::DiffServCodePoint dscp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000670 // SendPacket gets called from MediaEngine, typically on an encoder thread.
671 // If the thread is not our worker thread, we will post to our worker
672 // so that the real work happens on our worker. This avoids us having to
673 // synchronize access to all the pieces of the send path, including
674 // SRTP and the inner workings of the transport channels.
675 // The only downside is that we can't return a proper failure code if
676 // needed. Since UDP is unreliable anyway, this should be a non-issue.
677 if (talk_base::Thread::Current() != worker_thread_) {
678 // Avoid a copy by transferring the ownership of the packet data.
679 int message_id = (!rtcp) ? MSG_RTPPACKET : MSG_RTCPPACKET;
680 PacketMessageData* data = new PacketMessageData;
681 packet->TransferTo(&data->packet);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +0000682 data->dscp = dscp;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000683 worker_thread_->Post(this, message_id, data);
684 return true;
685 }
686
687 // Now that we are on the correct thread, ensure we have a place to send this
688 // packet before doing anything. (We might get RTCP packets that we don't
689 // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
690 // transport.
691 TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
692 transport_channel_ : rtcp_transport_channel_;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000693 if (!channel || !channel->writable()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000694 return false;
695 }
696
697 // Protect ourselves against crazy data.
698 if (!ValidPacket(rtcp, packet)) {
699 LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
700 << PacketType(rtcp) << " packet: wrong size="
701 << packet->length();
702 return false;
703 }
704
705 // Signal to the media sink before protecting the packet.
706 {
707 talk_base::CritScope cs(&signal_send_packet_cs_);
708 SignalSendPacketPreCrypto(packet->data(), packet->length(), rtcp);
709 }
710
711 // Protect if needed.
712 if (srtp_filter_.IsActive()) {
713 bool res;
714 char* data = packet->data();
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000715 int len = static_cast<int>(packet->length());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000716 if (!rtcp) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000717 res = srtp_filter_.ProtectRtp(data, len,
718 static_cast<int>(packet->capacity()), &len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000719 if (!res) {
720 int seq_num = -1;
721 uint32 ssrc = 0;
722 GetRtpSeqNum(data, len, &seq_num);
723 GetRtpSsrc(data, len, &ssrc);
724 LOG(LS_ERROR) << "Failed to protect " << content_name_
725 << " RTP packet: size=" << len
726 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
727 return false;
728 }
729 } else {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000730 res = srtp_filter_.ProtectRtcp(data, len,
731 static_cast<int>(packet->capacity()),
732 &len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000733 if (!res) {
734 int type = -1;
735 GetRtcpType(data, len, &type);
736 LOG(LS_ERROR) << "Failed to protect " << content_name_
737 << " RTCP packet: size=" << len << ", type=" << type;
738 return false;
739 }
740 }
741
742 // Update the length of the packet now that we've added the auth tag.
743 packet->SetLength(len);
744 } else if (secure_required_) {
745 // This is a double check for something that supposedly can't happen.
746 LOG(LS_ERROR) << "Can't send outgoing " << PacketType(rtcp)
747 << " packet when SRTP is inactive and crypto is required";
748
749 ASSERT(false);
750 return false;
751 }
752
753 // Signal to the media sink after protecting the packet.
754 {
755 talk_base::CritScope cs(&signal_send_packet_cs_);
756 SignalSendPacketPostCrypto(packet->data(), packet->length(), rtcp);
757 }
758
759 // Bon voyage.
mallinath@webrtc.org1112c302013-09-23 20:34:45 +0000760 int ret = channel->SendPacket(packet->data(), packet->length(), dscp,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000761 (secure() && secure_dtls()) ? PF_SRTP_BYPASS : 0);
762 if (ret != static_cast<int>(packet->length())) {
763 if (channel->GetError() == EWOULDBLOCK) {
764 LOG(LS_WARNING) << "Got EWOULDBLOCK from socket.";
765 SetReadyToSend(channel, false);
766 }
767 return false;
768 }
769 return true;
770}
771
772bool BaseChannel::WantsPacket(bool rtcp, talk_base::Buffer* packet) {
773 // Protect ourselves against crazy data.
774 if (!ValidPacket(rtcp, packet)) {
775 LOG(LS_ERROR) << "Dropping incoming " << content_name_ << " "
776 << PacketType(rtcp) << " packet: wrong size="
777 << packet->length();
778 return false;
779 }
780 // If this channel is suppose to handle RTP data, that is determined by
781 // checking against ssrc filter. This is necessary to do it here to avoid
782 // double decryption.
783 if (ssrc_filter_.IsActive() &&
784 !ssrc_filter_.DemuxPacket(packet->data(), packet->length(), rtcp)) {
785 return false;
786 }
787
788 return true;
789}
790
wu@webrtc.orga9890802013-12-13 00:21:03 +0000791void BaseChannel::HandlePacket(bool rtcp, talk_base::Buffer* packet,
792 const talk_base::PacketTime& packet_time) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000793 if (!WantsPacket(rtcp, packet)) {
794 return;
795 }
796
797 if (!has_received_packet_) {
798 has_received_packet_ = true;
799 signaling_thread()->Post(this, MSG_FIRSTPACKETRECEIVED);
800 }
801
802 // Signal to the media sink before unprotecting the packet.
803 {
804 talk_base::CritScope cs(&signal_recv_packet_cs_);
805 SignalRecvPacketPostCrypto(packet->data(), packet->length(), rtcp);
806 }
807
808 // Unprotect the packet, if needed.
809 if (srtp_filter_.IsActive()) {
810 char* data = packet->data();
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000811 int len = static_cast<int>(packet->length());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000812 bool res;
813 if (!rtcp) {
814 res = srtp_filter_.UnprotectRtp(data, len, &len);
815 if (!res) {
816 int seq_num = -1;
817 uint32 ssrc = 0;
818 GetRtpSeqNum(data, len, &seq_num);
819 GetRtpSsrc(data, len, &ssrc);
820 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
821 << " RTP packet: size=" << len
822 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
823 return;
824 }
825 } else {
826 res = srtp_filter_.UnprotectRtcp(data, len, &len);
827 if (!res) {
828 int type = -1;
829 GetRtcpType(data, len, &type);
830 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
831 << " RTCP packet: size=" << len << ", type=" << type;
832 return;
833 }
834 }
835
836 packet->SetLength(len);
837 } else if (secure_required_) {
838 // Our session description indicates that SRTP is required, but we got a
839 // packet before our SRTP filter is active. This means either that
840 // a) we got SRTP packets before we received the SDES keys, in which case
841 // we can't decrypt it anyway, or
842 // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
843 // channels, so we haven't yet extracted keys, even if DTLS did complete
844 // on the channel that the packets are being sent on. It's really good
845 // practice to wait for both RTP and RTCP to be good to go before sending
846 // media, to prevent weird failure modes, so it's fine for us to just eat
847 // packets here. This is all sidestepped if RTCP mux is used anyway.
848 LOG(LS_WARNING) << "Can't process incoming " << PacketType(rtcp)
849 << " packet when SRTP is inactive and crypto is required";
850 return;
851 }
852
853 // Signal to the media sink after unprotecting the packet.
854 {
855 talk_base::CritScope cs(&signal_recv_packet_cs_);
856 SignalRecvPacketPreCrypto(packet->data(), packet->length(), rtcp);
857 }
858
859 // Push it down to the media channel.
860 if (!rtcp) {
wu@webrtc.orga9890802013-12-13 00:21:03 +0000861 media_channel_->OnPacketReceived(packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000862 } else {
wu@webrtc.orga9890802013-12-13 00:21:03 +0000863 media_channel_->OnRtcpReceived(packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000864 }
865}
866
867void BaseChannel::OnNewLocalDescription(
868 BaseSession* session, ContentAction action) {
869 const ContentInfo* content_info =
870 GetFirstContent(session->local_description());
871 const MediaContentDescription* content_desc =
872 GetContentDescription(content_info);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000873 std::string error_desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000874 if (content_desc && content_info && !content_info->rejected &&
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000875 !SetLocalContent(content_desc, action, &error_desc)) {
876 SetSessionError(session_, BaseSession::ERROR_CONTENT, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000877 LOG(LS_ERROR) << "Failure in SetLocalContent with action " << action;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000878 }
879}
880
881void BaseChannel::OnNewRemoteDescription(
882 BaseSession* session, ContentAction action) {
883 const ContentInfo* content_info =
884 GetFirstContent(session->remote_description());
885 const MediaContentDescription* content_desc =
886 GetContentDescription(content_info);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000887 std::string error_desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000888 if (content_desc && content_info && !content_info->rejected &&
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000889 !SetRemoteContent(content_desc, action, &error_desc)) {
890 SetSessionError(session_, BaseSession::ERROR_CONTENT, error_desc);
891 LOG(LS_ERROR) << "Failure in SetRemoteContent with action " << action;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000892 }
893}
894
895void BaseChannel::EnableMedia_w() {
896 ASSERT(worker_thread_ == talk_base::Thread::Current());
897 if (enabled_)
898 return;
899
900 LOG(LS_INFO) << "Channel enabled";
901 enabled_ = true;
902 ChangeState();
903}
904
905void BaseChannel::DisableMedia_w() {
906 ASSERT(worker_thread_ == talk_base::Thread::Current());
907 if (!enabled_)
908 return;
909
910 LOG(LS_INFO) << "Channel disabled";
911 enabled_ = false;
912 ChangeState();
913}
914
915bool BaseChannel::MuteStream_w(uint32 ssrc, bool mute) {
916 ASSERT(worker_thread_ == talk_base::Thread::Current());
917 bool ret = media_channel()->MuteStream(ssrc, mute);
918 if (ret) {
919 if (mute)
920 muted_streams_.insert(ssrc);
921 else
922 muted_streams_.erase(ssrc);
923 }
924 return ret;
925}
926
927bool BaseChannel::IsStreamMuted_w(uint32 ssrc) {
928 ASSERT(worker_thread_ == talk_base::Thread::Current());
929 return muted_streams_.find(ssrc) != muted_streams_.end();
930}
931
932void BaseChannel::ChannelWritable_w() {
933 ASSERT(worker_thread_ == talk_base::Thread::Current());
934 if (writable_)
935 return;
936
937 LOG(LS_INFO) << "Channel socket writable ("
938 << transport_channel_->content_name() << ", "
939 << transport_channel_->component() << ")"
940 << (was_ever_writable_ ? "" : " for the first time");
941
942 std::vector<ConnectionInfo> infos;
943 transport_channel_->GetStats(&infos);
944 for (std::vector<ConnectionInfo>::const_iterator it = infos.begin();
945 it != infos.end(); ++it) {
946 if (it->best_connection) {
947 LOG(LS_INFO) << "Using " << it->local_candidate.ToSensitiveString()
948 << "->" << it->remote_candidate.ToSensitiveString();
949 break;
950 }
951 }
952
953 // If we're doing DTLS-SRTP, now is the time.
954 if (!was_ever_writable_ && ShouldSetupDtlsSrtp()) {
955 if (!SetupDtlsSrtp(false)) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000956 const std::string error_desc =
957 "Couldn't set up DTLS-SRTP on RTP channel.";
958 SessionErrorMessageData data(BaseSession::ERROR_TRANSPORT, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000959 // Sent synchronously.
960 signaling_thread()->Send(this, MSG_SESSION_ERROR, &data);
961 return;
962 }
963
964 if (rtcp_transport_channel_) {
965 if (!SetupDtlsSrtp(true)) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000966 const std::string error_desc =
967 "Couldn't set up DTLS-SRTP on RTCP channel";
968 SessionErrorMessageData data(BaseSession::ERROR_TRANSPORT, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000969 // Sent synchronously.
970 signaling_thread()->Send(this, MSG_SESSION_ERROR, &data);
971 return;
972 }
973 }
974 }
975
976 was_ever_writable_ = true;
977 writable_ = true;
978 ChangeState();
979}
980
981bool BaseChannel::SetDtlsSrtpCiphers(TransportChannel *tc, bool rtcp) {
982 std::vector<std::string> ciphers;
983 // We always use the default SRTP ciphers for RTCP, but we may use different
984 // ciphers for RTP depending on the media type.
985 if (!rtcp) {
986 GetSrtpCiphers(&ciphers);
987 } else {
988 GetSupportedDefaultCryptoSuites(&ciphers);
989 }
990 return tc->SetSrtpCiphers(ciphers);
991}
992
993bool BaseChannel::ShouldSetupDtlsSrtp() const {
994 return true;
995}
996
997// This function returns true if either DTLS-SRTP is not in use
998// *or* DTLS-SRTP is successfully set up.
999bool BaseChannel::SetupDtlsSrtp(bool rtcp_channel) {
1000 bool ret = false;
1001
1002 TransportChannel *channel = rtcp_channel ?
1003 rtcp_transport_channel_ : transport_channel_;
1004
1005 // No DTLS
1006 if (!channel->IsDtlsActive())
1007 return true;
1008
1009 std::string selected_cipher;
1010
1011 if (!channel->GetSrtpCipher(&selected_cipher)) {
1012 LOG(LS_ERROR) << "No DTLS-SRTP selected cipher";
1013 return false;
1014 }
1015
1016 LOG(LS_INFO) << "Installing keys from DTLS-SRTP on "
1017 << content_name() << " "
1018 << PacketType(rtcp_channel);
1019
1020 // OK, we're now doing DTLS (RFC 5764)
1021 std::vector<unsigned char> dtls_buffer(SRTP_MASTER_KEY_KEY_LEN * 2 +
1022 SRTP_MASTER_KEY_SALT_LEN * 2);
1023
1024 // RFC 5705 exporter using the RFC 5764 parameters
1025 if (!channel->ExportKeyingMaterial(
1026 kDtlsSrtpExporterLabel,
1027 NULL, 0, false,
1028 &dtls_buffer[0], dtls_buffer.size())) {
1029 LOG(LS_WARNING) << "DTLS-SRTP key export failed";
1030 ASSERT(false); // This should never happen
1031 return false;
1032 }
1033
1034 // Sync up the keys with the DTLS-SRTP interface
1035 std::vector<unsigned char> client_write_key(SRTP_MASTER_KEY_KEY_LEN +
1036 SRTP_MASTER_KEY_SALT_LEN);
1037 std::vector<unsigned char> server_write_key(SRTP_MASTER_KEY_KEY_LEN +
1038 SRTP_MASTER_KEY_SALT_LEN);
1039 size_t offset = 0;
1040 memcpy(&client_write_key[0], &dtls_buffer[offset],
1041 SRTP_MASTER_KEY_KEY_LEN);
1042 offset += SRTP_MASTER_KEY_KEY_LEN;
1043 memcpy(&server_write_key[0], &dtls_buffer[offset],
1044 SRTP_MASTER_KEY_KEY_LEN);
1045 offset += SRTP_MASTER_KEY_KEY_LEN;
1046 memcpy(&client_write_key[SRTP_MASTER_KEY_KEY_LEN],
1047 &dtls_buffer[offset], SRTP_MASTER_KEY_SALT_LEN);
1048 offset += SRTP_MASTER_KEY_SALT_LEN;
1049 memcpy(&server_write_key[SRTP_MASTER_KEY_KEY_LEN],
1050 &dtls_buffer[offset], SRTP_MASTER_KEY_SALT_LEN);
1051
1052 std::vector<unsigned char> *send_key, *recv_key;
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00001053 talk_base::SSLRole role;
1054 if (!channel->GetSslRole(&role)) {
1055 LOG(LS_WARNING) << "GetSslRole failed";
1056 return false;
1057 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001058
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00001059 if (role == talk_base::SSL_SERVER) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001060 send_key = &server_write_key;
1061 recv_key = &client_write_key;
1062 } else {
1063 send_key = &client_write_key;
1064 recv_key = &server_write_key;
1065 }
1066
1067 if (rtcp_channel) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001068 ret = srtp_filter_.SetRtcpParams(
1069 selected_cipher,
1070 &(*send_key)[0],
1071 static_cast<int>(send_key->size()),
1072 selected_cipher,
1073 &(*recv_key)[0],
1074 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001075 } else {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001076 ret = srtp_filter_.SetRtpParams(
1077 selected_cipher,
1078 &(*send_key)[0],
1079 static_cast<int>(send_key->size()),
1080 selected_cipher,
1081 &(*recv_key)[0],
1082 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001083 }
1084
1085 if (!ret)
1086 LOG(LS_WARNING) << "DTLS-SRTP key installation failed";
1087 else
1088 dtls_keyed_ = true;
1089
1090 return ret;
1091}
1092
1093void BaseChannel::ChannelNotWritable_w() {
1094 ASSERT(worker_thread_ == talk_base::Thread::Current());
1095 if (!writable_)
1096 return;
1097
1098 LOG(LS_INFO) << "Channel socket not writable ("
1099 << transport_channel_->content_name() << ", "
1100 << transport_channel_->component() << ")";
1101 writable_ = false;
1102 ChangeState();
1103}
1104
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001105// |dtls| will be set to true if DTLS is active for transport channel and
1106// crypto is empty.
1107bool BaseChannel::CheckSrtpConfig(const std::vector<CryptoParams>& cryptos,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001108 bool* dtls,
1109 std::string* error_desc) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001110 *dtls = transport_channel_->IsDtlsActive();
1111 if (*dtls && !cryptos.empty()) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001112 SafeSetError("Cryptos must be empty when DTLS is active.",
1113 error_desc);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001114 return false;
1115 }
1116 return true;
1117}
1118
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001119bool BaseChannel::SetSrtp_w(const std::vector<CryptoParams>& cryptos,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001120 ContentAction action,
1121 ContentSource src,
1122 std::string* error_desc) {
1123 if (action == CA_UPDATE) {
1124 // no crypto params.
1125 return true;
1126 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001127 bool ret = false;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001128 bool dtls = false;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001129 ret = CheckSrtpConfig(cryptos, &dtls, error_desc);
1130 if (!ret) {
1131 return false;
1132 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001133 switch (action) {
1134 case CA_OFFER:
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001135 // If DTLS is already active on the channel, we could be renegotiating
1136 // here. We don't update the srtp filter.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001137 if (!dtls) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001138 ret = srtp_filter_.SetOffer(cryptos, src);
1139 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001140 break;
1141 case CA_PRANSWER:
1142 // If we're doing DTLS-SRTP, we don't want to update the filter
1143 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001144 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001145 ret = srtp_filter_.SetProvisionalAnswer(cryptos, src);
1146 }
1147 break;
1148 case CA_ANSWER:
1149 // If we're doing DTLS-SRTP, we don't want to update the filter
1150 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001151 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001152 ret = srtp_filter_.SetAnswer(cryptos, src);
1153 }
1154 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001155 default:
1156 break;
1157 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001158 if (!ret) {
1159 SafeSetError("Failed to setup SRTP filter.", error_desc);
1160 return false;
1161 }
1162 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001163}
1164
1165bool BaseChannel::SetRtcpMux_w(bool enable, ContentAction action,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001166 ContentSource src,
1167 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001168 bool ret = false;
1169 switch (action) {
1170 case CA_OFFER:
1171 ret = rtcp_mux_filter_.SetOffer(enable, src);
1172 break;
1173 case CA_PRANSWER:
1174 ret = rtcp_mux_filter_.SetProvisionalAnswer(enable, src);
1175 break;
1176 case CA_ANSWER:
1177 ret = rtcp_mux_filter_.SetAnswer(enable, src);
1178 if (ret && rtcp_mux_filter_.IsActive()) {
1179 // We activated RTCP mux, close down the RTCP transport.
1180 set_rtcp_transport_channel(NULL);
1181 }
1182 break;
1183 case CA_UPDATE:
1184 // No RTCP mux info.
1185 ret = true;
1186 default:
1187 break;
1188 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001189 if (!ret) {
1190 SafeSetError("Failed to setup RTCP mux filter.", error_desc);
1191 return false;
1192 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001193 // |rtcp_mux_filter_| can be active if |action| is CA_PRANSWER or
1194 // CA_ANSWER, but we only want to tear down the RTCP transport channel if we
1195 // received a final answer.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001196 if (rtcp_mux_filter_.IsActive()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001197 // If the RTP transport is already writable, then so are we.
1198 if (transport_channel_->writable()) {
1199 ChannelWritable_w();
1200 }
1201 }
1202
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001203 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001204}
1205
1206bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
1207 ASSERT(worker_thread() == talk_base::Thread::Current());
1208 if (!media_channel()->AddRecvStream(sp))
1209 return false;
1210
1211 return ssrc_filter_.AddStream(sp);
1212}
1213
1214bool BaseChannel::RemoveRecvStream_w(uint32 ssrc) {
1215 ASSERT(worker_thread() == talk_base::Thread::Current());
1216 ssrc_filter_.RemoveStream(ssrc);
1217 return media_channel()->RemoveRecvStream(ssrc);
1218}
1219
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001220bool BaseChannel::AddSendStream_w(const StreamParams& sp) {
1221 ASSERT(worker_thread() == talk_base::Thread::Current());
1222 return media_channel()->AddSendStream(sp);
1223}
1224
1225bool BaseChannel::RemoveSendStream_w(uint32 ssrc) {
1226 ASSERT(worker_thread() == talk_base::Thread::Current());
1227 return media_channel()->RemoveSendStream(ssrc);
1228}
1229
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001230bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001231 ContentAction action,
1232 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001233 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1234 action == CA_PRANSWER || action == CA_UPDATE))
1235 return false;
1236
1237 // If this is an update, streams only contain streams that have changed.
1238 if (action == CA_UPDATE) {
1239 for (StreamParamsVec::const_iterator it = streams.begin();
1240 it != streams.end(); ++it) {
1241 StreamParams existing_stream;
1242 bool stream_exist = GetStreamByIds(local_streams_, it->groupid,
1243 it->id, &existing_stream);
1244 if (!stream_exist && it->has_ssrcs()) {
1245 if (media_channel()->AddSendStream(*it)) {
1246 local_streams_.push_back(*it);
1247 LOG(LS_INFO) << "Add send stream ssrc: " << it->first_ssrc();
1248 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001249 std::ostringstream desc;
1250 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1251 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001252 return false;
1253 }
1254 } else if (stream_exist && !it->has_ssrcs()) {
1255 if (!media_channel()->RemoveSendStream(existing_stream.first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001256 std::ostringstream desc;
1257 desc << "Failed to remove send stream with ssrc "
1258 << it->first_ssrc() << ".";
1259 SafeSetError(desc.str(), error_desc);
1260 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001261 }
1262 RemoveStreamBySsrc(&local_streams_, existing_stream.first_ssrc());
1263 } else {
1264 LOG(LS_WARNING) << "Ignore unsupported stream update";
1265 }
1266 }
1267 return true;
1268 }
1269 // Else streams are all the streams we want to send.
1270
1271 // Check for streams that have been removed.
1272 bool ret = true;
1273 for (StreamParamsVec::const_iterator it = local_streams_.begin();
1274 it != local_streams_.end(); ++it) {
1275 if (!GetStreamBySsrc(streams, it->first_ssrc(), NULL)) {
1276 if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001277 std::ostringstream desc;
1278 desc << "Failed to remove send stream with ssrc "
1279 << it->first_ssrc() << ".";
1280 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001281 ret = false;
1282 }
1283 }
1284 }
1285 // Check for new streams.
1286 for (StreamParamsVec::const_iterator it = streams.begin();
1287 it != streams.end(); ++it) {
1288 if (!GetStreamBySsrc(local_streams_, it->first_ssrc(), NULL)) {
1289 if (media_channel()->AddSendStream(*it)) {
1290 LOG(LS_INFO) << "Add send ssrc: " << it->ssrcs[0];
1291 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001292 std::ostringstream desc;
1293 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1294 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001295 ret = false;
1296 }
1297 }
1298 }
1299 local_streams_ = streams;
1300 return ret;
1301}
1302
1303bool BaseChannel::UpdateRemoteStreams_w(
1304 const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001305 ContentAction action,
1306 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001307 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1308 action == CA_PRANSWER || action == CA_UPDATE))
1309 return false;
1310
1311 // If this is an update, streams only contain streams that have changed.
1312 if (action == CA_UPDATE) {
1313 for (StreamParamsVec::const_iterator it = streams.begin();
1314 it != streams.end(); ++it) {
1315 StreamParams existing_stream;
1316 bool stream_exists = GetStreamByIds(remote_streams_, it->groupid,
1317 it->id, &existing_stream);
1318 if (!stream_exists && it->has_ssrcs()) {
1319 if (AddRecvStream_w(*it)) {
1320 remote_streams_.push_back(*it);
1321 LOG(LS_INFO) << "Add remote stream ssrc: " << it->first_ssrc();
1322 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001323 std::ostringstream desc;
1324 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1325 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001326 return false;
1327 }
1328 } else if (stream_exists && !it->has_ssrcs()) {
1329 if (!RemoveRecvStream_w(existing_stream.first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001330 std::ostringstream desc;
1331 desc << "Failed to remove remote stream with ssrc "
1332 << it->first_ssrc() << ".";
1333 SafeSetError(desc.str(), error_desc);
1334 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001335 }
1336 RemoveStreamBySsrc(&remote_streams_, existing_stream.first_ssrc());
1337 } else {
1338 LOG(LS_WARNING) << "Ignore unsupported stream update."
1339 << " Stream exists? " << stream_exists
1340 << " existing stream = " << existing_stream.ToString()
1341 << " new stream = " << it->ToString();
1342 }
1343 }
1344 return true;
1345 }
1346 // Else streams are all the streams we want to receive.
1347
1348 // Check for streams that have been removed.
1349 bool ret = true;
1350 for (StreamParamsVec::const_iterator it = remote_streams_.begin();
1351 it != remote_streams_.end(); ++it) {
1352 if (!GetStreamBySsrc(streams, it->first_ssrc(), NULL)) {
1353 if (!RemoveRecvStream_w(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001354 std::ostringstream desc;
1355 desc << "Failed to remove remote stream with ssrc "
1356 << it->first_ssrc() << ".";
1357 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001358 ret = false;
1359 }
1360 }
1361 }
1362 // Check for new streams.
1363 for (StreamParamsVec::const_iterator it = streams.begin();
1364 it != streams.end(); ++it) {
1365 if (!GetStreamBySsrc(remote_streams_, it->first_ssrc(), NULL)) {
1366 if (AddRecvStream_w(*it)) {
1367 LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0];
1368 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001369 std::ostringstream desc;
1370 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1371 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001372 ret = false;
1373 }
1374 }
1375 }
1376 remote_streams_ = streams;
1377 return ret;
1378}
1379
1380bool BaseChannel::SetBaseLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001381 ContentAction action,
1382 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001383 // Cache secure_required_ for belt and suspenders check on SendPacket
1384 secure_required_ = content->crypto_required();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001385 bool ret = UpdateLocalStreams_w(content->streams(), action, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001386 // Set local SRTP parameters (what we will encrypt with).
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001387 ret &= SetSrtp_w(content->cryptos(), action, CS_LOCAL, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001388 // Set local RTCP mux parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001389 ret &= SetRtcpMux_w(content->rtcp_mux(), action, CS_LOCAL, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001390 // Set local RTP header extensions.
1391 if (content->rtp_header_extensions_set()) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001392 if (!media_channel()->SetRecvRtpHeaderExtensions(
1393 content->rtp_header_extensions())) {
1394 std::ostringstream desc;
1395 desc << "Failed to set receive rtp header extensions for "
1396 << MediaTypeToString(content->type()) << " content.";
1397 SafeSetError(desc.str(), error_desc);
1398 ret = false;
1399 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001400 }
1401 set_local_content_direction(content->direction());
1402 return ret;
1403}
1404
1405bool BaseChannel::SetBaseRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001406 ContentAction action,
1407 std::string* error_desc) {
1408 bool ret = UpdateRemoteStreams_w(content->streams(), action, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001409 // Set remote SRTP parameters (what the other side will encrypt with).
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001410 ret &= SetSrtp_w(content->cryptos(), action, CS_REMOTE, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001411 // Set remote RTCP mux parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001412 ret &= SetRtcpMux_w(content->rtcp_mux(), action, CS_REMOTE, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001413 // Set remote RTP header extensions.
1414 if (content->rtp_header_extensions_set()) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001415 if (!media_channel()->SetSendRtpHeaderExtensions(
1416 content->rtp_header_extensions())) {
1417 std::ostringstream desc;
1418 desc << "Failed to set send rtp header extensions for "
1419 << MediaTypeToString(content->type()) << " content.";
1420 SafeSetError(desc.str(), error_desc);
1421 ret = false;
1422 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001423 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001424
1425 if (!media_channel()->SetMaxSendBandwidth(content->bandwidth())) {
1426 std::ostringstream desc;
1427 desc << "Failed to set max send bandwidth for "
1428 << MediaTypeToString(content->type()) << " content.";
1429 SafeSetError(desc.str(), error_desc);
1430 ret = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001431 }
1432 set_remote_content_direction(content->direction());
1433 return ret;
1434}
1435
1436void BaseChannel::OnMessage(talk_base::Message *pmsg) {
1437 switch (pmsg->message_id) {
1438 case MSG_ENABLE:
1439 EnableMedia_w();
1440 break;
1441 case MSG_DISABLE:
1442 DisableMedia_w();
1443 break;
1444 case MSG_MUTESTREAM: {
1445 MuteStreamData* data = static_cast<MuteStreamData*>(pmsg->pdata);
1446 data->result = MuteStream_w(data->ssrc, data->mute);
1447 break;
1448 }
1449 case MSG_ISSTREAMMUTED: {
1450 SsrcMessageData* data = static_cast<SsrcMessageData*>(pmsg->pdata);
1451 data->result = IsStreamMuted_w(data->ssrc);
1452 break;
1453 }
1454 case MSG_SETLOCALCONTENT: {
1455 SetContentData* data = static_cast<SetContentData*>(pmsg->pdata);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001456 data->result = SetLocalContent_w(data->content,
1457 data->action,
1458 data->error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001459 break;
1460 }
1461 case MSG_SETREMOTECONTENT: {
1462 SetContentData* data = static_cast<SetContentData*>(pmsg->pdata);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001463 data->result = SetRemoteContent_w(data->content,
1464 data->action,
1465 data->error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001466 break;
1467 }
1468 case MSG_ADDRECVSTREAM: {
1469 StreamMessageData* data = static_cast<StreamMessageData*>(pmsg->pdata);
1470 data->result = AddRecvStream_w(data->sp);
1471 break;
1472 }
1473 case MSG_REMOVERECVSTREAM: {
1474 SsrcMessageData* data = static_cast<SsrcMessageData*>(pmsg->pdata);
1475 data->result = RemoveRecvStream_w(data->ssrc);
1476 break;
1477 }
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001478 case MSG_ADDSENDSTREAM: {
1479 StreamMessageData* data = static_cast<StreamMessageData*>(pmsg->pdata);
1480 data->result = AddSendStream_w(data->sp);
1481 break;
1482 }
1483 case MSG_REMOVESENDSTREAM: {
1484 SsrcMessageData* data = static_cast<SsrcMessageData*>(pmsg->pdata);
1485 data->result = RemoveSendStream_w(data->ssrc);
1486 break;
1487 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001488
1489 case MSG_RTPPACKET:
1490 case MSG_RTCPPACKET: {
1491 PacketMessageData* data = static_cast<PacketMessageData*>(pmsg->pdata);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00001492 SendPacket(pmsg->message_id == MSG_RTCPPACKET, &data->packet, data->dscp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001493 delete data; // because it is Posted
1494 break;
1495 }
1496 case MSG_FIRSTPACKETRECEIVED: {
1497 SignalFirstPacketReceived(this);
1498 break;
1499 }
1500 case MSG_SESSION_ERROR: {
1501 SessionErrorMessageData* data = static_cast<SessionErrorMessageData*>
1502 (pmsg->pdata);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001503 SetSessionError(session_, data->error_, data->error_desc_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001504 break;
1505 }
1506 }
1507}
1508
1509void BaseChannel::Send(uint32 id, talk_base::MessageData *pdata) {
1510 worker_thread_->Send(this, id, pdata);
1511}
1512
1513void BaseChannel::Post(uint32 id, talk_base::MessageData *pdata) {
1514 worker_thread_->Post(this, id, pdata);
1515}
1516
1517void BaseChannel::PostDelayed(int cmsDelay, uint32 id,
1518 talk_base::MessageData *pdata) {
1519 worker_thread_->PostDelayed(cmsDelay, this, id, pdata);
1520}
1521
1522void BaseChannel::Clear(uint32 id, talk_base::MessageList* removed) {
1523 worker_thread_->Clear(this, id, removed);
1524}
1525
1526void BaseChannel::FlushRtcpMessages() {
1527 // Flush all remaining RTCP messages. This should only be called in
1528 // destructor.
1529 ASSERT(talk_base::Thread::Current() == worker_thread_);
1530 talk_base::MessageList rtcp_messages;
1531 Clear(MSG_RTCPPACKET, &rtcp_messages);
1532 for (talk_base::MessageList::iterator it = rtcp_messages.begin();
1533 it != rtcp_messages.end(); ++it) {
1534 Send(MSG_RTCPPACKET, it->pdata);
1535 }
1536}
1537
1538VoiceChannel::VoiceChannel(talk_base::Thread* thread,
1539 MediaEngineInterface* media_engine,
1540 VoiceMediaChannel* media_channel,
1541 BaseSession* session,
1542 const std::string& content_name,
1543 bool rtcp)
1544 : BaseChannel(thread, media_engine, media_channel, session, content_name,
1545 rtcp),
1546 received_media_(false) {
1547}
1548
1549VoiceChannel::~VoiceChannel() {
1550 StopAudioMonitor();
1551 StopMediaMonitor();
1552 // this can't be done in the base class, since it calls a virtual
1553 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001554 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001555}
1556
1557bool VoiceChannel::Init() {
1558 TransportChannel* rtcp_channel = rtcp() ? session()->CreateChannel(
1559 content_name(), "rtcp", ICE_CANDIDATE_COMPONENT_RTCP) : NULL;
1560 if (!BaseChannel::Init(session()->CreateChannel(
1561 content_name(), "rtp", ICE_CANDIDATE_COMPONENT_RTP),
1562 rtcp_channel)) {
1563 return false;
1564 }
1565 media_channel()->SignalMediaError.connect(
1566 this, &VoiceChannel::OnVoiceChannelError);
1567 srtp_filter()->SignalSrtpError.connect(
1568 this, &VoiceChannel::OnSrtpError);
1569 return true;
1570}
1571
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001572bool VoiceChannel::SetRemoteRenderer(uint32 ssrc, AudioRenderer* renderer) {
1573 AudioRenderMessageData data(ssrc, renderer, false);
1574 Send(MSG_SETRENDERER, &data);
1575 return data.result;
1576}
1577
1578bool VoiceChannel::SetLocalRenderer(uint32 ssrc, AudioRenderer* renderer) {
1579 AudioRenderMessageData data(ssrc, renderer, true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001580 Send(MSG_SETRENDERER, &data);
1581 return data.result;
1582}
1583
1584bool VoiceChannel::SetRingbackTone(const void* buf, int len) {
1585 SetRingbackToneMessageData data(buf, len);
1586 Send(MSG_SETRINGBACKTONE, &data);
1587 return data.result;
1588}
1589
1590// TODO(juberti): Handle early media the right way. We should get an explicit
1591// ringing message telling us to start playing local ringback, which we cancel
1592// if any early media actually arrives. For now, we do the opposite, which is
1593// to wait 1 second for early media, and start playing local ringback if none
1594// arrives.
1595void VoiceChannel::SetEarlyMedia(bool enable) {
1596 if (enable) {
1597 // Start the early media timeout
1598 PostDelayed(kEarlyMediaTimeout, MSG_EARLYMEDIATIMEOUT);
1599 } else {
1600 // Stop the timeout if currently going.
1601 Clear(MSG_EARLYMEDIATIMEOUT);
1602 }
1603}
1604
1605bool VoiceChannel::PlayRingbackTone(uint32 ssrc, bool play, bool loop) {
1606 PlayRingbackToneMessageData data(ssrc, play, loop);
1607 Send(MSG_PLAYRINGBACKTONE, &data);
1608 return data.result;
1609}
1610
1611bool VoiceChannel::PressDTMF(int digit, bool playout) {
1612 int flags = DF_SEND;
1613 if (playout) {
1614 flags |= DF_PLAY;
1615 }
1616 int duration_ms = 160;
1617 return InsertDtmf(0, digit, duration_ms, flags);
1618}
1619
1620bool VoiceChannel::CanInsertDtmf() {
1621 BoolMessageData data(false);
1622 Send(MSG_CANINSERTDTMF, &data);
1623 return data.data();
1624}
1625
1626bool VoiceChannel::InsertDtmf(uint32 ssrc, int event_code, int duration,
1627 int flags) {
1628 DtmfMessageData data(ssrc, event_code, duration, flags);
1629 Send(MSG_INSERTDTMF, &data);
1630 return data.result;
1631}
1632
1633bool VoiceChannel::SetOutputScaling(uint32 ssrc, double left, double right) {
1634 ScaleVolumeMessageData data(ssrc, left, right);
1635 Send(MSG_SCALEVOLUME, &data);
1636 return data.result;
1637}
1638bool VoiceChannel::GetStats(VoiceMediaInfo* stats) {
1639 VoiceStatsMessageData data(stats);
1640 Send(MSG_GETSTATS, &data);
1641 return data.result;
1642}
1643
1644void VoiceChannel::StartMediaMonitor(int cms) {
1645 media_monitor_.reset(new VoiceMediaMonitor(media_channel(), worker_thread(),
1646 talk_base::Thread::Current()));
1647 media_monitor_->SignalUpdate.connect(
1648 this, &VoiceChannel::OnMediaMonitorUpdate);
1649 media_monitor_->Start(cms);
1650}
1651
1652void VoiceChannel::StopMediaMonitor() {
1653 if (media_monitor_) {
1654 media_monitor_->Stop();
1655 media_monitor_->SignalUpdate.disconnect(this);
1656 media_monitor_.reset();
1657 }
1658}
1659
1660void VoiceChannel::StartAudioMonitor(int cms) {
1661 audio_monitor_.reset(new AudioMonitor(this, talk_base::Thread::Current()));
1662 audio_monitor_
1663 ->SignalUpdate.connect(this, &VoiceChannel::OnAudioMonitorUpdate);
1664 audio_monitor_->Start(cms);
1665}
1666
1667void VoiceChannel::StopAudioMonitor() {
1668 if (audio_monitor_) {
1669 audio_monitor_->Stop();
1670 audio_monitor_.reset();
1671 }
1672}
1673
1674bool VoiceChannel::IsAudioMonitorRunning() const {
1675 return (audio_monitor_.get() != NULL);
1676}
1677
1678void VoiceChannel::StartTypingMonitor(const TypingMonitorOptions& settings) {
1679 typing_monitor_.reset(new TypingMonitor(this, worker_thread(), settings));
1680 SignalAutoMuted.repeat(typing_monitor_->SignalMuted);
1681}
1682
1683void VoiceChannel::StopTypingMonitor() {
1684 typing_monitor_.reset();
1685}
1686
1687bool VoiceChannel::IsTypingMonitorRunning() const {
1688 return typing_monitor_;
1689}
1690
1691bool VoiceChannel::MuteStream_w(uint32 ssrc, bool mute) {
1692 bool ret = BaseChannel::MuteStream_w(ssrc, mute);
1693 if (typing_monitor_ && mute)
1694 typing_monitor_->OnChannelMuted();
1695 return ret;
1696}
1697
1698int VoiceChannel::GetInputLevel_w() {
1699 return media_engine()->GetInputLevel();
1700}
1701
1702int VoiceChannel::GetOutputLevel_w() {
1703 return media_channel()->GetOutputLevel();
1704}
1705
1706void VoiceChannel::GetActiveStreams_w(AudioInfo::StreamList* actives) {
1707 media_channel()->GetActiveStreams(actives);
1708}
1709
1710void VoiceChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001711 const char* data, size_t len,
1712 const talk_base::PacketTime& packet_time,
1713 int flags) {
1714 BaseChannel::OnChannelRead(channel, data, len, packet_time, flags);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001715
1716 // Set a flag when we've received an RTP packet. If we're waiting for early
1717 // media, this will disable the timeout.
1718 if (!received_media_ && !PacketIsRtcp(channel, data, len)) {
1719 received_media_ = true;
1720 }
1721}
1722
1723void VoiceChannel::ChangeState() {
1724 // Render incoming data if we're the active call, and we have the local
1725 // content. We receive data on the default channel and multiplexed streams.
1726 bool recv = IsReadyToReceive();
1727 if (!media_channel()->SetPlayout(recv)) {
1728 SendLastMediaError();
1729 }
1730
1731 // Send outgoing data if we're the active call, we have the remote content,
1732 // and we have had some form of connectivity.
1733 bool send = IsReadyToSend();
1734 SendFlags send_flag = send ? SEND_MICROPHONE : SEND_NOTHING;
1735 if (!media_channel()->SetSend(send_flag)) {
1736 LOG(LS_ERROR) << "Failed to SetSend " << send_flag << " on voice channel";
1737 SendLastMediaError();
1738 }
1739
1740 LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
1741}
1742
1743const ContentInfo* VoiceChannel::GetFirstContent(
1744 const SessionDescription* sdesc) {
1745 return GetFirstAudioContent(sdesc);
1746}
1747
1748bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001749 ContentAction action,
1750 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001751 ASSERT(worker_thread() == talk_base::Thread::Current());
1752 LOG(LS_INFO) << "Setting local voice description";
1753
1754 const AudioContentDescription* audio =
1755 static_cast<const AudioContentDescription*>(content);
1756 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001757 if (!audio) {
1758 SafeSetError("Can't find audio content in local description.", error_desc);
1759 return false;
1760 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001761
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001762 bool ret = SetBaseLocalContent_w(content, action, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001763 // Set local audio codecs (what we want to receive).
1764 // TODO(whyuan): Change action != CA_UPDATE to !audio->partial() when partial
1765 // is set properly.
1766 if (action != CA_UPDATE || audio->has_codecs()) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001767 if (!media_channel()->SetRecvCodecs(audio->codecs())) {
1768 SafeSetError("Failed to set audio receive codecs.", error_desc);
1769 ret = false;
1770 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001771 }
1772
1773 // If everything worked, see if we can start receiving.
1774 if (ret) {
1775 ChangeState();
1776 } else {
1777 LOG(LS_WARNING) << "Failed to set local voice description";
1778 }
1779 return ret;
1780}
1781
1782bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001783 ContentAction action,
1784 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001785 ASSERT(worker_thread() == talk_base::Thread::Current());
1786 LOG(LS_INFO) << "Setting remote voice description";
1787
1788 const AudioContentDescription* audio =
1789 static_cast<const AudioContentDescription*>(content);
1790 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001791 if (!audio) {
1792 SafeSetError("Can't find audio content in remote description.", error_desc);
1793 return false;
1794 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001795
1796 bool ret = true;
1797 // Set remote video codecs (what the other side wants to receive).
1798 if (action != CA_UPDATE || audio->has_codecs()) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001799 if (!media_channel()->SetSendCodecs(audio->codecs())) {
1800 SafeSetError("Failed to set audio send codecs.", error_desc);
1801 ret = false;
1802 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001803 }
1804
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001805 ret &= SetBaseRemoteContent_w(content, action, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001806
1807 if (action != CA_UPDATE) {
1808 // Tweak our audio processing settings, if needed.
1809 AudioOptions audio_options;
1810 if (!media_channel()->GetOptions(&audio_options)) {
1811 LOG(LS_WARNING) << "Can not set audio options from on remote content.";
1812 } else {
1813 if (audio->conference_mode()) {
1814 audio_options.conference_mode.Set(true);
1815 }
1816 if (audio->agc_minus_10db()) {
1817 audio_options.adjust_agc_delta.Set(kAgcMinus10db);
1818 }
1819 if (!media_channel()->SetOptions(audio_options)) {
1820 // Log an error on failure, but don't abort the call.
1821 LOG(LS_ERROR) << "Failed to set voice channel options";
1822 }
1823 }
1824 }
1825
1826 // If everything worked, see if we can start sending.
1827 if (ret) {
1828 ChangeState();
1829 } else {
1830 LOG(LS_WARNING) << "Failed to set remote voice description";
1831 }
1832 return ret;
1833}
1834
1835bool VoiceChannel::SetRingbackTone_w(const void* buf, int len) {
1836 ASSERT(worker_thread() == talk_base::Thread::Current());
1837 return media_channel()->SetRingbackTone(static_cast<const char*>(buf), len);
1838}
1839
1840bool VoiceChannel::PlayRingbackTone_w(uint32 ssrc, bool play, bool loop) {
1841 ASSERT(worker_thread() == talk_base::Thread::Current());
1842 if (play) {
1843 LOG(LS_INFO) << "Playing ringback tone, loop=" << loop;
1844 } else {
1845 LOG(LS_INFO) << "Stopping ringback tone";
1846 }
1847 return media_channel()->PlayRingbackTone(ssrc, play, loop);
1848}
1849
1850void VoiceChannel::HandleEarlyMediaTimeout() {
1851 // This occurs on the main thread, not the worker thread.
1852 if (!received_media_) {
1853 LOG(LS_INFO) << "No early media received before timeout";
1854 SignalEarlyMediaTimeout(this);
1855 }
1856}
1857
1858bool VoiceChannel::CanInsertDtmf_w() {
1859 return media_channel()->CanInsertDtmf();
1860}
1861
1862bool VoiceChannel::InsertDtmf_w(uint32 ssrc, int event, int duration,
1863 int flags) {
1864 if (!enabled()) {
1865 return false;
1866 }
1867
1868 return media_channel()->InsertDtmf(ssrc, event, duration, flags);
1869}
1870
1871bool VoiceChannel::SetOutputScaling_w(uint32 ssrc, double left, double right) {
1872 return media_channel()->SetOutputScaling(ssrc, left, right);
1873}
1874
1875bool VoiceChannel::GetStats_w(VoiceMediaInfo* stats) {
1876 return media_channel()->GetStats(stats);
1877}
1878
1879bool VoiceChannel::SetChannelOptions(const AudioOptions& options) {
1880 AudioOptionsMessageData data(options);
1881 Send(MSG_SETCHANNELOPTIONS, &data);
1882 return data.result;
1883}
1884
1885bool VoiceChannel::SetChannelOptions_w(const AudioOptions& options) {
1886 return media_channel()->SetOptions(options);
1887}
1888
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001889bool VoiceChannel::SetRenderer_w(uint32 ssrc, AudioRenderer* renderer,
1890 bool is_local) {
1891 if (is_local)
1892 return media_channel()->SetLocalRenderer(ssrc, renderer);
1893
1894 return media_channel()->SetRemoteRenderer(ssrc, renderer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001895}
1896
1897void VoiceChannel::OnMessage(talk_base::Message *pmsg) {
1898 switch (pmsg->message_id) {
1899 case MSG_SETRINGBACKTONE: {
1900 SetRingbackToneMessageData* data =
1901 static_cast<SetRingbackToneMessageData*>(pmsg->pdata);
1902 data->result = SetRingbackTone_w(data->buf, data->len);
1903 break;
1904 }
1905 case MSG_PLAYRINGBACKTONE: {
1906 PlayRingbackToneMessageData* data =
1907 static_cast<PlayRingbackToneMessageData*>(pmsg->pdata);
1908 data->result = PlayRingbackTone_w(data->ssrc, data->play, data->loop);
1909 break;
1910 }
1911 case MSG_EARLYMEDIATIMEOUT:
1912 HandleEarlyMediaTimeout();
1913 break;
1914 case MSG_CANINSERTDTMF: {
1915 BoolMessageData* data =
1916 static_cast<BoolMessageData*>(pmsg->pdata);
1917 data->data() = CanInsertDtmf_w();
1918 break;
1919 }
1920 case MSG_INSERTDTMF: {
1921 DtmfMessageData* data =
1922 static_cast<DtmfMessageData*>(pmsg->pdata);
1923 data->result = InsertDtmf_w(data->ssrc, data->event, data->duration,
1924 data->flags);
1925 break;
1926 }
1927 case MSG_SCALEVOLUME: {
1928 ScaleVolumeMessageData* data =
1929 static_cast<ScaleVolumeMessageData*>(pmsg->pdata);
1930 data->result = SetOutputScaling_w(data->ssrc, data->left, data->right);
1931 break;
1932 }
1933 case MSG_GETSTATS: {
1934 VoiceStatsMessageData* data =
1935 static_cast<VoiceStatsMessageData*>(pmsg->pdata);
1936 data->result = GetStats_w(data->stats);
1937 break;
1938 }
1939 case MSG_CHANNEL_ERROR: {
1940 VoiceChannelErrorMessageData* data =
1941 static_cast<VoiceChannelErrorMessageData*>(pmsg->pdata);
1942 SignalMediaError(this, data->ssrc, data->error);
1943 delete data;
1944 break;
1945 }
1946 case MSG_SETCHANNELOPTIONS: {
1947 AudioOptionsMessageData* data =
1948 static_cast<AudioOptionsMessageData*>(pmsg->pdata);
1949 data->result = SetChannelOptions_w(data->options);
1950 break;
1951 }
1952 case MSG_SETRENDERER: {
1953 AudioRenderMessageData* data =
1954 static_cast<AudioRenderMessageData*>(pmsg->pdata);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001955 data->result = SetRenderer_w(data->ssrc, data->renderer, data->is_local);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001956 break;
1957 }
1958 default:
1959 BaseChannel::OnMessage(pmsg);
1960 break;
1961 }
1962}
1963
1964void VoiceChannel::OnConnectionMonitorUpdate(
1965 SocketMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
1966 SignalConnectionMonitor(this, infos);
1967}
1968
1969void VoiceChannel::OnMediaMonitorUpdate(
1970 VoiceMediaChannel* media_channel, const VoiceMediaInfo& info) {
1971 ASSERT(media_channel == this->media_channel());
1972 SignalMediaMonitor(this, info);
1973}
1974
1975void VoiceChannel::OnAudioMonitorUpdate(AudioMonitor* monitor,
1976 const AudioInfo& info) {
1977 SignalAudioMonitor(this, info);
1978}
1979
1980void VoiceChannel::OnVoiceChannelError(
1981 uint32 ssrc, VoiceMediaChannel::Error err) {
1982 VoiceChannelErrorMessageData* data = new VoiceChannelErrorMessageData(
1983 ssrc, err);
1984 signaling_thread()->Post(this, MSG_CHANNEL_ERROR, data);
1985}
1986
1987void VoiceChannel::OnSrtpError(uint32 ssrc, SrtpFilter::Mode mode,
1988 SrtpFilter::Error error) {
1989 switch (error) {
1990 case SrtpFilter::ERROR_FAIL:
1991 OnVoiceChannelError(ssrc, (mode == SrtpFilter::PROTECT) ?
1992 VoiceMediaChannel::ERROR_REC_SRTP_ERROR :
1993 VoiceMediaChannel::ERROR_PLAY_SRTP_ERROR);
1994 break;
1995 case SrtpFilter::ERROR_AUTH:
1996 OnVoiceChannelError(ssrc, (mode == SrtpFilter::PROTECT) ?
1997 VoiceMediaChannel::ERROR_REC_SRTP_AUTH_FAILED :
1998 VoiceMediaChannel::ERROR_PLAY_SRTP_AUTH_FAILED);
1999 break;
2000 case SrtpFilter::ERROR_REPLAY:
2001 // Only receving channel should have this error.
2002 ASSERT(mode == SrtpFilter::UNPROTECT);
2003 OnVoiceChannelError(ssrc, VoiceMediaChannel::ERROR_PLAY_SRTP_REPLAY);
2004 break;
2005 default:
2006 break;
2007 }
2008}
2009
2010void VoiceChannel::GetSrtpCiphers(std::vector<std::string>* ciphers) const {
2011 GetSupportedAudioCryptoSuites(ciphers);
2012}
2013
2014VideoChannel::VideoChannel(talk_base::Thread* thread,
2015 MediaEngineInterface* media_engine,
2016 VideoMediaChannel* media_channel,
2017 BaseSession* session,
2018 const std::string& content_name,
2019 bool rtcp,
2020 VoiceChannel* voice_channel)
2021 : BaseChannel(thread, media_engine, media_channel, session, content_name,
2022 rtcp),
2023 voice_channel_(voice_channel),
2024 renderer_(NULL),
2025 screencapture_factory_(CreateScreenCapturerFactory()),
2026 previous_we_(talk_base::WE_CLOSE) {
2027}
2028
2029bool VideoChannel::Init() {
2030 TransportChannel* rtcp_channel = rtcp() ? session()->CreateChannel(
2031 content_name(), "video_rtcp", ICE_CANDIDATE_COMPONENT_RTCP) : NULL;
2032 if (!BaseChannel::Init(session()->CreateChannel(
2033 content_name(), "video_rtp", ICE_CANDIDATE_COMPONENT_RTP),
2034 rtcp_channel)) {
2035 return false;
2036 }
2037 media_channel()->SignalMediaError.connect(
2038 this, &VideoChannel::OnVideoChannelError);
2039 srtp_filter()->SignalSrtpError.connect(
2040 this, &VideoChannel::OnSrtpError);
2041 return true;
2042}
2043
2044void VoiceChannel::SendLastMediaError() {
2045 uint32 ssrc;
2046 VoiceMediaChannel::Error error;
2047 media_channel()->GetLastMediaError(&ssrc, &error);
2048 SignalMediaError(this, ssrc, error);
2049}
2050
2051VideoChannel::~VideoChannel() {
2052 std::vector<uint32> screencast_ssrcs;
2053 ScreencastMap::iterator iter;
2054 while (!screencast_capturers_.empty()) {
2055 if (!RemoveScreencast(screencast_capturers_.begin()->first)) {
2056 LOG(LS_ERROR) << "Unable to delete screencast with ssrc "
2057 << screencast_capturers_.begin()->first;
2058 ASSERT(false);
2059 break;
2060 }
2061 }
2062
2063 StopMediaMonitor();
2064 // this can't be done in the base class, since it calls a virtual
2065 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00002066
2067 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002068}
2069
2070bool VideoChannel::SetRenderer(uint32 ssrc, VideoRenderer* renderer) {
2071 VideoRenderMessageData data(ssrc, renderer);
2072 Send(MSG_SETRENDERER, &data);
2073 return true;
2074}
2075
2076bool VideoChannel::ApplyViewRequest(const ViewRequest& request) {
2077 ViewRequestMessageData data(request);
2078 Send(MSG_HANDLEVIEWREQUEST, &data);
2079 return data.result;
2080}
2081
2082VideoCapturer* VideoChannel::AddScreencast(
2083 uint32 ssrc, const ScreencastId& id) {
2084 AddScreencastMessageData data(ssrc, id);
2085 Send(MSG_ADDSCREENCAST, &data);
2086 return data.result;
2087}
2088
2089bool VideoChannel::SetCapturer(uint32 ssrc, VideoCapturer* capturer) {
2090 SetCapturerMessageData data(ssrc, capturer);
2091 Send(MSG_SETCAPTURER, &data);
2092 return data.result;
2093}
2094
2095bool VideoChannel::RemoveScreencast(uint32 ssrc) {
2096 RemoveScreencastMessageData data(ssrc);
2097 Send(MSG_REMOVESCREENCAST, &data);
2098 return data.result;
2099}
2100
2101bool VideoChannel::IsScreencasting() {
2102 IsScreencastingMessageData data;
2103 Send(MSG_ISSCREENCASTING, &data);
2104 return data.result;
2105}
2106
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00002107int VideoChannel::GetScreencastFps(uint32 ssrc) {
2108 ScreencastDetailsMessageData data(ssrc);
2109 Send(MSG_GETSCREENCASTDETAILS, &data);
2110 return data.fps;
2111}
2112
2113int VideoChannel::GetScreencastMaxPixels(uint32 ssrc) {
2114 ScreencastDetailsMessageData data(ssrc);
2115 Send(MSG_GETSCREENCASTDETAILS, &data);
2116 return data.screencast_max_pixels;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002117}
2118
2119bool VideoChannel::SendIntraFrame() {
2120 Send(MSG_SENDINTRAFRAME);
2121 return true;
2122}
2123
2124bool VideoChannel::RequestIntraFrame() {
2125 Send(MSG_REQUESTINTRAFRAME);
2126 return true;
2127}
2128
2129void VideoChannel::SetScreenCaptureFactory(
2130 ScreenCapturerFactory* screencapture_factory) {
2131 SetScreenCaptureFactoryMessageData data(screencapture_factory);
2132 Send(MSG_SETSCREENCASTFACTORY, &data);
2133}
2134
2135void VideoChannel::ChangeState() {
2136 // Render incoming data if we're the active call, and we have the local
2137 // content. We receive data on the default channel and multiplexed streams.
2138 bool recv = IsReadyToReceive();
2139 if (!media_channel()->SetRender(recv)) {
2140 LOG(LS_ERROR) << "Failed to SetRender on video channel";
2141 // TODO(gangji): Report error back to server.
2142 }
2143
2144 // Send outgoing data if we're the active call, we have the remote content,
2145 // and we have had some form of connectivity.
2146 bool send = IsReadyToSend();
2147 if (!media_channel()->SetSend(send)) {
2148 LOG(LS_ERROR) << "Failed to SetSend on video channel";
2149 // TODO(gangji): Report error back to server.
2150 }
2151
2152 LOG(LS_INFO) << "Changing video state, recv=" << recv << " send=" << send;
2153}
2154
2155bool VideoChannel::GetStats(VideoMediaInfo* stats) {
2156 VideoStatsMessageData data(stats);
2157 Send(MSG_GETSTATS, &data);
2158 return data.result;
2159}
2160
2161void VideoChannel::StartMediaMonitor(int cms) {
2162 media_monitor_.reset(new VideoMediaMonitor(media_channel(), worker_thread(),
2163 talk_base::Thread::Current()));
2164 media_monitor_->SignalUpdate.connect(
2165 this, &VideoChannel::OnMediaMonitorUpdate);
2166 media_monitor_->Start(cms);
2167}
2168
2169void VideoChannel::StopMediaMonitor() {
2170 if (media_monitor_) {
2171 media_monitor_->Stop();
2172 media_monitor_.reset();
2173 }
2174}
2175
2176const ContentInfo* VideoChannel::GetFirstContent(
2177 const SessionDescription* sdesc) {
2178 return GetFirstVideoContent(sdesc);
2179}
2180
2181bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002182 ContentAction action,
2183 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002184 ASSERT(worker_thread() == talk_base::Thread::Current());
2185 LOG(LS_INFO) << "Setting local video description";
2186
2187 const VideoContentDescription* video =
2188 static_cast<const VideoContentDescription*>(content);
2189 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002190 if (!video) {
2191 SafeSetError("Can't find video content in local description.", error_desc);
2192 return false;
2193 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002194
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002195 bool ret = SetBaseLocalContent_w(content, action, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002196 // Set local video codecs (what we want to receive).
2197 if (action != CA_UPDATE || video->has_codecs()) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002198 if (!media_channel()->SetRecvCodecs(video->codecs())) {
2199 SafeSetError("Failed to set video receive codecs.", error_desc);
2200 ret = false;
2201 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002202 }
2203
2204 if (action != CA_UPDATE) {
2205 VideoOptions video_options;
2206 media_channel()->GetOptions(&video_options);
2207 video_options.buffered_mode_latency.Set(video->buffered_mode_latency());
2208
2209 if (!media_channel()->SetOptions(video_options)) {
2210 // Log an error on failure, but don't abort the call.
2211 LOG(LS_ERROR) << "Failed to set video channel options";
2212 }
2213 }
2214
2215 // If everything worked, see if we can start receiving.
2216 if (ret) {
2217 ChangeState();
2218 } else {
2219 LOG(LS_WARNING) << "Failed to set local video description";
2220 }
2221 return ret;
2222}
2223
2224bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002225 ContentAction action,
2226 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002227 ASSERT(worker_thread() == talk_base::Thread::Current());
2228 LOG(LS_INFO) << "Setting remote video description";
2229
2230 const VideoContentDescription* video =
2231 static_cast<const VideoContentDescription*>(content);
2232 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002233 if (!video) {
2234 SafeSetError("Can't find video content in remote description.", error_desc);
2235 return false;
2236 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002237
2238 bool ret = true;
2239 // Set remote video codecs (what the other side wants to receive).
2240 if (action != CA_UPDATE || video->has_codecs()) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002241 if (!media_channel()->SetSendCodecs(video->codecs())) {
2242 SafeSetError("Failed to set video send codecs.", error_desc);
2243 ret = false;
2244 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002245 }
2246
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002247 ret &= SetBaseRemoteContent_w(content, action, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002248
2249 if (action != CA_UPDATE) {
2250 // Tweak our video processing settings, if needed.
2251 VideoOptions video_options;
2252 media_channel()->GetOptions(&video_options);
wu@webrtc.org9caf2762013-12-11 18:25:07 +00002253 if (video->conference_mode()) {
2254 video_options.conference_mode.Set(true);
2255 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002256 video_options.buffered_mode_latency.Set(video->buffered_mode_latency());
2257
2258 if (!media_channel()->SetOptions(video_options)) {
2259 // Log an error on failure, but don't abort the call.
2260 LOG(LS_ERROR) << "Failed to set video channel options";
2261 }
2262 }
2263
2264 // If everything worked, see if we can start sending.
2265 if (ret) {
2266 ChangeState();
2267 } else {
2268 LOG(LS_WARNING) << "Failed to set remote video description";
2269 }
2270 return ret;
2271}
2272
2273bool VideoChannel::ApplyViewRequest_w(const ViewRequest& request) {
2274 bool ret = true;
2275 // Set the send format for each of the local streams. If the view request
2276 // does not contain a local stream, set its send format to 0x0, which will
2277 // drop all frames.
2278 for (std::vector<StreamParams>::const_iterator it = local_streams().begin();
2279 it != local_streams().end(); ++it) {
2280 VideoFormat format(0, 0, 0, cricket::FOURCC_I420);
2281 StaticVideoViews::const_iterator view;
2282 for (view = request.static_video_views.begin();
2283 view != request.static_video_views.end(); ++view) {
2284 if (view->selector.Matches(*it)) {
2285 format.width = view->width;
2286 format.height = view->height;
2287 format.interval = cricket::VideoFormat::FpsToInterval(view->framerate);
2288 break;
2289 }
2290 }
2291
2292 ret &= media_channel()->SetSendStreamFormat(it->first_ssrc(), format);
2293 }
2294
2295 // Check if the view request has invalid streams.
2296 for (StaticVideoViews::const_iterator it = request.static_video_views.begin();
2297 it != request.static_video_views.end(); ++it) {
2298 if (!GetStream(local_streams(), it->selector, NULL)) {
2299 LOG(LS_WARNING) << "View request for ("
2300 << it->selector.ssrc << ", '"
2301 << it->selector.groupid << "', '"
2302 << it->selector.streamid << "'"
2303 << ") is not in the local streams.";
2304 }
2305 }
2306
2307 return ret;
2308}
2309
2310void VideoChannel::SetRenderer_w(uint32 ssrc, VideoRenderer* renderer) {
2311 media_channel()->SetRenderer(ssrc, renderer);
2312}
2313
2314VideoCapturer* VideoChannel::AddScreencast_w(
2315 uint32 ssrc, const ScreencastId& id) {
2316 if (screencast_capturers_.find(ssrc) != screencast_capturers_.end()) {
2317 return NULL;
2318 }
2319 VideoCapturer* screen_capturer =
2320 screencapture_factory_->CreateScreenCapturer(id);
2321 if (!screen_capturer) {
2322 return NULL;
2323 }
2324 screen_capturer->SignalStateChange.connect(this,
2325 &VideoChannel::OnStateChange);
2326 screencast_capturers_[ssrc] = screen_capturer;
2327 return screen_capturer;
2328}
2329
2330bool VideoChannel::SetCapturer_w(uint32 ssrc, VideoCapturer* capturer) {
2331 return media_channel()->SetCapturer(ssrc, capturer);
2332}
2333
2334bool VideoChannel::RemoveScreencast_w(uint32 ssrc) {
2335 ScreencastMap::iterator iter = screencast_capturers_.find(ssrc);
2336 if (iter == screencast_capturers_.end()) {
2337 return false;
2338 }
2339 // Clean up VideoCapturer.
2340 delete iter->second;
2341 screencast_capturers_.erase(iter);
2342 return true;
2343}
2344
2345bool VideoChannel::IsScreencasting_w() const {
2346 return !screencast_capturers_.empty();
2347}
2348
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00002349void VideoChannel::ScreencastDetails_w(
2350 ScreencastDetailsMessageData* data) const {
2351 ScreencastMap::const_iterator iter = screencast_capturers_.find(data->ssrc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002352 if (iter == screencast_capturers_.end()) {
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00002353 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002354 }
2355 VideoCapturer* capturer = iter->second;
2356 const VideoFormat* video_format = capturer->GetCaptureFormat();
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00002357 data->fps = VideoFormat::IntervalToFps(video_format->interval);
2358 data->screencast_max_pixels = capturer->screencast_max_pixels();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002359}
2360
2361void VideoChannel::SetScreenCaptureFactory_w(
2362 ScreenCapturerFactory* screencapture_factory) {
2363 if (screencapture_factory == NULL) {
2364 screencapture_factory_.reset(CreateScreenCapturerFactory());
2365 } else {
2366 screencapture_factory_.reset(screencapture_factory);
2367 }
2368}
2369
2370bool VideoChannel::GetStats_w(VideoMediaInfo* stats) {
2371 return media_channel()->GetStats(stats);
2372}
2373
2374void VideoChannel::OnScreencastWindowEvent_s(uint32 ssrc,
2375 talk_base::WindowEvent we) {
2376 ASSERT(signaling_thread() == talk_base::Thread::Current());
2377 SignalScreencastWindowEvent(ssrc, we);
2378}
2379
2380bool VideoChannel::SetChannelOptions(const VideoOptions &options) {
2381 VideoOptionsMessageData data(options);
2382 Send(MSG_SETCHANNELOPTIONS, &data);
2383 return data.result;
2384}
2385
2386bool VideoChannel::SetChannelOptions_w(const VideoOptions &options) {
2387 return media_channel()->SetOptions(options);
2388}
2389
2390void VideoChannel::OnMessage(talk_base::Message *pmsg) {
2391 switch (pmsg->message_id) {
2392 case MSG_SETRENDERER: {
2393 const VideoRenderMessageData* data =
2394 static_cast<VideoRenderMessageData*>(pmsg->pdata);
2395 SetRenderer_w(data->ssrc, data->renderer);
2396 break;
2397 }
2398 case MSG_ADDSCREENCAST: {
2399 AddScreencastMessageData* data =
2400 static_cast<AddScreencastMessageData*>(pmsg->pdata);
2401 data->result = AddScreencast_w(data->ssrc, data->window_id);
2402 break;
2403 }
2404 case MSG_SETCAPTURER: {
2405 SetCapturerMessageData* data =
2406 static_cast<SetCapturerMessageData*>(pmsg->pdata);
2407 data->result = SetCapturer_w(data->ssrc, data->capturer);
2408 break;
2409 }
2410 case MSG_REMOVESCREENCAST: {
2411 RemoveScreencastMessageData* data =
2412 static_cast<RemoveScreencastMessageData*>(pmsg->pdata);
2413 data->result = RemoveScreencast_w(data->ssrc);
2414 break;
2415 }
2416 case MSG_SCREENCASTWINDOWEVENT: {
2417 const ScreencastEventMessageData* data =
2418 static_cast<ScreencastEventMessageData*>(pmsg->pdata);
2419 OnScreencastWindowEvent_s(data->ssrc, data->event);
2420 delete data;
2421 break;
2422 }
2423 case MSG_ISSCREENCASTING: {
2424 IsScreencastingMessageData* data =
2425 static_cast<IsScreencastingMessageData*>(pmsg->pdata);
2426 data->result = IsScreencasting_w();
2427 break;
2428 }
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00002429 case MSG_GETSCREENCASTDETAILS: {
2430 ScreencastDetailsMessageData* data =
2431 static_cast<ScreencastDetailsMessageData*>(pmsg->pdata);
2432 ScreencastDetails_w(data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002433 break;
2434 }
2435 case MSG_SENDINTRAFRAME: {
2436 SendIntraFrame_w();
2437 break;
2438 }
2439 case MSG_REQUESTINTRAFRAME: {
2440 RequestIntraFrame_w();
2441 break;
2442 }
2443 case MSG_SETCHANNELOPTIONS: {
2444 VideoOptionsMessageData* data =
2445 static_cast<VideoOptionsMessageData*>(pmsg->pdata);
2446 data->result = SetChannelOptions_w(data->options);
2447 break;
2448 }
2449 case MSG_CHANNEL_ERROR: {
2450 const VideoChannelErrorMessageData* data =
2451 static_cast<VideoChannelErrorMessageData*>(pmsg->pdata);
2452 SignalMediaError(this, data->ssrc, data->error);
2453 delete data;
2454 break;
2455 }
2456 case MSG_HANDLEVIEWREQUEST: {
2457 ViewRequestMessageData* data =
2458 static_cast<ViewRequestMessageData*>(pmsg->pdata);
2459 data->result = ApplyViewRequest_w(data->request);
2460 break;
2461 }
2462 case MSG_SETSCREENCASTFACTORY: {
2463 SetScreenCaptureFactoryMessageData* data =
2464 static_cast<SetScreenCaptureFactoryMessageData*>(pmsg->pdata);
2465 SetScreenCaptureFactory_w(data->screencapture_factory);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002466 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002467 }
2468 case MSG_GETSTATS: {
2469 VideoStatsMessageData* data =
2470 static_cast<VideoStatsMessageData*>(pmsg->pdata);
2471 data->result = GetStats_w(data->stats);
2472 break;
2473 }
2474 default:
2475 BaseChannel::OnMessage(pmsg);
2476 break;
2477 }
2478}
2479
2480void VideoChannel::OnConnectionMonitorUpdate(
2481 SocketMonitor *monitor, const std::vector<ConnectionInfo> &infos) {
2482 SignalConnectionMonitor(this, infos);
2483}
2484
2485// TODO(pthatcher): Look into removing duplicate code between
2486// audio, video, and data, perhaps by using templates.
2487void VideoChannel::OnMediaMonitorUpdate(
2488 VideoMediaChannel* media_channel, const VideoMediaInfo &info) {
2489 ASSERT(media_channel == this->media_channel());
2490 SignalMediaMonitor(this, info);
2491}
2492
2493void VideoChannel::OnScreencastWindowEvent(uint32 ssrc,
2494 talk_base::WindowEvent event) {
2495 ScreencastEventMessageData* pdata =
2496 new ScreencastEventMessageData(ssrc, event);
2497 signaling_thread()->Post(this, MSG_SCREENCASTWINDOWEVENT, pdata);
2498}
2499
2500void VideoChannel::OnStateChange(VideoCapturer* capturer, CaptureState ev) {
2501 // Map capturer events to window events. In the future we may want to simply
2502 // pass these events up directly.
2503 talk_base::WindowEvent we;
2504 if (ev == CS_STOPPED) {
2505 we = talk_base::WE_CLOSE;
2506 } else if (ev == CS_PAUSED) {
2507 we = talk_base::WE_MINIMIZE;
2508 } else if (ev == CS_RUNNING && previous_we_ == talk_base::WE_MINIMIZE) {
2509 we = talk_base::WE_RESTORE;
2510 } else {
2511 return;
2512 }
2513 previous_we_ = we;
2514
2515 uint32 ssrc = 0;
2516 if (!GetLocalSsrc(capturer, &ssrc)) {
2517 return;
2518 }
2519 ScreencastEventMessageData* pdata =
2520 new ScreencastEventMessageData(ssrc, we);
2521 signaling_thread()->Post(this, MSG_SCREENCASTWINDOWEVENT, pdata);
2522}
2523
2524bool VideoChannel::GetLocalSsrc(const VideoCapturer* capturer, uint32* ssrc) {
2525 *ssrc = 0;
2526 for (ScreencastMap::iterator iter = screencast_capturers_.begin();
2527 iter != screencast_capturers_.end(); ++iter) {
2528 if (iter->second == capturer) {
2529 *ssrc = iter->first;
2530 return true;
2531 }
2532 }
2533 return false;
2534}
2535
2536void VideoChannel::OnVideoChannelError(uint32 ssrc,
2537 VideoMediaChannel::Error error) {
2538 VideoChannelErrorMessageData* data = new VideoChannelErrorMessageData(
2539 ssrc, error);
2540 signaling_thread()->Post(this, MSG_CHANNEL_ERROR, data);
2541}
2542
2543void VideoChannel::OnSrtpError(uint32 ssrc, SrtpFilter::Mode mode,
2544 SrtpFilter::Error error) {
2545 switch (error) {
2546 case SrtpFilter::ERROR_FAIL:
2547 OnVideoChannelError(ssrc, (mode == SrtpFilter::PROTECT) ?
2548 VideoMediaChannel::ERROR_REC_SRTP_ERROR :
2549 VideoMediaChannel::ERROR_PLAY_SRTP_ERROR);
2550 break;
2551 case SrtpFilter::ERROR_AUTH:
2552 OnVideoChannelError(ssrc, (mode == SrtpFilter::PROTECT) ?
2553 VideoMediaChannel::ERROR_REC_SRTP_AUTH_FAILED :
2554 VideoMediaChannel::ERROR_PLAY_SRTP_AUTH_FAILED);
2555 break;
2556 case SrtpFilter::ERROR_REPLAY:
2557 // Only receving channel should have this error.
2558 ASSERT(mode == SrtpFilter::UNPROTECT);
2559 // TODO(gangji): Turn on the signaling of replay error once we have
2560 // switched to the new mechanism for doing video retransmissions.
2561 // OnVideoChannelError(ssrc, VideoMediaChannel::ERROR_PLAY_SRTP_REPLAY);
2562 break;
2563 default:
2564 break;
2565 }
2566}
2567
2568
2569void VideoChannel::GetSrtpCiphers(std::vector<std::string>* ciphers) const {
2570 GetSupportedVideoCryptoSuites(ciphers);
2571}
2572
2573DataChannel::DataChannel(talk_base::Thread* thread,
2574 DataMediaChannel* media_channel,
2575 BaseSession* session,
2576 const std::string& content_name,
2577 bool rtcp)
2578 // MediaEngine is NULL
2579 : BaseChannel(thread, NULL, media_channel, session, content_name, rtcp),
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002580 data_channel_type_(cricket::DCT_NONE),
2581 ready_to_send_data_(false) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002582}
2583
2584DataChannel::~DataChannel() {
2585 StopMediaMonitor();
2586 // this can't be done in the base class, since it calls a virtual
2587 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00002588
2589 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002590}
2591
2592bool DataChannel::Init() {
2593 TransportChannel* rtcp_channel = rtcp() ? session()->CreateChannel(
2594 content_name(), "data_rtcp", ICE_CANDIDATE_COMPONENT_RTCP) : NULL;
2595 if (!BaseChannel::Init(session()->CreateChannel(
2596 content_name(), "data_rtp", ICE_CANDIDATE_COMPONENT_RTP),
2597 rtcp_channel)) {
2598 return false;
2599 }
2600 media_channel()->SignalDataReceived.connect(
2601 this, &DataChannel::OnDataReceived);
2602 media_channel()->SignalMediaError.connect(
2603 this, &DataChannel::OnDataChannelError);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002604 media_channel()->SignalReadyToSend.connect(
2605 this, &DataChannel::OnDataChannelReadyToSend);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002606 srtp_filter()->SignalSrtpError.connect(
2607 this, &DataChannel::OnSrtpError);
2608 return true;
2609}
2610
2611bool DataChannel::SendData(const SendDataParams& params,
2612 const talk_base::Buffer& payload,
2613 SendDataResult* result) {
2614 SendDataMessageData message_data(params, &payload, result);
2615 Send(MSG_SENDDATA, &message_data);
2616 return message_data.succeeded;
2617}
2618
2619const ContentInfo* DataChannel::GetFirstContent(
2620 const SessionDescription* sdesc) {
2621 return GetFirstDataContent(sdesc);
2622}
2623
2624
2625static bool IsRtpPacket(const talk_base::Buffer* packet) {
2626 int version;
2627 if (!GetRtpVersion(packet->data(), packet->length(), &version)) {
2628 return false;
2629 }
2630
2631 return version == 2;
2632}
2633
2634bool DataChannel::WantsPacket(bool rtcp, talk_base::Buffer* packet) {
2635 if (data_channel_type_ == DCT_SCTP) {
2636 // TODO(pthatcher): Do this in a more robust way by checking for
2637 // SCTP or DTLS.
2638 return !IsRtpPacket(packet);
2639 } else if (data_channel_type_ == DCT_RTP) {
2640 return BaseChannel::WantsPacket(rtcp, packet);
2641 }
2642 return false;
2643}
2644
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002645bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type,
2646 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002647 // It hasn't been set before, so set it now.
2648 if (data_channel_type_ == DCT_NONE) {
2649 data_channel_type_ = new_data_channel_type;
2650 return true;
2651 }
2652
2653 // It's been set before, but doesn't match. That's bad.
2654 if (data_channel_type_ != new_data_channel_type) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002655 std::ostringstream desc;
2656 desc << "Data channel type mismatch."
2657 << " Expected " << data_channel_type_
2658 << " Got " << new_data_channel_type;
2659 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002660 return false;
2661 }
2662
2663 // It's hasn't changed. Nothing to do.
2664 return true;
2665}
2666
2667bool DataChannel::SetDataChannelTypeFromContent(
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002668 const DataContentDescription* content,
2669 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002670 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
2671 (content->protocol() == kMediaProtocolDtlsSctp));
2672 DataChannelType data_channel_type = is_sctp ? DCT_SCTP : DCT_RTP;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002673 return SetDataChannelType(data_channel_type, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002674}
2675
2676bool DataChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002677 ContentAction action,
2678 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002679 ASSERT(worker_thread() == talk_base::Thread::Current());
2680 LOG(LS_INFO) << "Setting local data description";
2681
2682 const DataContentDescription* data =
2683 static_cast<const DataContentDescription*>(content);
2684 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002685 if (!data) {
2686 SafeSetError("Can't find data content in local description.", error_desc);
2687 return false;
2688 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002689
2690 bool ret = false;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002691 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002692 return false;
2693 }
2694
2695 if (data_channel_type_ == DCT_SCTP) {
2696 // SCTP data channels don't need the rest of the stuff.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002697 ret = UpdateLocalStreams_w(data->streams(), action, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002698 if (ret) {
2699 set_local_content_direction(content->direction());
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002700 // As in SetRemoteContent_w, make sure we set the local SCTP port
2701 // number as specified in our DataContentDescription.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002702 if (!media_channel()->SetRecvCodecs(data->codecs())) {
2703 SafeSetError("Failed to set data receive codecs.", error_desc);
2704 ret = false;
2705 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002706 }
2707 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002708 ret = SetBaseLocalContent_w(content, action, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002709
2710 if (action != CA_UPDATE || data->has_codecs()) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002711 if (!media_channel()->SetRecvCodecs(data->codecs())) {
2712 SafeSetError("Failed to set data receive codecs.", error_desc);
2713 ret = false;
2714 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002715 }
2716 }
2717
2718 // If everything worked, see if we can start receiving.
2719 if (ret) {
2720 ChangeState();
2721 } else {
2722 LOG(LS_WARNING) << "Failed to set local data description";
2723 }
2724 return ret;
2725}
2726
2727bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002728 ContentAction action,
2729 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002730 ASSERT(worker_thread() == talk_base::Thread::Current());
2731
2732 const DataContentDescription* data =
2733 static_cast<const DataContentDescription*>(content);
2734 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002735 if (!data) {
2736 SafeSetError("Can't find data content in remote description.", error_desc);
2737 return false;
2738 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002739
2740 bool ret = true;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002741 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002742 return false;
2743 }
2744
2745 if (data_channel_type_ == DCT_SCTP) {
2746 LOG(LS_INFO) << "Setting SCTP remote data description";
2747 // SCTP data channels don't need the rest of the stuff.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002748 ret = UpdateRemoteStreams_w(content->streams(), action, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002749 if (ret) {
2750 set_remote_content_direction(content->direction());
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002751 // We send the SCTP port number (not to be confused with the underlying
2752 // UDP port number) as a codec parameter. Make sure it gets there.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002753 if (!media_channel()->SetSendCodecs(data->codecs())) {
2754 SafeSetError("Failed to set data send codecs.", error_desc);
2755 ret = false;
2756 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002757 }
2758 } else {
2759 // If the remote data doesn't have codecs and isn't an update, it
2760 // must be empty, so ignore it.
2761 if (action != CA_UPDATE && !data->has_codecs()) {
2762 return true;
2763 }
2764 LOG(LS_INFO) << "Setting remote data description";
2765
2766 // Set remote video codecs (what the other side wants to receive).
2767 if (action != CA_UPDATE || data->has_codecs()) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002768 if (!media_channel()->SetSendCodecs(data->codecs())) {
2769 SafeSetError("Failed to set data send codecs.", error_desc);
2770 ret = false;
2771 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002772 }
2773
2774 if (ret) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002775 ret &= SetBaseRemoteContent_w(content, action, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002776 }
2777
2778 if (action != CA_UPDATE) {
2779 int bandwidth_bps = data->bandwidth();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002780 if (!media_channel()->SetMaxSendBandwidth(bandwidth_bps)) {
2781 std::ostringstream desc;
2782 desc << "Failed to set max send bandwidth for data content.";
2783 SafeSetError(desc.str(), error_desc);
2784 ret = false;
2785 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002786 }
2787 }
2788
2789 // If everything worked, see if we can start sending.
2790 if (ret) {
2791 ChangeState();
2792 } else {
2793 LOG(LS_WARNING) << "Failed to set remote data description";
2794 }
2795 return ret;
2796}
2797
2798void DataChannel::ChangeState() {
2799 // Render incoming data if we're the active call, and we have the local
2800 // content. We receive data on the default channel and multiplexed streams.
2801 bool recv = IsReadyToReceive();
2802 if (!media_channel()->SetReceive(recv)) {
2803 LOG(LS_ERROR) << "Failed to SetReceive on data channel";
2804 }
2805
2806 // Send outgoing data if we're the active call, we have the remote content,
2807 // and we have had some form of connectivity.
2808 bool send = IsReadyToSend();
2809 if (!media_channel()->SetSend(send)) {
2810 LOG(LS_ERROR) << "Failed to SetSend on data channel";
2811 }
2812
2813 // Post to trigger SignalReadyToSendData.
2814 signaling_thread()->Post(this, MSG_READYTOSENDDATA,
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002815 new DataChannelReadyToSendMessageData(send));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002816
2817 LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
2818}
2819
2820void DataChannel::OnMessage(talk_base::Message *pmsg) {
2821 switch (pmsg->message_id) {
2822 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002823 DataChannelReadyToSendMessageData* data =
2824 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002825 ready_to_send_data_ = data->data();
2826 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002827 delete data;
2828 break;
2829 }
2830 case MSG_SENDDATA: {
2831 SendDataMessageData* msg =
2832 static_cast<SendDataMessageData*>(pmsg->pdata);
2833 msg->succeeded = media_channel()->SendData(
2834 msg->params, *(msg->payload), msg->result);
2835 break;
2836 }
2837 case MSG_DATARECEIVED: {
2838 DataReceivedMessageData* data =
2839 static_cast<DataReceivedMessageData*>(pmsg->pdata);
2840 SignalDataReceived(this, data->params, data->payload);
2841 delete data;
2842 break;
2843 }
2844 case MSG_CHANNEL_ERROR: {
2845 const DataChannelErrorMessageData* data =
2846 static_cast<DataChannelErrorMessageData*>(pmsg->pdata);
2847 SignalMediaError(this, data->ssrc, data->error);
2848 delete data;
2849 break;
2850 }
2851 default:
2852 BaseChannel::OnMessage(pmsg);
2853 break;
2854 }
2855}
2856
2857void DataChannel::OnConnectionMonitorUpdate(
2858 SocketMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
2859 SignalConnectionMonitor(this, infos);
2860}
2861
2862void DataChannel::StartMediaMonitor(int cms) {
2863 media_monitor_.reset(new DataMediaMonitor(media_channel(), worker_thread(),
2864 talk_base::Thread::Current()));
2865 media_monitor_->SignalUpdate.connect(
2866 this, &DataChannel::OnMediaMonitorUpdate);
2867 media_monitor_->Start(cms);
2868}
2869
2870void DataChannel::StopMediaMonitor() {
2871 if (media_monitor_) {
2872 media_monitor_->Stop();
2873 media_monitor_->SignalUpdate.disconnect(this);
2874 media_monitor_.reset();
2875 }
2876}
2877
2878void DataChannel::OnMediaMonitorUpdate(
2879 DataMediaChannel* media_channel, const DataMediaInfo& info) {
2880 ASSERT(media_channel == this->media_channel());
2881 SignalMediaMonitor(this, info);
2882}
2883
2884void DataChannel::OnDataReceived(
2885 const ReceiveDataParams& params, const char* data, size_t len) {
2886 DataReceivedMessageData* msg = new DataReceivedMessageData(
2887 params, data, len);
2888 signaling_thread()->Post(this, MSG_DATARECEIVED, msg);
2889}
2890
2891void DataChannel::OnDataChannelError(
2892 uint32 ssrc, DataMediaChannel::Error err) {
2893 DataChannelErrorMessageData* data = new DataChannelErrorMessageData(
2894 ssrc, err);
2895 signaling_thread()->Post(this, MSG_CHANNEL_ERROR, data);
2896}
2897
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002898void DataChannel::OnDataChannelReadyToSend(bool writable) {
2899 // This is usded for congestion control to indicate that the stream is ready
2900 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
2901 // that the transport channel is ready.
2902 signaling_thread()->Post(this, MSG_READYTOSENDDATA,
2903 new DataChannelReadyToSendMessageData(writable));
2904}
2905
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002906void DataChannel::OnSrtpError(uint32 ssrc, SrtpFilter::Mode mode,
2907 SrtpFilter::Error error) {
2908 switch (error) {
2909 case SrtpFilter::ERROR_FAIL:
2910 OnDataChannelError(ssrc, (mode == SrtpFilter::PROTECT) ?
2911 DataMediaChannel::ERROR_SEND_SRTP_ERROR :
2912 DataMediaChannel::ERROR_RECV_SRTP_ERROR);
2913 break;
2914 case SrtpFilter::ERROR_AUTH:
2915 OnDataChannelError(ssrc, (mode == SrtpFilter::PROTECT) ?
2916 DataMediaChannel::ERROR_SEND_SRTP_AUTH_FAILED :
2917 DataMediaChannel::ERROR_RECV_SRTP_AUTH_FAILED);
2918 break;
2919 case SrtpFilter::ERROR_REPLAY:
2920 // Only receving channel should have this error.
2921 ASSERT(mode == SrtpFilter::UNPROTECT);
2922 OnDataChannelError(ssrc, DataMediaChannel::ERROR_RECV_SRTP_REPLAY);
2923 break;
2924 default:
2925 break;
2926 }
2927}
2928
2929void DataChannel::GetSrtpCiphers(std::vector<std::string>* ciphers) const {
2930 GetSupportedDataCryptoSuites(ciphers);
2931}
2932
2933bool DataChannel::ShouldSetupDtlsSrtp() const {
2934 return (data_channel_type_ == DCT_RTP);
2935}
2936
2937} // namespace cricket