blob: eb15ffbdaf9bb691a57642e77e4b9fa46a357f86 [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]38712522011-04-18 23:03:3224 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {
[email protected]3aa4af042012-06-14 21:02:3125 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
26 source.ToEventParametersCallback());
[email protected]38712522011-04-18 23:03:3227 EnsureWinsockInit();
28}
29
30TCPServerSocketWin::~TCPServerSocketWin() {
31 Close();
[email protected]3aa4af042012-06-14 21:02:3132 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
[email protected]38712522011-04-18 23:03:3233}
34
35int TCPServerSocketWin::Listen(const IPEndPoint& address, int backlog) {
36 DCHECK(CalledOnValidThread());
37 DCHECK_GT(backlog, 0);
38 DCHECK_EQ(socket_, INVALID_SOCKET);
39 DCHECK_EQ(socket_event_, WSA_INVALID_EVENT);
40
41 socket_event_ = WSACreateEvent();
42 if (socket_event_ == WSA_INVALID_EVENT) {
43 PLOG(ERROR) << "WSACreateEvent()";
44 return ERR_FAILED;
45 }
46
[email protected]03ec25382011-05-27 21:50:2847 socket_ = socket(address.GetFamily(), SOCK_STREAM, IPPROTO_TCP);
[email protected]38712522011-04-18 23:03:3248 if (socket_ < 0) {
49 PLOG(ERROR) << "socket() returned an error";
50 return MapSystemError(WSAGetLastError());
51 }
52
53 if (SetNonBlocking(socket_)) {
54 int result = MapSystemError(WSAGetLastError());
55 Close();
56 return result;
57 }
58
[email protected]7054e78f2012-05-07 21:44:5659 SockaddrStorage storage;
60 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
[email protected]38712522011-04-18 23:03:3261 return ERR_INVALID_ARGUMENT;
62
[email protected]7054e78f2012-05-07 21:44:5663 int result = bind(socket_, storage.addr, storage.addr_len);
[email protected]38712522011-04-18 23:03:3264 if (result < 0) {
65 PLOG(ERROR) << "bind() returned an error";
66 result = MapSystemError(WSAGetLastError());
67 Close();
68 return result;
69 }
70
71 result = listen(socket_, backlog);
72 if (result < 0) {
73 PLOG(ERROR) << "listen() returned an error";
74 result = MapSystemError(WSAGetLastError());
75 Close();
76 return result;
77 }
78
79 return OK;
80}
81
82int TCPServerSocketWin::GetLocalAddress(IPEndPoint* address) const {
83 DCHECK(CalledOnValidThread());
84 DCHECK(address);
85
[email protected]7054e78f2012-05-07 21:44:5686 SockaddrStorage storage;
87 if (getsockname(socket_, storage.addr, &storage.addr_len))
[email protected]38712522011-04-18 23:03:3288 return MapSystemError(WSAGetLastError());
[email protected]7054e78f2012-05-07 21:44:5689 if (!address->FromSockAddr(storage.addr, storage.addr_len))
[email protected]38712522011-04-18 23:03:3290 return ERR_FAILED;
91
92 return OK;
93}
94
95int TCPServerSocketWin::Accept(
[email protected]df7a30d2011-12-03 04:16:5096 scoped_ptr<StreamSocket>* socket, const CompletionCallback& callback) {
[email protected]38712522011-04-18 23:03:3297 DCHECK(CalledOnValidThread());
98 DCHECK(socket);
[email protected]df7a30d2011-12-03 04:16:5099 DCHECK(!callback.is_null());
100 DCHECK(accept_callback_.is_null());
[email protected]38712522011-04-18 23:03:32101
[email protected]3aa4af042012-06-14 21:02:31102 net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT);
[email protected]38712522011-04-18 23:03:32103
104 int result = AcceptInternal(socket);
105
106 if (result == ERR_IO_PENDING) {
107 // Start watching
108 WSAEventSelect(socket_, socket_event_, FD_ACCEPT);
109 accept_watcher_.StartWatching(socket_event_, this);
110
111 accept_socket_ = socket;
112 accept_callback_ = callback;
113 }
114
115 return result;
116}
117
[email protected]3268023f2011-05-05 00:08:10118int TCPServerSocketWin::AcceptInternal(scoped_ptr<StreamSocket>* socket) {
[email protected]7054e78f2012-05-07 21:44:56119 SockaddrStorage storage;
120 int new_socket = accept(socket_, storage.addr, &storage.addr_len);
[email protected]03ec25382011-05-27 21:50:28121 if (new_socket < 0) {
[email protected]38712522011-04-18 23:03:32122 int net_error = MapSystemError(WSAGetLastError());
123 if (net_error != ERR_IO_PENDING)
124 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error);
125 return net_error;
126 }
127
128 IPEndPoint address;
[email protected]7054e78f2012-05-07 21:44:56129 if (!address.FromSockAddr(storage.addr, storage.addr_len)) {
[email protected]38712522011-04-18 23:03:32130 NOTREACHED();
[email protected]03ec25382011-05-27 21:50:28131 if (closesocket(new_socket) < 0)
[email protected]a75c7452011-04-18 23:19:38132 PLOG(ERROR) << "closesocket";
[email protected]38712522011-04-18 23:03:32133 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, ERR_FAILED);
134 return ERR_FAILED;
135 }
[email protected]03ec25382011-05-27 21:50:28136 scoped_ptr<TCPClientSocket> tcp_socket(new TCPClientSocket(
[email protected]7054e78f2012-05-07 21:44:56137 AddressList(address),
[email protected]03ec25382011-05-27 21:50:28138 net_log_.net_log(), net_log_.source()));
139 int adopt_result = tcp_socket->AdoptSocket(new_socket);
140 if (adopt_result != OK) {
141 if (closesocket(new_socket) < 0)
142 PLOG(ERROR) << "closesocket";
143 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, adopt_result);
144 return adopt_result;
145 }
146 socket->reset(tcp_socket.release());
[email protected]38712522011-04-18 23:03:32147 net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT,
[email protected]3aa4af042012-06-14 21:02:31148 CreateNetLogIPEndPointCallback(&address));
[email protected]38712522011-04-18 23:03:32149 return OK;
150}
151
152void TCPServerSocketWin::Close() {
153 if (socket_ != INVALID_SOCKET) {
[email protected]a75c7452011-04-18 23:19:38154 if (closesocket(socket_) < 0)
155 PLOG(ERROR) << "closesocket";
[email protected]38712522011-04-18 23:03:32156 socket_ = INVALID_SOCKET;
157 }
158
159 if (socket_event_) {
160 WSACloseEvent(socket_event_);
161 socket_event_ = WSA_INVALID_EVENT;
162 }
163}
164
165void TCPServerSocketWin::OnObjectSignaled(HANDLE object) {
166 WSANETWORKEVENTS ev;
167 if (WSAEnumNetworkEvents(socket_, socket_event_, &ev) == SOCKET_ERROR) {
168 PLOG(ERROR) << "WSAEnumNetworkEvents()";
169 return;
170 }
171
172 if (ev.lNetworkEvents & FD_ACCEPT) {
173 int result = AcceptInternal(accept_socket_);
174 if (result != ERR_IO_PENDING) {
[email protected]38712522011-04-18 23:03:32175 accept_socket_ = NULL;
[email protected]e7560222012-03-31 00:35:38176 CompletionCallback callback = accept_callback_;
[email protected]df7a30d2011-12-03 04:16:50177 accept_callback_.Reset();
[email protected]e7560222012-03-31 00:35:38178 callback.Run(result);
[email protected]38712522011-04-18 23:03:32179 }
180 }
181}
182
183} // namespace net