Home | History | Annotate | Download | only in socket
      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 
     13 namespace net {
     14 
     15 TCPServerSocket::TCPServerSocket(NetLog* net_log, const NetLog::Source& source)
     16     : socket_(net_log, source),
     17       pending_accept_(false) {
     18 }
     19 
     20 TCPServerSocket::~TCPServerSocket() {
     21 }
     22 
     23 int 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 
     49 int TCPServerSocket::GetLocalAddress(IPEndPoint* address) const {
     50   return socket_.GetLocalAddress(address);
     51 }
     52 
     53 int 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 
     82 int 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 
     96 void 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