face: more robust handling of multicast face creation errors

Refs: #5030, #5297
Change-Id: I3ca985498d9d3756cbff94873063f3734bcea288
diff --git a/daemon/face/ethernet-channel.cpp b/daemon/face/ethernet-channel.cpp
index c07d6f8..655f313 100644
--- a/daemon/face/ethernet-channel.cpp
+++ b/daemon/face/ethernet-channel.cpp
@@ -101,8 +101,9 @@
 EthernetChannel::asyncRead(const FaceCreatedCallback& onFaceCreated,
                            const FaceCreationFailedCallback& onReceiveFailed)
 {
-  m_socket.async_wait(boost::asio::posix::stream_descriptor::wait_read,
-                      [=] (const auto& e) { this->handleRead(e, onFaceCreated, onReceiveFailed); });
+  m_socket.async_wait(boost::asio::posix::stream_descriptor::wait_read, [=] (const auto& e) {
+    handleRead(e, onFaceCreated, onReceiveFailed);
+  });
 }
 
 void
diff --git a/daemon/face/ethernet-factory.cpp b/daemon/face/ethernet-factory.cpp
index f7fb63f..9ffd16e 100644
--- a/daemon/face/ethernet-factory.cpp
+++ b/daemon/face/ethernet-factory.cpp
@@ -26,7 +26,6 @@
 #include "ethernet-factory.hpp"
 #include "generic-link-service.hpp"
 #include "multicast-ethernet-transport.hpp"
-#include "pcap-helper.hpp"
 
 #include <boost/range/adaptors.hpp>
 #include <boost/range/algorithm/copy.hpp>
@@ -170,13 +169,13 @@
                               const FaceCreationFailedCallback& onFailure)
 {
   if (!req.localUri || req.localUri->getScheme() != "dev") {
-    NFD_LOG_TRACE("Cannot create unicast Ethernet face without dev:// LocalUri");
+    NFD_LOG_TRACE("createFace: dev:// LocalUri required");
     onFailure(406, "Creation of unicast Ethernet faces requires a LocalUri with dev:// scheme");
     return;
   }
 
   if (req.params.persistency == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND) {
-    NFD_LOG_TRACE("createFace does not support FACE_PERSISTENCY_ON_DEMAND");
+    NFD_LOG_TRACE("createFace: unsupported FacePersistency");
     onFailure(406, "Outgoing Ethernet faces do not support on-demand persistency");
     return;
   }
@@ -185,14 +184,14 @@
   std::string localEndpoint(req.localUri->getHost());
 
   if (remoteEndpoint.isMulticast()) {
-    NFD_LOG_TRACE("createFace does not support multicast faces");
+    NFD_LOG_TRACE("createFace: unsupported multicast endpoint");
     onFailure(406, "Cannot create multicast Ethernet faces");
     return;
   }
 
   if (req.params.wantLocalFields) {
     // Ethernet faces are never local
-    NFD_LOG_TRACE("createFace cannot create non-local face with local fields enabled");
+    NFD_LOG_TRACE("createFace: cannot create non-local face with local fields enabled");
     onFailure(406, "Local fields can only be enabled on faces with local scope");
     return;
   }
@@ -258,7 +257,9 @@
   connectFaceClosedSignal(*face, [this, key] { m_mcastFaces.erase(key); });
 
   auto channelIt = m_channels.find(netif.getName());
-  face->setChannel(channelIt != m_channels.end() ? channelIt->second : nullptr);
+  if (channelIt != m_channels.end()) {
+    face->setChannel(channelIt->second);
+  }
 
   return face;
 }
@@ -332,15 +333,11 @@
   NFD_LOG_DEBUG("Creating multicast face on " << netif.getName());
   shared_ptr<Face> face;
   try {
-    face = this->createMulticastFace(netif, m_mcastConfig.group);
+    face = createMulticastFace(netif, m_mcastConfig.group);
   }
