1// 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"
10#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) {
24  int result = socket_.Open(address.GetFamily());
25  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
82int TCPServerSocket::ConvertAcceptedSocket(
83    int result,
84    scoped_ptr<StreamSocket>* output_accepted_socket) {
85  // Make sure the TCPSocket object is destroyed in any case.
86  scoped_ptr<TCPSocket> temp_accepted_socket(accepted_socket_.Pass());
87  if (result != OK)
88    return result;
89
90  output_accepted_socket->reset(new TCPClientSocket(
91      temp_accepted_socket.Pass(), accepted_address_));
92
93  return OK;
94}
95
96void TCPServerSocket::OnAcceptCompleted(
97    scoped_ptr<StreamSocket>* output_accepted_socket,
98    const CompletionCallback& forward_callback,
99    int result) {
100  result = ConvertAcceptedSocket(result, output_accepted_socket);
101  pending_accept_ = false;
102  forward_callback.Run(result);
103}
104
105}  // namespace net
106