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 "talk/p2p/base/tcpport.h" 29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/common.h" 31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/logging.h" 32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/p2p/base/common.h" 33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace cricket { 35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 36dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTCPPort::TCPPort(talk_base::Thread* thread, 37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen talk_base::PacketSocketFactory* factory, 38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen talk_base::Network* network, uint32 ip, 39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int min_port, int max_port, bool allow_listen) 40dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen : Port(thread, LOCAL_PORT_TYPE, factory, network, ip, min_port, max_port), 41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen incoming_only_(false), 42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen allow_listen_(allow_listen), 43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen socket_(NULL), 44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen error_(0) { 45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool TCPPort::Init() { 48dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Treat failure to create or bind a TCP socket as fatal. This 49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // should never happen. 50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen socket_ = factory_->CreateServerTcpSocket( 51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen talk_base::SocketAddress(ip_, 0), min_port_, max_port_, allow_listen_, 52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen false /* ssl */); 53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!socket_) { 54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_J(LS_ERROR, this) << "TCP socket creation failed."; 55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen socket_->SignalNewConnection.connect(this, &TCPPort::OnNewConnection); 58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochTCPPort::~TCPPort() { 62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete socket_; 63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochConnection* TCPPort::CreateConnection(const Candidate& address, 66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch CandidateOrigin origin) { 67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // We only support TCP protocols 68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((address.protocol() != "tcp") && (address.protocol() != "ssltcp")) 69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // We can't accept TCP connections incoming on other ports 72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (origin == ORIGIN_OTHER_PORT) 73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Check if we are allowed to make outgoing TCP connections 76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (incoming_only_ && (origin == ORIGIN_MESSAGE)) 77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // We don't know how to act as an ssl server yet 80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((address.protocol() == "ssltcp") && (origin == ORIGIN_THIS_PORT)) 81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch TCPConnection* conn = NULL; 84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (talk_base::AsyncPacketSocket* socket = 85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GetIncoming(address.address(), true)) { 86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch socket->SignalReadPacket.disconnect(this); 87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch conn = new TCPConnection(this, address, socket); 88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch conn = new TCPConnection(this, address); 90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch AddConnection(conn); 92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return conn; 93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid TCPPort::PrepareAddress() { 96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!allow_listen_) { 97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_J(LS_INFO, this) << "Not listening due to firewall restrictions."; 98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Note: We still add the address, since otherwise the remote side won't 100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // recognize our incoming TCP connections. 101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool allocated; 102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen talk_base::SocketAddress address = socket_->GetLocalAddress(&allocated); 103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (allocated) { 104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen AddAddress(address, "tcp", true); 105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen socket_->SignalAddressReady.connect(this, &TCPPort::OnAddresReady); 107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint TCPPort::SendTo(const void* data, size_t size, 111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const talk_base::SocketAddress& addr, bool payload) { 112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen talk_base::AsyncPacketSocket * socket = NULL; 113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (TCPConnection * conn = static_cast<TCPConnection*>(GetConnection(addr))) { 114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch socket = conn->socket(); 115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch socket = GetIncoming(addr); 117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!socket) { 119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_J(LS_ERROR, this) << "Attempted to send to an unknown destination, " 120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << addr.ToString(); 121731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return -1; // TODO: Set error_ 122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int sent = socket->Send(data, size); 125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (sent < 0) { 126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch error_ = socket->GetError(); 127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_J(LS_ERROR, this) << "TCP send of " << size 128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << " bytes failed with error " << error_; 129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return sent; 131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint TCPPort::SetOption(talk_base::Socket::Option opt, int value) { 134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return socket_->SetOption(opt, value); 135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint TCPPort::GetError() { 138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return error_; 139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid TCPPort::OnNewConnection(talk_base::AsyncPacketSocket* socket, 142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen talk_base::AsyncPacketSocket* new_socket) { 143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(socket == socket_); 144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Incoming incoming; 146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen incoming.addr = new_socket->GetRemoteAddress(); 147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen incoming.socket = new_socket; 148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch incoming.socket->SignalReadPacket.connect(this, &TCPPort::OnReadPacket); 149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_J(LS_VERBOSE, this) << "Accepted connection from " 151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << incoming.addr.ToString(); 152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch incoming_.push_back(incoming); 153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsentalk_base::AsyncPacketSocket* TCPPort::GetIncoming( 156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const talk_base::SocketAddress& addr, bool remove) { 157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen talk_base::AsyncPacketSocket* socket = NULL; 158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (std::list<Incoming>::iterator it = incoming_.begin(); 159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch it != incoming_.end(); ++it) { 160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (it->addr == addr) { 161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch socket = it->socket; 162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (remove) 163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch incoming_.erase(it); 164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return socket; 168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 170dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid TCPPort::OnReadPacket(talk_base::AsyncPacketSocket* socket, 171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const char* data, size_t size, 172dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const talk_base::SocketAddress& remote_addr) { 173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Port::OnReadPacket(data, size, remote_addr); 174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 176dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid TCPPort::OnAddresReady(talk_base::AsyncPacketSocket* socket, 177dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const talk_base::SocketAddress& address) { 178dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen AddAddress(address, "tcp", true); 179dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 180dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochTCPConnection::TCPConnection(TCPPort* port, const Candidate& candidate, 182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen talk_base::AsyncPacketSocket* socket) 183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch : Connection(port, 0, candidate), socket_(socket), error_(0) { 184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool outgoing = (socket_ == NULL); 185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (outgoing) { 186dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // TODO: Handle failures here (unlikely since TCP). 187dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 188dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen socket_ = port->socket_factory()->CreateClientTcpSocket( 189dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen talk_base::SocketAddress(port_->network()->ip(), 0), 190dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen candidate.address(), port->proxy(), port->user_agent(), 191dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen candidate.protocol() == "ssltcp"); 192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (socket_) { 193dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG_J(LS_VERBOSE, this) << "Connecting from " 194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << socket_->GetLocalAddress(NULL).ToString() 195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << " to " << candidate.address().ToString(); 196dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen set_connected(false); 197dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen socket_->SignalConnect.connect(this, &TCPConnection::OnConnect); 198dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 199dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG_J(LS_WARNING, this) << "Failed to create connection to " 200dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << candidate.address().ToString(); 201dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 203dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Incoming connections should match the network address. 204dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ASSERT(socket_->GetLocalAddress(NULL).ip() == port->ip_); 205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (socket_) { 208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen socket_->SignalReadPacket.connect(this, &TCPConnection::OnReadPacket); 209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen socket_->SignalClose.connect(this, &TCPConnection::OnClose); 210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochTCPConnection::~TCPConnection() { 214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete socket_; 215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint TCPConnection::Send(const void* data, size_t size) { 218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!socket_) { 219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen error_ = ENOTCONN; 220dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return SOCKET_ERROR; 221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (write_state() != STATE_WRITABLE) { 224731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO: Should STATE_WRITE_TIMEOUT return a non-blocking error? 225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch error_ = EWOULDBLOCK; 226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return SOCKET_ERROR; 227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int sent = socket_->Send(data, size); 229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (sent < 0) { 230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch error_ = socket_->GetError(); 231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch send_rate_tracker_.Update(sent); 233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return sent; 235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint TCPConnection::GetError() { 238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return error_; 239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 241dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid TCPConnection::OnConnect(talk_base::AsyncPacketSocket* socket) { 242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(socket == socket_); 243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_J(LS_VERBOSE, this) << "Connection established to " 244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << socket->GetRemoteAddress().ToString(); 245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch set_connected(true); 246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 248dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid TCPConnection::OnClose(talk_base::AsyncPacketSocket* socket, int error) { 249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(socket == socket_); 250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_J(LS_VERBOSE, this) << "Connection closed with error " << error; 251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch set_connected(false); 252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch set_write_state(STATE_WRITE_TIMEOUT); 253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 255dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid TCPConnection::OnReadPacket(talk_base::AsyncPacketSocket* socket, 256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const char* data, size_t size, 257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const talk_base::SocketAddress& remote_addr) { 258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(socket == socket_); 259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Connection::OnReadPacket(data, size); 260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} // namespace cricket 263