OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 "components/devtools_bridge/socket_tunnel_connection.h" | |
6 | |
7 #include <stdlib.h> | |
8 | |
9 #include "net/base/io_buffer.h" | |
10 #include "net/base/net_errors.h" | |
11 #include "net/socket/stream_socket.h" | |
12 | |
13 namespace devtools_bridge { | |
14 | |
15 SocketTunnelConnection::SocketTunnelConnection(int index) : index_(index) { | |
16 } | |
17 | |
18 SocketTunnelConnection::~SocketTunnelConnection() { | |
19 } | |
20 | |
21 void SocketTunnelConnection::Write(scoped_refptr<net::IOBufferWithSize> chunk) { | |
22 // TODO(serya): While it is unlikely (socket normally much faster than | |
23 // data channel) we should disconnect if too much data buffered. | |
24 buffer_.push_back(chunk); | |
25 if (buffer_.size() == 1) { | |
26 current_ = new net::DrainableIOBuffer(chunk.get(), chunk->size()); | |
27 WriteCurrent(); | |
28 } | |
29 } | |
30 | |
31 void SocketTunnelConnection::BuildControlPacket(char* buffer, | |
32 int op_code) { | |
33 static_assert(kControlPacketSizeBytes == 3, | |
34 "kControlPacketSizeBytes should equal 3"); | |
35 buffer[0] = kControlConnectionId; | |
36 buffer[1] = op_code; | |
37 buffer[2] = index_ + kMinConnectionId; | |
38 } | |
39 | |
40 void SocketTunnelConnection::WriteCurrent() { | |
41 while (true) { | |
42 while(current_->BytesRemaining() > 0) { | |
43 int result = socket()->Write(current_.get(), current_->BytesRemaining(), | |
44 base::Bind(&SocketTunnelConnection::OnWriteComplete, | |
45 base::Unretained(this))); | |
46 if (result > 0) | |
47 current_->DidConsume(result); | |
48 } | |
49 current_ = NULL; | |
50 | |
51 buffer_.pop_front(); | |
52 if (buffer_.empty()) | |
53 return; // Stop writing. | |
54 | |
55 net::IOBufferWithSize* chunk = buffer_.front().get(); | |
56 current_ = new net::DrainableIOBuffer(chunk, chunk->size()); | |
57 } | |
58 } | |
59 | |
60 void SocketTunnelConnection::OnWriteComplete(int result) { | |
61 if (result > 0) { | |
62 current_->DidConsume(result); | |
63 WriteCurrent(); | |
64 } | |
65 } | |
66 | |
67 void SocketTunnelConnection::ReadNextChunk() { | |
68 if (!read_buffer_.get()) { | |
69 read_buffer_ = new net::GrowableIOBuffer(); | |
70 read_buffer_->SetCapacity(kMaxPacketSizeBytes); | |
71 } | |
72 // Header of the data packet. | |
73 *read_buffer_->StartOfBuffer() = index_ + kMinConnectionId; | |
74 read_buffer_->set_offset(1); | |
75 | |
76 int result = socket()->Read( | |
77 read_buffer_.get(), | |
78 read_buffer_->RemainingCapacity(), | |
79 base::Bind(&SocketTunnelConnection::OnReadComplete, | |
80 base::Unretained(this))); | |
81 if (result == net::ERR_IO_PENDING) | |
82 return; | |
83 else | |
84 OnReadComplete(result); | |
85 } | |
86 | |
87 void SocketTunnelConnection::OnReadComplete(int result) { | |
88 if (result > 0) { | |
89 OnDataPacketRead(read_buffer_->StartOfBuffer(), | |
90 read_buffer_->offset() + result); | |
91 } else { | |
92 OnReadError(result); | |
93 } | |
94 } | |
95 | |
96 } // namespace devtools_bridge | |
OLD | NEW |