1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/socket/tcp_listen_socket.h"
8 // winsock2.h must be included first in order to ensure it is included before
11 #elif defined(OS_POSIX)
12 #include <arpa/inet.h>
14 #include <netinet/in.h>
15 #include <sys/socket.h>
16 #include <sys/types.h>
17 #include "net/base/net_errors.h"
20 #include "base/logging.h"
21 #include "base/sys_byteorder.h"
22 #include "base/threading/platform_thread.h"
23 #include "build/build_config.h"
24 #include "net/base/net_util.h"
25 #include "net/base/winsock_init.h"
26 #include "net/socket/socket_descriptor.h"
33 scoped_ptr
<TCPListenSocket
> TCPListenSocket::CreateAndListen(
34 const string
& ip
, int port
, StreamListenSocket::Delegate
* del
) {
35 SocketDescriptor s
= CreateAndBind(ip
, port
);
36 if (s
== kInvalidSocket
)
37 return scoped_ptr
<TCPListenSocket
>();
38 scoped_ptr
<TCPListenSocket
> sock(new TCPListenSocket(s
, del
));
43 TCPListenSocket::TCPListenSocket(SocketDescriptor s
,
44 StreamListenSocket::Delegate
* del
)
45 : StreamListenSocket(s
, del
) {
48 TCPListenSocket::~TCPListenSocket() {}
50 SocketDescriptor
TCPListenSocket::CreateAndBind(const string
& ip
, int port
) {
51 SocketDescriptor s
= CreatePlatformSocket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
52 if (s
!= kInvalidSocket
) {
55 static const int kOn
= 1;
56 setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
, &kOn
, sizeof(kOn
));
59 memset(&addr
, 0, sizeof(addr
));
60 addr
.sin_family
= AF_INET
;
61 addr
.sin_addr
.s_addr
= inet_addr(ip
.c_str());
62 addr
.sin_port
= base::HostToNet16(port
);
63 if (bind(s
, reinterpret_cast<sockaddr
*>(&addr
), sizeof(addr
))) {
66 #elif defined(OS_POSIX)
69 LOG(ERROR
) << "Could not bind socket to " << ip
<< ":" << port
;
76 SocketDescriptor
TCPListenSocket::CreateAndBindAnyPort(const string
& ip
,
78 SocketDescriptor s
= CreateAndBind(ip
, 0);
79 if (s
== kInvalidSocket
)
80 return kInvalidSocket
;
82 socklen_t addr_size
= sizeof(addr
);
83 bool failed
= getsockname(s
, reinterpret_cast<struct sockaddr
*>(&addr
),
85 if (addr_size
!= sizeof(addr
))
88 LOG(ERROR
) << "Could not determine bound port, getsockname() failed";
91 #elif defined(OS_POSIX)
94 return kInvalidSocket
;
96 *port
= base::NetToHost16(addr
.sin_port
);
100 void TCPListenSocket::Accept() {
101 SocketDescriptor conn
= AcceptSocket();
102 if (conn
== kInvalidSocket
)
104 scoped_ptr
<TCPListenSocket
> sock(
105 new TCPListenSocket(conn
, socket_delegate_
));
106 // It's up to the delegate to AddRef if it wants to keep it around.
107 #if defined(OS_POSIX)
108 sock
->WatchSocket(WAITING_READ
);
110 socket_delegate_
->DidAccept(this, sock
.PassAs
<StreamListenSocket
>());
113 TCPListenSocketFactory::TCPListenSocketFactory(const string
& ip
, int port
)
118 TCPListenSocketFactory::~TCPListenSocketFactory() {}
120 scoped_ptr
<StreamListenSocket
> TCPListenSocketFactory::CreateAndListen(
121 StreamListenSocket::Delegate
* delegate
) const {
122 return TCPListenSocket::CreateAndListen(ip_
, port_
, delegate
)
123 .PassAs
<StreamListenSocket
>();