1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/api/socket/tcp_socket.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/lazy_instance.h" 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/logging.h" 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/macros.h" 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/api/api_resource.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/address_list.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/ip_endpoint.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/rand_callback.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/tcp_client_socket.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kTCPSocketTypeInvalidError[] = 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Cannot call both connect and listen on the same socket."; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSocketListenError[] = "Could not listen on the specified port."; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static base::LazyInstance< 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BrowserContextKeyedAPIFactory<ApiResourceManager<ResumableTCPSocket> > > 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) g_factory = LAZY_INSTANCE_INITIALIZER; 264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static 284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)template <> 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<ApiResourceManager<ResumableTCPSocket> >* 304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ApiResourceManager<ResumableTCPSocket>::GetFactoryInstance() { 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return g_factory.Pointer(); 324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static base::LazyInstance<BrowserContextKeyedAPIFactory< 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ApiResourceManager<ResumableTCPServerSocket> > > g_server_factory = 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LAZY_INSTANCE_INITIALIZER; 378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// static 398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)template <> 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<ApiResourceManager<ResumableTCPServerSocket> >* 418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)ApiResourceManager<ResumableTCPServerSocket>::GetFactoryInstance() { 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return g_server_factory.Pointer(); 438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TCPSocket::TCPSocket(const std::string& owner_extension_id) 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : Socket(owner_extension_id), socket_mode_(UNKNOWN) {} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TCPSocket::TCPSocket(net::TCPClientSocket* tcp_client_socket, 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& owner_extension_id, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_connected) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : Socket(owner_extension_id), 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_(tcp_client_socket), 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_mode_(CLIENT) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->is_connected_ = is_connected; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TCPSocket::TCPSocket(net::TCPServerSocket* tcp_server_socket, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& owner_extension_id) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : Socket(owner_extension_id), 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_socket_(tcp_server_socket), 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) socket_mode_(SERVER) {} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TCPSocket* TCPSocket::CreateSocketForTesting( 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::TCPClientSocket* tcp_client_socket, 667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string& owner_extension_id, 677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool is_connected) { 687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return new TCPSocket(tcp_client_socket, owner_extension_id, is_connected); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TCPSocket* TCPSocket::CreateServerSocketForTesting( 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::TCPServerSocket* tcp_server_socket, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& owner_extension_id) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new TCPSocket(tcp_server_socket, owner_extension_id); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TCPSocket::~TCPSocket() { Disconnect(); } 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPSocket::Connect(const std::string& address, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int port, 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_mode_ == SERVER || !connect_callback_.is_null()) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(net::ERR_CONNECTION_FAILED); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!server_socket_.get()); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_mode_ = CLIENT; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connect_callback_ = callback; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = net::ERR_CONNECTION_FAILED; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_connected_) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::AddressList address_list; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!StringAndPortToAddressList(address, port, &address_list)) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = net::ERR_ADDRESS_INVALID; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) socket_.reset( 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new net::TCPClientSocket(address_list, NULL, net::NetLog::Source())); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connect_callback_ = callback; 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) result = socket_->Connect( 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&TCPSocket::OnConnectComplete, base::Unretained(this))); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (false); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != net::ERR_IO_PENDING) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnConnectComplete(result); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPSocket::Disconnect() { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_connected_ = false; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_.get()) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_->Disconnect(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_socket_.reset(NULL); 1218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) connect_callback_.Reset(); 1228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) read_callback_.Reset(); 1238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) accept_callback_.Reset(); 1248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) accept_socket_.reset(NULL); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPSocket::Bind(const std::string& address, int port) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net::ERR_FAILED; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void TCPSocket::Read(int count, const ReadCompletionCallback& callback) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_mode_ != CLIENT) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(net::ERR_FAILED, NULL); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!read_callback_.is_null()) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(net::ERR_IO_PENDING, NULL); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (count < 0) { 1458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) callback.Run(net::ERR_INVALID_ARGUMENT, NULL); 1468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 1478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!socket_.get() || !IsConnected()) { 1508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) callback.Run(net::ERR_SOCKET_NOT_CONNECTED, NULL); 1518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 1528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) read_callback_ = callback; 1558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) scoped_refptr<net::IOBuffer> io_buffer = new net::IOBuffer(count); 156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int result = socket_->Read( 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) io_buffer.get(), 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) count, 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind( 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &TCPSocket::OnReadComplete, base::Unretained(this), io_buffer)); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != net::ERR_IO_PENDING) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnReadComplete(io_buffer, result); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPSocket::RecvFrom(int count, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const RecvFromCompletionCallback& callback) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(net::ERR_FAILED, NULL, NULL, 0); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPSocket::SendTo(scoped_refptr<net::IOBuffer> io_buffer, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int byte_count, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& address, 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int port, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(net::ERR_FAILED); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPSocket::SetKeepAlive(bool enable, int delay) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!socket_.get()) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return socket_->SetKeepAlive(enable, delay); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPSocket::SetNoDelay(bool no_delay) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!socket_.get()) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return socket_->SetNoDelay(no_delay); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int TCPSocket::Listen(const std::string& address, 192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int port, 193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int backlog, 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error_msg) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_mode_ == CLIENT) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error_msg = kTCPSocketTypeInvalidError; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net::ERR_NOT_IMPLEMENTED; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!socket_.get()); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_mode_ = SERVER; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!server_socket_.get()) { 203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) server_socket_.reset(new net::TCPServerSocket(NULL, net::NetLog::Source())); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int result = server_socket_->ListenWithAddressAndPort(address, port, backlog); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error_msg = kSocketListenError; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void TCPSocket::Accept(const AcceptCompletionCallback& callback) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_mode_ != SERVER || !server_socket_.get()) { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(net::ERR_FAILED, NULL); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Limits to only 1 blocked accept call. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!accept_callback_.is_null()) { 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(net::ERR_FAILED, NULL); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int result = server_socket_->Accept( 225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &accept_socket_, 226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&TCPSocket::OnAccept, base::Unretained(this))); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == net::ERR_IO_PENDING) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_callback_ = callback; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (result == net::OK) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_callback_ = callback; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->OnAccept(result); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(result, NULL); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool TCPSocket::IsConnected() { 2387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch RefreshConnectionStatus(); 2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return is_connected_; 2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPSocket::GetPeerAddress(net::IPEndPoint* address) { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!socket_.get()) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !socket_->GetPeerAddress(address); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPSocket::GetLocalAddress(net::IPEndPoint* address) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_.get()) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !socket_->GetLocalAddress(address); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (server_socket_.get()) { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !server_socket_->GetLocalAddress(address); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)Socket::SocketType TCPSocket::GetSocketType() const { return Socket::TYPE_TCP; } 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPSocket::WriteImpl(net::IOBuffer* io_buffer, 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int io_buffer_size, 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::CompletionCallback& callback) { 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_mode_ != CLIENT) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net::ERR_FAILED; 2657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch else if (!socket_.get() || !IsConnected()) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net::ERR_SOCKET_NOT_CONNECTED; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return socket_->Write(io_buffer, io_buffer_size, callback); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid TCPSocket::RefreshConnectionStatus() { 272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!is_connected_) 273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (server_socket_) 275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 2767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!socket_->IsConnected()) { 2778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) Disconnect(); 2787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 2797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPSocket::OnConnectComplete(int result) { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!connect_callback_.is_null()); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!is_connected_); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_connected_ = result == net::OK; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connect_callback_.Run(result); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connect_callback_.Reset(); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!read_callback_.is_null()); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_.Run(result, io_buffer); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_.Reset(); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPSocket::OnAccept(int result) { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!accept_callback_.is_null()); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == net::OK && accept_socket_.get()) { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_callback_.Run( 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result, static_cast<net::TCPClientSocket*>(accept_socket_.release())); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_callback_.Run(result, NULL); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_callback_.Reset(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TCPSocket::Release() { 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Release() is only invoked when the underlying sockets are taken (via 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // ClientStream()) by TLSSocket. TLSSocket only supports CLIENT-mode 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // sockets. 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(!server_socket_.release() && !accept_socket_.release() && 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_mode_ == CLIENT) 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << "Called in server mode."; 3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Release() doesn't disconnect the underlying sockets, but it does 3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // disconnect them from this TCPSocket. 3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_connected_ = false; 3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) connect_callback_.Reset(); 3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) read_callback_.Reset(); 3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) accept_callback_.Reset(); 3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(socket_.get()) << "Called on null client socket."; 3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ignore_result(socket_.release()); 3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)net::TCPClientSocket* TCPSocket::ClientStream() { 3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (socket_mode_ != CLIENT || GetSocketType() != TYPE_TCP) 3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return NULL; 3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return socket_.get(); 3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool TCPSocket::HasPendingRead() const { 3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return !read_callback_.is_null(); 3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ResumableTCPSocket::ResumableTCPSocket(const std::string& owner_extension_id) 3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : TCPSocket(owner_extension_id), 3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) persistent_(false), 3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) buffer_size_(0), 341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) paused_(false) {} 3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)ResumableTCPSocket::ResumableTCPSocket(net::TCPClientSocket* tcp_client_socket, 3448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const std::string& owner_extension_id, 3458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bool is_connected) 3468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : TCPSocket(tcp_client_socket, owner_extension_id, is_connected), 3478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) persistent_(false), 3488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) buffer_size_(0), 349a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) paused_(false) {} 3508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ResumableTCPSocket::IsPersistent() const { return persistent(); } 3528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 3538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)ResumableTCPServerSocket::ResumableTCPServerSocket( 3548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const std::string& owner_extension_id) 355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : TCPSocket(owner_extension_id), persistent_(false), paused_(false) {} 3568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ResumableTCPServerSocket::IsPersistent() const { return persistent(); } 3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 360