-  catch (const EthernetTransport::Error& e) {
+  catch (const std::runtime_error& e) {
     NFD_LOG_WARN("Cannot create multicast face on " << netif.getName() << ": " << e.what());
-    return nullptr;
-  }
-  catch (const PcapHelper::Error& e) {
-    NFD_LOG_WARN("Cannot create multicast face on " << netif.getName() << ": " << e.what());
-    return nullptr;
+    return nullptr; // not a fatal error
   }
 
   if (face->getId() == INVALID_FACEID) {
diff --git a/daemon/face/ethernet-factory.hpp b/daemon/face/ethernet-factory.hpp
index 607c965..d8d49c9 100644
--- a/daemon/face/ethernet-factory.hpp
+++ b/daemon/face/ethernet-factory.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  Regents of the University of California,
+ * Copyright (c) 2014-2023,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -28,10 +28,12 @@
 
 #include "protocol-factory.hpp"
 #include "ethernet-channel.hpp"
+#include "network-predicate.hpp"
 
 namespace nfd::face {
 
-/** \brief Protocol factory for Ethernet.
+/**
+ * \brief Protocol factory for Ethernet.
  */
 class EthernetFactory final : public ProtocolFactory
 {
@@ -48,7 +50,7 @@
    * If this method is called twice with the same endpoint, only one channel
    * will be created. The second call will just return the existing channel.
    *
-   * \return always a valid pointer to a EthernetChannel object, an exception
+   * \return Always a valid pointer to a EthernetChannel object, an exception
    *         is thrown if it cannot be created.
    * \throw PcapHelper::Error channel creation failed
    */
@@ -65,7 +67,7 @@
    * \param localEndpoint local network interface
    * \param group multicast group address
    *
-   * \throw EthernetTransport::Error transport creation fails
+   * \throw std::runtime_error %Face creation failed
    */
   shared_ptr<Face>
   createMulticastFace(const ndn::net::NetworkInterface& localEndpoint,
@@ -84,14 +86,16 @@
   std::vector<shared_ptr<const Channel>>
   doGetChannels() const final;
 
-  /** \brief Create EthernetChannel on \p netif if requested by \p m_unicastConfig.
-   *  \return new or existing channel, or nullptr if no channel should be created
+  /**
+   * \brief Create EthernetChannel on \p netif if requested by \p m_unicastConfig.
+   * \return New or existing channel, or nullptr if no channel should be created.
    */
   shared_ptr<EthernetChannel>
   applyUnicastConfigToNetif(const shared_ptr<const ndn::net::NetworkInterface>& netif);
 
-  /** \brief Create Ethernet multicast face on \p netif if requested by \p m_mcastConfig.
-   *  \return new or existing face, or nullptr if no face should be created
+  /**
+   * \brief Create Ethernet multicast face on \p netif if requested by \p m_mcastConfig.
+   * \return New or existing face, or nullptr if no face should be created.
    */
   shared_ptr<Face>
   applyMcastConfigToNetif(const ndn::net::NetworkInterface& netif);
@@ -100,7 +104,8 @@
   applyConfig(const FaceSystem::ConfigContext& context);
 
 private:
-  std::map<std::string, shared_ptr<EthernetChannel>> m_channels; ///< ifname => channel
+  // ifname => channel
+  std::map<std::string, shared_ptr<EthernetChannel>> m_channels;
 
   struct UnicastConfig
   {
diff --git a/daemon/face/face-system.cpp b/daemon/face/face-system.cpp
index 7ab9879..bcc8a5e 100644
--- a/daemon/face/face-system.cpp
+++ b/daemon/face/face-system.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  Regents of the University of California,
+ * Copyright (c) 2014-2023,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -24,9 +24,8 @@
  */
 
 #include "face-system.hpp"
-#include "protocol-factory.hpp"
 #include "netdev-bound.hpp"
-#include "common/global.hpp"
+#include "protocol-factory.hpp"
 #include "fw/face-table.hpp"
 
 namespace nfd::face {
@@ -71,14 +70,14 @@
 }
 
 ProtocolFactory*
-FaceSystem::getFactoryById(const std::string& id)
+FaceSystem::getFactoryById(const std::string& id) const
 {
   auto found = m_factories.find(id);
   return found == m_factories.end() ? nullptr : found->second.get();
 }
 
 ProtocolFactory*
-FaceSystem::getFactoryByScheme(const std::string& scheme)
+FaceSystem::getFactoryByScheme(const std::string& scheme) const
 {
   auto found = m_factoryByScheme.find(scheme);
   return found == m_factoryByScheme.end() ? nullptr : found->second;
diff --git a/daemon/face/face-system.hpp b/daemon/face/face-system.hpp
index d7d534b..36148df 100644
--- a/daemon/face/face-system.hpp
+++ b/daemon/face/face-system.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  Regents of the University of California,
+ * Copyright (c) 2014-2023,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -26,7 +26,6 @@
 #ifndef NFD_DAEMON_FACE_FACE_SYSTEM_HPP
 #define NFD_DAEMON_FACE_FACE_SYSTEM_HPP
 
-#include "network-predicate.hpp"
 #include "common/config-file.hpp"
 
 #include <ndn-cxx/net/network-address.hpp>
@@ -62,15 +61,17 @@
   [[nodiscard]] std::set<const ProtocolFactory*>
   listProtocolFactories() const;
 
-  /** \return ProtocolFactory for the specified registered factory id or nullptr if not found.
+  /**
+   * \return ProtocolFactory for the specified registered factory id or nullptr if not found.
    */
   ProtocolFactory*
-  getFactoryById(const std::string& id);
+  getFactoryById(const std::string& id) const;
 
-  /** \return ProtocolFactory for the specified FaceUri scheme or nullptr if not found.
+  /**
+   * \return ProtocolFactory for the specified FaceUri scheme or nullptr if not found.
    */
   ProtocolFactory*
-  getFactoryByScheme(const std::string& scheme);
+  getFactoryByScheme(const std::string& scheme) const;
 
   bool
   hasFactoryForScheme(const std::string& scheme) const;
diff --git a/daemon/face/netdev-bound.hpp b/daemon/face/netdev-bound.hpp
index 9c9aec3..68cbdc6 100644
--- a/daemon/face/netdev-bound.hpp
+++ b/daemon/face/netdev-bound.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  Regents of the University of California,
+ * Copyright (c) 2014-2023,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -26,6 +26,7 @@
 #ifndef NFD_DAEMON_FACE_NETDEV_BOUND_HPP
 #define NFD_DAEMON_FACE_NETDEV_BOUND_HPP
 
+#include "network-predicate.hpp"
 #include "protocol-factory.hpp"
 
 namespace nfd::face {
diff --git a/daemon/face/tcp-factory.cpp b/daemon/face/tcp-factory.cpp
index 072525d..5edbd57 100644
--- a/daemon/face/tcp-factory.cpp
+++ b/daemon/face/tcp-factory.cpp
@@ -152,13 +152,13 @@
                          const FaceCreationFailedCallback& onFailure)
 {
   if (req.localUri) {
-    NFD_LOG_TRACE("Cannot create unicast TCP face with LocalUri");
+    NFD_LOG_TRACE("createFace: unsupported LocalUri");
     onFailure(406, "Unicast TCP faces cannot be created with a LocalUri");
     return;
   }
 
   if (req.params.persistency == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND) {
-    NFD_LOG_TRACE("createFace does not support FACE_PERSISTENCY_ON_DEMAND");
+    NFD_LOG_TRACE("createFace: unsupported FacePersistency");
     onFailure(406, "Outgoing TCP faces do not support on-demand persistency");
     return;
   }
@@ -170,13 +170,13 @@
   BOOST_ASSERT(!endpoint.address().is_multicast());
 
   if (req.params.wantLocalFields && !endpoint.address().is_loopback()) {
-    NFD_LOG_TRACE("createFace cannot create non-local face with local fields enabled");
+    NFD_LOG_TRACE("createFace: cannot create non-local face with local fields enabled");
     onFailure(406, "Local fields can only be enabled on faces with local scope");
     return;
   }
 
   if (req.params.mtu) {
-    NFD_LOG_TRACE("createFace cannot create a TCP face with an overridden MTU");
+    NFD_LOG_TRACE("createFace: cannot create TCP face with overridden MTU");
     onFailure(406, "TCP faces do not support MTU overrides");
     return;
   }
diff --git a/daemon/face/tcp-factory.hpp b/daemon/face/tcp-factory.hpp
index 23969f8..e94f33a 100644
--- a/daemon/face/tcp-factory.hpp
+++ b/daemon/face/tcp-factory.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  Regents of the University of California,
+ * Copyright (c) 2014-2023,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -27,11 +27,13 @@
 #define NFD_DAEMON_FACE_TCP_FACTORY_HPP
 
 #include "protocol-factory.hpp"
+#include "network-predicate.hpp"
 #include "tcp-channel.hpp"
 
 namespace nfd::face {
 
-/** \brief Protocol factory for TCP over IPv4 and IPv6.
+/**
+ * \brief Protocol factory for TCP over IPv4 and IPv6.
  */
 class TcpFactory final : public ProtocolFactory
 {
@@ -44,12 +46,12 @@
   /**
    * \brief Create TCP-based channel using tcp::Endpoint.
    *
-   * tcp::Endpoint is really an alias for boost::asio::ip::tcp::endpoint.
+   * tcp::Endpoint is an alias for boost::asio::ip::tcp::endpoint.
    *
    * If this method is called twice with the same endpoint, only one channel
    * will be created. The second call will just return the existing channel.
    *
-   * \return always a valid pointer to a TcpChannel object, an exception
+   * \return Always a valid pointer to a TcpChannel object, an exception
    *         is thrown if it cannot be created.
    */
   shared_ptr<TcpChannel>
diff --git a/daemon/face/udp-channel.cpp b/daemon/face/udp-channel.cpp
index 5573306..a7515f4 100644
--- a/daemon/face/udp-channel.cpp
+++ b/daemon/face/udp-channel.cpp
@@ -97,10 +97,9 @@
 UdpChannel::waitForNewPeer(const FaceCreatedCallback& onFaceCreated,
                            const FaceCreationFailedCallback& onReceiveFailed)
 {
-  m_socket.async_receive_from(boost::asio::buffer(m_receiveBuffer), m_remoteEndpoint,
-                              [=] (auto&&... args) {
-                                this->handleNewPeer(std::forward<decltype(args)>(args)..., onFaceCreated, onReceiveFailed);
-                              });
+  m_socket.async_receive_from(boost::asio::buffer(m_receiveBuffer), m_remoteEndpoint, [=] (auto&&... args) {
+    handleNewPeer(std::forward<decltype(args)>(args)..., onFaceCreated, onReceiveFailed);
+  });
 }
 
 void
diff --git a/daemon/face/udp-factory.cpp b/daemon/face/udp-factory.cpp
index 2c22c4c..be3f87e 100644
--- a/daemon/face/udp-factory.cpp
+++ b/daemon/face/udp-factory.cpp
@@ -28,6 +28,7 @@
 #include "multicast-udp-transport.hpp"
 #include "common/global.hpp"
 
+#include <boost/container/static_vector.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/range/adaptor/map.hpp>
 #include <boost/range/algorithm/copy.hpp>
@@ -196,7 +197,7 @@
     providedSchemes.insert("udp4");
   }
   else if (providedSchemes.count("udp4") > 0) {
-    NFD_LOG_WARN("Cannot close udp4 channel after its creation");
+    NFD_LOG_WARN("Cannot close UDP channel after its creation");
   }
 
   if (enableV6) {
@@ -209,7 +210,7 @@
     providedSchemes.insert("udp6");
   }
   else if (providedSchemes.count("udp6") > 0) {
-    NFD_LOG_WARN("Cannot close udp6 channel after its creation");
+    NFD_LOG_WARN("Cannot close UDP channel after its creation");
   }
 
   if (m_mcastConfig.isEnabled != mcastConfig.isEnabled) {
@@ -250,13 +251,13 @@
                          const FaceCreationFailedCallback& onFailure)
 {
   if (req.localUri) {
-    NFD_LOG_TRACE("Cannot create unicast UDP face with LocalUri");
+    NFD_LOG_TRACE("createFace: unsupported LocalUri");
     onFailure(406, "Unicast UDP faces cannot be created with a LocalUri");
     return;
   }
 
   if (req.params.persistency == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND) {
-    NFD_LOG_TRACE("createFace does not support FACE_PERSISTENCY_ON_DEMAND");
+    NFD_LOG_TRACE("createFace: unsupported FacePersistency");
     onFailure(406, "Outgoing UDP faces do not support on-demand persistency");
     return;
   }
@@ -265,14 +266,14 @@
                          boost::lexical_cast<uint16_t>(req.remoteUri.getPort()));
 
   if (endpoint.address().is_multicast()) {
-    NFD_LOG_TRACE("createFace does not support multicast faces");
+    NFD_LOG_TRACE("createFace: unsupported multicast endpoint");
     onFailure(406, "Cannot create multicast UDP faces");
     return;
   }
 
   if (req.params.wantLocalFields) {
     // UDP faces are never local
-    NFD_LOG_TRACE("createFace cannot create non-local face with local fields enabled");
+    NFD_LOG_TRACE("createFace: cannot create non-local face with local fields enabled");
     onFailure(406, "Local fields can only be enabled on faces with local scope");
     return;
   }
@@ -377,7 +378,9 @@
                                 [isV4 = localEp.address().is_v4()] (const auto& it) {
                                   return it.first.address().is_v4() == isV4;
                                 });
-  face->setChannel(channelIt != m_channels.end() ? channelIt->second : nullptr);
+  if (channelIt != m_channels.end()) {
+    face->setChannel(channelIt->second);
+  }
 
   return face;
 }
@@ -423,7 +426,7 @@
     return {};
   }
 
-  std::vector<ip::address> addrs;
+  boost::container::static_vector<ip::address, 2> addrs;
   for (auto af : {net::AddressFamily::V4, net::AddressFamily::V6}) {
     auto addr = pickAddress(*netif, af);
     if (addr)
@@ -442,8 +445,14 @@
 
   std::vector<shared_ptr<Face>> faces;
   for (const auto& addr : addrs) {
-    auto face = this->createMulticastFace(*netif, addr,
-                                          addr.is_v4() ? m_mcastConfig.group : m_mcastConfig.groupV6);
+    shared_ptr<Face> face;
+    try {
+      face = createMulticastFace(*netif, addr, addr.is_v4() ? m_mcastConfig.group : m_mcastConfig.groupV6);
+    }
+    catch (const std::runtime_error& e) {
+      NFD_LOG_WARN("Cannot create multicast face on " << addr << ": " << e.what());
+      continue; // not a fatal error
+    }
     if (face->getId() == INVALID_FACEID) {
       // new face: register with forwarding
       this->addFace(face);
diff --git a/daemon/face/udp-factory.hpp b/daemon/face/udp-factory.hpp
index 9144a7a..ca697e7 100644
--- a/daemon/face/udp-factory.hpp
+++ b/daemon/face/udp-factory.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  Regents of the University of California,
+ * Copyright (c) 2014-2023,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -27,11 +27,13 @@
 #define NFD_DAEMON_FACE_UDP_FACTORY_HPP
 
 #include "protocol-factory.hpp"
+#include "network-predicate.hpp"
 #include "udp-channel.hpp"
 
 namespace nfd::face {
 
-/** \brief Protocol factory for UDP over IPv4 and IPv6.
+/**
+ * \brief Protocol factory for UDP over IPv4 and IPv6.
  */
 class UdpFactory final : public ProtocolFactory
 {
@@ -51,7 +53,7 @@
   /**
    * \brief Create UDP-based channel using udp::Endpoint.
    *
-   * udp::Endpoint is really an alias for boost::asio::ip::udp::endpoint.
+   * udp::Endpoint is an alias for boost::asio::ip::udp::endpoint.
    *
    * If this method is called twice with the same endpoint, only one channel
    * will be created. The second call will just return the existing channel.
@@ -59,7 +61,7 @@
    * If a multicast face is already active on the same local endpoint,
    * the creation fails and an exception is thrown.
    *
-   * \return always a valid pointer to a UdpChannel object, an exception
+   * \return Always a valid pointer to a UdpChannel object, an exception
    *         is thrown if it cannot be created.
    * \throw UdpFactory::Error
    */
@@ -70,7 +72,7 @@
   /**
    * \brief Create a multicast UDP face.
    *
-   * udp::Endpoint is really an alias for boost::asio::ip::udp::endpoint.
+   * udp::Endpoint is an alias for boost::asio::ip::udp::endpoint.
    *
    * The face will join the specified multicast group.
    *
@@ -85,9 +87,9 @@
    * \param localAddress the local IP address to which the face will be bound
    * \param multicastEndpoint the multicast endpoint (multicast group and port number)
    *
-   * \return always a valid shared pointer to the created face;
+   * \return Always a valid shared pointer to the created face;
    *         an exception is thrown if the face cannot be created.
-   * \throw UdpFactory::Error
+   * \throw std::runtime_error %Face creation failed
    */
   shared_ptr<Face>
   createMulticastFace(const ndn::net::NetworkInterface& netif,
@@ -107,13 +109,15 @@
   std::vector<shared_ptr<const Channel>>
   doGetChannels() const final;
 
-  /** \brief Create UDP multicast faces on \p netif if needed by \p m_mcastConfig.
-   *  \return list of faces (just created or already existing) on \p netif
+  /**
+   * \brief Create UDP multicast faces on \p netif if needed by \p m_mcastConfig.
+   * \return List of faces (just created or already existing) on \p netif.
    */
   std::vector<shared_ptr<Face>>
   applyMcastConfigToNetif(const shared_ptr<const ndn::net::NetworkInterface>& netif);
 
-  /** \brief Create and destroy UDP multicast faces according to \p m_mcastConfig.
+  /**
+   * \brief Create and destroy UDP multicast faces according to \p m_mcastConfig.
    */
   void
   applyMcastConfig(const FaceSystem::ConfigContext& context);
diff --git a/daemon/face/unix-stream-factory.hpp b/daemon/face/unix-stream-factory.hpp
index 8b044d4..76bbfc9 100644
--- a/daemon/face/unix-stream-factory.hpp
+++ b/daemon/face/unix-stream-factory.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  Regents of the University of California,
+ * Copyright (c) 2014-2023,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -31,7 +31,8 @@
 
 namespace nfd::face {
 
-/** \brief Protocol factory for stream-oriented Unix sockets.
+/**
+ * \brief Protocol factory for stream-oriented Unix sockets.
  */
 class UnixStreamFactory final : public ProtocolFactory
 {
@@ -48,7 +49,7 @@
    * will be created.  The second call will just retrieve the existing
    * channel.
    *
-   * \returns always a valid pointer to a UnixStreamChannel object,
+   * \returns Always a valid pointer to a UnixStreamChannel object,
    *          an exception will be thrown if the channel cannot be created.
    */
   shared_ptr<UnixStreamChannel>
diff --git a/daemon/face/websocket-factory.hpp b/daemon/face/websocket-factory.hpp
index 7804a62..73631e3 100644
--- a/daemon/face/websocket-factory.hpp
+++ b/daemon/face/websocket-factory.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  Regents of the University of California,
+ * Copyright (c) 2014-2023,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -31,7 +31,8 @@
 
 namespace nfd::face {
 
-/** \brief Protocol factory for WebSocket.
+/**
+ * \brief Protocol factory for WebSocket.
  */
 class WebSocketFactory final : public ProtocolFactory
 {
@@ -44,13 +45,13 @@
   /**
    * \brief Create WebSocket-based channel using websocket::Endpoint.
    *
-   * websocket::Endpoint is really an alias for boost::asio::ip::tcp::endpoint.
+   * websocket::Endpoint is an alias for boost::asio::ip::tcp::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.
    *
-   * \returns always a valid pointer to a WebSocketChannel object, an exception
+   * \returns Always a valid pointer to a WebSocketChannel object, an exception
    *          is thrown if it cannot be created.
    */
   shared_ptr<WebSocketChannel>