3 * Copyright 2004--2005, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
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.
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.
28 #include "talk/p2p/base/transportchannelproxy.h"
29 #include "talk/base/common.h"
30 #include "talk/base/logging.h"
31 #include "talk/base/thread.h"
32 #include "talk/p2p/base/transport.h"
33 #include "talk/p2p/base/transportchannelimpl.h"
41 TransportChannelProxy::TransportChannelProxy(const std::string& content_name,
42 const std::string& name,
44 : TransportChannel(content_name, component),
47 worker_thread_ = talk_base::Thread::Current();
50 TransportChannelProxy::~TransportChannelProxy() {
51 // Clearing any pending signal.
52 worker_thread_->Clear(this);
54 impl_->GetTransport()->DestroyChannel(impl_->component());
57 void TransportChannelProxy::SetImplementation(TransportChannelImpl* impl) {
58 ASSERT(talk_base::Thread::Current() == worker_thread_);
62 // Ignore if the |impl| has already been set.
63 LOG(LS_WARNING) << "Ignored TransportChannelProxy::SetImplementation call "
64 << "with a same impl as the existing one.";
68 // Destroy any existing impl_.
70 impl_->GetTransport()->DestroyChannel(impl_->component());
73 // Adopt the supplied impl, and connect to its signals.
77 impl_->SignalReadableState.connect(
78 this, &TransportChannelProxy::OnReadableState);
79 impl_->SignalWritableState.connect(
80 this, &TransportChannelProxy::OnWritableState);
81 impl_->SignalReadPacket.connect(
82 this, &TransportChannelProxy::OnReadPacket);
83 impl_->SignalReadyToSend.connect(
84 this, &TransportChannelProxy::OnReadyToSend);
85 impl_->SignalRouteChange.connect(
86 this, &TransportChannelProxy::OnRouteChange);
87 for (OptionList::iterator it = pending_options_.begin();
88 it != pending_options_.end();
90 impl_->SetOption(it->first, it->second);
93 // Push down the SRTP ciphers, if any were set.
94 if (!pending_srtp_ciphers_.empty()) {
95 impl_->SetSrtpCiphers(pending_srtp_ciphers_);
97 pending_options_.clear();
100 // Post ourselves a message to see if we need to fire state callbacks.
101 worker_thread_->Post(this, MSG_UPDATESTATE);
104 int TransportChannelProxy::SendPacket(const char* data, size_t len,
105 const talk_base::PacketOptions& options,
107 ASSERT(talk_base::Thread::Current() == worker_thread_);
108 // Fail if we don't have an impl yet.
112 return impl_->SendPacket(data, len, options, flags);
115 int TransportChannelProxy::SetOption(talk_base::Socket::Option opt, int value) {
116 ASSERT(talk_base::Thread::Current() == worker_thread_);
118 pending_options_.push_back(OptionPair(opt, value));
121 return impl_->SetOption(opt, value);
124 int TransportChannelProxy::GetError() {
125 ASSERT(talk_base::Thread::Current() == worker_thread_);
129 return impl_->GetError();
132 bool TransportChannelProxy::GetStats(ConnectionInfos* infos) {
133 ASSERT(talk_base::Thread::Current() == worker_thread_);
137 return impl_->GetStats(infos);
140 bool TransportChannelProxy::IsDtlsActive() const {
141 ASSERT(talk_base::Thread::Current() == worker_thread_);
145 return impl_->IsDtlsActive();
148 bool TransportChannelProxy::GetSslRole(talk_base::SSLRole* role) const {
149 ASSERT(talk_base::Thread::Current() == worker_thread_);
153 return impl_->GetSslRole(role);
156 bool TransportChannelProxy::SetSslRole(talk_base::SSLRole role) {
157 ASSERT(talk_base::Thread::Current() == worker_thread_);
161 return impl_->SetSslRole(role);
164 bool TransportChannelProxy::SetSrtpCiphers(const std::vector<std::string>&
166 ASSERT(talk_base::Thread::Current() == worker_thread_);
167 pending_srtp_ciphers_ = ciphers; // Cache so we can send later, but always
168 // set so it stays consistent.
170 return impl_->SetSrtpCiphers(ciphers);
175 bool TransportChannelProxy::GetSrtpCipher(std::string* cipher) {
176 ASSERT(talk_base::Thread::Current() == worker_thread_);
180 return impl_->GetSrtpCipher(cipher);
183 bool TransportChannelProxy::GetLocalIdentity(
184 talk_base::SSLIdentity** identity) const {
185 ASSERT(talk_base::Thread::Current() == worker_thread_);
189 return impl_->GetLocalIdentity(identity);
192 bool TransportChannelProxy::GetRemoteCertificate(
193 talk_base::SSLCertificate** cert) const {
194 ASSERT(talk_base::Thread::Current() == worker_thread_);
198 return impl_->GetRemoteCertificate(cert);
201 bool TransportChannelProxy::ExportKeyingMaterial(const std::string& label,
202 const uint8* context,
207 ASSERT(talk_base::Thread::Current() == worker_thread_);
211 return impl_->ExportKeyingMaterial(label, context, context_len, use_context,
215 IceRole TransportChannelProxy::GetIceRole() const {
216 ASSERT(talk_base::Thread::Current() == worker_thread_);
218 return ICEROLE_UNKNOWN;
220 return impl_->GetIceRole();
223 void TransportChannelProxy::OnReadableState(TransportChannel* channel) {
224 ASSERT(talk_base::Thread::Current() == worker_thread_);
225 ASSERT(channel == impl_);
226 set_readable(impl_->readable());
227 // Note: SignalReadableState fired by set_readable.
230 void TransportChannelProxy::OnWritableState(TransportChannel* channel) {
231 ASSERT(talk_base::Thread::Current() == worker_thread_);
232 ASSERT(channel == impl_);
233 set_writable(impl_->writable());
234 // Note: SignalWritableState fired by set_readable.
237 void TransportChannelProxy::OnReadPacket(
238 TransportChannel* channel, const char* data, size_t size,
239 const talk_base::PacketTime& packet_time, int flags) {
240 ASSERT(talk_base::Thread::Current() == worker_thread_);
241 ASSERT(channel == impl_);
242 SignalReadPacket(this, data, size, packet_time, flags);
245 void TransportChannelProxy::OnReadyToSend(TransportChannel* channel) {
246 ASSERT(talk_base::Thread::Current() == worker_thread_);
247 ASSERT(channel == impl_);
248 SignalReadyToSend(this);
251 void TransportChannelProxy::OnRouteChange(TransportChannel* channel,
252 const Candidate& candidate) {
253 ASSERT(talk_base::Thread::Current() == worker_thread_);
254 ASSERT(channel == impl_);
255 SignalRouteChange(this, candidate);
258 void TransportChannelProxy::OnMessage(talk_base::Message* msg) {
259 ASSERT(talk_base::Thread::Current() == worker_thread_);
260 if (msg->message_id == MSG_UPDATESTATE) {
261 // If impl_ is already readable or writable, push up those signals.
262 set_readable(impl_ ? impl_->readable() : false);
263 set_writable(impl_ ? impl_->writable() : false);
267 } // namespace cricket