Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(563)

Unified Diff: net/base/tcp_listen_socket.cc

Issue 10161005: Add DefaultListenSocket. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix build on Windows Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/base/tcp_listen_socket.h ('k') | net/base/tcp_listen_socket_unittest.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/tcp_listen_socket.cc
diff --git a/net/base/tcp_listen_socket.cc b/net/base/tcp_listen_socket.cc
index 4b4dbd3553ec50af9fcc8fba45290afd2cfb908a..c34a9191bf29614c6378d94f26b07122fd54850b 100644
--- a/net/base/tcp_listen_socket.cc
+++ b/net/base/tcp_listen_socket.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "build/build_config.h"
+#include "net/base/tcp_listen_socket.h"
#if defined(OS_WIN)
// winsock2.h must be included first in order to ensure it is included before
@@ -17,117 +17,35 @@
#include "net/base/net_errors.h"
#endif
-#include "base/bind.h"
-#include "base/eintr_wrapper.h"
+#include "base/logging.h"
#include "base/sys_byteorder.h"
#include "base/threading/platform_thread.h"
+#include "build/build_config.h"
#include "net/base/net_util.h"
-#include "net/base/tcp_listen_socket.h"
-
-#if defined(OS_WIN)
-typedef int socklen_t;
#include "net/base/winsock_init.h"
-#endif // defined(OS_WIN)
-
-namespace net {
-
-namespace {
-
-const int kReadBufSize = 4096;
-const int kMaxSendBufSize = 1024 * 1024 * 5; // 5MB
-
-const net::BackoffEntry::Policy kSendBackoffPolicy = {
- // Number of initial errors (in sequence) to ignore before applying
- // exponential back-off rules.
- 0,
-
- // Initial delay for exponential back-off in ms.
- 25,
-
- // Factor by which the waiting time will be multiplied.
- 2,
-
- // Fuzzing percentage. ex: 10% will spread requests randomly
- // between 90%-100% of the calculated time.
- 0,
-
- // Maximum amount of time we are willing to delay our request in ms.
- 100,
- // Time to keep an entry from being discarded even when it
- // has no significant state, -1 to never discard.
- -1,
+using std::string;
- // Don't use initial delay unless the last request was an error.
- false,
-};
-
-} // namespace
-
-#if defined(OS_WIN)
-const SOCKET TCPListenSocket::kInvalidSocket = INVALID_SOCKET;
-const int TCPListenSocket::kSocketError = SOCKET_ERROR;
-#elif defined(OS_POSIX)
-const SOCKET TCPListenSocket::kInvalidSocket = -1;
-const int TCPListenSocket::kSocketError = -1;
-#endif
+namespace net {
-TCPListenSocket* TCPListenSocket::CreateAndListen(
- const std::string& ip, int port, ListenSocket::ListenSocketDelegate *del) {
+// static
+scoped_refptr<TCPListenSocket> TCPListenSocket::CreateAndListen(
+ const string& ip, int port, StreamListenSocket::Delegate* del) {
SOCKET s = CreateAndBind(ip, port);
- if (s == kInvalidSocket) {
- // TODO(erikkay): error handling
- } else {
- TCPListenSocket* sock = new TCPListenSocket(s, del);
- sock->Listen();
- return sock;
- }
- return NULL;
+ if (s == kInvalidSocket)
+ return NULL;
+ scoped_refptr<TCPListenSocket> sock(new TCPListenSocket(s, del));
+ sock->Listen();
+ return sock;
}
-void TCPListenSocket::PauseReads() {
- DCHECK(!reads_paused_);
- reads_paused_ = true;
-}
-
-void TCPListenSocket::ResumeReads() {
- DCHECK(reads_paused_);
- reads_paused_ = false;
- if (has_pending_reads_) {
- has_pending_reads_ = false;
- Read();
- }
-}
-
-TCPListenSocket::TCPListenSocket(SOCKET s,
- ListenSocket::ListenSocketDelegate *del)
- : ListenSocket(del),
- socket_(s),
- reads_paused_(false),
- has_pending_reads_(false),
- send_pending_size_(0),
- send_error_(false),
- send_backoff_(&kSendBackoffPolicy) {
-#if defined(OS_WIN)
- socket_event_ = WSACreateEvent();
- // TODO(ibrar): error handling in case of socket_event_ == WSA_INVALID_EVENT
- WatchSocket(NOT_WAITING);
-#elif defined(OS_POSIX)
- wait_state_ = NOT_WAITING;
-#endif
+TCPListenSocket::TCPListenSocket(SOCKET s, StreamListenSocket::Delegate* del)
+ : StreamListenSocket(s, del) {
}
-TCPListenSocket::~TCPListenSocket() {
-#if defined(OS_WIN)
- if (socket_event_) {
- WSACloseEvent(socket_event_);
- socket_event_ = WSA_INVALID_EVENT;
- }
-#endif
- CloseSocket(socket_);
-}
+TCPListenSocket::~TCPListenSocket() {}
-SOCKET TCPListenSocket::CreateAndBind(const std::string& ip, int port) {
+SOCKET TCPListenSocket::CreateAndBind(const string& ip, int port) {
#if defined(OS_WIN)
EnsureWinsockInit();
#endif
@@ -150,263 +68,24 @@ SOCKET TCPListenSocket::CreateAndBind(const std::string& ip, int port) {
#elif defined(OS_POSIX)
close(s);
#endif
+ LOG(ERROR) << "Could not bind socket to " << ip << ":" << port;
s = kInvalidSocket;
}
}
return s;
}
-SOCKET TCPListenSocket::Accept(SOCKET s) {
- sockaddr_in from;
- socklen_t from_len = sizeof(from);
- SOCKET conn =
- HANDLE_EINTR(accept(s, reinterpret_cast<sockaddr*>(&from), &from_len));
- if (conn != kInvalidSocket) {
- SetNonBlocking(conn);
- }
- return conn;
-}
-
-void TCPListenSocket::SendInternal(const char* bytes, int len) {
- DCHECK(bytes);
- if (!bytes || len <= 0)
- return;
-
- if (send_error_)
- return;
-
- if (send_pending_size_ + len > kMaxSendBufSize) {
- LOG(ERROR) << "send failed: buffer overrun";
- send_buffers_.clear();
- send_pending_size_ = 0;
- send_error_ = true;
- return;
- }
-
- scoped_refptr<IOBuffer> buffer(new IOBuffer(len));
- memcpy(buffer->data(), bytes, len);
- send_buffers_.push_back(new DrainableIOBuffer(buffer, len));
- send_pending_size_ += len;
-
- if (!send_timer_.IsRunning())
- SendData();
-}
-
-void TCPListenSocket::Listen() {
- int backlog = 10; // TODO(erikkay): maybe don't allow any backlog?
- listen(socket_, backlog);
- // TODO(erikkay): error handling
-#if defined(OS_POSIX)
- WatchSocket(WAITING_ACCEPT);
-#endif
-}
-
void TCPListenSocket::Accept() {
- SOCKET conn = Accept(socket_);
- if (conn != kInvalidSocket) {
- scoped_refptr<TCPListenSocket> sock(
- new TCPListenSocket(conn, socket_delegate_));
- // it's up to the delegate to AddRef if it wants to keep it around
-#if defined(OS_POSIX)
- sock->WatchSocket(WAITING_READ);
-#endif
- socket_delegate_->DidAccept(this, sock);
- } else {
- // TODO(ibrar): some error handling required here
- }
-}
-
-void TCPListenSocket::Read() {
- char buf[kReadBufSize + 1]; // +1 for null termination
- int len;
- do {
- len = HANDLE_EINTR(recv(socket_, buf, kReadBufSize, 0));
- if (len == kSocketError) {
-#if defined(OS_WIN)
- int err = WSAGetLastError();
- if (err == WSAEWOULDBLOCK) {
-#elif defined(OS_POSIX)
- if (errno == EWOULDBLOCK || errno == EAGAIN) {
-#endif
- break;
- } else {
- // TODO(ibrar): some error handling required here
- break;
- }
- } else if (len == 0) {
- // In Windows, Close() is called by OnObjectSignaled. In POSIX, we need
- // to call it here.
-#if defined(OS_POSIX)
- Close();
-#endif
- } else {
- // TODO(ibrar): maybe change DidRead to take a length instead
- DCHECK_GT(len, 0);
- DCHECK_LE(len, kReadBufSize);
- buf[len] = 0; // already create a buffer with +1 length
- socket_delegate_->DidRead(this, buf, len);
- }
- } while (len == kReadBufSize);
-}
-
-void TCPListenSocket::Close() {
-#if defined(OS_POSIX)
- if (wait_state_ == NOT_WAITING)
- return;
- wait_state_ = NOT_WAITING;
-#endif
- UnwatchSocket();
- socket_delegate_->DidClose(this);
-}
-
-void TCPListenSocket::CloseSocket(SOCKET s) {
- if (s && s != kInvalidSocket) {
- UnwatchSocket();
-#if defined(OS_WIN)
- closesocket(s);
-#elif defined(OS_POSIX)
- close(s);
-#endif
- }
-}
-
-void TCPListenSocket::WatchSocket(WaitState state) {
-#if defined(OS_WIN)
- WSAEventSelect(socket_, socket_event_, FD_ACCEPT | FD_CLOSE | FD_READ);
- watcher_.StartWatching(socket_event_, this);
-#elif defined(OS_POSIX)
- // Implicitly calls StartWatchingFileDescriptor().
- MessageLoopForIO::current()->WatchFileDescriptor(
- socket_, true, MessageLoopForIO::WATCH_READ, &watcher_, this);
- wait_state_ = state;
-#endif
-}
-
-void TCPListenSocket::UnwatchSocket() {
-#if defined(OS_WIN)
- watcher_.StopWatching();
-#elif defined(OS_POSIX)
- watcher_.StopWatchingFileDescriptor();
-#endif
-}
-
-// TODO(ibrar): We can add these functions into OS dependent files
-#if defined(OS_WIN)
-// MessageLoop watcher callback
-void TCPListenSocket::OnObjectSignaled(HANDLE object) {
- WSANETWORKEVENTS ev;
- if (kSocketError == WSAEnumNetworkEvents(socket_, socket_event_, &ev)) {
- // TODO
- return;
- }
-
- // The object was reset by WSAEnumNetworkEvents. Watch for the next signal.
- watcher_.StartWatching(object, this);
-
- if (ev.lNetworkEvents == 0) {
- // Occasionally the event is set even though there is no new data.
- // The net seems to think that this is ignorable.
+ SOCKET conn = AcceptSocket();
+ if (conn == kInvalidSocket)
return;
- }
- if (ev.lNetworkEvents & FD_ACCEPT) {
- Accept();
- }
- if (ev.lNetworkEvents & FD_READ) {
- if (reads_paused_) {
- has_pending_reads_ = true;
- } else {
- Read();
- }
- }
- if (ev.lNetworkEvents & FD_CLOSE) {
- Close();
- }
-}
-#elif defined(OS_POSIX)
-void TCPListenSocket::OnFileCanReadWithoutBlocking(int fd) {
- switch (wait_state_) {
- case WAITING_ACCEPT:
- Accept();
- break;
- case WAITING_READ:
- if (reads_paused_) {
- has_pending_reads_ = true;
- } else {
- Read();
- }
- break;
- default:
- // Close() is called by Read() in the Linux case.
- NOTREACHED();
- break;
- }
-}
-
-void TCPListenSocket::OnFileCanWriteWithoutBlocking(int fd) {
- // MessagePumpLibevent callback, we don't listen for write events
- // so we shouldn't ever reach here.
- NOTREACHED();
-}
-
-#endif
-
-void TCPListenSocket::SendData() {
- DCHECK(!send_buffers_.empty());
-
- int total_sent = 0;
-
- // Send data until all buffers have been sent or a call would block.
- while (!send_buffers_.empty()) {
- scoped_refptr<DrainableIOBuffer> buffer = send_buffers_.front();
-
- int len_left = buffer->BytesRemaining();
- int sent = HANDLE_EINTR(send(socket_, buffer->data(), len_left, 0));
- if (sent > 0) {
- if (sent == len_left)
- send_buffers_.pop_front();
- else
- buffer->DidConsume(sent);
-
- total_sent += sent;
- } else if (sent == kSocketError) {
-#if defined(OS_WIN)
- if (WSAGetLastError() != WSAEWOULDBLOCK) {
- LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError();
-#elif defined(OS_POSIX)
- if (errno != EWOULDBLOCK && errno != EAGAIN) {
- LOG(ERROR) << "send failed: errno==" << errno;
+ scoped_refptr<TCPListenSocket> sock(
+ new TCPListenSocket(conn, socket_delegate_));
+ // It's up to the delegate to AddRef if it wants to keep it around.
+#if defined(OS_POSIX)
+ sock->WatchSocket(WAITING_READ);
#endif
- // Don't try to re-send data after a socket error.
- send_buffers_.clear();
- send_pending_size_ = 0;
- send_error_ = true;
- return;
- }
-
- // The call would block. Don't send any more data at this time.
- break;
- } else {
- NOTREACHED();
- break;
- }
- }
-
- if (total_sent > 0) {
- send_pending_size_ -= total_sent;
- DCHECK_GE(send_pending_size_, 0);
-
- // Clear the back-off delay.
- send_backoff_.Reset();
- } else {
- // Increase the back-off delay.
- send_backoff_.InformOfRequest(false);
- }
-
- if (!send_buffers_.empty()) {
- DCHECK(!send_timer_.IsRunning());
- send_timer_.Start(FROM_HERE, send_backoff_.GetTimeUntilRelease(),
- this, &TCPListenSocket::SendData);
- }
+ socket_delegate_->DidAccept(this, sock);
}
} // namespace net
« no previous file with comments | « net/base/tcp_listen_socket.h ('k') | net/base/tcp_listen_socket_unittest.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698