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" 119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/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; 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rtc::PacketOptions options; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (channel_->writable()) { 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result = channel_->SendPacket(buffer->data(), buffer_size, options); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = net::MapSystemError(channel_->GetError()); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the underlying socket returns IO pending where it shouldn't we 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pretend the packet is dropped and return as succeeded because no 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // writeable callback will happen. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == net::ERR_IO_PENDING) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = net::OK; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Channel is not writable yet. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = net::ERR_IO_PENDING; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_callback_ = callback; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buffer_ = buffer; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buffer_size_ = buffer_size; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint TransportChannelSocketAdapter::SetReceiveBufferSize(int32 size) { 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_); 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return (channel_->SetOption(rtc::Socket::OPT_RCVBUF, size) == 0) ? 105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch net::OK : net::ERR_SOCKET_SET_RECEIVE_BUFFER_SIZE_ERROR; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 108c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint TransportChannelSocketAdapter::SetSendBufferSize(int32 size) { 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_); 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return (channel_->SetOption(rtc::Socket::OPT_SNDBUF, size) == 0) ? 111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch net::OK : net::ERR_SOCKET_SET_SEND_BUFFER_SIZE_ERROR; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransportChannelSocketAdapter::Close(int error_code) { 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!channel_) // Already closed. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(error_code != net::OK); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) closed_error_code_ = error_code; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_->SignalReadPacket.disconnect(this); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_->SignalDestroyed.disconnect(this); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_ = NULL; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!read_callback_.is_null()) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::CompletionCallback callback = read_callback_; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_.Reset(); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_ = NULL; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(error_code); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!write_callback_.is_null()) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::CompletionCallback callback = write_callback_; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_callback_.Reset(); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buffer_ = NULL; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(error_code); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransportChannelSocketAdapter::OnNewPacket( 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cricket::TransportChannel* channel, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* data, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t data_size, 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const rtc::PacketTime& packet_time, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags) { 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(channel, channel_); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!read_callback_.is_null()) { 150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(read_buffer_.get()); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LT(data_size, static_cast<size_t>(std::numeric_limits<int>::max())); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (read_buffer_size_ < static_cast<int>(data_size)) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Data buffer is smaller than the received packet. " 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Dropping the data that doesn't fit."; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_size = read_buffer_size_; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(read_buffer_->data(), data, data_size); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::CompletionCallback callback = read_callback_; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_.Reset(); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_ = NULL; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(data_size); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Data was received without a callback. Dropping the packet."; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransportChannelSocketAdapter::OnWritableState( 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cricket::TransportChannel* channel) { 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to send the packet if there is a pending write. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!write_callback_.is_null()) { 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rtc::PacketOptions options; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = channel_->SendPacket(write_buffer_->data(), 17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) write_buffer_size_, 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) options); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = net::MapSystemError(channel_->GetError()); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != net::ERR_IO_PENDING) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::CompletionCallback callback = write_callback_; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_callback_.Reset(); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buffer_ = NULL; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(result); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransportChannelSocketAdapter::OnChannelDestroyed( 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cricket::TransportChannel* channel) { 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(channel, channel_); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(net::ERR_CONNECTION_ABORTED); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace jingle_glue 201