C++程序  |  133行  |  4.73 KB

// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_SOCKET_SOCKET_LIBEVENT_H_
#define NET_SOCKET_SOCKET_LIBEVENT_H_

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread_checker.h"
#include "net/base/completion_callback.h"
#include "net/base/net_util.h"
#include "net/socket/socket_descriptor.h"

namespace net {

class IOBuffer;
class IPEndPoint;

// Socket class to provide asynchronous read/write operations on top of the
// posix socket api. It supports AF_INET, AF_INET6, and AF_UNIX addresses.
class NET_EXPORT_PRIVATE SocketLibevent
    : public base::MessageLoopForIO::Watcher {
 public:
  SocketLibevent();
  virtual ~SocketLibevent();

  // Opens a socket and returns net::OK if |address_family| is AF_INET, AF_INET6
  // or AF_UNIX. Otherwise, it does DCHECK() and returns a net error.
  int Open(int address_family);
  // Takes ownership of |socket|.
  int AdoptConnectedSocket(SocketDescriptor socket,
                           const SockaddrStorage& peer_address);
  // Releases ownership of |socket_fd_| to caller.
  SocketDescriptor ReleaseConnectedSocket();

  int Bind(const SockaddrStorage& address);

  int Listen(int backlog);
  int Accept(scoped_ptr<SocketLibevent>* socket,
             const CompletionCallback& callback);

  // Connects socket. On non-ERR_IO_PENDING error, sets errno and returns a net
  // error code. On ERR_IO_PENDING, |callback| is called with a net error code,
  // not errno, though errno is set if connect event happens with error.
  // TODO(byungchul): Need more robust way to pass system errno.
  int Connect(const SockaddrStorage& address,
              const CompletionCallback& callback);
  bool IsConnected() const;
  bool IsConnectedAndIdle() const;

  // Multiple outstanding requests of the same type are not supported.
  // Full duplex mode (reading and writing at the same time) is supported.
  // On error which is not ERR_IO_PENDING, sets errno and returns a net error
  // code. On ERR_IO_PENDING, |callback| is called with a net error code, not
  // errno, though errno is set if read or write events happen with error.
  // TODO(byungchul): Need more robust way to pass system errno.
  int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
  int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback);

  // Waits for next write event. This is called by TCPsocketLibevent for TCP
  // fastopen after sending first data. Returns ERR_IO_PENDING if it starts
  // waiting for write event successfully. Otherwise, returns a net error code.
  // It must not be called after Write() because Write() calls it internally.
  int WaitForWrite(IOBuffer* buf, int buf_len,
                   const CompletionCallback& callback);

  int GetLocalAddress(SockaddrStorage* address) const;
  int GetPeerAddress(SockaddrStorage* address) const;
  void SetPeerAddress(const SockaddrStorage& address);
  // Returns true if peer address has been set regardless of socket state.
  bool HasPeerAddress() const;

  void Close();

  SocketDescriptor socket_fd() const { return socket_fd_; }

 private:
  // base::MessageLoopForIO::Watcher methods.
  virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
  virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE;

  int DoAccept(scoped_ptr<SocketLibevent>* socket);
  void AcceptCompleted();

  int DoConnect();
  void ConnectCompleted();

  int DoRead(IOBuffer* buf, int buf_len);
  void ReadCompleted();

  int DoWrite(IOBuffer* buf, int buf_len);
  void WriteCompleted();

  void StopWatchingAndCleanUp();

  SocketDescriptor socket_fd_;

  base::MessageLoopForIO::FileDescriptorWatcher accept_socket_watcher_;
  scoped_ptr<SocketLibevent>* accept_socket_;
  CompletionCallback accept_callback_;

  base::MessageLoopForIO::FileDescriptorWatcher read_socket_watcher_;
  scoped_refptr<IOBuffer> read_buf_;
  int read_buf_len_;
  // External callback; called when read is complete.
  CompletionCallback read_callback_;

  base::MessageLoopForIO::FileDescriptorWatcher write_socket_watcher_;
  scoped_refptr<IOBuffer> write_buf_;
  int write_buf_len_;
  // External callback; called when write or connect is complete.
  CompletionCallback write_callback_;

  // A connect operation is pending. In this case, |write_callback_| needs to be
  // called when connect is complete.
  bool waiting_connect_;

  scoped_ptr<SockaddrStorage> peer_address_;

  base::ThreadChecker thread_checker_;

  DISALLOW_COPY_AND_ASSIGN(SocketLibevent);
};

}  // namespace net

#endif  // NET_SOCKET_SOCKET_LIBEVENT_H_