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(
36 StreamListenSocket::Delegate
* del
) {
37 SocketDescriptor s
= CreateAndBind(ip
, port
);
38 if (s
== kInvalidSocket
)
39 return scoped_ptr
<TCPListenSocket
>();
40 scoped_ptr
<TCPListenSocket
> sock(new TCPListenSocket(s
, del
));
45 TCPListenSocket::TCPListenSocket(SocketDescriptor s
,
46 StreamListenSocket::Delegate
* del
)
47 : StreamListenSocket(s
, del
) {
50 TCPListenSocket::~TCPListenSocket() {}
52 SocketDescriptor
TCPListenSocket::CreateAndBind(const string
& ip
, uint16 port
) {
53 SocketDescriptor s
= CreatePlatformSocket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
54 if (s
!= kInvalidSocket
) {
57 static const int kOn
= 1;
58 setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
, &kOn
, sizeof(kOn
));
61 memset(&addr
, 0, sizeof(addr
));
62 addr
.sin_family
= AF_INET
;
63 addr
.sin_addr
.s_addr
= inet_addr(ip
.c_str());
64 addr
.sin_port
= base::HostToNet16(port
);
65 if (bind(s
, reinterpret_cast<sockaddr
*>(&addr
), sizeof(addr
))) {
68 #elif defined(OS_POSIX)
71 LOG(ERROR
) << "Could not bind socket to " << ip
<< ":" << port
;
78 SocketDescriptor
TCPListenSocket::CreateAndBindAnyPort(const string
& ip
,
80 SocketDescriptor s
= CreateAndBind(ip
, 0);
81 if (s
== kInvalidSocket
)
82 return kInvalidSocket
;
84 socklen_t addr_size
= sizeof(addr
);
85 bool failed
= getsockname(s
, reinterpret_cast<struct sockaddr
*>(&addr
),
87 if (addr_size
!= sizeof(addr
))
90 LOG(ERROR
) << "Could not determine bound port, getsockname() failed";
93 #elif defined(OS_POSIX)
96 return kInvalidSocket
;
98 *port
= base::NetToHost16(addr
.sin_port
);
102 void TCPListenSocket::Accept() {
103 SocketDescriptor conn
= AcceptSocket();
104 if (conn
== kInvalidSocket
)
106 scoped_ptr
<TCPListenSocket
> sock(
107 new TCPListenSocket(conn
, socket_delegate_
));
108 // It's up to the delegate to AddRef if it wants to keep it around.
109 #if defined(OS_POSIX)
110 sock
->WatchSocket(WAITING_READ
);
112 socket_delegate_
->DidAccept(this, sock
.Pass());