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

Unified Diff: net/base/listen_socket.cc

Issue 6577: Porting of listen_socket, telnet_server to linux (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 12 years, 2 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
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

Powered by Google App Engine
This is Rietveld 408576698