Chromium Code Reviews| Index: net/base/stream_listen_socket.cc |
| diff --git a/net/base/tcp_listen_socket.cc b/net/base/stream_listen_socket.cc |
| similarity index 61% |
| copy from net/base/tcp_listen_socket.cc |
| copy to net/base/stream_listen_socket.cc |
| index 64638227a0a1e34c1130f43e4df4a1544dba3393..f49156e21edea6ce0356e891f5acce1b4ea6bb14 100644 |
| --- a/net/base/tcp_listen_socket.cc |
| +++ b/net/base/stream_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/stream_listen_socket.h" |
| #if defined(OS_WIN) |
| // winsock2.h must be included first in order to ensure it is included before |
| @@ -17,11 +17,13 @@ |
| #include "net/base/net_errors.h" |
| #endif |
| +#include "build/build_config.h" |
| #include "base/eintr_wrapper.h" |
| #include "base/sys_byteorder.h" |
| #include "base/threading/platform_thread.h" |
| #include "net/base/net_util.h" |
| -#include "net/base/tcp_listen_socket.h" |
| + |
| +using std::string; |
| #if defined(OS_WIN) |
| typedef int socklen_t; |
| @@ -36,56 +38,29 @@ const int kReadBufSize = 4096; |
| } // namespace |
| #if defined(OS_WIN) |
| -const SOCKET TCPListenSocket::kInvalidSocket = INVALID_SOCKET; |
| -const int TCPListenSocket::kSocketError = SOCKET_ERROR; |
| +const SOCKET StreamListenSocket::kInvalidSocket = INVALID_SOCKET; |
| +const int StreamListenSocket::kSocketError = SOCKET_ERROR; |
| #elif defined(OS_POSIX) |
| -const SOCKET TCPListenSocket::kInvalidSocket = -1; |
| -const int TCPListenSocket::kSocketError = -1; |
| +const SOCKET StreamListenSocket::kInvalidSocket = -1; |
| +const int StreamListenSocket::kSocketError = -1; |
| #endif |
| -TCPListenSocket* TCPListenSocket::CreateAndListen( |
| - const std::string& ip, int port, ListenSocket::ListenSocketDelegate *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; |
| -} |
| - |
| -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), |
| +StreamListenSocket::StreamListenSocket(SOCKET s, |
| + StreamListenSocket::Delegate* del) |
| + : socket_delegate_(del), |
| socket_(s), |
| reads_paused_(false), |
| has_pending_reads_(false) { |
| #if defined(OS_WIN) |
| socket_event_ = WSACreateEvent(); |
| - // TODO(ibrar): error handling in case of socket_event_ == WSA_INVALID_EVENT |
| + // 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() { |
| +StreamListenSocket::~StreamListenSocket() { |
| #if defined(OS_WIN) |
| if (socket_event_) { |
| WSACloseEvent(socket_event_); |
| @@ -95,44 +70,28 @@ TCPListenSocket::~TCPListenSocket() { |
| CloseSocket(socket_); |
| } |
| -SOCKET TCPListenSocket::CreateAndBind(const std::string& ip, int port) { |
| - SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); |
| - if (s != kInvalidSocket) { |
| -#if defined(OS_POSIX) |
| - // Allow rapid reuse. |
| - static const int kOn = 1; |
| - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); |
| -#endif |
| - sockaddr_in addr; |
| - memset(&addr, 0, sizeof(addr)); |
| - addr.sin_family = AF_INET; |
| - addr.sin_addr.s_addr = inet_addr(ip.c_str()); |
| - addr.sin_port = base::HostToNet16(port); |
| - if (bind(s, reinterpret_cast<sockaddr*>(&addr), sizeof(addr))) { |
| -#if defined(OS_WIN) |
| - closesocket(s); |
| -#elif defined(OS_POSIX) |
| - close(s); |
| -#endif |
| - s = kInvalidSocket; |
| - } |
| - } |
| - return s; |
| +void StreamListenSocket::Send(const char* bytes, int len, |
| + bool append_linefeed) { |
| + SendInternal(bytes, len); |
| + if (append_linefeed) |
| + SendInternal("\r\n", 2); |
| +} |
| + |
| +void StreamListenSocket::Send(const string& str, bool append_linefeed) { |
| + Send(str.data(), static_cast<int>(str.length()), append_linefeed); |
| } |
| -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) { |
| +SOCKET StreamListenSocket::AcceptSocket() { |
| + SOCKET conn = HANDLE_EINTR(accept(socket_, NULL, NULL)); |
| + if (conn == kInvalidSocket) |
| + LOG(ERROR) << "Error accepting connection."; |
| + else |
| SetNonBlocking(conn); |
| - } |
| return conn; |
| } |
| -void TCPListenSocket::SendInternal(const char* bytes, int len) { |
| - char* send_buf = const_cast<char *>(bytes); |
| +void StreamListenSocket::SendInternal(const char* bytes, int len) { |
| + char* send_buf = const_cast<char*>(bytes); |
| int len_left = len; |
| while (true) { |
| int sent = HANDLE_EINTR(send(socket_, send_buf, len_left, 0)); |
| @@ -150,7 +109,10 @@ void TCPListenSocket::SendInternal(const char* bytes, int len) { |
| break; |
| } |
| // Otherwise we would block, and now we have to wait for a retry. |
| - // Fall through to PlatformThread::YieldCurrentThread() |
| + // Fall through to PlatformThread::YieldCurrentThread(). |
| + } else if (sent == 0) { |
| + // Socket was disconnected. |
| + Close(); |
| } else { |
| // sent != len_left according to the shortcut above. |
| // Shift the buffer start and send the remainder after a short while. |
| @@ -161,32 +123,19 @@ void TCPListenSocket::SendInternal(const char* bytes, int len) { |
| } |
| } |
| -void TCPListenSocket::Listen() { |
| +void StreamListenSocket::Listen() { |
| int backlog = 10; // TODO(erikkay): maybe don't allow any backlog? |
| - listen(socket_, backlog); |
| - // TODO(erikkay): error handling |
| + if (listen(socket_, backlog) == -1) { |
|
mmenke
2012/04/30 19:11:44
nit: Suggest you keep the error handling TODO her
Philippe
2012/05/03 14:27:52
Done.
|
| + LOG(ERROR) << "Could not listen on socket."; |
| + return; |
| + } |
| #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 |
| +void StreamListenSocket::Read() { |
| + char buf[kReadBufSize + 1]; // +1 for null termination. |
| int len; |
| do { |
| len = HANDLE_EINTR(recv(socket_, buf, kReadBufSize, 0)); |
| @@ -199,26 +148,26 @@ void TCPListenSocket::Read() { |
| #endif |
| break; |
| } else { |
| - // TODO(ibrar): some error handling required here |
| + // TODO(ibrar): some error handling required here. |
| break; |
| } |
| } else if (len == 0) { |
| - // In Windows, Close() is called by OnObjectSignaled. In POSIX, we need |
| + // 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 |
| + // 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 |
| + buf[len] = 0; // Already create a buffer with +1 length. |
| socket_delegate_->DidRead(this, buf, len); |
| } |
| } while (len == kReadBufSize); |
| } |
| -void TCPListenSocket::Close() { |
| +void StreamListenSocket::Close() { |
| #if defined(OS_POSIX) |
| if (wait_state_ == NOT_WAITING) |
| return; |
| @@ -228,7 +177,7 @@ void TCPListenSocket::Close() { |
| socket_delegate_->DidClose(this); |
| } |
| -void TCPListenSocket::CloseSocket(SOCKET s) { |
| +void StreamListenSocket::CloseSocket(SOCKET s) { |
| if (s && s != kInvalidSocket) { |
| UnwatchSocket(); |
| #if defined(OS_WIN) |
| @@ -239,7 +188,7 @@ void TCPListenSocket::CloseSocket(SOCKET s) { |
| } |
| } |
| -void TCPListenSocket::WatchSocket(WaitState state) { |
| +void StreamListenSocket::WatchSocket(WaitState state) { |
| #if defined(OS_WIN) |
| WSAEventSelect(socket_, socket_event_, FD_ACCEPT | FD_CLOSE | FD_READ); |
| watcher_.StartWatching(socket_event_, this); |
| @@ -251,7 +200,7 @@ void TCPListenSocket::WatchSocket(WaitState state) { |
| #endif |
| } |
| -void TCPListenSocket::UnwatchSocket() { |
| +void StreamListenSocket::UnwatchSocket() { |
| #if defined(OS_WIN) |
| watcher_.StopWatching(); |
| #elif defined(OS_POSIX) |
| @@ -259,17 +208,17 @@ void TCPListenSocket::UnwatchSocket() { |
| #endif |
| } |
| -// TODO(ibrar): We can add these functions into OS dependent files |
| +// TODO(ibrar): We can add these functions into OS dependent files. |
| #if defined(OS_WIN) |
| -// MessageLoop watcher callback |
| -void TCPListenSocket::OnObjectSignaled(HANDLE object) { |
| +// MessageLoop watcher callback. |
| +void StreamListenSocket::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. |
| + // The object was reset by WSAEnumNetworkEvents. Watch for the next signal. |
| watcher_.StartWatching(object, this); |
| if (ev.lNetworkEvents == 0) { |
| @@ -292,7 +241,7 @@ void TCPListenSocket::OnObjectSignaled(HANDLE object) { |
| } |
| } |
| #elif defined(OS_POSIX) |
| -void TCPListenSocket::OnFileCanReadWithoutBlocking(int fd) { |
| +void StreamListenSocket::OnFileCanReadWithoutBlocking(int fd) { |
| switch (wait_state_) { |
| case WAITING_ACCEPT: |
| Accept(); |
| @@ -311,7 +260,7 @@ void TCPListenSocket::OnFileCanReadWithoutBlocking(int fd) { |
| } |
| } |
| -void TCPListenSocket::OnFileCanWriteWithoutBlocking(int fd) { |
| +void StreamListenSocket::OnFileCanWriteWithoutBlocking(int fd) { |
| // MessagePumpLibevent callback, we don't listen for write events |
| // so we shouldn't ever reach here. |
| NOTREACHED(); |
| @@ -319,4 +268,18 @@ void TCPListenSocket::OnFileCanWriteWithoutBlocking(int fd) { |
| #endif |
| +void StreamListenSocket::PauseReads() { |
| + DCHECK(!reads_paused_); |
| + reads_paused_ = true; |
| +} |
| + |
| +void StreamListenSocket::ResumeReads() { |
| + DCHECK(reads_paused_); |
| + reads_paused_ = false; |
| + if (has_pending_reads_) { |
| + has_pending_reads_ = false; |
| + Read(); |
| + } |
| +} |
| + |
| } // namespace net |