summaryrefslogtreecommitdiff
path: root/chromium/net/socket/tcp_listen_socket.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/socket/tcp_listen_socket.cc')
-rw-r--r--chromium/net/socket/tcp_listen_socket.cc128
1 files changed, 128 insertions, 0 deletions
diff --git a/chromium/net/socket/tcp_listen_socket.cc b/chromium/net/socket/tcp_listen_socket.cc
new file mode 100644
index 00000000000..aab2e45d0e9
--- /dev/null
+++ b/chromium/net/socket/tcp_listen_socket.cc
@@ -0,0 +1,128 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/socket/tcp_listen_socket.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 <arpa/inet.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include "net/base/net_errors.h"
+#endif
+
+#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/winsock_init.h"
+
+using std::string;
+
+namespace net {
+
+// static
+scoped_refptr<TCPListenSocket> TCPListenSocket::CreateAndListen(
+ const string& ip, int port, StreamListenSocket::Delegate* del) {
+ SocketDescriptor s = CreateAndBind(ip, port);
+ if (s == kInvalidSocket)
+ return NULL;
+ scoped_refptr<TCPListenSocket> sock(new TCPListenSocket(s, del));
+ sock->Listen();
+ return sock;
+}
+
+TCPListenSocket::TCPListenSocket(SocketDescriptor s,
+ StreamListenSocket::Delegate* del)
+ : StreamListenSocket(s, del) {
+}
+
+TCPListenSocket::~TCPListenSocket() {}
+
+SocketDescriptor TCPListenSocket::CreateAndBind(const string& ip, int port) {
+#if defined(OS_WIN)
+ EnsureWinsockInit();
+#endif
+
+ SocketDescriptor 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
+ LOG(ERROR) << "Could not bind socket to " << ip << ":" << port;
+ s = kInvalidSocket;
+ }
+ }
+ return s;
+}
+
+SocketDescriptor TCPListenSocket::CreateAndBindAnyPort(const string& ip,
+ int* port) {
+ SocketDescriptor s = CreateAndBind(ip, 0);
+ if (s == kInvalidSocket)
+ return kInvalidSocket;
+ sockaddr_in addr;
+ socklen_t addr_size = sizeof(addr);
+ bool failed = getsockname(s, reinterpret_cast<struct sockaddr*>(&addr),
+ &addr_size) != 0;
+ if (addr_size != sizeof(addr))
+ failed = true;
+ if (failed) {
+ LOG(ERROR) << "Could not determine bound port, getsockname() failed";
+#if defined(OS_WIN)
+ closesocket(s);
+#elif defined(OS_POSIX)
+ close(s);
+#endif
+ return kInvalidSocket;
+ }
+ *port = base::NetToHost16(addr.sin_port);
+ return s;
+}
+
+void TCPListenSocket::Accept() {
+ SocketDescriptor conn = AcceptSocket();
+ if (conn == kInvalidSocket)
+ return;
+ 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.get());
+}
+
+TCPListenSocketFactory::TCPListenSocketFactory(const string& ip, int port)
+ : ip_(ip),
+ port_(port) {
+}
+
+TCPListenSocketFactory::~TCPListenSocketFactory() {}
+
+scoped_refptr<StreamListenSocket> TCPListenSocketFactory::CreateAndListen(
+ StreamListenSocket::Delegate* delegate) const {
+ return TCPListenSocket::CreateAndListen(ip_, port_, delegate);
+}
+
+} // namespace net