Home | History | Annotate | Download | only in base
      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 #ifndef BASE_ASYNC_SOCKET_IO_HANDLER_H_
      6 #define BASE_ASYNC_SOCKET_IO_HANDLER_H_
      7 
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/sync_socket.h"
     10 #include "base/threading/non_thread_safe.h"
     11 
     12 namespace base {
     13 
     14 // Extends the CancelableSyncSocket class to allow reading from a socket
     15 // asynchronously on a TYPE_IO message loop thread.  This makes it easy to share
     16 // a thread that uses a message loop (e.g. for IPC and other things) and not
     17 // require a separate thread to read from the socket.
     18 //
     19 // Example usage (also see the unit tests):
     20 //
     21 // class SocketReader {
     22 //  public:
     23 //   SocketReader(base::CancelableSyncSocket* socket)
     24 //       : socket_(socket), buffer_() {
     25 //     io_handler.Initialize(socket_->handle(),
     26 //                           base::Bind(&SocketReader::OnDataAvailable,
     27 //                                      base::Unretained(this));
     28 //   }
     29 //
     30 //   void AsyncRead() {
     31 //     CHECK(io_handler.Read(&buffer_[0], sizeof(buffer_)));
     32 //   }
     33 //
     34 //  private:
     35 //   void OnDataAvailable(int bytes_read) {
     36 //     if (ProcessData(&buffer_[0], bytes_read)) {
     37 //       // Issue another read.
     38 //       CHECK(io_handler.Read(&buffer_[0], sizeof(buffer_)));
     39 //     }
     40 //   }
     41 //
     42 //   base::AsyncSocketIoHandler io_handler;
     43 //   base::CancelableSyncSocket* socket_;
     44 //   char buffer_[kBufferSize];
     45 // };
     46 //
     47 class BASE_EXPORT AsyncSocketIoHandler
     48     : public NON_EXPORTED_BASE(base::NonThreadSafe),
     49 // The message loop callback interface is different based on platforms.
     50 #if defined(OS_WIN)
     51       public NON_EXPORTED_BASE(base::MessageLoopForIO::IOHandler) {
     52 #else
     53       public NON_EXPORTED_BASE(base::MessageLoopForIO::Watcher) {
     54 #endif
     55  public:
     56   AsyncSocketIoHandler();
     57   virtual ~AsyncSocketIoHandler();
     58 
     59   // Type definition for the callback. The parameter tells how many
     60   // bytes were read and is 0 if an error occurred.
     61   typedef base::Callback<void(int)> ReadCompleteCallback;
     62 
     63   // Initializes the AsyncSocketIoHandler by hooking it up to the current
     64   // thread's message loop (must be TYPE_IO), to do async reads from the socket
     65   // on the current thread.  The |callback| will be invoked whenever a Read()
     66   // has completed.
     67   bool Initialize(base::SyncSocket::Handle socket,
     68                   const ReadCompleteCallback& callback);
     69 
     70   // Attempts to read from the socket.  The return value will be |false|
     71   // if an error occurred and |true| if data was read or a pending read
     72   // was issued.  Regardless of async or sync operation, the
     73   // ReadCompleteCallback (see above) will be called when data is available.
     74   bool Read(char* buffer, int buffer_len);
     75 
     76  private:
     77 #if defined(OS_WIN)
     78   // Implementation of IOHandler on Windows.
     79   virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context,
     80                              DWORD bytes_transfered,
     81                              DWORD error) OVERRIDE;
     82 #elif defined(OS_POSIX)
     83   // Implementation of base::MessageLoopForIO::Watcher.
     84   virtual void OnFileCanWriteWithoutBlocking(int socket) OVERRIDE {}
     85   virtual void OnFileCanReadWithoutBlocking(int socket) OVERRIDE;
     86 
     87   void EnsureWatchingSocket();
     88 #endif
     89 
     90   base::SyncSocket::Handle socket_;
     91 #if defined(OS_WIN)
     92   base::MessageLoopForIO::IOContext* context_;
     93   bool is_pending_;
     94 #elif defined(OS_POSIX)
     95   base::MessageLoopForIO::FileDescriptorWatcher socket_watcher_;
     96   // |pending_buffer_| and |pending_buffer_len_| are valid only between
     97   // Read() and OnFileCanReadWithoutBlocking().
     98   char* pending_buffer_;
     99   int pending_buffer_len_;
    100   // |true| iff the message loop is watching the socket for IO events.
    101   bool is_watching_;
    102 #endif
    103   ReadCompleteCallback read_complete_;
    104 
    105   DISALLOW_COPY_AND_ASSIGN(AsyncSocketIoHandler);
    106 };
    107 
    108 }  // namespace base.
    109 
    110 #endif  // BASE_ASYNC_SOCKET_IO_HANDLER_H_
    111