mgmt+face: move protocol-specific face creation checks into protocol factories
Also brought implementation of faces/create in line with design
refs #3731
Change-Id: I4f48079136b42c7fdbd4fdfba37116d2565f9dc1
diff --git a/daemon/face/channel.hpp b/daemon/face/channel.hpp
index 640395a..19beb7f 100644
--- a/daemon/face/channel.hpp
+++ b/daemon/face/channel.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2015, Regents of the University of California,
+ * Copyright (c) 2014-2016, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -41,7 +41,7 @@
* \brief Prototype for the callback that is invoked when the face
* fails to be created
*/
-typedef function<void(const std::string& reason)> FaceCreationFailedCallback;
+typedef function<void(uint32_t status, const std::string& reason)> FaceCreationFailedCallback;
class Channel : noncopyable
diff --git a/daemon/face/ethernet-factory.cpp b/daemon/face/ethernet-factory.cpp
index dd9d034..85f00f1 100644
--- a/daemon/face/ethernet-factory.cpp
+++ b/daemon/face/ethernet-factory.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2015, Regents of the University of California,
+ * Copyright (c) 2014-2016, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -59,9 +59,9 @@
EthernetFactory::createFace(const FaceUri& uri,
ndn::nfd::FacePersistency persistency,
const FaceCreatedCallback& onCreated,
- const FaceCreationFailedCallback& onConnectFailed)
+ const FaceCreationFailedCallback& onFailure)
{
- BOOST_THROW_EXCEPTION(Error("EthernetFactory does not support 'createFace' operation"));
+ onFailure(406, "Unsupported protocol");
}
std::vector<shared_ptr<const Channel>>
diff --git a/daemon/face/ethernet-factory.hpp b/daemon/face/ethernet-factory.hpp
index b44c2b7..f29e09a 100644
--- a/daemon/face/ethernet-factory.hpp
+++ b/daemon/face/ethernet-factory.hpp
@@ -80,7 +80,7 @@
createFace(const FaceUri& uri,
ndn::nfd::FacePersistency persistency,
const FaceCreatedCallback& onCreated,
- const FaceCreationFailedCallback& onConnectFailed) override;
+ const FaceCreationFailedCallback& onFailure) override;
virtual std::vector<shared_ptr<const Channel>>
getChannels() const override;
diff --git a/daemon/face/tcp-channel.cpp b/daemon/face/tcp-channel.cpp
index 21943c8..163b0e9 100644
--- a/daemon/face/tcp-channel.cpp
+++ b/daemon/face/tcp-channel.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2015, Regents of the University of California,
+ * Copyright (c) 2014-2016, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -151,7 +151,7 @@
NFD_LOG_DEBUG("[" << m_localEndpoint << "] Accept failed: " << error.message());
if (onAcceptFailed)
- onAcceptFailed(error.message());
+ onAcceptFailed(500, "Accept failed: " + error.message());
return;
}
@@ -189,7 +189,7 @@
socket->close();
if (onConnectFailed)
- onConnectFailed(error.message());
+ onConnectFailed(504, "Connect failed: " + error.message());
return;
}
@@ -209,7 +209,7 @@
socket->close(error);
if (onConnectFailed)
- onConnectFailed("Connect to remote endpoint timed out");
+ onConnectFailed(504, "Connect to remote endpoint timed out");
}
} // namespace nfd
diff --git a/daemon/face/tcp-factory.cpp b/daemon/face/tcp-factory.cpp
index a0fad93..5c96492 100644
--- a/daemon/face/tcp-factory.cpp
+++ b/daemon/face/tcp-factory.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2015, Regents of the University of California,
+ * Copyright (c) 2014-2016, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -105,15 +105,24 @@
BOOST_ASSERT(uri.isCanonical());
if (persistency != ndn::nfd::FACE_PERSISTENCY_PERSISTENT) {
- BOOST_THROW_EXCEPTION(Error("TcpFactory::createFace supports only FACE_PERSISTENCY_PERSISTENT"));
+ NFD_LOG_TRACE("createFace only supports FACE_PERSISTENCY_PERSISTENT");
+ onConnectFailed(406, "Outgoing TCP faces only support persistent persistency");
+ return;
}
tcp::Endpoint endpoint(ip::address::from_string(uri.getHost()),
boost::lexical_cast<uint16_t>(uri.getPort()));
+ if (endpoint.address().is_multicast()) {
+ NFD_LOG_TRACE("createFace cannot create multicast faces");
+ onConnectFailed(406, "Cannot create multicast TCP faces");
+ return;
+ }
+
if (m_prohibitedEndpoints.find(endpoint) != m_prohibitedEndpoints.end()) {
- onConnectFailed("Requested endpoint is prohibited "
- "(reserved by this NFD or disallowed by face management protocol)");
+ NFD_LOG_TRACE("Requested endpoint is prohibited "
+ "(reserved by NFD or disallowed by face management protocol)");
+ onConnectFailed(406, "Requested endpoint is prohibited");
return;
}
@@ -126,7 +135,8 @@
}
}
- onConnectFailed("No channels available to connect to " + boost::lexical_cast<std::string>(endpoint));
+ NFD_LOG_TRACE("No channels available to connect to " + boost::lexical_cast<std::string>(endpoint));
+ onConnectFailed(504, "No channels available to connect");
}
std::vector<shared_ptr<const Channel>>
diff --git a/daemon/face/udp-channel.cpp b/daemon/face/udp-channel.cpp
index e6d65df..9b66b0d 100644
--- a/daemon/face/udp-channel.cpp
+++ b/daemon/face/udp-channel.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2015, Regents of the University of California,
+ * Copyright (c) 2014-2016, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -62,7 +62,7 @@
catch (const boost::system::system_error& e) {
NFD_LOG_WARN("[" << m_localEndpoint << "] Connect failed: " << e.what());
if (onConnectFailed)
- onConnectFailed(e.what());
+ onConnectFailed(504, std::string("Connect failed: ") + e.what());
return;
}
@@ -113,7 +113,7 @@
NFD_LOG_DEBUG("[" << m_localEndpoint << "] Receive failed: " << error.message());
if (onReceiveFailed)
- onReceiveFailed(error.message());
+ onReceiveFailed(500, "Receive failed: " + error.message());
return;
}
@@ -128,7 +128,7 @@
NFD_LOG_WARN("[" << m_localEndpoint << "] Failed to create face for peer "
<< m_remoteEndpoint << ": " << e.what());
if (onReceiveFailed)
- onReceiveFailed(e.what());
+ onReceiveFailed(504, "Failed to create face for peer");
return;
}
diff --git a/daemon/face/udp-factory.cpp b/daemon/face/udp-factory.cpp
index e905a0b..499c72c 100644
--- a/daemon/face/udp-factory.cpp
+++ b/daemon/face/udp-factory.cpp
@@ -239,20 +239,24 @@
BOOST_ASSERT(uri.isCanonical());
if (persistency == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND) {
- BOOST_THROW_EXCEPTION(Error("UdpFactory::createFace does not support FACE_PERSISTENCY_ON_DEMAND"));
+ NFD_LOG_TRACE("createFace does not support FACE_PERSISTENCY_ON_DEMAND");
+ onConnectFailed(406, "Outgoing unicast UDP faces do not support on-demand persistency");
+ return;
}
udp::Endpoint endpoint(ip::address::from_string(uri.getHost()),
boost::lexical_cast<uint16_t>(uri.getPort()));
if (endpoint.address().is_multicast()) {
- onConnectFailed("The provided address is multicast. Please use createMulticastFace method");
+ NFD_LOG_TRACE("createFace does not support multicast faces");
+ onConnectFailed(406, "Cannot create multicast UDP faces");
return;
}
if (m_prohibitedEndpoints.find(endpoint) != m_prohibitedEndpoints.end()) {
- onConnectFailed("Requested endpoint is prohibited "
- "(reserved by this NFD or disallowed by face management protocol)");
+ NFD_LOG_TRACE("Requested endpoint is prohibited "
+ "(reserved by this NFD or disallowed by face management protocol)");
+ onConnectFailed(406, "Requested endpoint is prohibited");
return;
}
@@ -265,7 +269,8 @@
}
}
- onConnectFailed("No channels available to connect to " + boost::lexical_cast<std::string>(endpoint));
+ NFD_LOG_TRACE("No channels available to connect to " + boost::lexical_cast<std::string>(endpoint));
+ onConnectFailed(504, "No channels available to connect");
}
std::vector<shared_ptr<const Channel>>
diff --git a/daemon/face/unix-stream-channel.cpp b/daemon/face/unix-stream-channel.cpp
index 5b56c6a..85416fd 100644
--- a/daemon/face/unix-stream-channel.cpp
+++ b/daemon/face/unix-stream-channel.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2015, Regents of the University of California,
+ * Copyright (c) 2014-2016, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -126,7 +126,7 @@
NFD_LOG_DEBUG("[" << m_endpoint << "] Accept failed: " << error.message());
if (onAcceptFailed)
- onAcceptFailed(error.message());
+ onAcceptFailed(500, "Accept failed: " + error.message());
return;
}
diff --git a/daemon/face/unix-stream-factory.cpp b/daemon/face/unix-stream-factory.cpp
index 3de85b4..b85953e 100644
--- a/daemon/face/unix-stream-factory.cpp
+++ b/daemon/face/unix-stream-factory.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2015, Regents of the University of California,
+ * Copyright (c) 2014-2016, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -51,7 +51,7 @@
const FaceCreatedCallback& onCreated,
const FaceCreationFailedCallback& onConnectFailed)
{
- BOOST_THROW_EXCEPTION(Error("UnixStreamFactory does not support 'createFace' operation"));
+ onConnectFailed(406, "Unsupported protocol");
}
std::vector<shared_ptr<const Channel>>
diff --git a/daemon/face/websocket-factory.cpp b/daemon/face/websocket-factory.cpp
index bcb3970..cea0078 100644
--- a/daemon/face/websocket-factory.cpp
+++ b/daemon/face/websocket-factory.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2015, Regents of the University of California,
+ * Copyright (c) 2014-2016, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -56,7 +56,7 @@
const FaceCreatedCallback& onCreated,
const FaceCreationFailedCallback& onConnectFailed)
{
- BOOST_THROW_EXCEPTION(Error("WebSocketFactory does not support 'createFace' operation"));
+ onConnectFailed(406, "Unsupported protocol");
}
std::vector<shared_ptr<const Channel>>
diff --git a/daemon/mgmt/face-manager.cpp b/daemon/mgmt/face-manager.cpp
index 8b7057c..9cd0e07 100644
--- a/daemon/mgmt/face-manager.cpp
+++ b/daemon/mgmt/face-manager.cpp
@@ -91,17 +91,21 @@
FaceUri uri;
if (!uri.parse(parameters.getUri())) {
NFD_LOG_TRACE("failed to parse URI");
- return done(ControlResponse(400, "Malformed command"));
+ done(ControlResponse(400, "Malformed command"));
+ return;
}
if (!uri.isCanonical()) {
NFD_LOG_TRACE("received non-canonical URI");
- return done(ControlResponse(400, "Non-canonical URI"));
+ done(ControlResponse(400, "Non-canonical URI"));
+ return;
}
auto factory = m_factories.find(uri.getScheme());
if (factory == m_factories.end()) {
- return done(ControlResponse(501, "Unsupported protocol"));
+ NFD_LOG_TRACE("received create request for unsupported protocol");
+ done(ControlResponse(406, "Unsupported protocol"));
+ return;
}
try {
@@ -110,35 +114,50 @@
bind(&FaceManager::afterCreateFaceSuccess,
this, parameters, _1, done),
bind(&FaceManager::afterCreateFaceFailure,
- this, _1, done));
+ this, _1, _2, done));
}
catch (const std::runtime_error& error) {
- std::string errorMessage = "Face creation failed: ";
- errorMessage += error.what();
-
- NFD_LOG_ERROR(errorMessage);
- return done(ControlResponse(500, errorMessage));
+ NFD_LOG_ERROR("Face creation failed: " << error.what());
+ done(ControlResponse(500, "Face creation failed due to internal error"));
+ return;
}
catch (const std::logic_error& error) {
- std::string errorMessage = "Face creation failed: ";
- errorMessage += error.what();
-
- NFD_LOG_ERROR(errorMessage);
- return done(ControlResponse(500, errorMessage));
+ NFD_LOG_ERROR("Face creation failed: " << error.what());
+ done(ControlResponse(500, "Face creation failed due to internal error"));
+ return;
}
}
+/**
+ * \todo #3232
+ * If the creation of this face would conflict with an existing face (e.g. same underlying
+ * protocol and remote address, or a NIC-associated permanent face), the command will fail
+ * with StatusCode 409.
+ */
void
-FaceManager::afterCreateFaceSuccess(ControlParameters& parameters,
+FaceManager::afterCreateFaceSuccess(const ControlParameters& parameters,
const shared_ptr<Face>& newFace,
const ndn::mgmt::CommandContinuation& done)
{
- m_faceTable.add(newFace);
- parameters.setFaceId(newFace->getId());
- parameters.setUri(newFace->getRemoteUri().toString());
- parameters.setFacePersistency(newFace->getPersistency());
+ ControlParameters response;
- done(ControlResponse(200, "OK").setBody(parameters.wireEncode()));
+ m_faceTable.add(newFace);
+
+ // Set ControlResponse parameters
+ response.setFaceId(newFace->getId());
+ response.setFacePersistency(newFace->getPersistency());
+
+ done(ControlResponse(200, "OK").setBody(response.wireEncode()));
+}
+
+void
+FaceManager::afterCreateFaceFailure(uint32_t status,
+ const std::string& reason,
+ const ndn::mgmt::CommandContinuation& done)
+{
+ NFD_LOG_DEBUG("Face creation failed: " << reason);
+
+ done(ControlResponse(status, reason));
}
void
@@ -155,15 +174,6 @@
}
void
-FaceManager::afterCreateFaceFailure(const std::string& reason,
- const ndn::mgmt::CommandContinuation& done)
-{
- NFD_LOG_DEBUG("Failed to create face: " << reason);
-
- done(ControlResponse(408, "Failed to create face: " + reason));
-}
-
-void
FaceManager::enableLocalControl(const Name& topPrefix, const Interest& interest,
const ControlParameters& parameters,
const ndn::mgmt::CommandContinuation& done)
diff --git a/daemon/mgmt/face-manager.hpp b/daemon/mgmt/face-manager.hpp
index f31f04b..094f288 100644
--- a/daemon/mgmt/face-manager.hpp
+++ b/daemon/mgmt/face-manager.hpp
@@ -77,12 +77,13 @@
PUBLIC_WITH_TESTS_ELSE_PRIVATE: // helpers for ControlCommand
void
- afterCreateFaceSuccess(ControlParameters& parameters,
+ afterCreateFaceSuccess(const ControlParameters& parameters,
const shared_ptr<Face>& newFace,
const ndn::mgmt::CommandContinuation& done);
void
- afterCreateFaceFailure(const std::string& reason,
+ afterCreateFaceFailure(uint32_t status,
+ const std::string& reason,
const ndn::mgmt::CommandContinuation& done);
Face*