10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/*
20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle
30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2004--2006, Google Inc.
40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without
60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met:
70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer.
100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer in the documentation
120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     and/or other materials provided with the distribution.
130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  3. The name of the author may not be used to endorse or promote products
140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     derived from this software without specific prior written permission.
150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */
270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <string>
29cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "pseudotcpchannel.h"
30cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/p2p/base/candidate.h"
31cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/p2p/base/transportchannel.h"
322a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/basictypes.h"
332a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/common.h"
342a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/logging.h"
352a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/scoped_ptr.h"
362a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/stringutils.h"
370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
382a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgusing namespace rtc;
390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket {
410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
422a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgextern const rtc::ConstantLabel SESSION_STATES[];
430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// MSG_WK_* - worker thread messages
450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// MSG_ST_* - stream thread messages
460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// MSG_SI_* - signal thread messages
470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgenum {
490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  MSG_WK_CLOCK = 1,
500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  MSG_WK_PURGE,
510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  MSG_ST_EVENT,
520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  MSG_SI_DESTROYCHANNEL,
530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  MSG_SI_DESTROY,
540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstruct EventData : public MessageData {
570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int event, error;
580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  EventData(int ev, int err = 0) : event(ev), error(err) { }
590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// PseudoTcpChannel::InternalStream
630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass PseudoTcpChannel::InternalStream : public StreamInterface {
660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgpublic:
670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  InternalStream(PseudoTcpChannel* parent);
680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual ~InternalStream();
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual StreamState GetState() const;
710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual StreamResult Read(void* buffer, size_t buffer_len,
720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                       size_t* read, int* error);
730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual StreamResult Write(const void* data, size_t data_len,
740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                        size_t* written, int* error);
750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual void Close();
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgprivate:
780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // parent_ is accessed and modified exclusively on the event thread, to
790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // avoid thread contention.  This means that the PseudoTcpChannel cannot go
800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // away until after it receives a Close() from TunnelStream.
810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  PseudoTcpChannel* parent_;
820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// PseudoTcpChannel
860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Member object lifetime summaries:
870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//   session_ - passed in constructor, cleared when channel_ goes away.
880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//   channel_ - created in Connect, destroyed when session_ or tcp_ goes away.
890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//   tcp_ - created in Connect, destroyed when channel_ goes away, or connection
900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//     closes.
910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//   worker_thread_ - created when channel_ is created, purged when channel_ is
920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//     destroyed.
930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//   stream_ - created in GetStream, destroyed by owner at arbitrary time.
940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//   this - created in constructor, destroyed when worker_thread_ and stream_
950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//     are both gone.
960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Signal thread methods
1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcpChannel::PseudoTcpChannel(Thread* stream_thread, Session* session)
1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  : signal_thread_(session->session_manager()->signaling_thread()),
1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    worker_thread_(NULL),
1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stream_thread_(stream_thread),
1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    session_(session), channel_(NULL), tcp_(NULL), stream_(NULL),
1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stream_readable_(false), pending_read_event_(false),
1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ready_to_connect_(false) {
1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signal_thread_->IsCurrent());
1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(NULL != session_);
1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcpChannel::~PseudoTcpChannel() {
1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signal_thread_->IsCurrent());
1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread_ == NULL);
1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(session_ == NULL);
1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(channel_ == NULL);
1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(stream_ == NULL);
1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(tcp_ == NULL);
1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool PseudoTcpChannel::Connect(const std::string& content_name,
1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               const std::string& channel_name,
1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               int component) {
1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signal_thread_->IsCurrent());
1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CritScope lock(&cs_);
1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (channel_)
1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(session_ != NULL);
1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  worker_thread_ = session_->session_manager()->worker_thread();
1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  content_name_ = content_name;
1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_ = session_->CreateChannel(
1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      content_name, channel_name, component);
1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_name_ = channel_name;
1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->SetOption(Socket::OPT_DONTFRAGMENT, 1);
1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->SignalDestroyed.connect(this,
1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    &PseudoTcpChannel::OnChannelDestroyed);
1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->SignalWritableState.connect(this,
1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    &PseudoTcpChannel::OnChannelWritableState);
1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->SignalReadPacket.connect(this,
1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    &PseudoTcpChannel::OnChannelRead);
1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->SignalRouteChange.connect(this,
1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    &PseudoTcpChannel::OnChannelConnectionChanged);
1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(tcp_ == NULL);
1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  tcp_ = new PseudoTcp(this, 0);
1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (session_->initiator()) {
1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Since we may try several protocols and network adapters that won't work,
1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // waiting until we get our first writable notification before initiating
1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // TCP negotiation.
1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ready_to_connect_ = true;
1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgStreamInterface* PseudoTcpChannel::GetStream() {
1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signal_thread_->IsCurrent());
1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CritScope lock(&cs_);
1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(NULL != session_);
1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!stream_)
1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stream_ = new PseudoTcpChannel::InternalStream(this);
1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //TODO("should we disallow creation of new stream at some point?");
1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return stream_;
1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::OnChannelDestroyed(TransportChannel* channel) {
1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG_F(LS_INFO) << "(" << channel->component() << ")";
1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signal_thread_->IsCurrent());
1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CritScope lock(&cs_);
1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(channel == channel_);
1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  signal_thread_->Clear(this, MSG_SI_DESTROYCHANNEL);
1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // When MSG_WK_PURGE is received, we know there will be no more messages from
1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // the worker thread.
1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  worker_thread_->Clear(this, MSG_WK_CLOCK);
1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  worker_thread_->Post(this, MSG_WK_PURGE);
1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session_ = NULL;
1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_ = NULL;
1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if ((stream_ != NULL)
1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      && ((tcp_ == NULL) || (tcp_->State() != PseudoTcp::TCP_CLOSED)))
1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_CLOSE, 0));
1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (tcp_) {
1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    tcp_->Close(true);
1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    AdjustClock();
1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalChannelClosed(this);
1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::OnSessionTerminate(Session* session) {
1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // When the session terminates before we even connected
1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CritScope lock(&cs_);
1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (session_ != NULL && channel_ == NULL) {
1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(session == session_);
1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(worker_thread_ == NULL);
1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(tcp_ == NULL);
1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_INFO) << "Destroying unconnected PseudoTcpChannel";
2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    session_ = NULL;
2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (stream_ != NULL)
2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_CLOSE, -1));
2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Even though session_ is being destroyed, we mustn't clear the pointer,
2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // since we'll need it to tear down channel_.
2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //
2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO: Is it always the case that if channel_ != NULL then we'll get
2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // a channel-destroyed notification?
2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::GetOption(PseudoTcp::Option opt, int* value) {
2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signal_thread_->IsCurrent());
2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CritScope lock(&cs_);
2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(tcp_ != NULL);
2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  tcp_->GetOption(opt, value);
2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::SetOption(PseudoTcp::Option opt, int value) {
2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signal_thread_->IsCurrent());
2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CritScope lock(&cs_);
2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(tcp_ != NULL);
2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  tcp_->SetOption(opt, value);
2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Stream thread methods
2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgStreamState PseudoTcpChannel::GetState() const {
2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(stream_ != NULL && stream_thread_->IsCurrent());
2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CritScope lock(&cs_);
2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!session_)
2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SS_CLOSED;
2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!tcp_)
2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SS_OPENING;
2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (tcp_->State()) {
2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case PseudoTcp::TCP_LISTEN:
2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case PseudoTcp::TCP_SYN_SENT:
2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case PseudoTcp::TCP_SYN_RECEIVED:
2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return SS_OPENING;
2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case PseudoTcp::TCP_ESTABLISHED:
2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return SS_OPEN;
2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case PseudoTcp::TCP_CLOSED:
2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    default:
2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return SS_CLOSED;
2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgStreamResult PseudoTcpChannel::Read(void* buffer, size_t buffer_len,
2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                    size_t* read, int* error) {
2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(stream_ != NULL && stream_thread_->IsCurrent());
2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CritScope lock(&cs_);
2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!tcp_)
2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SR_BLOCK;
2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  stream_readable_ = false;
2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int result = tcp_->Recv(static_cast<char*>(buffer), buffer_len);
2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //LOG_F(LS_VERBOSE) << "Recv returned: " << result;
2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (result > 0) {
2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (read)
2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *read = result;
2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // PseudoTcp doesn't currently support repeated Readable signals.  Simulate
2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // them here.
2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stream_readable_ = true;
2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!pending_read_event_) {
2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      pending_read_event_ = true;
2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_READ), true);
2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SR_SUCCESS;
2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (IsBlockingError(tcp_->GetError())) {
2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SR_BLOCK;
2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (error)
2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *error = tcp_->GetError();
2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SR_ERROR;
2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // This spot is never reached.
2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgStreamResult PseudoTcpChannel::Write(const void* data, size_t data_len,
2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                     size_t* written, int* error) {
2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(stream_ != NULL && stream_thread_->IsCurrent());
2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CritScope lock(&cs_);
2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!tcp_)
2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SR_BLOCK;
2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int result = tcp_->Send(static_cast<const char*>(data), data_len);
2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //LOG_F(LS_VERBOSE) << "Send returned: " << result;
2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (result > 0) {
2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (written)
2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *written = result;
2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SR_SUCCESS;
2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (IsBlockingError(tcp_->GetError())) {
2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SR_BLOCK;
2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (error)
2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *error = tcp_->GetError();
2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SR_ERROR;
2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // This spot is never reached.
3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::Close() {
3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(stream_ != NULL && stream_thread_->IsCurrent());
3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CritScope lock(&cs_);
3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  stream_ = NULL;
3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Clear out any pending event notifications
3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  stream_thread_->Clear(this, MSG_ST_EVENT);
3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (tcp_) {
3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    tcp_->Close(false);
3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    AdjustClock();
3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    CheckDestroy();
3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Worker thread methods
3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::OnChannelWritableState(TransportChannel* channel) {
3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG_F(LS_VERBOSE) << "[" << channel_name_ << "]";
3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread_->IsCurrent());
3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CritScope lock(&cs_);
3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!channel_) {
3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_WARNING) << "NULL channel";
3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(channel == channel_);
3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!tcp_) {
3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_WARNING) << "NULL tcp";
3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!ready_to_connect_ || !channel->writable())
3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ready_to_connect_ = false;
3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  tcp_->Connect();
3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  AdjustClock();
3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::OnChannelRead(TransportChannel* channel,
343f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org                                     const char* data, size_t size,
3442a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                                     const rtc::PacketTime& packet_time,
345f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org                                     int flags) {
3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //LOG_F(LS_VERBOSE) << "(" << size << ")";
3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread_->IsCurrent());
3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CritScope lock(&cs_);
3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!channel_) {
3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_WARNING) << "NULL channel";
3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(channel == channel_);
3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!tcp_) {
3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_WARNING) << "NULL tcp";
3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  tcp_->NotifyPacket(data, size);
3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  AdjustClock();
3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::OnChannelConnectionChanged(TransportChannel* channel,
3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                  const Candidate& candidate) {
3640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG_F(LS_VERBOSE) << "[" << channel_name_ << "]";
3650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread_->IsCurrent());
3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CritScope lock(&cs_);
3670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!channel_) {
3680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_WARNING) << "NULL channel";
3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(channel == channel_);
3720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!tcp_) {
3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_WARNING) << "NULL tcp";
3740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
3750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint16 mtu = 1280;  // safe default
3780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int family = candidate.address().family();
3790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Socket* socket =
3800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      worker_thread_->socketserver()->CreateAsyncSocket(family, SOCK_DGRAM);
3812a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::scoped_ptr<Socket> mtu_socket(socket);
3820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (socket == NULL) {
3830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_WARNING) << "Couldn't create socket while estimating MTU.";
3840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
3850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (mtu_socket->Connect(candidate.address()) < 0 ||
3860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        mtu_socket->EstimateMTU(&mtu) < 0) {
3870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_F(LS_WARNING) << "Failed to estimate MTU, error="
3880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        << mtu_socket->GetError();
3890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG_F(LS_VERBOSE) << "Using MTU of " << mtu << " bytes";
3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  tcp_->NotifyMTU(mtu);
3940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  AdjustClock();
3950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::OnTcpOpen(PseudoTcp* tcp) {
3980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG_F(LS_VERBOSE) << "[" << channel_name_ << "]";
3990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(cs_.CurrentThreadIsOwner());
4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread_->IsCurrent());
4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(tcp == tcp_);
4020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (stream_) {
4030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stream_readable_ = true;
4040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    pending_read_event_ = true;
4050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stream_thread_->Post(this, MSG_ST_EVENT,
4060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         new EventData(SE_OPEN | SE_READ | SE_WRITE));
4070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::OnTcpReadable(PseudoTcp* tcp) {
4110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //LOG_F(LS_VERBOSE);
4120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(cs_.CurrentThreadIsOwner());
4130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread_->IsCurrent());
4140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(tcp == tcp_);
4150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (stream_) {
4160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stream_readable_ = true;
4170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!pending_read_event_) {
4180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      pending_read_event_ = true;
4190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_READ));
4200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
4210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::OnTcpWriteable(PseudoTcp* tcp) {
4250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //LOG_F(LS_VERBOSE);
4260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(cs_.CurrentThreadIsOwner());
4270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread_->IsCurrent());
4280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(tcp == tcp_);
4290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (stream_)
4300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_WRITE));
4310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::OnTcpClosed(PseudoTcp* tcp, uint32 nError) {
4340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG_F(LS_VERBOSE) << "[" << channel_name_ << "]";
4350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(cs_.CurrentThreadIsOwner());
4360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread_->IsCurrent());
4370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(tcp == tcp_);
4380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (stream_)
4390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_CLOSE, nError));
4400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
4430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Multi-thread methods
4440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
4450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::OnMessage(Message* pmsg) {
4470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (pmsg->message_id == MSG_WK_CLOCK) {
4480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(worker_thread_->IsCurrent());
4500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //LOG(LS_INFO) << "PseudoTcpChannel::OnMessage(MSG_WK_CLOCK)";
4510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    CritScope lock(&cs_);
4520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (tcp_) {
4530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      tcp_->NotifyClock(PseudoTcp::Now());
4540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      AdjustClock(false);
4550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
4560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (pmsg->message_id == MSG_WK_PURGE) {
4580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(worker_thread_->IsCurrent());
4600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_INFO) << "(MSG_WK_PURGE)";
4610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // At this point, we know there are no additional worker thread messages.
4620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    CritScope lock(&cs_);
4630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(NULL == session_);
4640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(NULL == channel_);
4650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    worker_thread_ = NULL;
4660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    CheckDestroy();
4670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (pmsg->message_id == MSG_ST_EVENT) {
4690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(stream_thread_->IsCurrent());
4710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //LOG(LS_INFO) << "PseudoTcpChannel::OnMessage(MSG_ST_EVENT, "
4720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //             << data->event << ", " << data->error << ")";
4730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(stream_ != NULL);
4740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    EventData* data = static_cast<EventData*>(pmsg->pdata);
4750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (data->event & SE_READ) {
4760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      CritScope lock(&cs_);
4770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      pending_read_event_ = false;
4780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
4790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stream_->SignalEvent(stream_, data->event, data->error);
4800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    delete data;
4810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (pmsg->message_id == MSG_SI_DESTROYCHANNEL) {
4830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(signal_thread_->IsCurrent());
4850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_INFO) << "(MSG_SI_DESTROYCHANNEL)";
4860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(session_ != NULL);
4870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(channel_ != NULL);
4880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    session_->DestroyChannel(content_name_, channel_->component());
4890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (pmsg->message_id == MSG_SI_DESTROY) {
4910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(signal_thread_->IsCurrent());
4930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_INFO) << "(MSG_SI_DESTROY)";
4940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // The message queue is empty, so it is safe to destroy ourselves.
4950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    delete this;
4960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
4980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(false);
4990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgIPseudoTcpNotify::WriteResult PseudoTcpChannel::TcpWritePacket(
5030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    PseudoTcp* tcp, const char* buffer, size_t len) {
5040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(cs_.CurrentThreadIsOwner());
5050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(tcp == tcp_);
5060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(NULL != channel_);
5072a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::PacketOptions packet_options;
508f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  int sent = channel_->SendPacket(buffer, len, packet_options);
5090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (sent > 0) {
5100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //LOG_F(LS_VERBOSE) << "(" << sent << ") Sent";
5110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return IPseudoTcpNotify::WR_SUCCESS;
5120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (IsBlockingError(channel_->GetError())) {
5130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_VERBOSE) << "Blocking";
5140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return IPseudoTcpNotify::WR_SUCCESS;
5150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (channel_->GetError() == EMSGSIZE) {
5160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_ERROR) << "EMSGSIZE";
5170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return IPseudoTcpNotify::WR_TOO_LARGE;
5180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
5190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    PLOG(LS_ERROR, channel_->GetError()) << "PseudoTcpChannel::TcpWritePacket";
5200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(false);
5210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return IPseudoTcpNotify::WR_FAIL;
5220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::AdjustClock(bool clear) {
5260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(cs_.CurrentThreadIsOwner());
5270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(NULL != tcp_);
5280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  long timeout = 0;
5300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (tcp_->GetNextClock(PseudoTcp::Now(), timeout)) {
5310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(NULL != channel_);
5320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Reset the next clock, by clearing the old and setting a new one.
5330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (clear)
5340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      worker_thread_->Clear(this, MSG_WK_CLOCK);
5350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    worker_thread_->PostDelayed(_max(timeout, 0L), this, MSG_WK_CLOCK);
5360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
5370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  delete tcp_;
5400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  tcp_ = NULL;
5410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ready_to_connect_ = false;
5420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (channel_) {
5440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // If TCP has failed, no need for channel_ anymore
5450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    signal_thread_->Post(this, MSG_SI_DESTROYCHANNEL);
5460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::CheckDestroy() {
5500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(cs_.CurrentThreadIsOwner());
5510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if ((worker_thread_ != NULL) || (stream_ != NULL))
5520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
5530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  signal_thread_->Post(this, MSG_SI_DESTROY);
5540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
5570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// PseudoTcpChannel::InternalStream
5580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
5590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcpChannel::InternalStream::InternalStream(PseudoTcpChannel* parent)
5610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  : parent_(parent) {
5620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcpChannel::InternalStream::~InternalStream() {
5650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Close();
5660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgStreamState PseudoTcpChannel::InternalStream::GetState() const {
5690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!parent_)
5700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SS_CLOSED;
5710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return parent_->GetState();
5720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgStreamResult PseudoTcpChannel::InternalStream::Read(
5750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    void* buffer, size_t buffer_len, size_t* read, int* error) {
5760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!parent_) {
5770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (error)
5780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *error = ENOTCONN;
5790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SR_ERROR;
5800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return parent_->Read(buffer, buffer_len, read, error);
5820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgStreamResult PseudoTcpChannel::InternalStream::Write(
5850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const void* data, size_t data_len,  size_t* written, int* error) {
5860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!parent_) {
5870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (error)
5880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *error = ENOTCONN;
5890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SR_ERROR;
5900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return parent_->Write(data, data_len, written, error);
5920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcpChannel::InternalStream::Close() {
5950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!parent_)
5960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
5970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  parent_->Close();
5980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  parent_ = NULL;
5990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
6020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} // namespace cricket
604