Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d1b64066c | ||
|
|
ed808ab2c9 | ||
|
|
7b0f4d1dd8 | ||
|
|
483d652d95 | ||
|
|
1c85221192 | ||
|
|
d397d7773c | ||
|
|
f91ab74da9 | ||
|
|
db9d37edab | ||
|
|
ce81230b09 | ||
|
|
802c092d1a | ||
|
|
e8f4246e13 | ||
|
|
cdb8f364c1 | ||
|
|
e06b627f31 | ||
|
|
d6474640da | ||
|
|
9dcfc40f21 | ||
|
|
2231ab526f | ||
|
|
eab7249b74 | ||
|
|
292e5e1436 | ||
|
|
5ae2877796 | ||
|
|
76c751ce80 | ||
|
|
e4eec13108 | ||
|
|
6ad890a098 | ||
|
|
8896478926 | ||
|
|
58ad5d4dd7 | ||
|
|
ce07470031 | ||
|
|
ebaf7b61fc | ||
|
|
083f778321 | ||
|
|
78926c9083 | ||
|
|
e84044e87d | ||
|
|
9427941781 | ||
|
|
13b76f0937 | ||
|
|
be40fb1e56 | ||
|
|
684fa0f89d | ||
|
|
0e97a97603 | ||
|
|
ff8b39746b | ||
|
|
35b16b1984 | ||
|
|
d0381c05a6 | ||
|
|
60d06d8770 | ||
|
|
0d6d036e4f | ||
|
|
addecff68b | ||
|
|
4d384fcce5 | ||
|
|
faf3eb0823 | ||
|
|
73b909a514 | ||
|
|
a4ff44ce6f | ||
|
|
90c20face8 | ||
|
|
baba2535e1 | ||
|
|
c3ea5a7886 | ||
|
|
2bda6f8d9c | ||
|
|
f08a7376e9 | ||
|
|
63df436e5f | ||
|
|
6b34ab9cec | ||
|
|
5d57f97fa7 | ||
|
|
9cfeecaa2f | ||
|
|
6f570de8d7 | ||
|
|
31367925c6 | ||
|
|
31c781e453 | ||
|
|
8269a05874 | ||
|
|
95ff7112aa | ||
|
|
c0273e3505 | ||
|
|
a788e25e70 | ||
|
|
3056e08c9e |
No files matched your search
@@ -25,7 +25,7 @@ ndnsec-keygen "/tmp/jenkins/$NODE_NAME" | ndnsec-install-cert -
|
||||
# Run unit tests
|
||||
# Core
|
||||
./build/unit-tests-core -l test_suite
|
||||
sudo ./build/unit-tests-core -t CorePrivilegeHelper -l test_suite
|
||||
sudo ./build/unit-tests-core -t TestPrivilegeHelper -l test_suite
|
||||
|
||||
# Daemon
|
||||
./build/unit-tests-daemon -l test_suite
|
||||
|
||||
@@ -18,10 +18,37 @@ class Derived : public Base
|
||||
|
||||
@conf
|
||||
def check_override(self):
|
||||
if self.check_cxx(msg='Checking for override specifier',
|
||||
fragment=OVERRIDE,
|
||||
features='cxx', mandatory=False):
|
||||
self.define('HAVE_CXX_OVERRIDE', 1)
|
||||
self.check_cxx(msg='Checking for override specifier',
|
||||
fragment=OVERRIDE,
|
||||
define_name='HAVE_CXX_OVERRIDE',
|
||||
features='cxx', mandatory=False)
|
||||
|
||||
STD_TO_STRING = '''
|
||||
#include <string>
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
std::string s = std::to_string(0);
|
||||
s = std::to_string(0l);
|
||||
s = std::to_string(0ll);
|
||||
s = std::to_string(0u);
|
||||
s = std::to_string(0ul);
|
||||
s = std::to_string(0ull);
|
||||
s = std::to_string(0.0f);
|
||||
s = std::to_string(0.0);
|
||||
s = std::to_string(0.0l);
|
||||
s.clear();
|
||||
return 0;
|
||||
}
|
||||
'''
|
||||
|
||||
@conf
|
||||
def check_std_to_string(self):
|
||||
self.check_cxx(msg='Checking for std::to_string',
|
||||
fragment=STD_TO_STRING,
|
||||
define_name='HAVE_STD_TO_STRING',
|
||||
features='cxx', mandatory=False)
|
||||
|
||||
def configure(conf):
|
||||
conf.check_override()
|
||||
conf.check_std_to_string()
|
||||
@@ -139,6 +139,7 @@ class ClangFlags(GccBasicFlags):
|
||||
flags['CXXFLAGS'] += ['-std=c++11',
|
||||
'-Wno-error=unneeded-internal-declaration', # Bug #1588
|
||||
'-Wno-error=deprecated-register',
|
||||
'-Wno-error=unused-local-typedef', # Bug #2657
|
||||
]
|
||||
if Utils.unversioned_sys_platform() == "darwin":
|
||||
flags['CXXFLAGS'] += ['-stdlib=libc++']
|
||||
|
||||
@@ -67,6 +67,11 @@ def options(opt):
|
||||
|
||||
def configure(conf):
|
||||
if (conf.options.with_pch and conf.env['COMPILER_CXX'] in PCH_COMPILER_OPTIONS.keys()):
|
||||
if Utils.unversioned_sys_platform() == "darwin" and conf.env['CXX_NAME'] == 'clang':
|
||||
version = tuple(int(i) for i in conf.env['CC_VERSION'])
|
||||
if version < (6, 1, 0):
|
||||
# Issue #2804
|
||||
return
|
||||
conf.env.WITH_PCH = True
|
||||
flags = PCH_COMPILER_OPTIONS[conf.env['COMPILER_CXX']]
|
||||
conf.env.CXXPCH_F = flags[0]
|
||||
|
||||
@@ -36,8 +36,8 @@ def checkWebsocket(self, **kw):
|
||||
|
||||
# Looking for the following:
|
||||
# static int const major_version = 0;
|
||||
# static int const minor_version = 3;
|
||||
# static int const patch_version = 0;
|
||||
# static int const minor_version = 5;
|
||||
# static int const patch_version = 1;
|
||||
|
||||
version = [None, None, None]
|
||||
|
||||
@@ -71,7 +71,7 @@ def checkWebsocket(self, **kw):
|
||||
Logs.warn(' git submodule init && git submodule update')
|
||||
Logs.warn('Otherwise, manually download and extract websocketpp library:')
|
||||
Logs.warn(' mkdir websocketpp')
|
||||
Logs.warn(' curl -L https://github.com/zaphoyd/websocketpp/tarball/4309749dd98937b8a7be5dc0bfe679ba201c5512 > websocket.tar.gz')
|
||||
Logs.warn(' curl -L https://github.com/zaphoyd/websocketpp/archive/0.5.1.tar.gz > websocket.tar.gz')
|
||||
Logs.warn(' tar zxf websocket.tar.gz -C websocketpp/ --strip 1')
|
||||
Logs.warn('Alternatively, WebSocket support can be disabled with --without-websocket')
|
||||
self.fatal("The configuration failed")
|
||||
|
||||
@@ -62,6 +62,7 @@ volunteers.
|
||||
|
||||
* Syed Obaid Amin <http://obaidamin.weebly.com/>
|
||||
* Vince Lehman <vslehman@memphis.edu>
|
||||
* Minsheng Zhang <mzhang4@memphis.edu>
|
||||
* Lan Wang <http://www.cs.memphis.edu/~lanwang/>
|
||||
|
||||
## Project contributors
|
||||
@@ -71,3 +72,4 @@ people who have reported bugs, submitted patches, and implemented new features
|
||||
in the library:
|
||||
|
||||
* Tai-Lin Chu <https://www.linkedin.com/pub/tai-lin-chu/55/5b2/669>
|
||||
* Spyridon Mastorakis <http://cs.ucla.edu/~mastorakis/>
|
||||
+16
-3
@@ -57,11 +57,12 @@
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <ndn-cxx/common.hpp>
|
||||
#include <ndn-cxx/interest.hpp>
|
||||
#include <ndn-cxx/data.hpp>
|
||||
#include <ndn-cxx/util/event-emitter.hpp> // deprecated
|
||||
#include <ndn-cxx/util/face-uri.hpp>
|
||||
#include <ndn-cxx/util/signal.hpp>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
@@ -80,7 +81,6 @@ using boost::noncopyable;
|
||||
using std::shared_ptr;
|
||||
using std::unique_ptr;
|
||||
using std::weak_ptr;
|
||||
using std::bad_weak_ptr;
|
||||
using std::make_shared;
|
||||
using std::enable_shared_from_this;
|
||||
|
||||
@@ -98,7 +98,7 @@ using ndn::Data;
|
||||
using ndn::Name;
|
||||
using ndn::Exclude;
|
||||
using ndn::Block;
|
||||
using ndn::util::EventEmitter; // deprecated
|
||||
using ndn::util::FaceUri;
|
||||
|
||||
namespace tlv {
|
||||
// Don't write "namespace tlv = ndn::tlv", because NFD can add other members into this namespace.
|
||||
@@ -111,4 +111,17 @@ namespace signal = ndn::util::signal;
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
// Some platforms are missing std::to_string (issue #2743)
|
||||
#ifndef HAVE_STD_TO_STRING
|
||||
namespace std {
|
||||
template<typename V>
|
||||
inline std::string
|
||||
to_string(const V& v)
|
||||
{
|
||||
return boost::lexical_cast<std::string>(v);
|
||||
}
|
||||
} // namespace std
|
||||
#endif // HAVE_STD_TO_STRING
|
||||
|
||||
|
||||
#endif // NFD_COMMON_HPP
|
||||
@@ -7,23 +7,17 @@ when they die.
|
||||
Initial setup
|
||||
-------------
|
||||
|
||||
Edit `net.named-data.nfd` and `net.named-data.nrd` correcting paths for `nfd` and `nfd`
|
||||
binaries, configuration file, and log files.
|
||||
Edit `net.named-data.nfd` correcting paths for `nfd` binary, configuration and log files.
|
||||
|
||||
# Copy launchd.plist for nfd (forwarding daemon)
|
||||
# Copy launchd.plist for NFD
|
||||
sudo cp net.named-data.nfd.plist /Library/LaunchDaemons/
|
||||
sudo chown root /Library/LaunchDaemons/net.named-data.nfd.plist
|
||||
|
||||
# Copy launchd.plist for nrd (RIB management daemon)
|
||||
sudo cp net.named-data.nrd.plist /Library/LaunchDaemons/
|
||||
sudo chown root /Library/LaunchDaemons/net.named-data.nrd.plist
|
||||
|
||||
### Assumptions in the default scripts
|
||||
|
||||
* `nfd` and `nrd` are installed into `/usr/local/bin`
|
||||
* `nfd` is installed into `/usr/local/bin`
|
||||
* Configuration file is `/usr/local/etc/ndn/nfd.conf`
|
||||
* `nfd` will be run as root
|
||||
* `nrd` will be run as user `ndn` and group `ndn`
|
||||
* Log files will be written to `/usr/local/var/log/ndn` folder, which is owned by user `ndn`
|
||||
|
||||
### Creating users
|
||||
@@ -62,29 +56,24 @@ Folder `/usr/local/var/log/ndn` should be created and assigned proper user and g
|
||||
sudo mkdir -p /usr/local/var/log/ndn
|
||||
sudo chown -R ndn:ndn /usr/local/var/log/ndn
|
||||
|
||||
`HOME` directories for `nfd` and `nrd` should be created and configured with correct
|
||||
library's config file and contain proper NDN security credentials for signing Data
|
||||
packets. This is necessary since default private key storage on OSX (`osx-keychain`) does
|
||||
not support non-interactive access, and file-based private key storage needs to be used:
|
||||
`HOME` directory for `nfd` should be created and configured with correct library's config file
|
||||
and contain proper NDN security credentials for signing Data packets. This is necessary since
|
||||
default private key storage on OSX (`osx-keychain`) does not support non-interactive access,
|
||||
and file-based private key storage needs to be used:
|
||||
|
||||
# Generate self-signed NDN certificate for nfd (owned by root)
|
||||
sudo mkdir -p /usr/local/var/lib/ndn/nfd/.ndn
|
||||
sudo sh -c 'echo tpm=file > /usr/local/var/lib/ndn/nfd/.ndn/client.conf'
|
||||
sudo HOME=/usr/local/var/lib/ndn/nfd ndnsec-keygen /localhost/daemons/nfd | \
|
||||
sudo HOME=/usr/local/var/lib/ndn/nfd ndnsec-install-cert -
|
||||
|
||||
# Generate self-signed NDN certificate for nrd (owned by ndn)
|
||||
sudo mkdir -p /usr/local/var/lib/ndn/nrd/.ndn
|
||||
sudo chown -R ndn:ndn /usr/local/var/lib/ndn/nrd
|
||||
sudo -u ndn -g ndn sh -c 'echo tpm=file > /usr/local/var/lib/ndn/nrd/.ndn/client.conf'
|
||||
sudo -u ndn -g ndn HOME=/usr/local/var/lib/ndn/nrd ndnsec-keygen /localhost/daemons/nrd | \
|
||||
sudo -u ndn -g ndn HOME=/usr/local/var/lib/ndn/nrd ndnsec-install-cert -
|
||||
# Create HOME and generate self-signed NDN certificate for nfd
|
||||
sudo -s -- ' \
|
||||
mkdir -p /usr/local/var/lib/ndn/nfd/.ndn; \
|
||||
export HOME=/usr/local/var/lib/ndn/nfd; \
|
||||
echo tpm=tpm-file > /usr/local/var/lib/ndn/nfd/.ndn/client.conf; \
|
||||
ndnsec-keygen /localhost/daemons/nfd | ndnsec-install-cert -; \
|
||||
'
|
||||
|
||||
### Configuring NFD's security
|
||||
|
||||
NFD sample configuration allows anybody to create faces, add nexthops to FIB,
|
||||
and set strategy choice for namespaces. While such settings could be a good start, it is
|
||||
generally not a good idea to run NFD in this mode.
|
||||
NFD sample configuration allows anybody to create faces, add nexthops to FIB, and set strategy
|
||||
choice for namespaces. While such settings could be a good start, it is generally not a good
|
||||
idea to run NFD in this mode.
|
||||
|
||||
While thorough discussion about security configuration of NFD is outside the scope of this
|
||||
document, at least the following change should be done to nfd.conf in authorize section:
|
||||
@@ -93,7 +82,7 @@ document, at least the following change should be done to nfd.conf in authorize
|
||||
{
|
||||
authorize
|
||||
{
|
||||
certfile certs/localhost_daemons_nrd.ndncert
|
||||
certfile certs/localhost_daemons_nfd.ndncert
|
||||
privileges
|
||||
{
|
||||
faces
|
||||
@@ -114,25 +103,25 @@ document, at least the following change should be done to nfd.conf in authorize
|
||||
}
|
||||
|
||||
While this configuration still allows management of faces and updating strategy choice by
|
||||
anybody, only NFD's RIB Manager Daemon (`nrd`) is allowed to manage FIB.
|
||||
anybody, only NFD's RIB Manager (i.e., NFD itself) is allowed to manage FIB.
|
||||
|
||||
As the final step to make this configuration work, nrd's self-signed certificate needs to
|
||||
be exported into `localhost_daemons_nrd.ndncert` file:
|
||||
As the final step to make this configuration work, NFD's self-signed certificate needs to
|
||||
be exported into `localhost_daemons_nfd.ndncert` file:
|
||||
|
||||
sudo mkdir /usr/local/etc/ndn/certs
|
||||
sudo sh -c 'sudo -u ndn -g ndn HOME=/usr/local/var/lib/ndn/nrd \
|
||||
ndnsec-dump-certificate -i /localhost/daemons/nrd \
|
||||
> /usr/local/etc/ndn/certs/localhost_daemons_nrd.ndncert'
|
||||
sudo -s -- '\
|
||||
mkdir -p /usr/local/etc/ndn/certs || true; \
|
||||
export HOME=/usr/local/var/lib/ndn/nfd; \
|
||||
ndnsec-dump-certificate -i /localhost/daemons/nfd > \
|
||||
/usr/local/etc/ndn/certs/localhost_daemons_nfd.ndncert; \
|
||||
'
|
||||
|
||||
|
||||
Enable auto-start
|
||||
-----------------
|
||||
|
||||
sudo launchctl load -w /Library/LaunchDaemons/net.named-data.nfd.plist
|
||||
sudo launchctl load -w /Library/LaunchDaemons/net.named-data.nrd.plist
|
||||
|
||||
Disable auto-start
|
||||
------------------
|
||||
|
||||
sudo launchctl unload -w /Library/LaunchDaemons/net.named-data.nfd.plist
|
||||
sudo launchctl unload -w /Library/LaunchDaemons/net.named-data.nrd.plist
|
||||
@@ -1,25 +0,0 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
||||
"http://www.apple.com/DTDs/PropertyList-1.0.dtd" >
|
||||
<plist version='1.0'>
|
||||
<dict>
|
||||
<key>Label</key><string>net.named-data.nrd</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/usr/local/bin/nrd</string>
|
||||
<string>--config</string>
|
||||
<string>/usr/local/etc/ndn/nfd.conf</string>
|
||||
</array>
|
||||
<key>UserName</key><string>ndn</string>
|
||||
<key>GroupName</key><string>ndn</string>
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>HOME</key><string>/usr/local/var/lib/ndn/nrd</string>
|
||||
</dict>
|
||||
<key>Debug</key><true/>
|
||||
<key>Disabled</key><true/>
|
||||
<key>KeepAlive</key><true/>
|
||||
<key>StandardErrorPath</key><string>/usr/local/var/log/ndn/nrd.log</string>
|
||||
<key>ProcessType</key><string>Background</string>
|
||||
</dict>
|
||||
</plist>
|
||||
+26
-45
@@ -8,26 +8,18 @@ when they die.
|
||||
Initial setup
|
||||
-------------
|
||||
|
||||
Edit `nfd.conf` and `nrd.conf` correcting paths for `nfd` and `nfd` binaries,
|
||||
configuration file, and log files.
|
||||
* Edit `nfd.conf` correcting paths for `nfd` binary, configuration and log files.
|
||||
|
||||
# Copy upstart config file for nfd (forwarding daemon)
|
||||
sudo cp nfd.conf /etc/init/
|
||||
* Copy upstart config file for NFD
|
||||
|
||||
# Copy upstart config file for nrd (RIB management daemon)
|
||||
sudo cp nrd.conf /etc/init/
|
||||
|
||||
# Copy upstart config file for nfd-watcher (will restart NFD when network change detected)
|
||||
sudo cp nfd-watcher.conf /etc/init/
|
||||
sudo cp nfd.conf /etc/init/
|
||||
|
||||
### Assumptions in the default scripts
|
||||
|
||||
* `nfd` and `nrd` are installed into `/usr/local/bin`
|
||||
* `nfd` is installed into `/usr/local/bin`
|
||||
* Configuration file is `/usr/local/etc/ndn/nfd.conf`
|
||||
* `nfd` will be run as root
|
||||
* `nrd` will be run as user `ndn` and group `ndn`
|
||||
* Log files will be written to `/usr/local/var/log/ndn` folder, which is owned by user `ndn`
|
||||
* Whenever network connectivity changes, both `nfd` and `nrd` are restarted
|
||||
|
||||
### Creating users
|
||||
|
||||
@@ -53,19 +45,15 @@ Folder `/usr/local/var/log/ndn` should be created and assigned proper user and g
|
||||
sudo mkdir -p /usr/local/var/log/ndn
|
||||
sudo chown -R ndn:ndn /usr/local/var/log/ndn
|
||||
|
||||
`HOME` directories for `nfd` and `nrd` should be created prior to starting. This is
|
||||
necessary to manage unique security credentials for the deamons.
|
||||
`HOME` directory for `nfd` should be created prior to starting. This is necessary to manage
|
||||
unique security credentials for the deamon.
|
||||
|
||||
# Create HOME and generate self-signed NDN certificate for nfd
|
||||
sudo mkdir -p /usr/local/var/lib/ndn/nfd/.ndn
|
||||
sudo HOME=/usr/local/var/lib/ndn/nfd ndnsec-keygen /localhost/daemons/nfd | \
|
||||
sudo HOME=/usr/local/var/lib/ndn/nfd ndnsec-install-cert -
|
||||
|
||||
# Create HOME and generate self-signed NDN certificate for nrd
|
||||
sudo mkdir -p /usr/local/var/lib/ndn/nrd/.ndn
|
||||
sudo chown -R ndn:ndn /usr/local/var/lib/ndn/nrd
|
||||
sudo -u ndn -g ndn HOME=/usr/local/var/lib/ndn/nrd ndnsec-keygen /localhost/daemons/nrd | \
|
||||
sudo -u ndn -g ndn HOME=/usr/local/var/lib/ndn/nrd ndnsec-install-cert -
|
||||
sudo -s -- ' \
|
||||
mkdir -p /usr/local/var/lib/ndn/nfd/.ndn; \
|
||||
export HOME=/usr/local/var/lib/ndn/nfd; \
|
||||
ndnsec-keygen /localhost/daemons/nfd | ndnsec-install-cert -; \
|
||||
'
|
||||
|
||||
### Configuring NFD's security
|
||||
|
||||
@@ -81,7 +69,7 @@ section:
|
||||
{
|
||||
authorize
|
||||
{
|
||||
certfile certs/localhost_daemons_nrd.ndncert
|
||||
certfile certs/localhost_daemons_nfd.ndncert
|
||||
privileges
|
||||
{
|
||||
faces
|
||||
@@ -102,43 +90,36 @@ section:
|
||||
}
|
||||
|
||||
While this configuration still allows management of faces and updating strategy choice by
|
||||
anybody, only NFD's RIB Manager Daemon (`nrd`) is allowed to manage FIB.
|
||||
anybody, only NFD's RIB Manager (i.e., NFD itself) is allowed to manage FIB.
|
||||
|
||||
As the final step to make this configuration work, nrd's self-signed certificate needs to
|
||||
be exported into `localhost_daemons_nrd.ndncert` file:
|
||||
As the final step to make this configuration work, nfd's self-signed certificate needs to
|
||||
be exported into `localhost_daemons_nfd.ndncert` file:
|
||||
|
||||
sudo mkdir /usr/local/etc/ndn/certs
|
||||
sudo sh -c 'sudo -u ndn -g ndn HOME=/usr/local/var/lib/ndn/nrd \
|
||||
ndnsec-dump-certificate -i /localhost/daemons/nrd \
|
||||
> /usr/local/etc/ndn/certs/localhost_daemons_nrd.ndncert'
|
||||
sudo -s -- '\
|
||||
mkdir -p /usr/local/etc/ndn/certs || true; \
|
||||
export HOME=/usr/local/var/lib/ndn/nfd; \
|
||||
ndnsec-dump-certificate -i /localhost/daemons/nfd > \
|
||||
/usr/local/etc/ndn/certs/localhost_daemons_nfd.ndncert; \
|
||||
'
|
||||
|
||||
|
||||
Enable auto-start
|
||||
-----------------
|
||||
|
||||
After copying the provided upstart scripts, `nfd` and `nrd` daemons will automatically run
|
||||
after the reboot. To manually start them, use the following commands:
|
||||
After copying the provided upstart script, `nfd` daemon will automatically run after the reboot.
|
||||
To manually start them, use the following commands:
|
||||
|
||||
sudo start nfd
|
||||
# nrd will be automatically started by upstart
|
||||
|
||||
Note that an additional upstart job, ``nfd-watcher``, will automatically monitor for
|
||||
network connectivity changes, such as when network interface gets connected, disconnected,
|
||||
or IP addresses of the network interface get updated. When ``nfd-watcher`` detects the
|
||||
event, it will restart `nfd` and `nrd`.
|
||||
|
||||
Disable auto-start
|
||||
------------------
|
||||
|
||||
To stop `nrd` and `nfd` daemon, use the following commands:
|
||||
To stop `nfd` daemon, use the following commands:
|
||||
|
||||
sudo stop nfd
|
||||
# nrd will be automatically stopped by upstart
|
||||
|
||||
Note that as long as upstart files are present in `/etc/init/`, the daemons will
|
||||
automatically start after the reboot. To permanently stop `nfd` and `nrd` daemons, delete
|
||||
Note that as long as upstart files are present in `/etc/init/`, the daemon will
|
||||
automatically start after the reboot. To permanently stop `nfd` daemon, delete
|
||||
the upstart files:
|
||||
|
||||
sudo rm /etc/init/nfd.conf
|
||||
sudo rm /etc/init/nrd.conf
|
||||
sudo rm /etc/init/nfd-watcher.conf
|
||||
@@ -1,13 +0,0 @@
|
||||
# nfd-watcher.conf
|
||||
#
|
||||
# Restarting NDN Forwarding Daemon on network connectivity changes
|
||||
|
||||
start on (net-device-up or
|
||||
net-device-removed or
|
||||
net-device-changed)
|
||||
task
|
||||
|
||||
script
|
||||
status nfd | grep -q start/ || stop
|
||||
restart nfd
|
||||
end script
|
||||
@@ -14,4 +14,13 @@ env HOME=/usr/local/var/lib/ndn/nfd
|
||||
export HOME
|
||||
|
||||
exec /usr/local/bin/nfd --config /usr/local/etc/ndn/nfd.conf 2>> /usr/local/var/log/ndn/nfd.log
|
||||
|
||||
post-start script
|
||||
if [ -f /usr/local/etc/ndn/nfd-init.sh ]; then
|
||||
sleep 2 # post-start is executed just after nfd process starts, but there is no guarantee
|
||||
# that all initialization has been finished
|
||||
. /usr/local/etc/ndn/nfd-init.sh
|
||||
fi
|
||||
end script
|
||||
|
||||
post-stop exec sleep 2
|
||||
@@ -1,22 +0,0 @@
|
||||
# nrd.conf
|
||||
#
|
||||
# NDN RIB Manager Daemon
|
||||
|
||||
description "NDN RIB Manager Daemon"
|
||||
|
||||
start on started nfd
|
||||
stop on stopping nfd
|
||||
|
||||
respawn
|
||||
respawn limit unlimited
|
||||
|
||||
setuid ndn
|
||||
setgid ndn
|
||||
|
||||
pre-start exec sleep 2
|
||||
script
|
||||
export HOME=/usr/local/var/lib/ndn/nrd
|
||||
/usr/local/bin/nrd --config /usr/local/etc/ndn/nfd.conf 2>> /usr/local/var/log/ndn/nrd.log
|
||||
end script
|
||||
|
||||
post-stop exec sleep 2
|
||||
@@ -30,8 +30,6 @@
|
||||
|
||||
namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("ConfigFile");
|
||||
|
||||
void
|
||||
ConfigFile::throwErrorOnUnknownSection(const std::string& filename,
|
||||
const std::string& sectionName,
|
||||
@@ -108,6 +106,13 @@ ConfigFile::parse(std::istream& input, bool isDryRun, const std::string& filenam
|
||||
process(isDryRun, filename);
|
||||
}
|
||||
|
||||
void
|
||||
ConfigFile::parse(const ConfigSection& config, bool isDryRun, const std::string& filename)
|
||||
{
|
||||
m_global = config;
|
||||
process(isDryRun, filename);
|
||||
}
|
||||
|
||||
void
|
||||
ConfigFile::process(bool isDryRun, const std::string& filename)
|
||||
{
|
||||
|
||||
+11
-2
@@ -91,7 +91,7 @@ public:
|
||||
/**
|
||||
* \param input configuration (as a string) to parse
|
||||
* \param isDryRun true if performing a dry run of configuration, false otherwise
|
||||
* \param filename optional convenience argument to provide more detailed error messages
|
||||
* \param filename logical filename of the config file, can appear in error messages
|
||||
* \throws ConfigFile::Error if file not found
|
||||
* \throws ConfigFile::Error if parse error
|
||||
*/
|
||||
@@ -101,12 +101,21 @@ public:
|
||||
/**
|
||||
* \param input stream to parse
|
||||
* \param isDryRun true if performing a dry run of configuration, false otherwise
|
||||
* \param filename optional convenience argument to provide more detailed error messages
|
||||
* \param filename logical filename of the config file, can appear in error messages
|
||||
* \throws ConfigFile::Error if parse error
|
||||
*/
|
||||
void
|
||||
parse(std::istream& input, bool isDryRun, const std::string& filename);
|
||||
|
||||
/**
|
||||
* \param config ConfigSection that needs to be processed
|
||||
* \param isDryRun true if performing a dry run of configuration, false otherwise
|
||||
* \param filename logical filename of the config file, can appear in error messages
|
||||
* \throws ConfigFile::Error if parse error
|
||||
*/
|
||||
void
|
||||
parse(const ConfigSection& config, bool isDryRun, const std::string& filename);
|
||||
|
||||
private:
|
||||
|
||||
void
|
||||
|
||||
+13
-10
@@ -1,11 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014 Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -20,9 +21,10 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
*/
|
||||
|
||||
#include "global-io.hpp"
|
||||
#include <boost/thread/tss.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
@@ -32,13 +34,14 @@ void
|
||||
resetGlobalScheduler();
|
||||
} // namespace scheduler
|
||||
|
||||
static shared_ptr<boost::asio::io_service> g_ioService;
|
||||
|
||||
static boost::thread_specific_ptr<boost::asio::io_service> g_ioService;
|
||||
|
||||
boost::asio::io_service&
|
||||
getGlobalIoService()
|
||||
{
|
||||
if (!static_cast<bool>(g_ioService)) {
|
||||
g_ioService = make_shared<boost::asio::io_service>();
|
||||
if (g_ioService.get() == nullptr) {
|
||||
g_ioService.reset(new boost::asio::io_service());
|
||||
}
|
||||
return *g_ioService;
|
||||
}
|
||||
|
||||
+78
-82
@@ -1,11 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014 Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -20,10 +21,16 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
*/
|
||||
|
||||
#include "logger-factory.hpp"
|
||||
|
||||
#include <boost/range/adaptor/map.hpp>
|
||||
|
||||
#ifdef HAVE_CUSTOM_LOGGER
|
||||
#error "This file should not be compiled when custom logger is used"
|
||||
#endif
|
||||
|
||||
namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("LoggerFactory");
|
||||
@@ -65,44 +72,37 @@ LoggerFactory::parseLevel(const std::string& level)
|
||||
// std::cerr << m_levelNames.begin()->first << std::endl;
|
||||
|
||||
LevelMap::const_iterator levelIt = m_levelNames.find(upperLevel);
|
||||
if (levelIt != m_levelNames.end())
|
||||
{
|
||||
return levelIt->second;
|
||||
}
|
||||
try
|
||||
{
|
||||
uint32_t levelNo = boost::lexical_cast<uint32_t>(level);
|
||||
if (levelIt != m_levelNames.end()) {
|
||||
return levelIt->second;
|
||||
}
|
||||
try {
|
||||
uint32_t levelNo = boost::lexical_cast<uint32_t>(level);
|
||||
|
||||
if ((boost::lexical_cast<uint32_t>(LOG_NONE) <= levelNo &&
|
||||
levelNo <= boost::lexical_cast<uint32_t>(LOG_TRACE)) ||
|
||||
levelNo == LOG_ALL)
|
||||
{
|
||||
return static_cast<LogLevel>(levelNo);
|
||||
}
|
||||
if ((boost::lexical_cast<uint32_t>(LOG_NONE) <= levelNo &&
|
||||
levelNo <= boost::lexical_cast<uint32_t>(LOG_TRACE)) ||
|
||||
levelNo == LOG_ALL) {
|
||||
return static_cast<LogLevel>(levelNo);
|
||||
}
|
||||
catch (const boost::bad_lexical_cast& error)
|
||||
{
|
||||
}
|
||||
throw LoggerFactory::Error("Unsupported logging level \"" +
|
||||
level + "\"");
|
||||
}
|
||||
catch (const boost::bad_lexical_cast& error) {
|
||||
}
|
||||
|
||||
throw LoggerFactory::Error("Unsupported logging level \"" + level + "\"");
|
||||
}
|
||||
|
||||
LogLevel
|
||||
LoggerFactory::extractLevel(const ConfigSection& item, const std::string& key)
|
||||
{
|
||||
std::string levelString;
|
||||
try
|
||||
{
|
||||
levelString = item.get_value<std::string>();
|
||||
}
|
||||
catch (const boost::property_tree::ptree_error& error)
|
||||
{
|
||||
}
|
||||
try {
|
||||
levelString = item.get_value<std::string>();
|
||||
}
|
||||
catch (const boost::property_tree::ptree_error& error) {
|
||||
}
|
||||
|
||||
if (levelString.empty())
|
||||
{
|
||||
throw LoggerFactory::Error("No logging level found for option \"" + key + "\"");
|
||||
}
|
||||
if (levelString.empty()) {
|
||||
throw LoggerFactory::Error("No logging level found for option \"" + key + "\"");
|
||||
}
|
||||
|
||||
return parseLevel(levelString);
|
||||
}
|
||||
@@ -126,58 +126,51 @@ LoggerFactory::onConfig(const ConfigSection& section,
|
||||
// Forwarder WARN
|
||||
// }
|
||||
|
||||
if (!isDryRun)
|
||||
{
|
||||
ConfigSection::const_assoc_iterator item = section.find("default_level");
|
||||
if (item != section.not_found())
|
||||
{
|
||||
LogLevel level = extractLevel(item->second, "default_level");
|
||||
setDefaultLevel(level);
|
||||
}
|
||||
else
|
||||
{
|
||||
setDefaultLevel(LOG_INFO);
|
||||
}
|
||||
if (!isDryRun) {
|
||||
ConfigSection::const_assoc_iterator item = section.find("default_level");
|
||||
if (item != section.not_found()) {
|
||||
LogLevel level = extractLevel(item->second, "default_level");
|
||||
setDefaultLevel(level);
|
||||
}
|
||||
|
||||
for (ConfigSection::const_iterator item = section.begin();
|
||||
item != section.end();
|
||||
++item)
|
||||
{
|
||||
LogLevel level = extractLevel(item->second, item->first);
|
||||
|
||||
if (item->first == "default_level")
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerMap::iterator loggerIt = m_loggers.find(item->first);
|
||||
if (loggerIt == m_loggers.end())
|
||||
{
|
||||
NFD_LOG_DEBUG("Failed to configure logging level for module \"" <<
|
||||
item->first << "\" (module not found)");
|
||||
}
|
||||
else if (!isDryRun)
|
||||
{
|
||||
// std::cerr << "changing level for module " << item->first << " to " << level << std::endl;
|
||||
loggerIt->second.setLogLevel(level);
|
||||
}
|
||||
}
|
||||
else {
|
||||
setDefaultLevel(LOG_INFO);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& i : section) {
|
||||
LogLevel level = extractLevel(i.second, i.first);
|
||||
|
||||
if (i.first == "default_level") {
|
||||
// do nothing
|
||||
}
|
||||
else {
|
||||
std::unique_lock<std::mutex> lock(m_loggersGuard);
|
||||
LoggerMap::iterator loggerIt = m_loggers.find(i.first);
|
||||
if (loggerIt == m_loggers.end()) {
|
||||
lock.unlock();
|
||||
NFD_LOG_DEBUG("Failed to configure logging level for module \"" <<
|
||||
i.first << "\" (module not found)");
|
||||
}
|
||||
else if (!isDryRun) {
|
||||
loggerIt->second.setLogLevel(level);
|
||||
lock.unlock();
|
||||
NFD_LOG_DEBUG("Changing level for module " << i.first << " to " << level);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LoggerFactory::setDefaultLevel(LogLevel level)
|
||||
{
|
||||
// std::cerr << "changing to default_level " << level << std::endl;
|
||||
std::lock_guard<std::mutex> lock(m_loggersGuard);
|
||||
|
||||
m_defaultLevel = level;
|
||||
for (LoggerMap::iterator i = m_loggers.begin(); i != m_loggers.end(); ++i)
|
||||
{
|
||||
// std::cerr << "changing " << i->first << " to default " << m_defaultLevel << std::endl;
|
||||
i->second.setLogLevel(m_defaultLevel);
|
||||
}
|
||||
for (auto&& logger : m_loggers) {
|
||||
// std::cerr << "changing " << i->first << " to default " << m_defaultLevel << std::endl;
|
||||
logger.second.setLogLevel(m_defaultLevel);
|
||||
}
|
||||
}
|
||||
|
||||
Logger&
|
||||
@@ -192,6 +185,8 @@ LoggerFactory::createLogger(const std::string& moduleName)
|
||||
// std::cerr << "creating logger for " << moduleName
|
||||
// << " with level " << m_defaultLevel << std::endl;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_loggersGuard);
|
||||
|
||||
std::pair<LoggerMap::iterator, bool> loggerIt =
|
||||
m_loggers.insert(NameAndLogger(moduleName, Logger(moduleName, m_defaultLevel)));
|
||||
|
||||
@@ -201,11 +196,12 @@ LoggerFactory::createLogger(const std::string& moduleName)
|
||||
std::list<std::string>
|
||||
LoggerFactory::getModules() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_loggersGuard);
|
||||
|
||||
std::list<std::string> modules;
|
||||
for (LoggerMap::const_iterator i = m_loggers.begin(); i != m_loggers.end(); ++i)
|
||||
{
|
||||
modules.push_back(i->first);
|
||||
}
|
||||
for (const auto& loggerName : m_loggers | boost::adaptors::map_keys) {
|
||||
modules.push_back(loggerName);
|
||||
}
|
||||
|
||||
return modules;
|
||||
}
|
||||
|
||||
+16
-7
@@ -1,11 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014 Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -20,12 +21,17 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
*/
|
||||
|
||||
#ifndef NFD_CORE_LOGGER_FACTORY_HPP
|
||||
#define NFD_CORE_LOGGER_FACTORY_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#ifdef HAVE_CUSTOM_LOGGER
|
||||
#include "custom-logger-factory.hpp"
|
||||
#else
|
||||
|
||||
#include "config-file.hpp"
|
||||
#include "logger.hpp"
|
||||
|
||||
@@ -95,6 +101,7 @@ private:
|
||||
typedef std::pair<std::string, Logger> NameAndLogger;
|
||||
|
||||
LoggerMap m_loggers;
|
||||
mutable std::mutex m_loggersGuard;
|
||||
|
||||
LogLevel m_defaultLevel;
|
||||
};
|
||||
@@ -107,4 +114,6 @@ LoggerFactory::getDefaultLevel() const
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // HAVE_CUSTOM_LOGGER
|
||||
|
||||
#endif // NFD_CORE_LOGGER_FACTORY_HPP
|
||||
@@ -24,6 +24,11 @@
|
||||
*/
|
||||
|
||||
#include "logger.hpp"
|
||||
|
||||
#ifdef HAVE_CUSTOM_LOGGER
|
||||
#error "This file should not be compiled when custom logger is used"
|
||||
#endif
|
||||
|
||||
#include <ndn-cxx/util/time.hpp>
|
||||
#include <cinttypes>
|
||||
#include <stdio.h>
|
||||
@@ -31,6 +36,8 @@
|
||||
|
||||
namespace nfd {
|
||||
|
||||
std::mutex g_logMutex;
|
||||
|
||||
Logger::Logger(const std::string& name, LogLevel level)
|
||||
: m_moduleName(name)
|
||||
, m_enabledLogLevel(level)
|
||||
|
||||
+22
-19
@@ -1,12 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -28,19 +28,25 @@
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#ifdef HAVE_CUSTOM_LOGGER
|
||||
#include "custom-logger.hpp"
|
||||
#else
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
/** \brief indicates a log level
|
||||
* \note This type is internal. Logger should be accessed through NFD_LOG_* macros.
|
||||
*/
|
||||
enum LogLevel {
|
||||
LOG_FATAL = -1, // fatal (will be logged unconditionally)
|
||||
LOG_NONE = 0, // no messages
|
||||
LOG_ERROR = 1, // serious error messages
|
||||
LOG_WARN = 2, // warning messages
|
||||
LOG_INFO = 3, // informational messages
|
||||
LOG_DEBUG = 4, // debug messages
|
||||
LOG_TRACE = 5, // trace messages (most verbose)
|
||||
// LOG_FATAL is not a level and is logged unconditionally
|
||||
LOG_ALL = 255 // all messages
|
||||
};
|
||||
|
||||
@@ -57,10 +63,7 @@ public:
|
||||
bool
|
||||
isEnabled(LogLevel level) const
|
||||
{
|
||||
// std::cerr << m_moduleName <<
|
||||
// " enabled = " << m_enabledLogLevel
|
||||
// << " level = " << level << std::endl;
|
||||
return (m_enabledLogLevel >= level);
|
||||
return m_enabledLogLevel >= level;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -127,12 +130,15 @@ nfd::Logger& cls<specialization>::g_logger = nfd::LoggerFactory::create(name)
|
||||
template<> \
|
||||
nfd::Logger& cls<s1, s2>::g_logger = nfd::LoggerFactory::create(name)
|
||||
|
||||
extern std::mutex g_logMutex;
|
||||
|
||||
#define NFD_LOG(level, msg, expression) \
|
||||
do { \
|
||||
if (g_logger.isEnabled(::nfd::LOG_##level)) \
|
||||
if (g_logger.isEnabled(::nfd::LOG_##level)) { \
|
||||
std::lock_guard<std::mutex> lock(::nfd::g_logMutex); \
|
||||
std::clog << ::nfd::Logger::now() << " "#msg": " \
|
||||
<< "[" << g_logger << "] " << expression << "\n"; \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define NFD_LOG_TRACE(expression) NFD_LOG(TRACE, TRACE, expression)
|
||||
@@ -140,13 +146,10 @@ do { \
|
||||
#define NFD_LOG_INFO(expression) NFD_LOG(INFO, INFO, expression)
|
||||
#define NFD_LOG_WARN(expression) NFD_LOG(WARN, WARNING, expression)
|
||||
#define NFD_LOG_ERROR(expression) NFD_LOG(ERROR, ERROR, expression)
|
||||
|
||||
#define NFD_LOG_FATAL(expression) \
|
||||
do { \
|
||||
std::clog << ::nfd::Logger::now() << " FATAL: " \
|
||||
<< "[" << g_logger << "] " << expression << "\n"; \
|
||||
} while (false)
|
||||
#define NFD_LOG_FATAL(expression) NFD_LOG(FATAL, FATAL, expression)
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // HAVE_CUSTOM_LOGGER
|
||||
|
||||
#endif // NFD_CORE_LOGGER_HPP
|
||||
@@ -131,7 +131,9 @@ PrivilegeHelper::initialize(const std::string& userName, const std::string& grou
|
||||
s_normalUid = passwd.pw_uid;
|
||||
}
|
||||
#else
|
||||
throw Error("Dropping and raising privileges is not supported on this platform");
|
||||
if (!userName.empty() || !groupName.empty()) {
|
||||
throw Error("Dropping and raising privileges is not supported on this platform");
|
||||
}
|
||||
#endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
}
|
||||
|
||||
@@ -159,7 +161,7 @@ PrivilegeHelper::drop()
|
||||
|
||||
NFD_LOG_INFO("dropped to effective uid=" << ::geteuid() << " gid=" << ::getegid());
|
||||
#else
|
||||
throw Error("Dropping privileges is not supported on this platform");
|
||||
NFD_LOG_WARN("Dropping privileges is not supported on this platform");
|
||||
#endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
}
|
||||
|
||||
@@ -186,7 +188,7 @@ PrivilegeHelper::raise()
|
||||
}
|
||||
NFD_LOG_INFO("elevated to effective uid=" << ::geteuid() << " gid=" << ::getegid());
|
||||
#else
|
||||
throw Error("Elevating privileges is not supported on this platform");
|
||||
NFD_LOG_WARN("Elevating privileges is not supported on this platform");
|
||||
#endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
static void
|
||||
raise();
|
||||
|
||||
private:
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
static uid_t s_normalUid;
|
||||
static gid_t s_normalGid;
|
||||
|
||||
+19
-9
@@ -1,12 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -24,15 +24,25 @@
|
||||
*/
|
||||
|
||||
#include "random.hpp"
|
||||
#include <boost/thread/tss.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
static boost::random::mt19937 g_rng;
|
||||
static boost::thread_specific_ptr<boost::random::mt19937> g_rng;
|
||||
|
||||
boost::random::mt19937&
|
||||
getGlobalRng()
|
||||
{
|
||||
return g_rng;
|
||||
if (g_rng.get() == nullptr) {
|
||||
g_rng.reset(new boost::random::mt19937());
|
||||
}
|
||||
return *g_rng;
|
||||
}
|
||||
|
||||
void
|
||||
resetGlobalRng()
|
||||
{
|
||||
g_rng.reset();
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
+14
-11
@@ -1,12 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -26,17 +26,20 @@
|
||||
#include "scheduler.hpp"
|
||||
#include "global-io.hpp"
|
||||
|
||||
#include <boost/thread/tss.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace scheduler {
|
||||
|
||||
static shared_ptr<Scheduler> g_scheduler;
|
||||
static boost::thread_specific_ptr<Scheduler> g_scheduler;
|
||||
|
||||
inline Scheduler&
|
||||
Scheduler&
|
||||
getGlobalScheduler()
|
||||
{
|
||||
if (!static_cast<bool>(g_scheduler)) {
|
||||
g_scheduler = make_shared<Scheduler>(ref(getGlobalIoService()));
|
||||
if (g_scheduler.get() == nullptr) {
|
||||
g_scheduler.reset(new Scheduler(getGlobalIoService()));
|
||||
}
|
||||
|
||||
return *g_scheduler;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,10 +25,12 @@
|
||||
#ifndef NFD_DAEMON_FACE_CHANNEL_HPP
|
||||
#define NFD_DAEMON_FACE_CHANNEL_HPP
|
||||
|
||||
#include "face.hpp"
|
||||
#include "common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
class Face;
|
||||
|
||||
class Channel : noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -28,14 +28,13 @@
|
||||
|
||||
#include "face.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
#include "core/logger.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
class Unicast {};
|
||||
class Multicast {};
|
||||
struct Unicast {};
|
||||
struct Multicast {};
|
||||
|
||||
template<class Protocol, class Type = Unicast>
|
||||
template<class Protocol, class Addressing = Unicast>
|
||||
class DatagramFace : public Face
|
||||
{
|
||||
public:
|
||||
@@ -44,14 +43,9 @@ public:
|
||||
/** \brief Construct datagram face
|
||||
*
|
||||
* \param socket Protocol-specific socket for the created face
|
||||
* \param isOnDemand If true, the face can be closed after it remains
|
||||
* unused for a certain amount of time
|
||||
*/
|
||||
DatagramFace(const FaceUri& remoteUri, const FaceUri& localUri,
|
||||
const shared_ptr<typename protocol::socket>& socket,
|
||||
bool isOnDemand);
|
||||
|
||||
~DatagramFace() DECL_OVERRIDE;
|
||||
typename protocol::socket socket);
|
||||
|
||||
// from Face
|
||||
void
|
||||
@@ -68,18 +62,6 @@ public:
|
||||
size_t nBytesReceived,
|
||||
const boost::system::error_code& error);
|
||||
|
||||
/**
|
||||
* \brief Set m_hasBeenUsedRecently to false
|
||||
*/
|
||||
void
|
||||
resetRecentUsage();
|
||||
|
||||
bool
|
||||
hasBeenUsedRecently() const;
|
||||
|
||||
void
|
||||
setOnDemand(bool isOnDemand);
|
||||
|
||||
protected:
|
||||
void
|
||||
processErrorCode(const boost::system::error_code& error);
|
||||
@@ -99,97 +81,108 @@ protected:
|
||||
void
|
||||
closeSocket();
|
||||
|
||||
bool
|
||||
hasBeenUsedRecently() const;
|
||||
|
||||
/**
|
||||
* \brief Set m_hasBeenUsedRecently to false
|
||||
*/
|
||||
void
|
||||
resetRecentUsage();
|
||||
|
||||
protected:
|
||||
shared_ptr<typename protocol::socket> m_socket;
|
||||
uint8_t m_inputBuffer[ndn::MAX_NDN_PACKET_SIZE];
|
||||
bool m_hasBeenUsedRecently;
|
||||
typename protocol::socket m_socket;
|
||||
|
||||
NFD_LOG_INCLASS_DECLARE();
|
||||
|
||||
private:
|
||||
uint8_t m_inputBuffer[ndn::MAX_NDN_PACKET_SIZE];
|
||||
bool m_hasBeenUsedRecently;
|
||||
};
|
||||
|
||||
|
||||
template<class T, class U>
|
||||
inline
|
||||
DatagramFace<T, U>::DatagramFace(const FaceUri& remoteUri, const FaceUri& localUri,
|
||||
const shared_ptr<typename DatagramFace::protocol::socket>& socket,
|
||||
bool isOnDemand)
|
||||
: Face(remoteUri, localUri)
|
||||
, m_socket(socket)
|
||||
typename DatagramFace::protocol::socket socket)
|
||||
: Face(remoteUri, localUri, false, std::is_same<U, Multicast>::value)
|
||||
, m_socket(std::move(socket))
|
||||
{
|
||||
setOnDemand(isOnDemand);
|
||||
NFD_LOG_FACE_INFO("Creating face");
|
||||
|
||||
m_socket->async_receive(boost::asio::buffer(m_inputBuffer, ndn::MAX_NDN_PACKET_SIZE), 0,
|
||||
bind(&DatagramFace<T, U>::handleReceive, this, _1, _2));
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline
|
||||
DatagramFace<T, U>::~DatagramFace()
|
||||
{
|
||||
m_socket.async_receive(boost::asio::buffer(m_inputBuffer, ndn::MAX_NDN_PACKET_SIZE),
|
||||
bind(&DatagramFace<T, U>::handleReceive, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::sendInterest(const Interest& interest)
|
||||
{
|
||||
this->emitSignal(onSendInterest, interest);
|
||||
const Block& payload = interest.wireEncode();
|
||||
m_socket->async_send(boost::asio::buffer(payload.wire(), payload.size()),
|
||||
bind(&DatagramFace<T, U>::handleSend, this, _1, _2, payload));
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
// anything else should be done here?
|
||||
this->emitSignal(onSendInterest, interest);
|
||||
|
||||
const Block& payload = interest.wireEncode();
|
||||
m_socket.async_send(boost::asio::buffer(payload.wire(), payload.size()),
|
||||
bind(&DatagramFace<T, U>::handleSend, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred,
|
||||
payload));
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::sendData(const Data& data)
|
||||
{
|
||||
this->emitSignal(onSendData, data);
|
||||
const Block& payload = data.wireEncode();
|
||||
m_socket->async_send(boost::asio::buffer(payload.wire(), payload.size()),
|
||||
bind(&DatagramFace<T, U>::handleSend, this, _1, _2, payload));
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
// anything else should be done here?
|
||||
this->emitSignal(onSendData, data);
|
||||
|
||||
const Block& payload = data.wireEncode();
|
||||
m_socket.async_send(boost::asio::buffer(payload.wire(), payload.size()),
|
||||
bind(&DatagramFace<T, U>::handleSend, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred,
|
||||
payload));
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::close()
|
||||
{
|
||||
if (!m_socket->is_open())
|
||||
if (!m_socket.is_open())
|
||||
return;
|
||||
|
||||
NFD_LOG_INFO("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Closing face");
|
||||
NFD_LOG_FACE_INFO("Closing face");
|
||||
|
||||
closeSocket();
|
||||
fail("Face closed");
|
||||
this->fail("Face closed");
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::processErrorCode(const boost::system::error_code& error)
|
||||
{
|
||||
if (error == boost::asio::error::operation_aborted) // when socket is closed by someone
|
||||
if (error == boost::asio::error::operation_aborted) // when cancel() is called
|
||||
return;
|
||||
|
||||
// this should be unnecessary, but just in case
|
||||
if (!m_socket->is_open()) {
|
||||
if (!m_socket.is_open()) {
|
||||
this->fail("Tunnel closed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (error != boost::asio::error::eof)
|
||||
NFD_LOG_WARN("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Send or receive operation failed, closing face: "
|
||||
<< error.message());
|
||||
NFD_LOG_FACE_WARN("Send or receive operation failed: " << error.message());
|
||||
|
||||
closeSocket();
|
||||
|
||||
if (error == boost::asio::error::eof)
|
||||
this->fail("Tunnel closed");
|
||||
else
|
||||
this->fail("Send or receive operation failed: " + error.message());
|
||||
this->fail(error.message());
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
@@ -202,8 +195,7 @@ DatagramFace<T, U>::handleSend(const boost::system::error_code& error,
|
||||
if (error)
|
||||
return processErrorCode(error);
|
||||
|
||||
NFD_LOG_TRACE("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Successfully sent: " << nBytesSent << " bytes");
|
||||
NFD_LOG_FACE_TRACE("Successfully sent: " << nBytesSent << " bytes");
|
||||
this->getMutableCounters().getNOutBytes() += nBytesSent;
|
||||
}
|
||||
|
||||
@@ -214,9 +206,11 @@ DatagramFace<T, U>::handleReceive(const boost::system::error_code& error,
|
||||
{
|
||||
receiveDatagram(m_inputBuffer, nBytesReceived, error);
|
||||
|
||||
if (m_socket->is_open())
|
||||
m_socket->async_receive(boost::asio::buffer(m_inputBuffer, ndn::MAX_NDN_PACKET_SIZE), 0,
|
||||
bind(&DatagramFace<T, U>::handleReceive, this, _1, _2));
|
||||
if (m_socket.is_open())
|
||||
m_socket.async_receive(boost::asio::buffer(m_inputBuffer, ndn::MAX_NDN_PACKET_SIZE),
|
||||
bind(&DatagramFace<T, U>::handleReceive, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
@@ -225,37 +219,32 @@ DatagramFace<T, U>::receiveDatagram(const uint8_t* buffer,
|
||||
size_t nBytesReceived,
|
||||
const boost::system::error_code& error)
|
||||
{
|
||||
if (error || nBytesReceived == 0)
|
||||
if (error)
|
||||
return processErrorCode(error);
|
||||
|
||||
NFD_LOG_TRACE("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Received: " << nBytesReceived << " bytes");
|
||||
NFD_LOG_FACE_TRACE("Received: " << nBytesReceived << " bytes");
|
||||
this->getMutableCounters().getNInBytes() += nBytesReceived;
|
||||
|
||||
bool isOk = false;
|
||||
Block element;
|
||||
bool isOk = Block::fromBuffer(buffer, nBytesReceived, element);
|
||||
std::tie(isOk, element) = Block::fromBuffer(buffer, nBytesReceived);
|
||||
if (!isOk)
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Failed to parse incoming packet");
|
||||
NFD_LOG_FACE_WARN("Failed to parse incoming packet");
|
||||
// This message won't extend the face lifetime
|
||||
return;
|
||||
}
|
||||
|
||||
if (element.size() != nBytesReceived)
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Received datagram size and decoded "
|
||||
<< "element size don't match");
|
||||
NFD_LOG_FACE_WARN("Received datagram size and decoded element size don't match");
|
||||
// This message won't extend the face lifetime
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->decodeAndDispatchInput(element))
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Received unrecognized block of type ["
|
||||
<< element.type() << "]");
|
||||
NFD_LOG_FACE_WARN("Received unrecognized TLV block of type " << element.type());
|
||||
// This message won't extend the face lifetime
|
||||
return;
|
||||
}
|
||||
@@ -267,16 +256,19 @@ template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::keepFaceAliveUntilAllHandlersExecuted(const shared_ptr<Face>& face)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::closeSocket()
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
// use the non-throwing variants and ignore errors, if any
|
||||
boost::system::error_code error;
|
||||
m_socket->shutdown(protocol::socket::shutdown_both, error);
|
||||
m_socket->close(error);
|
||||
m_socket.shutdown(protocol::socket::shutdown_both, error);
|
||||
m_socket.close(error);
|
||||
// after this, handlers will be called with an error code
|
||||
|
||||
// ensure that the Face object is alive at least until all pending
|
||||
@@ -286,10 +278,10 @@ DatagramFace<T, U>::closeSocket()
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::setOnDemand(bool isOnDemand)
|
||||
inline bool
|
||||
DatagramFace<T, U>::hasBeenUsedRecently() const
|
||||
{
|
||||
Face::setOnDemand(isOnDemand);
|
||||
return m_hasBeenUsedRecently;
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
@@ -299,13 +291,6 @@ DatagramFace<T, U>::resetRecentUsage()
|
||||
m_hasBeenUsedRecently = false;
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline bool
|
||||
DatagramFace<T, U>::hasBeenUsedRecently() const
|
||||
{
|
||||
return m_hasBeenUsedRecently;
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_DATAGRAM_FACE_HPP
|
||||
@@ -25,13 +25,12 @@
|
||||
|
||||
#include "ethernet-face.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
#include "core/logger.hpp"
|
||||
|
||||
#include <pcap/pcap.h>
|
||||
|
||||
#include <cerrno> // for errno
|
||||
#include <cstdio> // for std::snprintf()
|
||||
#include <cstring> // for std::strerror() and std::strncpy()
|
||||
#include <stdio.h> // for snprintf()
|
||||
#include <arpa/inet.h> // for htons() and ntohs()
|
||||
#include <net/ethernet.h> // for struct ether_header
|
||||
#include <net/if.h> // for struct ifreq
|
||||
@@ -63,12 +62,12 @@ NFD_LOG_INIT("EthernetFace");
|
||||
|
||||
const time::nanoseconds EthernetFace::REASSEMBLER_LIFETIME = time::seconds(60);
|
||||
|
||||
EthernetFace::EthernetFace(const shared_ptr<boost::asio::posix::stream_descriptor>& socket,
|
||||
EthernetFace::EthernetFace(boost::asio::posix::stream_descriptor socket,
|
||||
const NetworkInterfaceInfo& interface,
|
||||
const ethernet::Address& address)
|
||||
: Face(FaceUri(address), FaceUri::fromDev(interface.name))
|
||||
: Face(FaceUri(address), FaceUri::fromDev(interface.name), false, true)
|
||||
, m_pcap(nullptr, pcap_close)
|
||||
, m_socket(socket)
|
||||
, m_socket(std::move(socket))
|
||||
#if defined(__linux__)
|
||||
, m_interfaceIndex(interface.index)
|
||||
#endif
|
||||
@@ -79,8 +78,7 @@ EthernetFace::EthernetFace(const shared_ptr<boost::asio::posix::stream_descripto
|
||||
, m_nDropped(0)
|
||||
#endif
|
||||
{
|
||||
NFD_LOG_INFO("Creating ethernet face on " << m_interfaceName << ": "
|
||||
<< m_srcAddress << " <--> " << m_destAddress);
|
||||
NFD_LOG_FACE_INFO("Creating face on " << m_interfaceName << "/" << m_srcAddress);
|
||||
pcapInit();
|
||||
|
||||
int fd = pcap_get_selectable_fd(m_pcap.get());
|
||||
@@ -90,43 +88,42 @@ EthernetFace::EthernetFace(const shared_ptr<boost::asio::posix::stream_descripto
|
||||
// need to duplicate the fd, otherwise both pcap_close()
|
||||
// and stream_descriptor::close() will try to close the
|
||||
// same fd and one of them will fail
|
||||
m_socket->assign(::dup(fd));
|
||||
m_socket.assign(::dup(fd));
|
||||
|
||||
m_interfaceMtu = getInterfaceMtu();
|
||||
NFD_LOG_DEBUG("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Interface MTU is: " << m_interfaceMtu);
|
||||
NFD_LOG_FACE_DEBUG("Interface MTU is: " << m_interfaceMtu);
|
||||
|
||||
m_slicer.reset(new ndnlp::Slicer(m_interfaceMtu));
|
||||
|
||||
char filter[100];
|
||||
std::snprintf(filter, sizeof(filter),
|
||||
"(ether proto 0x%x) && (ether dst %s) && (not ether src %s)",
|
||||
ethernet::ETHERTYPE_NDN,
|
||||
m_destAddress.toString().c_str(),
|
||||
m_srcAddress.toString().c_str());
|
||||
// std::snprintf not found in some environments
|
||||
// http://redmine.named-data.net/issues/2299 for more information
|
||||
snprintf(filter, sizeof(filter),
|
||||
"(ether proto 0x%x) && (ether dst %s) && (not ether src %s)",
|
||||
ethernet::ETHERTYPE_NDN,
|
||||
m_destAddress.toString().c_str(),
|
||||
m_srcAddress.toString().c_str());
|
||||
setPacketFilter(filter);
|
||||
|
||||
if (!m_destAddress.isBroadcast() && !joinMulticastGroup())
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Falling back to promiscuous mode");
|
||||
NFD_LOG_FACE_WARN("Falling back to promiscuous mode");
|
||||
pcap_set_promisc(m_pcap.get(), 1);
|
||||
}
|
||||
|
||||
m_socket->async_read_some(boost::asio::null_buffers(),
|
||||
bind(&EthernetFace::handleRead, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
EthernetFace::~EthernetFace()
|
||||
{
|
||||
m_socket.async_read_some(boost::asio::null_buffers(),
|
||||
bind(&EthernetFace::handleRead, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void
|
||||
EthernetFace::sendInterest(const Interest& interest)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
this->emitSignal(onSendInterest, interest);
|
||||
|
||||
ndnlp::PacketArray pa = m_slicer->slice(interest.wireEncode());
|
||||
for (const auto& packet : *pa) {
|
||||
sendPacket(packet);
|
||||
@@ -136,7 +133,10 @@ EthernetFace::sendInterest(const Interest& interest)
|
||||
void
|
||||
EthernetFace::sendData(const Data& data)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
this->emitSignal(onSendData, data);
|
||||
|
||||
ndnlp::PacketArray pa = m_slicer->slice(data.wireEncode());
|
||||
for (const auto& packet : *pa) {
|
||||
sendPacket(packet);
|
||||
@@ -149,13 +149,12 @@ EthernetFace::close()
|
||||
if (!m_pcap)
|
||||
return;
|
||||
|
||||
NFD_LOG_INFO("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Closing face");
|
||||
NFD_LOG_FACE_INFO("Closing face");
|
||||
|
||||
boost::system::error_code error;
|
||||
m_socket->cancel(error); // ignore errors
|
||||
m_socket->close(error); // ignore errors
|
||||
m_pcap.reset(nullptr);
|
||||
m_socket.cancel(error); // ignore errors
|
||||
m_socket.close(error); // ignore errors
|
||||
m_pcap.reset();
|
||||
|
||||
fail("Face closed");
|
||||
}
|
||||
@@ -184,8 +183,7 @@ EthernetFace::pcapInit()
|
||||
|
||||
if (pcap_setdirection(m_pcap.get(), PCAP_D_IN) < 0)
|
||||
// no need to throw on failure, BPF will filter unwanted packets anyway
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] pcap_setdirection failed: " << pcap_geterr(m_pcap.get()));
|
||||
NFD_LOG_FACE_WARN("pcap_setdirection failed: " << pcap_geterr(m_pcap.get()));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -211,12 +209,11 @@ EthernetFace::joinMulticastGroup()
|
||||
mr.mr_alen = m_destAddress.size();
|
||||
std::copy(m_destAddress.begin(), m_destAddress.end(), mr.mr_address);
|
||||
|
||||
if (::setsockopt(m_socket->native_handle(), SOL_PACKET,
|
||||
if (::setsockopt(m_socket.native_handle(), SOL_PACKET,
|
||||
PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == 0)
|
||||
return true; // success
|
||||
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] setsockopt(PACKET_ADD_MEMBERSHIP) failed: " << std::strerror(errno));
|
||||
NFD_LOG_FACE_WARN("setsockopt(PACKET_ADD_MEMBERSHIP) failed: " << std::strerror(errno));
|
||||
#endif
|
||||
|
||||
#if defined(SIOCADDMULTI)
|
||||
@@ -250,7 +247,7 @@ EthernetFace::joinMulticastGroup()
|
||||
static_assert(sizeof(ifr.ifr_addr) >= offsetof(sockaddr_dl, sdl_data) + ethernet::ADDR_LEN,
|
||||
"ifr_addr in struct ifreq is too small on this platform");
|
||||
#else
|
||||
int fd = m_socket->native_handle();
|
||||
int fd = m_socket.native_handle();
|
||||
|
||||
ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
|
||||
std::copy(m_destAddress.begin(), m_destAddress.end(), ifr.ifr_hwaddr.sa_data);
|
||||
@@ -262,8 +259,7 @@ EthernetFace::joinMulticastGroup()
|
||||
if (::ioctl(fd, SIOCADDMULTI, &ifr) == 0)
|
||||
return true; // success
|
||||
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] ioctl(SIOCADDMULTI) failed: " << std::strerror(errno));
|
||||
NFD_LOG_FACE_WARN("ioctl(SIOCADDMULTI) failed: " << std::strerror(errno));
|
||||
#endif
|
||||
|
||||
return false;
|
||||
@@ -274,8 +270,7 @@ EthernetFace::sendPacket(const ndn::Block& block)
|
||||
{
|
||||
if (!m_pcap)
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Trying to send on closed face");
|
||||
NFD_LOG_FACE_WARN("Trying to send on closed face");
|
||||
return fail("Face closed");
|
||||
}
|
||||
|
||||
@@ -309,8 +304,7 @@ EthernetFace::sendPacket(const ndn::Block& block)
|
||||
return fail("Failed to inject frame");
|
||||
}
|
||||
|
||||
NFD_LOG_TRACE("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Successfully sent: " << block.size() << " bytes");
|
||||
NFD_LOG_FACE_TRACE("Successfully sent: " << block.size() << " bytes");
|
||||
this->getMutableCounters().getNOutBytes() += block.size();
|
||||
}
|
||||
|
||||
@@ -332,7 +326,7 @@ EthernetFace::handleRead(const boost::system::error_code& error, size_t)
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName << "] Read timeout");
|
||||
NFD_LOG_FACE_WARN("Read timeout");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -344,34 +338,30 @@ EthernetFace::handleRead(const boost::system::error_code& error, size_t)
|
||||
ret = pcap_stats(m_pcap.get(), &ps);
|
||||
if (ret < 0)
|
||||
{
|
||||
NFD_LOG_DEBUG("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] pcap_stats failed: " << pcap_geterr(m_pcap.get()));
|
||||
NFD_LOG_FACE_DEBUG("pcap_stats failed: " << pcap_geterr(m_pcap.get()));
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
if (ps.ps_drop - m_nDropped > 0)
|
||||
NFD_LOG_DEBUG("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Detected " << ps.ps_drop - m_nDropped << " dropped packet(s)");
|
||||
NFD_LOG_FACE_DEBUG("Detected " << ps.ps_drop - m_nDropped << " dropped packet(s)");
|
||||
m_nDropped = ps.ps_drop;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_socket->async_read_some(boost::asio::null_buffers(),
|
||||
bind(&EthernetFace::handleRead, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
m_socket.async_read_some(boost::asio::null_buffers(),
|
||||
bind(&EthernetFace::handleRead, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void
|
||||
EthernetFace::processIncomingPacket(const pcap_pkthdr* header, const uint8_t* packet)
|
||||
{
|
||||
size_t length = header->caplen;
|
||||
if (length < ethernet::HDR_LEN + ethernet::MIN_DATA_LEN)
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Received frame is too short (" << length << " bytes)");
|
||||
return;
|
||||
}
|
||||
if (length < ethernet::HDR_LEN + ethernet::MIN_DATA_LEN) {
|
||||
NFD_LOG_FACE_WARN("Received frame is too short (" << length << " bytes)");
|
||||
return;
|
||||
}
|
||||
|
||||
const ether_header* eh = reinterpret_cast<const ether_header*>(packet);
|
||||
const ethernet::Address sourceAddress(eh->ether_shost);
|
||||
@@ -388,36 +378,31 @@ EthernetFace::processIncomingPacket(const pcap_pkthdr* header, const uint8_t* pa
|
||||
length -= ethernet::HDR_LEN;
|
||||
|
||||
/// \todo Reserve space in front and at the back of the underlying buffer
|
||||
Block fragment;
|
||||
bool isOk = Block::fromBuffer(packet, length, fragment);
|
||||
if (!isOk)
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Block received from " << sourceAddress.toString()
|
||||
<< " is invalid or too large to process");
|
||||
return;
|
||||
}
|
||||
bool isOk = false;
|
||||
Block fragmentBlock;
|
||||
std::tie(isOk, fragmentBlock) = Block::fromBuffer(packet, length);
|
||||
if (!isOk) {
|
||||
NFD_LOG_FACE_WARN("Block received from " << sourceAddress.toString()
|
||||
<< " is invalid or too large to process");
|
||||
return;
|
||||
}
|
||||
|
||||
NFD_LOG_TRACE("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Received: " << fragment.size() << " bytes from "
|
||||
<< sourceAddress.toString());
|
||||
this->getMutableCounters().getNInBytes() += fragment.size();
|
||||
NFD_LOG_FACE_TRACE("Received: " << fragmentBlock.size() << " bytes from "
|
||||
<< sourceAddress.toString());
|
||||
this->getMutableCounters().getNInBytes() += fragmentBlock.size();
|
||||
|
||||
Reassembler& reassembler = m_reassemblers[sourceAddress];
|
||||
if (!reassembler.pms)
|
||||
{
|
||||
// new sender, setup a PartialMessageStore for it
|
||||
reassembler.pms.reset(new ndnlp::PartialMessageStore);
|
||||
reassembler.pms->onReceive.connect(
|
||||
[this, sourceAddress] (const Block& block) {
|
||||
NFD_LOG_TRACE("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] All fragments received from " << sourceAddress.toString());
|
||||
if (!decodeAndDispatchInput(block))
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Received unrecognized TLV block of type " << block.type()
|
||||
<< " from " << sourceAddress.toString());
|
||||
});
|
||||
}
|
||||
if (!reassembler.pms) {
|
||||
// new sender, setup a PartialMessageStore for it
|
||||
reassembler.pms.reset(new ndnlp::PartialMessageStore);
|
||||
reassembler.pms->onReceive.connect(
|
||||
[this, sourceAddress] (const Block& block) {
|
||||
NFD_LOG_FACE_TRACE("All fragments received from " << sourceAddress.toString());
|
||||
if (!decodeAndDispatchInput(block))
|
||||
NFD_LOG_FACE_WARN("Received unrecognized TLV block of type " << block.type()
|
||||
<< " from " << sourceAddress.toString());
|
||||
});
|
||||
}
|
||||
|
||||
scheduler::cancel(reassembler.expireEvent);
|
||||
reassembler.expireEvent = scheduler::schedule(REASSEMBLER_LIFETIME,
|
||||
@@ -425,14 +410,14 @@ EthernetFace::processIncomingPacket(const pcap_pkthdr* header, const uint8_t* pa
|
||||
BOOST_VERIFY(m_reassemblers.erase(sourceAddress) == 1);
|
||||
});
|
||||
|
||||
try {
|
||||
reassembler.pms->receiveNdnlpData(fragment);
|
||||
}
|
||||
catch (const ndnlp::ParseError& e) {
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Received invalid NDNLP fragment from "
|
||||
<< sourceAddress.toString() << " : " << e.what());
|
||||
ndnlp::NdnlpData fragment;
|
||||
std::tie(isOk, fragment) = ndnlp::NdnlpData::fromBlock(fragmentBlock);
|
||||
if (!isOk) {
|
||||
NFD_LOG_FACE_WARN("Received invalid NDNLP fragment from " << sourceAddress.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
reassembler.pms->receive(fragment);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -446,18 +431,17 @@ EthernetFace::processErrorCode(const boost::system::error_code& error)
|
||||
if (error == boost::asio::error::eof)
|
||||
{
|
||||
msg = "Face closed";
|
||||
NFD_LOG_DEBUG("[id:" << getId() << ",endpoint:" << m_interfaceName << "] " << msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = "Receive operation failed: " + error.message();
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName << "] " << msg);
|
||||
NFD_LOG_FACE_WARN(msg);
|
||||
}
|
||||
fail(msg);
|
||||
}
|
||||
|
||||
size_t
|
||||
EthernetFace::getInterfaceMtu() const
|
||||
EthernetFace::getInterfaceMtu()
|
||||
{
|
||||
#ifdef SIOCGIFMTU
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
@@ -466,7 +450,7 @@ EthernetFace::getInterfaceMtu() const
|
||||
udp::socket sock(ref(getGlobalIoService()), udp::v4());
|
||||
int fd = sock.native_handle();
|
||||
#else
|
||||
int fd = m_socket->native_handle();
|
||||
int fd = m_socket.native_handle();
|
||||
#endif
|
||||
|
||||
ifreq ifr{};
|
||||
@@ -475,8 +459,7 @@ EthernetFace::getInterfaceMtu() const
|
||||
if (::ioctl(fd, SIOCGIFMTU, &ifr) == 0)
|
||||
return static_cast<size_t>(ifr.ifr_mtu);
|
||||
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Failed to get interface MTU: " << std::strerror(errno));
|
||||
NFD_LOG_FACE_WARN("Failed to get interface MTU: " << std::strerror(errno));
|
||||
#endif
|
||||
|
||||
return ethernet::MAX_DATA_LEN;
|
||||
|
||||
@@ -60,12 +60,10 @@ public:
|
||||
Error(const std::string& what) : Face::Error(what) {}
|
||||
};
|
||||
|
||||
EthernetFace(const shared_ptr<boost::asio::posix::stream_descriptor>& socket,
|
||||
EthernetFace(boost::asio::posix::stream_descriptor socket,
|
||||
const NetworkInterfaceInfo& interface,
|
||||
const ethernet::Address& address);
|
||||
|
||||
~EthernetFace() DECL_OVERRIDE;
|
||||
|
||||
/// send an Interest
|
||||
void
|
||||
sendInterest(const Interest& interest) DECL_OVERRIDE;
|
||||
@@ -138,7 +136,7 @@ private:
|
||||
* @brief Returns the MTU of the underlying network interface
|
||||
*/
|
||||
size_t
|
||||
getInterfaceMtu() const;
|
||||
getInterfaceMtu();
|
||||
|
||||
private:
|
||||
struct Reassembler
|
||||
@@ -148,7 +146,7 @@ private:
|
||||
};
|
||||
|
||||
unique_ptr<pcap_t, void(*)(pcap_t*)> m_pcap;
|
||||
shared_ptr<boost::asio::posix::stream_descriptor> m_socket;
|
||||
boost::asio::posix::stream_descriptor m_socket;
|
||||
|
||||
#if defined(__linux__)
|
||||
int m_interfaceIndex;
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
|
||||
namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("EthernetFactory");
|
||||
|
||||
shared_ptr<EthernetFace>
|
||||
EthernetFactory::createMulticastFace(const NetworkInterfaceInfo& interface,
|
||||
const ethernet::Address &address)
|
||||
@@ -44,8 +42,8 @@ EthernetFactory::createMulticastFace(const NetworkInterfaceInfo& interface,
|
||||
if (face)
|
||||
return face;
|
||||
|
||||
auto socket = make_shared<boost::asio::posix::stream_descriptor>(ref(getGlobalIoService()));
|
||||
face = make_shared<EthernetFace>(socket, interface, address);
|
||||
face = make_shared<EthernetFace>(boost::asio::posix::stream_descriptor(getGlobalIoService()),
|
||||
interface, address);
|
||||
|
||||
auto key = std::make_pair(interface.name, address);
|
||||
face->onFail.connectSingleShot([this, key] (const std::string& reason) {
|
||||
|
||||
+15
-51
@@ -25,14 +25,17 @@
|
||||
|
||||
#include "face.hpp"
|
||||
|
||||
#include <ndn-cxx/management/nfd-face-event-notification.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
Face::Face(const FaceUri& remoteUri, const FaceUri& localUri, bool isLocal)
|
||||
Face::Face(const FaceUri& remoteUri, const FaceUri& localUri, bool isLocal, bool isMultiAccess)
|
||||
: m_id(INVALID_FACEID)
|
||||
, m_isLocal(isLocal)
|
||||
, m_remoteUri(remoteUri)
|
||||
, m_localUri(localUri)
|
||||
, m_isLocal(isLocal)
|
||||
, m_isOnDemand(false)
|
||||
, m_isMultiAccess(isMultiAccess)
|
||||
, m_isFailed(false)
|
||||
{
|
||||
onReceiveInterest.connect([this] (const ndn::Interest&) { ++m_counters.getNInInterests(); });
|
||||
@@ -45,37 +48,6 @@ Face::~Face()
|
||||
{
|
||||
}
|
||||
|
||||
FaceId
|
||||
Face::getId() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
// this method is private and should be used only by the FaceTable
|
||||
void
|
||||
Face::setId(FaceId faceId)
|
||||
{
|
||||
m_id = faceId;
|
||||
}
|
||||
|
||||
void
|
||||
Face::setDescription(const std::string& description)
|
||||
{
|
||||
m_description = description;
|
||||
}
|
||||
|
||||
const std::string&
|
||||
Face::getDescription() const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
bool
|
||||
Face::isMultiAccess() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Face::isUp() const
|
||||
{
|
||||
@@ -126,22 +98,14 @@ void
|
||||
Face::copyStatusTo(FaceTraits& traits) const
|
||||
{
|
||||
traits.setFaceId(getId())
|
||||
.setRemoteUri(getRemoteUri().toString())
|
||||
.setLocalUri(getLocalUri().toString());
|
||||
|
||||
if (isLocal()) {
|
||||
traits.setFaceScope(ndn::nfd::FACE_SCOPE_LOCAL);
|
||||
}
|
||||
else {
|
||||
traits.setFaceScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
|
||||
}
|
||||
|
||||
if (isOnDemand()) {
|
||||
traits.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
|
||||
}
|
||||
else {
|
||||
traits.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
|
||||
}
|
||||
.setRemoteUri(getRemoteUri().toString())
|
||||
.setLocalUri(getLocalUri().toString())
|
||||
.setFaceScope(isLocal() ? ndn::nfd::FACE_SCOPE_LOCAL
|
||||
: ndn::nfd::FACE_SCOPE_NON_LOCAL)
|
||||
.setFacePersistency(isOnDemand() ? ndn::nfd::FACE_PERSISTENCY_ON_DEMAND
|
||||
: ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
|
||||
.setLinkType(isMultiAccess() ? ndn::nfd::LINK_TYPE_MULTI_ACCESS
|
||||
: ndn::nfd::LINK_TYPE_POINT_TO_POINT);
|
||||
}
|
||||
|
||||
template void
|
||||
@@ -154,11 +118,11 @@ ndn::nfd::FaceStatus
|
||||
Face::getFaceStatus() const
|
||||
{
|
||||
ndn::nfd::FaceStatus status;
|
||||
copyStatusTo(status);
|
||||
|
||||
copyStatusTo(status);
|
||||
this->getCounters().copyTo(status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
} //namespace nfd
|
||||
} // namespace nfd
|
||||
+105
-42
@@ -27,11 +27,10 @@
|
||||
#define NFD_DAEMON_FACE_FACE_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include "face-counters.hpp"
|
||||
|
||||
#include <ndn-cxx/util/face-uri.hpp>
|
||||
#include <ndn-cxx/management/nfd-face-status.hpp>
|
||||
#include <ndn-cxx/management/nfd-face-event-notification.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
@@ -52,7 +51,6 @@ const FaceId FACEID_NULL = 255;
|
||||
/// upper bound of reserved FaceIds
|
||||
const FaceId FACEID_RESERVED_MAX = 255;
|
||||
|
||||
using ndn::util::FaceUri;
|
||||
|
||||
/** \brief represents a face
|
||||
*/
|
||||
@@ -72,7 +70,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
Face(const FaceUri& remoteUri, const FaceUri& localUri, bool isLocal = false);
|
||||
Face(const FaceUri& remoteUri, const FaceUri& localUri,
|
||||
bool isLocal = false, bool isMultiAccess = false);
|
||||
|
||||
virtual
|
||||
~Face();
|
||||
@@ -112,27 +111,31 @@ public: // attributes
|
||||
FaceId
|
||||
getId() const;
|
||||
|
||||
/** \brief Set the description
|
||||
*
|
||||
* This is typically invoked by mgmt on set description command
|
||||
/** \brief Get the description
|
||||
*/
|
||||
virtual void
|
||||
setDescription(const std::string& description);
|
||||
|
||||
/// Get the description
|
||||
virtual const std::string&
|
||||
const std::string&
|
||||
getDescription() const;
|
||||
|
||||
/** \brief Set the face description
|
||||
*
|
||||
* This is typically invoked by management on set description command
|
||||
*/
|
||||
void
|
||||
setDescription(const std::string& description);
|
||||
|
||||
/** \brief Get whether face is connected to a local app
|
||||
*/
|
||||
bool
|
||||
isLocal() const;
|
||||
|
||||
/** \brief Get whether packets sent this Face may reach multiple peers
|
||||
*
|
||||
* In this base class this property is always false.
|
||||
/** \brief Get whether face is created on demand or explicitly via FaceManagement protocol
|
||||
*/
|
||||
virtual bool
|
||||
bool
|
||||
isOnDemand() const;
|
||||
|
||||
/** \brief Get whether packets sent by this face may reach multiple peers
|
||||
*/
|
||||
bool
|
||||
isMultiAccess() const;
|
||||
|
||||
/** \brief Get whether underlying communication is up
|
||||
@@ -142,11 +145,6 @@ public: // attributes
|
||||
virtual bool
|
||||
isUp() const;
|
||||
|
||||
/** \brief Get whether face is created on demand or explicitly via FaceManagement protocol
|
||||
*/
|
||||
bool
|
||||
isOnDemand() const;
|
||||
|
||||
const FaceCounters&
|
||||
getCounters() const;
|
||||
|
||||
@@ -171,51 +169,95 @@ public: // attributes
|
||||
virtual ndn::nfd::FaceStatus
|
||||
getFaceStatus() const;
|
||||
|
||||
protected:
|
||||
// this is a non-virtual method
|
||||
bool
|
||||
decodeAndDispatchInput(const Block& element);
|
||||
|
||||
FaceCounters&
|
||||
getMutableCounters();
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PROTECTED:
|
||||
void
|
||||
setOnDemand(bool isOnDemand);
|
||||
|
||||
protected:
|
||||
bool
|
||||
decodeAndDispatchInput(const Block& element);
|
||||
|
||||
/** \brief fail the face and raise onFail event if it's UP; otherwise do nothing
|
||||
*/
|
||||
void
|
||||
fail(const std::string& reason);
|
||||
|
||||
FaceCounters&
|
||||
getMutableCounters();
|
||||
|
||||
DECLARE_SIGNAL_EMIT(onReceiveInterest)
|
||||
DECLARE_SIGNAL_EMIT(onReceiveData)
|
||||
DECLARE_SIGNAL_EMIT(onSendInterest)
|
||||
DECLARE_SIGNAL_EMIT(onSendData)
|
||||
|
||||
private:
|
||||
// this method should be used only by the FaceTable
|
||||
void
|
||||
setId(FaceId faceId);
|
||||
|
||||
private:
|
||||
FaceId m_id;
|
||||
std::string m_description;
|
||||
bool m_isLocal; // for scoping purposes
|
||||
FaceCounters m_counters;
|
||||
FaceUri m_remoteUri;
|
||||
FaceUri m_localUri;
|
||||
const FaceUri m_remoteUri;
|
||||
const FaceUri m_localUri;
|
||||
const bool m_isLocal;
|
||||
bool m_isOnDemand;
|
||||
const bool m_isMultiAccess;
|
||||
bool m_isFailed;
|
||||
|
||||
// allow setting FaceId
|
||||
friend class FaceTable;
|
||||
};
|
||||
|
||||
inline FaceId
|
||||
Face::getId() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::setId(FaceId faceId)
|
||||
{
|
||||
m_id = faceId;
|
||||
}
|
||||
|
||||
inline const std::string&
|
||||
Face::getDescription() const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::setDescription(const std::string& description)
|
||||
{
|
||||
m_description = description;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Face::isLocal() const
|
||||
{
|
||||
return m_isLocal;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Face::isOnDemand() const
|
||||
{
|
||||
return m_isOnDemand;
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::setOnDemand(bool isOnDemand)
|
||||
{
|
||||
m_isOnDemand = isOnDemand;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Face::isMultiAccess() const
|
||||
{
|
||||
return m_isMultiAccess;
|
||||
}
|
||||
|
||||
inline const FaceCounters&
|
||||
Face::getCounters() const
|
||||
{
|
||||
@@ -240,17 +282,38 @@ Face::getLocalUri() const
|
||||
return m_localUri;
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::setOnDemand(bool isOnDemand)
|
||||
{
|
||||
m_isOnDemand = isOnDemand;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Face::isOnDemand() const
|
||||
{
|
||||
return m_isOnDemand;
|
||||
}
|
||||
/** \defgroup FaceLogging Face logging macros
|
||||
*
|
||||
* These macros augment the log message with some face-specific information,
|
||||
* such as the face ID, that are useful to distinguish which face produced the
|
||||
* message. It is strongly recommended to use these macros instead of the
|
||||
* generic ones for all logging inside Face subclasses.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define NFD_LOG_FACE(level, msg) \
|
||||
NFD_LOG_##level("[id=" << this->getId() << \
|
||||
",local=" << this->getLocalUri() << \
|
||||
",remote=" << this->getRemoteUri() << \
|
||||
"] " << msg)
|
||||
|
||||
/** \brief Log a message at TRACE level */
|
||||
#define NFD_LOG_FACE_TRACE(msg) NFD_LOG_FACE(TRACE, msg)
|
||||
|
||||
/** \brief Log a message at DEBUG level */
|
||||
#define NFD_LOG_FACE_DEBUG(msg) NFD_LOG_FACE(DEBUG, msg)
|
||||
|
||||
/** \brief Log a message at INFO level */
|
||||
#define NFD_LOG_FACE_INFO(msg) NFD_LOG_FACE(INFO, msg)
|
||||
|
||||
/** \brief Log a message at WARN level */
|
||||
#define NFD_LOG_FACE_WARN(msg) NFD_LOG_FACE(WARN, msg)
|
||||
|
||||
/** \brief Log a message at ERROR level */
|
||||
#define NFD_LOG_FACE_ERROR(msg) NFD_LOG_FACE(ERROR, msg)
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
|
||||
@@ -152,9 +152,11 @@ LocalFace::decodeAndDispatchInput(const Block& element)
|
||||
i->wireDecode(payload);
|
||||
if (&payload != &element)
|
||||
{
|
||||
i->getLocalControlHeader().wireDecode(element,
|
||||
false,
|
||||
this->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
|
||||
uint8_t mask = 0;
|
||||
if (this->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID)) {
|
||||
mask |= ndn::nfd::LocalControlHeader::ENCODE_NEXT_HOP;
|
||||
}
|
||||
i->getLocalControlHeader().wireDecode(element, mask);
|
||||
}
|
||||
|
||||
this->emitSignal(onReceiveInterest, *i);
|
||||
@@ -193,17 +195,22 @@ LocalFace::isEmptyFilteredLocalControlHeader(const ndn::nfd::LocalControlHeader&
|
||||
if (!this->isLocalControlHeaderEnabled())
|
||||
return true;
|
||||
|
||||
return header.empty(this->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID),
|
||||
false);
|
||||
uint8_t mask = 0;
|
||||
if (this->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID)) {
|
||||
mask |= ndn::nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID;
|
||||
}
|
||||
return header.empty(mask);
|
||||
}
|
||||
|
||||
template<class Packet>
|
||||
inline Block
|
||||
LocalFace::filterAndEncodeLocalControlHeader(const Packet& packet)
|
||||
{
|
||||
return packet.getLocalControlHeader().wireEncode(packet,
|
||||
this->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID),
|
||||
false);
|
||||
uint8_t mask = 0;
|
||||
if (this->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID)) {
|
||||
mask |= ndn::nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID;
|
||||
}
|
||||
return packet.getLocalControlHeader().wireEncode(packet, mask);
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
@@ -31,17 +31,13 @@ NFD_LOG_INCLASS_2TEMPLATE_SPECIALIZATION_DEFINE(DatagramFace,
|
||||
MulticastUdpFace::protocol, Multicast,
|
||||
"MulticastUdpFace");
|
||||
|
||||
MulticastUdpFace::MulticastUdpFace(const shared_ptr<MulticastUdpFace::protocol::socket>& recvSocket,
|
||||
const shared_ptr<MulticastUdpFace::protocol::socket>& sendSocket,
|
||||
const MulticastUdpFace::protocol::endpoint& localEndpoint,
|
||||
const MulticastUdpFace::protocol::endpoint& multicastEndpoint)
|
||||
: DatagramFace<protocol, Multicast>(FaceUri(multicastEndpoint),
|
||||
FaceUri(localEndpoint),
|
||||
recvSocket, false)
|
||||
, m_multicastGroup(multicastEndpoint)
|
||||
, m_sendSocket(sendSocket)
|
||||
MulticastUdpFace::MulticastUdpFace(const protocol::endpoint& multicastGroup,
|
||||
const FaceUri& localUri,
|
||||
protocol::socket recvSocket, protocol::socket sendSocket)
|
||||
: DatagramFace(FaceUri(multicastGroup), localUri, std::move(recvSocket))
|
||||
, m_multicastGroup(multicastGroup)
|
||||
, m_sendSocket(std::move(sendSocket))
|
||||
{
|
||||
NFD_LOG_INFO("Creating multicast UDP face for group " << m_multicastGroup);
|
||||
}
|
||||
|
||||
const MulticastUdpFace::protocol::endpoint&
|
||||
@@ -50,38 +46,32 @@ MulticastUdpFace::getMulticastGroup() const
|
||||
return m_multicastGroup;
|
||||
}
|
||||
|
||||
void
|
||||
MulticastUdpFace::sendBlock(const Block& block)
|
||||
{
|
||||
m_sendSocket->async_send_to(boost::asio::buffer(block.wire(), block.size()),
|
||||
m_multicastGroup,
|
||||
bind(&MulticastUdpFace::handleSend, this, _1, _2, block));
|
||||
}
|
||||
|
||||
void
|
||||
MulticastUdpFace::sendInterest(const Interest& interest)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
this->emitSignal(onSendInterest, interest);
|
||||
|
||||
NFD_LOG_DEBUG("Sending interest");
|
||||
sendBlock(interest.wireEncode());
|
||||
}
|
||||
|
||||
void
|
||||
MulticastUdpFace::sendData(const Data& data)
|
||||
{
|
||||
/// \todo After this method implements duplicate suppression, onSendData signal should
|
||||
/// be emitted only when data is actually sent out
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
/// \todo After this face implements duplicate suppression, onSendData should
|
||||
/// be emitted only when data is actually sent out. See also #2555
|
||||
this->emitSignal(onSendData, data);
|
||||
|
||||
NFD_LOG_DEBUG("Sending data");
|
||||
sendBlock(data.wireEncode());
|
||||
}
|
||||
|
||||
bool
|
||||
MulticastUdpFace::isMultiAccess() const
|
||||
void
|
||||
MulticastUdpFace::sendBlock(const Block& block)
|
||||
{
|
||||
return true;
|
||||
m_sendSocket.async_send_to(boost::asio::buffer(block.wire(), block.size()), m_multicastGroup,
|
||||
bind(&MulticastUdpFace::handleSend, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred,
|
||||
block));
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
@@ -40,10 +40,8 @@ public:
|
||||
/**
|
||||
* \brief Creates a UDP-based face for multicast communication
|
||||
*/
|
||||
MulticastUdpFace(const shared_ptr<protocol::socket>& recvSocket,
|
||||
const shared_ptr<protocol::socket>& sendSocket,
|
||||
const protocol::endpoint& localEndpoint,
|
||||
const protocol::endpoint& multicastEndpoint);
|
||||
MulticastUdpFace(const protocol::endpoint& multicastGroup, const FaceUri& localUri,
|
||||
protocol::socket recvSocket, protocol::socket sendSocket);
|
||||
|
||||
const protocol::endpoint&
|
||||
getMulticastGroup() const;
|
||||
@@ -55,16 +53,13 @@ public:
|
||||
void
|
||||
sendData(const Data& data) DECL_OVERRIDE;
|
||||
|
||||
bool
|
||||
isMultiAccess() const DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
void
|
||||
sendBlock(const Block& block);
|
||||
|
||||
private:
|
||||
protocol::endpoint m_multicastGroup;
|
||||
shared_ptr<protocol::socket> m_sendSocket;
|
||||
protocol::socket m_sendSocket;
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ndnlp-data.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace ndnlp {
|
||||
|
||||
std::tuple<bool, NdnlpData>
|
||||
NdnlpData::fromBlock(const Block& wire)
|
||||
{
|
||||
if (wire.type() != tlv::NdnlpData) {
|
||||
// top element is not NdnlpData
|
||||
return std::make_tuple(false, NdnlpData());
|
||||
}
|
||||
wire.parse();
|
||||
const Block::element_container& elements = wire.elements();
|
||||
if (elements.size() < 2) {
|
||||
// NdnlpData element has incorrect number of children
|
||||
return std::make_tuple(false, NdnlpData());
|
||||
}
|
||||
|
||||
NdnlpData parsed;
|
||||
|
||||
const Block& sequenceElement = elements.front();
|
||||
if (sequenceElement.type() != tlv::NdnlpSequence) {
|
||||
// NdnlpSequence element is missing
|
||||
return std::make_tuple(false, NdnlpData());
|
||||
}
|
||||
if (sequenceElement.value_size() != sizeof(uint64_t)) {
|
||||
// NdnlpSequence element has incorrect length
|
||||
return std::make_tuple(false, NdnlpData());
|
||||
}
|
||||
parsed.seq = be64toh(*reinterpret_cast<const uint64_t*>(&*sequenceElement.value_begin()));
|
||||
|
||||
const Block& payloadElement = elements.back();
|
||||
if (payloadElement.type() != tlv::NdnlpPayload) {
|
||||
// NdnlpPayload element is missing
|
||||
return std::make_tuple(false, NdnlpData());
|
||||
}
|
||||
parsed.payload = payloadElement;
|
||||
|
||||
if (elements.size() == 2) { // single wire packet
|
||||
parsed.fragIndex = 0;
|
||||
parsed.fragCount = 1;
|
||||
return std::make_tuple(true, parsed);
|
||||
}
|
||||
if (elements.size() != 4) {
|
||||
// NdnlpData element has incorrect number of children
|
||||
return std::make_tuple(false, NdnlpData());
|
||||
}
|
||||
|
||||
const Block& fragIndexElement = elements.at(1);
|
||||
if (fragIndexElement.type() != tlv::NdnlpFragIndex) {
|
||||
// NdnlpFragIndex element is missing
|
||||
return std::make_tuple(false, NdnlpData());
|
||||
}
|
||||
uint64_t fragIndex = ndn::readNonNegativeInteger(fragIndexElement);
|
||||
if (fragIndex > std::numeric_limits<uint16_t>::max()) {
|
||||
// NdnlpFragIndex is too large
|
||||
return std::make_tuple(false, NdnlpData());
|
||||
}
|
||||
parsed.fragIndex = static_cast<uint16_t>(fragIndex);
|
||||
|
||||
const Block& fragCountElement = elements.at(2);
|
||||
if (fragCountElement.type() != tlv::NdnlpFragCount) {
|
||||
// NdnlpFragCount element is missing
|
||||
return std::make_tuple(false, NdnlpData());
|
||||
}
|
||||
uint64_t fragCount = ndn::readNonNegativeInteger(fragCountElement);
|
||||
if (fragCount > std::numeric_limits<uint16_t>::max()) {
|
||||
// NdnlpFragCount is too large
|
||||
return std::make_tuple(false, NdnlpData());
|
||||
}
|
||||
parsed.fragCount = static_cast<uint16_t>(fragCount);
|
||||
|
||||
if (parsed.fragIndex >= parsed.fragCount) {
|
||||
// NdnlpFragIndex must be less than NdnlpFragCount
|
||||
return std::make_tuple(false, NdnlpData());
|
||||
}
|
||||
|
||||
return std::make_tuple(true, parsed);
|
||||
}
|
||||
|
||||
} // namespace ndnlp
|
||||
} // namespace nfd
|
||||
@@ -1,11 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014 Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -20,7 +21,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
*/
|
||||
|
||||
#ifndef NFD_DAEMON_FACE_NDNLP_PARSE_HPP
|
||||
#define NFD_DAEMON_FACE_NDNLP_PARSE_HPP
|
||||
@@ -31,14 +32,6 @@
|
||||
namespace nfd {
|
||||
namespace ndnlp {
|
||||
|
||||
struct ParseError : public std::runtime_error
|
||||
{
|
||||
ParseError(const std::string& what)
|
||||
: std::runtime_error(what)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/** \brief represents a NdnlpData packet
|
||||
*
|
||||
* NdnlpData ::= NDNLP-DATA-TYPE TLV-LENGTH
|
||||
@@ -51,17 +44,16 @@ class NdnlpData
|
||||
{
|
||||
public:
|
||||
/** \brief parse a NdnlpData packet
|
||||
*
|
||||
* \exception ParseError packet is malformated
|
||||
* \return whether \p wire has a valid NdnlpData packet, and the parsed packet
|
||||
*/
|
||||
void
|
||||
wireDecode(const Block& wire);
|
||||
static std::tuple<bool, NdnlpData>
|
||||
fromBlock(const Block& wire);
|
||||
|
||||
public:
|
||||
uint64_t m_seq;
|
||||
uint16_t m_fragIndex;
|
||||
uint16_t m_fragCount;
|
||||
Block m_payload;
|
||||
uint64_t seq;
|
||||
uint16_t fragIndex;
|
||||
uint16_t fragCount;
|
||||
Block payload;
|
||||
};
|
||||
|
||||
} // namespace ndnlp
|
||||
@@ -1,92 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014 Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
#include "ndnlp-parse.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace ndnlp {
|
||||
|
||||
void
|
||||
NdnlpData::wireDecode(const Block& wire)
|
||||
{
|
||||
if (wire.type() != tlv::NdnlpData) {
|
||||
throw ParseError("top element is not NdnlpData");
|
||||
}
|
||||
wire.parse();
|
||||
const Block::element_container& elements = wire.elements();
|
||||
if (elements.size() < 2) {
|
||||
throw ParseError("NdnlpData element has incorrect number of children");
|
||||
}
|
||||
|
||||
const Block& sequenceElement = elements.front();
|
||||
if (sequenceElement.type() != tlv::NdnlpSequence) {
|
||||
throw ParseError("NdnlpSequence element is missing");
|
||||
}
|
||||
if (sequenceElement.value_size() != sizeof(uint64_t)) {
|
||||
throw ParseError("NdnlpSequence element has incorrect length");
|
||||
}
|
||||
m_seq = be64toh(*reinterpret_cast<const uint64_t*>(&*sequenceElement.value_begin()));
|
||||
|
||||
const Block& payloadElement = elements.back();
|
||||
if (payloadElement.type() != tlv::NdnlpPayload) {
|
||||
throw ParseError("NdnlpPayload element is missing");
|
||||
}
|
||||
m_payload = payloadElement;
|
||||
|
||||
if (elements.size() == 2) { // single wire packet
|
||||
m_fragIndex = 0;
|
||||
m_fragCount = 1;
|
||||
return;
|
||||
}
|
||||
if (elements.size() != 4) {
|
||||
throw ParseError("NdnlpData element has incorrect number of children");
|
||||
}
|
||||
|
||||
const Block& fragIndexElement = elements.at(1);
|
||||
if (fragIndexElement.type() != tlv::NdnlpFragIndex) {
|
||||
throw ParseError("NdnlpFragIndex element is missing");
|
||||
}
|
||||
uint64_t fragIndex = ndn::readNonNegativeInteger(fragIndexElement);
|
||||
if (fragIndex > std::numeric_limits<uint16_t>::max()) {
|
||||
throw ParseError("NdnlpFragIndex is too large");
|
||||
}
|
||||
m_fragIndex = static_cast<uint16_t>(fragIndex);
|
||||
|
||||
const Block& fragCountElement = elements.at(2);
|
||||
if (fragCountElement.type() != tlv::NdnlpFragCount) {
|
||||
throw ParseError("NdnlpFragCount element is missing");
|
||||
}
|
||||
uint64_t fragCount = ndn::readNonNegativeInteger(fragCountElement);
|
||||
if (fragCount > std::numeric_limits<uint16_t>::max()) {
|
||||
throw ParseError("NdnlpFragCount is too large");
|
||||
}
|
||||
m_fragCount = static_cast<uint16_t>(fragCount);
|
||||
|
||||
if (m_fragIndex >= m_fragCount) {
|
||||
throw ParseError("NdnlpFragIndex must be less than NdnlpFragCount");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ndnlp
|
||||
} // namespace nfd
|
||||
@@ -24,10 +24,13 @@
|
||||
*/
|
||||
|
||||
#include "ndnlp-partial-message-store.hpp"
|
||||
#include "core/logger.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace ndnlp {
|
||||
|
||||
NFD_LOG_INIT("NdnlpPartialMessageStore");
|
||||
|
||||
PartialMessage::PartialMessage()
|
||||
: m_fragCount(0)
|
||||
, m_received(0)
|
||||
@@ -63,21 +66,32 @@ PartialMessage::isComplete() const
|
||||
return m_received == m_fragCount;
|
||||
}
|
||||
|
||||
Block
|
||||
std::tuple<bool, Block>
|
||||
PartialMessage::reassemble()
|
||||
{
|
||||
BOOST_ASSERT(this->isComplete());
|
||||
|
||||
ndn::BufferPtr buffer = make_shared<ndn::Buffer>(m_totalLength);
|
||||
uint8_t* buf = buffer->get();
|
||||
for (std::vector<Block>::const_iterator it = m_payloads.begin();
|
||||
it != m_payloads.end(); ++it) {
|
||||
const Block& payload = *it;
|
||||
memcpy(buf, payload.value(), payload.value_size());
|
||||
buf += payload.value_size();
|
||||
ndn::Buffer::iterator buf = buffer->begin();
|
||||
for (const Block& payload : m_payloads) {
|
||||
buf = std::copy(payload.value_begin(), payload.value_end(), buf);
|
||||
}
|
||||
BOOST_ASSERT(buf == buffer->end());
|
||||
|
||||
return Block(buffer);
|
||||
return Block::fromBuffer(buffer, 0);
|
||||
}
|
||||
|
||||
std::tuple<bool, Block>
|
||||
PartialMessage::reassembleSingle(const NdnlpData& fragment)
|
||||
{
|
||||
BOOST_ASSERT(fragment.fragCount == 1);
|
||||
|
||||
try {
|
||||
return std::make_tuple(true, fragment.payload.blockFromValue());
|
||||
}
|
||||
catch (tlv::Error&) {
|
||||
return std::make_tuple(false, Block());
|
||||
}
|
||||
}
|
||||
|
||||
PartialMessageStore::PartialMessageStore(const time::nanoseconds& idleDuration)
|
||||
@@ -85,29 +99,38 @@ PartialMessageStore::PartialMessageStore(const time::nanoseconds& idleDuration)
|
||||
{
|
||||
}
|
||||
|
||||
PartialMessageStore::~PartialMessageStore()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
PartialMessageStore::receiveNdnlpData(const Block& pkt)
|
||||
PartialMessageStore::receive(const NdnlpData& pkt)
|
||||
{
|
||||
NdnlpData parsed;
|
||||
parsed.wireDecode(pkt);
|
||||
if (parsed.m_fragCount == 1) { // single fragment
|
||||
this->onReceive(parsed.m_payload.blockFromValue());
|
||||
bool isReassembled = false;
|
||||
Block reassembled;
|
||||
|
||||
if (pkt.fragCount == 1) { // single fragment
|
||||
std::tie(isReassembled, reassembled) = PartialMessage::reassembleSingle(pkt);
|
||||
}
|
||||
else {
|
||||
uint64_t messageIdentifier = pkt.seq - pkt.fragIndex;
|
||||
PartialMessage& pm = m_partialMessages[messageIdentifier];
|
||||
this->scheduleCleanup(messageIdentifier, pm);
|
||||
|
||||
pm.add(pkt.fragIndex, pkt.fragCount, pkt.payload);
|
||||
|
||||
if (pm.isComplete()) {
|
||||
std::tie(isReassembled, reassembled) = pm.reassemble();
|
||||
m_partialMessages.erase(messageIdentifier);
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isReassembled) {
|
||||
NFD_LOG_TRACE(pkt.seq << " reassemble error");
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t messageIdentifier = parsed.m_seq - parsed.m_fragIndex;
|
||||
PartialMessage& pm = m_partialMessages[messageIdentifier];
|
||||
this->scheduleCleanup(messageIdentifier, pm);
|
||||
|
||||
pm.add(parsed.m_fragIndex, parsed.m_fragCount, parsed.m_payload);
|
||||
if (pm.isComplete()) {
|
||||
this->onReceive(pm.reassemble());
|
||||
this->cleanup(messageIdentifier);
|
||||
}
|
||||
NFD_LOG_TRACE(pkt.seq << " deliver");
|
||||
this->onReceive(reassembled);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -121,6 +144,7 @@ PartialMessageStore::scheduleCleanup(uint64_t messageIdentifier,
|
||||
void
|
||||
PartialMessageStore::cleanup(uint64_t messageIdentifier)
|
||||
{
|
||||
NFD_LOG_TRACE(messageIdentifier << " cleanup");
|
||||
m_partialMessages.erase(messageIdentifier);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#ifndef NFD_DAEMON_FACE_NDNLP_PARTIAL_MESSAGE_STORE_HPP
|
||||
#define NFD_DAEMON_FACE_NDNLP_PARTIAL_MESSAGE_STORE_HPP
|
||||
|
||||
#include "ndnlp-parse.hpp"
|
||||
#include "ndnlp-data.hpp"
|
||||
#include "core/scheduler.hpp"
|
||||
|
||||
namespace nfd {
|
||||
@@ -56,15 +56,19 @@ public:
|
||||
isComplete() const;
|
||||
|
||||
/** \brief reassemble network layer packet
|
||||
*
|
||||
* isComplete() must be true before calling this method
|
||||
*
|
||||
* \exception ndn::Block::Error packet is malformated
|
||||
* \return network layer packet
|
||||
* \pre isComplete() == true
|
||||
* \return whether success, network layer packet
|
||||
*/
|
||||
Block
|
||||
std::tuple<bool, Block>
|
||||
reassemble();
|
||||
|
||||
/** \brief reassemble network layer packet from a single fragment
|
||||
* \pre fragment.fragCount == 1
|
||||
* \return whether success, network layer packet
|
||||
*/
|
||||
static std::tuple<bool, Block>
|
||||
reassembleSingle(const NdnlpData& fragment);
|
||||
|
||||
public:
|
||||
scheduler::ScopedEventId expiry;
|
||||
|
||||
@@ -83,16 +87,12 @@ public:
|
||||
explicit
|
||||
PartialMessageStore(const time::nanoseconds& idleDuration = time::milliseconds(100));
|
||||
|
||||
virtual
|
||||
~PartialMessageStore();
|
||||
|
||||
/** \brief receive a NdnlpData packet
|
||||
*
|
||||
* \exception ParseError NDNLP packet is malformated
|
||||
* \exception ndn::Block::Error network layer packet is malformated
|
||||
* Reassembly errors will be ignored.
|
||||
*/
|
||||
void
|
||||
receiveNdnlpData(const Block& pkt);
|
||||
receive(const NdnlpData& pkt);
|
||||
|
||||
/** \brief fires when network layer packet is received
|
||||
*/
|
||||
|
||||
@@ -26,11 +26,12 @@
|
||||
#ifndef NFD_DAEMON_FACE_PROTOCOL_FACTORY_HPP
|
||||
#define NFD_DAEMON_FACE_PROTOCOL_FACTORY_HPP
|
||||
|
||||
#include "face.hpp"
|
||||
#include "common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
class Channel;
|
||||
class Face;
|
||||
|
||||
/**
|
||||
* \brief Prototype for the callback called when face is created
|
||||
@@ -69,9 +70,8 @@ public:
|
||||
const FaceCreatedCallback& onCreated,
|
||||
const FaceConnectFailedCallback& onConnectFailed) = 0;
|
||||
|
||||
virtual std::list<shared_ptr<const Channel> >
|
||||
virtual std::list<shared_ptr<const Channel>>
|
||||
getChannels() const = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
+53
-70
@@ -29,7 +29,6 @@
|
||||
#include "face.hpp"
|
||||
#include "local-face.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
#include "core/logger.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
@@ -42,14 +41,8 @@ class StreamFace : public FaceBase
|
||||
public:
|
||||
typedef Protocol protocol;
|
||||
|
||||
/**
|
||||
* \brief Create instance of StreamFace
|
||||
*/
|
||||
StreamFace(const FaceUri& remoteUri, const FaceUri& localUri,
|
||||
const shared_ptr<typename protocol::socket>& socket,
|
||||
bool isOnDemand);
|
||||
|
||||
~StreamFace() DECL_OVERRIDE;
|
||||
typename protocol::socket socket, bool isOnDemand);
|
||||
|
||||
// from FaceBase
|
||||
void
|
||||
@@ -83,7 +76,9 @@ protected:
|
||||
deferredClose(const shared_ptr<Face>& face);
|
||||
|
||||
protected:
|
||||
shared_ptr<typename protocol::socket> m_socket;
|
||||
typename protocol::socket m_socket;
|
||||
|
||||
NFD_LOG_INCLASS_DECLARE();
|
||||
|
||||
private:
|
||||
uint8_t m_inputBuffer[ndn::MAX_NDN_PACKET_SIZE];
|
||||
@@ -92,8 +87,6 @@ private:
|
||||
|
||||
friend struct StreamFaceSenderImpl<Protocol, FaceBase, Interest>;
|
||||
friend struct StreamFaceSenderImpl<Protocol, FaceBase, Data>;
|
||||
|
||||
NFD_LOG_INCLASS_DECLARE();
|
||||
};
|
||||
|
||||
// All inherited classes must use
|
||||
@@ -111,7 +104,7 @@ template<class Protocol, class U>
|
||||
struct StreamFaceValidator
|
||||
{
|
||||
static void
|
||||
validateSocket(typename Protocol::socket& socket)
|
||||
validateSocket(const typename Protocol::socket& socket)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -120,22 +113,20 @@ struct StreamFaceValidator
|
||||
template<class T, class FaceBase>
|
||||
inline
|
||||
StreamFace<T, FaceBase>::StreamFace(const FaceUri& remoteUri, const FaceUri& localUri,
|
||||
const shared_ptr<typename StreamFace::protocol::socket>& socket,
|
||||
bool isOnDemand)
|
||||
typename StreamFace::protocol::socket socket, bool isOnDemand)
|
||||
: FaceBase(remoteUri, localUri)
|
||||
, m_socket(socket)
|
||||
, m_socket(std::move(socket))
|
||||
, m_inputBufferSize(0)
|
||||
{
|
||||
FaceBase::setOnDemand(isOnDemand);
|
||||
StreamFaceValidator<T, FaceBase>::validateSocket(*socket);
|
||||
m_socket->async_receive(boost::asio::buffer(m_inputBuffer, ndn::MAX_NDN_PACKET_SIZE), 0,
|
||||
bind(&StreamFace<T, FaceBase>::handleReceive, this, _1, _2));
|
||||
}
|
||||
NFD_LOG_FACE_INFO("Creating face");
|
||||
|
||||
template<class T, class U>
|
||||
inline
|
||||
StreamFace<T, U>::~StreamFace()
|
||||
{
|
||||
this->setOnDemand(isOnDemand);
|
||||
StreamFaceValidator<T, FaceBase>::validateSocket(m_socket);
|
||||
|
||||
m_socket.async_receive(boost::asio::buffer(m_inputBuffer, ndn::MAX_NDN_PACKET_SIZE),
|
||||
bind(&StreamFace<T, FaceBase>::handleReceive, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
|
||||
@@ -178,6 +169,7 @@ template<class T, class U>
|
||||
inline void
|
||||
StreamFace<T, U>::sendInterest(const Interest& interest)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
this->emitSignal(onSendInterest, interest);
|
||||
StreamFaceSenderImpl<T, U, Interest>::send(*this, interest);
|
||||
}
|
||||
@@ -186,6 +178,7 @@ template<class T, class U>
|
||||
inline void
|
||||
StreamFace<T, U>::sendData(const Data& data)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
this->emitSignal(onSendData, data);
|
||||
StreamFaceSenderImpl<T, U, Data>::send(*this, data);
|
||||
}
|
||||
@@ -194,11 +187,10 @@ template<class T, class U>
|
||||
inline void
|
||||
StreamFace<T, U>::close()
|
||||
{
|
||||
if (!m_socket->is_open())
|
||||
if (!m_socket.is_open())
|
||||
return;
|
||||
|
||||
NFD_LOG_INFO("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Closing face");
|
||||
NFD_LOG_FACE_INFO("Closing face");
|
||||
|
||||
shutdownSocket();
|
||||
this->fail("Face closed");
|
||||
@@ -212,36 +204,31 @@ StreamFace<T, U>::processErrorCode(const boost::system::error_code& error)
|
||||
error == boost::asio::error::shut_down) // after shutdown() is called
|
||||
return;
|
||||
|
||||
if (!m_socket->is_open())
|
||||
if (!m_socket.is_open())
|
||||
{
|
||||
this->fail("Connection closed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (error != boost::asio::error::eof)
|
||||
NFD_LOG_WARN("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Send or receive operation failed, closing face: "
|
||||
<< error.message());
|
||||
NFD_LOG_FACE_WARN("Send or receive operation failed: " << error.message());
|
||||
|
||||
shutdownSocket();
|
||||
|
||||
if (error == boost::asio::error::eof)
|
||||
{
|
||||
this->fail("Connection closed");
|
||||
}
|
||||
this->fail("Connection closed");
|
||||
else
|
||||
{
|
||||
this->fail("Send or receive operation failed: " + error.message());
|
||||
}
|
||||
this->fail(error.message());
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
StreamFace<T, U>::sendFromQueue()
|
||||
{
|
||||
const Block& block = this->m_sendQueue.front();
|
||||
boost::asio::async_write(*this->m_socket, boost::asio::buffer(block),
|
||||
bind(&StreamFace<T, U>::handleSend, this, _1, _2));
|
||||
boost::asio::async_write(m_socket, boost::asio::buffer(m_sendQueue.front()),
|
||||
bind(&StreamFace<T, U>::handleSend, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
@@ -254,8 +241,7 @@ StreamFace<T, U>::handleSend(const boost::system::error_code& error,
|
||||
|
||||
BOOST_ASSERT(!m_sendQueue.empty());
|
||||
|
||||
NFD_LOG_TRACE("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Successfully sent: " << nBytesSent << " bytes");
|
||||
NFD_LOG_FACE_TRACE("Successfully sent: " << nBytesSent << " bytes");
|
||||
this->getMutableCounters().getNOutBytes() += nBytesSent;
|
||||
|
||||
m_sendQueue.pop();
|
||||
@@ -271,8 +257,7 @@ StreamFace<T, U>::handleReceive(const boost::system::error_code& error,
|
||||
if (error)
|
||||
return processErrorCode(error);
|
||||
|
||||
NFD_LOG_TRACE("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Received: " << nBytesReceived << " bytes");
|
||||
NFD_LOG_FACE_TRACE("Received: " << nBytesReceived << " bytes");
|
||||
this->getMutableCounters().getNInBytes() += nBytesReceived;
|
||||
|
||||
m_inputBufferSize += nBytesReceived;
|
||||
@@ -281,29 +266,24 @@ StreamFace<T, U>::handleReceive(const boost::system::error_code& error,
|
||||
|
||||
bool isOk = true;
|
||||
Block element;
|
||||
while (m_inputBufferSize - offset > 0)
|
||||
{
|
||||
isOk = Block::fromBuffer(m_inputBuffer + offset, m_inputBufferSize - offset, element);
|
||||
if (!isOk)
|
||||
break;
|
||||
while (m_inputBufferSize - offset > 0) {
|
||||
std::tie(isOk, element) = Block::fromBuffer(m_inputBuffer + offset, m_inputBufferSize - offset);
|
||||
if (!isOk)
|
||||
break;
|
||||
|
||||
offset += element.size();
|
||||
offset += element.size();
|
||||
|
||||
BOOST_ASSERT(offset <= m_inputBufferSize);
|
||||
BOOST_ASSERT(offset <= m_inputBufferSize);
|
||||
|
||||
if (!this->decodeAndDispatchInput(element))
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Received unrecognized block of type ["
|
||||
<< element.type() << "]");
|
||||
// ignore unknown packet and proceed
|
||||
}
|
||||
if (!this->decodeAndDispatchInput(element)) {
|
||||
NFD_LOG_FACE_WARN("Received unrecognized TLV block of type " << element.type());
|
||||
// ignore unknown packet and proceed
|
||||
}
|
||||
}
|
||||
|
||||
if (!isOk && m_inputBufferSize == ndn::MAX_NDN_PACKET_SIZE && offset == 0)
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Failed to parse incoming packet or packet too large to process, "
|
||||
<< "closing face");
|
||||
NFD_LOG_FACE_WARN("Failed to parse incoming packet or packet too large to process");
|
||||
shutdownSocket();
|
||||
this->fail("Failed to parse incoming packet or packet too large to process");
|
||||
return;
|
||||
@@ -323,21 +303,25 @@ StreamFace<T, U>::handleReceive(const boost::system::error_code& error,
|
||||
}
|
||||
}
|
||||
|
||||
m_socket->async_receive(boost::asio::buffer(m_inputBuffer + m_inputBufferSize,
|
||||
ndn::MAX_NDN_PACKET_SIZE - m_inputBufferSize), 0,
|
||||
bind(&StreamFace<T, U>::handleReceive, this, _1, _2));
|
||||
m_socket.async_receive(boost::asio::buffer(m_inputBuffer + m_inputBufferSize,
|
||||
ndn::MAX_NDN_PACKET_SIZE - m_inputBufferSize),
|
||||
bind(&StreamFace<T, U>::handleReceive, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
StreamFace<T, U>::shutdownSocket()
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
// Cancel all outstanding operations and shutdown the socket
|
||||
// so that no further sends or receives are possible.
|
||||
// Use the non-throwing variants and ignore errors, if any.
|
||||
boost::system::error_code error;
|
||||
m_socket->cancel(error);
|
||||
m_socket->shutdown(protocol::socket::shutdown_both, error);
|
||||
m_socket.cancel(error);
|
||||
m_socket.shutdown(protocol::socket::shutdown_both, error);
|
||||
|
||||
// ensure that the Face object is alive at least until all pending
|
||||
// handlers are dispatched
|
||||
@@ -347,7 +331,7 @@ StreamFace<T, U>::shutdownSocket()
|
||||
// Some bug or feature of Boost.Asio (see http://redmine.named-data.net/issues/1856):
|
||||
//
|
||||
// When shutdownSocket is called from within a socket event (e.g., from handleReceive),
|
||||
// m_socket->shutdown() does not trigger the cancellation of the handleSend callback.
|
||||
// m_socket.shutdown() does not trigger the cancellation of the handleSend callback.
|
||||
// Instead, handleSend is invoked as nothing bad happened.
|
||||
//
|
||||
// In order to prevent the assertion in handleSend from failing, we clear the queue
|
||||
@@ -361,8 +345,7 @@ template<class T, class U>
|
||||
inline void
|
||||
StreamFace<T, U>::deferredClose(const shared_ptr<Face>& face)
|
||||
{
|
||||
NFD_LOG_DEBUG("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Clearing send queue");
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
// clear send queue
|
||||
std::queue<Block> emptyQueue;
|
||||
@@ -370,7 +353,7 @@ StreamFace<T, U>::deferredClose(const shared_ptr<Face>& face)
|
||||
|
||||
// use the non-throwing variant and ignore errors, if any
|
||||
boost::system::error_code error;
|
||||
m_socket->close(error);
|
||||
m_socket.close(error);
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
+84
-146
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
#include "tcp-channel.hpp"
|
||||
#include "tcp-face.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
|
||||
namespace nfd {
|
||||
@@ -34,13 +35,10 @@ using namespace boost::asio;
|
||||
|
||||
TcpChannel::TcpChannel(const tcp::Endpoint& localEndpoint)
|
||||
: m_localEndpoint(localEndpoint)
|
||||
, m_isListening(false)
|
||||
{
|
||||
this->setUri(FaceUri(localEndpoint));
|
||||
}
|
||||
|
||||
TcpChannel::~TcpChannel()
|
||||
, m_acceptor(getGlobalIoService())
|
||||
, m_acceptSocket(getGlobalIoService())
|
||||
{
|
||||
setUri(FaceUri(m_localEndpoint));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -48,24 +46,21 @@ TcpChannel::listen(const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onAcceptFailed,
|
||||
int backlog/* = tcp::acceptor::max_connections*/)
|
||||
{
|
||||
m_acceptor = make_shared<ip::tcp::acceptor>(ref(getGlobalIoService()));
|
||||
m_acceptor->open(m_localEndpoint.protocol());
|
||||
m_acceptor->set_option(ip::tcp::acceptor::reuse_address(true));
|
||||
if (isListening()) {
|
||||
NFD_LOG_WARN("[" << m_localEndpoint << "] Already listening");
|
||||
return;
|
||||
}
|
||||
|
||||
m_acceptor.open(m_localEndpoint.protocol());
|
||||
m_acceptor.set_option(ip::tcp::acceptor::reuse_address(true));
|
||||
if (m_localEndpoint.address().is_v6())
|
||||
{
|
||||
m_acceptor->set_option(ip::v6_only(true));
|
||||
}
|
||||
m_acceptor->bind(m_localEndpoint);
|
||||
m_acceptor->listen(backlog);
|
||||
m_acceptor.set_option(ip::v6_only(true));
|
||||
|
||||
shared_ptr<ip::tcp::socket> clientSocket =
|
||||
make_shared<ip::tcp::socket>(ref(getGlobalIoService()));
|
||||
m_acceptor->async_accept(*clientSocket,
|
||||
bind(&TcpChannel::handleSuccessfulAccept, this, _1,
|
||||
clientSocket,
|
||||
onFaceCreated, onAcceptFailed));
|
||||
m_acceptor.bind(m_localEndpoint);
|
||||
m_acceptor.listen(backlog);
|
||||
|
||||
m_isListening = true;
|
||||
// start accepting connections
|
||||
accept(onFaceCreated, onAcceptFailed);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -74,47 +69,24 @@ TcpChannel::connect(const tcp::Endpoint& remoteEndpoint,
|
||||
const TcpChannel::ConnectFailedCallback& onConnectFailed,
|
||||
const time::seconds& timeout/* = time::seconds(4)*/)
|
||||
{
|
||||
ChannelFaceMap::iterator i = m_channelFaces.find(remoteEndpoint);
|
||||
if (i != m_channelFaces.end()) {
|
||||
onFaceCreated(i->second);
|
||||
auto it = m_channelFaces.find(remoteEndpoint);
|
||||
if (it != m_channelFaces.end()) {
|
||||
onFaceCreated(it->second);
|
||||
return;
|
||||
}
|
||||
|
||||
shared_ptr<ip::tcp::socket> clientSocket =
|
||||
make_shared<ip::tcp::socket>(ref(getGlobalIoService()));
|
||||
auto clientSocket = make_shared<ip::tcp::socket>(ref(getGlobalIoService()));
|
||||
|
||||
scheduler::EventId connectTimeoutEvent = scheduler::schedule(timeout,
|
||||
bind(&TcpChannel::handleFailedConnect, this, clientSocket, onConnectFailed));
|
||||
bind(&TcpChannel::handleConnectTimeout, this, clientSocket, onConnectFailed));
|
||||
|
||||
clientSocket->async_connect(remoteEndpoint,
|
||||
bind(&TcpChannel::handleSuccessfulConnect, this, _1,
|
||||
bind(&TcpChannel::handleConnect, this,
|
||||
boost::asio::placeholders::error,
|
||||
clientSocket, connectTimeoutEvent,
|
||||
onFaceCreated, onConnectFailed));
|
||||
}
|
||||
|
||||
void
|
||||
TcpChannel::connect(const std::string& remoteHost, const std::string& remotePort,
|
||||
const TcpChannel::FaceCreatedCallback& onFaceCreated,
|
||||
const TcpChannel::ConnectFailedCallback& onConnectFailed,
|
||||
const time::seconds& timeout/* = time::seconds(4)*/)
|
||||
{
|
||||
shared_ptr<ip::tcp::socket> clientSocket =
|
||||
make_shared<ip::tcp::socket>(ref(getGlobalIoService()));
|
||||
|
||||
ip::tcp::resolver::query query(remoteHost, remotePort);
|
||||
shared_ptr<ip::tcp::resolver> resolver =
|
||||
make_shared<ip::tcp::resolver>(ref(getGlobalIoService()));
|
||||
|
||||
scheduler::EventId connectTimeoutEvent = scheduler::schedule(timeout,
|
||||
bind(&TcpChannel::handleFailedConnect, this, clientSocket, onConnectFailed));
|
||||
|
||||
resolver->async_resolve(query,
|
||||
bind(&TcpChannel::handleEndpointResolution, this, _1, _2,
|
||||
clientSocket, connectTimeoutEvent,
|
||||
onFaceCreated, onConnectFailed,
|
||||
resolver));
|
||||
}
|
||||
|
||||
size_t
|
||||
TcpChannel::size() const
|
||||
{
|
||||
@@ -122,35 +94,39 @@ TcpChannel::size() const
|
||||
}
|
||||
|
||||
void
|
||||
TcpChannel::createFace(const shared_ptr<ip::tcp::socket>& socket,
|
||||
TcpChannel::createFace(ip::tcp::socket socket,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
bool isOnDemand)
|
||||
{
|
||||
tcp::Endpoint remoteEndpoint = socket->remote_endpoint();
|
||||
|
||||
shared_ptr<Face> face;
|
||||
tcp::Endpoint remoteEndpoint = socket.remote_endpoint();
|
||||
|
||||
ChannelFaceMap::iterator faceMapPos = m_channelFaces.find(remoteEndpoint);
|
||||
if (faceMapPos == m_channelFaces.end())
|
||||
{
|
||||
if (socket->local_endpoint().address().is_loopback())
|
||||
face = make_shared<TcpLocalFace>(socket, isOnDemand);
|
||||
else
|
||||
face = make_shared<TcpFace>(socket, isOnDemand);
|
||||
auto it = m_channelFaces.find(remoteEndpoint);
|
||||
if (it == m_channelFaces.end()) {
|
||||
tcp::Endpoint localEndpoint = socket.local_endpoint();
|
||||
|
||||
face->onFail.connectSingleShot(bind(&TcpChannel::afterFaceFailed, this, remoteEndpoint));
|
||||
if (localEndpoint.address().is_loopback() &&
|
||||
remoteEndpoint.address().is_loopback())
|
||||
face = make_shared<TcpLocalFace>(FaceUri(remoteEndpoint), FaceUri(localEndpoint),
|
||||
std::move(socket), isOnDemand);
|
||||
else
|
||||
face = make_shared<TcpFace>(FaceUri(remoteEndpoint), FaceUri(localEndpoint),
|
||||
std::move(socket), isOnDemand);
|
||||
|
||||
m_channelFaces[remoteEndpoint] = face;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we've already created a a face for this endpoint, just reuse it
|
||||
face = faceMapPos->second;
|
||||
face->onFail.connectSingleShot([this, remoteEndpoint] (const std::string&) {
|
||||
NFD_LOG_TRACE("Erasing " << remoteEndpoint << " from channel face map");
|
||||
m_channelFaces.erase(remoteEndpoint);
|
||||
});
|
||||
m_channelFaces[remoteEndpoint] = face;
|
||||
}
|
||||
else {
|
||||
// we already have a face for this endpoint, just reuse it
|
||||
face = it->second;
|
||||
|
||||
boost::system::error_code error;
|
||||
socket->shutdown(ip::tcp::socket::shutdown_both, error);
|
||||
socket->close(error);
|
||||
}
|
||||
boost::system::error_code error;
|
||||
socket.shutdown(ip::tcp::socket::shutdown_both, error);
|
||||
socket.close(error);
|
||||
}
|
||||
|
||||
// Need to invoke the callback regardless of whether or not we have already created
|
||||
// the face so that control responses and such can be sent.
|
||||
@@ -158,50 +134,43 @@ TcpChannel::createFace(const shared_ptr<ip::tcp::socket>& socket,
|
||||
}
|
||||
|
||||
void
|
||||
TcpChannel::afterFaceFailed(tcp::Endpoint &remoteEndpoint)
|
||||
TcpChannel::accept(const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onAcceptFailed)
|
||||
{
|
||||
NFD_LOG_DEBUG("afterFaceFailed: " << remoteEndpoint);
|
||||
m_channelFaces.erase(remoteEndpoint);
|
||||
m_acceptor.async_accept(m_acceptSocket, bind(&TcpChannel::handleAccept, this,
|
||||
boost::asio::placeholders::error,
|
||||
onFaceCreated, onAcceptFailed));
|
||||
}
|
||||
|
||||
void
|
||||
TcpChannel::handleSuccessfulAccept(const boost::system::error_code& error,
|
||||
const shared_ptr<boost::asio::ip::tcp::socket>& socket,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onAcceptFailed)
|
||||
TcpChannel::handleAccept(const boost::system::error_code& error,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onAcceptFailed)
|
||||
{
|
||||
if (error) {
|
||||
if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
|
||||
if (error == boost::asio::error::operation_aborted) // when the socket is closed by someone
|
||||
return;
|
||||
|
||||
NFD_LOG_DEBUG("Connect to remote endpoint failed: "
|
||||
<< error.category().message(error.value()));
|
||||
|
||||
if (static_cast<bool>(onAcceptFailed))
|
||||
onAcceptFailed("Connect to remote endpoint failed: " +
|
||||
error.category().message(error.value()));
|
||||
NFD_LOG_DEBUG("[" << m_localEndpoint << "] Accept failed: " << error.message());
|
||||
if (onAcceptFailed)
|
||||
onAcceptFailed(error.message());
|
||||
return;
|
||||
}
|
||||
|
||||
// prepare accepting the next connection
|
||||
shared_ptr<ip::tcp::socket> clientSocket =
|
||||
make_shared<ip::tcp::socket>(ref(getGlobalIoService()));
|
||||
m_acceptor->async_accept(*clientSocket,
|
||||
bind(&TcpChannel::handleSuccessfulAccept, this, _1,
|
||||
clientSocket,
|
||||
onFaceCreated, onAcceptFailed));
|
||||
NFD_LOG_DEBUG("[" << m_localEndpoint << "] Connection from " << m_acceptSocket.remote_endpoint());
|
||||
|
||||
NFD_LOG_DEBUG("[" << m_localEndpoint << "] "
|
||||
"<< Connection from " << socket->remote_endpoint());
|
||||
createFace(socket, onFaceCreated, true);
|
||||
createFace(std::move(m_acceptSocket), onFaceCreated, true);
|
||||
|
||||
// prepare accepting the next connection
|
||||
accept(onFaceCreated, onAcceptFailed);
|
||||
}
|
||||
|
||||
void
|
||||
TcpChannel::handleSuccessfulConnect(const boost::system::error_code& error,
|
||||
const shared_ptr<ip::tcp::socket>& socket,
|
||||
const scheduler::EventId& connectTimeoutEvent,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed)
|
||||
TcpChannel::handleConnect(const boost::system::error_code& error,
|
||||
const shared_ptr<ip::tcp::socket>& socket,
|
||||
const scheduler::EventId& connectTimeoutEvent,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed)
|
||||
{
|
||||
scheduler::cancel(connectTimeoutEvent);
|
||||
|
||||
@@ -214,66 +183,35 @@ TcpChannel::handleSuccessfulConnect(const boost::system::error_code& error,
|
||||
#else
|
||||
if (error) {
|
||||
#endif
|
||||
|
||||
if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
|
||||
if (error == boost::asio::error::operation_aborted) // when the socket is closed by someone
|
||||
return;
|
||||
|
||||
NFD_LOG_WARN("[" << m_localEndpoint << "] Connect failed: " << error.message());
|
||||
|
||||
socket->close();
|
||||
|
||||
NFD_LOG_DEBUG("Connect to remote endpoint failed: "
|
||||
<< error.category().message(error.value()));
|
||||
|
||||
onConnectFailed("Connect to remote endpoint failed: " +
|
||||
error.category().message(error.value()));
|
||||
if (onConnectFailed)
|
||||
onConnectFailed(error.message());
|
||||
return;
|
||||
}
|
||||
|
||||
NFD_LOG_DEBUG("[" << m_localEndpoint << "] "
|
||||
">> Connection to " << socket->remote_endpoint());
|
||||
NFD_LOG_DEBUG("[" << m_localEndpoint << "] Connected to " << socket->remote_endpoint());
|
||||
|
||||
createFace(socket, onFaceCreated, false);
|
||||
createFace(std::move(*socket), onFaceCreated, false);
|
||||
}
|
||||
|
||||
void
|
||||
TcpChannel::handleFailedConnect(const shared_ptr<ip::tcp::socket>& socket,
|
||||
const ConnectFailedCallback& onConnectFailed)
|
||||
TcpChannel::handleConnectTimeout(const shared_ptr<ip::tcp::socket>& socket,
|
||||
const ConnectFailedCallback& onConnectFailed)
|
||||
{
|
||||
NFD_LOG_DEBUG("Connect to remote endpoint timed out");
|
||||
onConnectFailed("Connect to remote endpoint timed out");
|
||||
socket->close(); // abort the connection
|
||||
}
|
||||
|
||||
void
|
||||
TcpChannel::handleEndpointResolution(const boost::system::error_code& error,
|
||||
ip::tcp::resolver::iterator remoteEndpoint,
|
||||
const shared_ptr<boost::asio::ip::tcp::socket>& socket,
|
||||
const scheduler::EventId& connectTimeoutEvent,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed,
|
||||
const shared_ptr<ip::tcp::resolver>& resolver)
|
||||
{
|
||||
if (error ||
|
||||
remoteEndpoint == ip::tcp::resolver::iterator())
|
||||
{
|
||||
if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
|
||||
return;
|
||||
// abort the connection attempt
|
||||
boost::system::error_code error;
|
||||
socket->close(error);
|
||||
|
||||
socket->close();
|
||||
scheduler::cancel(connectTimeoutEvent);
|
||||
|
||||
NFD_LOG_DEBUG("Remote endpoint hostname or port cannot be resolved: "
|
||||
<< error.category().message(error.value()));
|
||||
|
||||
onConnectFailed("Remote endpoint hostname or port cannot be resolved: " +
|
||||
error.category().message(error.value()));
|
||||
return;
|
||||
}
|
||||
|
||||
// got endpoint, now trying to connect (only try the first resolution option)
|
||||
socket->async_connect(*remoteEndpoint,
|
||||
bind(&TcpChannel::handleSuccessfulConnect, this, _1,
|
||||
socket, connectTimeoutEvent,
|
||||
onFaceCreated, onConnectFailed));
|
||||
if (onConnectFailed)
|
||||
onConnectFailed("Connect to remote endpoint timed out");
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
+18
-50
@@ -27,7 +27,6 @@
|
||||
#define NFD_DAEMON_FACE_TCP_CHANNEL_HPP
|
||||
|
||||
#include "channel.hpp"
|
||||
#include "tcp-face.hpp"
|
||||
#include "core/scheduler.hpp"
|
||||
|
||||
namespace nfd {
|
||||
@@ -55,9 +54,6 @@ public:
|
||||
explicit
|
||||
TcpChannel(const tcp::Endpoint& localEndpoint);
|
||||
|
||||
virtual
|
||||
~TcpChannel();
|
||||
|
||||
/**
|
||||
* \brief Enable listening on the local endpoint, accept connections,
|
||||
* and create faces when remote host makes a connection
|
||||
@@ -81,23 +77,6 @@ public:
|
||||
const ConnectFailedCallback& onConnectFailed,
|
||||
const time::seconds& timeout = time::seconds(4));
|
||||
|
||||
/**
|
||||
* \brief Create a face by establishing connection to the specified
|
||||
* remote host and remote port
|
||||
*
|
||||
* This method will never block and will return immediately. All
|
||||
* necessary hostname and port resolution and connection will happen
|
||||
* in asynchronous mode.
|
||||
*
|
||||
* If connection cannot be established within specified timeout, it
|
||||
* will be aborted.
|
||||
*/
|
||||
void
|
||||
connect(const std::string& remoteHost, const std::string& remotePort,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed,
|
||||
const time::seconds& timeout = time::seconds(4));
|
||||
|
||||
/**
|
||||
* \brief Get number of faces in the channel
|
||||
*/
|
||||
@@ -109,53 +88,42 @@ public:
|
||||
|
||||
private:
|
||||
void
|
||||
createFace(const shared_ptr<boost::asio::ip::tcp::socket>& socket,
|
||||
createFace(boost::asio::ip::tcp::socket socket,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
bool isOnDemand);
|
||||
|
||||
void
|
||||
afterFaceFailed(tcp::Endpoint &endpoint);
|
||||
accept(const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed);
|
||||
|
||||
void
|
||||
handleSuccessfulAccept(const boost::system::error_code& error,
|
||||
const shared_ptr<boost::asio::ip::tcp::socket>& socket,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed);
|
||||
handleAccept(const boost::system::error_code& error,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed);
|
||||
|
||||
void
|
||||
handleSuccessfulConnect(const boost::system::error_code& error,
|
||||
const shared_ptr<boost::asio::ip::tcp::socket>& socket,
|
||||
const scheduler::EventId& connectTimeoutEvent,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed);
|
||||
handleConnect(const boost::system::error_code& error,
|
||||
const shared_ptr<boost::asio::ip::tcp::socket>& socket,
|
||||
const scheduler::EventId& connectTimeoutEvent,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed);
|
||||
|
||||
void
|
||||
handleFailedConnect(const shared_ptr<boost::asio::ip::tcp::socket>& socket,
|
||||
const ConnectFailedCallback& onConnectFailed);
|
||||
|
||||
void
|
||||
handleEndpointResolution(const boost::system::error_code& error,
|
||||
boost::asio::ip::tcp::resolver::iterator remoteEndpoint,
|
||||
const shared_ptr<boost::asio::ip::tcp::socket>& socket,
|
||||
const scheduler::EventId& connectTimeoutEvent,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed,
|
||||
const shared_ptr<boost::asio::ip::tcp::resolver>& resolver);
|
||||
handleConnectTimeout(const shared_ptr<boost::asio::ip::tcp::socket>& socket,
|
||||
const ConnectFailedCallback& onConnectFailed);
|
||||
|
||||
private:
|
||||
std::map<tcp::Endpoint, shared_ptr<Face>> m_channelFaces;
|
||||
|
||||
tcp::Endpoint m_localEndpoint;
|
||||
|
||||
typedef std::map< tcp::Endpoint, shared_ptr<Face> > ChannelFaceMap;
|
||||
ChannelFaceMap m_channelFaces;
|
||||
|
||||
bool m_isListening;
|
||||
shared_ptr<boost::asio::ip::tcp::acceptor> m_acceptor;
|
||||
boost::asio::ip::tcp::acceptor m_acceptor;
|
||||
boost::asio::ip::tcp::socket m_acceptSocket;
|
||||
};
|
||||
|
||||
inline bool
|
||||
TcpChannel::isListening() const
|
||||
{
|
||||
return m_isListening;
|
||||
return m_acceptor.is_open();
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
@@ -32,18 +32,15 @@ NFD_LOG_INCLASS_2TEMPLATE_SPECIALIZATION_DEFINE(StreamFace,
|
||||
TcpLocalFace::protocol, LocalFace,
|
||||
"TcpLocalFace");
|
||||
|
||||
TcpFace::TcpFace(const shared_ptr<TcpFace::protocol::socket>& socket, bool isOnDemand)
|
||||
: StreamFace<protocol>(FaceUri(socket->remote_endpoint()),
|
||||
FaceUri(socket->local_endpoint()),
|
||||
socket, isOnDemand)
|
||||
TcpFace::TcpFace(const FaceUri& remoteUri, const FaceUri& localUri,
|
||||
protocol::socket socket, bool isOnDemand)
|
||||
: StreamFace<protocol>(remoteUri, localUri, std::move(socket), isOnDemand)
|
||||
{
|
||||
}
|
||||
|
||||
TcpLocalFace::TcpLocalFace(const shared_ptr<TcpLocalFace::protocol::socket>& socket,
|
||||
bool isOnDemand)
|
||||
: StreamFace<protocol, LocalFace>(FaceUri(socket->remote_endpoint()),
|
||||
FaceUri(socket->local_endpoint()),
|
||||
socket, isOnDemand)
|
||||
TcpLocalFace::TcpLocalFace(const FaceUri& remoteUri, const FaceUri& localUri,
|
||||
protocol::socket socket, bool isOnDemand)
|
||||
: StreamFace<protocol, LocalFace>(remoteUri, localUri, std::move(socket), isOnDemand)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -36,11 +36,10 @@ namespace nfd {
|
||||
class TcpFace : public StreamFace<boost::asio::ip::tcp>
|
||||
{
|
||||
public:
|
||||
TcpFace(const shared_ptr<protocol::socket>& socket,
|
||||
bool isOnDemand);
|
||||
TcpFace(const FaceUri& remoteUri, const FaceUri& localUri,
|
||||
protocol::socket socket, bool isOnDemand);
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
/**
|
||||
* \brief Implementation of Face abstraction that uses TCP
|
||||
@@ -50,27 +49,27 @@ public:
|
||||
class TcpLocalFace : public StreamFace<boost::asio::ip::tcp, LocalFace>
|
||||
{
|
||||
public:
|
||||
TcpLocalFace(const shared_ptr<protocol::socket>& socket,
|
||||
bool isOnDemand);
|
||||
TcpLocalFace(const FaceUri& remoteUri, const FaceUri& localUri,
|
||||
protocol::socket socket, bool isOnDemand);
|
||||
};
|
||||
|
||||
|
||||
/** \brief Class validating use of TcpLocalFace
|
||||
*/
|
||||
template<>
|
||||
struct StreamFaceValidator<boost::asio::ip::tcp, LocalFace>
|
||||
struct StreamFaceValidator<TcpLocalFace::protocol, LocalFace>
|
||||
{
|
||||
/** Check that local endpoint is loopback
|
||||
*
|
||||
* @throws Face::Error if validation failed
|
||||
*/
|
||||
static void
|
||||
validateSocket(boost::asio::ip::tcp::socket& socket)
|
||||
validateSocket(const TcpLocalFace::protocol::socket& socket)
|
||||
{
|
||||
if (!socket.local_endpoint().address().is_loopback() ||
|
||||
!socket.remote_endpoint().address().is_loopback())
|
||||
{
|
||||
throw Face::Error("TcpLocalFace can be created only on loopback interface");
|
||||
throw Face::Error("TcpLocalFace can be created only on a loopback address");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
+84
-178
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
#include "udp-channel.hpp"
|
||||
#include "udp-face.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
|
||||
namespace nfd {
|
||||
@@ -35,126 +36,54 @@ using namespace boost::asio;
|
||||
UdpChannel::UdpChannel(const udp::Endpoint& localEndpoint,
|
||||
const time::seconds& timeout)
|
||||
: m_localEndpoint(localEndpoint)
|
||||
, m_isListening(false)
|
||||
, m_socket(getGlobalIoService())
|
||||
, m_idleFaceTimeout(timeout)
|
||||
{
|
||||
/// \todo the reuse_address works as we want in Linux, but in other system could be different.
|
||||
/// We need to check this
|
||||
/// (SO_REUSEADDR doesn't behave uniformly in different OS)
|
||||
|
||||
m_socket = make_shared<ip::udp::socket>(ref(getGlobalIoService()));
|
||||
m_socket->open(m_localEndpoint.protocol());
|
||||
m_socket->set_option(boost::asio::ip::udp::socket::reuse_address(true));
|
||||
if (m_localEndpoint.address().is_v6())
|
||||
{
|
||||
m_socket->set_option(ip::v6_only(true));
|
||||
}
|
||||
|
||||
try {
|
||||
m_socket->bind(m_localEndpoint);
|
||||
}
|
||||
catch (boost::system::system_error& e) {
|
||||
//The bind failed, so the socket is useless now
|
||||
m_socket->close();
|
||||
throw Error("Failed to properly configure the socket. "
|
||||
"UdpChannel creation aborted, check the address (" + std::string(e.what()) + ")");
|
||||
}
|
||||
|
||||
this->setUri(FaceUri(localEndpoint));
|
||||
setUri(FaceUri(m_localEndpoint));
|
||||
}
|
||||
|
||||
void
|
||||
UdpChannel::listen(const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onListenFailed)
|
||||
const ConnectFailedCallback& onReceiveFailed)
|
||||
{
|
||||
if (m_isListening) {
|
||||
throw Error("Listen already called on this channel");
|
||||
if (isListening()) {
|
||||
NFD_LOG_WARN("[" << m_localEndpoint << "] Already listening");
|
||||
return;
|
||||
}
|
||||
m_isListening = true;
|
||||
|
||||
onFaceCreatedNewPeerCallback = onFaceCreated;
|
||||
onConnectFailedNewPeerCallback = onListenFailed;
|
||||
m_socket.open(m_localEndpoint.protocol());
|
||||
m_socket.set_option(ip::udp::socket::reuse_address(true));
|
||||
if (m_localEndpoint.address().is_v6())
|
||||
m_socket.set_option(ip::v6_only(true));
|
||||
|
||||
m_socket->async_receive_from(boost::asio::buffer(m_inputBuffer, ndn::MAX_NDN_PACKET_SIZE),
|
||||
m_newRemoteEndpoint,
|
||||
bind(&UdpChannel::newPeer, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
m_socket.bind(m_localEndpoint);
|
||||
m_socket.async_receive_from(boost::asio::buffer(m_inputBuffer, ndn::MAX_NDN_PACKET_SIZE),
|
||||
m_remoteEndpoint,
|
||||
bind(&UdpChannel::handleNewPeer, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred,
|
||||
onFaceCreated, onReceiveFailed));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UdpChannel::connect(const udp::Endpoint& remoteEndpoint,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed)
|
||||
{
|
||||
ChannelFaceMap::iterator i = m_channelFaces.find(remoteEndpoint);
|
||||
if (i != m_channelFaces.end()) {
|
||||
i->second->setOnDemand(false);
|
||||
onFaceCreated(i->second);
|
||||
return;
|
||||
}
|
||||
|
||||
//creating a new socket for the face that will be created soon
|
||||
shared_ptr<ip::udp::socket> clientSocket =
|
||||
make_shared<ip::udp::socket>(ref(getGlobalIoService()));
|
||||
|
||||
clientSocket->open(m_localEndpoint.protocol());
|
||||
clientSocket->set_option(ip::udp::socket::reuse_address(true));
|
||||
|
||||
shared_ptr<UdpFace> face;
|
||||
try {
|
||||
clientSocket->bind(m_localEndpoint);
|
||||
clientSocket->connect(remoteEndpoint); //@todo connect or async_connect
|
||||
//(since there is no handshake the connect shouldn't block). If we go for
|
||||
//async_connect, make sure that if in the meantime we receive a UDP pkt from
|
||||
//that endpoint nothing bad happen (it's difficult, but it could happen)
|
||||
face = createFace(remoteEndpoint, false).second;
|
||||
}
|
||||
catch (boost::system::system_error& e) {
|
||||
clientSocket->close();
|
||||
onConnectFailed("Failed to configure socket (" + std::string(e.what()) + ")");
|
||||
catch (const boost::system::system_error& e) {
|
||||
NFD_LOG_WARN("[" << m_localEndpoint << "] Connect failed: " << e.what());
|
||||
if (onConnectFailed)
|
||||
onConnectFailed(e.what());
|
||||
return;
|
||||
}
|
||||
createFace(clientSocket, onFaceCreated, false);
|
||||
}
|
||||
|
||||
void
|
||||
UdpChannel::connect(const std::string& remoteHost,
|
||||
const std::string& remotePort,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed)
|
||||
{
|
||||
ip::udp::resolver::query query(remoteHost, remotePort);
|
||||
shared_ptr<ip::udp::resolver> resolver =
|
||||
make_shared<ip::udp::resolver>(ref(getGlobalIoService()));
|
||||
|
||||
resolver->async_resolve(query,
|
||||
bind(&UdpChannel::handleEndpointResolution, this, _1, _2,
|
||||
onFaceCreated, onConnectFailed,
|
||||
resolver));
|
||||
}
|
||||
|
||||
void
|
||||
UdpChannel::handleEndpointResolution(const boost::system::error_code& error,
|
||||
ip::udp::resolver::iterator remoteEndpoint,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed,
|
||||
const shared_ptr<ip::udp::resolver>& resolver)
|
||||
{
|
||||
if (error != 0 ||
|
||||
remoteEndpoint == ip::udp::resolver::iterator())
|
||||
{
|
||||
if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
|
||||
return;
|
||||
|
||||
NFD_LOG_DEBUG("Remote endpoint hostname or port cannot be resolved: "
|
||||
<< error.category().message(error.value()));
|
||||
|
||||
onConnectFailed("Remote endpoint hostname or port cannot be resolved: " +
|
||||
error.category().message(error.value()));
|
||||
return;
|
||||
}
|
||||
|
||||
connect(*remoteEndpoint, onFaceCreated, onConnectFailed);
|
||||
// Need to invoke the callback regardless of whether or not we had already
|
||||
// created the face so that control responses and such can be sent
|
||||
onFaceCreated(face);
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -163,102 +92,79 @@ UdpChannel::size() const
|
||||
return m_channelFaces.size();
|
||||
}
|
||||
|
||||
|
||||
shared_ptr<UdpFace>
|
||||
UdpChannel::createFace(const shared_ptr<ip::udp::socket>& socket,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
bool isOnDemand)
|
||||
std::pair<bool, shared_ptr<UdpFace>>
|
||||
UdpChannel::createFace(const udp::Endpoint& remoteEndpoint, bool isOnDemand)
|
||||
{
|
||||
udp::Endpoint remoteEndpoint = socket->remote_endpoint();
|
||||
auto it = m_channelFaces.find(remoteEndpoint);
|
||||
if (it != m_channelFaces.end()) {
|
||||
// we already have a face for this endpoint, just reuse it
|
||||
if (!isOnDemand)
|
||||
// only on-demand -> non-on-demand transition is allowed
|
||||
it->second->setOnDemand(false);
|
||||
return {false, it->second};
|
||||
}
|
||||
|
||||
shared_ptr<UdpFace> face;
|
||||
// else, create a new face
|
||||
ip::udp::socket socket(getGlobalIoService(), m_localEndpoint.protocol());
|
||||
socket.set_option(ip::udp::socket::reuse_address(true));
|
||||
socket.bind(m_localEndpoint);
|
||||
socket.connect(remoteEndpoint);
|
||||
|
||||
ChannelFaceMap::iterator faceMapPos = m_channelFaces.find(remoteEndpoint);
|
||||
if (faceMapPos == m_channelFaces.end())
|
||||
{
|
||||
face = make_shared<UdpFace>(socket, isOnDemand, m_idleFaceTimeout);
|
||||
auto face = make_shared<UdpFace>(FaceUri(remoteEndpoint), FaceUri(m_localEndpoint),
|
||||
std::move(socket), isOnDemand, m_idleFaceTimeout);
|
||||
|
||||
face->onFail.connectSingleShot(bind(&UdpChannel::afterFaceFailed, this, remoteEndpoint));
|
||||
face->onFail.connectSingleShot([this, remoteEndpoint] (const std::string&) {
|
||||
NFD_LOG_TRACE("Erasing " << remoteEndpoint << " from channel face map");
|
||||
m_channelFaces.erase(remoteEndpoint);
|
||||
});
|
||||
m_channelFaces[remoteEndpoint] = face;
|
||||
|
||||
m_channelFaces[remoteEndpoint] = face;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we've already created a a face for this endpoint, just reuse it
|
||||
face = faceMapPos->second;
|
||||
|
||||
boost::system::error_code error;
|
||||
socket->shutdown(ip::udp::socket::shutdown_both, error);
|
||||
socket->close(error);
|
||||
}
|
||||
|
||||
// Need to invoke the callback regardless of whether or not we have already created
|
||||
// the face so that control responses and such can be sent.
|
||||
onFaceCreated(face);
|
||||
|
||||
return face;
|
||||
return {true, face};
|
||||
}
|
||||
|
||||
void
|
||||
UdpChannel::newPeer(const boost::system::error_code& error,
|
||||
size_t nBytesReceived)
|
||||
UdpChannel::handleNewPeer(const boost::system::error_code& error,
|
||||
size_t nBytesReceived,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onReceiveFailed)
|
||||
{
|
||||
NFD_LOG_DEBUG("UdpChannel::newPeer from " << m_newRemoteEndpoint);
|
||||
|
||||
shared_ptr<UdpFace> face;
|
||||
|
||||
ChannelFaceMap::iterator i = m_channelFaces.find(m_newRemoteEndpoint);
|
||||
if (i != m_channelFaces.end()) {
|
||||
//The face already exists.
|
||||
//Usually this shouldn't happen, because the channel creates a Udpface
|
||||
//as soon as it receives a pkt from a new endpoint and then the
|
||||
//traffic is dispatched by the kernel directly to the face.
|
||||
//However, if the node receives multiple packets from the same endpoint
|
||||
//"at the same time", while the channel is creating the face the kernel
|
||||
//could dispatch the other pkts to the channel because the face is not yet
|
||||
//ready. In this case, the channel has to pass the pkt to the face
|
||||
|
||||
NFD_LOG_DEBUG("The creation of the face for the remote endpoint "
|
||||
<< m_newRemoteEndpoint
|
||||
<< " is in progress");
|
||||
|
||||
face = i->second;
|
||||
}
|
||||
else {
|
||||
shared_ptr<ip::udp::socket> clientSocket =
|
||||
make_shared<ip::udp::socket>(ref(getGlobalIoService()));
|
||||
clientSocket->open(m_localEndpoint.protocol());
|
||||
clientSocket->set_option(ip::udp::socket::reuse_address(true));
|
||||
clientSocket->bind(m_localEndpoint);
|
||||
boost::system::error_code ec;
|
||||
clientSocket->connect(m_newRemoteEndpoint, ec);
|
||||
if (ec) {
|
||||
NFD_LOG_WARN("Error while creating on-demand UDP face from " << m_newRemoteEndpoint << ": "
|
||||
<< boost::system::system_error(ec).what());
|
||||
if (error) {
|
||||
if (error == boost::asio::error::operation_aborted) // when the socket is closed by someone
|
||||
return;
|
||||
}
|
||||
|
||||
face = createFace(clientSocket,
|
||||
onFaceCreatedNewPeerCallback,
|
||||
true);
|
||||
NFD_LOG_DEBUG("[" << m_localEndpoint << "] Receive failed: " << error.message());
|
||||
if (onReceiveFailed)
|
||||
onReceiveFailed(error.message());
|
||||
return;
|
||||
}
|
||||
|
||||
NFD_LOG_DEBUG("[" << m_localEndpoint << "] New peer " << m_remoteEndpoint);
|
||||
|
||||
bool created;
|
||||
shared_ptr<UdpFace> face;
|
||||
try {
|
||||
std::tie(created, face) = createFace(m_remoteEndpoint, true);
|
||||
}
|
||||
catch (const boost::system::system_error& e) {
|
||||
NFD_LOG_WARN("[" << m_localEndpoint << "] Failed to create face for peer "
|
||||
<< m_remoteEndpoint << ": " << e.what());
|
||||
if (onReceiveFailed)
|
||||
onReceiveFailed(e.what());
|
||||
return;
|
||||
}
|
||||
|
||||
if (created)
|
||||
onFaceCreated(face);
|
||||
|
||||
// dispatch the datagram to the face for processing
|
||||
face->receiveDatagram(m_inputBuffer, nBytesReceived, error);
|
||||
|
||||
m_socket->async_receive_from(boost::asio::buffer(m_inputBuffer, ndn::MAX_NDN_PACKET_SIZE),
|
||||
m_newRemoteEndpoint,
|
||||
bind(&UdpChannel::newPeer, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UdpChannel::afterFaceFailed(udp::Endpoint &endpoint)
|
||||
{
|
||||
NFD_LOG_DEBUG("afterFaceFailed: " << endpoint);
|
||||
m_channelFaces.erase(endpoint);
|
||||
m_socket.async_receive_from(boost::asio::buffer(m_inputBuffer, ndn::MAX_NDN_PACKET_SIZE),
|
||||
m_remoteEndpoint,
|
||||
bind(&UdpChannel::handleNewPeer, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred,
|
||||
onFaceCreated, onReceiveFailed));
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
+28
-69
@@ -27,8 +27,6 @@
|
||||
#define NFD_DAEMON_FACE_UDP_CHANNEL_HPP
|
||||
|
||||
#include "channel.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
#include "udp-face.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
@@ -36,22 +34,14 @@ namespace udp {
|
||||
typedef boost::asio::ip::udp::endpoint Endpoint;
|
||||
} // namespace udp
|
||||
|
||||
class UdpFace;
|
||||
|
||||
/**
|
||||
* \brief Class implementing UDP-based channel to create faces
|
||||
*
|
||||
*
|
||||
*/
|
||||
class UdpChannel : public Channel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Exception of UdpChannel
|
||||
*/
|
||||
struct Error : public std::runtime_error
|
||||
{
|
||||
Error(const std::string& what) : runtime_error(what) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Create UDP channel for the local endpoint
|
||||
*
|
||||
@@ -79,7 +69,7 @@ public:
|
||||
*/
|
||||
void
|
||||
listen(const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onAcceptFailed);
|
||||
const ConnectFailedCallback& onReceiveFailed);
|
||||
|
||||
/**
|
||||
* \brief Create a face by establishing connection to remote endpoint
|
||||
@@ -90,21 +80,6 @@ public:
|
||||
connect(const udp::Endpoint& remoteEndpoint,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed);
|
||||
/**
|
||||
* \brief Create a face by establishing connection to the specified
|
||||
* remote host and remote port
|
||||
*
|
||||
* This method will never block and will return immediately. All
|
||||
* necessary hostname and port resolution and connection will happen
|
||||
* in asynchronous mode.
|
||||
*
|
||||
* If connection cannot be established within specified timeout, it
|
||||
* will be aborted.
|
||||
*/
|
||||
void
|
||||
connect(const std::string& remoteHost, const std::string& remotePort,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed);
|
||||
|
||||
/**
|
||||
* \brief Get number of faces in the channel
|
||||
@@ -112,68 +87,52 @@ public:
|
||||
size_t
|
||||
size() const;
|
||||
|
||||
bool
|
||||
isListening() const;
|
||||
|
||||
private:
|
||||
shared_ptr<UdpFace>
|
||||
createFace(const shared_ptr<boost::asio::ip::udp::socket>& socket,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
bool isOnDemand);
|
||||
void
|
||||
afterFaceFailed(udp::Endpoint& endpoint);
|
||||
std::pair<bool, shared_ptr<UdpFace>>
|
||||
createFace(const udp::Endpoint& remoteEndpoint, bool isOnDemand);
|
||||
|
||||
/**
|
||||
* \brief The UdpChannel has received a new pkt from a remote endpoint not yet
|
||||
* associated with any UdpFace
|
||||
* \brief The channel has received a new packet from a remote
|
||||
* endpoint that is not associated with any UdpFace yet
|
||||
*/
|
||||
void
|
||||
newPeer(const boost::system::error_code& error, size_t nBytesReceived);
|
||||
|
||||
void
|
||||
handleEndpointResolution(const boost::system::error_code& error,
|
||||
boost::asio::ip::udp::resolver::iterator remoteEndpoint,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed,
|
||||
const shared_ptr<boost::asio::ip::udp::resolver>& resolver);
|
||||
handleNewPeer(const boost::system::error_code& error,
|
||||
size_t nBytesReceived,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onReceiveFailed);
|
||||
|
||||
private:
|
||||
std::map<udp::Endpoint, shared_ptr<UdpFace>> m_channelFaces;
|
||||
|
||||
udp::Endpoint m_localEndpoint;
|
||||
|
||||
/**
|
||||
* \brief Endpoint used to store the information about the last new remote endpoint
|
||||
* \brief The latest peer that started communicating with us
|
||||
*/
|
||||
udp::Endpoint m_newRemoteEndpoint;
|
||||
|
||||
/**
|
||||
* Callbacks for face creation.
|
||||
* New communications are detected using async_receive_from.
|
||||
* Its handler has a fixed signature. No space for the face callback
|
||||
*/
|
||||
FaceCreatedCallback onFaceCreatedNewPeerCallback;
|
||||
|
||||
// @todo remove the onConnectFailedNewPeerCallback if it remains unused
|
||||
ConnectFailedCallback onConnectFailedNewPeerCallback;
|
||||
udp::Endpoint m_remoteEndpoint;
|
||||
|
||||
/**
|
||||
* \brief Socket used to "accept" new communication
|
||||
**/
|
||||
shared_ptr<boost::asio::ip::udp::socket> m_socket;
|
||||
|
||||
uint8_t m_inputBuffer[ndn::MAX_NDN_PACKET_SIZE];
|
||||
|
||||
typedef std::map< udp::Endpoint, shared_ptr<UdpFace> > ChannelFaceMap;
|
||||
ChannelFaceMap m_channelFaces;
|
||||
|
||||
/**
|
||||
* \brief If true, it means the function listen has already been called
|
||||
*/
|
||||
bool m_isListening;
|
||||
boost::asio::ip::udp::socket m_socket;
|
||||
|
||||
/**
|
||||
* \brief every time m_idleFaceTimeout expires all the idle (and on-demand)
|
||||
* faces will be removed
|
||||
* \brief When this timeout expires, all idle on-demand faces will be closed
|
||||
*/
|
||||
time::seconds m_idleFaceTimeout;
|
||||
|
||||
uint8_t m_inputBuffer[ndn::MAX_NDN_PACKET_SIZE];
|
||||
};
|
||||
|
||||
inline bool
|
||||
UdpChannel::isListening() const
|
||||
{
|
||||
return m_socket.is_open();
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_UDP_CHANNEL_HPP
|
||||
+22
-33
@@ -37,15 +37,15 @@ namespace nfd {
|
||||
|
||||
NFD_LOG_INCLASS_TEMPLATE_SPECIALIZATION_DEFINE(DatagramFace, UdpFace::protocol, "UdpFace");
|
||||
|
||||
UdpFace::UdpFace(const shared_ptr<UdpFace::protocol::socket>& socket,
|
||||
bool isOnDemand,
|
||||
UdpFace::UdpFace(const FaceUri& remoteUri, const FaceUri& localUri,
|
||||
protocol::socket socket, bool isOnDemand,
|
||||
const time::seconds& idleTimeout)
|
||||
: DatagramFace<protocol>(FaceUri(socket->remote_endpoint()),
|
||||
FaceUri(socket->local_endpoint()),
|
||||
socket, isOnDemand)
|
||||
: DatagramFace(remoteUri, localUri, std::move(socket))
|
||||
, m_idleTimeout(idleTimeout)
|
||||
, m_lastIdleCheck(time::steady_clock::now())
|
||||
{
|
||||
this->setOnDemand(isOnDemand);
|
||||
|
||||
#ifdef __linux__
|
||||
//
|
||||
// By default, Linux does path MTU discovery on IPv4 sockets,
|
||||
@@ -60,42 +60,33 @@ UdpFace::UdpFace(const shared_ptr<UdpFace::protocol::socket>& socket,
|
||||
// routers along the path to perform fragmentation as needed.
|
||||
//
|
||||
const int value = IP_PMTUDISC_DONT;
|
||||
if (::setsockopt(socket->native_handle(), IPPROTO_IP,
|
||||
IP_MTU_DISCOVER, &value, sizeof(value)) < 0)
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Failed to disable path MTU discovery: " << std::strerror(errno));
|
||||
}
|
||||
if (::setsockopt(m_socket.native_handle(), IPPROTO_IP,
|
||||
IP_MTU_DISCOVER, &value, sizeof(value)) < 0) {
|
||||
NFD_LOG_FACE_WARN("Failed to disable path MTU discovery: " << std::strerror(errno));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (isOnDemand && m_idleTimeout > time::seconds::zero()) {
|
||||
m_closeIfIdleEvent = scheduler::schedule(m_idleTimeout,
|
||||
bind(&UdpFace::closeIfIdle, this));
|
||||
if (this->isOnDemand() && m_idleTimeout > time::seconds::zero()) {
|
||||
m_closeIfIdleEvent = scheduler::schedule(m_idleTimeout, bind(&UdpFace::closeIfIdle, this));
|
||||
}
|
||||
}
|
||||
|
||||
UdpFace::~UdpFace()
|
||||
{
|
||||
scheduler::cancel(m_closeIfIdleEvent);
|
||||
}
|
||||
|
||||
ndn::nfd::FaceStatus
|
||||
UdpFace::getFaceStatus() const
|
||||
{
|
||||
auto status = Face::getFaceStatus();
|
||||
auto status = DatagramFace::getFaceStatus();
|
||||
|
||||
if (isOnDemand()) {
|
||||
time::milliseconds left = m_idleTimeout - time::duration_cast<time::milliseconds>(
|
||||
time::steady_clock::now() - m_lastIdleCheck);
|
||||
time::milliseconds left = m_idleTimeout;
|
||||
left -= time::duration_cast<time::milliseconds>(time::steady_clock::now() - m_lastIdleCheck);
|
||||
|
||||
if (left < time::milliseconds::zero())
|
||||
left = time::milliseconds::zero();
|
||||
|
||||
if (hasBeenUsedRecently()) {
|
||||
status.setExpirationPeriod(left + m_idleTimeout);
|
||||
}
|
||||
else {
|
||||
status.setExpirationPeriod(left);
|
||||
}
|
||||
if (hasBeenUsedRecently())
|
||||
left += m_idleTimeout;
|
||||
|
||||
status.setExpirationPeriod(left);
|
||||
}
|
||||
|
||||
return status;
|
||||
@@ -108,22 +99,20 @@ UdpFace::closeIfIdle()
|
||||
// (non-on-demand -> on-demand transition is not allowed)
|
||||
if (isOnDemand()) {
|
||||
if (!hasBeenUsedRecently()) {
|
||||
NFD_LOG_INFO("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
|
||||
<< "] Idle for more than " << m_idleTimeout << ", closing");
|
||||
NFD_LOG_FACE_INFO("Closing for inactivity");
|
||||
close();
|
||||
|
||||
// #1718 manual test: uncomment, run NFD in valgrind, send in a UDP packet
|
||||
// expect read-after-free error and crash
|
||||
// getGlobalIoService().post([this] {
|
||||
// NFD_LOG_ERROR("Remaining references: " << this->shared_from_this().use_count());
|
||||
// NFD_LOG_FACE_ERROR("Remaining references: " << this->shared_from_this().use_count());
|
||||
// });
|
||||
}
|
||||
else {
|
||||
resetRecentUsage();
|
||||
|
||||
m_lastIdleCheck = time::steady_clock::now();
|
||||
m_closeIfIdleEvent = scheduler::schedule(m_idleTimeout,
|
||||
bind(&UdpFace::closeIfIdle, this));
|
||||
m_closeIfIdleEvent = scheduler::schedule(m_idleTimeout, bind(&UdpFace::closeIfIdle, this));
|
||||
}
|
||||
}
|
||||
// else do nothing and do not reschedule the event
|
||||
|
||||
@@ -32,18 +32,16 @@
|
||||
namespace nfd {
|
||||
|
||||
/**
|
||||
* \brief Implementation of Face abstraction that uses UDP
|
||||
* as underlying transport mechanism
|
||||
* \brief Implementation of Face abstraction that uses
|
||||
* unicast UDP as underlying transport mechanism
|
||||
*/
|
||||
class UdpFace : public DatagramFace<boost::asio::ip::udp>
|
||||
{
|
||||
public:
|
||||
UdpFace(const shared_ptr<protocol::socket>& socket,
|
||||
bool isOnDemand,
|
||||
UdpFace(const FaceUri& remoteUri, const FaceUri& localUri,
|
||||
protocol::socket socket, bool isOnDemand,
|
||||
const time::seconds& idleTimeout);
|
||||
|
||||
~UdpFace() DECL_OVERRIDE;
|
||||
|
||||
ndn::nfd::FaceStatus
|
||||
getFaceStatus() const DECL_OVERRIDE;
|
||||
|
||||
@@ -52,9 +50,12 @@ private:
|
||||
closeIfIdle();
|
||||
|
||||
private:
|
||||
scheduler::EventId m_closeIfIdleEvent;
|
||||
time::seconds m_idleTimeout;
|
||||
const time::seconds m_idleTimeout;
|
||||
time::steady_clock::TimePoint m_lastIdleCheck;
|
||||
scheduler::ScopedEventId m_closeIfIdleEvent;
|
||||
|
||||
// friend because it needs to invoke protected Face::setOnDemand
|
||||
friend class UdpChannel;
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
+57
-80
@@ -27,8 +27,10 @@
|
||||
#include "core/global-io.hpp"
|
||||
#include "core/network-interface.hpp"
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <sys/socket.h>
|
||||
#ifdef __linux__
|
||||
#include <cerrno> // for errno
|
||||
#include <cstring> // for std::strerror()
|
||||
#include <sys/socket.h> // for setsockopt()
|
||||
#endif
|
||||
|
||||
namespace nfd {
|
||||
@@ -147,20 +149,20 @@ UdpFactory::createChannel(const std::string& localIp,
|
||||
shared_ptr<MulticastUdpFace>
|
||||
UdpFactory::createMulticastFace(const udp::Endpoint& localEndpoint,
|
||||
const udp::Endpoint& multicastEndpoint,
|
||||
const std::string& networkInterfaceName /* "" */)
|
||||
const std::string& networkInterfaceName/* = ""*/)
|
||||
{
|
||||
//checking if the local and multicast endpoint are already in use for a multicast face
|
||||
shared_ptr<MulticastUdpFace> multicastFace = findMulticastFace(localEndpoint);
|
||||
if (static_cast<bool>(multicastFace)) {
|
||||
if (multicastFace->getMulticastGroup() == multicastEndpoint)
|
||||
return multicastFace;
|
||||
// checking if the local and multicast endpoints are already in use for a multicast face
|
||||
shared_ptr<MulticastUdpFace> face = findMulticastFace(localEndpoint);
|
||||
if (static_cast<bool>(face)) {
|
||||
if (face->getMulticastGroup() == multicastEndpoint)
|
||||
return face;
|
||||
else
|
||||
throw Error("Cannot create the requested UDP multicast face, local "
|
||||
"endpoint is already allocated for a UDP multicast face "
|
||||
"on a different multicast group");
|
||||
}
|
||||
|
||||
//checking if the local endpoint is already in use for an unicast channel
|
||||
// checking if the local endpoint is already in use for a unicast channel
|
||||
shared_ptr<UdpChannel> unicast = findChannel(localEndpoint);
|
||||
if (static_cast<bool>(unicast)) {
|
||||
throw Error("Cannot create the requested UDP multicast face, local "
|
||||
@@ -186,79 +188,63 @@ UdpFactory::createMulticastFace(const udp::Endpoint& localEndpoint,
|
||||
"the multicast group given as input is not a multicast address");
|
||||
}
|
||||
|
||||
shared_ptr<ip::udp::socket> receiveSocket =
|
||||
make_shared<ip::udp::socket>(ref(getGlobalIoService()));
|
||||
ip::udp::socket receiveSocket(getGlobalIoService());
|
||||
receiveSocket.open(multicastEndpoint.protocol());
|
||||
receiveSocket.set_option(ip::udp::socket::reuse_address(true));
|
||||
receiveSocket.bind(multicastEndpoint);
|
||||
|
||||
shared_ptr<ip::udp::socket> sendSocket =
|
||||
make_shared<ip::udp::socket>(ref(getGlobalIoService()));
|
||||
ip::udp::socket sendSocket(getGlobalIoService());
|
||||
sendSocket.open(multicastEndpoint.protocol());
|
||||
sendSocket.set_option(ip::udp::socket::reuse_address(true));
|
||||
sendSocket.set_option(ip::multicast::enable_loopback(false));
|
||||
sendSocket.bind(udp::Endpoint(ip::address_v4::any(), multicastEndpoint.port()));
|
||||
if (localEndpoint.address() != ALL_V4_ENDPOINT)
|
||||
sendSocket.set_option(ip::multicast::outbound_interface(localEndpoint.address().to_v4()));
|
||||
|
||||
receiveSocket->open(multicastEndpoint.protocol());
|
||||
receiveSocket->set_option(ip::udp::socket::reuse_address(true));
|
||||
|
||||
sendSocket->open(multicastEndpoint.protocol());
|
||||
sendSocket->set_option(ip::udp::socket::reuse_address(true));
|
||||
sendSocket->set_option(ip::multicast::enable_loopback(false));
|
||||
|
||||
try {
|
||||
sendSocket->bind(udp::Endpoint(ip::address_v4::any(), multicastEndpoint.port()));
|
||||
receiveSocket->bind(multicastEndpoint);
|
||||
|
||||
if (localEndpoint.address() != ip::address::from_string("0.0.0.0")) {
|
||||
sendSocket->set_option(ip::multicast::outbound_interface(localEndpoint.address().to_v4()));
|
||||
}
|
||||
sendSocket->set_option(ip::multicast::join_group(multicastEndpoint.address().to_v4(),
|
||||
sendSocket.set_option(ip::multicast::join_group(multicastEndpoint.address().to_v4(),
|
||||
localEndpoint.address().to_v4()));
|
||||
receiveSocket.set_option(ip::multicast::join_group(multicastEndpoint.address().to_v4(),
|
||||
localEndpoint.address().to_v4()));
|
||||
|
||||
receiveSocket->set_option(ip::multicast::join_group(multicastEndpoint.address().to_v4(),
|
||||
localEndpoint.address().to_v4()));
|
||||
}
|
||||
catch (boost::system::system_error& e) {
|
||||
std::stringstream msg;
|
||||
msg << "Failed to properly configure the socket, check the address (" << e.what() << ")";
|
||||
throw Error(msg.str());
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
//On linux system, if there are more than one MulticastUdpFace for the same multicast group but
|
||||
//bound on different network interfaces, the socket has to be bound with the specific interface
|
||||
//using SO_BINDTODEVICE, otherwise the face will receive packets also from other interfaces.
|
||||
//Without SO_BINDTODEVICE every MulticastUdpFace that have joined the same multicast group
|
||||
//on different interfaces will receive the same packet.
|
||||
//This applies only on linux, for OS X the ip::multicast::join_group is enough to get
|
||||
//the desired behaviour
|
||||
#ifdef __linux__
|
||||
/*
|
||||
* On Linux, if there is more than one MulticastUdpFace for the same multicast
|
||||
* group but they are bound to different network interfaces, the socket needs
|
||||
* to be bound to the specific interface using SO_BINDTODEVICE, otherwise the
|
||||
* face will receive all packets sent to the other interfaces as well.
|
||||
* This happens only on Linux. On OS X, the ip::multicast::join_group option
|
||||
* is enough to get the desired behaviour.
|
||||
*/
|
||||
if (!networkInterfaceName.empty()) {
|
||||
if (::setsockopt(receiveSocket->native_handle(), SOL_SOCKET, SO_BINDTODEVICE,
|
||||
networkInterfaceName.c_str(), networkInterfaceName.size()+1) == -1){
|
||||
throw Error("Cannot bind multicast face to " + networkInterfaceName
|
||||
+ " make sure you have CAP_NET_RAW capability" );
|
||||
if (::setsockopt(receiveSocket.native_handle(), SOL_SOCKET, SO_BINDTODEVICE,
|
||||
networkInterfaceName.c_str(), networkInterfaceName.size() + 1) < 0) {
|
||||
throw Error("Cannot bind multicast face to " + networkInterfaceName +
|
||||
": " + std::strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
multicastFace = make_shared<MulticastUdpFace>(receiveSocket, sendSocket,
|
||||
localEndpoint, multicastEndpoint);
|
||||
face = make_shared<MulticastUdpFace>(multicastEndpoint, FaceUri(localEndpoint),
|
||||
std::move(receiveSocket), std::move(sendSocket));
|
||||
|
||||
multicastFace->onFail.connectSingleShot(bind(&UdpFactory::afterFaceFailed, this, localEndpoint));
|
||||
face->onFail.connectSingleShot([this, localEndpoint] (const std::string& reason) {
|
||||
m_multicastFaces.erase(localEndpoint);
|
||||
});
|
||||
m_multicastFaces[localEndpoint] = face;
|
||||
|
||||
m_multicastFaces[localEndpoint] = multicastFace;
|
||||
|
||||
return multicastFace;
|
||||
return face;
|
||||
}
|
||||
|
||||
shared_ptr<MulticastUdpFace>
|
||||
UdpFactory::createMulticastFace(const std::string& localIp,
|
||||
const std::string& multicastIp,
|
||||
const std::string& multicastPort,
|
||||
const std::string& networkInterfaceName /* "" */)
|
||||
const std::string& networkInterfaceName/* = ""*/)
|
||||
{
|
||||
using namespace boost::asio::ip;
|
||||
udp::Endpoint localEndpoint(address::from_string(localIp),
|
||||
udp::Endpoint localEndpoint(ip::address::from_string(localIp),
|
||||
boost::lexical_cast<uint16_t>(multicastPort));
|
||||
|
||||
udp::Endpoint multicastEndpoint(address::from_string(multicastIp),
|
||||
udp::Endpoint multicastEndpoint(ip::address::from_string(multicastIp),
|
||||
boost::lexical_cast<uint16_t>(multicastPort));
|
||||
|
||||
return createMulticastFace(localEndpoint, multicastEndpoint, networkInterfaceName);
|
||||
}
|
||||
|
||||
@@ -268,6 +254,7 @@ UdpFactory::createFace(const FaceUri& uri,
|
||||
const FaceConnectFailedCallback& onConnectFailed)
|
||||
{
|
||||
BOOST_ASSERT(uri.isCanonical());
|
||||
|
||||
boost::asio::ip::address ipAddress = boost::asio::ip::address::from_string(uri.getHost());
|
||||
udp::Endpoint endpoint(ipAddress, boost::lexical_cast<uint16_t>(uri.getPort()));
|
||||
|
||||
@@ -276,15 +263,13 @@ UdpFactory::createFace(const FaceUri& uri,
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_prohibitedEndpoints.find(endpoint) != m_prohibitedEndpoints.end())
|
||||
{
|
||||
onConnectFailed("Requested endpoint is prohibited "
|
||||
"(reserved by this NFD or disallowed by face management protocol)");
|
||||
return;
|
||||
}
|
||||
if (m_prohibitedEndpoints.find(endpoint) != m_prohibitedEndpoints.end()) {
|
||||
onConnectFailed("Requested endpoint is prohibited "
|
||||
"(reserved by this NFD or disallowed by face management protocol)");
|
||||
return;
|
||||
}
|
||||
|
||||
// very simple logic for now
|
||||
|
||||
for (ChannelMap::iterator channel = m_channels.begin();
|
||||
channel != m_channels.end();
|
||||
++channel)
|
||||
@@ -296,6 +281,7 @@ UdpFactory::createFace(const FaceUri& uri,
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
onConnectFailed("No channels available to connect to " +
|
||||
boost::lexical_cast<std::string>(endpoint));
|
||||
}
|
||||
@@ -320,17 +306,10 @@ UdpFactory::findMulticastFace(const udp::Endpoint& localEndpoint)
|
||||
return shared_ptr<MulticastUdpFace>();
|
||||
}
|
||||
|
||||
void
|
||||
UdpFactory::afterFaceFailed(udp::Endpoint& endpoint)
|
||||
{
|
||||
NFD_LOG_DEBUG("afterFaceFailed: " << endpoint);
|
||||
m_multicastFaces.erase(endpoint);
|
||||
}
|
||||
|
||||
std::list<shared_ptr<const Channel> >
|
||||
std::list<shared_ptr<const Channel>>
|
||||
UdpFactory::getChannels() const
|
||||
{
|
||||
std::list<shared_ptr<const Channel> > channels;
|
||||
std::list<shared_ptr<const Channel>> channels;
|
||||
for (ChannelMap::const_iterator i = m_channels.begin(); i != m_channels.end(); ++i)
|
||||
{
|
||||
channels.push_back(i->second);
|
||||
@@ -339,6 +318,4 @@ UdpFactory::getChannels() const
|
||||
return channels;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace nfd
|
||||
@@ -30,10 +30,9 @@
|
||||
#include "udp-channel.hpp"
|
||||
#include "multicast-udp-face.hpp"
|
||||
|
||||
|
||||
namespace nfd {
|
||||
|
||||
// @todo The multicast support for ipv6 must be implemented
|
||||
/// @todo IPv6 multicast support not implemented
|
||||
|
||||
class UdpFactory : public ProtocolFactory
|
||||
{
|
||||
@@ -51,7 +50,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map< udp::Endpoint, shared_ptr<MulticastUdpFace> > MulticastFaceMap;
|
||||
typedef std::map<udp::Endpoint, shared_ptr<MulticastUdpFace>> MulticastFaceMap;
|
||||
|
||||
explicit
|
||||
UdpFactory(const std::string& defaultPort = "6363");
|
||||
@@ -143,13 +142,13 @@ public:
|
||||
const std::string& multicastPort,
|
||||
const std::string& networkInterfaceName = "");
|
||||
|
||||
// from Factory
|
||||
// from ProtocolFactory
|
||||
virtual void
|
||||
createFace(const FaceUri& uri,
|
||||
const FaceCreatedCallback& onCreated,
|
||||
const FaceConnectFailedCallback& onConnectFailed);
|
||||
|
||||
virtual std::list<shared_ptr<const Channel> >
|
||||
virtual std::list<shared_ptr<const Channel>>
|
||||
getChannels() const;
|
||||
|
||||
/**
|
||||
@@ -159,7 +158,6 @@ public:
|
||||
getMulticastFaces() const;
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
|
||||
void
|
||||
prohibitEndpoint(const udp::Endpoint& endpoint);
|
||||
|
||||
@@ -183,7 +181,6 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
shared_ptr<UdpChannel>
|
||||
findChannel(const udp::Endpoint& localEndpoint);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Look up multicast UdpFace using specified local endpoint
|
||||
*
|
||||
@@ -196,7 +193,7 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
findMulticastFace(const udp::Endpoint& localEndpoint);
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
typedef std::map< udp::Endpoint, shared_ptr<UdpChannel> > ChannelMap;
|
||||
typedef std::map<udp::Endpoint, shared_ptr<UdpChannel>> ChannelMap;
|
||||
|
||||
ChannelMap m_channels;
|
||||
MulticastFaceMap m_multicastFaces;
|
||||
@@ -205,14 +202,12 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
std::set<udp::Endpoint> m_prohibitedEndpoints;
|
||||
};
|
||||
|
||||
|
||||
inline const UdpFactory::MulticastFaceMap&
|
||||
UdpFactory::getMulticastFaces() const
|
||||
{
|
||||
return m_multicastFaces;
|
||||
}
|
||||
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_UDP_FACTORY_HPP
|
||||
@@ -1,11 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014 Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -20,9 +21,10 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
*/
|
||||
|
||||
#include "unix-stream-channel.hpp"
|
||||
#include "unix-stream-face.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
@@ -32,26 +34,24 @@ namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("UnixStreamChannel");
|
||||
|
||||
using namespace boost::asio::local;
|
||||
|
||||
UnixStreamChannel::UnixStreamChannel(const unix_stream::Endpoint& endpoint)
|
||||
: m_endpoint(endpoint)
|
||||
, m_isListening(false)
|
||||
, m_acceptor(getGlobalIoService())
|
||||
, m_socket(getGlobalIoService())
|
||||
{
|
||||
setUri(FaceUri(endpoint));
|
||||
setUri(FaceUri(m_endpoint));
|
||||
}
|
||||
|
||||
UnixStreamChannel::~UnixStreamChannel()
|
||||
{
|
||||
if (m_isListening)
|
||||
{
|
||||
// use the non-throwing variants during destruction
|
||||
// and ignore any errors
|
||||
boost::system::error_code error;
|
||||
m_acceptor->close(error);
|
||||
NFD_LOG_TRACE("[" << m_endpoint << "] Removing socket file");
|
||||
boost::filesystem::remove(m_endpoint.path(), error);
|
||||
}
|
||||
if (isListening()) {
|
||||
// use the non-throwing variants during destruction
|
||||
// and ignore any errors
|
||||
boost::system::error_code error;
|
||||
m_acceptor.close(error);
|
||||
NFD_LOG_DEBUG("[" << m_endpoint << "] Removing socket file");
|
||||
boost::filesystem::remove(m_endpoint.path(), error);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -59,7 +59,7 @@ UnixStreamChannel::listen(const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onAcceptFailed,
|
||||
int backlog/* = acceptor::max_connections*/)
|
||||
{
|
||||
if (m_isListening) {
|
||||
if (isListening()) {
|
||||
NFD_LOG_WARN("[" << m_endpoint << "] Already listening");
|
||||
return;
|
||||
}
|
||||
@@ -69,81 +69,74 @@ UnixStreamChannel::listen(const FaceCreatedCallback& onFaceCreated,
|
||||
fs::path socketPath(m_endpoint.path());
|
||||
fs::file_type type = fs::symlink_status(socketPath).type();
|
||||
|
||||
if (type == fs::socket_file)
|
||||
{
|
||||
boost::system::error_code error;
|
||||
stream_protocol::socket socket(getGlobalIoService());
|
||||
socket.connect(m_endpoint, error);
|
||||
NFD_LOG_TRACE("[" << m_endpoint << "] connect() on existing socket file returned: "
|
||||
+ error.message());
|
||||
if (!error)
|
||||
{
|
||||
// someone answered, leave the socket alone
|
||||
throw Error("Socket file at " + m_endpoint.path()
|
||||
+ " belongs to another NFD process");
|
||||
}
|
||||
else if (error == boost::system::errc::connection_refused ||
|
||||
error == boost::system::errc::timed_out)
|
||||
{
|
||||
// no one is listening on the remote side,
|
||||
// we can safely remove the socket file
|
||||
NFD_LOG_INFO("[" << m_endpoint << "] Removing stale socket file");
|
||||
fs::remove(socketPath);
|
||||
}
|
||||
if (type == fs::socket_file) {
|
||||
boost::system::error_code error;
|
||||
boost::asio::local::stream_protocol::socket socket(getGlobalIoService());
|
||||
socket.connect(m_endpoint, error);
|
||||
NFD_LOG_TRACE("[" << m_endpoint << "] connect() on existing socket file returned: "
|
||||
+ error.message());
|
||||
if (!error) {
|
||||
// someone answered, leave the socket alone
|
||||
throw Error("Socket file at " + m_endpoint.path()
|
||||
+ " belongs to another NFD process");
|
||||
}
|
||||
else if (type != fs::file_not_found)
|
||||
{
|
||||
throw Error(m_endpoint.path() + " already exists and is not a socket file");
|
||||
else if (error == boost::asio::error::connection_refused ||
|
||||
error == boost::asio::error::timed_out) {
|
||||
// no one is listening on the remote side,
|
||||
// we can safely remove the stale socket
|
||||
NFD_LOG_DEBUG("[" << m_endpoint << "] Removing stale socket file");
|
||||
fs::remove(socketPath);
|
||||
}
|
||||
}
|
||||
else if (type != fs::file_not_found) {
|
||||
throw Error(m_endpoint.path() + " already exists and is not a socket file");
|
||||
}
|
||||
|
||||
m_acceptor = make_shared<stream_protocol::acceptor>(ref(getGlobalIoService()));
|
||||
m_acceptor->open();
|
||||
m_acceptor->bind(m_endpoint);
|
||||
m_acceptor->listen(backlog);
|
||||
m_isListening = true;
|
||||
m_acceptor.open();
|
||||
m_acceptor.bind(m_endpoint);
|
||||
m_acceptor.listen(backlog);
|
||||
|
||||
if (::chmod(m_endpoint.path().c_str(), 0666) < 0)
|
||||
{
|
||||
throw Error("Failed to chmod() socket file at " + m_endpoint.path());
|
||||
}
|
||||
if (::chmod(m_endpoint.path().c_str(), 0666) < 0) {
|
||||
throw Error("chmod(" + m_endpoint.path() + ") failed: " + std::strerror(errno));
|
||||
}
|
||||
|
||||
shared_ptr<stream_protocol::socket> clientSocket =
|
||||
make_shared<stream_protocol::socket>(ref(getGlobalIoService()));
|
||||
|
||||
m_acceptor->async_accept(*clientSocket,
|
||||
bind(&UnixStreamChannel::handleSuccessfulAccept, this,
|
||||
boost::asio::placeholders::error, clientSocket,
|
||||
onFaceCreated, onAcceptFailed));
|
||||
// start accepting connections
|
||||
accept(onFaceCreated, onAcceptFailed);
|
||||
}
|
||||
|
||||
void
|
||||
UnixStreamChannel::handleSuccessfulAccept(const boost::system::error_code& error,
|
||||
const shared_ptr<stream_protocol::socket>& socket,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onAcceptFailed)
|
||||
UnixStreamChannel::accept(const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onAcceptFailed)
|
||||
{
|
||||
m_acceptor.async_accept(m_socket, bind(&UnixStreamChannel::handleAccept, this,
|
||||
boost::asio::placeholders::error,
|
||||
onFaceCreated, onAcceptFailed));
|
||||
}
|
||||
|
||||
void
|
||||
UnixStreamChannel::handleAccept(const boost::system::error_code& error,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onAcceptFailed)
|
||||
{
|
||||
if (error) {
|
||||
if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
|
||||
if (error == boost::asio::error::operation_aborted) // when the socket is closed by someone
|
||||
return;
|
||||
|
||||
NFD_LOG_DEBUG("[" << m_endpoint << "] Connection failed: " << error.message());
|
||||
onAcceptFailed("Connection failed: " + error.message());
|
||||
NFD_LOG_DEBUG("[" << m_endpoint << "] Accept failed: " << error.message());
|
||||
if (onAcceptFailed)
|
||||
onAcceptFailed(error.message());
|
||||
return;
|
||||
}
|
||||
|
||||
NFD_LOG_DEBUG("[" << m_endpoint << "] << Incoming connection");
|
||||
NFD_LOG_DEBUG("[" << m_endpoint << "] Incoming connection");
|
||||
|
||||
shared_ptr<stream_protocol::socket> clientSocket =
|
||||
make_shared<stream_protocol::socket>(ref(getGlobalIoService()));
|
||||
auto remoteUri = FaceUri::fromFd(m_socket.native_handle());
|
||||
auto localUri = FaceUri(m_socket.local_endpoint());
|
||||
auto face = make_shared<UnixStreamFace>(remoteUri, localUri, std::move(m_socket));
|
||||
onFaceCreated(face);
|
||||
|
||||
// prepare accepting the next connection
|
||||
m_acceptor->async_accept(*clientSocket,
|
||||
bind(&UnixStreamChannel::handleSuccessfulAccept, this,
|
||||
boost::asio::placeholders::error, clientSocket,
|
||||
onFaceCreated, onAcceptFailed));
|
||||
|
||||
shared_ptr<UnixStreamFace> face = make_shared<UnixStreamFace>(socket);
|
||||
onFaceCreated(face);
|
||||
accept(onFaceCreated, onAcceptFailed);
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
@@ -26,7 +26,6 @@
|
||||
#define NFD_DAEMON_FACE_UNIX_STREAM_CHANNEL_HPP
|
||||
|
||||
#include "channel.hpp"
|
||||
#include "unix-stream-face.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
@@ -60,8 +59,7 @@ public:
|
||||
explicit
|
||||
UnixStreamChannel(const unix_stream::Endpoint& endpoint);
|
||||
|
||||
virtual
|
||||
~UnixStreamChannel();
|
||||
~UnixStreamChannel() DECL_OVERRIDE;
|
||||
|
||||
/**
|
||||
* \brief Enable listening on the local endpoint, accept connections,
|
||||
@@ -77,19 +75,31 @@ public:
|
||||
const ConnectFailedCallback& onAcceptFailed,
|
||||
int backlog = boost::asio::local::stream_protocol::acceptor::max_connections);
|
||||
|
||||
bool
|
||||
isListening() const;
|
||||
|
||||
private:
|
||||
void
|
||||
handleSuccessfulAccept(const boost::system::error_code& error,
|
||||
const shared_ptr<boost::asio::local::stream_protocol::socket>& socket,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onConnectFailed);
|
||||
accept(const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onAcceptFailed);
|
||||
|
||||
void
|
||||
handleAccept(const boost::system::error_code& error,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const ConnectFailedCallback& onAcceptFailed);
|
||||
|
||||
private:
|
||||
unix_stream::Endpoint m_endpoint;
|
||||
shared_ptr<boost::asio::local::stream_protocol::acceptor> m_acceptor;
|
||||
bool m_isListening;
|
||||
boost::asio::local::stream_protocol::acceptor m_acceptor;
|
||||
boost::asio::local::stream_protocol::socket m_socket;
|
||||
};
|
||||
|
||||
inline bool
|
||||
UnixStreamChannel::isListening() const
|
||||
{
|
||||
return m_acceptor.is_open();
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_UNIX_STREAM_CHANNEL_HPP
|
||||
@@ -33,14 +33,14 @@ NFD_LOG_INCLASS_2TEMPLATE_SPECIALIZATION_DEFINE(StreamFace,
|
||||
UnixStreamFace::protocol, LocalFace,
|
||||
"UnixStreamFace");
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_same<UnixStreamFace::protocol::socket::native_handle_type,
|
||||
int>::value));
|
||||
|
||||
UnixStreamFace::UnixStreamFace(const shared_ptr<UnixStreamFace::protocol::socket>& socket)
|
||||
: StreamFace<protocol, LocalFace>(FaceUri::fromFd(socket->native_handle()),
|
||||
FaceUri(socket->local_endpoint()),
|
||||
socket, true)
|
||||
UnixStreamFace::UnixStreamFace(const FaceUri& remoteUri, const FaceUri& localUri,
|
||||
protocol::socket socket)
|
||||
: StreamFace<protocol, LocalFace>(remoteUri, localUri, std::move(socket), true)
|
||||
{
|
||||
static_assert(
|
||||
std::is_same<std::remove_cv<protocol::socket::native_handle_type>::type, int>::value,
|
||||
"The native handle type for UnixStreamFace sockets must be 'int'"
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
@@ -40,8 +40,8 @@ namespace nfd {
|
||||
class UnixStreamFace : public StreamFace<boost::asio::local::stream_protocol, LocalFace>
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
UnixStreamFace(const shared_ptr<protocol::socket>& socket);
|
||||
UnixStreamFace(const FaceUri& remoteUri, const FaceUri& localUri,
|
||||
protocol::socket socket);
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
*/
|
||||
|
||||
#include "websocket-channel.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
#include "core/scheduler.hpp"
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
|
||||
@@ -31,13 +33,13 @@ namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("WebSocketChannel");
|
||||
|
||||
using namespace boost::asio;
|
||||
|
||||
WebSocketChannel::WebSocketChannel(const websocket::Endpoint& localEndpoint)
|
||||
: m_localEndpoint(localEndpoint)
|
||||
, m_isListening(false)
|
||||
, m_pingInterval(10000)
|
||||
{
|
||||
setUri(FaceUri(m_localEndpoint, "ws"));
|
||||
|
||||
// Setup WebSocket server
|
||||
m_server.clear_access_channels(websocketpp::log::alevel::all);
|
||||
m_server.clear_error_channels(websocketpp::log::alevel::all);
|
||||
@@ -46,19 +48,19 @@ WebSocketChannel::WebSocketChannel(const websocket::Endpoint& localEndpoint)
|
||||
m_server.set_open_handler(bind(&WebSocketChannel::handleOpen, this, _1));
|
||||
m_server.set_close_handler(bind(&WebSocketChannel::handleClose, this, _1));
|
||||
m_server.init_asio(&getGlobalIoService());
|
||||
|
||||
// Detect disconnections using ping-pong messages
|
||||
m_server.set_pong_handler(bind(&WebSocketChannel::handlePong, this, _1, _2));
|
||||
m_server.set_pong_timeout_handler(bind(&WebSocketChannel::handlePongTimeout, this, _1, _2));
|
||||
|
||||
// Always set SO_REUSEADDR flag
|
||||
m_server.set_reuse_addr(true);
|
||||
|
||||
// Detect disconnection using PONG message
|
||||
m_server.set_pong_handler(bind(&WebSocketChannel::handlePong, this, _1, _2));
|
||||
m_server.set_pong_timeout_handler(bind(&WebSocketChannel::handlePongTimeout,
|
||||
this, _1, _2));
|
||||
|
||||
this->setUri(FaceUri(localEndpoint, "ws"));
|
||||
}
|
||||
|
||||
WebSocketChannel::~WebSocketChannel()
|
||||
void
|
||||
WebSocketChannel::setPingInterval(time::milliseconds interval)
|
||||
{
|
||||
m_pingInterval = interval;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -70,120 +72,109 @@ WebSocketChannel::setPongTimeout(time::milliseconds timeout)
|
||||
void
|
||||
WebSocketChannel::handlePongTimeout(websocketpp::connection_hdl hdl, std::string msg)
|
||||
{
|
||||
ChannelFaceMap::iterator it = m_channelFaces.find(hdl);
|
||||
if (it != m_channelFaces.end())
|
||||
{
|
||||
it->second->close();
|
||||
NFD_LOG_DEBUG("handlePongTimeout: remove " << it->second->getRemoteUri());
|
||||
m_channelFaces.erase(it);
|
||||
}
|
||||
auto it = m_channelFaces.find(hdl);
|
||||
if (it != m_channelFaces.end()) {
|
||||
NFD_LOG_TRACE(__func__ << ": " << it->second->getRemoteUri());
|
||||
it->second->close();
|
||||
m_channelFaces.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannel::handlePong(websocketpp::connection_hdl hdl, std::string msg)
|
||||
{
|
||||
ChannelFaceMap::iterator it = m_channelFaces.find(hdl);
|
||||
if (it != m_channelFaces.end())
|
||||
{
|
||||
NFD_LOG_TRACE("handlePong: from " << it->second->getRemoteUri());
|
||||
}
|
||||
auto it = m_channelFaces.find(hdl);
|
||||
if (it != m_channelFaces.end()) {
|
||||
NFD_LOG_TRACE("Pong from " << it->second->getRemoteUri());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannel::handleMessage(websocketpp::connection_hdl hdl,
|
||||
websocket::Server::message_ptr msg)
|
||||
{
|
||||
ChannelFaceMap::iterator it = m_channelFaces.find(hdl);
|
||||
if (it != m_channelFaces.end())
|
||||
{
|
||||
it->second->handleReceive(msg->get_payload());
|
||||
}
|
||||
auto it = m_channelFaces.find(hdl);
|
||||
if (it != m_channelFaces.end()) {
|
||||
it->second->handleReceive(msg->get_payload());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannel::handleOpen(websocketpp::connection_hdl hdl)
|
||||
{
|
||||
std::string remote;
|
||||
try
|
||||
{
|
||||
remote = "wsclient://" + m_server.get_con_from_hdl(hdl)->get_remote_endpoint();
|
||||
}
|
||||
catch (websocketpp::lib::error_code&)
|
||||
{
|
||||
NFD_LOG_DEBUG("handleOpen: cannot get remote uri");
|
||||
websocketpp::lib::error_code ecode;
|
||||
m_server.close(hdl, websocketpp::close::status::normal, "closed by channel", ecode);
|
||||
}
|
||||
shared_ptr<WebSocketFace> face = ndn::make_shared<WebSocketFace>(FaceUri(remote), this->getUri(),
|
||||
hdl, ref(m_server));
|
||||
m_onFaceCreatedCallback(face);
|
||||
m_channelFaces[hdl] = face;
|
||||
|
||||
// Schedule PING message
|
||||
scheduler::EventId pingEvent = scheduler::schedule(m_pingInterval,
|
||||
bind(&WebSocketChannel::sendPing, this, hdl));
|
||||
face->setPingEventId(pingEvent);
|
||||
try {
|
||||
std::string remote = "wsclient://" + m_server.get_con_from_hdl(hdl)->get_remote_endpoint();
|
||||
auto face = make_shared<WebSocketFace>(FaceUri(remote), this->getUri(),
|
||||
hdl, ref(m_server));
|
||||
m_onFaceCreatedCallback(face);
|
||||
m_channelFaces[hdl] = face;
|
||||
// Schedule ping message
|
||||
scheduler::EventId pingEvent = scheduler::schedule(m_pingInterval,
|
||||
bind(&WebSocketChannel::sendPing,
|
||||
this, hdl));
|
||||
face->setPingEventId(pingEvent);
|
||||
}
|
||||
catch (const FaceUri::Error& e) {
|
||||
NFD_LOG_WARN(e.what());
|
||||
websocketpp::lib::error_code ec;
|
||||
m_server.close(hdl, websocketpp::close::status::normal, "closed by channel", ec);
|
||||
// ignore error on close
|
||||
}
|
||||
catch (const websocketpp::exception& e) {
|
||||
NFD_LOG_WARN("Cannot get remote connection: " << e.what());
|
||||
websocketpp::lib::error_code ec;
|
||||
m_server.close(hdl, websocketpp::close::status::normal, "closed by channel", ec);
|
||||
// ignore error on close
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannel::sendPing(websocketpp::connection_hdl hdl)
|
||||
{
|
||||
ChannelFaceMap::iterator it = m_channelFaces.find(hdl);
|
||||
if (it != m_channelFaces.end())
|
||||
{
|
||||
try
|
||||
{
|
||||
m_server.ping(hdl, "NFD-WebSocket");
|
||||
}
|
||||
catch (websocketpp::lib::error_code&)
|
||||
{
|
||||
it->second->close();
|
||||
NFD_LOG_DEBUG("sendPing: failed to ping " << it->second->getRemoteUri());
|
||||
m_channelFaces.erase(it);
|
||||
}
|
||||
auto it = m_channelFaces.find(hdl);
|
||||
if (it != m_channelFaces.end()) {
|
||||
NFD_LOG_TRACE("Sending ping to " << it->second->getRemoteUri());
|
||||
|
||||
NFD_LOG_TRACE("sendPing: to " << it->second->getRemoteUri());
|
||||
websocketpp::lib::error_code ec;
|
||||
m_server.ping(hdl, "NFD-WebSocket", ec);
|
||||
if (ec)
|
||||
{
|
||||
NFD_LOG_WARN("Failed to ping " << it->second->getRemoteUri() << ": " << ec.message());
|
||||
it->second->close();
|
||||
m_channelFaces.erase(it);
|
||||
return;
|
||||
}
|
||||
|
||||
// Schedule next PING message
|
||||
scheduler::EventId pingEvent = scheduler::schedule(m_pingInterval,
|
||||
bind(&WebSocketChannel::sendPing, this, hdl));
|
||||
it->second->setPingEventId(pingEvent);
|
||||
}
|
||||
// Schedule next ping message
|
||||
scheduler::EventId pingEvent = scheduler::schedule(m_pingInterval,
|
||||
bind(&WebSocketChannel::sendPing,
|
||||
this, hdl));
|
||||
it->second->setPingEventId(pingEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannel::handleClose(websocketpp::connection_hdl hdl)
|
||||
{
|
||||
ChannelFaceMap::iterator it = m_channelFaces.find(hdl);
|
||||
if (it != m_channelFaces.end())
|
||||
{
|
||||
it->second->close();
|
||||
NFD_LOG_DEBUG("handleClose: remove " << it->second->getRemoteUri());
|
||||
m_channelFaces.erase(it);
|
||||
}
|
||||
auto it = m_channelFaces.find(hdl);
|
||||
if (it != m_channelFaces.end()) {
|
||||
NFD_LOG_TRACE(__func__ << ": " << it->second->getRemoteUri());
|
||||
it->second->close();
|
||||
m_channelFaces.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WebSocketChannel::listen(const FaceCreatedCallback& onFaceCreated)
|
||||
{
|
||||
if (m_isListening)
|
||||
{
|
||||
throw Error("Listen already called on this channel");
|
||||
}
|
||||
if (isListening()) {
|
||||
NFD_LOG_WARN("[" << m_localEndpoint << "] Already listening");
|
||||
return;
|
||||
}
|
||||
m_isListening = true;
|
||||
|
||||
m_onFaceCreatedCallback = onFaceCreated;
|
||||
|
||||
try
|
||||
{
|
||||
m_server.listen(m_localEndpoint);
|
||||
}
|
||||
catch (websocketpp::lib::error_code ec)
|
||||
{
|
||||
throw Error("Failed to listen on local endpoint");
|
||||
}
|
||||
|
||||
m_server.listen(m_localEndpoint);
|
||||
m_server.start_accept();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,33 +27,16 @@
|
||||
#define NFD_DAEMON_FACE_WEBSOCKET_CHANNEL_HPP
|
||||
|
||||
#include "channel.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
#include "core/scheduler.hpp"
|
||||
#include "websocket-face.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
/**
|
||||
* \brief Class implementing WebSocket-based channel to create faces
|
||||
*
|
||||
*
|
||||
*/
|
||||
class WebSocketChannel : public Channel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Exception of WebSocketChannel
|
||||
*/
|
||||
class Error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
Error(const std::string& what)
|
||||
: runtime_error(what)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Create WebSocket channel for the local endpoint
|
||||
*
|
||||
@@ -66,9 +49,6 @@ public:
|
||||
explicit
|
||||
WebSocketChannel(const websocket::Endpoint& localEndpoint);
|
||||
|
||||
virtual
|
||||
~WebSocketChannel();
|
||||
|
||||
/**
|
||||
* \brief Enable listening on the local endpoint, accept connections,
|
||||
* and create faces when remote host makes a connection
|
||||
@@ -88,11 +68,9 @@ public:
|
||||
bool
|
||||
isListening() const;
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
void
|
||||
setPingInterval(time::milliseconds interval)
|
||||
{
|
||||
m_pingInterval = interval;
|
||||
}
|
||||
setPingInterval(time::milliseconds interval);
|
||||
|
||||
void
|
||||
setPongTimeout(time::milliseconds timeout);
|
||||
@@ -118,20 +96,16 @@ private:
|
||||
|
||||
private:
|
||||
websocket::Endpoint m_localEndpoint;
|
||||
|
||||
websocket::Server m_server;
|
||||
|
||||
std::map<websocketpp::connection_hdl, shared_ptr<WebSocketFace>,
|
||||
std::owner_less<websocketpp::connection_hdl>> m_channelFaces;
|
||||
|
||||
/**
|
||||
* Callbacks for face creation.
|
||||
* New communications are detected using async_receive_from.
|
||||
* Its handler has a fixed signature. No space for the face callback
|
||||
* Callback for face creation
|
||||
*/
|
||||
FaceCreatedCallback m_onFaceCreatedCallback;
|
||||
|
||||
typedef std::map< websocketpp::connection_hdl, shared_ptr<WebSocketFace>,
|
||||
std::owner_less<websocketpp::connection_hdl> > ChannelFaceMap;
|
||||
ChannelFaceMap m_channelFaces;
|
||||
|
||||
/**
|
||||
* \brief If true, it means the function listen has already been called
|
||||
*/
|
||||
|
||||
@@ -37,6 +37,7 @@ WebSocketFace::WebSocketFace(const FaceUri& remoteUri, const FaceUri& localUri,
|
||||
, m_server(server)
|
||||
, m_closed(false)
|
||||
{
|
||||
NFD_LOG_FACE_INFO("Creating face");
|
||||
this->setOnDemand(true);
|
||||
}
|
||||
|
||||
@@ -46,18 +47,18 @@ WebSocketFace::sendInterest(const Interest& interest)
|
||||
if (m_closed)
|
||||
return;
|
||||
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
this->emitSignal(onSendInterest, interest);
|
||||
|
||||
const Block& payload = interest.wireEncode();
|
||||
this->getMutableCounters().getNOutBytes() += payload.size();
|
||||
|
||||
try {
|
||||
m_server.send(m_handle, payload.wire(), payload.size(),
|
||||
websocketpp::frame::opcode::binary);
|
||||
}
|
||||
catch (const websocketpp::lib::error_code& e) {
|
||||
NFD_LOG_WARN("Failed to send Interest: " << e << " (" << e.message() << ")");
|
||||
}
|
||||
websocketpp::lib::error_code ec;
|
||||
m_server.send(m_handle, payload.wire(), payload.size(),
|
||||
websocketpp::frame::opcode::binary, ec);
|
||||
if (ec)
|
||||
NFD_LOG_FACE_WARN("Failed to send Interest: " << ec.message());
|
||||
}
|
||||
|
||||
void
|
||||
@@ -66,32 +67,34 @@ WebSocketFace::sendData(const Data& data)
|
||||
if (m_closed)
|
||||
return;
|
||||
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
this->emitSignal(onSendData, data);
|
||||
|
||||
const Block& payload = data.wireEncode();
|
||||
this->getMutableCounters().getNOutBytes() += payload.size();
|
||||
|
||||
try {
|
||||
m_server.send(m_handle, payload.wire(), payload.size(),
|
||||
websocketpp::frame::opcode::binary);
|
||||
}
|
||||
catch (const websocketpp::lib::error_code& e) {
|
||||
NFD_LOG_WARN("Failed to send Data: " << e << " (" << e.message() << ")");
|
||||
}
|
||||
websocketpp::lib::error_code ec;
|
||||
m_server.send(m_handle, payload.wire(), payload.size(),
|
||||
websocketpp::frame::opcode::binary, ec);
|
||||
if (ec)
|
||||
NFD_LOG_FACE_WARN("Failed to send Data: " << ec.message());
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketFace::close()
|
||||
{
|
||||
if (m_closed == false)
|
||||
{
|
||||
m_closed = true;
|
||||
scheduler::cancel(m_pingEventId);
|
||||
websocketpp::lib::error_code ecode;
|
||||
m_server.close(m_handle, websocketpp::close::status::normal, "closed by nfd", ecode);
|
||||
if (m_closed)
|
||||
return;
|
||||
|
||||
fail("Face closed");
|
||||
}
|
||||
NFD_LOG_FACE_INFO("Closing face");
|
||||
|
||||
m_closed = true;
|
||||
scheduler::cancel(m_pingEventId);
|
||||
websocketpp::lib::error_code ec;
|
||||
m_server.close(m_handle, websocketpp::close::status::normal, "closed by nfd", ec);
|
||||
// ignore error on close
|
||||
fail("Face closed");
|
||||
}
|
||||
|
||||
void
|
||||
@@ -100,30 +103,27 @@ WebSocketFace::handleReceive(const std::string& msg)
|
||||
// Copy message into Face internal buffer
|
||||
if (msg.size() > ndn::MAX_NDN_PACKET_SIZE)
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << this->getId()
|
||||
<< "] Received WebSocket message is too big (" << msg.size() << " bytes)");
|
||||
NFD_LOG_FACE_WARN("Received WebSocket message is too big (" << msg.size() << " bytes)");
|
||||
return;
|
||||
}
|
||||
|
||||
NFD_LOG_TRACE("[id:" << this->getId()
|
||||
<< "] Received: " << msg.size() << " bytes");
|
||||
NFD_LOG_FACE_TRACE("Received: " << msg.size() << " bytes");
|
||||
this->getMutableCounters().getNInBytes() += msg.size();
|
||||
|
||||
// Try to parse message data
|
||||
bool isOk = false;
|
||||
Block element;
|
||||
bool isOk = Block::fromBuffer(reinterpret_cast<const uint8_t*>(msg.c_str()),
|
||||
msg.size(), element);
|
||||
std::tie(isOk, element) = Block::fromBuffer(reinterpret_cast<const uint8_t*>(msg.c_str()),
|
||||
msg.size());
|
||||
if (!isOk)
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << this->getId()
|
||||
<< "] Received block is invalid or too large to process");
|
||||
NFD_LOG_FACE_WARN("Received block is invalid or too large to process");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->decodeAndDispatchInput(element))
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << this->getId()
|
||||
<< "] Received unrecognized TLV block of type " << element.type());
|
||||
NFD_LOG_FACE_WARN("Received unrecognized TLV block of type " << element.type());
|
||||
// ignore unknown packet and proceed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#define NFD_DAEMON_FACE_WEBSOCKET_FACE_HPP
|
||||
|
||||
#include "face.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include "core/scheduler.hpp"
|
||||
|
||||
#ifndef HAVE_WEBSOCKET
|
||||
|
||||
@@ -29,8 +29,6 @@ namespace nfd {
|
||||
|
||||
using namespace boost::asio;
|
||||
|
||||
NFD_LOG_INIT("WebSocketFactory");
|
||||
|
||||
WebSocketFactory::WebSocketFactory(const std::string& defaultPort)
|
||||
: m_defaultPort(defaultPort)
|
||||
{
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "protocol-factory.hpp"
|
||||
#include "websocket-channel.hpp"
|
||||
|
||||
|
||||
namespace nfd {
|
||||
|
||||
class WebSocketFactory : public ProtocolFactory
|
||||
@@ -63,8 +62,7 @@ public:
|
||||
* \returns always a valid pointer to a WebSocketChannel object, an exception
|
||||
* is thrown if it cannot be created.
|
||||
*
|
||||
* \throws WebSocketFactory::Error, TcpResolver::Error
|
||||
*
|
||||
* \throws WebSocketFactory::Error
|
||||
*/
|
||||
shared_ptr<WebSocketChannel>
|
||||
createChannel(const websocket::Endpoint& localEndpoint);
|
||||
@@ -80,7 +78,7 @@ public:
|
||||
shared_ptr<WebSocketChannel>
|
||||
createChannel(const std::string& localIp, const std::string& port);
|
||||
|
||||
// from Factory
|
||||
// from ProtocolFactory
|
||||
virtual void
|
||||
createFace(const FaceUri& uri,
|
||||
const FaceCreatedCallback& onCreated,
|
||||
@@ -90,7 +88,6 @@ public:
|
||||
getChannels() const;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* \brief Look up WebSocketChannel using specified local endpoint
|
||||
*
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace fw {
|
||||
NFD_LOG_INIT("AccessStrategy");
|
||||
|
||||
const Name AccessStrategy::STRATEGY_NAME("ndn:/localhost/nfd/strategy/access/%FD%01");
|
||||
NFD_REGISTER_STRATEGY(AccessStrategy);
|
||||
|
||||
AccessStrategy::AccessStrategy(Forwarder& forwarder, const Name& name)
|
||||
: Strategy(forwarder, name)
|
||||
@@ -50,16 +51,15 @@ AccessStrategy::afterReceiveInterest(const Face& inFace,
|
||||
shared_ptr<fib::Entry> fibEntry,
|
||||
shared_ptr<pit::Entry> pitEntry)
|
||||
{
|
||||
RetransmissionSuppression::Result suppressResult =
|
||||
m_retransmissionSuppression.decide(inFace, interest, *pitEntry);
|
||||
RetxSuppression::Result suppressResult = m_retxSuppression.decide(inFace, interest, *pitEntry);
|
||||
switch (suppressResult) {
|
||||
case RetransmissionSuppression::NEW:
|
||||
case RetxSuppression::NEW:
|
||||
this->afterReceiveNewInterest(inFace, interest, fibEntry, pitEntry);
|
||||
break;
|
||||
case RetransmissionSuppression::FORWARD:
|
||||
case RetxSuppression::FORWARD:
|
||||
this->afterReceiveRetxInterest(inFace, interest, fibEntry, pitEntry);
|
||||
break;
|
||||
case RetransmissionSuppression::SUPPRESS:
|
||||
case RetxSuppression::SUPPRESS:
|
||||
NFD_LOG_DEBUG(interest << " interestFrom " << inFace.getId() << " retx-suppress");
|
||||
break;
|
||||
default:
|
||||
@@ -264,6 +264,9 @@ AccessStrategy::addPrefixMeasurements(const Data& data)
|
||||
BOOST_ASSERT(me != nullptr);
|
||||
}
|
||||
|
||||
static const time::nanoseconds ME_LIFETIME = time::seconds(8);
|
||||
this->getMeasurements().extendLifetime(*me, ME_LIFETIME);
|
||||
|
||||
return me->getOrCreateStrategyInfo<MtInfo>();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "strategy.hpp"
|
||||
#include "rtt-estimator.hpp"
|
||||
#include "retransmission-suppression.hpp"
|
||||
#include "retx-suppression-fixed.hpp"
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -167,7 +167,7 @@ public:
|
||||
|
||||
private:
|
||||
FaceInfoTable m_fit;
|
||||
RetransmissionSuppression m_retransmissionSuppression;
|
||||
RetxSuppressionFixed m_retxSuppression;
|
||||
signal::ScopedConnection m_removeFaceInfoConn;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014 Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
#ifndef NFD_DAEMON_FW_AVAILABLE_STRATEGIES_HPP
|
||||
#define NFD_DAEMON_FW_AVAILABLE_STRATEGIES_HPP
|
||||
|
||||
#include "strategy.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
shared_ptr<Strategy>
|
||||
makeDefaultStrategy(Forwarder& forwarder);
|
||||
|
||||
void
|
||||
installStrategies(Forwarder& forwarder);
|
||||
|
||||
} // namespace fw
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FW_AVAILABLE_STRATEGIES_HPP
|
||||
@@ -1,12 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -29,6 +29,7 @@ namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
const Name BestRouteStrategy::STRATEGY_NAME("ndn:/localhost/nfd/strategy/best-route/%FD%01");
|
||||
NFD_REGISTER_STRATEGY(BestRouteStrategy);
|
||||
|
||||
BestRouteStrategy::BestRouteStrategy(Forwarder& forwarder, const Name& name)
|
||||
: Strategy(forwarder, name)
|
||||
|
||||
@@ -31,7 +31,8 @@ namespace fw {
|
||||
|
||||
NFD_LOG_INIT("BestRouteStrategy2");
|
||||
|
||||
const Name BestRouteStrategy2::STRATEGY_NAME("ndn:/localhost/nfd/strategy/best-route/%FD%02");
|
||||
const Name BestRouteStrategy2::STRATEGY_NAME("ndn:/localhost/nfd/strategy/best-route/%FD%03");
|
||||
NFD_REGISTER_STRATEGY(BestRouteStrategy2);
|
||||
|
||||
BestRouteStrategy2::BestRouteStrategy2(Forwarder& forwarder, const Name& name)
|
||||
: Strategy(forwarder, name)
|
||||
@@ -103,9 +104,9 @@ BestRouteStrategy2::afterReceiveInterest(const Face& inFace,
|
||||
const fib::NextHopList& nexthops = fibEntry->getNextHops();
|
||||
fib::NextHopList::const_iterator it = nexthops.end();
|
||||
|
||||
RetransmissionSuppression::Result suppression =
|
||||
m_retransmissionSuppression.decide(inFace, interest, *pitEntry);
|
||||
if (suppression == RetransmissionSuppression::NEW) {
|
||||
RetxSuppression::Result suppression =
|
||||
m_retxSuppression.decide(inFace, interest, *pitEntry);
|
||||
if (suppression == RetxSuppression::NEW) {
|
||||
// forward to nexthop with lowest cost except downstream
|
||||
it = std::find_if(nexthops.begin(), nexthops.end(),
|
||||
bind(&predicate_NextHop_eligible, pitEntry, _1, inFace.getId(),
|
||||
@@ -124,7 +125,7 @@ BestRouteStrategy2::afterReceiveInterest(const Face& inFace,
|
||||
return;
|
||||
}
|
||||
|
||||
if (suppression == RetransmissionSuppression::SUPPRESS) {
|
||||
if (suppression == RetxSuppression::SUPPRESS) {
|
||||
NFD_LOG_DEBUG(interest << " from=" << inFace.getId()
|
||||
<< " suppressed");
|
||||
return;
|
||||
|
||||
@@ -27,18 +27,18 @@
|
||||
#define NFD_DAEMON_FW_BEST_ROUTE_STRATEGY2_HPP
|
||||
|
||||
#include "strategy.hpp"
|
||||
#include "retransmission-suppression.hpp"
|
||||
#include "retx-suppression-exponential.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
/** \brief Best Route strategy version 2
|
||||
/** \brief Best Route strategy version 3
|
||||
*
|
||||
* This strategy forwards a new Interest to the lowest-cost nexthop (except downstream).
|
||||
* After that, it recognizes consumer retransmission:
|
||||
* if a similar Interest arrives from any downstream after MIN_RETRANSMISSION_INTERVAL,
|
||||
* the strategy forwards the Interest again to the lowest-cost nexthop (except downstream)
|
||||
* that is not previously used. If all nexthops have been used, the strategy starts over.
|
||||
* After that, if consumer retransmits the Interest (and is not suppressed according to
|
||||
* exponential backoff algorithm), the strategy forwards the Interest again to
|
||||
* the lowest-cost nexthop (except downstream) that is not previously used.
|
||||
* If all nexthops have been used, the strategy starts over.
|
||||
*/
|
||||
class BestRouteStrategy2 : public Strategy
|
||||
{
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
static const Name STRATEGY_NAME;
|
||||
|
||||
private:
|
||||
RetransmissionSuppression m_retransmissionSuppression;
|
||||
RetxSuppressionExponential m_retxSuppression;
|
||||
};
|
||||
|
||||
} // namespace fw
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -29,6 +29,7 @@ namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
const Name BroadcastStrategy::STRATEGY_NAME("ndn:/localhost/nfd/strategy/broadcast/%FD%01");
|
||||
NFD_REGISTER_STRATEGY(BroadcastStrategy);
|
||||
|
||||
BroadcastStrategy::BroadcastStrategy(Forwarder& forwarder, const Name& name)
|
||||
: Strategy(forwarder, name)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -33,6 +33,7 @@ NFD_LOG_INIT("ClientControlStrategy");
|
||||
|
||||
const Name
|
||||
ClientControlStrategy::STRATEGY_NAME("ndn:/localhost/nfd/strategy/client-control/%FD%01");
|
||||
NFD_REGISTER_STRATEGY(ClientControlStrategy);
|
||||
|
||||
ClientControlStrategy::ClientControlStrategy(Forwarder& forwarder, const Name& name)
|
||||
: BestRouteStrategy(forwarder, name)
|
||||
|
||||
+42
-22
@@ -1,12 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "forwarder.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include "core/random.hpp"
|
||||
#include "available-strategies.hpp"
|
||||
#include "strategy.hpp"
|
||||
#include <boost/random/uniform_int_distribution.hpp>
|
||||
|
||||
namespace nfd {
|
||||
@@ -91,23 +91,25 @@ Forwarder::onIncomingInterest(Face& inFace, const Interest& interest)
|
||||
const pit::InRecordCollection& inRecords = pitEntry->getInRecords();
|
||||
bool isPending = inRecords.begin() != inRecords.end();
|
||||
if (!isPending) {
|
||||
// CS lookup
|
||||
const Data* csMatch = m_cs.find(interest);
|
||||
if (csMatch != 0) {
|
||||
const_cast<Data*>(csMatch)->setIncomingFaceId(FACEID_CONTENT_STORE);
|
||||
// XXX should we lookup PIT for other Interests that also match csMatch?
|
||||
|
||||
// set PIT straggler timer
|
||||
this->setStragglerTimer(pitEntry, true, csMatch->getFreshnessPeriod());
|
||||
|
||||
// goto outgoing Data pipeline
|
||||
this->onOutgoingData(*csMatch, inFace);
|
||||
return;
|
||||
}
|
||||
m_cs.find(interest,
|
||||
bind(&Forwarder::onContentStoreHit, this, ref(inFace), pitEntry, _1, _2),
|
||||
bind(&Forwarder::onContentStoreMiss, this, ref(inFace), pitEntry, _1));
|
||||
}
|
||||
else {
|
||||
this->onContentStoreMiss(inFace, pitEntry, interest);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Forwarder::onContentStoreMiss(const Face& inFace,
|
||||
shared_ptr<pit::Entry> pitEntry,
|
||||
const Interest& interest)
|
||||
{
|
||||
NFD_LOG_DEBUG("onContentStoreMiss interest=" << interest.getName());
|
||||
|
||||
shared_ptr<Face> face = const_pointer_cast<Face>(inFace.shared_from_this());
|
||||
// insert InRecord
|
||||
pitEntry->insertOrUpdateInRecord(inFace.shared_from_this(), interest);
|
||||
pitEntry->insertOrUpdateInRecord(face, interest);
|
||||
|
||||
// set PIT unsatisfy timer
|
||||
this->setUnsatisfyTimer(pitEntry);
|
||||
@@ -120,6 +122,24 @@ Forwarder::onIncomingInterest(Face& inFace, const Interest& interest)
|
||||
cref(inFace), cref(interest), fibEntry, pitEntry));
|
||||
}
|
||||
|
||||
void
|
||||
Forwarder::onContentStoreHit(const Face& inFace,
|
||||
shared_ptr<pit::Entry> pitEntry,
|
||||
const Interest& interest,
|
||||
const Data& data)
|
||||
{
|
||||
NFD_LOG_DEBUG("onContentStoreMiss interest=" << interest.getName());
|
||||
|
||||
const_pointer_cast<Data>(data.shared_from_this())->setIncomingFaceId(FACEID_CONTENT_STORE);
|
||||
// XXX should we lookup PIT for other Interests that also match csMatch?
|
||||
|
||||
// set PIT straggler timer
|
||||
this->setStragglerTimer(pitEntry, true, data.getFreshnessPeriod());
|
||||
|
||||
// goto outgoing Data pipeline
|
||||
this->onOutgoingData(data, *const_pointer_cast<Face>(inFace.shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
Forwarder::onInterestLoop(Face& inFace, const Interest& interest,
|
||||
shared_ptr<pit::Entry> pitEntry)
|
||||
|
||||
@@ -110,6 +110,17 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE: // pipelines
|
||||
VIRTUAL_WITH_TESTS void
|
||||
onIncomingInterest(Face& inFace, const Interest& interest);
|
||||
|
||||
/** \brief Content Store miss pipeline
|
||||
*/
|
||||
void
|
||||
onContentStoreMiss(const Face& inFace, shared_ptr<pit::Entry> pitEntry, const Interest& interest);
|
||||
|
||||
/** \brief Content Store hit pipeline
|
||||
*/
|
||||
void
|
||||
onContentStoreHit(const Face& inFace, shared_ptr<pit::Entry> pitEntry,
|
||||
const Interest& interest, const Data& data);
|
||||
|
||||
/** \brief Interest loop pipeline
|
||||
*/
|
||||
VIRTUAL_WITH_TESTS void
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
const Name NccStrategy::STRATEGY_NAME("ndn:/localhost/nfd/strategy/ncc/%FD%01");
|
||||
NFD_REGISTER_STRATEGY(NccStrategy);
|
||||
|
||||
NccStrategy::NccStrategy(Forwarder& forwarder, const Name& name)
|
||||
: Strategy(forwarder, name)
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "retx-suppression-exponential.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
const RetxSuppressionExponential::Duration RetxSuppressionExponential::DEFAULT_INITIAL_INTERVAL =
|
||||
time::milliseconds(1);
|
||||
const float RetxSuppressionExponential::DEFAULT_MULTIPLIER = 2.0;
|
||||
const RetxSuppressionExponential::Duration RetxSuppressionExponential::DEFAULT_MAX_INTERVAL =
|
||||
time::milliseconds(250);
|
||||
|
||||
class RetxSuppressionExponential::PitInfo : public StrategyInfo
|
||||
{
|
||||
public:
|
||||
static constexpr int
|
||||
getTypeId()
|
||||
{
|
||||
return 1020;
|
||||
}
|
||||
|
||||
explicit
|
||||
PitInfo(const Duration& initialInterval)
|
||||
: suppressionInterval(initialInterval)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
/** \brief if last transmission occurred within suppressionInterval,
|
||||
* retransmission will be suppressed
|
||||
*/
|
||||
Duration suppressionInterval;
|
||||
};
|
||||
|
||||
RetxSuppressionExponential::RetxSuppressionExponential(const Duration& initialInterval,
|
||||
float multiplier,
|
||||
const Duration& maxInterval)
|
||||
: m_initialInterval(initialInterval)
|
||||
, m_multiplier(multiplier)
|
||||
, m_maxInterval(maxInterval)
|
||||
{
|
||||
BOOST_ASSERT(initialInterval > time::milliseconds::zero());
|
||||
BOOST_ASSERT(multiplier >= 1.0);
|
||||
BOOST_ASSERT(maxInterval >= initialInterval);
|
||||
}
|
||||
|
||||
RetxSuppression::Result
|
||||
RetxSuppressionExponential::decide(const Face& inFace, const Interest& interest,
|
||||
pit::Entry& pitEntry) const
|
||||
{
|
||||
bool isNewPitEntry = !pitEntry.hasUnexpiredOutRecords();
|
||||
if (isNewPitEntry) {
|
||||
return NEW;
|
||||
}
|
||||
|
||||
time::steady_clock::TimePoint lastOutgoing = this->getLastOutgoing(pitEntry);
|
||||
time::steady_clock::TimePoint now = time::steady_clock::now();
|
||||
time::steady_clock::Duration sinceLastOutgoing = now - lastOutgoing;
|
||||
|
||||
shared_ptr<PitInfo> pi = pitEntry.getOrCreateStrategyInfo<PitInfo>(m_initialInterval);
|
||||
bool shouldSuppress = sinceLastOutgoing < pi->suppressionInterval;
|
||||
|
||||
if (shouldSuppress) {
|
||||
return SUPPRESS;
|
||||
}
|
||||
|
||||
pi->suppressionInterval = std::min(m_maxInterval,
|
||||
time::duration_cast<Duration>(pi->suppressionInterval * m_multiplier));
|
||||
return FORWARD;
|
||||
}
|
||||
|
||||
} // namespace fw
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,78 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NFD_DAEMON_FW_RETX_SUPPRESSION_EXPONENTIAL_HPP
|
||||
#define NFD_DAEMON_FW_RETX_SUPPRESSION_EXPONENTIAL_HPP
|
||||
|
||||
#include "retx-suppression.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
/** \brief a retransmission suppression decision algorithm that
|
||||
* suppresses retransmissions using exponential backoff
|
||||
*
|
||||
* The i-th retransmission will be suppressed if the last transmission (out-record)
|
||||
* occurred within MIN(initialInterval * multiplier^(i-1), maxInterval)
|
||||
*/
|
||||
class RetxSuppressionExponential : public RetxSuppression
|
||||
{
|
||||
public:
|
||||
/** \brief time granularity
|
||||
*/
|
||||
typedef time::microseconds Duration;
|
||||
|
||||
explicit
|
||||
RetxSuppressionExponential(const Duration& initialInterval = DEFAULT_INITIAL_INTERVAL,
|
||||
float multiplier = DEFAULT_MULTIPLIER,
|
||||
const Duration& maxInterval = DEFAULT_MAX_INTERVAL);
|
||||
|
||||
/** \brief determines whether Interest is a retransmission,
|
||||
* and if so, whether it shall be forwarded or suppressed
|
||||
*/
|
||||
virtual Result
|
||||
decide(const Face& inFace, const Interest& interest,
|
||||
pit::Entry& pitEntry) const DECL_OVERRIDE;
|
||||
|
||||
public:
|
||||
/** \brief StrategyInfo on pit::Entry
|
||||
*/
|
||||
class PitInfo;
|
||||
|
||||
public:
|
||||
static const Duration DEFAULT_INITIAL_INTERVAL;
|
||||
static const float DEFAULT_MULTIPLIER;
|
||||
static const Duration DEFAULT_MAX_INTERVAL;
|
||||
|
||||
private:
|
||||
const Duration m_initialInterval;
|
||||
const float m_multiplier;
|
||||
const Duration m_maxInterval;
|
||||
};
|
||||
|
||||
} // namespace fw
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FW_RETX_SUPPRESSION_EXPONENTIAL_HPP
|
||||
@@ -0,0 +1,56 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "retx-suppression-fixed.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
const time::milliseconds RetxSuppressionFixed::DEFAULT_MIN_RETX_INTERVAL(100);
|
||||
|
||||
RetxSuppressionFixed::RetxSuppressionFixed(const time::milliseconds& minRetxInterval)
|
||||
: m_minRetxInterval(minRetxInterval)
|
||||
{
|
||||
BOOST_ASSERT(minRetxInterval > time::milliseconds::zero());
|
||||
}
|
||||
|
||||
RetxSuppression::Result
|
||||
RetxSuppressionFixed::decide(const Face& inFace, const Interest& interest,
|
||||
pit::Entry& pitEntry) const
|
||||
{
|
||||
bool isNewPitEntry = !pitEntry.hasUnexpiredOutRecords();
|
||||
if (isNewPitEntry) {
|
||||
return NEW;
|
||||
}
|
||||
|
||||
time::steady_clock::TimePoint lastOutgoing = this->getLastOutgoing(pitEntry);
|
||||
time::steady_clock::TimePoint now = time::steady_clock::now();
|
||||
time::steady_clock::Duration sinceLastOutgoing = now - lastOutgoing;
|
||||
bool shouldSuppress = sinceLastOutgoing < m_minRetxInterval;
|
||||
return shouldSuppress ? SUPPRESS : FORWARD;
|
||||
}
|
||||
|
||||
} // namespace fw
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,60 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NFD_DAEMON_FW_RETX_SUPPRESSION_FIXED_HPP
|
||||
#define NFD_DAEMON_FW_RETX_SUPPRESSION_FIXED_HPP
|
||||
|
||||
#include "retx-suppression.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
/** \brief a retransmission suppression decision algorithm that
|
||||
* suppresses retransmissions within a fixed duration
|
||||
*/
|
||||
class RetxSuppressionFixed : public RetxSuppression
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
RetxSuppressionFixed(const time::milliseconds& minRetxInterval = DEFAULT_MIN_RETX_INTERVAL);
|
||||
|
||||
/** \brief determines whether Interest is a retransmission,
|
||||
* and if so, whether it shall be forwarded or suppressed
|
||||
*/
|
||||
virtual Result
|
||||
decide(const Face& inFace, const Interest& interest,
|
||||
pit::Entry& pitEntry) const DECL_OVERRIDE;
|
||||
|
||||
public:
|
||||
static const time::milliseconds DEFAULT_MIN_RETX_INTERVAL;
|
||||
|
||||
private:
|
||||
const time::milliseconds m_minRetxInterval;
|
||||
};
|
||||
|
||||
} // namespace fw
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FW_RETX_SUPPRESSION_FIXED_HPP
|
||||
@@ -23,24 +23,14 @@
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "retransmission-suppression.hpp"
|
||||
#include "retx-suppression.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
/// \todo don't use fixed interval; make it adaptive or use exponential back-off #1913
|
||||
const time::milliseconds RetransmissionSuppression::MIN_RETRANSMISSION_INTERVAL(100);
|
||||
|
||||
RetransmissionSuppression::Result
|
||||
RetransmissionSuppression::decide(const Face& inFace, const Interest& interest,
|
||||
const pit::Entry& pitEntry)
|
||||
time::steady_clock::TimePoint
|
||||
RetxSuppression::getLastOutgoing(const pit::Entry& pitEntry) const
|
||||
{
|
||||
bool isNewPitEntry = !pitEntry.hasUnexpiredOutRecords();
|
||||
if (isNewPitEntry) {
|
||||
return NEW;
|
||||
}
|
||||
|
||||
// when was the last outgoing Interest?
|
||||
const pit::OutRecordCollection& outRecords = pitEntry.getOutRecords();
|
||||
pit::OutRecordCollection::const_iterator lastOutgoing = std::max_element(
|
||||
outRecords.begin(), outRecords.end(),
|
||||
@@ -49,10 +39,7 @@ RetransmissionSuppression::decide(const Face& inFace, const Interest& interest,
|
||||
});
|
||||
BOOST_ASSERT(lastOutgoing != outRecords.end()); // otherwise it's new PIT entry
|
||||
|
||||
time::steady_clock::TimePoint now = time::steady_clock::now();
|
||||
time::steady_clock::Duration sinceLastOutgoing = now - lastOutgoing->getLastRenewed();
|
||||
bool shouldSuppress = sinceLastOutgoing < MIN_RETRANSMISSION_INTERVAL;
|
||||
return shouldSuppress ? SUPPRESS : FORWARD;
|
||||
return lastOutgoing->getLastRenewed();
|
||||
}
|
||||
|
||||
} // namespace fw
|
||||
@@ -23,8 +23,8 @@
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NFD_DAEMON_FW_RETRANSMISSION_SUPPRESSION_HPP
|
||||
#define NFD_DAEMON_FW_RETRANSMISSION_SUPPRESSION_HPP
|
||||
#ifndef NFD_DAEMON_FW_RETX_SUPPRESSION_HPP
|
||||
#define NFD_DAEMON_FW_RETX_SUPPRESSION_HPP
|
||||
|
||||
#include "strategy.hpp"
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace fw {
|
||||
|
||||
/** \brief helper for consumer retransmission suppression
|
||||
*/
|
||||
class RetransmissionSuppression : noncopyable
|
||||
class RetxSuppression : noncopyable
|
||||
{
|
||||
public:
|
||||
enum Result {
|
||||
@@ -53,14 +53,18 @@ public:
|
||||
/** \brief determines whether Interest is a retransmission,
|
||||
* and if so, whether it shall be forwarded or suppressed
|
||||
*/
|
||||
Result
|
||||
decide(const Face& inFace, const Interest& interest, const pit::Entry& pitEntry);
|
||||
virtual Result
|
||||
decide(const Face& inFace, const Interest& interest, pit::Entry& pitEntry) const = 0;
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
static const time::milliseconds MIN_RETRANSMISSION_INTERVAL;
|
||||
protected:
|
||||
/** \return last out-record time
|
||||
* \pre pitEntry has one or more unexpired out-records
|
||||
*/
|
||||
time::steady_clock::TimePoint
|
||||
getLastOutgoing(const pit::Entry& pitEntry) const;
|
||||
};
|
||||
|
||||
} // namespace fw
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FW_RETRANSMISSION_SUPPRESSION_HPP
|
||||
#endif // NFD_DAEMON_FW_RETX_SUPPRESSION_HPP
|
||||
@@ -23,12 +23,8 @@
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "best-route-strategy.hpp"
|
||||
#include "broadcast-strategy.hpp"
|
||||
#include "client-control-strategy.hpp"
|
||||
#include "ncc-strategy.hpp"
|
||||
#include "strategy-registry.hpp"
|
||||
#include "best-route-strategy2.hpp"
|
||||
#include "access-strategy.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
@@ -39,25 +35,28 @@ makeDefaultStrategy(Forwarder& forwarder)
|
||||
return make_shared<BestRouteStrategy2>(ref(forwarder));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline void
|
||||
installStrategy(Forwarder& forwarder)
|
||||
static std::map<Name, StrategyCreateFunc>&
|
||||
getStrategyFactories()
|
||||
{
|
||||
StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
|
||||
if (!strategyChoice.hasStrategy(S::STRATEGY_NAME)) {
|
||||
strategyChoice.install(make_shared<S>(ref(forwarder)));
|
||||
}
|
||||
static std::map<Name, StrategyCreateFunc> strategyFactories;
|
||||
return strategyFactories;
|
||||
}
|
||||
|
||||
void
|
||||
registerStrategyImpl(const Name& strategyName, const StrategyCreateFunc& createFunc)
|
||||
{
|
||||
getStrategyFactories().insert({strategyName, createFunc});
|
||||
}
|
||||
|
||||
void
|
||||
installStrategies(Forwarder& forwarder)
|
||||
{
|
||||
installStrategy<BestRouteStrategy>(forwarder);
|
||||
installStrategy<BroadcastStrategy>(forwarder);
|
||||
installStrategy<ClientControlStrategy>(forwarder);
|
||||
installStrategy<NccStrategy>(forwarder);
|
||||
installStrategy<BestRouteStrategy2>(forwarder);
|
||||
installStrategy<AccessStrategy>(forwarder);
|
||||
StrategyChoice& sc = forwarder.getStrategyChoice();
|
||||
for (const auto& pair : getStrategyFactories()) {
|
||||
if (!sc.hasStrategy(pair.first, true)) {
|
||||
sc.install(pair.second(forwarder));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace fw
|
||||
@@ -0,0 +1,78 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NFD_DAEMON_FW_STRATEGY_REGISTRY_HPP
|
||||
#define NFD_DAEMON_FW_STRATEGY_REGISTRY_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
class Forwarder;
|
||||
|
||||
namespace fw {
|
||||
|
||||
class Strategy;
|
||||
|
||||
shared_ptr<Strategy>
|
||||
makeDefaultStrategy(Forwarder& forwarder);
|
||||
|
||||
void
|
||||
installStrategies(Forwarder& forwarder);
|
||||
|
||||
|
||||
typedef std::function<shared_ptr<Strategy>(Forwarder&)> StrategyCreateFunc;
|
||||
|
||||
void
|
||||
registerStrategyImpl(const Name& strategyName, const StrategyCreateFunc& createFunc);
|
||||
|
||||
/** \brief registers a strategy to be installed later
|
||||
*/
|
||||
template<typename S>
|
||||
void
|
||||
registerStrategy()
|
||||
{
|
||||
registerStrategyImpl(S::STRATEGY_NAME,
|
||||
[] (Forwarder& forwarder) { return make_shared<S>(ref(forwarder)); });
|
||||
}
|
||||
|
||||
/** \brief registers a built-in strategy
|
||||
*
|
||||
* This macro should appear once in .cpp of each built-in strategy.
|
||||
*/
|
||||
#define NFD_REGISTER_STRATEGY(StrategyType) \
|
||||
static class NfdAuto ## StrategyType ## StrategyRegistrationClass \
|
||||
{ \
|
||||
public: \
|
||||
NfdAuto ## StrategyType ## StrategyRegistrationClass() \
|
||||
{ \
|
||||
::nfd::fw::registerStrategy<StrategyType>(); \
|
||||
} \
|
||||
} g_nfdAuto ## StrategyType ## StrategyRegistrationVariable
|
||||
|
||||
} // namespace fw
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FW_STRATEGY_REGISTRY_HPP
|
||||
@@ -1,12 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -27,6 +27,7 @@
|
||||
#define NFD_DAEMON_FW_STRATEGY_HPP
|
||||
|
||||
#include "forwarder.hpp"
|
||||
#include "strategy-registry.hpp"
|
||||
#include "table/measurements-accessor.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
+165
-278
@@ -1,12 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -23,153 +23,57 @@
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "nfd.hpp"
|
||||
#include "rib/nrd.hpp"
|
||||
|
||||
#include "version.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include "core/privilege-helper.hpp"
|
||||
#include "fw/forwarder.hpp"
|
||||
#include "face/null-face.hpp"
|
||||
#include "mgmt/internal-face.hpp"
|
||||
#include "mgmt/fib-manager.hpp"
|
||||
#include "mgmt/face-manager.hpp"
|
||||
#include "mgmt/strategy-choice-manager.hpp"
|
||||
#include "mgmt/status-server.hpp"
|
||||
#include "core/config-file.hpp"
|
||||
#include "mgmt/general-config-section.hpp"
|
||||
#include "mgmt/tables-config-section.hpp"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/program_options/options_description.hpp>
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
#include <boost/program_options/parsers.hpp>
|
||||
|
||||
// boost::thread is used instead of std::thread to guarantee proper cleanup of thread local storage,
|
||||
// see http://www.boost.org/doc/libs/1_48_0/doc/html/thread/thread_local_storage.html
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("NFD");
|
||||
|
||||
struct ProgramOptions
|
||||
{
|
||||
bool showUsage;
|
||||
bool showVersion;
|
||||
bool showModules;
|
||||
std::string config;
|
||||
};
|
||||
|
||||
class Nfd : noncopyable
|
||||
/** \brief Executes NFD with RIB manager
|
||||
*
|
||||
* NFD (main forwarding procedure) and RIB manager execute in two different threads.
|
||||
* Each thread has its own instances global io_service and global scheduler.
|
||||
*
|
||||
* When either of the daemons fails, execution of non-failed daemon will be terminated as
|
||||
* well. In other words, when NFD fails, RIB manager will be terminated; when RIB manager
|
||||
* fails, NFD will be terminated.
|
||||
*/
|
||||
class NfdRunner : noncopyable
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
Nfd(const std::string& configFile)
|
||||
: m_configFile(configFile)
|
||||
, m_originalStreamBuf(0)
|
||||
NfdRunner(const std::string& configFile)
|
||||
: m_nfd(configFile, m_nfdKeyChain)
|
||||
, m_configFile(configFile)
|
||||
, m_terminationSignalSet(getGlobalIoService())
|
||||
, m_reloadSignalSet(getGlobalIoService())
|
||||
{
|
||||
}
|
||||
m_terminationSignalSet.add(SIGINT);
|
||||
m_terminationSignalSet.add(SIGTERM);
|
||||
m_terminationSignalSet.async_wait(bind(&NfdRunner::terminate, this, _1, _2));
|
||||
|
||||
~Nfd()
|
||||
{
|
||||
if (static_cast<bool>(m_originalStreamBuf)) {
|
||||
std::clog.rdbuf(m_originalStreamBuf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
initialize()
|
||||
{
|
||||
initializeLogging();
|
||||
|
||||
m_forwarder = make_shared<Forwarder>();
|
||||
|
||||
initializeManagement();
|
||||
|
||||
m_forwarder->getFaceTable().addReserved(make_shared<NullFace>(), FACEID_NULL);
|
||||
m_forwarder->getFaceTable().addReserved(
|
||||
make_shared<NullFace>(FaceUri("contentstore://")), FACEID_CONTENT_STORE);
|
||||
|
||||
PrivilegeHelper::drop();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
initializeLogging()
|
||||
{
|
||||
ConfigFile config(&ConfigFile::ignoreUnknownSection);
|
||||
LoggerFactory::getInstance().setConfigFile(config);
|
||||
|
||||
config.parse(m_configFile, true);
|
||||
config.parse(m_configFile, false);
|
||||
}
|
||||
|
||||
class IgnoreRibAndLogSections
|
||||
{
|
||||
public:
|
||||
void
|
||||
operator()(const std::string& filename,
|
||||
const std::string& sectionName,
|
||||
const ConfigSection& section,
|
||||
bool isDryRun)
|
||||
|
||||
{
|
||||
// Ignore "log" and sections beginning with "rib_" (intended for rib manager),
|
||||
// but raise an error if we're missing a handler for an NFD section.
|
||||
|
||||
if (sectionName.find("rib") == 0 || sectionName == "log")
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
// missing NFD section
|
||||
ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
initializeManagement()
|
||||
{
|
||||
m_internalFace = make_shared<InternalFace>();
|
||||
|
||||
m_fibManager = make_shared<FibManager>(ref(m_forwarder->getFib()),
|
||||
bind(&Forwarder::getFace, m_forwarder.get(), _1),
|
||||
m_internalFace,
|
||||
ndn::ref(m_keyChain));
|
||||
|
||||
m_faceManager = make_shared<FaceManager>(ref(m_forwarder->getFaceTable()),
|
||||
m_internalFace,
|
||||
ndn::ref(m_keyChain));
|
||||
|
||||
m_strategyChoiceManager =
|
||||
make_shared<StrategyChoiceManager>(ref(m_forwarder->getStrategyChoice()),
|
||||
m_internalFace,
|
||||
ndn::ref(m_keyChain));
|
||||
|
||||
m_statusServer = make_shared<StatusServer>(m_internalFace,
|
||||
ref(*m_forwarder),
|
||||
ndn::ref(m_keyChain));
|
||||
|
||||
ConfigFile config((IgnoreRibAndLogSections()));
|
||||
general::setConfigFile(config);
|
||||
|
||||
TablesConfigSection tablesConfig(m_forwarder->getCs(),
|
||||
m_forwarder->getPit(),
|
||||
m_forwarder->getFib(),
|
||||
m_forwarder->getStrategyChoice(),
|
||||
m_forwarder->getMeasurements());
|
||||
tablesConfig.setConfigFile(config);
|
||||
|
||||
m_internalFace->getValidator().setConfigFile(config);
|
||||
|
||||
m_forwarder->getFaceTable().addReserved(m_internalFace, FACEID_INTERNAL_FACE);
|
||||
|
||||
m_faceManager->setConfigFile(config);
|
||||
|
||||
// parse config file
|
||||
config.parse(m_configFile, true);
|
||||
config.parse(m_configFile, false);
|
||||
|
||||
tablesConfig.ensureTablesAreConfigured();
|
||||
|
||||
// add FIB entry for NFD Management Protocol
|
||||
shared_ptr<fib::Entry> entry = m_forwarder->getFib().insert("/localhost/nfd").first;
|
||||
entry->addNextHop(m_internalFace, 0);
|
||||
m_reloadSignalSet.add(SIGHUP);
|
||||
m_reloadSignalSet.async_wait(bind(&NfdRunner::reload, this, _1, _2));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -192,137 +96,127 @@ public:
|
||||
static void
|
||||
printModules(std::ostream& os)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
os << "Available logging modules: \n";
|
||||
|
||||
list<string> modules(LoggerFactory::getInstance().getModules());
|
||||
for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
|
||||
{
|
||||
os << *i << "\n";
|
||||
}
|
||||
for (const auto& module : LoggerFactory::getInstance().getModules()) {
|
||||
os << module << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
parseCommandLine(int argc, char** argv, ProgramOptions& options)
|
||||
void
|
||||
initialize()
|
||||
{
|
||||
options.showUsage = false;
|
||||
options.showVersion = false;
|
||||
options.showModules = false;
|
||||
options.config = DEFAULT_CONFIG_FILE;
|
||||
m_nfd.initialize();
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int optionIndex = 0;
|
||||
static ::option longOptions[] = {
|
||||
{ "help" , no_argument , 0, 0 },
|
||||
{ "modules", no_argument , 0, 0 },
|
||||
{ "config" , required_argument, 0, 0 },
|
||||
{ "version", no_argument , 0, 0 },
|
||||
{ 0 , 0 , 0, 0 }
|
||||
};
|
||||
int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
|
||||
if (c == -1)
|
||||
break;
|
||||
int
|
||||
run()
|
||||
{
|
||||
/** \brief return value
|
||||
* A non-zero value is assigned when either NFD or RIB manager (running in a separate
|
||||
* thread) fails.
|
||||
*/
|
||||
std::atomic_int retval(0);
|
||||
|
||||
switch (c) {
|
||||
case 0:
|
||||
switch (optionIndex) {
|
||||
case 0: // help
|
||||
options.showUsage = true;
|
||||
break;
|
||||
case 1: // modules
|
||||
options.showModules = true;
|
||||
break;
|
||||
case 2: // config
|
||||
options.config = ::optarg;
|
||||
break;
|
||||
case 3: // version
|
||||
options.showVersion = true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
boost::asio::io_service* const mainIo = &getGlobalIoService();
|
||||
boost::asio::io_service* nrdIo = nullptr;
|
||||
|
||||
// Mutex and conditional variable to implement synchronization between main and RIB manager
|
||||
// threads:
|
||||
// - to block main thread until RIB manager thread starts and initializes nrdIo (to allow
|
||||
// stopping it later)
|
||||
std::mutex m;
|
||||
std::condition_variable cv;
|
||||
|
||||
std::string configFile = this->m_configFile; // c++11 lambda cannot capture member variables
|
||||
boost::thread nrdThread([configFile, &retval, &nrdIo, mainIo, &cv, &m] {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m);
|
||||
nrdIo = &getGlobalIoService();
|
||||
BOOST_ASSERT(nrdIo != mainIo);
|
||||
}
|
||||
break;
|
||||
cv.notify_all(); // notify that nrdIo has been assigned
|
||||
|
||||
try {
|
||||
ndn::KeyChain nrdKeyChain;
|
||||
// must be created inside a separate thread
|
||||
rib::Nrd nrd(configFile, nrdKeyChain);
|
||||
nrd.initialize();
|
||||
getGlobalIoService().run(); // nrdIo is not thread-safe to use here
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
NFD_LOG_FATAL(e.what());
|
||||
retval = 6;
|
||||
mainIo->stop();
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m);
|
||||
nrdIo = nullptr;
|
||||
}
|
||||
});
|
||||
|
||||
{
|
||||
// Wait to guarantee that nrdIo is properly initialized, so it can be used to terminate
|
||||
// RIB manager thread.
|
||||
std::unique_lock<std::mutex> lock(m);
|
||||
cv.wait(lock, [&nrdIo] { return nrdIo != nullptr; });
|
||||
}
|
||||
|
||||
try {
|
||||
mainIo->run();
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
NFD_LOG_FATAL(e.what());
|
||||
retval = 4;
|
||||
}
|
||||
catch (const PrivilegeHelper::Error& e) {
|
||||
NFD_LOG_FATAL(e.what());
|
||||
retval = 5;
|
||||
}
|
||||
|
||||
{
|
||||
// nrdIo is guaranteed to be alive at this point
|
||||
std::lock_guard<std::mutex> lock(m);
|
||||
if (nrdIo != nullptr) {
|
||||
nrdIo->stop();
|
||||
nrdIo = nullptr;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
nrdThread.join();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
terminate(const boost::system::error_code& error,
|
||||
int signalNo,
|
||||
boost::asio::signal_set& signalSet)
|
||||
terminate(const boost::system::error_code& error, int signalNo)
|
||||
{
|
||||
if (error)
|
||||
return;
|
||||
|
||||
if (signalNo == SIGINT ||
|
||||
signalNo == SIGTERM)
|
||||
{
|
||||
getGlobalIoService().stop();
|
||||
NFD_LOG_INFO("Caught signal '" << strsignal(signalNo) << "', exiting...");
|
||||
}
|
||||
else
|
||||
{
|
||||
signalSet.async_wait(bind(&Nfd::terminate, this, _1, _2, ref(signalSet)));
|
||||
}
|
||||
NFD_LOG_INFO("Caught signal '" << ::strsignal(signalNo) << "', exiting...");
|
||||
getGlobalIoService().stop();
|
||||
}
|
||||
|
||||
void
|
||||
reload(const boost::system::error_code& error,
|
||||
int signalNo,
|
||||
boost::asio::signal_set& signalSet)
|
||||
reload(const boost::system::error_code& error, int signalNo)
|
||||
{
|
||||
if (error)
|
||||
return;
|
||||
|
||||
NFD_LOG_INFO("Caught signal '" << strsignal(signalNo));
|
||||
NFD_LOG_INFO("Caught signal '" << ::strsignal(signalNo) << "', reloading...");
|
||||
m_nfd.reloadConfigFile();
|
||||
|
||||
////////////////////////
|
||||
// Reload config file //
|
||||
////////////////////////
|
||||
|
||||
// Logging
|
||||
initializeLogging();
|
||||
/// \todo Reopen log file
|
||||
|
||||
// Other stuff
|
||||
ConfigFile config((IgnoreRibAndLogSections()));
|
||||
|
||||
general::setConfigFile(config);
|
||||
|
||||
TablesConfigSection tablesConfig(m_forwarder->getCs(),
|
||||
m_forwarder->getPit(),
|
||||
m_forwarder->getFib(),
|
||||
m_forwarder->getStrategyChoice(),
|
||||
m_forwarder->getMeasurements());
|
||||
|
||||
tablesConfig.setConfigFile(config);
|
||||
|
||||
m_internalFace->getValidator().setConfigFile(config);
|
||||
m_faceManager->setConfigFile(config);
|
||||
|
||||
config.parse(m_configFile, false);
|
||||
|
||||
////////////////////////
|
||||
|
||||
signalSet.async_wait(bind(&Nfd::reload, this, _1, _2, ref(signalSet)));
|
||||
m_reloadSignalSet.async_wait(bind(&NfdRunner::reload, this, _1, _2));
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_configFile;
|
||||
ndn::KeyChain m_nfdKeyChain;
|
||||
Nfd m_nfd;
|
||||
std::string m_configFile;
|
||||
|
||||
shared_ptr<Forwarder> m_forwarder;
|
||||
|
||||
shared_ptr<InternalFace> m_internalFace;
|
||||
shared_ptr<FibManager> m_fibManager;
|
||||
shared_ptr<FaceManager> m_faceManager;
|
||||
shared_ptr<StrategyChoiceManager> m_strategyChoiceManager;
|
||||
shared_ptr<StatusServer> m_statusServer;
|
||||
|
||||
shared_ptr<std::ofstream> m_logFile;
|
||||
std::basic_streambuf<char>* m_originalStreamBuf;
|
||||
ndn::KeyChain m_keyChain;
|
||||
boost::asio::signal_set m_terminationSignalSet;
|
||||
boost::asio::signal_set m_reloadSignalSet;
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
@@ -332,34 +226,50 @@ main(int argc, char** argv)
|
||||
{
|
||||
using namespace nfd;
|
||||
|
||||
ProgramOptions options;
|
||||
bool isCommandLineValid = Nfd::parseCommandLine(argc, argv, options);
|
||||
if (!isCommandLineValid) {
|
||||
Nfd::printUsage(std::cerr, argv[0]);
|
||||
namespace po = boost::program_options;
|
||||
|
||||
po::options_description description;
|
||||
|
||||
std::string configFile = DEFAULT_CONFIG_FILE;
|
||||
description.add_options()
|
||||
("help,h", "print this help message")
|
||||
("version,V", "print version and exit")
|
||||
("modules,m", "list available logging modules")
|
||||
("config,c", po::value<std::string>(&configFile), "path to configuration file")
|
||||
;
|
||||
|
||||
po::variables_map vm;
|
||||
try {
|
||||
po::store(po::command_line_parser(argc, argv).options(description).run(), vm);
|
||||
po::notify(vm);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "ERROR: " << e.what() << std::endl;
|
||||
NfdRunner::printUsage(std::cerr, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (options.showUsage) {
|
||||
Nfd::printUsage(std::cout, argv[0]);
|
||||
if (vm.count("help") > 0) {
|
||||
NfdRunner::printUsage(std::cout, argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (options.showVersion) {
|
||||
if (vm.count("version") > 0) {
|
||||
std::cout << NFD_VERSION_BUILD_STRING << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (options.showModules) {
|
||||
Nfd::printModules(std::cout);
|
||||
if (vm.count("modules") > 0) {
|
||||
NfdRunner::printModules(std::cout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Nfd nfdInstance(options.config);
|
||||
NfdRunner runner(configFile);
|
||||
|
||||
try {
|
||||
nfdInstance.initialize();
|
||||
runner.initialize();
|
||||
}
|
||||
catch (boost::filesystem::filesystem_error& e) {
|
||||
catch (const boost::filesystem::filesystem_error& e) {
|
||||
if (e.code() == boost::system::errc::permission_denied) {
|
||||
NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
|
||||
argv[0] << " should be run as superuser");
|
||||
@@ -381,28 +291,5 @@ main(int argc, char** argv)
|
||||
return 3;
|
||||
}
|
||||
|
||||
boost::asio::signal_set terminationSignalSet(getGlobalIoService());
|
||||
terminationSignalSet.add(SIGINT);
|
||||
terminationSignalSet.add(SIGTERM);
|
||||
terminationSignalSet.async_wait(bind(&Nfd::terminate, &nfdInstance, _1, _2,
|
||||
ref(terminationSignalSet)));
|
||||
|
||||
boost::asio::signal_set reloadSignalSet(getGlobalIoService());
|
||||
reloadSignalSet.add(SIGHUP);
|
||||
reloadSignalSet.async_wait(bind(&Nfd::reload, &nfdInstance, _1, _2,
|
||||
ref(reloadSignalSet)));
|
||||
|
||||
try {
|
||||
getGlobalIoService().run();
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
NFD_LOG_FATAL(e.what());
|
||||
return 4;
|
||||
}
|
||||
catch (const PrivilegeHelper::Error& e) {
|
||||
NFD_LOG_FATAL(e.what());
|
||||
return 5;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return runner.run();
|
||||
}
|
||||
@@ -24,8 +24,6 @@
|
||||
*/
|
||||
|
||||
#include "channel-status-publisher.hpp"
|
||||
|
||||
#include "core/logger.hpp"
|
||||
#include "face/protocol-factory.hpp"
|
||||
#include "face/channel.hpp"
|
||||
|
||||
@@ -33,9 +31,6 @@
|
||||
|
||||
namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("ChannelStatusPublisher");
|
||||
|
||||
|
||||
ChannelStatusPublisher::ChannelStatusPublisher(const FactoryMap& factories,
|
||||
AppFace& face,
|
||||
const Name& prefix,
|
||||
@@ -43,13 +38,10 @@ ChannelStatusPublisher::ChannelStatusPublisher(const FactoryMap& factories,
|
||||
: SegmentPublisher(face, prefix, keyChain)
|
||||
, m_factories(factories)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
ChannelStatusPublisher::~ChannelStatusPublisher()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
size_t
|
||||
|
||||
@@ -380,8 +380,8 @@ FaceManager::processSectionUdp(const ConfigSection& configSection,
|
||||
// udp
|
||||
// {
|
||||
// port 6363 ; UDP unicast port number
|
||||
// idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
|
||||
// keep_alive_interval 25; interval (seconds) between keep-alive refreshes
|
||||
// idle_timeout 600 ; idle time (seconds) before closing a UDP unicast face
|
||||
// keep_alive_interval 25 ; interval (seconds) between keep-alive refreshes
|
||||
|
||||
// ; NFD creates one UDP multicast face per NIC
|
||||
// mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
|
||||
@@ -392,7 +392,7 @@ FaceManager::processSectionUdp(const ConfigSection& configSection,
|
||||
std::string port = "6363";
|
||||
bool enableV4 = true;
|
||||
bool enableV6 = true;
|
||||
size_t timeout = 30;
|
||||
size_t timeout = 600;
|
||||
size_t keepAliveInterval = 25;
|
||||
bool useMcast = true;
|
||||
std::string mcastGroup = "224.0.23.170";
|
||||
|
||||
@@ -24,16 +24,12 @@
|
||||
**/
|
||||
|
||||
#include "face-query-status-publisher.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
#include <ndn-cxx/management/nfd-face-status.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("FaceQueryStatusPublisher");
|
||||
|
||||
|
||||
FaceQueryStatusPublisher::FaceQueryStatusPublisher(const FaceTable& faceTable,
|
||||
AppFace& face,
|
||||
const Name& prefix,
|
||||
|
||||
@@ -23,17 +23,13 @@
|
||||
**/
|
||||
|
||||
#include "face-status-publisher.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include "fw/face-table.hpp"
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
#include <ndn-cxx/management/nfd-face-status.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("FaceStatusPublisher");
|
||||
|
||||
|
||||
FaceStatusPublisher::FaceStatusPublisher(const FaceTable& faceTable,
|
||||
AppFace& face,
|
||||
const Name& prefix,
|
||||
@@ -41,13 +37,10 @@ FaceStatusPublisher::FaceStatusPublisher(const FaceTable& faceTable,
|
||||
: SegmentPublisher(face, prefix, keyChain)
|
||||
, m_faceTable(faceTable)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
FaceStatusPublisher::~FaceStatusPublisher()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
size_t
|
||||
|
||||
@@ -79,9 +79,9 @@ FibEnumerationPublisher::generate(ndn::EncodingBuffer& outBuffer)
|
||||
|
||||
totalLength += fibEntryLength;
|
||||
}
|
||||
|
||||
NFD_LOG_DEBUG("generate: Total length = " << totalLength);
|
||||
return totalLength;
|
||||
}
|
||||
|
||||
|
||||
} // namespace nfd
|
||||
@@ -24,16 +24,12 @@
|
||||
**/
|
||||
|
||||
#include "strategy-choice-publisher.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include "table/strategy-choice.hpp"
|
||||
|
||||
#include <ndn-cxx/management/nfd-strategy-choice.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("StrategyChoicePublisher");
|
||||
|
||||
|
||||
StrategyChoicePublisher::StrategyChoicePublisher(const StrategyChoice& strategyChoice,
|
||||
AppFace& face,
|
||||
const Name& prefix,
|
||||
@@ -41,12 +37,10 @@ StrategyChoicePublisher::StrategyChoicePublisher(const StrategyChoice& strategyC
|
||||
: SegmentPublisher(face, prefix, keyChain)
|
||||
, m_strategyChoice(strategyChoice)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
StrategyChoicePublisher::~StrategyChoicePublisher()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
size_t
|
||||
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "nfd.hpp"
|
||||
|
||||
#include "core/logger-factory.hpp"
|
||||
#include "core/privilege-helper.hpp"
|
||||
#include "fw/forwarder.hpp"
|
||||
#include "face/null-face.hpp"
|
||||
#include "mgmt/internal-face.hpp"
|
||||
#include "mgmt/fib-manager.hpp"
|
||||
#include "mgmt/face-manager.hpp"
|
||||
#include "mgmt/strategy-choice-manager.hpp"
|
||||
#include "mgmt/status-server.hpp"
|
||||
#include "core/config-file.hpp"
|
||||
#include "mgmt/general-config-section.hpp"
|
||||
#include "mgmt/tables-config-section.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
static const std::string INTERNAL_CONFIG = "internal://nfd.conf";
|
||||
|
||||
Nfd::Nfd(const std::string& configFile, ndn::KeyChain& keyChain)
|
||||
: m_configFile(configFile)
|
||||
, m_keyChain(keyChain)
|
||||
{
|
||||
}
|
||||
|
||||
Nfd::Nfd(const ConfigSection& config, ndn::KeyChain& keyChain)
|
||||
: m_configSection(config)
|
||||
, m_keyChain(keyChain)
|
||||
{
|
||||
}
|
||||
|
||||
Nfd::~Nfd()
|
||||
{
|
||||
// It is necessary to explicitly define the destructor, because some member variables (e.g.,
|
||||
// unique_ptr<Forwarder>) are forward-declared, but implicitly declared destructor requires
|
||||
// complete types for all members when instantiated.
|
||||
}
|
||||
|
||||
void
|
||||
Nfd::initialize()
|
||||
{
|
||||
initializeLogging();
|
||||
|
||||
m_forwarder.reset(new Forwarder());
|
||||
|
||||
initializeManagement();
|
||||
|
||||
m_forwarder->getFaceTable().addReserved(make_shared<NullFace>(), FACEID_NULL);
|
||||
m_forwarder->getFaceTable().addReserved(make_shared<NullFace>(FaceUri("contentstore://")),
|
||||
FACEID_CONTENT_STORE);
|
||||
|
||||
PrivilegeHelper::drop();
|
||||
}
|
||||
|
||||
void
|
||||
Nfd::initializeLogging()
|
||||
{
|
||||
ConfigFile config(&ConfigFile::ignoreUnknownSection);
|
||||
LoggerFactory::getInstance().setConfigFile(config);
|
||||
|
||||
if (!m_configFile.empty()) {
|
||||
config.parse(m_configFile, true);
|
||||
config.parse(m_configFile, false);
|
||||
}
|
||||
else {
|
||||
config.parse(m_configSection, true, INTERNAL_CONFIG);
|
||||
config.parse(m_configSection, false, INTERNAL_CONFIG);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
ignoreRibAndLogSections(const std::string& filename, const std::string& sectionName,
|
||||
const ConfigSection& section, bool isDryRun)
|
||||
{
|
||||
// Ignore "log" and "rib" sections, but raise an error if we're missing a
|
||||
// handler for an NFD section.
|
||||
if (sectionName == "rib" || sectionName == "log") {
|
||||
// do nothing
|
||||
}
|
||||
else {
|
||||
// missing NFD section
|
||||
ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Nfd::initializeManagement()
|
||||
{
|
||||
m_internalFace = make_shared<InternalFace>();
|
||||
|
||||
m_fibManager.reset(new FibManager(m_forwarder->getFib(),
|
||||
bind(&Forwarder::getFace, m_forwarder.get(), _1),
|
||||
m_internalFace, m_keyChain));
|
||||
|
||||
m_faceManager.reset(new FaceManager(m_forwarder->getFaceTable(), m_internalFace, m_keyChain));
|
||||
|
||||
m_strategyChoiceManager.reset(new StrategyChoiceManager(m_forwarder->getStrategyChoice(),
|
||||
m_internalFace, m_keyChain));
|
||||
|
||||
m_statusServer.reset(new StatusServer(m_internalFace, *m_forwarder, m_keyChain));
|
||||
|
||||
ConfigFile config(&ignoreRibAndLogSections);
|
||||
general::setConfigFile(config);
|
||||
|
||||
TablesConfigSection tablesConfig(m_forwarder->getCs(),
|
||||
m_forwarder->getPit(),
|
||||
m_forwarder->getFib(),
|
||||
m_forwarder->getStrategyChoice(),
|
||||
m_forwarder->getMeasurements());
|
||||
tablesConfig.setConfigFile(config);
|
||||
|
||||
m_internalFace->getValidator().setConfigFile(config);
|
||||
|
||||
m_forwarder->getFaceTable().addReserved(m_internalFace, FACEID_INTERNAL_FACE);
|
||||
|
||||
m_faceManager->setConfigFile(config);
|
||||
|
||||
// parse config file
|
||||
if (!m_configFile.empty()) {
|
||||
config.parse(m_configFile, true);
|
||||
config.parse(m_configFile, false);
|
||||
}
|
||||
else {
|
||||
config.parse(m_configSection, true, INTERNAL_CONFIG);
|
||||
config.parse(m_configSection, false, INTERNAL_CONFIG);
|
||||
}
|
||||
|
||||
tablesConfig.ensureTablesAreConfigured();
|
||||
|
||||
// add FIB entry for NFD Management Protocol
|
||||
shared_ptr<fib::Entry> entry = m_forwarder->getFib().insert("/localhost/nfd").first;
|
||||
entry->addNextHop(m_internalFace, 0);
|
||||
}
|
||||
|
||||
void
|
||||
Nfd::reloadConfigFile()
|
||||
{
|
||||
// Logging
|
||||
initializeLogging();
|
||||
/// \todo Reopen log file
|
||||
|
||||
// Other stuff
|
||||
ConfigFile config(&ignoreRibAndLogSections);
|
||||
|
||||
general::setConfigFile(config);
|
||||
|
||||
TablesConfigSection tablesConfig(m_forwarder->getCs(),
|
||||
m_forwarder->getPit(),
|
||||
m_forwarder->getFib(),
|
||||
m_forwarder->getStrategyChoice(),
|
||||
m_forwarder->getMeasurements());
|
||||
|
||||
tablesConfig.setConfigFile(config);
|
||||
|
||||
m_internalFace->getValidator().setConfigFile(config);
|
||||
m_faceManager->setConfigFile(config);
|
||||
|
||||
if (!m_configFile.empty()) {
|
||||
config.parse(m_configFile, false);
|
||||
}
|
||||
else {
|
||||
config.parse(m_configSection, false, INTERNAL_CONFIG);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NFD_DAEMON_NFD_HPP
|
||||
#define NFD_DAEMON_NFD_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
#include "core/config-file.hpp"
|
||||
|
||||
#include <ndn-cxx/security/key-chain.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
class Forwarder;
|
||||
class InternalFace;
|
||||
class FibManager;
|
||||
class FaceManager;
|
||||
class StrategyChoiceManager;
|
||||
class StatusServer;
|
||||
|
||||
/**
|
||||
* \brief Class representing NFD instance
|
||||
* This class can be used to initialize all components of NFD
|
||||
*/
|
||||
class Nfd : noncopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Create NFD instance using absolute or relative path to \p configFile
|
||||
*/
|
||||
Nfd(const std::string& configFile, ndn::KeyChain& keyChain);
|
||||
|
||||
/**
|
||||
* \brief Create NFD instance using a parsed ConfigSection \p config
|
||||
* This version of the constructor is more appropriate for integrated environments,
|
||||
* such as NS-3 or android.
|
||||
* \note When using this version of the constructor, error messages will include
|
||||
* "internal://nfd.conf" when referring to configuration errors.
|
||||
*/
|
||||
Nfd(const ConfigSection& config, ndn::KeyChain& keyChain);
|
||||
|
||||
/**
|
||||
* \brief Destructor
|
||||
*/
|
||||
~Nfd();
|
||||
|
||||
/**
|
||||
* \brief Perform initialization of NFD instance
|
||||
* After initialization, NFD instance can be started by invoking run on globalIoService
|
||||
*/
|
||||
void
|
||||
initialize();
|
||||
|
||||
/**
|
||||
* \brief Reload configuration file and apply update (if any)
|
||||
*/
|
||||
void
|
||||
reloadConfigFile();
|
||||
|
||||
private:
|
||||
void
|
||||
initializeLogging();
|
||||
|
||||
void
|
||||
initializeManagement();
|
||||
|
||||
private:
|
||||
std::string m_configFile;
|
||||
ConfigSection m_configSection;
|
||||
|
||||
unique_ptr<Forwarder> m_forwarder;
|
||||
|
||||
shared_ptr<InternalFace> m_internalFace;
|
||||
unique_ptr<FibManager> m_fibManager;
|
||||
unique_ptr<FaceManager> m_faceManager;
|
||||
unique_ptr<StrategyChoiceManager> m_strategyChoiceManager;
|
||||
unique_ptr<StatusServer> m_statusServer;
|
||||
|
||||
ndn::KeyChain& m_keyChain;
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_NFD_HPP
|
||||
@@ -1,89 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* \author Ilya Moiseenko <http://ilyamoiseenko.com/>
|
||||
* \author Junxiao Shi <http://www.cs.arizona.edu/people/shijunxiao/>
|
||||
* \author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
|
||||
*/
|
||||
|
||||
#ifndef NFD_DAEMON_TABLE_CS_SKIP_LIST_ENTRY_HPP
|
||||
#define NFD_DAEMON_TABLE_CS_SKIP_LIST_ENTRY_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
#include "cs-entry.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace cs {
|
||||
namespace skip_list {
|
||||
|
||||
/** \brief represents an entry in a CS with skip list implementation
|
||||
*/
|
||||
class Entry : public cs::Entry
|
||||
{
|
||||
public:
|
||||
typedef std::map<int, std::list<Entry*>::iterator > LayerIterators;
|
||||
|
||||
Entry() = default;
|
||||
|
||||
/** \brief releases reference counts on shared objects
|
||||
*/
|
||||
void
|
||||
release();
|
||||
|
||||
/** \brief saves the iterator pointing to the CS entry on a specific layer of skip list
|
||||
*/
|
||||
void
|
||||
setIterator(int layer, const LayerIterators::mapped_type& layerIterator);
|
||||
|
||||
/** \brief removes the iterator pointing to the CS entry on a specific layer of skip list
|
||||
*/
|
||||
void
|
||||
removeIterator(int layer);
|
||||
|
||||
/** \brief returns the table containing <layer, iterator> pairs.
|
||||
*/
|
||||
const LayerIterators&
|
||||
getIterators() const;
|
||||
|
||||
private:
|
||||
/** \brief prints <layer, iterator> pairs.
|
||||
*/
|
||||
void
|
||||
printIterators() const;
|
||||
|
||||
private:
|
||||
LayerIterators m_layerIterators;
|
||||
};
|
||||
|
||||
inline const Entry::LayerIterators&
|
||||
Entry::getIterators() const
|
||||
{
|
||||
return m_layerIterators;
|
||||
}
|
||||
|
||||
} // namespace skip_list
|
||||
} // namespace cs
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_TABLE_CS_SKIP_LIST_ENTRY_HPP
|
||||
+20
-4
@@ -63,6 +63,16 @@ Cs::insert(const Data& data, bool isUnsolicited)
|
||||
{
|
||||
NFD_LOG_DEBUG("insert " << data.getName());
|
||||
|
||||
// recognize CachingPolicy
|
||||
using ndn::nfd::LocalControlHeader;
|
||||
const LocalControlHeader& lch = data.getLocalControlHeader();
|
||||
if (lch.hasCachingPolicy()) {
|
||||
LocalControlHeader::CachingPolicy policy = lch.getCachingPolicy();
|
||||
if (policy == LocalControlHeader::CachingPolicy::NO_CACHE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool isNewEntry = false; TableIt it;
|
||||
// use .insert because gcc46 does not support .emplace
|
||||
std::tie(it, isNewEntry) = m_table.insert(EntryImpl(data.shared_from_this(), isUnsolicited));
|
||||
@@ -87,9 +97,14 @@ Cs::insert(const Data& data, bool isUnsolicited)
|
||||
return true;
|
||||
}
|
||||
|
||||
const Data*
|
||||
Cs::find(const Interest& interest) const
|
||||
void
|
||||
Cs::find(const Interest& interest,
|
||||
const HitCallback& hitCallback,
|
||||
const MissCallback& missCallback) const
|
||||
{
|
||||
BOOST_ASSERT(static_cast<bool>(hitCallback));
|
||||
BOOST_ASSERT(static_cast<bool>(missCallback));
|
||||
|
||||
const Name& prefix = interest.getName();
|
||||
bool isRightmost = interest.getChildSelector() == 1;
|
||||
NFD_LOG_DEBUG("find " << prefix << (isRightmost ? " R" : " L"));
|
||||
@@ -110,10 +125,11 @@ Cs::find(const Interest& interest) const
|
||||
|
||||
if (match == last) {
|
||||
NFD_LOG_DEBUG(" no-match");
|
||||
return nullptr;
|
||||
missCallback(interest);
|
||||
return;
|
||||
}
|
||||
NFD_LOG_DEBUG(" matching " << match->getName());
|
||||
return &match->getData();
|
||||
hitCallback(interest, match->getData());
|
||||
}
|
||||
|
||||
TableIt
|
||||
|
||||
+12
-2
@@ -68,10 +68,20 @@ public:
|
||||
bool
|
||||
insert(const Data& data, bool isUnsolicited = false);
|
||||
|
||||
typedef std::function<void(const Interest&, const Data& data)> HitCallback;
|
||||
typedef std::function<void(const Interest&)> MissCallback;
|
||||
|
||||
/** \brief finds the best matching Data packet
|
||||
* \param interest the Interest for lookup
|
||||
* \param hitCallback a callback if a match is found; must not be empty
|
||||
* \param missCallback a callback if there's no match; must not be empty
|
||||
* \note A lookup invokes either callback exactly once.
|
||||
* The callback may be invoked either before or after find() returns
|
||||
*/
|
||||
const Data*
|
||||
find(const Interest& interest) const;
|
||||
void
|
||||
find(const Interest& interest,
|
||||
const HitCallback& hitCallback,
|
||||
const MissCallback& missCallback) const;
|
||||
|
||||
void
|
||||
erase(const Name& exactName)
|
||||
|
||||
@@ -123,7 +123,7 @@ DeadNonceList::mark()
|
||||
size_t nMarks = this->countMarks();
|
||||
m_actualMarkCounts.insert(nMarks);
|
||||
|
||||
NFD_LOG_DEBUG("mark nMarks=" << nMarks);
|
||||
NFD_LOG_TRACE("mark nMarks=" << nMarks);
|
||||
|
||||
scheduler::schedule(m_markInterval, bind(&DeadNonceList::mark, this));
|
||||
}
|
||||
@@ -138,13 +138,13 @@ DeadNonceList::adjustCapacity()
|
||||
// all counts are above expected count, adjust down
|
||||
m_capacity = std::max(MIN_CAPACITY,
|
||||
static_cast<size_t>(m_capacity * CAPACITY_DOWN));
|
||||
NFD_LOG_DEBUG("adjustCapacity DOWN capacity=" << m_capacity);
|
||||
NFD_LOG_TRACE("adjustCapacity DOWN capacity=" << m_capacity);
|
||||
}
|
||||
else if (equalRange.first == m_actualMarkCounts.end()) {
|
||||
// all counts are below expected count, adjust up
|
||||
m_capacity = std::min(MAX_CAPACITY,
|
||||
static_cast<size_t>(m_capacity * CAPACITY_UP));
|
||||
NFD_LOG_DEBUG("adjustCapacity UP capacity=" << m_capacity);
|
||||
NFD_LOG_TRACE("adjustCapacity UP capacity=" << m_capacity);
|
||||
}
|
||||
|
||||
m_actualMarkCounts.clear();
|
||||
|
||||
+147
-3
@@ -3,12 +3,155 @@
|
||||
NFD Release Notes
|
||||
=================
|
||||
|
||||
NFD version 0.3.2 (changes since version 0.3.1)
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Release date: May 12, 2015
|
||||
|
||||
New features:
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
- **Tables**
|
||||
|
||||
* Change lookup API to allow async implementations of ContentStore (:issue:`2411`)
|
||||
|
||||
- **Management**
|
||||
|
||||
* Perform FIB updates before modifying RIB (:issue:`1941`)
|
||||
|
||||
Updates and bug fixes:
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- **Documentation**
|
||||
|
||||
* Update planned Features: face enhancements (:issue:`2617`)
|
||||
|
||||
* Updated NFD's developer guide to reflect new changes and adding a new section on
|
||||
NFD/ndn-cxx unit testing
|
||||
|
||||
- **Face**
|
||||
|
||||
* Refactor channel acceptors to avoid use of shared pointers (:issue:`2613`)
|
||||
|
||||
* Refactor code to avoid deprecated `Block::fromBuffer` overloads (:issue:`2553`)
|
||||
|
||||
* Refactor code to use move semantics for sockets where possible (:issue:`2613`)
|
||||
|
||||
* Switch to non-throwing version of websocketpp APIs (:issue:`2630`)
|
||||
|
||||
- **Forwarding**
|
||||
|
||||
* Extend measurements lifetime in AccessStrategy (:issue:`2452`)
|
||||
|
||||
- **Management**
|
||||
|
||||
* Stop removed namespace from inheriting ancestor route (:issue:`2757`)
|
||||
|
||||
* Fix TestFibUpdates/EraseFace on Ubuntu 14.04 32-bit (:issue:`2697`)
|
||||
|
||||
- **Tools**
|
||||
|
||||
* Fix hanging of `nfdc` on wrong input (:issue:`2690`)
|
||||
|
||||
- **Build**
|
||||
|
||||
* Make build scripts compatible with Python 3 (:issue:`2625`)
|
||||
|
||||
* Get rid of the last use of ndn::dns in NFD (:issue:`2422`)
|
||||
|
||||
* Update waf build system to version 1.8.9 (:issue:`2209`, :issue:`2657`, :issue:`2792`)
|
||||
|
||||
* Tweak default pkg-config search paths (:issue:`2711`)
|
||||
|
||||
* Use C version of snprintf (:issue:`2299`)
|
||||
|
||||
* Emulate `std::to_string` when it is missing (:issue:`2299`)
|
||||
|
||||
* Fix several "defined but not used" warnings with gcc-5 (:issue:`2767`)
|
||||
|
||||
* Disable precompiled headers on OS X with clang < 6.1.0 (:issue:`2804`)
|
||||
|
||||
****************************************************************************
|
||||
|
||||
NFD version 0.3.1 (changes since version 0.3.0)
|
||||
-----------------------------------------------
|
||||
|
||||
Release date: March 3, 2015
|
||||
|
||||
New features:
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
- ``nfd`` and ``nrd`` daemons are now merged into a single process using separate threads
|
||||
(:issue:`2489`)
|
||||
|
||||
- **Core**
|
||||
|
||||
- Extend ConfigFile to support passing a parsed ConfigSection (:issue:`2495`)
|
||||
|
||||
- Allow customization of Logger and LoggerFactory (:issue:`2433`)
|
||||
|
||||
- Make global io_service, scheduler, and global random generator thread-local, and logger
|
||||
thread-safe (:issue:`2489`)
|
||||
|
||||
- **Forwarding**
|
||||
|
||||
- Introduce exponential back-off interest retransmission suppression mechanism and enable
|
||||
its use in the best-route strategy (:issue:`1913`)
|
||||
|
||||
- Strategies are now registered with a macro, making it simpler to introduce new strategies
|
||||
to NFD codebase (:issue:`2410`)
|
||||
|
||||
- **Tables**
|
||||
|
||||
- ContentStore now recognizes CachingPolicy-NoCache from LocalControlHeader (:issue:`2185`)
|
||||
|
||||
Updates and bug fixes:
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- **Faces**
|
||||
|
||||
- Remove Tcp|UdpChannel::connect overloads that perform DNS resolution (:issue:`2422`)
|
||||
|
||||
- Properly handle error conditions in UdpChannel::newPeer (:issue:`2516`)
|
||||
|
||||
- Fix inconsistency of UDP face timeouts in sample `nfd.conf` and actual defaults
|
||||
(:issue:`2473`)
|
||||
|
||||
- Introduce Face-specific logging macros (:issue:`2450`)
|
||||
|
||||
- Refactor handling of LinkType face trait and fix FaceStatus reporting: the link type was
|
||||
not properly propagated (:issue:`2563`)
|
||||
|
||||
- Avoid exceptions in NDNLP PartialMessageStore (:issue:`2261`)
|
||||
|
||||
- Update websocketpp to version 0.5.1
|
||||
|
||||
- **Tables**
|
||||
|
||||
- Reduce priority of DeadNonceList log messages from DEBUG to TRACE
|
||||
|
||||
- **Management**
|
||||
|
||||
- Change register/unregister logging in RibManager to INFO level (:issue:`2547`)
|
||||
|
||||
- **Tools**
|
||||
|
||||
- Change prefix for :ref:`the local hub prefix discovery <local-prefix-discovery>` to be
|
||||
under ``/localhop/nfd`` (:issue:`2479`, :issue:`2512`)
|
||||
|
||||
- **Tests**
|
||||
|
||||
- Change naming conventions for unit test files and test suite names (:issue:`2497`)
|
||||
|
||||
- Fix segfault in TableNameTree test suite when all test logs are enabled (:issue:`2564`)
|
||||
|
||||
****************************************************************************
|
||||
|
||||
NFD version 0.3.0 (changes since version 0.2.0)
|
||||
-----------------------------------------------
|
||||
|
||||
Release date: February 2, 2015
|
||||
|
||||
|
||||
New features:
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
@@ -472,8 +615,9 @@ Planned Functions and Features for Next Releases
|
||||
For congestion control
|
||||
|
||||
- Face enhancements
|
||||
Add fragmentation support for Ethernet face, may add support for new types such as
|
||||
WiFi direct and WebSockets.
|
||||
Add faces for new underlying protocols such as WiFi direct.
|
||||
Introduce the concept of "permanent faces" that can survive socket errors.
|
||||
Design a new hop-by-hop header that supports fragmentation, reliability improvement, etc.
|
||||
|
||||
- Tables
|
||||
Experiment and evaluate different data structures and algorithms.
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ NFD Documentation
|
||||
|
||||
**Additional documentation**
|
||||
|
||||
* `NFD Developer's Guide <http://named-data.net/wp-content/uploads/2014/07/NFD-developer-guide.pdf>`_
|
||||
* `NFD Developer's Guide <http://named-data.net/techreport/ndn-0021-3-nfd-developer-guide.pdf>`_
|
||||
|
||||
A comprehensive guide to the design and implementation of NFD. The developer's guide also contains
|
||||
suggestions and hints for anyone wanting to modify or extend NFD.
|
||||
|
||||
@@ -6,13 +6,13 @@ Discover local hub prefix
|
||||
Some applications need to discover prefix(es) under which they can publish data
|
||||
/ which Interests local hub will be able to forward down to the application.
|
||||
In order to discover that, applications need to send an interest for
|
||||
``/localhop/ndn-autoconf/routable-prefixes`` prefix. Response data to the
|
||||
``/localhop/nfd/rib/routable-prefixes`` prefix. Response data to the
|
||||
interest contains a list of prefixes and should be encoded as:
|
||||
|
||||
::
|
||||
|
||||
Response ::= DATA-TYPE TLV-LENGTH
|
||||
Name (= /localhop/ndn-autoconf/routable-prefixes/[version])
|
||||
Name (= /localhop/nfd/rib/routable-prefixes/[version]/[segment])
|
||||
MetaInfo (= ResponseMetaInfo)
|
||||
Content (= ResponseContent)
|
||||
Signature
|
||||
@@ -28,5 +28,5 @@ interest contains a list of prefixes and should be encoded as:
|
||||
towards the face from which the request has been received. The requester may
|
||||
process list of the returned names and pick whichever it wants to use.
|
||||
|
||||
For now, the ``/localhop/ndn-autoconf/routable-prefixes`` data is served by
|
||||
For now, the ``/localhop/nfd/rib/routable-prefixes`` data is served by
|
||||
:ref:`ndn-autoconfig-server`.
|
||||
+5
-2
@@ -32,7 +32,6 @@ log
|
||||
;
|
||||
; Run:
|
||||
; nfd --modules
|
||||
; nrd --modules
|
||||
;
|
||||
; Or look for NFD_LOG_INIT(<module name>) statements in .cpp files
|
||||
;
|
||||
@@ -93,7 +92,11 @@ face_system
|
||||
port 6363 ; UDP unicast port number
|
||||
enable_v4 yes ; set to 'no' to disable IPv4 channels, default 'yes'
|
||||
enable_v6 yes ; set to 'no' to disable IPv6 channels, default 'yes'
|
||||
idle_timeout 600 ; idle time (seconds) before closing a UDP unicast face
|
||||
|
||||
; idle time (seconds) before closing a UDP unicast face, the actual timeout would be
|
||||
; anywhere within [idle_timeout, 2*idle_timeout), default is 600
|
||||
idle_timeout 600
|
||||
|
||||
keep_alive_interval 25; interval (seconds) between keep-alive refreshes
|
||||
|
||||
; UDP multicast settings
|
||||
|
||||
+18
-18
@@ -1,12 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -28,27 +28,27 @@
|
||||
namespace nfd {
|
||||
namespace rib {
|
||||
|
||||
shared_ptr<FibUpdate>
|
||||
FibUpdate
|
||||
FibUpdate::createAddUpdate(const Name& name, const uint64_t faceId, const uint64_t cost)
|
||||
{
|
||||
shared_ptr<FibUpdate> update = make_shared<FibUpdate>();
|
||||
FibUpdate update;
|
||||
|
||||
update->name = name;
|
||||
update->faceId = faceId;
|
||||
update->cost = cost;
|
||||
update->action = ADD_NEXTHOP;
|
||||
update.name = name;
|
||||
update.faceId = faceId;
|
||||
update.cost = cost;
|
||||
update.action = ADD_NEXTHOP;
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
shared_ptr<FibUpdate>
|
||||
FibUpdate
|
||||
FibUpdate::createRemoveUpdate(const Name& name, const uint64_t faceId)
|
||||
{
|
||||
shared_ptr<FibUpdate> update = make_shared<FibUpdate>();
|
||||
FibUpdate update;
|
||||
|
||||
update->name = name;
|
||||
update->faceId = faceId;
|
||||
update->action = REMOVE_NEXTHOP;
|
||||
update.name = name;
|
||||
update.faceId = faceId;
|
||||
update.action = REMOVE_NEXTHOP;
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
+26
-20
@@ -1,12 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -43,14 +43,22 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
static shared_ptr<FibUpdate>
|
||||
bool
|
||||
operator==(const FibUpdate& other) const
|
||||
{
|
||||
return (this->name == other.name &&
|
||||
this->faceId == other.faceId &&
|
||||
this->cost == other.cost &&
|
||||
this->action == other.action);
|
||||
}
|
||||
|
||||
static FibUpdate
|
||||
createAddUpdate(const Name& name, const uint64_t faceId, const uint64_t cost);
|
||||
|
||||
static shared_ptr<FibUpdate>
|
||||
static FibUpdate
|
||||
createRemoveUpdate(const Name& name, const uint64_t faceId);
|
||||
|
||||
enum Action
|
||||
{
|
||||
enum Action {
|
||||
ADD_NEXTHOP = 0,
|
||||
REMOVE_NEXTHOP = 1
|
||||
};
|
||||
@@ -69,15 +77,13 @@ operator<<(std::ostream& os, const FibUpdate& update)
|
||||
<< " Name: " << update.name << ", "
|
||||
<< "faceId: " << update.faceId << ", ";
|
||||
|
||||
if (update.action == FibUpdate::ADD_NEXTHOP)
|
||||
{
|
||||
os << "cost: " << update.cost << ", "
|
||||
<< "action: ADD_NEXTHOP";
|
||||
}
|
||||
else
|
||||
{
|
||||
os << "action: REMOVE_NEXTHOP";
|
||||
}
|
||||
if (update.action == FibUpdate::ADD_NEXTHOP) {
|
||||
os << "cost: " << update.cost << ", "
|
||||
<< "action: ADD_NEXTHOP";
|
||||
}
|
||||
else {
|
||||
os << "action: REMOVE_NEXTHOP";
|
||||
}
|
||||
|
||||
os << ")";
|
||||
|
||||
|
||||
Loaded 100 of 201 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user