15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/* 25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * libjingle 35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2004--2005, Google Inc. 45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Redistribution and use in source and binary forms, with or without 65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * modification, are permitted provided that the following conditions are met: 75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * this list of conditions and the following disclaimer. 105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * this list of conditions and the following disclaimer in the documentation 125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * and/or other materials provided with the distribution. 135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 3. The name of the author may not be used to endorse or promote products 145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * derived from this software without specific prior written permission. 155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org */ 275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/p2p/base/tcpport.h" 295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/common.h" 315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/logging.h" 325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/p2p/base/common.h" 335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace cricket { 355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgTCPPort::TCPPort(talk_base::Thread* thread, 375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org talk_base::PacketSocketFactory* factory, 385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org talk_base::Network* network, const talk_base::IPAddress& ip, 395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int min_port, int max_port, const std::string& username, 405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& password, bool allow_listen) 415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : Port(thread, LOCAL_PORT_TYPE, factory, network, ip, min_port, max_port, 425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org username, password), 435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org incoming_only_(false), 445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org allow_listen_(allow_listen), 455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket_(NULL), 465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_(0) { 475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO(mallinath) - Set preference value as per RFC 6544. 485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // http://b/issue?id=7141794 495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool TCPPort::Init() { 525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (allow_listen_) { 535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Treat failure to create or bind a TCP socket as fatal. This 545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // should never happen. 555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket_ = socket_factory()->CreateServerTcpSocket( 565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org talk_base::SocketAddress(ip(), 0), min_port(), max_port(), 575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org false /* ssl */); 585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!socket_) { 595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_J(LS_ERROR, this) << "TCP socket creation failed."; 605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket_->SignalNewConnection.connect(this, &TCPPort::OnNewConnection); 635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket_->SignalAddressReady.connect(this, &TCPPort::OnAddressReady); 645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgTCPPort::~TCPPort() { 695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete socket_; 705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgConnection* TCPPort::CreateConnection(const Candidate& address, 735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CandidateOrigin origin) { 745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // We only support TCP protocols 755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((address.protocol() != TCP_PROTOCOL_NAME) && 765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org (address.protocol() != SSLTCP_PROTOCOL_NAME)) { 775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return NULL; 785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // We can't accept TCP connections incoming on other ports 815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (origin == ORIGIN_OTHER_PORT) 825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return NULL; 835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Check if we are allowed to make outgoing TCP connections 855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (incoming_only_ && (origin == ORIGIN_MESSAGE)) 865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return NULL; 875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // We don't know how to act as an ssl server yet 895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((address.protocol() == SSLTCP_PROTOCOL_NAME) && 905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org (origin == ORIGIN_THIS_PORT)) { 915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return NULL; 925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!IsCompatibleAddress(address.address())) { 955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return NULL; 965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org TCPConnection* conn = NULL; 995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (talk_base::AsyncPacketSocket* socket = 1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org GetIncoming(address.address(), true)) { 1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket->SignalReadPacket.disconnect(this); 1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org conn = new TCPConnection(this, address, socket); 1035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org conn = new TCPConnection(this, address); 1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org AddConnection(conn); 1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return conn; 1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid TCPPort::PrepareAddress() { 1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (socket_) { 1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // If socket isn't bound yet the address will be added in 1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // OnAddressReady(). Socket may be in the CLOSED state if Listen() 1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // failed, we still want ot add the socket address. 1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_VERBOSE) << "Preparing TCP address, current state: " 1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << socket_->GetState(); 1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (socket_->GetState() == talk_base::AsyncPacketSocket::STATE_BOUND || 1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket_->GetState() == talk_base::AsyncPacketSocket::STATE_CLOSED) 1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org AddAddress(socket_->GetLocalAddress(), socket_->GetLocalAddress(), 1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org TCP_PROTOCOL_NAME, LOCAL_PORT_TYPE, 1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ICE_TYPE_PREFERENCE_HOST_TCP, true); 1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_J(LS_INFO, this) << "Not listening due to firewall restrictions."; 1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Note: We still add the address, since otherwise the remote side won't 1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // recognize our incoming TCP connections. 1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org AddAddress(talk_base::SocketAddress(ip(), 0), 1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org talk_base::SocketAddress(ip(), 0), TCP_PROTOCOL_NAME, 1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOCAL_PORT_TYPE, ICE_TYPE_PREFERENCE_HOST_TCP, true); 1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint TCPPort::SendTo(const void* data, size_t size, 1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const talk_base::SocketAddress& addr, bool payload) { 1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org talk_base::AsyncPacketSocket * socket = NULL; 1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (TCPConnection * conn = static_cast<TCPConnection*>(GetConnection(addr))) { 1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket = conn->socket(); 1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket = GetIncoming(addr); 1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!socket) { 1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_J(LS_ERROR, this) << "Attempted to send to an unknown destination, " 1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << addr.ToSensitiveString(); 1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; // TODO: Set error_ 1445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int sent = socket->Send(data, size); 1475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (sent < 0) { 1485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = socket->GetError(); 1495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_J(LS_ERROR, this) << "TCP send of " << size 1505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << " bytes failed with error " << error_; 1515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return sent; 1535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint TCPPort::GetOption(talk_base::Socket::Option opt, int* value) { 1565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (socket_) { 1575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return socket_->GetOption(opt, value); 1585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 1595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SOCKET_ERROR; 1605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint TCPPort::SetOption(talk_base::Socket::Option opt, int value) { 1645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (socket_) { 1655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return socket_->SetOption(opt, value); 1665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SOCKET_ERROR; 1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint TCPPort::GetError() { 1725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return error_; 1735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid TCPPort::OnNewConnection(talk_base::AsyncPacketSocket* socket, 1765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org talk_base::AsyncPacketSocket* new_socket) { 1775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(socket == socket_); 1785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Incoming incoming; 1805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org incoming.addr = new_socket->GetRemoteAddress(); 1815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org incoming.socket = new_socket; 1825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org incoming.socket->SignalReadPacket.connect(this, &TCPPort::OnReadPacket); 1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org incoming.socket->SignalReadyToSend.connect(this, &TCPPort::OnReadyToSend); 1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_J(LS_VERBOSE, this) << "Accepted connection from " 1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << incoming.addr.ToSensitiveString(); 1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org incoming_.push_back(incoming); 1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtalk_base::AsyncPacketSocket* TCPPort::GetIncoming( 1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const talk_base::SocketAddress& addr, bool remove) { 1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org talk_base::AsyncPacketSocket* socket = NULL; 1935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (std::list<Incoming>::iterator it = incoming_.begin(); 1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org it != incoming_.end(); ++it) { 1955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (it->addr == addr) { 1965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket = it->socket; 1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (remove) 1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org incoming_.erase(it); 1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return socket; 2035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid TCPPort::OnReadPacket(talk_base::AsyncPacketSocket* socket, 2065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const char* data, size_t size, 2075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const talk_base::SocketAddress& remote_addr) { 2085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Port::OnReadPacket(data, size, remote_addr, PROTO_TCP); 2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid TCPPort::OnReadyToSend(talk_base::AsyncPacketSocket* socket) { 2125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Port::OnReadyToSend(); 2135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid TCPPort::OnAddressReady(talk_base::AsyncPacketSocket* socket, 2165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const talk_base::SocketAddress& address) { 2175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org AddAddress(address, address, "tcp", 2185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOCAL_PORT_TYPE, ICE_TYPE_PREFERENCE_HOST_TCP, 2195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org true); 2205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgTCPConnection::TCPConnection(TCPPort* port, const Candidate& candidate, 2235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org talk_base::AsyncPacketSocket* socket) 2245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : Connection(port, 0, candidate), socket_(socket), error_(0) { 2255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool outgoing = (socket_ == NULL); 2265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (outgoing) { 2275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO: Handle failures here (unlikely since TCP). 2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int opts = (candidate.protocol() == SSLTCP_PROTOCOL_NAME) ? 2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org talk_base::PacketSocketFactory::OPT_SSLTCP : 0; 2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket_ = port->socket_factory()->CreateClientTcpSocket( 2315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org talk_base::SocketAddress(port_->Network()->ip(), 0), 2325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org candidate.address(), port->proxy(), port->user_agent(), opts); 2335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (socket_) { 2345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_J(LS_VERBOSE, this) << "Connecting from " 2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << socket_->GetLocalAddress().ToSensitiveString() 2365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << " to " 2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << candidate.address().ToSensitiveString(); 2385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org set_connected(false); 2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket_->SignalConnect.connect(this, &TCPConnection::OnConnect); 2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 2415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_J(LS_WARNING, this) << "Failed to create connection to " 2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << candidate.address().ToSensitiveString(); 2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 2455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Incoming connections should match the network address. 2465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(socket_->GetLocalAddress().ipaddr() == port->ip()); 2475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (socket_) { 2505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket_->SignalReadPacket.connect(this, &TCPConnection::OnReadPacket); 2515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket_->SignalReadyToSend.connect(this, &TCPConnection::OnReadyToSend); 2525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket_->SignalClose.connect(this, &TCPConnection::OnClose); 2535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgTCPConnection::~TCPConnection() { 2575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete socket_; 2585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint TCPConnection::Send(const void* data, size_t size) { 2615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!socket_) { 2625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = ENOTCONN; 2635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SOCKET_ERROR; 2645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (write_state() != STATE_WRITABLE) { 2675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO: Should STATE_WRITE_TIMEOUT return a non-blocking error? 2685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = EWOULDBLOCK; 2695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SOCKET_ERROR; 2705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int sent = socket_->Send(data, size); 2725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (sent < 0) { 2735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = socket_->GetError(); 2745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 2755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org send_rate_tracker_.Update(sent); 2765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return sent; 2785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint TCPConnection::GetError() { 2815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return error_; 2825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid TCPConnection::OnConnect(talk_base::AsyncPacketSocket* socket) { 2855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(socket == socket_); 2865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_J(LS_VERBOSE, this) << "Connection established to " 2875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << socket->GetRemoteAddress().ToSensitiveString(); 2885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org set_connected(true); 2895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid TCPConnection::OnClose(talk_base::AsyncPacketSocket* socket, int error) { 2925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(socket == socket_); 2935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_J(LS_VERBOSE, this) << "Connection closed with error " << error; 2945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org set_connected(false); 2955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org set_write_state(STATE_WRITE_TIMEOUT); 2965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid TCPConnection::OnReadPacket(talk_base::AsyncPacketSocket* socket, 2995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const char* data, size_t size, 3005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const talk_base::SocketAddress& remote_addr) { 3015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(socket == socket_); 3025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Connection::OnReadPacket(data, size); 3035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 3045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid TCPConnection::OnReadyToSend(talk_base::AsyncPacketSocket* socket) { 3065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(socket == socket_); 3075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Connection::OnReadyToSend(); 3085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 3095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} // namespace cricket 311