blob: c8345060f8ca25f1ac109213bc2f043a22a594c5 [file] [log] [blame]
[email protected]7054e78f2012-05-07 21:44:561// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]38712522011-04-18 23:03:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/socket/tcp_server_socket_win.h"
6
7#include <mstcpip.h>
8
9#include "net/base/ip_endpoint.h"
10#include "net/base/net_errors.h"
11#include "net/base/net_util.h"
12#include "net/base/winsock_init.h"
13#include "net/base/winsock_util.h"
[email protected]3aa4af042012-06-14 21:02:3114#include "net/socket/socket_net_log_params.h"
[email protected]38712522011-04-18 23:03:3215#include "net/socket/tcp_client_socket.h"
16
17namespace net {
18
19TCPServerSocketWin::TCPServerSocketWin(net::NetLog* net_log,
20 const net::NetLog::Source& source)
21 : socket_(INVALID_SOCKET),
22 socket_event_(WSA_INVALID_EVENT),
23 accept_socket_(NULL),
[email protected]68f2a232012-09-17 06:59:4024 reuse_address_(false),
[email protected]38712522011-04-18 23:03:3225 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {
[email protected]3aa4af042012-06-14 21:02:3126 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
27 source.ToEventParametersCallback());
[email protected]38712522011-04-18 23:03:3228 EnsureWinsockInit();
29}
30
31TCPServerSocketWin::~TCPServerSocketWin() {
32 Close();
[email protected]3aa4af042012-06-14 21:02:3133 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
[email protected]38712522011-04-18 23:03:3234}
35
[email protected]68f2a232012-09-17 06:59:4036void TCPServerSocketWin::AllowAddressReuse() {
37 DCHECK(CalledOnValidThread());
38 DCHECK_EQ(socket_, INVALID_SOCKET);
39 DCHECK_EQ(socket_event_, WSA_INVALID_EVENT);
40
41 reuse_address_ = true;
42}
43
[email protected]38712522011-04-18 23:03:3244int TCPServerSocketWin::Listen(const IPEndPoint& address, int backlog) {
45 DCHECK(CalledOnValidThread());
46 DCHECK_GT(backlog, 0);
47 DCHECK_EQ(socket_, INVALID_SOCKET);
48 DCHECK_EQ(socket_event_, WSA_INVALID_EVENT);
49
50 socket_event_ = WSACreateEvent();
51 if (socket_event_ == WSA_INVALID_EVENT) {
52 PLOG(ERROR) << "WSACreateEvent()";
53 return ERR_FAILED;
54 }
55
[email protected]e466aaf2012-12-13 01:46:4456 socket_ = socket(address.GetSockAddrFamily(), SOCK_STREAM, IPPROTO_TCP);
[email protected]38712522011-04-18 23:03:3257 if (socket_ < 0) {
58 PLOG(ERROR) << "socket() returned an error";
59 return MapSystemError(WSAGetLastError());
60 }
61
62 if (SetNonBlocking(socket_)) {
63 int result = MapSystemError(WSAGetLastError());
64 Close();
65 return result;
66 }
67
[email protected]68f2a232012-09-17 06:59:4068 int result = SetSocketOptions();
69 if (result != OK)
70 return result;
71
[email protected]7054e78f2012-05-07 21:44:5672 SockaddrStorage storage;
73 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
[email protected]38712522011-04-18 23:03:3274 return ERR_INVALID_ARGUMENT;
75
[email protected]68f2a232012-09-17 06:59:4076 result = bind(socket_, storage.addr, storage.addr_len);
[email protected]38712522011-04-18 23:03:3277 if (result < 0) {
78 PLOG(ERROR) << "bind() returned an error";
79 result = MapSystemError(WSAGetLastError());
80 Close();
81 return result;
82 }
83
84 result = listen(socket_, backlog);
85 if (result < 0) {
86 PLOG(ERROR) << "listen() returned an error";
87 result = MapSystemError(WSAGetLastError());
88 Close();
89 return result;
90 }
91
92 return OK;
93}
94
95int TCPServerSocketWin::GetLocalAddress(IPEndPoint* address) const {
96 DCHECK(CalledOnValidThread());
97 DCHECK(address);
98
[email protected]7054e78f2012-05-07 21:44:5699 SockaddrStorage storage;
100 if (getsockname(socket_, storage.addr, &storage.addr_len))
[email protected]38712522011-04-18 23:03:32101 return MapSystemError(WSAGetLastError());
[email protected]7054e78f2012-05-07 21:44:56102 if (!address->FromSockAddr(storage.addr, storage.addr_len))
[email protected]38712522011-04-18 23:03:32103 return ERR_FAILED;
104
105 return OK;
106}
107
108int TCPServerSocketWin::Accept(
[email protected]df7a30d2011-12-03 04:16:50109 scoped_ptr<StreamSocket>* socket, const CompletionCallback& callback) {
[email protected]38712522011-04-18 23:03:32110 DCHECK(CalledOnValidThread());
111 DCHECK(socket);
[email protected]df7a30d2011-12-03 04:16:50112 DCHECK(!callback.is_null());
113 DCHECK(accept_callback_.is_null());
[email protected]38712522011-04-18 23:03:32114
[email protected]3aa4af042012-06-14 21:02:31115 net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT);
[email protected]38712522011-04-18 23:03:32116
117 int result = AcceptInternal(socket);
118
119 if (result == ERR_IO_PENDING) {
120 // Start watching
121 WSAEventSelect(socket_, socket_event_, FD_ACCEPT);
122 accept_watcher_.StartWatching(socket_event_, this);
123
124 accept_socket_ = socket;
125 accept_callback_ = callback;
126 }
127
128 return result;
129}
130
[email protected]68f2a232012-09-17 06:59:40131int TCPServerSocketWin::SetSocketOptions() {
132 BOOL true_value = 1;
133 if (reuse_address_) {
134 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
135 reinterpret_cast<const char*>(&true_value),
136 sizeof(true_value));
137 if (rv < 0)
138 return MapSystemError(errno);
139 }
140 return OK;
141}
142
[email protected]3268023f2011-05-05 00:08:10143int TCPServerSocketWin::AcceptInternal(scoped_ptr<StreamSocket>* socket) {
[email protected]7054e78f2012-05-07 21:44:56144 SockaddrStorage storage;
145 int new_socket = accept(socket_, storage.addr, &storage.addr_len);
[email protected]03ec25382011-05-27 21:50:28146 if (new_socket < 0) {
[email protected]38712522011-04-18 23:03:32147 int net_error = MapSystemError(WSAGetLastError());
148 if (net_error != ERR_IO_PENDING)
149 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error);
150 return net_error;
151 }
152
153 IPEndPoint address;
[email protected]7054e78f2012-05-07 21:44:56154 if (!address.FromSockAddr(storage.addr, storage.addr_len)) {
[email protected]38712522011-04-18 23:03:32155 NOTREACHED();
[email protected]03ec25382011-05-27 21:50:28156 if (closesocket(new_socket) < 0)
[email protected]a75c7452011-04-18 23:19:38157 PLOG(ERROR) << "closesocket";
[email protected]38712522011-04-18 23:03:32158 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, ERR_FAILED);
159 return ERR_FAILED;
160 }
[email protected]03ec25382011-05-27 21:50:28161 scoped_ptr<TCPClientSocket> tcp_socket(new TCPClientSocket(
[email protected]7054e78f2012-05-07 21:44:56162 AddressList(address),
[email protected]03ec25382011-05-27 21:50:28163 net_log_.net_log(), net_log_.source()));
164 int adopt_result = tcp_socket->AdoptSocket(new_socket);
165 if (adopt_result != OK) {
166 if (closesocket(new_socket) < 0)
167 PLOG(ERROR) << "closesocket";
168 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, adopt_result);
169 return adopt_result;
170 }
171 socket->reset(tcp_socket.release());
[email protected]38712522011-04-18 23:03:32172 net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT,
[email protected]3aa4af042012-06-14 21:02:31173 CreateNetLogIPEndPointCallback(&address));
[email protected]38712522011-04-18 23:03:32174 return OK;
175}
176
177void TCPServerSocketWin::Close() {
178 if (socket_ != INVALID_SOCKET) {
[email protected]a75c7452011-04-18 23:19:38179 if (closesocket(socket_) < 0)
180 PLOG(ERROR) << "closesocket";
[email protected]38712522011-04-18 23:03:32181 socket_ = INVALID_SOCKET;
182 }
183
184 if (socket_event_) {
185 WSACloseEvent(socket_event_);
186 socket_event_ = WSA_INVALID_EVENT;
187 }
188}
189
190void TCPServerSocketWin::OnObjectSignaled(HANDLE object) {
191 WSANETWORKEVENTS ev;
192 if (WSAEnumNetworkEvents(socket_, socket_event_, &ev) == SOCKET_ERROR) {
193 PLOG(ERROR) << "WSAEnumNetworkEvents()";
194 return;
195 }
196
197 if (ev.lNetworkEvents & FD_ACCEPT) {
198 int result = AcceptInternal(accept_socket_);
199 if (result != ERR_IO_PENDING) {
[email protected]38712522011-04-18 23:03:32200 accept_socket_ = NULL;
[email protected]e7560222012-03-31 00:35:38201 CompletionCallback callback = accept_callback_;
[email protected]df7a30d2011-12-03 04:16:50202 accept_callback_.Reset();
[email protected]e7560222012-03-31 00:35:38203 callback.Run(result);
[email protected]38712522011-04-18 23:03:32204 }
205 }
206}
207
208} // namespace net