blob: 5b1ad659d20ede4a4db31acef22081704ded6cb1 [file] [log] [blame]
[email protected]21160f02013-09-01 23:04:271// Copyright 2013 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.
4
5#include "net/socket/tcp_server_socket.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/logging.h"
[email protected]21160f02013-09-01 23:04:2710#include "net/base/net_errors.h"
11#include "net/socket/tcp_client_socket.h"
12
13namespace net {
14
15TCPServerSocket::TCPServerSocket(NetLog* net_log, const NetLog::Source& source)
16 : socket_(net_log, source),
17 pending_accept_(false) {
18}
19
20TCPServerSocket::~TCPServerSocket() {
21}
22
23int TCPServerSocket::Listen(const IPEndPoint& address, int backlog) {
[email protected]c9080d82013-09-15 15:14:1624 int result = socket_.Open(address.GetFamily());
[email protected]21160f02013-09-01 23:04:2725 if (result != OK)
26 return result;
27
28 result = socket_.SetDefaultOptionsForServer();
29 if (result != OK) {
30 socket_.Close();
31 return result;
32 }
33
34 result = socket_.Bind(address);
35 if (result != OK) {
36 socket_.Close();
37 return result;
38 }
39
40 result = socket_.Listen(backlog);
41 if (result != OK) {
42 socket_.Close();
43 return result;
44 }
45
46 return OK;
47}
48
49int TCPServerSocket::GetLocalAddress(IPEndPoint* address) const {
50 return socket_.GetLocalAddress(address);
51}
52
53int TCPServerSocket::Accept(scoped_ptr<StreamSocket>* socket,
54 const CompletionCallback& callback) {
55 DCHECK(socket);
56 DCHECK(!callback.is_null());
57
58 if (pending_accept_) {
59 NOTREACHED();
60 return ERR_UNEXPECTED;
61 }
62
63 // It is safe to use base::Unretained(this). |socket_| is owned by this class,
64 // and the callback won't be run after |socket_| is destroyed.
65 CompletionCallback accept_callback =
66 base::Bind(&TCPServerSocket::OnAcceptCompleted, base::Unretained(this),
67 socket, callback);
68 int result = socket_.Accept(&accepted_socket_, &accepted_address_,
69 accept_callback);
70 if (result != ERR_IO_PENDING) {
71 // |accept_callback| won't be called so we need to run
72 // ConvertAcceptedSocket() ourselves in order to do the conversion from
73 // |accepted_socket_| to |socket|.
74 result = ConvertAcceptedSocket(result, socket);
75 } else {
76 pending_accept_ = true;
77 }
78
79 return result;
80}
81
svaldez58804c42015-10-06 00:13:4782void TCPServerSocket::DetachFromThread() {
83 socket_.DetachFromThread();
84}
85
[email protected]21160f02013-09-01 23:04:2786int TCPServerSocket::ConvertAcceptedSocket(
87 int result,
88 scoped_ptr<StreamSocket>* output_accepted_socket) {
89 // Make sure the TCPSocket object is destroyed in any case.
90 scoped_ptr<TCPSocket> temp_accepted_socket(accepted_socket_.Pass());
91 if (result != OK)
92 return result;
93
[email protected]659fd67c2013-09-18 21:50:2694 output_accepted_socket->reset(new TCPClientSocket(
[email protected]c9080d82013-09-15 15:14:1695 temp_accepted_socket.Pass(), accepted_address_));
[email protected]21160f02013-09-01 23:04:2796
[email protected]21160f02013-09-01 23:04:2797 return OK;
98}
99
100void TCPServerSocket::OnAcceptCompleted(
101 scoped_ptr<StreamSocket>* output_accepted_socket,
102 const CompletionCallback& forward_callback,
103 int result) {
104 result = ConvertAcceptedSocket(result, output_accepted_socket);
105 pending_accept_ = false;
106 forward_callback.Run(result);
107}
108
109} // namespace net