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(); |
| 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 |