15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/tcp_server_socket_win.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mstcpip.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/ip_endpoint.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/winsock_init.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/winsock_util.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/socket_net_log_params.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/tcp_client_socket.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TCPServerSocketWin::TCPServerSocketWin(net::NetLog* net_log, 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::NetLog::Source& source) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : socket_(INVALID_SOCKET), 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_event_(WSA_INVALID_EVENT), 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_socket_(NULL), 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source.ToEventParametersCallback()); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnsureWinsockInit(); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TCPServerSocketWin::~TCPServerSocketWin() { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPServerSocketWin::Listen(const IPEndPoint& address, int backlog) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(backlog, 0); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(socket_, INVALID_SOCKET); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(socket_event_, WSA_INVALID_EVENT); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_event_ = WSACreateEvent(); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_event_ == WSA_INVALID_EVENT) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "WSACreateEvent()"; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_FAILED; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) socket_ = socket(address.GetSockAddrFamily(), SOCK_STREAM, IPPROTO_TCP); 48f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch if (socket_ == INVALID_SOCKET) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "socket() returned an error"; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSystemError(WSAGetLastError()); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SetNonBlocking(socket_)) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = MapSystemError(WSAGetLastError()); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = SetSocketOptions(); 607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (result != OK) { 617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Close(); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!address.ToSockAddr(storage.addr, &storage.addr_len)) { 677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Close(); 687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return ERR_ADDRESS_INVALID; 697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = bind(socket_, storage.addr, storage.addr_len); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "bind() returned an error"; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = MapSystemError(WSAGetLastError()); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = listen(socket_, backlog); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "listen() returned an error"; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = MapSystemError(WSAGetLastError()); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPServerSocketWin::GetLocalAddress(IPEndPoint* address) const { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(address); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (getsockname(socket_, storage.addr, &storage.addr_len)) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSystemError(WSAGetLastError()); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!address->FromSockAddr(storage.addr, storage.addr_len)) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_FAILED; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPServerSocketWin::Accept( 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<StreamSocket>* socket, const CompletionCallback& callback) { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(socket); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(accept_callback_.is_null()); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = AcceptInternal(socket); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == ERR_IO_PENDING) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start watching 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WSAEventSelect(socket_, socket_event_, FD_ACCEPT); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_watcher_.StartWatching(socket_event_, this); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_socket_ = socket; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_callback_ = callback; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPServerSocketWin::SetSocketOptions() { 1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // On Windows, a bound end point can be hijacked by another process by 1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // setting SO_REUSEADDR. Therefore a Windows-only option SO_EXCLUSIVEADDRUSE 1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // was introduced in Windows NT 4.0 SP4. If the socket that is bound to the 1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // end point has SO_EXCLUSIVEADDRUSE enabled, it is not possible for another 1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // socket to forcibly bind to the end point until the end point is unbound. 1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // It is recommend that all server applications must use SO_EXCLUSIVEADDRUSE. 1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // MSDN: http://goo.gl/M6fjQ. 1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // 1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Unlike on *nix, on Windows a TCP server socket can always bind to an end 1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // point in TIME_WAIT state without setting SO_REUSEADDR, therefore it is not 1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // needed here. 1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // 1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // SO_EXCLUSIVEADDRUSE will prevent a TCP client socket from binding to an end 1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // point in TIME_WAIT status. It does not have this effect for a TCP server 1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // socket. 1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL true_value = 1; 1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int rv = setsockopt(socket_, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch reinterpret_cast<const char*>(&true_value), 1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sizeof(true_value)); 1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (rv < 0) 1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return MapSystemError(errno); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPServerSocketWin::AcceptInternal(scoped_ptr<StreamSocket>* socket) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int new_socket = accept(socket_, storage.addr, &storage.addr_len); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_socket < 0) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int net_error = MapSystemError(WSAGetLastError()); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net_error != ERR_IO_PENDING) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net_error; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPEndPoint address; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!address.FromSockAddr(storage.addr, storage.addr_len)) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (closesocket(new_socket) < 0) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "closesocket"; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, ERR_FAILED); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_FAILED; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<TCPClientSocket> tcp_socket(new TCPClientSocket( 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddressList(address), 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.net_log(), net_log_.source())); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int adopt_result = tcp_socket->AdoptSocket(new_socket); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (adopt_result != OK) { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (closesocket(new_socket) < 0) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "closesocket"; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, adopt_result); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return adopt_result; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket->reset(tcp_socket.release()); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT, 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateNetLogIPEndPointCallback(&address)); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPServerSocketWin::Close() { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_ != INVALID_SOCKET) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (closesocket(socket_) < 0) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "closesocket"; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_ = INVALID_SOCKET; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_event_) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WSACloseEvent(socket_event_); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_event_ = WSA_INVALID_EVENT; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPServerSocketWin::OnObjectSignaled(HANDLE object) { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WSANETWORKEVENTS ev; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (WSAEnumNetworkEvents(socket_, socket_event_, &ev) == SOCKET_ERROR) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "WSAEnumNetworkEvents()"; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ev.lNetworkEvents & FD_ACCEPT) { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = AcceptInternal(accept_socket_); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != ERR_IO_PENDING) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_socket_ = NULL; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompletionCallback callback = accept_callback_; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_callback_.Reset(); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(result); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 218