| Index: webrtc/libjingle/session/tunnel/pseudotcpchannel.cc
|
| diff --git a/webrtc/libjingle/session/tunnel/pseudotcpchannel.cc b/webrtc/libjingle/session/tunnel/pseudotcpchannel.cc
|
| deleted file mode 100644
|
| index c5b9443253c41c2fa7db5ce24fc83657d5f4d621..0000000000000000000000000000000000000000
|
| --- a/webrtc/libjingle/session/tunnel/pseudotcpchannel.cc
|
| +++ /dev/null
|
| @@ -1,605 +0,0 @@
|
| -/*
|
| - * libjingle
|
| - * Copyright 2004--2006, 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 <algorithm>
|
| -#include <string>
|
| -
|
| -#include "pseudotcpchannel.h"
|
| -#include "webrtc/p2p/base/candidate.h"
|
| -#include "webrtc/p2p/base/transportchannel.h"
|
| -#include "webrtc/base/basictypes.h"
|
| -#include "webrtc/base/common.h"
|
| -#include "webrtc/base/logging.h"
|
| -#include "webrtc/base/scoped_ptr.h"
|
| -#include "webrtc/base/stringutils.h"
|
| -
|
| -using namespace rtc;
|
| -
|
| -namespace cricket {
|
| -
|
| -extern const rtc::ConstantLabel SESSION_STATES[];
|
| -
|
| -// MSG_WK_* - worker thread messages
|
| -// MSG_ST_* - stream thread messages
|
| -// MSG_SI_* - signal thread messages
|
| -
|
| -enum {
|
| - MSG_WK_CLOCK = 1,
|
| - MSG_WK_PURGE,
|
| - MSG_ST_EVENT,
|
| - MSG_SI_DESTROYCHANNEL,
|
| - MSG_SI_DESTROY,
|
| -};
|
| -
|
| -struct EventData : public MessageData {
|
| - int event, error;
|
| - EventData(int ev, int err = 0) : event(ev), error(err) { }
|
| -};
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -// PseudoTcpChannel::InternalStream
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| -class PseudoTcpChannel::InternalStream : public StreamInterface {
|
| -public:
|
| - InternalStream(PseudoTcpChannel* parent);
|
| - virtual ~InternalStream();
|
| -
|
| - virtual StreamState GetState() const;
|
| - virtual StreamResult Read(void* buffer, size_t buffer_len,
|
| - size_t* read, int* error);
|
| - virtual StreamResult Write(const void* data, size_t data_len,
|
| - size_t* written, int* error);
|
| - virtual void Close();
|
| -
|
| -private:
|
| - // parent_ is accessed and modified exclusively on the event thread, to
|
| - // avoid thread contention. This means that the PseudoTcpChannel cannot go
|
| - // away until after it receives a Close() from TunnelStream.
|
| - PseudoTcpChannel* parent_;
|
| -};
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -// PseudoTcpChannel
|
| -// Member object lifetime summaries:
|
| -// session_ - passed in constructor, cleared when channel_ goes away.
|
| -// channel_ - created in Connect, destroyed when session_ or tcp_ goes away.
|
| -// tcp_ - created in Connect, destroyed when channel_ goes away, or connection
|
| -// closes.
|
| -// worker_thread_ - created when channel_ is created, purged when channel_ is
|
| -// destroyed.
|
| -// stream_ - created in GetStream, destroyed by owner at arbitrary time.
|
| -// this - created in constructor, destroyed when worker_thread_ and stream_
|
| -// are both gone.
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| -//
|
| -// Signal thread methods
|
| -//
|
| -
|
| -PseudoTcpChannel::PseudoTcpChannel(Thread* stream_thread, Session* session)
|
| - : signal_thread_(session->session_manager()->signaling_thread()),
|
| - worker_thread_(NULL),
|
| - stream_thread_(stream_thread),
|
| - session_(session), channel_(NULL), tcp_(NULL), stream_(NULL),
|
| - stream_readable_(false), pending_read_event_(false),
|
| - ready_to_connect_(false) {
|
| - ASSERT(signal_thread_->IsCurrent());
|
| - ASSERT(NULL != session_);
|
| -}
|
| -
|
| -PseudoTcpChannel::~PseudoTcpChannel() {
|
| - ASSERT(signal_thread_->IsCurrent());
|
| - ASSERT(worker_thread_ == NULL);
|
| - ASSERT(session_ == NULL);
|
| - ASSERT(channel_ == NULL);
|
| - ASSERT(stream_ == NULL);
|
| - ASSERT(tcp_ == NULL);
|
| -}
|
| -
|
| -bool PseudoTcpChannel::Connect(const std::string& content_name,
|
| - const std::string& channel_name,
|
| - int component) {
|
| - ASSERT(signal_thread_->IsCurrent());
|
| - CritScope lock(&cs_);
|
| -
|
| - if (channel_)
|
| - return false;
|
| -
|
| - ASSERT(session_ != NULL);
|
| - worker_thread_ = session_->session_manager()->worker_thread();
|
| - content_name_ = content_name;
|
| - channel_ = session_->CreateChannel(
|
| - content_name, channel_name, component);
|
| - channel_name_ = channel_name;
|
| - channel_->SetOption(Socket::OPT_DONTFRAGMENT, 1);
|
| -
|
| - channel_->SignalDestroyed.connect(this,
|
| - &PseudoTcpChannel::OnChannelDestroyed);
|
| - channel_->SignalWritableState.connect(this,
|
| - &PseudoTcpChannel::OnChannelWritableState);
|
| - channel_->SignalReadPacket.connect(this,
|
| - &PseudoTcpChannel::OnChannelRead);
|
| - channel_->SignalRouteChange.connect(this,
|
| - &PseudoTcpChannel::OnChannelConnectionChanged);
|
| -
|
| - ASSERT(tcp_ == NULL);
|
| - tcp_ = new PseudoTcp(this, 0);
|
| - if (session_->initiator()) {
|
| - // Since we may try several protocols and network adapters that won't work,
|
| - // waiting until we get our first writable notification before initiating
|
| - // TCP negotiation.
|
| - ready_to_connect_ = true;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -StreamInterface* PseudoTcpChannel::GetStream() {
|
| - ASSERT(signal_thread_->IsCurrent());
|
| - CritScope lock(&cs_);
|
| - ASSERT(NULL != session_);
|
| - if (!stream_)
|
| - stream_ = new PseudoTcpChannel::InternalStream(this);
|
| - //TODO("should we disallow creation of new stream at some point?");
|
| - return stream_;
|
| -}
|
| -
|
| -void PseudoTcpChannel::OnChannelDestroyed(TransportChannel* channel) {
|
| - LOG_F(LS_INFO) << "(" << channel->component() << ")";
|
| - ASSERT(signal_thread_->IsCurrent());
|
| - CritScope lock(&cs_);
|
| - ASSERT(channel == channel_);
|
| - signal_thread_->Clear(this, MSG_SI_DESTROYCHANNEL);
|
| - // When MSG_WK_PURGE is received, we know there will be no more messages from
|
| - // the worker thread.
|
| - worker_thread_->Clear(this, MSG_WK_CLOCK);
|
| - worker_thread_->Post(this, MSG_WK_PURGE);
|
| - session_ = NULL;
|
| - channel_ = NULL;
|
| - if ((stream_ != NULL)
|
| - && ((tcp_ == NULL) || (tcp_->State() != PseudoTcp::TCP_CLOSED)))
|
| - stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_CLOSE, 0));
|
| - if (tcp_) {
|
| - tcp_->Close(true);
|
| - AdjustClock();
|
| - }
|
| - SignalChannelClosed(this);
|
| -}
|
| -
|
| -void PseudoTcpChannel::OnSessionTerminate(Session* session) {
|
| - // When the session terminates before we even connected
|
| - CritScope lock(&cs_);
|
| - if (session_ != NULL && channel_ == NULL) {
|
| - ASSERT(session == session_);
|
| - ASSERT(worker_thread_ == NULL);
|
| - ASSERT(tcp_ == NULL);
|
| - LOG(LS_INFO) << "Destroying unconnected PseudoTcpChannel";
|
| - session_ = NULL;
|
| - if (stream_ != NULL)
|
| - stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_CLOSE, -1));
|
| - }
|
| -
|
| - // Even though session_ is being destroyed, we mustn't clear the pointer,
|
| - // since we'll need it to tear down channel_.
|
| - //
|
| - // TODO: Is it always the case that if channel_ != NULL then we'll get
|
| - // a channel-destroyed notification?
|
| -}
|
| -
|
| -void PseudoTcpChannel::GetOption(PseudoTcp::Option opt, int* value) {
|
| - ASSERT(signal_thread_->IsCurrent());
|
| - CritScope lock(&cs_);
|
| - ASSERT(tcp_ != NULL);
|
| - tcp_->GetOption(opt, value);
|
| -}
|
| -
|
| -void PseudoTcpChannel::SetOption(PseudoTcp::Option opt, int value) {
|
| - ASSERT(signal_thread_->IsCurrent());
|
| - CritScope lock(&cs_);
|
| - ASSERT(tcp_ != NULL);
|
| - tcp_->SetOption(opt, value);
|
| -}
|
| -
|
| -//
|
| -// Stream thread methods
|
| -//
|
| -
|
| -StreamState PseudoTcpChannel::GetState() const {
|
| - ASSERT(stream_ != NULL && stream_thread_->IsCurrent());
|
| - CritScope lock(&cs_);
|
| - if (!session_)
|
| - return SS_CLOSED;
|
| - if (!tcp_)
|
| - return SS_OPENING;
|
| - switch (tcp_->State()) {
|
| - case PseudoTcp::TCP_LISTEN:
|
| - case PseudoTcp::TCP_SYN_SENT:
|
| - case PseudoTcp::TCP_SYN_RECEIVED:
|
| - return SS_OPENING;
|
| - case PseudoTcp::TCP_ESTABLISHED:
|
| - return SS_OPEN;
|
| - case PseudoTcp::TCP_CLOSED:
|
| - default:
|
| - return SS_CLOSED;
|
| - }
|
| -}
|
| -
|
| -StreamResult PseudoTcpChannel::Read(void* buffer, size_t buffer_len,
|
| - size_t* read, int* error) {
|
| - ASSERT(stream_ != NULL && stream_thread_->IsCurrent());
|
| - CritScope lock(&cs_);
|
| - if (!tcp_)
|
| - return SR_BLOCK;
|
| -
|
| - stream_readable_ = false;
|
| - int result = tcp_->Recv(static_cast<char*>(buffer), buffer_len);
|
| - //LOG_F(LS_VERBOSE) << "Recv returned: " << result;
|
| - if (result > 0) {
|
| - if (read)
|
| - *read = result;
|
| - // PseudoTcp doesn't currently support repeated Readable signals. Simulate
|
| - // them here.
|
| - stream_readable_ = true;
|
| - if (!pending_read_event_) {
|
| - pending_read_event_ = true;
|
| - stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_READ), true);
|
| - }
|
| - return SR_SUCCESS;
|
| - } else if (IsBlockingError(tcp_->GetError())) {
|
| - return SR_BLOCK;
|
| - } else {
|
| - if (error)
|
| - *error = tcp_->GetError();
|
| - return SR_ERROR;
|
| - }
|
| - // This spot is never reached.
|
| -}
|
| -
|
| -StreamResult PseudoTcpChannel::Write(const void* data, size_t data_len,
|
| - size_t* written, int* error) {
|
| - ASSERT(stream_ != NULL && stream_thread_->IsCurrent());
|
| - CritScope lock(&cs_);
|
| - if (!tcp_)
|
| - return SR_BLOCK;
|
| - int result = tcp_->Send(static_cast<const char*>(data), data_len);
|
| - //LOG_F(LS_VERBOSE) << "Send returned: " << result;
|
| - if (result > 0) {
|
| - if (written)
|
| - *written = result;
|
| - return SR_SUCCESS;
|
| - } else if (IsBlockingError(tcp_->GetError())) {
|
| - return SR_BLOCK;
|
| - } else {
|
| - if (error)
|
| - *error = tcp_->GetError();
|
| - return SR_ERROR;
|
| - }
|
| - // This spot is never reached.
|
| -}
|
| -
|
| -void PseudoTcpChannel::Close() {
|
| - ASSERT(stream_ != NULL && stream_thread_->IsCurrent());
|
| - CritScope lock(&cs_);
|
| - stream_ = NULL;
|
| - // Clear out any pending event notifications
|
| - stream_thread_->Clear(this, MSG_ST_EVENT);
|
| - if (tcp_) {
|
| - tcp_->Close(false);
|
| - AdjustClock();
|
| - } else {
|
| - CheckDestroy();
|
| - }
|
| -}
|
| -
|
| -//
|
| -// Worker thread methods
|
| -//
|
| -
|
| -void PseudoTcpChannel::OnChannelWritableState(TransportChannel* channel) {
|
| - LOG_F(LS_VERBOSE) << "[" << channel_name_ << "]";
|
| - ASSERT(worker_thread_->IsCurrent());
|
| - CritScope lock(&cs_);
|
| - if (!channel_) {
|
| - LOG_F(LS_WARNING) << "NULL channel";
|
| - return;
|
| - }
|
| - ASSERT(channel == channel_);
|
| - if (!tcp_) {
|
| - LOG_F(LS_WARNING) << "NULL tcp";
|
| - return;
|
| - }
|
| - if (!ready_to_connect_ || !channel->writable())
|
| - return;
|
| -
|
| - ready_to_connect_ = false;
|
| - tcp_->Connect();
|
| - AdjustClock();
|
| -}
|
| -
|
| -void PseudoTcpChannel::OnChannelRead(TransportChannel* channel,
|
| - const char* data, size_t size,
|
| - const rtc::PacketTime& packet_time,
|
| - int flags) {
|
| - //LOG_F(LS_VERBOSE) << "(" << size << ")";
|
| - ASSERT(worker_thread_->IsCurrent());
|
| - CritScope lock(&cs_);
|
| - if (!channel_) {
|
| - LOG_F(LS_WARNING) << "NULL channel";
|
| - return;
|
| - }
|
| - ASSERT(channel == channel_);
|
| - if (!tcp_) {
|
| - LOG_F(LS_WARNING) << "NULL tcp";
|
| - return;
|
| - }
|
| - tcp_->NotifyPacket(data, size);
|
| - AdjustClock();
|
| -}
|
| -
|
| -void PseudoTcpChannel::OnChannelConnectionChanged(TransportChannel* channel,
|
| - const Candidate& candidate) {
|
| - LOG_F(LS_VERBOSE) << "[" << channel_name_ << "]";
|
| - ASSERT(worker_thread_->IsCurrent());
|
| - CritScope lock(&cs_);
|
| - if (!channel_) {
|
| - LOG_F(LS_WARNING) << "NULL channel";
|
| - return;
|
| - }
|
| - ASSERT(channel == channel_);
|
| - if (!tcp_) {
|
| - LOG_F(LS_WARNING) << "NULL tcp";
|
| - return;
|
| - }
|
| -
|
| - uint16 mtu = 1280; // safe default
|
| - int family = candidate.address().family();
|
| - Socket* socket =
|
| - worker_thread_->socketserver()->CreateAsyncSocket(family, SOCK_DGRAM);
|
| - rtc::scoped_ptr<Socket> mtu_socket(socket);
|
| - if (socket == NULL) {
|
| - LOG_F(LS_WARNING) << "Couldn't create socket while estimating MTU.";
|
| - } else {
|
| - if (mtu_socket->Connect(candidate.address()) < 0 ||
|
| - mtu_socket->EstimateMTU(&mtu) < 0) {
|
| - LOG_F(LS_WARNING) << "Failed to estimate MTU, error="
|
| - << mtu_socket->GetError();
|
| - }
|
| - }
|
| -
|
| - LOG_F(LS_VERBOSE) << "Using MTU of " << mtu << " bytes";
|
| - tcp_->NotifyMTU(mtu);
|
| - AdjustClock();
|
| -}
|
| -
|
| -void PseudoTcpChannel::OnTcpOpen(PseudoTcp* tcp) {
|
| - LOG_F(LS_VERBOSE) << "[" << channel_name_ << "]";
|
| - ASSERT(cs_.CurrentThreadIsOwner());
|
| - ASSERT(worker_thread_->IsCurrent());
|
| - ASSERT(tcp == tcp_);
|
| - if (stream_) {
|
| - stream_readable_ = true;
|
| - pending_read_event_ = true;
|
| - stream_thread_->Post(this, MSG_ST_EVENT,
|
| - new EventData(SE_OPEN | SE_READ | SE_WRITE));
|
| - }
|
| -}
|
| -
|
| -void PseudoTcpChannel::OnTcpReadable(PseudoTcp* tcp) {
|
| - //LOG_F(LS_VERBOSE);
|
| - ASSERT(cs_.CurrentThreadIsOwner());
|
| - ASSERT(worker_thread_->IsCurrent());
|
| - ASSERT(tcp == tcp_);
|
| - if (stream_) {
|
| - stream_readable_ = true;
|
| - if (!pending_read_event_) {
|
| - pending_read_event_ = true;
|
| - stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_READ));
|
| - }
|
| - }
|
| -}
|
| -
|
| -void PseudoTcpChannel::OnTcpWriteable(PseudoTcp* tcp) {
|
| - //LOG_F(LS_VERBOSE);
|
| - ASSERT(cs_.CurrentThreadIsOwner());
|
| - ASSERT(worker_thread_->IsCurrent());
|
| - ASSERT(tcp == tcp_);
|
| - if (stream_)
|
| - stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_WRITE));
|
| -}
|
| -
|
| -void PseudoTcpChannel::OnTcpClosed(PseudoTcp* tcp, uint32 nError) {
|
| - LOG_F(LS_VERBOSE) << "[" << channel_name_ << "]";
|
| - ASSERT(cs_.CurrentThreadIsOwner());
|
| - ASSERT(worker_thread_->IsCurrent());
|
| - ASSERT(tcp == tcp_);
|
| - if (stream_)
|
| - stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_CLOSE, nError));
|
| -}
|
| -
|
| -//
|
| -// Multi-thread methods
|
| -//
|
| -
|
| -void PseudoTcpChannel::OnMessage(Message* pmsg) {
|
| - if (pmsg->message_id == MSG_WK_CLOCK) {
|
| -
|
| - ASSERT(worker_thread_->IsCurrent());
|
| - //LOG(LS_INFO) << "PseudoTcpChannel::OnMessage(MSG_WK_CLOCK)";
|
| - CritScope lock(&cs_);
|
| - if (tcp_) {
|
| - tcp_->NotifyClock(PseudoTcp::Now());
|
| - AdjustClock(false);
|
| - }
|
| -
|
| - } else if (pmsg->message_id == MSG_WK_PURGE) {
|
| -
|
| - ASSERT(worker_thread_->IsCurrent());
|
| - LOG_F(LS_INFO) << "(MSG_WK_PURGE)";
|
| - // At this point, we know there are no additional worker thread messages.
|
| - CritScope lock(&cs_);
|
| - ASSERT(NULL == session_);
|
| - ASSERT(NULL == channel_);
|
| - worker_thread_ = NULL;
|
| - CheckDestroy();
|
| -
|
| - } else if (pmsg->message_id == MSG_ST_EVENT) {
|
| -
|
| - ASSERT(stream_thread_->IsCurrent());
|
| - //LOG(LS_INFO) << "PseudoTcpChannel::OnMessage(MSG_ST_EVENT, "
|
| - // << data->event << ", " << data->error << ")";
|
| - ASSERT(stream_ != NULL);
|
| - EventData* data = static_cast<EventData*>(pmsg->pdata);
|
| - if (data->event & SE_READ) {
|
| - CritScope lock(&cs_);
|
| - pending_read_event_ = false;
|
| - }
|
| - stream_->SignalEvent(stream_, data->event, data->error);
|
| - delete data;
|
| -
|
| - } else if (pmsg->message_id == MSG_SI_DESTROYCHANNEL) {
|
| -
|
| - ASSERT(signal_thread_->IsCurrent());
|
| - LOG_F(LS_INFO) << "(MSG_SI_DESTROYCHANNEL)";
|
| - ASSERT(session_ != NULL);
|
| - ASSERT(channel_ != NULL);
|
| - session_->DestroyChannel(content_name_, channel_->component());
|
| -
|
| - } else if (pmsg->message_id == MSG_SI_DESTROY) {
|
| -
|
| - ASSERT(signal_thread_->IsCurrent());
|
| - LOG_F(LS_INFO) << "(MSG_SI_DESTROY)";
|
| - // The message queue is empty, so it is safe to destroy ourselves.
|
| - delete this;
|
| -
|
| - } else {
|
| - ASSERT(false);
|
| - }
|
| -}
|
| -
|
| -IPseudoTcpNotify::WriteResult PseudoTcpChannel::TcpWritePacket(
|
| - PseudoTcp* tcp, const char* buffer, size_t len) {
|
| - ASSERT(cs_.CurrentThreadIsOwner());
|
| - ASSERT(tcp == tcp_);
|
| - ASSERT(NULL != channel_);
|
| - rtc::PacketOptions packet_options;
|
| - int sent = channel_->SendPacket(buffer, len, packet_options);
|
| - if (sent > 0) {
|
| - //LOG_F(LS_VERBOSE) << "(" << sent << ") Sent";
|
| - return IPseudoTcpNotify::WR_SUCCESS;
|
| - } else if (IsBlockingError(channel_->GetError())) {
|
| - LOG_F(LS_VERBOSE) << "Blocking";
|
| - return IPseudoTcpNotify::WR_SUCCESS;
|
| - } else if (channel_->GetError() == EMSGSIZE) {
|
| - LOG_F(LS_ERROR) << "EMSGSIZE";
|
| - return IPseudoTcpNotify::WR_TOO_LARGE;
|
| - } else {
|
| - PLOG(LS_ERROR, channel_->GetError()) << "PseudoTcpChannel::TcpWritePacket";
|
| - ASSERT(false);
|
| - return IPseudoTcpNotify::WR_FAIL;
|
| - }
|
| -}
|
| -
|
| -void PseudoTcpChannel::AdjustClock(bool clear) {
|
| - ASSERT(cs_.CurrentThreadIsOwner());
|
| - ASSERT(NULL != tcp_);
|
| -
|
| - long timeout = 0;
|
| - if (tcp_->GetNextClock(PseudoTcp::Now(), timeout)) {
|
| - ASSERT(NULL != channel_);
|
| - // Reset the next clock, by clearing the old and setting a new one.
|
| - if (clear)
|
| - worker_thread_->Clear(this, MSG_WK_CLOCK);
|
| - worker_thread_->PostDelayed(std::max(timeout, 0L), this, MSG_WK_CLOCK);
|
| - return;
|
| - }
|
| -
|
| - delete tcp_;
|
| - tcp_ = NULL;
|
| - ready_to_connect_ = false;
|
| -
|
| - if (channel_) {
|
| - // If TCP has failed, no need for channel_ anymore
|
| - signal_thread_->Post(this, MSG_SI_DESTROYCHANNEL);
|
| - }
|
| -}
|
| -
|
| -void PseudoTcpChannel::CheckDestroy() {
|
| - ASSERT(cs_.CurrentThreadIsOwner());
|
| - if ((worker_thread_ != NULL) || (stream_ != NULL))
|
| - return;
|
| - signal_thread_->Post(this, MSG_SI_DESTROY);
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -// PseudoTcpChannel::InternalStream
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| -PseudoTcpChannel::InternalStream::InternalStream(PseudoTcpChannel* parent)
|
| - : parent_(parent) {
|
| -}
|
| -
|
| -PseudoTcpChannel::InternalStream::~InternalStream() {
|
| - Close();
|
| -}
|
| -
|
| -StreamState PseudoTcpChannel::InternalStream::GetState() const {
|
| - if (!parent_)
|
| - return SS_CLOSED;
|
| - return parent_->GetState();
|
| -}
|
| -
|
| -StreamResult PseudoTcpChannel::InternalStream::Read(
|
| - void* buffer, size_t buffer_len, size_t* read, int* error) {
|
| - if (!parent_) {
|
| - if (error)
|
| - *error = ENOTCONN;
|
| - return SR_ERROR;
|
| - }
|
| - return parent_->Read(buffer, buffer_len, read, error);
|
| -}
|
| -
|
| -StreamResult PseudoTcpChannel::InternalStream::Write(
|
| - const void* data, size_t data_len, size_t* written, int* error) {
|
| - if (!parent_) {
|
| - if (error)
|
| - *error = ENOTCONN;
|
| - return SR_ERROR;
|
| - }
|
| - return parent_->Write(data, data_len, written, error);
|
| -}
|
| -
|
| -void PseudoTcpChannel::InternalStream::Close() {
|
| - if (!parent_)
|
| - return;
|
| - parent_->Close();
|
| - parent_ = NULL;
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| -} // namespace cricket
|
|
|