tcp_server_socket.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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 "build/build_config.h"
11#include "net/base/net_errors.h"
12#include "net/socket/tcp_client_socket.h"
13
14namespace net {
15
16TCPServerSocket::TCPServerSocket(NetLog* net_log, const NetLog::Source& source)
17    : socket_(net_log, source),
18      pending_accept_(false) {
19}
20
21TCPServerSocket::~TCPServerSocket() {
22}
23
24int TCPServerSocket::Listen(const IPEndPoint& address, int backlog) {
25  int result = socket_.Create(address.GetFamily());
26  if (result != OK)
27    return result;
28
29  result = socket_.SetDefaultOptionsForServer();
30  if (result != OK) {
31    socket_.Close();
32    return result;
33  }
34
35  result = socket_.Bind(address);
36  if (result != OK) {
37    socket_.Close();
38    return result;
39  }
40
41  result = socket_.Listen(backlog);
42  if (result != OK) {
43    socket_.Close();
44    return result;
45  }
46
47  return OK;
48}
49
50int TCPServerSocket::GetLocalAddress(IPEndPoint* address) const {
51  return socket_.GetLocalAddress(address);
52}
53
54int TCPServerSocket::Accept(scoped_ptr<StreamSocket>* socket,
55                            const CompletionCallback& callback) {
56  DCHECK(socket);
57  DCHECK(!callback.is_null());
58
59  if (pending_accept_) {
60    NOTREACHED();
61    return ERR_UNEXPECTED;
62  }
63
64  // It is safe to use base::Unretained(this). |socket_| is owned by this class,
65  // and the callback won't be run after |socket_| is destroyed.
66  CompletionCallback accept_callback =
67      base::Bind(&TCPServerSocket::OnAcceptCompleted, base::Unretained(this),
68                 socket, callback);
69  int result = socket_.Accept(&accepted_socket_, &accepted_address_,
70                              accept_callback);
71  if (result != ERR_IO_PENDING) {
72    // |accept_callback| won't be called so we need to run
73    // ConvertAcceptedSocket() ourselves in order to do the conversion from
74    // |accepted_socket_| to |socket|.
75    result = ConvertAcceptedSocket(result, socket);
76  } else {
77    pending_accept_ = true;
78  }
79
80  return result;
81}
82
83int TCPServerSocket::ConvertAcceptedSocket(
84    int result,
85    scoped_ptr<StreamSocket>* output_accepted_socket) {
86  // Make sure the TCPSocket object is destroyed in any case.
87  scoped_ptr<TCPSocket> temp_accepted_socket(accepted_socket_.Pass());
88  if (result != OK)
89    return result;
90
91  scoped_ptr<TCPClientSocket> client_socket(new TCPClientSocket(
92      AddressList(accepted_address_),
93      temp_accepted_socket->net_log().net_log(),
94      temp_accepted_socket->net_log().source()));
95  // TODO(yzshen): Once we switch TCPClientSocket::AdoptSocket() to take a
96  // TCPSocket object, we don't need to do platform-specific handling.
97#if defined(OS_WIN)
98  SOCKET raw_socket = temp_accepted_socket->Release();
99#elif defined(OS_POSIX)
100  int raw_socket = temp_accepted_socket->Release();
101#endif
102  result = client_socket->AdoptSocket(raw_socket);
103  if (result != OK) {
104    // |client_socket| won't take ownership of |raw_socket| on failure.
105    // Therefore, we put it back into |temp_accepted_socket| to close it.
106    temp_accepted_socket->Adopt(raw_socket);
107    return result;
108  }
109
110  *output_accepted_socket = client_socket.Pass();
111  return OK;
112}
113
114void TCPServerSocket::OnAcceptCompleted(
115    scoped_ptr<StreamSocket>* output_accepted_socket,
116    const CompletionCallback& forward_callback,
117    int result) {
118  result = ConvertAcceptedSocket(result, output_accepted_socket);
119  pending_accept_ = false;
120  forward_callback.Run(result);
121}
122
123}  // namespace net
124