face: UDP face/channel/factory

Change-Id: I4683b45378637133982efd23edd16a0c35148948
refs #1189
diff --git a/daemon/face/udp-factory.hpp b/daemon/face/udp-factory.hpp
new file mode 100644
index 0000000..695d1e5
--- /dev/null
+++ b/daemon/face/udp-factory.hpp
@@ -0,0 +1,171 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NFD_FACE_UDP_FACTORY_HPP
+#define NFD_FACE_UDP_FACTORY_HPP
+
+#include "protocol-factory.hpp"
+#include "udp-channel.hpp"
+#include "multicast-udp-face.hpp"
+
+
+namespace nfd {
+
+// @todo The multicast support for ipv6 must be implemented
+
+class UdpFactory : public ProtocolFactory
+{
+public:
+  /**
+   * \brief Exception of UdpFactory
+   */
+  struct Error : public ProtocolFactory::Error
+  {
+    Error(const std::string& what) : ProtocolFactory::Error(what) {}
+  };
+  
+  explicit
+  UdpFactory(const std::string& defaultPort = "6363");
+
+  /**
+   * \brief Create UDP-based channel using udp::Endpoint
+   *
+   * udp::Endpoint is really an alias for boost::asio::ip::udp::endpoint.
+   *
+   * If this method called twice with the same endpoint, only one channel
+   * will be created.  The second call will just retrieve the existing
+   * channel.
+   *
+   * If a multicast face is already active on the same local endpoint,
+   * the creation fails and an exception is thrown
+   *
+   * Once a face is created, if it doesn't send/receive anything for
+   * a period of time equal to timeout, it will be destroyed
+   * @todo this funcionality has to be implemented
+   *
+   * \returns always a valid pointer to a UdpChannel object, an exception
+   *          is thrown if it cannot be created.
+   *
+   * \throws UdpFactory::Error
+   *
+   * \see http://www.boost.org/doc/libs/1_42_0/doc/html/boost_asio/reference/ip__udp/endpoint.html
+   *      for details on ways to create udp::Endpoint
+   */
+  shared_ptr<UdpChannel>
+  createChannel(const udp::Endpoint& localEndpoint,
+         const time::Duration& timeout = time::seconds(600));
+
+  /**
+   * \brief Create UDP-based channel using specified host and port number
+   *
+   * This method will attempt to resolve the provided host and port numbers
+   * and will throw UdpFactory::Error when channel cannot be created.
+   *
+   * Note that this call will **BLOCK** until resolution is done or failed.
+   *
+   * If localHost is a IPv6 address of a specific device, it must be in the form: 
+   * ip address%interface name
+   * Example: fe80::5e96:9dff:fe7d:9c8d%en1
+   * Otherwise, you can use :: 
+   *
+   * Once a face is created, if it doesn't send/receive anything for
+   * a period of time equal to timeout, it will be destroyed
+   * @todo this funcionality has to be implemented
+   *
+   * \throws UdpChannel::Error if the bind on the socket fails
+   * \throws UdpFactory::Error
+   */
+  shared_ptr<UdpChannel>
+  createChannel(const std::string& localHost,
+         const std::string& localPort,
+         const time::Duration& timeout = time::seconds(600));
+
+  /**
+   * \brief Create MulticastUdpFace using udp::Endpoint
+   *
+   * udp::Endpoint is really an alias for boost::asio::ip::udp::endpoint.
+   *
+   * The face will join the multicast group
+   *
+   * If this method called twice with the same endpoint and group, only one face
+   * will be created.  The second call will just retrieve the existing
+   * channel.
+   *
+   * If an unicast face is already active on the same local NIC and port, the
+   * creation fails and an exception is thrown
+   *
+   * \returns always a valid pointer to a MulticastUdpFace object, an exception
+   *          is thrown if it cannot be created. 
+   *
+   * \throws UdpFactory::Error
+   *
+   * \see http://www.boost.org/doc/libs/1_42_0/doc/html/boost_asio/reference/ip__udp/endpoint.html
+   *      for details on ways to create udp::Endpoint
+   */
+  shared_ptr<MulticastUdpFace>
+  createMulticastFace(const udp::Endpoint& localEndpoint,
+                      const udp::Endpoint& multicastEndpoint);
+  
+  shared_ptr<MulticastUdpFace>
+  createMulticastFace(const std::string& localIp,
+                      const std::string& multicastIp,
+                      const std::string& multicastPort);
+  
+  // from Factory
+  virtual void
+  createFace(const FaceUri& uri,
+             const FaceCreatedCallback& onCreated,
+             const FaceConnectFailedCallback& onConnectFailed);
+
+protected:
+  typedef std::map< udp::Endpoint, shared_ptr<MulticastUdpFace> > MulticastFaceMap;
+
+  /**
+   * \brief Keeps tracking of the MulticastUdpFace created
+   */
+  MulticastFaceMap m_multicastFaces;
+
+private:
+  void
+  afterFaceFailed(udp::Endpoint& endpoint);
+    
+  /**
+   * \brief Look up UdpChannel using specified local endpoint
+   *
+   * \returns shared pointer to the existing UdpChannel object
+   *          or empty shared pointer when such channel does not exist
+   *
+   * \throws never
+   */
+  shared_ptr<UdpChannel>
+  findChannel(const udp::Endpoint& localEndpoint);
+  
+  
+  /**
+   * \brief Look up multicast UdpFace using specified local endpoint
+   *
+   * \returns shared pointer to the existing multicast MulticastUdpFace object
+   *          or empty shared pointer when such face does not exist
+   *
+   * \throws never
+   */
+  shared_ptr<MulticastUdpFace>
+  findMulticastFace(const udp::Endpoint& localEndpoint);
+  
+  void
+  continueCreateFaceAfterResolve(const udp::Endpoint& endpoint,
+                                 const FaceCreatedCallback& onCreated,
+                                 const FaceConnectFailedCallback& onConnectFailed);
+  
+  typedef std::map< udp::Endpoint, shared_ptr<UdpChannel> > ChannelMap;
+  ChannelMap m_channels;
+  
+  std::string m_defaultPort;
+};
+
+} // namespace nfd
+
+#endif // NFD_FACE_UDP_FACTORY_HPP