| Index: net/base/listen_socket.cc
|
| ===================================================================
|
| --- net/base/listen_socket.cc (revision 3911)
|
| +++ net/base/listen_socket.cc (working copy)
|
| @@ -2,29 +2,56 @@
|
| // 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"
|
| +
|
| +#if defined(OS_WIN)
|
| // winsock2.h must be included first in order to ensure it is included before
|
| // windows.h.
|
| #include <winsock2.h>
|
| +#elif defined(OS_POSIX)
|
| +#include <errno.h>
|
| +#include <sys/socket.h>
|
| +#include <arpa/inet.h>
|
| +#include "base/message_loop.h"
|
| +#include "net/base/net_errors.h"
|
| +#include "third_party/libevent/event.h"
|
| +#endif
|
|
|
| +#include "net/base/net_util.h"
|
| #include "net/base/listen_socket.h"
|
|
|
| -#define READ_BUF_SIZE 200
|
| +#if defined(OS_WIN)
|
| +#define socklen_t int
|
| +#elif defined(OS_POSIX)
|
| +const int INVALID_SOCKET = -1; // Used same name as in Windows to avoid #ifdef
|
| +const int SOCKET_ERROR = -1;
|
| +#endif
|
|
|
| +const int kReadBufSize = 200;
|
| +
|
| ListenSocket::ListenSocket(SOCKET s, ListenSocketDelegate *del)
|
| +#if defined(OS_WIN)
|
| : socket_(s),
|
| +#elif defined(OS_POSIX)
|
| + : event_(new event),
|
| + socket_(s),
|
| +#endif
|
| socket_delegate_(del) {
|
| +#if defined(OS_WIN)
|
| socket_event_ = WSACreateEvent();
|
| - WSAEventSelect(socket_, socket_event_, FD_ACCEPT | FD_CLOSE | FD_READ);
|
| - watcher_.StartWatching(socket_event_, this);
|
| + // TODO(ibrar): error handling in case of socket_event_ == WSA_INVALID_EVENT
|
| + WatchSocket(NOT_WAITING);
|
| +#endif
|
| }
|
|
|
| ListenSocket::~ListenSocket() {
|
| +#if defined(OS_WIN)
|
| if (socket_event_) {
|
| - watcher_.StopWatching();
|
| WSACloseEvent(socket_event_);
|
| + socket_event_ = WSA_INVALID_EVENT;
|
| }
|
| - if (socket_)
|
| - closesocket(socket_);
|
| +#endif
|
| + CloseSocket(socket_);
|
| }
|
|
|
| SOCKET ListenSocket::Listen(std::string ip, int port) {
|
| @@ -34,9 +61,12 @@
|
| addr.sin_family = AF_INET;
|
| addr.sin_addr.s_addr = inet_addr(ip.c_str());
|
| addr.sin_port = htons(port);
|
| - if (bind(s, reinterpret_cast<SOCKADDR*>(&addr), sizeof(addr))) {
|
| + if (bind(s, reinterpret_cast<sockaddr*>(&addr), sizeof(addr))) {
|
| +#if defined(OS_WIN)
|
| closesocket(s);
|
| - s = INVALID_SOCKET;
|
| +#elif defined(OS_POSIX)
|
| + close(s);
|
| +#endif
|
| }
|
| }
|
| return s;
|
| @@ -58,61 +88,133 @@
|
| void ListenSocket::Listen() {
|
| int backlog = 10; // TODO(erikkay): maybe don't allow any backlog?
|
| listen(socket_, backlog);
|
| - // TODO(erikkay): handle error
|
| + // TODO(erikkay): error handling
|
| +#if defined(OS_POSIX)
|
| + WatchSocket(WAITING_ACCEPT);
|
| +#endif
|
| }
|
|
|
| SOCKET ListenSocket::Accept(SOCKET s) {
|
| sockaddr_in from;
|
| - int from_len = sizeof(from);
|
| - SOCKET conn = accept(s, reinterpret_cast<SOCKADDR*>(&from), &from_len);
|
| + socklen_t from_len = sizeof(from);
|
| + SOCKET conn = accept(s, reinterpret_cast<sockaddr*>(&from), &from_len);
|
| if (conn != INVALID_SOCKET) {
|
| - // a non-blocking socket
|
| - unsigned long no_block = 1;
|
| - ioctlsocket(conn, FIONBIO, &no_block);
|
| + net::SetNonBlocking(conn);
|
| }
|
| return conn;
|
| }
|
|
|
| void ListenSocket::Accept() {
|
| SOCKET conn = Accept(socket_);
|
| - if (conn == INVALID_SOCKET) {
|
| - // TODO
|
| - } else {
|
| + if (conn != INVALID_SOCKET) {
|
| scoped_refptr<ListenSocket> sock =
|
| new ListenSocket(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 ListenSocket::Read() {
|
| - char buf[READ_BUF_SIZE+1];
|
| + char buf[kReadBufSize + 1]; // +1 for null termination
|
| int len;
|
| do {
|
| - len = recv(socket_, buf, READ_BUF_SIZE, 0);
|
| + len = recv(socket_, buf, kReadBufSize, 0);
|
| if (len == SOCKET_ERROR) {
|
| +#if defined(OS_WIN)
|
| int err = WSAGetLastError();
|
| if (err == WSAEWOULDBLOCK) {
|
| +#elif defined(OS_POSIX)
|
| + if (errno == EWOULDBLOCK || errno == EAGAIN) {
|
| +#endif
|
| break;
|
| } else {
|
| - // TODO - error
|
| + // TODO(ibrar): some error handling required here
|
| break;
|
| }
|
| } else if (len == 0) {
|
| - // socket closed, ignore
|
| - } else {
|
| - // TODO(erikkay): maybe change DidRead to take a length instead
|
| - DCHECK(len > 0 && len <= READ_BUF_SIZE);
|
| - buf[len] = 0;
|
| + // socket closed ignore in case of window only
|
| +#if defined(OS_POSIX)
|
| + wait_state_ = WAITING_CLOSE;
|
| +#endif
|
| + } else {
|
| + // TODO(ibrar): maybe change DidRead to take a length instead
|
| + DCHECK(len > 0 && len <= kReadBufSize);
|
| + buf[len] = 0; // already create a buffer with +1 length
|
| socket_delegate_->DidRead(this, buf);
|
| }
|
| - } while (len == READ_BUF_SIZE);
|
| + } while (len == kReadBufSize);
|
| }
|
| -
|
| +void ListenSocket::CloseSocket(SOCKET s) {
|
| + if (s) {
|
| + UnwatchSocket();
|
| +#if defined(OS_WIN)
|
| + closesocket(s);
|
| +#elif defined(OS_POSIX)
|
| + close(s);
|
| +#endif
|
| + s = INVALID_SOCKET;
|
| + }
|
| +}
|
| void ListenSocket::Close() {
|
| socket_delegate_->DidClose(this);
|
| + CloseSocket(socket_);
|
| }
|
|
|
| +void ListenSocket::UnwatchSocket() {
|
| +#if defined(OS_WIN)
|
| + watcher_.StopWatching();
|
| +#elif defined(OS_POSIX)
|
| + MessageLoopForIO::current()->UnwatchSocket(event_.get());
|
| + wait_state_ = NOT_WAITING;
|
| +#endif
|
| +}
|
| +
|
| +void ListenSocket::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)
|
| + MessageLoopForIO::current()->WatchSocket(
|
| + socket_, EV_READ|EV_PERSIST, event_.get(),this);
|
| + wait_state_ = state;
|
| +#endif
|
| +}
|
| +
|
| +void ListenSocket::SendInternal(const char* bytes, int len) {
|
| + int sent = send(socket_, bytes, len, 0);
|
| + if (sent == SOCKET_ERROR) {
|
| +#if defined(OS_WIN)
|
| + int err = WSAGetLastError();
|
| + if (err == WSAEWOULDBLOCK) {
|
| +#elif defined(OS_POSIX)
|
| + if (errno == EWOULDBLOCK || errno == EAGAIN) {
|
| +#endif
|
| + // TODO (ibrar): there should be logic here to handle this because
|
| + // it is not an error
|
| + }
|
| + } else if (sent != len) {
|
| + LOG(ERROR) << "send failed: ";
|
| + }
|
| +}
|
| +
|
| +void ListenSocket::Send(const char* bytes, int len, bool append_linefeed) {
|
| + SendInternal(bytes, len);
|
| + if (append_linefeed) {
|
| + SendInternal("\r\n", 2);
|
| + }
|
| +}
|
| +
|
| +void ListenSocket::Send(const std::string& str, bool append_linefeed) {
|
| + Send(str.data(), static_cast<int>(str.length()), append_linefeed);
|
| +}
|
| +
|
| +// TODO (ibrar): We can add these functions into OS dependent files
|
| +#if defined(OS_WIN)
|
| // MessageLoop watcher callback
|
| void ListenSocket::OnObjectSignaled(HANDLE object) {
|
| WSANETWORKEVENTS ev;
|
| @@ -139,24 +241,16 @@
|
| Close();
|
| }
|
| }
|
| -
|
| -void ListenSocket::SendInternal(const char* bytes, int len) {
|
| - int sent = send(socket_, bytes, len, 0);
|
| - if (sent == SOCKET_ERROR) {
|
| - // TODO
|
| - } else if (sent != len) {
|
| - // TODO
|
| +#elif defined(OS_POSIX)
|
| +void ListenSocket::OnSocketReady(short flags) {
|
| + if (wait_state_ == WAITING_ACCEPT) {
|
| + Accept();
|
| }
|
| -}
|
| -
|
| -void ListenSocket::Send(const char* bytes, int len, bool append_linefeed) {
|
| - SendInternal(bytes, len);
|
| - if (append_linefeed) {
|
| - SendInternal("\r\n", 2);
|
| + if (wait_state_ == WAITING_READ) {
|
| + Read();
|
| }
|
| + if (wait_state_ == WAITING_CLOSE) {
|
| + Close();
|
| + }
|
| }
|
| -
|
| -void ListenSocket::Send(const std::string& str, bool append_linefeed) {
|
| - Send(str.data(), static_cast<int>(str.length()), append_linefeed);
|
| -}
|
| -
|
| +#endif
|
|
|