147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <iomanip>
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/asyncsocket.h"
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h"
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/socketfactory.h"
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/socketpool.h"
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/socketstream.h"
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/thread.h"
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc {
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// StreamCache - Caches a set of open streams, defers creation to a separate
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//  StreamPool.
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgStreamCache::StreamCache(StreamPool* pool) : pool_(pool) {
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgStreamCache::~StreamCache() {
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (ConnectedList::iterator it = active_.begin(); it != active_.end();
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org       ++it) {
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    delete it->second;
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (ConnectedList::iterator it = cached_.begin(); it != cached_.end();
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org       ++it) {
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    delete it->second;
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgStreamInterface* StreamCache::RequestConnectedStream(
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    const SocketAddress& remote, int* err) {
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG_F(LS_VERBOSE) << "(" << remote << ")";
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (ConnectedList::iterator it = cached_.begin(); it != cached_.end();
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org       ++it) {
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (remote == it->first) {
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      it->second->SignalEvent.disconnect(this);
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Move from cached_ to active_
4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      active_.push_front(*it);
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      cached_.erase(it);
5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (err)
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *err = 0;
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG_F(LS_VERBOSE) << "Providing cached stream";
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return active_.front().second;
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (StreamInterface* stream = pool_->RequestConnectedStream(remote, err)) {
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // We track active streams so that we can remember their address
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    active_.push_front(ConnectedStream(remote, stream));
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_F(LS_VERBOSE) << "Providing new stream";
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return active_.front().second;
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return NULL;
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid StreamCache::ReturnConnectedStream(StreamInterface* stream) {
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (ConnectedList::iterator it = active_.begin(); it != active_.end();
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org       ++it) {
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (stream == it->second) {
7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG_F(LS_VERBOSE) << "(" << it->first << ")";
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (stream->GetState() == SS_CLOSED) {
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // Return closed streams
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        LOG_F(LS_VERBOSE) << "Returning closed stream";
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        pool_->ReturnConnectedStream(it->second);
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else {
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // Monitor open streams
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        stream->SignalEvent.connect(this, &StreamCache::OnStreamEvent);
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        LOG_F(LS_VERBOSE) << "Caching stream";
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        cached_.push_front(*it);
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      active_.erase(it);
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return;
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(false);
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid StreamCache::OnStreamEvent(StreamInterface* stream, int events, int err) {
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((events & SE_CLOSE) == 0) {
9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_F(LS_WARNING) << "(" << events << ", " << err
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                      << ") received non-close event";
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return;
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (ConnectedList::iterator it = cached_.begin(); it != cached_.end();
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org       ++it) {
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (stream == it->second) {
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG_F(LS_VERBOSE) << "(" << it->first << ")";
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // We don't cache closed streams, so return it.
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      it->second->SignalEvent.disconnect(this);
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG_F(LS_VERBOSE) << "Returning closed stream";
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      pool_->ReturnConnectedStream(it->second);
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      cached_.erase(it);
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return;
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(false);
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//////////////////////////////////////////////////////////////////////
11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// NewSocketPool
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//////////////////////////////////////////////////////////////////////
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgNewSocketPool::NewSocketPool(SocketFactory* factory) : factory_(factory) {
11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgNewSocketPool::~NewSocketPool() {
11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgStreamInterface*
12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgNewSocketPool::RequestConnectedStream(const SocketAddress& remote, int* err) {
12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  AsyncSocket* socket =
12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      factory_->CreateAsyncSocket(remote.family(), SOCK_STREAM);
12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!socket) {
12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (err)
12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      *err = -1;
12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return NULL;
12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((socket->Connect(remote) != 0) && !socket->IsBlocking()) {
12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (err)
13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      *err = socket->GetError();
13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    delete socket;
13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return NULL;
13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (err)
13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *err = 0;
13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return new SocketStream(socket);
13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid
14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgNewSocketPool::ReturnConnectedStream(StreamInterface* stream) {
14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Thread::Current()->Dispose(stream);
14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//////////////////////////////////////////////////////////////////////
14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// ReuseSocketPool
14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//////////////////////////////////////////////////////////////////////
14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgReuseSocketPool::ReuseSocketPool(SocketFactory* factory)
14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org: factory_(factory), stream_(NULL), checked_out_(false) {
15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgReuseSocketPool::~ReuseSocketPool() {
15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(!checked_out_);
15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  delete stream_;
15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgStreamInterface*
15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgReuseSocketPool::RequestConnectedStream(const SocketAddress& remote, int* err) {
15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Only one socket can be used from this "pool" at a time
16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(!checked_out_);
16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!stream_) {
16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_F(LS_VERBOSE) << "Creating new socket";
16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int family = remote.family();
16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // TODO: Deal with this when we/I clean up DNS resolution.
16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (remote.IsUnresolvedIP()) {
16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      family = AF_INET;
16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    AsyncSocket* socket =
16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        factory_->CreateAsyncSocket(family, SOCK_STREAM);
17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!socket) {
17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (err)
17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *err = -1;
17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return NULL;
17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    stream_ = new SocketStream(socket);
17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((stream_->GetState() == SS_OPEN) && (remote == remote_)) {
17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_F(LS_VERBOSE) << "Reusing connection to: " << remote_;
17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    remote_ = remote;
18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    stream_->Close();
18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((stream_->GetSocket()->Connect(remote_) != 0)
18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        && !stream_->GetSocket()->IsBlocking()) {
18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (err)
18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *err = stream_->GetSocket()->GetError();
18647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return NULL;
18747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
18847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG_F(LS_VERBOSE) << "Opening connection to: " << remote_;
18947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
19047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
19147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  stream_->SignalEvent.disconnect(this);
19247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  checked_out_ = true;
19347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (err)
19447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *err = 0;
19547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return stream_;
19647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
19747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
19847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid
19947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgReuseSocketPool::ReturnConnectedStream(StreamInterface* stream) {
20047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(stream == stream_);
20147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(checked_out_);
20247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  checked_out_ = false;
20347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Until the socket is reused, monitor it to determine if it closes.
20447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  stream_->SignalEvent.connect(this, &ReuseSocketPool::OnStreamEvent);
20547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
20647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
20747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid
20847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgReuseSocketPool::OnStreamEvent(StreamInterface* stream, int events, int err) {
20947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(stream == stream_);
21047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(!checked_out_);
21147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
21247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // If the stream was written to and then immediately returned to us then
21347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // we may get a writable notification for it, which we should ignore.
21447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (events == SE_WRITE) {
21547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_F(LS_VERBOSE) << "Pooled Socket unexpectedly writable: ignoring";
21647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return;
21747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
21847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
21947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // If the peer sent data, we can't process it, so drop the connection.
22047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // If the socket has closed, clean it up.
22147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // In either case, we'll reconnect it the next time it is used.
22247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(0 != (events & (SE_READ|SE_CLOSE)));
22347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (0 != (events & SE_CLOSE)) {
22447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_F(LS_VERBOSE) << "Connection closed with error: " << err;
22547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
22647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_F(LS_VERBOSE) << "Pooled Socket unexpectedly readable: closing";
22747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
22847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  stream_->Close();
22947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
23047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
23147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
23247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// LoggingPoolAdapter - Adapts a StreamPool to supply streams with attached
23347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// LoggingAdapters.
23447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
23547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
23647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgLoggingPoolAdapter::LoggingPoolAdapter(
23747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    StreamPool* pool, LoggingSeverity level, const std::string& label,
23847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    bool binary_mode)
23947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  : pool_(pool), level_(level), label_(label), binary_mode_(binary_mode) {
24047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
24147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
24247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgLoggingPoolAdapter::~LoggingPoolAdapter() {
24347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (StreamList::iterator it = recycle_bin_.begin();
24447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org       it != recycle_bin_.end(); ++it) {
24547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    delete *it;
24647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
24747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
24847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
24947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgStreamInterface* LoggingPoolAdapter::RequestConnectedStream(
25047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    const SocketAddress& remote, int* err) {
25147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (StreamInterface* stream = pool_->RequestConnectedStream(remote, err)) {
25247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT(SS_CLOSED != stream->GetState());
25347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    std::stringstream ss;
25447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ss << label_ << "(0x" << std::setfill('0') << std::hex << std::setw(8)
25547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org       << stream << ")";
25647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_V(level_) << ss.str()
25747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  << ((SS_OPEN == stream->GetState()) ? " Connected"
25847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                                      : " Connecting")
25947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  << " to " << remote;
26047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (recycle_bin_.empty()) {
26147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return new LoggingAdapter(stream, level_, ss.str(), binary_mode_);
26247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
26347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LoggingAdapter* logging = recycle_bin_.front();
26447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    recycle_bin_.pop_front();
26547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    logging->set_label(ss.str());
26647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    logging->Attach(stream);
26747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return logging;
26847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
26947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return NULL;
27047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
27147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
27247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid LoggingPoolAdapter::ReturnConnectedStream(StreamInterface* stream) {
27347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LoggingAdapter* logging = static_cast<LoggingAdapter*>(stream);
27447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  pool_->ReturnConnectedStream(logging->Detach());
27547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  recycle_bin_.push_back(logging);
27647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
27747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
27847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
27947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
28047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} // namespace rtc
281