face/tcp: Adding success/fail callbacks for TCP channel connect/listen

refs: #1132, #1133, #1134, #1135

Change-Id: I7df15dd9cd24f26b1ed96a4781934ffd93bc8f6e
diff --git a/daemon/face/tcp-channel.cpp b/daemon/face/tcp-channel.cpp
index 4018161..bbefa44 100644
--- a/daemon/face/tcp-channel.cpp
+++ b/daemon/face/tcp-channel.cpp
@@ -5,7 +5,6 @@
  */
 
 #include "tcp-channel.hpp"
-#include "tcp-face.hpp"
 
 namespace ndn {
 
@@ -19,7 +18,9 @@
 }
 
 void
-TcpChannel::listen(int backlog/* = tcp::acceptor::max_connections*/)
+TcpChannel::listen(const FaceCreatedCallback& onFaceCreated,
+                   const ConnectFailedCallback& onAcceptFailed,
+                   int backlog/* = tcp::acceptor::max_connections*/)
 {
   m_acceptor = make_shared<ip::tcp::acceptor>(boost::ref(m_ioService));
   m_acceptor->open(m_localEndpoint.protocol());
@@ -30,12 +31,15 @@
   shared_ptr<ip::tcp::socket> clientSocket =
     make_shared<ip::tcp::socket>(boost::ref(m_ioService));
   m_acceptor->async_accept(*clientSocket,
-                           bind(&TcpChannel::handleConnection, this,
-                                _1, clientSocket));
+                           bind(&TcpChannel::handleConnection, this, _1,
+                                clientSocket,
+                                onFaceCreated, onAcceptFailed));
 }
 
 void
 TcpChannel::connect(const tcp::Endpoint& remoteEndpoint,
+                    const TcpChannel::FaceCreatedCallback& onFaceCreated,
+                    const TcpChannel::ConnectFailedCallback& onConnectFailed,
                     const time::Duration& timeout/* = time::seconds(4)*/)
 {
   shared_ptr<ip::tcp::socket> clientSocket =
@@ -49,16 +53,20 @@
   clientSocket->bind(m_localEndpoint);
 
   clientSocket->async_connect(remoteEndpoint,
-                              bind(&TcpChannel::handleSuccessfulConnect, this,
-                                   _1, clientSocket, connectTimeoutTimer));
+                              bind(&TcpChannel::handleSuccessfulConnect, this, _1,
+                                   clientSocket, connectTimeoutTimer,
+                                   onFaceCreated, onConnectFailed));
 
   connectTimeoutTimer->expires_from_now(timeout);
-  connectTimeoutTimer->async_wait(bind(&TcpChannel::handleFailedConnect, this,
-                                       _1, clientSocket, connectTimeoutTimer));
+  connectTimeoutTimer->async_wait(bind(&TcpChannel::handleFailedConnect, this, _1,
+                                       clientSocket, connectTimeoutTimer,
+                                       onConnectFailed));
 }
 
 void
 TcpChannel::connect(const std::string& remoteHost, const std::string& remotePort,
+                    const TcpChannel::FaceCreatedCallback& onFaceCreated,
+                    const TcpChannel::ConnectFailedCallback& onConnectFailed,
                     const time::Duration& timeout/* = time::seconds(4)*/)
 {
   shared_ptr<ip::tcp::socket> clientSocket =
@@ -77,17 +85,21 @@
 
   resolver->async_resolve(query,
                           bind(&TcpChannel::handleEndpointResoution, this, _1, _2,
-                               clientSocket, connectTimeoutTimer));
+                               clientSocket, connectTimeoutTimer,
+                               onFaceCreated, onConnectFailed));
 
   connectTimeoutTimer->expires_from_now(timeout);
-  connectTimeoutTimer->async_wait(bind(&TcpChannel::handleFailedConnect, this,
-                                       _1, clientSocket, connectTimeoutTimer));
+  connectTimeoutTimer->async_wait(bind(&TcpChannel::handleFailedConnect, this, _1,
+                                       clientSocket, connectTimeoutTimer,
+                                       onConnectFailed));
 }
 
 
 void
 TcpChannel::handleConnection(const boost::system::error_code& error,
-                             const shared_ptr<ip::tcp::socket>& socket)
+                             const shared_ptr<ip::tcp::socket>& socket,
+                             const FaceCreatedCallback& onFaceCreated,
+                             const ConnectFailedCallback& onConnectFailed)
 {
   if (error) {
     if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
@@ -100,17 +112,18 @@
   }
 
   /**
-   * \todo Either remove FaceId from here or set it here to some real value
+   * \todo Remove FaceId from here
    */
   shared_ptr<TcpFace> face = make_shared<TcpFace>(1, boost::cref(socket));
-
-  // what's next?
+  onFaceCreated(face);
 }
 
 void
 TcpChannel::handleSuccessfulConnect(const boost::system::error_code& error,
                                     const shared_ptr<ip::tcp::socket>& socket,
-                                    const shared_ptr<monotonic_deadline_timer>& timer)
+                                    const shared_ptr<monotonic_deadline_timer>& timer,
+                                    const FaceCreatedCallback& onFaceCreated,
+                                    const ConnectFailedCallback& onConnectFailed)
 {
   timer->cancel();
 
@@ -124,13 +137,14 @@
     return;
   }
 
