1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/* 2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle 3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2005, Google Inc. 4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without 6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met: 7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 1. Redistributions of source code must retain the above copyright notice, 9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer. 10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright notice, 11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer in the documentation 12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * and/or other materials provided with the distribution. 13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 3. The name of the author may not be used to endorse or promote products 14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * derived from this software without specific prior written permission. 15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */ 27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <iomanip> 29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/asyncsocket.h" 31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/logging.h" 32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/socketfactory.h" 33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/socketpool.h" 34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/socketstream.h" 35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/thread.h" 36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace talk_base { 38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/////////////////////////////////////////////////////////////////////////////// 40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// StreamCache - Caches a set of open streams, defers creation to a separate 41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// StreamPool. 42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/////////////////////////////////////////////////////////////////////////////// 43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStreamCache::StreamCache(StreamPool* pool) : pool_(pool) { 45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStreamCache::~StreamCache() { 48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (ConnectedList::iterator it = active_.begin(); it != active_.end(); 49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ++it) { 50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete it->second; 51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (ConnectedList::iterator it = cached_.begin(); it != cached_.end(); 53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ++it) { 54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete it->second; 55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStreamInterface* StreamCache::RequestConnectedStream( 59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const SocketAddress& remote, int* err) { 60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_VERBOSE) << "(" << remote << ")"; 61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (ConnectedList::iterator it = cached_.begin(); it != cached_.end(); 62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ++it) { 63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (remote == it->first) { 64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch it->second->SignalEvent.disconnect(this); 65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Move from cached_ to active_ 66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch active_.push_front(*it); 67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch cached_.erase(it); 68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (err) 69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *err = 0; 70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_VERBOSE) << "Providing cached stream"; 71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return active_.front().second; 72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (StreamInterface* stream = pool_->RequestConnectedStream(remote, err)) { 75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // We track active streams so that we can remember their address 76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch active_.push_front(ConnectedStream(remote, stream)); 77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_VERBOSE) << "Providing new stream"; 78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return active_.front().second; 79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StreamCache::ReturnConnectedStream(StreamInterface* stream) { 84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (ConnectedList::iterator it = active_.begin(); it != active_.end(); 85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ++it) { 86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (stream == it->second) { 87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_VERBOSE) << "(" << it->first << ")"; 88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (stream->GetState() == SS_CLOSED) { 89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Return closed streams 90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_VERBOSE) << "Returning closed stream"; 91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch pool_->ReturnConnectedStream(it->second); 92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Monitor open streams 94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch stream->SignalEvent.connect(this, &StreamCache::OnStreamEvent); 95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_VERBOSE) << "Caching stream"; 96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch cached_.push_front(*it); 97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch active_.erase(it); 99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(false); 103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid StreamCache::OnStreamEvent(StreamInterface* stream, int events, int err) { 106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((events & SE_CLOSE) == 0) { 107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_WARNING) << "(" << events << ", " << err 108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << ") received non-close event"; 109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (ConnectedList::iterator it = cached_.begin(); it != cached_.end(); 112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ++it) { 113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (stream == it->second) { 114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_VERBOSE) << "(" << it->first << ")"; 115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // We don't cache closed streams, so return it. 116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch it->second->SignalEvent.disconnect(this); 117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_VERBOSE) << "Returning closed stream"; 118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch pool_->ReturnConnectedStream(it->second); 119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch cached_.erase(it); 120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(false); 124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch////////////////////////////////////////////////////////////////////// 127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// NewSocketPool 128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch////////////////////////////////////////////////////////////////////// 129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochNewSocketPool::NewSocketPool(SocketFactory* factory) : factory_(factory) { 131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochNewSocketPool::~NewSocketPool() { 134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStreamInterface* 137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochNewSocketPool::RequestConnectedStream(const SocketAddress& remote, int* err) { 138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch AsyncSocket* socket = factory_->CreateAsyncSocket(SOCK_STREAM); 139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!socket) { 140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(false); 141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (err) 142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *err = -1; 143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((socket->Connect(remote) != 0) && !socket->IsBlocking()) { 146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (err) 147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *err = socket->GetError(); 148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete socket; 149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (err) 152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *err = 0; 153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return new SocketStream(socket); 154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid 157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochNewSocketPool::ReturnConnectedStream(StreamInterface* stream) { 158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Thread::Current()->Dispose(stream); 159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch////////////////////////////////////////////////////////////////////// 162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// ReuseSocketPool 163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch////////////////////////////////////////////////////////////////////// 164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochReuseSocketPool::ReuseSocketPool(SocketFactory* factory) 166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch: factory_(factory), stream_(NULL), checked_out_(false) { 167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochReuseSocketPool::~ReuseSocketPool() { 170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(!checked_out_); 171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete stream_; 172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStreamInterface* 175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochReuseSocketPool::RequestConnectedStream(const SocketAddress& remote, int* err) { 176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Only one socket can be used from this "pool" at a time 177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(!checked_out_); 178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!stream_) { 179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_VERBOSE) << "Creating new socket"; 180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch AsyncSocket* socket = factory_->CreateAsyncSocket(SOCK_STREAM); 181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!socket) { 182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(false); 183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (err) 184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *err = -1; 185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch stream_ = new SocketStream(socket); 188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((stream_->GetState() == SS_OPEN) && (remote == remote_)) { 190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_VERBOSE) << "Reusing connection to: " << remote_; 191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch remote_ = remote; 193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch stream_->Close(); 194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((stream_->GetSocket()->Connect(remote_) != 0) 195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch && !stream_->GetSocket()->IsBlocking()) { 196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (err) 197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *err = stream_->GetSocket()->GetError(); 198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_VERBOSE) << "Opening connection to: " << remote_; 201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch stream_->SignalEvent.disconnect(this); 204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch checked_out_ = true; 205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (err) 206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *err = 0; 207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return stream_; 208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid 211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochReuseSocketPool::ReturnConnectedStream(StreamInterface* stream) { 212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(stream == stream_); 213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(checked_out_); 214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch checked_out_ = false; 215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Until the socket is reused, monitor it to determine if it closes. 216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch stream_->SignalEvent.connect(this, &ReuseSocketPool::OnStreamEvent); 217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid 220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochReuseSocketPool::OnStreamEvent(StreamInterface* stream, int events, int err) { 221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(stream == stream_); 222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(!checked_out_); 223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 224dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // If the stream was written to and then immediately returned to us then 225dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // we may get a writable notification for it, which we should ignore. 226dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (events == SE_WRITE) { 227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG_F(LS_VERBOSE) << "Pooled Socket unexpectedly writable: ignoring"; 228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 230dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 231dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // If the peer sent data, we can't process it, so drop the connection. 232dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // If the socket has closed, clean it up. 233dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // In either case, we'll reconnect it the next time it is used. 234dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ASSERT(0 != (events & (SE_READ|SE_CLOSE))); 235dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (0 != (events & SE_CLOSE)) { 236dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG_F(LS_VERBOSE) << "Connection closed with error: " << err; 237dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 238dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG_F(LS_VERBOSE) << "Pooled Socket unexpectedly readable: closing"; 239dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch stream_->Close(); 241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/////////////////////////////////////////////////////////////////////////////// 244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// LoggingPoolAdapter - Adapts a StreamPool to supply streams with attached 245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// LoggingAdapters. 246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/////////////////////////////////////////////////////////////////////////////// 247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochLoggingPoolAdapter::LoggingPoolAdapter( 249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch StreamPool* pool, LoggingSeverity level, const std::string& label, 250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool binary_mode) 251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch : pool_(pool), level_(level), label_(label), binary_mode_(binary_mode) { 252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochLoggingPoolAdapter::~LoggingPoolAdapter() { 255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (StreamList::iterator it = recycle_bin_.begin(); 256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch it != recycle_bin_.end(); ++it) { 257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete *it; 258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochStreamInterface* LoggingPoolAdapter::RequestConnectedStream( 262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const SocketAddress& remote, int* err) { 263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (StreamInterface* stream = pool_->RequestConnectedStream(remote, err)) { 264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(SS_CLOSED != stream->GetState()); 265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::stringstream ss; 266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ss << label_ << "(0x" << std::setfill('0') << std::hex << std::setw(8) 267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << stream << ")"; 268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_V(level_) << ss.str() 269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << ((SS_OPEN == stream->GetState()) ? " Connected" 270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch : " Connecting") 271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << " to " << remote; 272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (recycle_bin_.empty()) { 273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return new LoggingAdapter(stream, level_, ss.str(), binary_mode_); 274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LoggingAdapter* logging = recycle_bin_.front(); 276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch recycle_bin_.pop_front(); 277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch logging->set_label(ss.str()); 278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch logging->Attach(stream); 279f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return logging; 280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid LoggingPoolAdapter::ReturnConnectedStream(StreamInterface* stream) { 285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LoggingAdapter* logging = static_cast<LoggingAdapter*>(stream); 286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch pool_->ReturnConnectedStream(logging->Detach()); 287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch recycle_bin_.push_back(logging); 288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/////////////////////////////////////////////////////////////////////////////// 291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} // namespace talk_base 293