2013-07-10 02:45:36 +02:00
|
|
|
/*
|
|
|
|
* libjingle
|
|
|
|
* Copyright 2004--2005, Google Inc.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
|
|
|
*
|
|
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
|
|
* and/or other materials provided with the distribution.
|
|
|
|
* 3. The name of the author may not be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
|
|
|
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "talk/p2p/base/transportchannelproxy.h"
|
|
|
|
#include "talk/base/common.h"
|
2013-09-28 01:04:10 +02:00
|
|
|
#include "talk/base/logging.h"
|
2013-07-10 02:45:36 +02:00
|
|
|
#include "talk/base/thread.h"
|
|
|
|
#include "talk/p2p/base/transport.h"
|
|
|
|
#include "talk/p2p/base/transportchannelimpl.h"
|
|
|
|
|
|
|
|
namespace cricket {
|
|
|
|
|
|
|
|
enum {
|
|
|
|
MSG_UPDATESTATE,
|
|
|
|
};
|
|
|
|
|
|
|
|
TransportChannelProxy::TransportChannelProxy(const std::string& content_name,
|
|
|
|
const std::string& name,
|
|
|
|
int component)
|
|
|
|
: TransportChannel(content_name, component),
|
|
|
|
name_(name),
|
|
|
|
impl_(NULL) {
|
|
|
|
worker_thread_ = talk_base::Thread::Current();
|
|
|
|
}
|
|
|
|
|
|
|
|
TransportChannelProxy::~TransportChannelProxy() {
|
|
|
|
// Clearing any pending signal.
|
|
|
|
worker_thread_->Clear(this);
|
|
|
|
if (impl_)
|
|
|
|
impl_->GetTransport()->DestroyChannel(impl_->component());
|
|
|
|
}
|
|
|
|
|
|
|
|
void TransportChannelProxy::SetImplementation(TransportChannelImpl* impl) {
|
2013-09-28 01:04:10 +02:00
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
|
|
|
|
if (impl == impl_) {
|
|
|
|
ASSERT(false);
|
|
|
|
// Ignore if the |impl| has already been set.
|
|
|
|
LOG(LS_WARNING) << "Ignored TransportChannelProxy::SetImplementation call "
|
|
|
|
<< "with a same impl as the existing one.";
|
|
|
|
return;
|
|
|
|
}
|
2013-07-10 02:45:36 +02:00
|
|
|
|
|
|
|
// Destroy any existing impl_.
|
|
|
|
if (impl_) {
|
|
|
|
impl_->GetTransport()->DestroyChannel(impl_->component());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adopt the supplied impl, and connect to its signals.
|
|
|
|
impl_ = impl;
|
|
|
|
|
|
|
|
if (impl_) {
|
|
|
|
impl_->SignalReadableState.connect(
|
|
|
|
this, &TransportChannelProxy::OnReadableState);
|
|
|
|
impl_->SignalWritableState.connect(
|
|
|
|
this, &TransportChannelProxy::OnWritableState);
|
|
|
|
impl_->SignalReadPacket.connect(
|
|
|
|
this, &TransportChannelProxy::OnReadPacket);
|
|
|
|
impl_->SignalReadyToSend.connect(
|
|
|
|
this, &TransportChannelProxy::OnReadyToSend);
|
|
|
|
impl_->SignalRouteChange.connect(
|
|
|
|
this, &TransportChannelProxy::OnRouteChange);
|
|
|
|
for (OptionList::iterator it = pending_options_.begin();
|
|
|
|
it != pending_options_.end();
|
|
|
|
++it) {
|
|
|
|
impl_->SetOption(it->first, it->second);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Push down the SRTP ciphers, if any were set.
|
|
|
|
if (!pending_srtp_ciphers_.empty()) {
|
|
|
|
impl_->SetSrtpCiphers(pending_srtp_ciphers_);
|
|
|
|
}
|
|
|
|
pending_options_.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Post ourselves a message to see if we need to fire state callbacks.
|
|
|
|
worker_thread_->Post(this, MSG_UPDATESTATE);
|
|
|
|
}
|
|
|
|
|
2013-09-23 22:34:45 +02:00
|
|
|
int TransportChannelProxy::SendPacket(const char* data, size_t len,
|
2014-02-14 01:56:12 +01:00
|
|
|
const talk_base::PacketOptions& options,
|
2013-09-23 22:34:45 +02:00
|
|
|
int flags) {
|
2013-07-10 02:45:36 +02:00
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
// Fail if we don't have an impl yet.
|
|
|
|
if (!impl_) {
|
|
|
|
return -1;
|
|
|
|
}
|
2014-02-14 01:56:12 +01:00
|
|
|
return impl_->SendPacket(data, len, options, flags);
|
2013-07-10 02:45:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int TransportChannelProxy::SetOption(talk_base::Socket::Option opt, int value) {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
if (!impl_) {
|
|
|
|
pending_options_.push_back(OptionPair(opt, value));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return impl_->SetOption(opt, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
int TransportChannelProxy::GetError() {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
if (!impl_) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return impl_->GetError();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TransportChannelProxy::GetStats(ConnectionInfos* infos) {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
if (!impl_) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return impl_->GetStats(infos);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TransportChannelProxy::IsDtlsActive() const {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
if (!impl_) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return impl_->IsDtlsActive();
|
|
|
|
}
|
|
|
|
|
2013-08-24 01:21:25 +02:00
|
|
|
bool TransportChannelProxy::GetSslRole(talk_base::SSLRole* role) const {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
if (!impl_) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return impl_->GetSslRole(role);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TransportChannelProxy::SetSslRole(talk_base::SSLRole role) {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
if (!impl_) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return impl_->SetSslRole(role);
|
|
|
|
}
|
|
|
|
|
2013-07-10 02:45:36 +02:00
|
|
|
bool TransportChannelProxy::SetSrtpCiphers(const std::vector<std::string>&
|
|
|
|
ciphers) {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
pending_srtp_ciphers_ = ciphers; // Cache so we can send later, but always
|
|
|
|
// set so it stays consistent.
|
|
|
|
if (impl_) {
|
|
|
|
return impl_->SetSrtpCiphers(ciphers);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TransportChannelProxy::GetSrtpCipher(std::string* cipher) {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
if (!impl_) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return impl_->GetSrtpCipher(cipher);
|
|
|
|
}
|
|
|
|
|
2013-10-09 17:37:36 +02:00
|
|
|
bool TransportChannelProxy::GetLocalIdentity(
|
|
|
|
talk_base::SSLIdentity** identity) const {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
if (!impl_) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return impl_->GetLocalIdentity(identity);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TransportChannelProxy::GetRemoteCertificate(
|
|
|
|
talk_base::SSLCertificate** cert) const {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
if (!impl_) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return impl_->GetRemoteCertificate(cert);
|
|
|
|
}
|
|
|
|
|
2013-07-10 02:45:36 +02:00
|
|
|
bool TransportChannelProxy::ExportKeyingMaterial(const std::string& label,
|
|
|
|
const uint8* context,
|
|
|
|
size_t context_len,
|
|
|
|
bool use_context,
|
|
|
|
uint8* result,
|
|
|
|
size_t result_len) {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
if (!impl_) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return impl_->ExportKeyingMaterial(label, context, context_len, use_context,
|
|
|
|
result, result_len);
|
|
|
|
}
|
|
|
|
|
2013-08-12 23:18:15 +02:00
|
|
|
IceRole TransportChannelProxy::GetIceRole() const {
|
2013-07-10 02:45:36 +02:00
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
if (!impl_) {
|
2013-08-12 23:18:15 +02:00
|
|
|
return ICEROLE_UNKNOWN;
|
2013-07-10 02:45:36 +02:00
|
|
|
}
|
2013-08-12 23:18:15 +02:00
|
|
|
return impl_->GetIceRole();
|
2013-07-10 02:45:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void TransportChannelProxy::OnReadableState(TransportChannel* channel) {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
ASSERT(channel == impl_);
|
|
|
|
set_readable(impl_->readable());
|
|
|
|
// Note: SignalReadableState fired by set_readable.
|
|
|
|
}
|
|
|
|
|
|
|
|
void TransportChannelProxy::OnWritableState(TransportChannel* channel) {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
ASSERT(channel == impl_);
|
|
|
|
set_writable(impl_->writable());
|
|
|
|
// Note: SignalWritableState fired by set_readable.
|
|
|
|
}
|
|
|
|
|
2013-12-13 01:21:03 +01:00
|
|
|
void TransportChannelProxy::OnReadPacket(
|
|
|
|
TransportChannel* channel, const char* data, size_t size,
|
|
|
|
const talk_base::PacketTime& packet_time, int flags) {
|
2013-07-10 02:45:36 +02:00
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
ASSERT(channel == impl_);
|
2013-12-13 01:21:03 +01:00
|
|
|
SignalReadPacket(this, data, size, packet_time, flags);
|
2013-07-10 02:45:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void TransportChannelProxy::OnReadyToSend(TransportChannel* channel) {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
ASSERT(channel == impl_);
|
|
|
|
SignalReadyToSend(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TransportChannelProxy::OnRouteChange(TransportChannel* channel,
|
|
|
|
const Candidate& candidate) {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
ASSERT(channel == impl_);
|
|
|
|
SignalRouteChange(this, candidate);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TransportChannelProxy::OnMessage(talk_base::Message* msg) {
|
|
|
|
ASSERT(talk_base::Thread::Current() == worker_thread_);
|
|
|
|
if (msg->message_id == MSG_UPDATESTATE) {
|
|
|
|
// If impl_ is already readable or writable, push up those signals.
|
|
|
|
set_readable(impl_ ? impl_->readable() : false);
|
|
|
|
set_writable(impl_ ? impl_->writable() : false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace cricket
|