blob: 1645f96bdfb304043c3c01a9bbd480a45ae3d5c6 [file] [log] [blame]
[email protected]ad48b7f2012-02-21 21:20:021// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]2fc3b422010-09-28 20:59:562// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]f6da0b252011-03-31 00:26:035#include "jingle/glue/channel_socket_adapter.h"
[email protected]2fc3b422010-09-28 20:59:566
7#include <limits>
8
[email protected]ad48b7f2012-02-21 21:20:029#include "base/callback.h"
[email protected]2fc3b422010-09-28 20:59:5610#include "base/logging.h"
[email protected]2a9ec0e2013-07-17 23:00:3011#include "base/message_loop/message_loop.h"
[email protected]2fc3b422010-09-28 20:59:5612#include "net/base/io_buffer.h"
13#include "net/base/net_errors.h"
[email protected]2fc3b422010-09-28 20:59:5614#include "third_party/libjingle/source/talk/p2p/base/transportchannel.h"
15
[email protected]f6da0b252011-03-31 00:26:0316namespace jingle_glue {
[email protected]2fc3b422010-09-28 20:59:5617
18TransportChannelSocketAdapter::TransportChannelSocketAdapter(
19 cricket::TransportChannel* channel)
[email protected]b231184d2013-04-27 07:51:5520 : message_loop_(base::MessageLoop::current()),
[email protected]6c875752011-04-01 01:59:0721 channel_(channel),
[email protected]2fc3b422010-09-28 20:59:5622 closed_error_code_(net::OK) {
[email protected]2fc3b422010-09-28 20:59:5623 DCHECK(channel_);
24
25 channel_->SignalReadPacket.connect(
26 this, &TransportChannelSocketAdapter::OnNewPacket);
27 channel_->SignalWritableState.connect(
28 this, &TransportChannelSocketAdapter::OnWritableState);
29 channel_->SignalDestroyed.connect(
30 this, &TransportChannelSocketAdapter::OnChannelDestroyed);
31}
32
33TransportChannelSocketAdapter::~TransportChannelSocketAdapter() {
[email protected]ad48b7f2012-02-21 21:20:0234 if (!destruction_callback_.is_null())
35 destruction_callback_.Run();
36}
37
38void TransportChannelSocketAdapter::SetOnDestroyedCallback(
39 const base::Closure& callback) {
40 destruction_callback_ = callback;
[email protected]2fc3b422010-09-28 20:59:5641}
42
43int TransportChannelSocketAdapter::Read(
[email protected]83039bb2011-12-09 18:43:5544 net::IOBuffer* buf,
45 int buffer_size,
[email protected]3f55aa12011-12-07 02:03:3346 const net::CompletionCallback& callback) {
[email protected]b231184d2013-04-27 07:51:5547 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
[email protected]3f55aa12011-12-07 02:03:3348 DCHECK(buf);
49 DCHECK(!callback.is_null());
[email protected]83039bb2011-12-09 18:43:5550 CHECK(read_callback_.is_null());
[email protected]2fc3b422010-09-28 20:59:5651
52 if (!channel_) {
53 DCHECK(closed_error_code_ != net::OK);
54 return closed_error_code_;
55 }
56
57 read_callback_ = callback;
58 read_buffer_ = buf;
59 read_buffer_size_ = buffer_size;
[email protected]2fc3b422010-09-28 20:59:5660
61 return net::ERR_IO_PENDING;
62}
63
64int TransportChannelSocketAdapter::Write(
[email protected]83039bb2011-12-09 18:43:5565 net::IOBuffer* buffer,
66 int buffer_size,
67 const net::CompletionCallback& callback) {
[email protected]b231184d2013-04-27 07:51:5568 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
[email protected]2fc3b422010-09-28 20:59:5669 DCHECK(buffer);
[email protected]83039bb2011-12-09 18:43:5570 DCHECK(!callback.is_null());
71 CHECK(write_callback_.is_null());
[email protected]2fc3b422010-09-28 20:59:5672
73 if (!channel_) {
74 DCHECK(closed_error_code_ != net::OK);
75 return closed_error_code_;
76 }
77
[email protected]4d83fbc2011-04-22 19:35:4978 int result;
[email protected]e758d4c2014-08-06 16:48:1679 rtc::PacketOptions options;
[email protected]4d83fbc2011-04-22 19:35:4980 if (channel_->writable()) {
[email protected]e6b239a2014-02-15 06:09:5281 result = channel_->SendPacket(buffer->data(), buffer_size, options);
[email protected]87185ec2011-07-27 13:25:4082 if (result < 0) {
[email protected]4d83fbc2011-04-22 19:35:4983 result = net::MapSystemError(channel_->GetError());
[email protected]87185ec2011-07-27 13:25:4084
85 // If the underlying socket returns IO pending where it shouldn't we
86 // pretend the packet is dropped and return as succeeded because no
87 // writeable callback will happen.
88 if (result == net::ERR_IO_PENDING)
89 result = net::OK;
90 }
[email protected]4d83fbc2011-04-22 19:35:4991 } else {
92 // Channel is not writable yet.
93 result = net::ERR_IO_PENDING;
[email protected]4d83fbc2011-04-22 19:35:4994 write_callback_ = callback;
95 write_buffer_ = buffer;
96 write_buffer_size_ = buffer_size;
97 }
98
[email protected]2fc3b422010-09-28 20:59:5699 return result;
100}
101
[email protected]28b96d1c2014-04-09 12:21:15102int TransportChannelSocketAdapter::SetReceiveBufferSize(int32 size) {
[email protected]b231184d2013-04-27 07:51:55103 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
[email protected]e758d4c2014-08-06 16:48:16104 return (channel_->SetOption(rtc::Socket::OPT_RCVBUF, size) == 0) ?
[email protected]28b96d1c2014-04-09 12:21:15105 net::OK : net::ERR_SOCKET_SET_RECEIVE_BUFFER_SIZE_ERROR;
[email protected]2fc3b422010-09-28 20:59:56106}
107
[email protected]28b96d1c2014-04-09 12:21:15108int TransportChannelSocketAdapter::SetSendBufferSize(int32 size) {
[email protected]b231184d2013-04-27 07:51:55109 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
[email protected]e758d4c2014-08-06 16:48:16110 return (channel_->SetOption(rtc::Socket::OPT_SNDBUF, size) == 0) ?
[email protected]28b96d1c2014-04-09 12:21:15111 net::OK : net::ERR_SOCKET_SET_SEND_BUFFER_SIZE_ERROR;
[email protected]2fc3b422010-09-28 20:59:56112}
113
114void TransportChannelSocketAdapter::Close(int error_code) {
[email protected]b231184d2013-04-27 07:51:55115 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
[email protected]2fc3b422010-09-28 20:59:56116
117 if (!channel_) // Already closed.
118 return;
119
120 DCHECK(error_code != net::OK);
121 closed_error_code_ = error_code;
122 channel_->SignalReadPacket.disconnect(this);
123 channel_->SignalDestroyed.disconnect(this);
124 channel_ = NULL;
125
[email protected]83039bb2011-12-09 18:43:55126 if (!read_callback_.is_null()) {
[email protected]3f55aa12011-12-07 02:03:33127 net::CompletionCallback callback = read_callback_;
128 read_callback_.Reset();
129 read_buffer_ = NULL;
130 callback.Run(error_code);
[email protected]2fc3b422010-09-28 20:59:56131 }
132
[email protected]83039bb2011-12-09 18:43:55133 if (!write_callback_.is_null()) {
134 net::CompletionCallback callback = write_callback_;
135 write_callback_.Reset();
[email protected]2fc3b422010-09-28 20:59:56136 write_buffer_ = NULL;
[email protected]83039bb2011-12-09 18:43:55137 callback.Run(error_code);
[email protected]2fc3b422010-09-28 20:59:56138 }
139}
140
141void TransportChannelSocketAdapter::OnNewPacket(
[email protected]8bb746372012-04-26 04:20:12142 cricket::TransportChannel* channel,
143 const char* data,
144 size_t data_size,
[email protected]e758d4c2014-08-06 16:48:16145 const rtc::PacketTime& packet_time,
[email protected]8bb746372012-04-26 04:20:12146 int flags) {
[email protected]b231184d2013-04-27 07:51:55147 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
[email protected]2fc3b422010-09-28 20:59:56148 DCHECK_EQ(channel, channel_);
[email protected]83039bb2011-12-09 18:43:55149 if (!read_callback_.is_null()) {
[email protected]f9d8a772013-06-01 04:33:17150 DCHECK(read_buffer_.get());
[email protected]2fc3b422010-09-28 20:59:56151 CHECK_LT(data_size, static_cast<size_t>(std::numeric_limits<int>::max()));
152
153 if (read_buffer_size_ < static_cast<int>(data_size)) {
154 LOG(WARNING) << "Data buffer is smaller than the received packet. "
155 << "Dropping the data that doesn't fit.";
156 data_size = read_buffer_size_;
157 }
158
159 memcpy(read_buffer_->data(), data, data_size);
160
[email protected]83039bb2011-12-09 18:43:55161 net::CompletionCallback callback = read_callback_;
162 read_callback_.Reset();
163 read_buffer_ = NULL;
164
165 callback.Run(data_size);
[email protected]2fc3b422010-09-28 20:59:56166 } else {
167 LOG(WARNING)
168 << "Data was received without a callback. Dropping the packet.";
169 }
170}
171
172void TransportChannelSocketAdapter::OnWritableState(
173 cricket::TransportChannel* channel) {
[email protected]b231184d2013-04-27 07:51:55174 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
[email protected]2fc3b422010-09-28 20:59:56175 // Try to send the packet if there is a pending write.
[email protected]83039bb2011-12-09 18:43:55176 if (!write_callback_.is_null()) {
[email protected]e758d4c2014-08-06 16:48:16177 rtc::PacketOptions options;
[email protected]2fc3b422010-09-28 20:59:56178 int result = channel_->SendPacket(write_buffer_->data(),
[email protected]7791cf42013-09-23 23:11:57179 write_buffer_size_,
[email protected]e6b239a2014-02-15 06:09:52180 options);
[email protected]2fc3b422010-09-28 20:59:56181 if (result < 0)
[email protected]f6da0b252011-03-31 00:26:03182 result = net::MapSystemError(channel_->GetError());
[email protected]2fc3b422010-09-28 20:59:56183
184 if (result != net::ERR_IO_PENDING) {
[email protected]83039bb2011-12-09 18:43:55185 net::CompletionCallback callback = write_callback_;
186 write_callback_.Reset();
[email protected]f749f9c2011-12-09 01:06:19187 write_buffer_ = NULL;
[email protected]83039bb2011-12-09 18:43:55188 callback.Run(result);
[email protected]2fc3b422010-09-28 20:59:56189 }
190 }
191}
192
193void TransportChannelSocketAdapter::OnChannelDestroyed(
194 cricket::TransportChannel* channel) {
[email protected]b231184d2013-04-27 07:51:55195 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
[email protected]2fc3b422010-09-28 20:59:56196 DCHECK_EQ(channel, channel_);
197 Close(net::ERR_CONNECTION_ABORTED);
198}
199
[email protected]f6da0b252011-03-31 00:26:03200} // namespace jingle_glue