-  handleConnection(error, socket);
+  handleConnection(error, socket, onFaceCreated, onConnectFailed);
 }
 
 void
 TcpChannel::handleFailedConnect(const boost::system::error_code& error,
                                 const shared_ptr<ip::tcp::socket>& socket,
-                                const shared_ptr<monotonic_deadline_timer>& timer)
+                                const shared_ptr<monotonic_deadline_timer>& timer,
+                                const ConnectFailedCallback& onConnectFailed)
 {
   if (error) { // e.g., cancelled
     return;
@@ -145,7 +159,9 @@
 TcpChannel::handleEndpointResoution(const boost::system::error_code& error,
                                     ip::tcp::resolver::iterator remoteEndpoint,
                                     const shared_ptr<boost::asio::ip::tcp::socket>& socket,
-                                    const shared_ptr<boost::asio::monotonic_deadline_timer>& timer)
+                                    const shared_ptr<boost::asio::monotonic_deadline_timer>& timer,
+                                    const FaceCreatedCallback& onFaceCreated,
+                                    const ConnectFailedCallback& onConnectFailed)
 {
   if (error ||
       remoteEndpoint == ip::tcp::resolver::iterator())
@@ -162,8 +178,9 @@
 
   // got endpoint, now trying to connect (only try the first resolution option)
   socket->async_connect(*remoteEndpoint,
-                        bind(&TcpChannel::handleSuccessfulConnect, this,
-                             _1, socket, timer));
+                        bind(&TcpChannel::handleSuccessfulConnect, this, _1,
+                             socket, timer,
+                             onFaceCreated, onConnectFailed));
 }
 
 
diff --git a/daemon/face/tcp-channel.hpp b/daemon/face/tcp-channel.hpp
index c410769..64596d0 100644
--- a/daemon/face/tcp-channel.hpp
+++ b/daemon/face/tcp-channel.hpp
@@ -9,6 +9,7 @@
 
 #include "common.hpp"
 #include "core/monotonic_deadline_timer.hpp"
+#include "tcp-face.hpp"
 
 namespace tcp {
 typedef boost::asio::ip::tcp::endpoint Endpoint;
@@ -55,20 +56,24 @@
    *        connections
    */
   void
-  listen(int backlog = boost::asio::ip::tcp::acceptor::max_connections);
+  listen(const FaceCreatedCallback& onFaceCreated,
+         const ConnectFailedCallback& onAcceptFailed,
+         int backlog = boost::asio::ip::tcp::acceptor::max_connections);
 
   /**
    * \brief Create a face by establishing connection to remote endpoint
    */
   void
   connect(const tcp::Endpoint& remoteEndpoint,
+          const FaceCreatedCallback& onFaceCreated,
+          const ConnectFailedCallback& onConnectFailed,
           const time::Duration& timeout = time::seconds(4));
 
   /**
    * \brief Create a face by establishing connection to the specified
    *        remote host and remote port
    *
-   * This method will never blocks and will return immediately. All
+   * This method will never block and will return immediately. All
    * necessary hostname and port resolution and connection will happen
    * in asynchronous mode.
    *
@@ -77,28 +82,37 @@
    */
   void
   connect(const std::string& remoteHost, const std::string& remotePort,
+          const FaceCreatedCallback& onFaceCreated,
+          const ConnectFailedCallback& onConnectFailed,
           const time::Duration& timeout = time::seconds(4));
   
 private:
   void
   handleConnection(const boost::system::error_code& error,
-                   const shared_ptr<boost::asio::ip::tcp::socket>& socket);
+                   const shared_ptr<boost::asio::ip::tcp::socket>& socket,
+                   const FaceCreatedCallback& onFaceCreated,
+                   const ConnectFailedCallback& onConnectFailed);
 
   void
   handleSuccessfulConnect(const boost::system::error_code& error,
                           const shared_ptr<boost::asio::ip::tcp::socket>& socket,
-                          const shared_ptr<boost::asio::monotonic_deadline_timer>& timer);
+                          const shared_ptr<boost::asio::monotonic_deadline_timer>& timer,
+                          const FaceCreatedCallback& onFaceCreated,
+                          const ConnectFailedCallback& onConnectFailed);
   
   void
   handleFailedConnect(const boost::system::error_code& error,
                       const shared_ptr<boost::asio::ip::tcp::socket>& socket,
-                      const shared_ptr<boost::asio::monotonic_deadline_timer>& timer);
+                      const shared_ptr<boost::asio::monotonic_deadline_timer>& timer,
+                      const ConnectFailedCallback& onConnectFailed);
 
   void
   handleEndpointResoution(const boost::system::error_code& error,
                           boost::asio::ip::tcp::resolver::iterator remoteEndpoint,
                           const shared_ptr<boost::asio::ip::tcp::socket>& socket,
-                          const shared_ptr<boost::asio::monotonic_deadline_timer>& timer);
+                          const shared_ptr<boost::asio::monotonic_deadline_timer>& timer,
+                          const FaceCreatedCallback& onFaceCreated,
+                          const ConnectFailedCallback& onConnectFailed);
   
 private:
   boost::asio::io_service& m_ioService;