Index: webrtc/base/asynctcpsocket.cc |
diff --git a/webrtc/base/asynctcpsocket.cc b/webrtc/base/asynctcpsocket.cc |
index 31dec92367fc1c876e1b1c4fba1c92eb49b8c91f..65ec0f287bbe8f53333bdd33a3cf7cb96bbad610 100644 |
--- a/webrtc/base/asynctcpsocket.cc |
+++ b/webrtc/base/asynctcpsocket.cc |
@@ -12,6 +12,8 @@ |
#include <string.h> |
+#include <algorithm> |
+ |
#include "webrtc/base/byteorder.h" |
#include "webrtc/base/checks.h" |
#include "webrtc/base/common.h" |
@@ -30,6 +32,11 @@ static const size_t kPacketLenSize = sizeof(PacketLength); |
static const size_t kBufSize = kMaxPacketSize + kPacketLenSize; |
+// The input buffer will be resized so that at least kMinimumRecvSize bytes can |
+// be received (but it will not grow above the maximum size passed to the |
+// constructor). |
+static const size_t kMinimumRecvSize = 128; |
+ |
static const int kListenBacklog = 5; |
// Binds and connects |socket| |
@@ -53,12 +60,11 @@ AsyncTCPSocketBase::AsyncTCPSocketBase(AsyncSocket* socket, bool listen, |
size_t max_packet_size) |
: socket_(socket), |
listen_(listen), |
- insize_(max_packet_size), |
- inpos_(0), |
+ max_insize_(max_packet_size), |
max_outsize_(max_packet_size) { |
if (!listen_) { |
// Listening sockets don't send/receive data, so they don't need buffers. |
- inbuf_.reset(new char[insize_]); |
+ inbuf_.EnsureCapacity(kMinimumRecvSize); |
} |
RTC_DCHECK(socket_.get() != NULL); |
@@ -182,7 +188,7 @@ void AsyncTCPSocketBase::OnReadEvent(AsyncSocket* socket) { |
rtc::SocketAddress address; |
rtc::AsyncSocket* new_socket = socket->Accept(&address); |
if (!new_socket) { |
- // TODO: Do something better like forwarding the error |
+ // TODO(stefan): Do something better like forwarding the error |
// to the user. |
LOG(LS_ERROR) << "TCP accept failed with error " << socket_->GetError(); |
return; |
@@ -193,24 +199,44 @@ void AsyncTCPSocketBase::OnReadEvent(AsyncSocket* socket) { |
// Prime a read event in case data is waiting. |
new_socket->SignalReadEvent(new_socket); |
} else { |
- RTC_DCHECK(inbuf_.get()); |
- int len = socket_->Recv(inbuf_.get() + inpos_, insize_ - inpos_); |
- if (len < 0) { |
- // TODO: Do something better like forwarding the error to the user. |
- if (!socket_->IsBlocking()) { |
- LOG(LS_ERROR) << "Recv() returned error: " << socket_->GetError(); |
+ size_t total_recv = 0; |
+ while (true) { |
+ size_t free_size = inbuf_.capacity() - inbuf_.size(); |
+ if (free_size < kMinimumRecvSize && inbuf_.capacity() < max_insize_) { |
+ inbuf_.EnsureCapacity(std::min(max_insize_, inbuf_.capacity() * 2)); |
+ free_size = inbuf_.capacity() - inbuf_.size(); |
+ } |
+ |
+ int len = socket_->Recv(inbuf_.data() + inbuf_.size(), free_size); |
+ if (len < 0) { |
+ // TODO(stefan): Do something better like forwarding the error to the |
+ // user. |
+ if (!socket_->IsBlocking()) { |
+ LOG(LS_ERROR) << "Recv() returned error: " << socket_->GetError(); |
+ } |
+ break; |
+ } |
+ |
+ total_recv += len; |
+ inbuf_.SetSize(inbuf_.size() + len); |
+ if (!len || static_cast<size_t>(len) < free_size) { |
+ break; |
} |
- return; |
} |
- inpos_ += len; |
+ if (!total_recv) { |
+ return; |
+ } |
- ProcessInput(inbuf_.get(), &inpos_); |
+ size_t size = inbuf_.size(); |
+ ProcessInput(inbuf_.data<char>(), &size); |
- if (inpos_ >= insize_) { |
+ if (size > inbuf_.size()) { |
LOG(LS_ERROR) << "input buffer overflow"; |
RTC_NOTREACHED(); |
- inpos_ = 0; |
+ inbuf_.Clear(); |
+ } else { |
+ inbuf_.SetSize(size); |
} |
} |
} |