OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/renderer_host/p2p/socket_host_tcp.h" | 5 #include "content/browser/renderer_host/p2p/socket_host_tcp.h" |
6 | 6 |
7 #include "base/sys_byteorder.h" | 7 #include "base/sys_byteorder.h" |
8 #include "content/common/p2p_messages.h" | 8 #include "content/common/p2p_messages.h" |
9 #include "ipc/ipc_sender.h" | 9 #include "ipc/ipc_sender.h" |
10 #include "net/base/io_buffer.h" | 10 #include "net/base/io_buffer.h" |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
80 | 80 |
81 void P2PSocketHostTcp::OnConnected(int result) { | 81 void P2PSocketHostTcp::OnConnected(int result) { |
82 DCHECK_EQ(state_, STATE_CONNECTING); | 82 DCHECK_EQ(state_, STATE_CONNECTING); |
83 DCHECK_NE(result, net::ERR_IO_PENDING); | 83 DCHECK_NE(result, net::ERR_IO_PENDING); |
84 | 84 |
85 if (result != net::OK) { | 85 if (result != net::OK) { |
86 OnError(); | 86 OnError(); |
87 return; | 87 return; |
88 } | 88 } |
89 | 89 |
90 if (!socket_->SetSendBufferSize(kMaxSendBufferSize)) { | |
91 LOG(WARNING) << "Failed to set send buffer size for TCP socket."; | |
92 } | |
93 | |
94 net::IPEndPoint address; | 90 net::IPEndPoint address; |
95 result = socket_->GetLocalAddress(&address); | 91 result = socket_->GetLocalAddress(&address); |
96 if (result < 0) { | 92 if (result < 0) { |
97 LOG(ERROR) << "P2PSocket::Init(): unable to get local address: " | 93 LOG(ERROR) << "P2PSocket::Init(): unable to get local address: " |
98 << result; | 94 << result; |
99 OnError(); | 95 OnError(); |
100 return; | 96 return; |
101 } | 97 } |
102 | 98 |
103 VLOG(1) << "Local address: " << address.ToString(); | 99 VLOG(1) << "Local address: " << address.ToString(); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
189 } | 185 } |
190 | 186 |
191 void P2PSocketHostTcp::Send(const net::IPEndPoint& to, | 187 void P2PSocketHostTcp::Send(const net::IPEndPoint& to, |
192 const std::vector<char>& data) { | 188 const std::vector<char>& data) { |
193 if (!socket_.get()) { | 189 if (!socket_.get()) { |
194 // The Send message may be sent after the an OnError message was | 190 // The Send message may be sent after the an OnError message was |
195 // sent by hasn't been processed the renderer. | 191 // sent by hasn't been processed the renderer. |
196 return; | 192 return; |
197 } | 193 } |
198 | 194 |
199 if (write_buffer_) { | |
200 // Silently drop packet if we haven't finished sending previous | |
201 // packet. | |
202 VLOG(1) << "Dropping TCP packet."; | |
203 return; | |
204 } | |
205 | |
206 if (!(to == remote_address_)) { | 195 if (!(to == remote_address_)) { |
207 // Renderer should use this socket only to send data to | 196 // Renderer should use this socket only to send data to |remote_address_|. |
208 // |remote_address_|. | |
209 NOTREACHED(); | 197 NOTREACHED(); |
210 OnError(); | 198 OnError(); |
211 return; | 199 return; |
212 } | 200 } |
213 | 201 |
214 if (!connected_) { | 202 if (!connected_) { |
215 P2PSocketHost::StunMessageType type; | 203 P2PSocketHost::StunMessageType type; |
216 bool stun = GetStunPacketType(&*data.begin(), data.size(), &type); | 204 bool stun = GetStunPacketType(&*data.begin(), data.size(), &type); |
217 if (!stun || type == STUN_DATA_INDICATION) { | 205 if (!stun || type == STUN_DATA_INDICATION) { |
218 LOG(ERROR) << "Page tried to send a data packet to " << to.ToString() | 206 LOG(ERROR) << "Page tried to send a data packet to " << to.ToString() |
219 << " before STUN binding is finished."; | 207 << " before STUN binding is finished."; |
220 OnError(); | 208 OnError(); |
221 return; | 209 return; |
222 } | 210 } |
223 } | 211 } |
224 | 212 |
225 int size = kPacketHeaderSize + data.size(); | 213 int size = kPacketHeaderSize + data.size(); |
226 write_buffer_ = new net::DrainableIOBuffer(new net::IOBuffer(size), size); | 214 scoped_refptr<net::DrainableIOBuffer> buffer = |
227 *reinterpret_cast<uint16*>(write_buffer_->data()) = | 215 new net::DrainableIOBuffer(new net::IOBuffer(size), size); |
228 base::HostToNet16(data.size()); | 216 *reinterpret_cast<uint16*>(buffer->data()) = base::HostToNet16(data.size()); |
229 memcpy(write_buffer_->data() + kPacketHeaderSize, &data[0], data.size()); | 217 memcpy(buffer->data() + kPacketHeaderSize, &data[0], data.size()); |
230 | 218 |
219 if (write_buffer_) { | |
220 write_queue_.push(buffer); | |
221 return; | |
222 } | |
223 | |
224 write_buffer_ = buffer; | |
231 DoWrite(); | 225 DoWrite(); |
232 } | 226 } |
233 | 227 |
234 void P2PSocketHostTcp::DoWrite() { | 228 void P2PSocketHostTcp::DoWrite() { |
235 while (true) { | 229 while (write_buffer_ && state_ == STATE_OPEN) { |
236 int result = socket_->Write(write_buffer_, write_buffer_->BytesRemaining(), | 230 int result = socket_->Write(write_buffer_, write_buffer_->BytesRemaining(), |
237 base::Bind(&P2PSocketHostTcp::OnWritten, | 231 base::Bind(&P2PSocketHostTcp::OnWritten, |
238 base::Unretained(this))); | 232 base::Unretained(this))); |
239 if (result >= 0) { | 233 HandleWriteResult(result); |
240 write_buffer_->DidConsume(result); | |
241 if (write_buffer_->BytesRemaining() == 0) { | |
242 write_buffer_ = NULL; | |
243 break; | |
244 } | |
245 } else { | |
246 if (result != net::ERR_IO_PENDING) { | |
247 LOG(ERROR) << "Error when sending data in TCP socket: " << result; | |
248 OnError(); | |
249 } | |
250 break; | |
251 } | |
252 } | 234 } |
253 } | 235 } |
254 | 236 |
255 void P2PSocketHostTcp::OnWritten(int result) { | 237 void P2PSocketHostTcp::OnWritten(int result) { |
256 DCHECK(write_buffer_); | 238 DCHECK(write_buffer_); |
257 DCHECK_NE(result, net::ERR_IO_PENDING); | 239 DCHECK_NE(result, net::ERR_IO_PENDING); |
258 | 240 |
259 if (result < 0) { | 241 if (result < 0) { |
Ronghua Wu (Left Chromium)
2013/04/04 05:23:59
you can remove this part now.
Sergey Ulanov
2013/04/04 18:40:34
Done.
| |
260 DCHECK(result != net::ERR_IO_PENDING); | 242 DCHECK(result != net::ERR_IO_PENDING); |
261 LOG(ERROR) << "Error when sending data in TCP socket: " << result; | 243 LOG(ERROR) << "Error when sending data in TCP socket: " << result; |
262 OnError(); | 244 OnError(); |
263 return; | 245 return; |
264 } | 246 } |
265 | 247 |
266 write_buffer_->DidConsume(result); | 248 HandleWriteResult(result); |
267 if (write_buffer_->BytesRemaining() == 0) { | 249 DoWrite(); |
268 write_buffer_ = NULL; | 250 } |
269 } else { | 251 |
270 DoWrite(); | 252 void P2PSocketHostTcp::HandleWriteResult(int result) { |
253 if (result >= 0) { | |
254 write_buffer_->DidConsume(result); | |
255 if (write_buffer_->BytesRemaining() == 0) { | |
256 message_sender_->Send(new P2PMsg_OnSendComplete(id_)); | |
257 if (write_queue_.empty()) { | |
258 write_buffer_ = NULL; | |
259 } else { | |
260 write_buffer_ = write_queue_.front(); | |
261 write_queue_.pop(); | |
262 } | |
263 } | |
264 } else if (result != net::ERR_IO_PENDING) { | |
265 LOG(ERROR) << "Error when sending data in TCP socket: " << result; | |
266 OnError(); | |
271 } | 267 } |
272 } | 268 } |
273 | 269 |
274 P2PSocketHost* P2PSocketHostTcp::AcceptIncomingTcpConnection( | 270 P2PSocketHost* P2PSocketHostTcp::AcceptIncomingTcpConnection( |
275 const net::IPEndPoint& remote_address, int id) { | 271 const net::IPEndPoint& remote_address, int id) { |
276 NOTREACHED(); | 272 NOTREACHED(); |
277 OnError(); | 273 OnError(); |
278 return NULL; | 274 return NULL; |
279 } | 275 } |
280 | 276 |
281 } // namespace content | 277 } // namespace content |
OLD | NEW |