Index: webrtc/pc/channel.cc |
diff --git a/webrtc/pc/channel.cc b/webrtc/pc/channel.cc |
index 56335e24d085c74c37050233eb6ca6b73b75adaa..1f29261ed2532bdf7422792b5e9878b7a06e3efc 100644 |
--- a/webrtc/pc/channel.cc |
+++ b/webrtc/pc/channel.cc |
@@ -69,6 +69,7 @@ enum { |
MSG_READYTOSENDDATA, |
MSG_DATARECEIVED, |
MSG_FIRSTPACKETRECEIVED, |
+ MSG_STREAMCLOSEDREMOTELY, |
}; |
// Value specified in RFC 5764. |
@@ -930,16 +931,16 @@ void BaseChannel::ChannelWritable_n() { |
UpdateMediaSendRecvState(); |
} |
-void BaseChannel::SignalDtlsSrtpSetupFailure_n(bool rtcp) { |
+void BaseChannel::SignalDtlsSetupFailure_n(bool rtcp) { |
RTC_DCHECK(network_thread_->IsCurrent()); |
invoker_.AsyncInvoke<void>( |
RTC_FROM_HERE, signaling_thread(), |
- Bind(&BaseChannel::SignalDtlsSrtpSetupFailure_s, this, rtcp)); |
+ Bind(&BaseChannel::SignalDtlsSetupFailure_s, this, rtcp)); |
} |
-void BaseChannel::SignalDtlsSrtpSetupFailure_s(bool rtcp) { |
+void BaseChannel::SignalDtlsSetupFailure_s(bool rtcp) { |
RTC_DCHECK(signaling_thread() == rtc::Thread::Current()); |
- SignalDtlsSrtpSetupFailure(this, rtcp); |
+ SignalDtlsSetupFailure(this, rtcp); |
} |
bool BaseChannel::SetDtlsSrtpCryptoSuites_n(TransportChannel* tc, bool rtcp) { |
@@ -1060,13 +1061,13 @@ void BaseChannel::MaybeSetupDtlsSrtp_n() { |
} |
if (!SetupDtlsSrtp_n(false)) { |
- SignalDtlsSrtpSetupFailure_n(false); |
+ SignalDtlsSetupFailure_n(false); |
return; |
} |
if (rtcp_transport_channel_) { |
if (!SetupDtlsSrtp_n(true)) { |
- SignalDtlsSrtpSetupFailure_n(true); |
+ SignalDtlsSetupFailure_n(true); |
return; |
} |
} |
@@ -2146,23 +2147,25 @@ void VideoChannel::GetSrtpCryptoSuites_n( |
GetSupportedVideoCryptoSuites(crypto_options(), crypto_suites); |
} |
-RtpDataChannel::RtpDataChannel(rtc::Thread* worker_thread, |
- rtc::Thread* network_thread, |
- DataMediaChannel* media_channel, |
- TransportController* transport_controller, |
- const std::string& content_name, |
- bool rtcp, |
- bool srtp_required) |
+DataChannel::DataChannel(rtc::Thread* worker_thread, |
+ rtc::Thread* network_thread, |
+ DataMediaChannel* media_channel, |
+ TransportController* transport_controller, |
+ const std::string& content_name, |
+ bool rtcp, |
+ bool srtp_required) |
: BaseChannel(worker_thread, |
network_thread, |
media_channel, |
transport_controller, |
content_name, |
rtcp, |
- srtp_required) {} |
+ srtp_required), |
+ data_channel_type_(cricket::DCT_NONE), |
+ ready_to_send_data_(false) {} |
-RtpDataChannel::~RtpDataChannel() { |
- TRACE_EVENT0("webrtc", "RtpDataChannel::~RtpDataChannel"); |
+DataChannel::~DataChannel() { |
+ TRACE_EVENT0("webrtc", "DataChannel::~DataChannel"); |
StopMediaMonitor(); |
// this can't be done in the base class, since it calls a virtual |
DisableMedia_w(); |
@@ -2170,48 +2173,78 @@ RtpDataChannel::~RtpDataChannel() { |
Deinit(); |
} |
-bool RtpDataChannel::Init_w(const std::string* bundle_transport_name) { |
+bool DataChannel::Init_w(const std::string* bundle_transport_name) { |
if (!BaseChannel::Init_w(bundle_transport_name)) { |
return false; |
} |
- media_channel()->SignalDataReceived.connect(this, |
- &RtpDataChannel::OnDataReceived); |
+ media_channel()->SignalDataReceived.connect( |
+ this, &DataChannel::OnDataReceived); |
media_channel()->SignalReadyToSend.connect( |
- this, &RtpDataChannel::OnDataChannelReadyToSend); |
+ this, &DataChannel::OnDataChannelReadyToSend); |
+ media_channel()->SignalStreamClosedRemotely.connect( |
+ this, &DataChannel::OnStreamClosedRemotely); |
return true; |
} |
-bool RtpDataChannel::SendData(const SendDataParams& params, |
- const rtc::CopyOnWriteBuffer& payload, |
- SendDataResult* result) { |
+bool DataChannel::SendData(const SendDataParams& params, |
+ const rtc::CopyOnWriteBuffer& payload, |
+ SendDataResult* result) { |
return InvokeOnWorker( |
RTC_FROM_HERE, Bind(&DataMediaChannel::SendData, media_channel(), params, |
payload, result)); |
} |
-const ContentInfo* RtpDataChannel::GetFirstContent( |
+const ContentInfo* DataChannel::GetFirstContent( |
const SessionDescription* sdesc) { |
return GetFirstDataContent(sdesc); |
} |
-bool RtpDataChannel::CheckDataChannelTypeFromContent( |
- const DataContentDescription* content, |
- std::string* error_desc) { |
- bool is_sctp = ((content->protocol() == kMediaProtocolSctp) || |
- (content->protocol() == kMediaProtocolDtlsSctp)); |
+bool DataChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) { |
+ if (data_channel_type_ == DCT_SCTP) { |
+ // TODO(pthatcher): Do this in a more robust way by checking for |
+ // SCTP or DTLS. |
+ return !IsRtpPacket(packet->data(), packet->size()); |
+ } else if (data_channel_type_ == DCT_RTP) { |
+ return BaseChannel::WantsPacket(rtcp, packet); |
+ } |
+ return false; |
+} |
+ |
+bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type, |
+ std::string* error_desc) { |
+ // It hasn't been set before, so set it now. |
+ if (data_channel_type_ == DCT_NONE) { |
+ data_channel_type_ = new_data_channel_type; |
+ return true; |
+ } |
+ |
// It's been set before, but doesn't match. That's bad. |
- if (is_sctp) { |
- SafeSetError("Data channel type mismatch. Expected RTP, got SCTP.", |
- error_desc); |
+ if (data_channel_type_ != new_data_channel_type) { |
+ std::ostringstream desc; |
+ desc << "Data channel type mismatch." |
+ << " Expected " << data_channel_type_ |
+ << " Got " << new_data_channel_type; |
+ SafeSetError(desc.str(), error_desc); |
return false; |
} |
+ |
+ // It's hasn't changed. Nothing to do. |
return true; |
} |
-bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content, |
- ContentAction action, |
- std::string* error_desc) { |
- TRACE_EVENT0("webrtc", "RtpDataChannel::SetLocalContent_w"); |
+bool DataChannel::SetDataChannelTypeFromContent( |
+ const DataContentDescription* content, |
+ std::string* error_desc) { |
+ bool is_sctp = ((content->protocol() == kMediaProtocolSctp) || |
+ (content->protocol() == kMediaProtocolDtlsSctp)); |
+ DataChannelType data_channel_type = is_sctp ? DCT_SCTP : DCT_RTP; |
+ return SetDataChannelType(data_channel_type, error_desc); |
+} |
+ |
+bool DataChannel::SetLocalContent_w(const MediaContentDescription* content, |
+ ContentAction action, |
+ std::string* error_desc) { |
+ TRACE_EVENT0("webrtc", "DataChannel::SetLocalContent_w"); |
RTC_DCHECK(worker_thread() == rtc::Thread::Current()); |
LOG(LS_INFO) << "Setting local data description"; |
@@ -2223,14 +2256,19 @@ bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content, |
return false; |
} |
- if (!CheckDataChannelTypeFromContent(data, error_desc)) { |
+ if (!SetDataChannelTypeFromContent(data, error_desc)) { |
return false; |
} |
- if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) { |
- return false; |
+ if (data_channel_type_ == DCT_RTP) { |
+ if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) { |
+ return false; |
+ } |
} |
+ // FYI: We send the SCTP port number (not to be confused with the |
+ // underlying UDP port number) as a codec parameter. So even SCTP |
+ // data channels need codecs. |
DataRecvParameters recv_params = last_recv_params_; |
RtpParametersFromMediaDescription(data, &recv_params); |
if (!media_channel()->SetRecvParameters(recv_params)) { |
@@ -2238,8 +2276,10 @@ bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content, |
error_desc); |
return false; |
} |
- for (const DataCodec& codec : data->codecs()) { |
- bundle_filter()->AddPayloadType(codec.id); |
+ if (data_channel_type_ == DCT_RTP) { |
+ for (const DataCodec& codec : data->codecs()) { |
+ bundle_filter()->AddPayloadType(codec.id); |
+ } |
} |
last_recv_params_ = recv_params; |
@@ -2257,10 +2297,10 @@ bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content, |
return true; |
} |
-bool RtpDataChannel::SetRemoteContent_w(const MediaContentDescription* content, |
- ContentAction action, |
- std::string* error_desc) { |
- TRACE_EVENT0("webrtc", "RtpDataChannel::SetRemoteContent_w"); |
+bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content, |
+ ContentAction action, |
+ std::string* error_desc) { |
+ TRACE_EVENT0("webrtc", "DataChannel::SetRemoteContent_w"); |
RTC_DCHECK(worker_thread() == rtc::Thread::Current()); |
const DataContentDescription* data = |
@@ -2277,15 +2317,17 @@ bool RtpDataChannel::SetRemoteContent_w(const MediaContentDescription* content, |
return true; |
} |
- if (!CheckDataChannelTypeFromContent(data, error_desc)) { |
+ if (!SetDataChannelTypeFromContent(data, error_desc)) { |
return false; |
} |
LOG(LS_INFO) << "Setting remote data description"; |
- if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) { |
+ if (data_channel_type_ == DCT_RTP && |
+ !SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) { |
return false; |
} |
+ |
DataSendParameters send_params = last_send_params_; |
RtpSendParametersFromMediaDescription<DataCodec>(data, &send_params); |
if (!media_channel()->SetSendParameters(send_params)) { |
@@ -2310,7 +2352,7 @@ bool RtpDataChannel::SetRemoteContent_w(const MediaContentDescription* content, |
return true; |
} |
-void RtpDataChannel::UpdateMediaSendRecvState_w() { |
+void DataChannel::UpdateMediaSendRecvState_w() { |
// Render incoming data if we're the active call, and we have the local |
// content. We receive data on the default channel and multiplexed streams. |
bool recv = IsReadyToReceiveMedia_w(); |
@@ -2331,7 +2373,7 @@ void RtpDataChannel::UpdateMediaSendRecvState_w() { |
LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send; |
} |
-void RtpDataChannel::OnMessage(rtc::Message* pmsg) { |
+void DataChannel::OnMessage(rtc::Message *pmsg) { |
switch (pmsg->message_id) { |
case MSG_READYTOSENDDATA: { |
DataChannelReadyToSendMessageData* data = |
@@ -2344,7 +2386,7 @@ void RtpDataChannel::OnMessage(rtc::Message* pmsg) { |
case MSG_DATARECEIVED: { |
DataReceivedMessageData* data = |
static_cast<DataReceivedMessageData*>(pmsg->pdata); |
- SignalDataReceived(data->params, data->payload); |
+ SignalDataReceived(this, data->params, data->payload); |
delete data; |
break; |
} |
@@ -2354,27 +2396,33 @@ void RtpDataChannel::OnMessage(rtc::Message* pmsg) { |
delete data; |
break; |
} |
+ case MSG_STREAMCLOSEDREMOTELY: { |
+ rtc::TypedMessageData<uint32_t>* data = |
+ static_cast<rtc::TypedMessageData<uint32_t>*>(pmsg->pdata); |
+ SignalStreamClosedRemotely(data->data()); |
+ delete data; |
+ break; |
+ } |
default: |
BaseChannel::OnMessage(pmsg); |
break; |
} |
} |
-void RtpDataChannel::OnConnectionMonitorUpdate( |
- ConnectionMonitor* monitor, |
- const std::vector<ConnectionInfo>& infos) { |
+void DataChannel::OnConnectionMonitorUpdate( |
+ ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) { |
SignalConnectionMonitor(this, infos); |
} |
-void RtpDataChannel::StartMediaMonitor(int cms) { |
+void DataChannel::StartMediaMonitor(int cms) { |
media_monitor_.reset(new DataMediaMonitor(media_channel(), worker_thread(), |
rtc::Thread::Current())); |
- media_monitor_->SignalUpdate.connect(this, |
- &RtpDataChannel::OnMediaMonitorUpdate); |
+ media_monitor_->SignalUpdate.connect( |
+ this, &DataChannel::OnMediaMonitorUpdate); |
media_monitor_->Start(cms); |
} |
-void RtpDataChannel::StopMediaMonitor() { |
+void DataChannel::StopMediaMonitor() { |
if (media_monitor_) { |
media_monitor_->Stop(); |
media_monitor_->SignalUpdate.disconnect(this); |
@@ -2382,28 +2430,27 @@ void RtpDataChannel::StopMediaMonitor() { |
} |
} |
-void RtpDataChannel::OnMediaMonitorUpdate(DataMediaChannel* media_channel, |
- const DataMediaInfo& info) { |
+void DataChannel::OnMediaMonitorUpdate( |
+ DataMediaChannel* media_channel, const DataMediaInfo& info) { |
RTC_DCHECK(media_channel == this->media_channel()); |
SignalMediaMonitor(this, info); |
} |
-void RtpDataChannel::OnDataReceived(const ReceiveDataParams& params, |
- const char* data, |
- size_t len) { |
+void DataChannel::OnDataReceived( |
+ const ReceiveDataParams& params, const char* data, size_t len) { |
DataReceivedMessageData* msg = new DataReceivedMessageData( |
params, data, len); |
signaling_thread()->Post(RTC_FROM_HERE, this, MSG_DATARECEIVED, msg); |
} |
-void RtpDataChannel::OnDataChannelError(uint32_t ssrc, |
- DataMediaChannel::Error err) { |
+void DataChannel::OnDataChannelError(uint32_t ssrc, |
+ DataMediaChannel::Error err) { |
DataChannelErrorMessageData* data = new DataChannelErrorMessageData( |
ssrc, err); |
signaling_thread()->Post(RTC_FROM_HERE, this, MSG_CHANNEL_ERROR, data); |
} |
-void RtpDataChannel::OnDataChannelReadyToSend(bool writable) { |
+void DataChannel::OnDataChannelReadyToSend(bool writable) { |
// This is usded for congestion control to indicate that the stream is ready |
// to send by the MediaChannel, as opposed to OnReadyToSend, which indicates |
// that the transport channel is ready. |
@@ -2411,9 +2458,19 @@ void RtpDataChannel::OnDataChannelReadyToSend(bool writable) { |
new DataChannelReadyToSendMessageData(writable)); |
} |
-void RtpDataChannel::GetSrtpCryptoSuites_n( |
- std::vector<int>* crypto_suites) const { |
+void DataChannel::GetSrtpCryptoSuites_n(std::vector<int>* crypto_suites) const { |
GetSupportedDataCryptoSuites(crypto_options(), crypto_suites); |
} |
+bool DataChannel::ShouldSetupDtlsSrtp_n() const { |
+ return data_channel_type_ == DCT_RTP && BaseChannel::ShouldSetupDtlsSrtp_n(); |
+} |
+ |
+void DataChannel::OnStreamClosedRemotely(uint32_t sid) { |
+ rtc::TypedMessageData<uint32_t>* message = |
+ new rtc::TypedMessageData<uint32_t>(sid); |
+ signaling_thread()->Post(RTC_FROM_HERE, this, MSG_STREAMCLOSEDREMOTELY, |
+ message); |
+} |
+ |
} // namespace cricket |