OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "jingle/glue/channel_socket_adapter.h" | |
6 | |
7 #include <limits> | |
8 | |
9 #include "base/callback.h" | |
10 #include "base/logging.h" | |
11 #include "base/message_loop/message_loop.h" | |
12 #include "net/base/io_buffer.h" | |
13 #include "net/base/net_errors.h" | |
14 #include "third_party/webrtc/p2p/base/transportchannel.h" | |
15 | |
16 namespace jingle_glue { | |
17 | |
18 TransportChannelSocketAdapter::TransportChannelSocketAdapter( | |
19 cricket::TransportChannel* channel) | |
20 : message_loop_(base::MessageLoop::current()), | |
21 channel_(channel), | |
22 closed_error_code_(net::OK) { | |
23 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 | |
33 TransportChannelSocketAdapter::~TransportChannelSocketAdapter() { | |
34 if (!destruction_callback_.is_null()) | |
35 destruction_callback_.Run(); | |
36 } | |
37 | |
38 void TransportChannelSocketAdapter::SetOnDestroyedCallback( | |
39 const base::Closure& callback) { | |
40 destruction_callback_ = callback; | |
41 } | |
42 | |
43 int TransportChannelSocketAdapter::Read( | |
44 net::IOBuffer* buf, | |
45 int buffer_size, | |
46 const net::CompletionCallback& callback) { | |
47 DCHECK_EQ(base::MessageLoop::current(), message_loop_); | |
48 DCHECK(buf); | |
49 DCHECK(!callback.is_null()); | |
50 CHECK(read_callback_.is_null()); | |
51 | |
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; | |
60 | |
61 return net::ERR_IO_PENDING; | |
62 } | |
63 | |
64 int TransportChannelSocketAdapter::Write( | |
65 net::IOBuffer* buffer, | |
66 int buffer_size, | |
67 const net::CompletionCallback& callback) { | |
68 DCHECK_EQ(base::MessageLoop::current(), message_loop_); | |
69 DCHECK(buffer); | |
70 DCHECK(!callback.is_null()); | |
71 CHECK(write_callback_.is_null()); | |
72 | |
73 if (!channel_) { | |
74 DCHECK(closed_error_code_ != net::OK); | |
75 return closed_error_code_; | |
76 } | |
77 | |
78 int result; | |
79 rtc::PacketOptions options; | |
80 if (channel_->writable()) { | |
81 result = channel_->SendPacket(buffer->data(), buffer_size, options); | |
82 if (result < 0) { | |
83 result = net::MapSystemError(channel_->GetError()); | |
84 | |
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 } | |
91 } else { | |
92 // Channel is not writable yet. | |
93 result = net::ERR_IO_PENDING; | |
94 write_callback_ = callback; | |
95 write_buffer_ = buffer; | |
96 write_buffer_size_ = buffer_size; | |
97 } | |
98 | |
99 return result; | |
100 } | |
101 | |
102 int TransportChannelSocketAdapter::SetReceiveBufferSize(int32 size) { | |
103 DCHECK_EQ(base::MessageLoop::current(), message_loop_); | |
104 return (channel_->SetOption(rtc::Socket::OPT_RCVBUF, size) == 0) ? | |
105 net::OK : net::ERR_SOCKET_SET_RECEIVE_BUFFER_SIZE_ERROR; | |
106 } | |
107 | |
108 int TransportChannelSocketAdapter::SetSendBufferSize(int32 size) { | |
109 DCHECK_EQ(base::MessageLoop::current(), message_loop_); | |
110 return (channel_->SetOption(rtc::Socket::OPT_SNDBUF, size) == 0) ? | |
111 net::OK : net::ERR_SOCKET_SET_SEND_BUFFER_SIZE_ERROR; | |
112 } | |
113 | |
114 void TransportChannelSocketAdapter::Close(int error_code) { | |
115 DCHECK_EQ(base::MessageLoop::current(), message_loop_); | |
116 | |
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 | |
126 if (!read_callback_.is_null()) { | |
127 net::CompletionCallback callback = read_callback_; | |
128 read_callback_.Reset(); | |
129 read_buffer_ = NULL; | |
130 callback.Run(error_code); | |
131 } | |
132 | |
133 if (!write_callback_.is_null()) { | |
134 net::CompletionCallback callback = write_callback_; | |
135 write_callback_.Reset(); | |
136 write_buffer_ = NULL; | |
137 callback.Run(error_code); | |
138 } | |
139 } | |
140 | |
141 void TransportChannelSocketAdapter::OnNewPacket( | |
142 cricket::TransportChannel* channel, | |
143 const char* data, | |
144 size_t data_size, | |
145 const rtc::PacketTime& packet_time, | |
146 int flags) { | |
147 DCHECK_EQ(base::MessageLoop::current(), message_loop_); | |
148 DCHECK_EQ(channel, channel_); | |
149 if (!read_callback_.is_null()) { | |
150 DCHECK(read_buffer_.get()); | |
151 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 | |
161 net::CompletionCallback callback = read_callback_; | |
162 read_callback_.Reset(); | |
163 read_buffer_ = NULL; | |
164 | |
165 callback.Run(data_size); | |
166 } else { | |
167 LOG(WARNING) | |
168 << "Data was received without a callback. Dropping the packet."; | |
169 } | |
170 } | |
171 | |
172 void TransportChannelSocketAdapter::OnWritableState( | |
173 cricket::TransportChannel* channel) { | |
174 DCHECK_EQ(base::MessageLoop::current(), message_loop_); | |
175 // Try to send the packet if there is a pending write. | |
176 if (!write_callback_.is_null()) { | |
177 rtc::PacketOptions options; | |
178 int result = channel_->SendPacket(write_buffer_->data(), | |
179 write_buffer_size_, | |
180 options); | |
181 if (result < 0) | |
182 result = net::MapSystemError(channel_->GetError()); | |
183 | |
184 if (result != net::ERR_IO_PENDING) { | |
185 net::CompletionCallback callback = write_callback_; | |
186 write_callback_.Reset(); | |
187 write_buffer_ = NULL; | |
188 callback.Run(result); | |
189 } | |
190 } | |
191 } | |
192 | |
193 void TransportChannelSocketAdapter::OnChannelDestroyed( | |
194 cricket::TransportChannel* channel) { | |
195 DCHECK_EQ(base::MessageLoop::current(), message_loop_); | |
196 DCHECK_EQ(channel, channel_); | |
197 Close(net::ERR_CONNECTION_ABORTED); | |
198 } | |
199 | |
200 } // namespace jingle_glue | |
OLD | NEW |