http_connection.cc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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. #include "net/server/http_connection.h"
  5. #include <utility>
  6. #include "base/logging.h"
  7. #include "net/server/web_socket.h"
  8. #include "net/socket/stream_socket.h"
  9. namespace net {
  10. HttpConnection::ReadIOBuffer::ReadIOBuffer()
  11. : base_(base::MakeRefCounted<GrowableIOBuffer>()) {
  12. SetCapacity(kInitialBufSize);
  13. }
  14. HttpConnection::ReadIOBuffer::~ReadIOBuffer() {
  15. data_ = nullptr; // base_ owns data_.
  16. }
  17. int HttpConnection::ReadIOBuffer::GetCapacity() const {
  18. return base_->capacity();
  19. }
  20. void HttpConnection::ReadIOBuffer::SetCapacity(int capacity) {
  21. DCHECK_LE(GetSize(), capacity);
  22. data_ = nullptr;
  23. base_->SetCapacity(capacity);
  24. data_ = base_->data();
  25. }
  26. bool HttpConnection::ReadIOBuffer::IncreaseCapacity() {
  27. if (GetCapacity() >= max_buffer_size_) {
  28. LOG(ERROR) << "Too large read data is pending: capacity=" << GetCapacity()
  29. << ", max_buffer_size=" << max_buffer_size_
  30. << ", read=" << GetSize();
  31. return false;
  32. }
  33. int new_capacity = GetCapacity() * kCapacityIncreaseFactor;
  34. if (new_capacity > max_buffer_size_)
  35. new_capacity = max_buffer_size_;
  36. SetCapacity(new_capacity);
  37. return true;
  38. }
  39. char* HttpConnection::ReadIOBuffer::StartOfBuffer() const {
  40. return base_->StartOfBuffer();
  41. }
  42. int HttpConnection::ReadIOBuffer::GetSize() const {
  43. return base_->offset();
  44. }
  45. void HttpConnection::ReadIOBuffer::DidRead(int bytes) {
  46. DCHECK_GE(RemainingCapacity(), bytes);
  47. base_->set_offset(base_->offset() + bytes);
  48. data_ = base_->data();
  49. }
  50. int HttpConnection::ReadIOBuffer::RemainingCapacity() const {
  51. return base_->RemainingCapacity();
  52. }
  53. void HttpConnection::ReadIOBuffer::DidConsume(int bytes) {
  54. int previous_size = GetSize();
  55. int unconsumed_size = previous_size - bytes;
  56. DCHECK_LE(0, unconsumed_size);
  57. if (unconsumed_size > 0) {
  58. // Move unconsumed data to the start of buffer.
  59. memmove(StartOfBuffer(), StartOfBuffer() + bytes, unconsumed_size);
  60. }
  61. base_->set_offset(unconsumed_size);
  62. data_ = base_->data();
  63. // If capacity is too big, reduce it.
  64. if (GetCapacity() > kMinimumBufSize &&
  65. GetCapacity() > previous_size * kCapacityIncreaseFactor) {
  66. int new_capacity = GetCapacity() / kCapacityIncreaseFactor;
  67. if (new_capacity < kMinimumBufSize)
  68. new_capacity = kMinimumBufSize;
  69. // this avoids the pointer to dangle until `SetCapacity` gets called.
  70. data_ = nullptr;
  71. // realloc() within GrowableIOBuffer::SetCapacity() could move data even
  72. // when size is reduced. If unconsumed_size == 0, i.e. no data exists in
  73. // the buffer, free internal buffer first to guarantee no data move.
  74. if (!unconsumed_size)
  75. base_->SetCapacity(0);
  76. SetCapacity(new_capacity);
  77. }
  78. }
  79. HttpConnection::QueuedWriteIOBuffer::QueuedWriteIOBuffer() = default;
  80. HttpConnection::QueuedWriteIOBuffer::~QueuedWriteIOBuffer() {
  81. data_ = nullptr; // pending_data_ owns data_.
  82. }
  83. bool HttpConnection::QueuedWriteIOBuffer::IsEmpty() const {
  84. return pending_data_.empty();
  85. }
  86. bool HttpConnection::QueuedWriteIOBuffer::Append(const std::string& data) {
  87. if (data.empty())
  88. return true;
  89. if (total_size_ + static_cast<int>(data.size()) > max_buffer_size_) {
  90. LOG(ERROR) << "Too large write data is pending: size="
  91. << total_size_ + data.size()
  92. << ", max_buffer_size=" << max_buffer_size_;
  93. return false;
  94. }
  95. pending_data_.push(std::make_unique<std::string>(data));
  96. total_size_ += data.size();
  97. // If new data is the first pending data, updates data_.
  98. if (pending_data_.size() == 1)
  99. data_ = const_cast<char*>(pending_data_.front()->data());
  100. return true;
  101. }
  102. void HttpConnection::QueuedWriteIOBuffer::DidConsume(int size) {
  103. DCHECK_GE(total_size_, size);
  104. DCHECK_GE(GetSizeToWrite(), size);
  105. if (size == 0)
  106. return;
  107. if (size < GetSizeToWrite()) {
  108. data_ += size;
  109. } else { // size == GetSizeToWrite(). Updates data_ to next pending data.
  110. data_ = nullptr;
  111. pending_data_.pop();
  112. data_ =
  113. IsEmpty() ? nullptr : const_cast<char*>(pending_data_.front()->data());
  114. }
  115. total_size_ -= size;
  116. }
  117. int HttpConnection::QueuedWriteIOBuffer::GetSizeToWrite() const {
  118. if (IsEmpty()) {
  119. DCHECK_EQ(0, total_size_);
  120. return 0;
  121. }
  122. DCHECK_GE(data_, pending_data_.front()->data());
  123. int consumed = static_cast<int>(data_ - pending_data_.front()->data());
  124. DCHECK_GT(static_cast<int>(pending_data_.front()->size()), consumed);
  125. return pending_data_.front()->size() - consumed;
  126. }
  127. HttpConnection::HttpConnection(int id, std::unique_ptr<StreamSocket> socket)
  128. : id_(id),
  129. socket_(std::move(socket)),
  130. read_buf_(base::MakeRefCounted<ReadIOBuffer>()),
  131. write_buf_(base::MakeRefCounted<QueuedWriteIOBuffer>()) {}
  132. HttpConnection::~HttpConnection() = default;
  133. void HttpConnection::SetWebSocket(std::unique_ptr<WebSocket> web_socket) {
  134. DCHECK(!web_socket_);
  135. web_socket_ = std::move(web_socket);
  136. }
  137. } // namespace net