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 "net/server/http_connection.h" | 5 #include "net/server/http_connection.h" |
6 | 6 |
7 #include "net/server/http_server.h" | |
8 #include "net/server/http_server_response_info.h" | |
9 #include "net/server/web_socket.h" | 7 #include "net/server/web_socket.h" |
10 #include "net/socket/stream_listen_socket.h" | 8 #include "net/socket/stream_socket.h" |
11 | 9 |
12 namespace net { | 10 namespace net { |
13 | 11 |
14 int HttpConnection::last_id_ = 0; | 12 namespace { |
15 | 13 |
16 void HttpConnection::Send(const std::string& data) { | 14 const int kInitialReadBufSize = 1024; |
17 if (!socket_.get()) | 15 const int kMinimumReadBufSize = 128; |
18 return; | 16 const int kCapacityIncreaseFactor = 2; |
19 socket_->Send(data); | 17 |
18 const int kDefaultPendingDataLimit = 1 * 1024 * 1024; // 1 Mbytes. | |
19 | |
20 } // namespace | |
21 | |
22 HttpConnection::ReadIOBuffer::ReadIOBuffer() | |
23 : base_(new GrowableIOBuffer()), | |
24 capacity_limit_(kDefaultPendingDataLimit) { | |
25 SetCapacity(kInitialReadBufSize); | |
20 } | 26 } |
21 | 27 |
22 void HttpConnection::Send(const char* bytes, int len) { | 28 HttpConnection::ReadIOBuffer::~ReadIOBuffer() { |
23 if (!socket_.get()) | 29 data_ = NULL; // base_ owns data_. |
24 return; | |
25 socket_->Send(bytes, len); | |
26 } | 30 } |
27 | 31 |
28 void HttpConnection::Send(const HttpServerResponseInfo& response) { | 32 IOBuffer* HttpConnection::ReadIOBuffer::GetUnusedIOBuffer() const { |
29 Send(response.Serialize()); | 33 return base_.get(); |
30 } | 34 } |
31 | 35 |
32 HttpConnection::HttpConnection(HttpServer* server, | 36 int HttpConnection::ReadIOBuffer::GetUnusedCapacity() const { |
33 scoped_ptr<StreamListenSocket> sock) | 37 return base_->RemainingCapacity(); |
34 : server_(server), | 38 } |
35 socket_(sock.Pass()) { | 39 |
36 id_ = last_id_++; | 40 int HttpConnection::ReadIOBuffer::GetCapacity() const { |
41 return base_->capacity(); | |
42 } | |
43 | |
44 void HttpConnection::ReadIOBuffer::SetCapacity(int capacity) { | |
45 base_->SetCapacity(capacity); | |
46 data_ = base_->StartOfBuffer(); | |
mmenke
2014/06/06 15:41:03
This looks wrong to me, when there's unconsumed da
byungchul
2014/06/06 19:17:35
Fixed and added unittests.
| |
47 } | |
48 | |
49 bool HttpConnection::ReadIOBuffer::IncreaseCapacity() { | |
50 if (GetCapacity() > capacity_limit_) { | |
51 LOG(ERROR) << "Too large read data is pending: capacity=" << GetCapacity() | |
52 << ", capacity_limit=" << capacity_limit_ | |
53 << ", consumed=" << base_->offset(); | |
54 return false; | |
55 } | |
56 SetCapacity(GetCapacity() * kCapacityIncreaseFactor); | |
57 return true; | |
58 } | |
59 | |
60 int HttpConnection::ReadIOBuffer::GetUnconsumedSize() const { | |
61 DCHECK_GE(base_->data(), data_); | |
62 return base_->data() - data_; | |
63 } | |
64 | |
65 void HttpConnection::ReadIOBuffer::DidRead(int bytes) { | |
66 DCHECK_LE(bytes, GetUnusedCapacity()); | |
67 base_->set_offset(base_->offset() + bytes); | |
68 } | |
69 | |
70 void HttpConnection::ReadIOBuffer::DidConsume(int bytes) { | |
71 DCHECK_LE(bytes, GetUnconsumedSize()); | |
72 if (bytes < GetUnconsumedSize()) { | |
73 data_ += bytes; | |
74 return; | |
75 } | |
76 // Since bytes == GetUnconsumedSize() here, base_->offset() is the size of | |
77 // consumed data, and all data has been consumed. No need to keep consumed | |
78 // data any more because no data will be moved. | |
79 // If capacity is too big, reduce it. | |
80 if (GetCapacity() > kMinimumReadBufSize | |
81 && GetCapacity() > base_->offset() * kCapacityIncreaseFactor) { | |
82 SetCapacity(GetCapacity() / kCapacityIncreaseFactor); | |
83 } | |
84 base_->set_offset(0); | |
85 } | |
86 | |
87 HttpConnection::PendingWriteIOBuffer::PendingWriteIOBuffer() | |
88 : total_size_(0), | |
89 total_size_limit_(kDefaultPendingDataLimit) { | |
90 } | |
91 | |
92 HttpConnection::PendingWriteIOBuffer::~PendingWriteIOBuffer() { | |
93 } | |
94 | |
95 bool HttpConnection::PendingWriteIOBuffer::IsEmpty() const { | |
96 return pending_data_.empty(); | |
97 } | |
98 | |
99 bool HttpConnection::PendingWriteIOBuffer::Append(const std::string& data) { | |
100 if (data.empty()) { | |
101 return true; | |
102 } | |
103 | |
104 if (total_size_ + static_cast<int>(data.size()) > total_size_limit_) { | |
105 LOG(ERROR) << "Too large write data is pending: size=" | |
106 << total_size_ + data.size() | |
107 << ", size_limit=" << total_size_limit_; | |
108 return false; | |
109 } | |
110 | |
111 pending_data_.push(data); | |
112 total_size_ += data.size(); | |
113 | |
114 // If new data is the first pending data, updates data_. | |
115 if (pending_data_.size() == 1) { | |
116 data_ = const_cast<char*>(pending_data_.front().data()); | |
117 } | |
118 return true; | |
119 } | |
120 | |
121 void HttpConnection::PendingWriteIOBuffer::DidConsume(int size) { | |
122 DCHECK_LE(size, total_size_); | |
123 DCHECK_LE(size, GetSizeToWrite()); | |
124 if (size == 0) { | |
125 return; | |
126 } | |
127 | |
128 if (size < GetSizeToWrite()) { | |
129 data_ += size; | |
130 } else { // size == GetSizeToWrite(). Updates data_ to next pending data. | |
131 pending_data_.pop(); | |
132 data_ = IsEmpty() ? NULL : const_cast<char*>(pending_data_.front().data()); | |
133 } | |
134 total_size_ -= size; | |
135 } | |
136 | |
137 int HttpConnection::PendingWriteIOBuffer::GetSizeToWrite() const { | |
138 if (IsEmpty()) { | |
139 DCHECK_EQ(total_size_, 0); | |
140 return 0; | |
141 } | |
142 DCHECK_GE(data_, pending_data_.front().data()); | |
143 int consumed = static_cast<int>(data_ - pending_data_.front().data()); | |
144 DCHECK_GT(static_cast<int>(pending_data_.front().size()), consumed); | |
145 return pending_data_.front().size() - consumed; | |
146 } | |
147 | |
148 HttpConnection::HttpConnection(int id, | |
149 scoped_ptr<StreamSocket> socket) | |
150 : id_(id), | |
151 socket_(socket.Pass()), | |
152 read_buf_(new ReadIOBuffer()), | |
153 write_buf_(new PendingWriteIOBuffer()) { | |
37 } | 154 } |
38 | 155 |
39 HttpConnection::~HttpConnection() { | 156 HttpConnection::~HttpConnection() { |
40 server_->delegate_->OnClose(id_); | |
41 } | 157 } |
42 | 158 |
43 void HttpConnection::Shift(int num_bytes) { | 159 void HttpConnection::SetWebSocket(scoped_ptr<WebSocket> web_socket) { |
44 recv_data_ = recv_data_.substr(num_bytes); | 160 DCHECK(!web_socket_); |
161 web_socket_ = web_socket.Pass(); | |
45 } | 162 } |
46 | 163 |
47 } // namespace net | 164 } // namespace net |
OLD | NEW |