channel_socket_adapter.cc revision 868fa2fe829687343ffae624259930155e16dbd8
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "jingle/glue/channel_socket_adapter.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/libjingle/source/talk/p2p/base/transportchannel.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace jingle_glue { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TransportChannelSocketAdapter::TransportChannelSocketAdapter( 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cricket::TransportChannel* channel) 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : message_loop_(base::MessageLoop::current()), 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_(channel), 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) closed_error_code_(net::OK) { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(channel_); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_->SignalReadPacket.connect( 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, &TransportChannelSocketAdapter::OnNewPacket); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_->SignalWritableState.connect( 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, &TransportChannelSocketAdapter::OnWritableState); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_->SignalDestroyed.connect( 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, &TransportChannelSocketAdapter::OnChannelDestroyed); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TransportChannelSocketAdapter::~TransportChannelSocketAdapter() { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!destruction_callback_.is_null()) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) destruction_callback_.Run(); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransportChannelSocketAdapter::SetOnDestroyedCallback( 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Closure& callback) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) destruction_callback_ = callback; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TransportChannelSocketAdapter::Read( 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::IOBuffer* buf, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buffer_size, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::CompletionCallback& callback) { 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(buf); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(read_callback_.is_null()); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!channel_) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(closed_error_code_ != net::OK); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return closed_error_code_; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_ = callback; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_ = buf; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_size_ = buffer_size; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net::ERR_IO_PENDING; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TransportChannelSocketAdapter::Write( 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::IOBuffer* buffer, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buffer_size, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::CompletionCallback& callback) { 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(buffer); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(write_callback_.is_null()); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!channel_) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(closed_error_code_ != net::OK); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return closed_error_code_; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (channel_->writable()) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = channel_->SendPacket(buffer->data(), buffer_size); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = net::MapSystemError(channel_->GetError()); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the underlying socket returns IO pending where it shouldn't we 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pretend the packet is dropped and return as succeeded because no 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // writeable callback will happen. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == net::ERR_IO_PENDING) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = net::OK; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Channel is not writable yet. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = net::ERR_IO_PENDING; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_callback_ = callback; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buffer_ = buffer; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buffer_size_ = buffer_size; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TransportChannelSocketAdapter::SetReceiveBufferSize(int32 size) { 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return channel_->SetOption(talk_base::Socket::OPT_RCVBUF, size) == 0; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TransportChannelSocketAdapter::SetSendBufferSize(int32 size) { 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return channel_->SetOption(talk_base::Socket::OPT_SNDBUF, size) == 0; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransportChannelSocketAdapter::Close(int error_code) { 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!channel_) // Already closed. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(error_code != net::OK); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) closed_error_code_ = error_code; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_->SignalReadPacket.disconnect(this); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_->SignalDestroyed.disconnect(this); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_ = NULL; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!read_callback_.is_null()) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::CompletionCallback callback = read_callback_; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_.Reset(); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_ = NULL; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(error_code); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!write_callback_.is_null()) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::CompletionCallback callback = write_callback_; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_callback_.Reset(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buffer_ = NULL; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(error_code); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransportChannelSocketAdapter::OnNewPacket( 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cricket::TransportChannel* channel, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* data, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t data_size, 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags) { 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(channel, channel_); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!read_callback_.is_null()) { 146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(read_buffer_.get()); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LT(data_size, static_cast<size_t>(std::numeric_limits<int>::max())); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (read_buffer_size_ < static_cast<int>(data_size)) { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Data buffer is smaller than the received packet. " 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Dropping the data that doesn't fit."; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_size = read_buffer_size_; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(read_buffer_->data(), data, data_size); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::CompletionCallback callback = read_callback_; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_.Reset(); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_ = NULL; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(data_size); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Data was received without a callback. Dropping the packet."; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransportChannelSocketAdapter::OnWritableState( 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cricket::TransportChannel* channel) { 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to send the packet if there is a pending write. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!write_callback_.is_null()) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = channel_->SendPacket(write_buffer_->data(), 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buffer_size_); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = net::MapSystemError(channel_->GetError()); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != net::ERR_IO_PENDING) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::CompletionCallback callback = write_callback_; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_callback_.Reset(); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buffer_ = NULL; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(result); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransportChannelSocketAdapter::OnChannelDestroyed( 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cricket::TransportChannel* channel) { 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(channel, channel_); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(net::ERR_CONNECTION_ABORTED); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace jingle_glue 195