Compare commits
333
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
704430ca07 | ||
|
|
58d479cd4a | ||
|
|
305529410b | ||
|
|
150b80deee | ||
|
|
280d7dde50 | ||
|
|
8509398137 | ||
|
|
42388d6c08 | ||
|
|
ffe8bbb8aa | ||
|
|
330136a89e | ||
|
|
bb9102f7d4 | ||
|
|
4310d505a7 | ||
|
|
d5fe0cf158 | ||
|
|
9360623853 | ||
|
|
e6f0e91590 | ||
|
|
dd7e5da016 | ||
|
|
459cf197b7 | ||
|
|
073da60b19 | ||
|
|
4370fde844 | ||
|
|
965f23dd61 | ||
|
|
72cee94646 | ||
|
|
bc9ed49a55 | ||
|
|
6db75f0bd2 | ||
|
|
4100646192 | ||
|
|
3152abac67 | ||
|
|
9aac873415 | ||
|
|
da3ba96430 | ||
|
|
809462490f | ||
|
|
498373dd01 | ||
|
|
c64d30aeff | ||
|
|
5c47597be9 | ||
|
|
6d8ee7acc9 | ||
|
|
cde37ad608 | ||
|
|
c5401494fe | ||
|
|
65caf20092 | ||
|
|
ca25d72064 | ||
|
|
f22ebaf7f1 | ||
|
|
f35a5a9b08 | ||
|
|
f68f378a23 | ||
|
|
8717e87046 | ||
|
|
0de23a29c5 | ||
|
|
6c4a67af0d | ||
|
|
35120ea2f1 | ||
|
|
eee7b97d7b | ||
|
|
762912d711 | ||
|
|
bd916ad7fc | ||
|
|
4c3e6b89a1 | ||
|
|
8c0500fd97 | ||
|
|
da93f1fd0c | ||
|
|
57df288f5b | ||
|
|
52e8540a86 | ||
|
|
077df8fbb6 | ||
|
|
8728a25f1d | ||
|
|
d5134a7cd4 | ||
|
|
47ab029798 | ||
|
|
ed89ccc521 | ||
|
|
16aabbcc3b | ||
|
|
9c7c79f2eb | ||
|
|
a044be7ed9 | ||
|
|
2d6d5637c0 | ||
|
|
5b8a2b2128 | ||
|
|
abb307c9c5 | ||
|
|
ba81830e81 | ||
|
|
b755e9d5a7 | ||
|
|
c8a66d3530 | ||
|
|
1354611277 | ||
|
|
1d7e7afd38 | ||
|
|
6535f1ed28 | ||
|
|
a1939ba993 | ||
|
|
964d4598ef | ||
|
|
747b67d38f | ||
|
|
d7c9636078 | ||
|
|
94735f99cb | ||
|
|
9c903e063e | ||
|
|
f485d89f16 | ||
|
|
f9572e8439 | ||
|
|
687dba8614 | ||
|
|
d374c406b2 | ||
|
|
259d0d876f | ||
|
|
40cb61c6bd | ||
|
|
643b36b814 | ||
|
|
0a49d34342 | ||
|
|
74c895d316 | ||
|
|
5e5e445182 | ||
|
|
86d3187d9b | ||
|
|
a98bf93a25 | ||
|
|
ec2a698301 | ||
|
|
01f8dba914 | ||
|
|
d2856a41ef | ||
|
|
441ba2175e | ||
|
|
435d705138 | ||
|
|
06a29459dc | ||
|
|
483c43396c | ||
|
|
ecbf584299 | ||
|
|
63ab1bb27a | ||
|
|
6704a4a6e4 | ||
|
|
7cec7eafce | ||
|
|
711c793171 | ||
|
|
73860e3397 | ||
|
|
698f4fea3a | ||
|
|
4ee73d42a4 | ||
|
|
36f3500d21 | ||
|
|
c6184cdb3e | ||
|
|
8149d1077b | ||
|
|
0355e9fd06 | ||
|
|
2fc649bfc6 | ||
|
|
67ba8d28df | ||
|
|
375dcb0bd6 | ||
|
|
0e092aee5c | ||
|
|
faa5c0cd3c | ||
|
|
149e02cf7d | ||
|
|
a714792b03 | ||
|
|
66c569ddcc | ||
|
|
3f41ade02d | ||
|
|
0315269228 | ||
|
|
62b19a6c09 | ||
|
|
7c90e6dfea | ||
|
|
4e274ac915 | ||
|
|
ee7c8441c8 | ||
|
|
c1dfdb44da | ||
|
|
a4527cc837 | ||
|
|
8082993f7f | ||
|
|
b81cff966e | ||
|
|
731f0d70fa | ||
|
|
08f07016a3 | ||
|
|
2666473042 | ||
|
|
5b6deaea18 | ||
|
|
971d3c2b09 | ||
|
|
dbe4f9fefe | ||
|
|
692842d6ad | ||
|
|
cb6e05f2dd | ||
|
|
5620fb2ac9 | ||
|
|
965d3a4e72 | ||
|
|
187ade8566 | ||
|
|
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 | ||
|
|
7c10b3bdc8 | ||
|
|
5af9bd3d6d | ||
|
|
ba3f79ec4f | ||
|
|
66ff0989c5 | ||
|
|
e46279dc83 | ||
|
|
de88b46ac1 | ||
|
|
9a090a0f91 | ||
|
|
8919abe4c4 | ||
|
|
748e9892da | ||
|
|
bda8366ada | ||
|
|
2a655f70a1 | ||
|
|
262203b644 | ||
|
|
49343f6fab | ||
|
|
5d4c977f64 | ||
|
|
76818632e0 | ||
|
|
d7bb88b53a | ||
|
|
0e156df634 | ||
|
|
a37405dbd8 | ||
|
|
80ee7cb931 | ||
|
|
fbf783450c | ||
|
|
04cf5a99d9 | ||
|
|
7c7d33a4b5 | ||
|
|
85d17fcaed | ||
|
|
218be0a884 | ||
|
|
6316220d36 | ||
|
|
5010123d5c | ||
|
|
fc20696c59 | ||
|
|
4381fb6b11 | ||
|
|
319f2c8dbc | ||
|
|
6cdbdfc5ff | ||
|
|
192af1f71c | ||
|
|
5640ec8934 | ||
|
|
b283128b6f | ||
|
|
35353963db | ||
|
|
1e46be30e4 | ||
|
|
767cb33632 | ||
|
|
b30c7b0596 | ||
|
|
c099ddb587 | ||
|
|
a22a217261 | ||
|
|
c91ebfa900 | ||
|
|
8934c4212a | ||
|
|
750fa1cf86 | ||
|
|
09fc3d9df8 | ||
|
|
eae4f80d2c | ||
|
|
39ef261a29 | ||
|
|
158f73fce2 | ||
|
|
3cb4fc6778 | ||
|
|
f8b41eb1b1 | ||
|
|
4147c002ec | ||
|
|
8eb9957db6 | ||
|
|
c5173de511 | ||
|
|
b9d439d202 | ||
|
|
b94af7c82f | ||
|
|
508411efb5 | ||
|
|
e5e1e250cd | ||
|
|
a938818047 | ||
|
|
27533da4f1 | ||
|
|
7e14816e85 | ||
|
|
49e11e797e | ||
|
|
1e064171da | ||
|
|
27be0b0d41 | ||
|
|
1c93cae6c5 | ||
|
|
cd4ee5fcb4 | ||
|
|
ac7b437cdb | ||
|
|
584a569a26 | ||
|
|
70aaf8ad81 | ||
|
|
6077b39ae5 | ||
|
|
66df974ce8 | ||
|
|
e368d999a1 | ||
|
|
2ef995772b | ||
|
|
afbd74d9f1 | ||
|
|
5ccd0c27fd | ||
|
|
4b2e6cb321 | ||
|
|
7726ae5182 | ||
|
|
75ab6b765f | ||
|
|
6db058c4af | ||
|
|
60607c734d | ||
|
|
2bf8d2a703 | ||
|
|
455581daa7 | ||
|
|
759f7060e3 | ||
|
|
2e0db686bd | ||
|
|
c17de8379b | ||
|
|
10783f221d | ||
|
|
b499a601b5 | ||
|
|
2b73ca3216 | ||
|
|
376f73762a | ||
|
|
ab205c20e6 | ||
|
|
ec3e4fc305 | ||
|
|
dbcb1a1192 | ||
|
|
70db992dd1 | ||
|
|
b2bcbcd866 | ||
|
|
a1937bf54c | ||
|
|
913806d047 | ||
|
|
320d23334f | ||
|
|
cd55cde10d | ||
|
|
21303afdf1 | ||
|
|
8e273cac72 | ||
|
|
3651fd75f7 | ||
|
|
689f0e9d52 | ||
|
|
838c4f1a2a | ||
|
|
7c7c136dc4 | ||
|
|
3a8b1b5add | ||
|
|
56a21bf34a | ||
|
|
39cd633013 | ||
|
|
3ffe66d4ef | ||
|
|
6990e4c7b8 | ||
|
|
1f30aac8a2 | ||
|
|
c0640f5e97 | ||
|
|
b4bac92547 | ||
|
|
4e88e07f76 | ||
|
|
cf1e6e7465 | ||
|
|
306df5eeac | ||
|
|
ab1e8f2497 | ||
|
|
35eefdfa1a | ||
|
|
4d4e725233 | ||
|
|
4cf4170b75 | ||
|
|
67f11acf5c | ||
|
|
a110f268c7 | ||
|
|
dae253025c | ||
|
|
9942cea529 | ||
|
|
27d570a089 | ||
|
|
6687aabbc2 | ||
|
|
8bfd56d051 | ||
|
|
15539105df | ||
|
|
f9c2bb19fe | ||
|
|
77c8751576 | ||
|
|
b4336c2e0a | ||
|
|
0e42c574ed | ||
|
|
98733147f5 | ||
|
|
b1c1a83db3 | ||
|
|
60d06387da | ||
|
|
e93d6a3401 | ||
|
|
82e7f58c4f | ||
|
|
3b21fa3258 | ||
|
|
c2642ca20c | ||
|
|
7b0e9cf792 | ||
|
|
3f5655fce5 | ||
|
|
86bc91ae56 | ||
|
|
2075788ffc |
No files matched your search
@@ -5,3 +5,4 @@
|
||||
**/*.pyc
|
||||
build/
|
||||
VERSION
|
||||
unit-tests.conf
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
|
||||
for file in "$DIR"/.jenkins.d/*; do
|
||||
[[ -f $file && -x $file ]] || continue
|
||||
echo "Run: $file"
|
||||
"$file"
|
||||
done
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
source "$JDIR"/util.sh
|
||||
|
||||
if has OSX $NODE_LABELS; then
|
||||
if has OSX-10.8 $NODE_LABELS; then
|
||||
EXTRA_FLAGS=--c++11
|
||||
fi
|
||||
|
||||
set -x
|
||||
brew update
|
||||
brew upgrade
|
||||
brew install boost pkg-config cryptopp $EXTRA_FLAGS
|
||||
brew cleanup
|
||||
fi
|
||||
|
||||
if has Ubuntu $NODE_LABELS; then
|
||||
BOOST_PKG=libboost-all-dev
|
||||
if has Ubuntu-12.04 $NODE_LABELS; then
|
||||
BOOST_PKG=libboost1.48-all-dev
|
||||
fi
|
||||
|
||||
set -x
|
||||
sudo apt-get update -qq -y
|
||||
sudo apt-get -qq -y install build-essential pkg-config $BOOST_PKG \
|
||||
libcrypto++-dev libsqlite3-dev libpcap-dev
|
||||
fi
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
set -x
|
||||
set -e
|
||||
|
||||
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
source "$JDIR"/util.sh
|
||||
|
||||
pushd ${CACHE_DIR:-/tmp} >/dev/null
|
||||
|
||||
INSTALLED_VERSION=$((cd ndn-cxx && git rev-parse HEAD) 2>/dev/null || echo NONE)
|
||||
|
||||
sudo rm -Rf ndn-cxx-latest
|
||||
|
||||
git clone --depth 1 git://github.com/named-data/ndn-cxx ndn-cxx-latest
|
||||
|
||||
LATEST_VERSION=$((cd ndn-cxx-latest && git rev-parse HEAD) 2>/dev/null || echo UNKNOWN)
|
||||
|
||||
if [[ $INSTALLED_VERSION != $LATEST_VERSION ]]; then
|
||||
sudo rm -Rf ndn-cxx
|
||||
mv ndn-cxx-latest ndn-cxx
|
||||
else
|
||||
sudo rm -Rf ndn-cxx-latest
|
||||
fi
|
||||
|
||||
sudo rm -Rf /usr/local/include/ndn-cxx
|
||||
sudo rm -f /usr/local/lib/libndn-cxx*
|
||||
sudo rm -f /usr/local/lib/pkgconfig/libndn-cxx*
|
||||
|
||||
pushd ndn-cxx >/dev/null
|
||||
|
||||
./waf configure -j1 --color=yes --enable-shared --disable-static --without-osx-keychain
|
||||
./waf -j1 --color=yes
|
||||
sudo ./waf install -j1 --color=yes
|
||||
|
||||
popd >/dev/null
|
||||
popd >/dev/null
|
||||
|
||||
if has Linux $NODE_LABELS; then
|
||||
sudo ldconfig
|
||||
elif has FreeBSD $NODE_LABELS; then
|
||||
sudo ldconfig -a
|
||||
fi
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
set -x
|
||||
set -e
|
||||
|
||||
git submodule init
|
||||
git submodule sync
|
||||
git submodule update
|
||||
|
||||
# Cleanup
|
||||
sudo ./waf -j1 --color=yes distclean
|
||||
|
||||
# Configure/build in optimized mode with tests and precompiled headers
|
||||
./waf -j1 --color=yes configure --with-tests
|
||||
./waf -j1 --color=yes build
|
||||
|
||||
# Cleanup
|
||||
sudo ./waf -j1 --color=yes distclean
|
||||
|
||||
# Configure/build in optimized mode without tests and with precompiled headers
|
||||
./waf -j1 --color=yes configure
|
||||
./waf -j1 --color=yes build
|
||||
|
||||
# Cleanup
|
||||
sudo ./waf -j1 --color=yes distclean
|
||||
|
||||
# Configure/build in debug mode
|
||||
if [[ "$JOB_NAME" == *"code-coverage" ]]; then
|
||||
COVERAGE="--with-coverage"
|
||||
fi
|
||||
./waf -j1 --color=yes configure --debug --with-tests --without-pch $COVERAGE
|
||||
./waf -j1 --color=yes build
|
||||
|
||||
# (tests will be run against debug version)
|
||||
|
||||
# Install
|
||||
sudo ./waf -j1 --color=yes install
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
set -x
|
||||
set -e
|
||||
|
||||
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
source "$JDIR"/util.sh
|
||||
|
||||
# Prepare environment
|
||||
rm -Rf ~/.ndnx ~/.ndn
|
||||
|
||||
if has OSX $NODE_LABELS; then
|
||||
security unlock-keychain -p "named-data"
|
||||
sudo chgrp admin /dev/bpf*
|
||||
sudo chmod g+rw /dev/bpf*
|
||||
fi
|
||||
|
||||
if has Linux $NODE_LABELS; then
|
||||
sudo setcap cap_net_raw,cap_net_admin=eip `pwd`/build/unit-tests-core || true
|
||||
sudo setcap cap_net_raw,cap_net_admin=eip `pwd`/build/unit-tests-daemon || true
|
||||
sudo setcap cap_net_raw,cap_net_admin=eip `pwd`/build/unit-tests-rib || true
|
||||
fi
|
||||
|
||||
ndnsec-keygen "/tmp/jenkins/$NODE_NAME" | ndnsec-install-cert -
|
||||
|
||||
# Run unit tests
|
||||
# Core
|
||||
if [[ -n $XUNIT ]]; then
|
||||
./build/unit-tests-core -l all -- --log_format2=XML --log_sink2=build/xunit-core-report.xml
|
||||
sudo ./build/unit-tests-core -t TestPrivilegeHelper -l all -- --log_format2=XML --log_sink2=build/xunit-core-sudo-report.xml
|
||||
|
||||
./build/unit-tests-daemon -l all -- --log_format2=XML --log_sink2=build/xunit-daemon-report.xml
|
||||
|
||||
./build/unit-tests-rib -l all -- --log_format2=XML --log_sink2=build/xunit-rib-report.xml
|
||||
else
|
||||
./build/unit-tests-core -l test_suite
|
||||
sudo ./build/unit-tests-core -t TestPrivilegeHelper -l test_suite
|
||||
|
||||
./build/unit-tests-daemon -l test_suite
|
||||
|
||||
./build/unit-tests-rib -l test_suite
|
||||
fi
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
set -x
|
||||
set -e
|
||||
|
||||
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
source "$JDIR"/util.sh
|
||||
|
||||
if [[ "$JOB_NAME" == *"code-coverage" ]]; then
|
||||
BASE="`pwd | sed -e 's|/|\\\/|g'`\\"
|
||||
(cd build && gcovr -x -f $BASE/core -f $BASE/daemon -f $BASE/rib -r ../ -o coverage.xml ./)
|
||||
fi
|
||||
@@ -0,0 +1,33 @@
|
||||
CONTINUOUS INTEGRATION SCRIPTS
|
||||
==============================
|
||||
|
||||
Environment Variables Used in Build Scripts
|
||||
-------------------------------------------
|
||||
|
||||
- `NODE_LABELS`: the variable defines a list of OS properties. The set values are used by the
|
||||
build scripts to select proper behavior for different OS.
|
||||
|
||||
The list should include at least `[OS_TYPE]`, `[DISTRO_TYPE]`, and `[DISTRO_VERSION]`.
|
||||
|
||||
Possible values for Linux OS:
|
||||
|
||||
* `[OS_TYPE]`: `Linux`
|
||||
* `[DISTRO_TYPE]`: `Ubuntu`
|
||||
* `[DISTRO_VERSION]`: `Ubuntu-12.04`, `Ubuntu-14.04`, `Ubuntu-15.04`
|
||||
|
||||
Possible values of OSX OS:
|
||||
|
||||
* `[OS_TYPE]`: `OSX`
|
||||
* `[DISTRO_TYPE]`: `OSX` (can be absent)
|
||||
* `[DISTRO_VERSION]`: `OSX-10.10`, `OSX-10.9`, `OSX-10.8`, `OSX-10.7`
|
||||
|
||||
- `JOB_NAME`: optional variable to define type of the job. Depending on the defined job type,
|
||||
the build scripts can perform different tasks.
|
||||
|
||||
Possible values:
|
||||
|
||||
* empty: default build process
|
||||
* `code-coverage` (Linux OS is assumed): build process with code coverage analysis
|
||||
|
||||
- `CACHE_DIR`: the variable defines a path to folder containing cached files from previous builds,
|
||||
e.g., a compiled version of ndn-cxx library. If not set, `/tmp` is used.
|
||||
@@ -0,0 +1,9 @@
|
||||
has() {
|
||||
local p=$1
|
||||
shift
|
||||
local x
|
||||
for x in "$@"; do
|
||||
[[ "${x}" == "${p}" ]] && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
+5
-33
@@ -1,4 +1,4 @@
|
||||
# For Ubuntu only
|
||||
sudo: true
|
||||
language: cpp
|
||||
os:
|
||||
- linux
|
||||
@@ -8,36 +8,8 @@ notifications:
|
||||
email:
|
||||
on_success: always
|
||||
on_failure: always
|
||||
before_install:
|
||||
- travis_retry sudo apt-get update
|
||||
- travis_retry sudo apt-get install -qq libssl-dev libpcap-dev libboost1.48-all-dev libcrypto++-dev libsqlite3-dev
|
||||
- travis_retry git clone --depth 1 git://github.com/named-data/ndn-cxx ndn-cxx
|
||||
- cd ndn-cxx
|
||||
- ./waf configure
|
||||
- ./waf -j1
|
||||
- sudo ./waf install
|
||||
- sudo ldconfig
|
||||
- cd ..
|
||||
- ndnsec-keygen /tmp/key | ndnsec-install-cert -
|
||||
script:
|
||||
- ./waf configure --with-tests
|
||||
- ./waf -j1
|
||||
- sudo ./waf install
|
||||
- ./build/unit-tests-core
|
||||
- ./build/unit-tests-daemon
|
||||
- ./build/unit-tests-rib
|
||||
# Tutorial for setting up notifications:
|
||||
# http://docs.travis-ci.com/user/notifications/
|
||||
# Here's a simple example for email notifications:
|
||||
#
|
||||
# notifications:
|
||||
# email:
|
||||
# recipients:
|
||||
# - one@example.com
|
||||
# - other@example.com
|
||||
# on_success: [always|never|change] # default: change
|
||||
# on_failure: [always|never|change] # default: always
|
||||
#
|
||||
# There are also other types of notifications available, including:
|
||||
# IRC, Campfire, Flowdock, HipChat, and Webhook.
|
||||
# For more infomation about notifications, please visit the link above.
|
||||
- if [[ $TRAVIS_OS_NAME == linux ]]; then export NODE_LABELS="Linux Ubuntu Ubuntu-12.04"; fi
|
||||
- if [[ $TRAVIS_OS_NAME == osx ]]; then export NODE_LABELS="OSX OSX-10.10"; fi
|
||||
- echo $NODE_LABELS
|
||||
- ./.jenkins
|
||||
@@ -8,13 +8,14 @@ from waflib import Configure
|
||||
|
||||
BOOST_ASIO_HAS_KQUEUE_CHECK = '''
|
||||
#include <boost/asio.hpp>
|
||||
#if defined(BOOST_ASIO_HAS_KQUEUE) and BOOST_VERSION >= 105600
|
||||
#error "Ethernet face support cannot be enabled on this platform"
|
||||
#if defined(BOOST_ASIO_HAS_KQUEUE) and BOOST_VERSION == 105600
|
||||
#error "Ethernet face support cannot be enabled on this platform with boost 1.56"
|
||||
#endif
|
||||
'''
|
||||
|
||||
@Configure.conf
|
||||
def check_asio_pcap_support(conf):
|
||||
# https://svn.boost.org/trac/boost/ticket/10367
|
||||
if conf.check_cxx(msg='Checking if Ethernet face support can be enabled',
|
||||
fragment=BOOST_ASIO_HAS_KQUEUE_CHECK,
|
||||
features='cxx', use='BOOST', mandatory=False):
|
||||
|
||||
+216
-76
@@ -30,15 +30,15 @@ When using this tool, the wscript will look like:
|
||||
|
||||
Options are generated, in order to specify the location of boost includes/libraries.
|
||||
The `check_boost` configuration function allows to specify the used boost libraries.
|
||||
It can also provide default arguments to the --boost-static and --boost-mt command-line arguments.
|
||||
It can also provide default arguments to the --boost-mt command-line arguments.
|
||||
Everything will be packaged together in a BOOST component that you can use.
|
||||
|
||||
When using MSVC, a lot of compilation flags need to match your BOOST build configuration:
|
||||
- you may have to add /EHsc to your CXXFLAGS or define boost::throw_exception if BOOST_NO_EXCEPTIONS is defined.
|
||||
Errors: C4530
|
||||
- boost libraries will try to be smart and use the (pretty but often not useful) auto-linking feature of MSVC
|
||||
So before calling `conf.check_boost` you might want to disabling by adding:
|
||||
conf.env.DEFINES_BOOST += ['BOOST_ALL_NO_LIB']
|
||||
So before calling `conf.check_boost` you might want to disabling by adding
|
||||
conf.env.DEFINES_BOOST += ['BOOST_ALL_NO_LIB']
|
||||
Errors:
|
||||
- boost might also be compiled with /MT, which links the runtime statically.
|
||||
If you have problems with redefined symbols,
|
||||
@@ -52,24 +52,55 @@ import sys
|
||||
import re
|
||||
from waflib import Utils, Logs, Errors
|
||||
from waflib.Configure import conf
|
||||
from waflib.TaskGen import feature, after_method
|
||||
|
||||
BOOST_LIBS = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib', '/usr/lib/x86_64-linux-gnu', '/usr/lib/i386-linux-gnu', '/usr/local/ndn/lib']
|
||||
BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include', '/usr/local/ndn/include']
|
||||
BOOST_LIBS = ['/usr/lib/x86_64-linux-gnu', '/usr/lib/i386-linux-gnu',
|
||||
'/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib']
|
||||
BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include']
|
||||
BOOST_VERSION_FILE = 'boost/version.hpp'
|
||||
BOOST_VERSION_CODE = '''
|
||||
#include <iostream>
|
||||
#include <boost/version.hpp>
|
||||
int main() { std::cout << BOOST_LIB_VERSION << ":" << BOOST_VERSION << std::endl; }
|
||||
'''
|
||||
BOOST_SYSTEM_CODE = '''
|
||||
|
||||
BOOST_ERROR_CODE = '''
|
||||
#include <boost/system/error_code.hpp>
|
||||
int main() { boost::system::error_code c; }
|
||||
'''
|
||||
|
||||
PTHREAD_CODE = '''
|
||||
#include <pthread.h>
|
||||
static void* f(void*) { return 0; }
|
||||
int main() {
|
||||
pthread_t th;
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_create(&th, &attr, &f, 0);
|
||||
pthread_join(th, 0);
|
||||
pthread_cleanup_push(0, 0);
|
||||
pthread_cleanup_pop(0);
|
||||
pthread_attr_destroy(&attr);
|
||||
}
|
||||
'''
|
||||
|
||||
BOOST_THREAD_CODE = '''
|
||||
#include <boost/thread.hpp>
|
||||
int main() { boost::thread t; }
|
||||
'''
|
||||
|
||||
BOOST_LOG_CODE = '''
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/log/utility/setup/console.hpp>
|
||||
#include <boost/log/utility/setup/common_attributes.hpp>
|
||||
int main() {
|
||||
using namespace boost::log;
|
||||
add_common_attributes();
|
||||
add_console_log(std::clog, keywords::format = "%Message%");
|
||||
BOOST_LOG_TRIVIAL(debug) << "log is working" << std::endl;
|
||||
}
|
||||
'''
|
||||
|
||||
# toolsets from {boost_dir}/tools/build/v2/tools/common.jam
|
||||
PLATFORM = Utils.unversioned_sys_platform()
|
||||
detect_intel = lambda env: (PLATFORM == 'win32') and 'iw' or 'il'
|
||||
@@ -101,34 +132,37 @@ BOOST_TOOLSETS = {
|
||||
|
||||
def options(opt):
|
||||
opt = opt.add_option_group('Boost Options')
|
||||
|
||||
opt.add_option('--boost-includes', type='string',
|
||||
default='', dest='boost_includes',
|
||||
help='''path to the directory where the boost includes are, e.g., /path/to/boost_1_55_0/stage/include''')
|
||||
help='''path to the directory where the boost includes are,
|
||||
e.g., /path/to/boost_1_55_0/stage/include''')
|
||||
opt.add_option('--boost-libs', type='string',
|
||||
default='', dest='boost_libs',
|
||||
help='''path to the directory where the boost libs are, e.g., /path/to/boost_1_55_0/stage/lib''')
|
||||
opt.add_option('--boost-static', action='store_true',
|
||||
default=False, dest='boost_static',
|
||||
help='link with static boost libraries (.lib/.a)')
|
||||
help='''path to the directory where the boost libs are,
|
||||
e.g., path/to/boost_1_55_0/stage/lib''')
|
||||
opt.add_option('--boost-mt', action='store_true',
|
||||
default=False, dest='boost_mt',
|
||||
help='select multi-threaded libraries')
|
||||
opt.add_option('--boost-abi', type='string', default='', dest='boost_abi',
|
||||
help='''select libraries with tags (dgsyp, d for debug), see doc Boost, Getting Started, chapter 6.1''')
|
||||
help='''select libraries with tags (gd for debug, static is automatically added),
|
||||
see doc Boost, Getting Started, chapter 6.1''')
|
||||
opt.add_option('--boost-linkage_autodetect', action="store_true", dest='boost_linkage_autodetect',
|
||||
help="auto-detect boost linkage options (don't get used to it / might break other stuff)")
|
||||
opt.add_option('--boost-toolset', type='string',
|
||||
default='', dest='boost_toolset',
|
||||
help='force a toolset e.g. msvc, vc90, gcc, mingw, mgw45 (default: auto)')
|
||||
help='force a toolset e.g. msvc, vc90, \
|
||||
gcc, mingw, mgw45 (default: auto)')
|
||||
py_version = '%d%d' % (sys.version_info[0], sys.version_info[1])
|
||||
opt.add_option('--boost-python', type='string',
|
||||
default=py_version, dest='boost_python',
|
||||
help='select the lib python with this version (default: %s)' % py_version)
|
||||
help='select the lib python with this version \
|
||||
(default: %s)' % py_version)
|
||||
|
||||
|
||||
@conf
|
||||
def __boost_get_version_file(self, d):
|
||||
if not d:
|
||||
return None
|
||||
dnode = self.root.find_dir(d)
|
||||
if dnode:
|
||||
return dnode.find_node(BOOST_VERSION_FILE)
|
||||
@@ -141,18 +175,15 @@ def boost_get_version(self, d):
|
||||
if node:
|
||||
try:
|
||||
txt = node.read()
|
||||
except (OSError, IOError):
|
||||
except EnvironmentError:
|
||||
Logs.error("Could not read the file %r" % node.abspath())
|
||||
else:
|
||||
re_but1 = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.+)"', re.M)
|
||||
m1 = re_but1.search(txt)
|
||||
|
||||
re_but2 = re.compile('^#define\\s+BOOST_VERSION\\s+(\\d+)', re.M)
|
||||
m2 = re_but2.search(txt)
|
||||
|
||||
if m1 and m2:
|
||||
return (m1.group(1), m2.group(1))
|
||||
|
||||
return self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[d], execute=True, define_ret=True).split(":")
|
||||
|
||||
@conf
|
||||
@@ -160,7 +191,7 @@ def boost_get_includes(self, *k, **kw):
|
||||
includes = k and k[0] or kw.get('includes', None)
|
||||
if includes and self.__boost_get_version_file(includes):
|
||||
return includes
|
||||
for d in Utils.to_list(self.environ.get('INCLUDE', '')) + BOOST_INCLUDES:
|
||||
for d in self.environ.get('INCLUDE', '').split(';') + BOOST_INCLUDES:
|
||||
if self.__boost_get_version_file(d):
|
||||
return d
|
||||
if includes:
|
||||
@@ -195,7 +226,9 @@ def __boost_get_libs_path(self, *k, **kw):
|
||||
path = self.root.find_dir(libs)
|
||||
files = path.ant_glob('*boost_*')
|
||||
if not libs or not files:
|
||||
for d in Utils.to_list(self.environ.get('LIB', [])) + BOOST_LIBS:
|
||||
for d in self.environ.get('LIB', '').split(';') + BOOST_LIBS:
|
||||
if not d:
|
||||
continue
|
||||
path = self.root.find_dir(d)
|
||||
if path:
|
||||
files = path.ant_glob('*boost_*')
|
||||
@@ -226,15 +259,10 @@ def boost_get_libs(self, *k, **kw):
|
||||
according to the parameters
|
||||
'''
|
||||
path, files = self.__boost_get_libs_path(**kw)
|
||||
t = []
|
||||
if kw.get('mt', False):
|
||||
t.append('mt')
|
||||
if kw.get('abi', None):
|
||||
t.append(kw['abi'])
|
||||
tags = t and '(-%s)+' % '-'.join(t) or ''
|
||||
files = sorted(files, key=lambda f: (len(f.name), f.name), reverse=True)
|
||||
toolset = self.boost_get_toolset(kw.get('toolset', ''))
|
||||
toolset_pat = '(-%s[0-9]{0,3})+' % toolset
|
||||
version = '(-%s)+' % self.env.BOOST_VERSION
|
||||
toolset_pat = '(-%s[0-9]{0,3})' % toolset
|
||||
version = '-%s' % self.env.BOOST_VERSION
|
||||
|
||||
def find_lib(re_lib, files):
|
||||
for file in files:
|
||||
@@ -248,28 +276,110 @@ def boost_get_libs(self, *k, **kw):
|
||||
name = name[3:]
|
||||
return name[:name.rfind('.')]
|
||||
|
||||
libs = []
|
||||
for lib in Utils.to_list(k and k[0] or kw.get('lib', None)):
|
||||
py = (lib == 'python') and '(-py%s)+' % kw['python'] or ''
|
||||
# Trying libraries, from most strict match to least one
|
||||
for pattern in ['boost_%s%s%s%s%s' % (lib, toolset_pat, tags, py, version),
|
||||
'boost_%s%s%s%s' % (lib, tags, py, version),
|
||||
'boost_%s%s%s' % (lib, tags, version),
|
||||
# Give up trying to find the right version
|
||||
'boost_%s%s%s%s' % (lib, toolset_pat, tags, py),
|
||||
'boost_%s%s%s' % (lib, tags, py),
|
||||
'boost_%s%s' % (lib, tags)]:
|
||||
self.to_log('Trying pattern %s' % pattern)
|
||||
file = find_lib(re.compile(pattern), files)
|
||||
if file:
|
||||
libs.append(format_lib_name(file.name))
|
||||
break
|
||||
else:
|
||||
self.end_msg('lib %s not found in %s' % (lib, path.abspath()))
|
||||
self.fatal('The configuration failed')
|
||||
def match_libs(lib_names, is_static):
|
||||
libs = []
|
||||
lib_names = Utils.to_list(lib_names)
|
||||
if not lib_names:
|
||||
return libs
|
||||
t = []
|
||||
if kw.get('mt', False):
|
||||
t.append('-mt')
|
||||
if kw.get('abi', None):
|
||||
t.append('%s%s' % (is_static and '-s' or '-', kw['abi']))
|
||||
elif is_static:
|
||||
t.append('-s')
|
||||
tags_pat = t and ''.join(t) or ''
|
||||
ext = is_static and self.env.cxxstlib_PATTERN or self.env.cxxshlib_PATTERN
|
||||
ext = ext.partition('%s')[2] # remove '%s' or 'lib%s' from PATTERN
|
||||
|
||||
return path.abspath(), libs
|
||||
for lib in lib_names:
|
||||
if lib == 'python':
|
||||
# for instance, with python='27',
|
||||
# accepts '-py27', '-py2', '27' and '2'
|
||||
# but will reject '-py3', '-py26', '26' and '3'
|
||||
tags = '({0})?((-py{2})|(-py{1}(?=[^0-9]))|({2})|({1}(?=[^0-9]))|(?=[^0-9])(?!-py))'.format(tags_pat, kw['python'][0], kw['python'])
|
||||
else:
|
||||
tags = tags_pat
|
||||
# Trying libraries, from most strict match to least one
|
||||
for pattern in ['boost_%s%s%s%s%s$' % (lib, toolset_pat, tags, version, ext),
|
||||
'boost_%s%s%s%s$' % (lib, tags, version, ext),
|
||||
# Give up trying to find the right version
|
||||
'boost_%s%s%s%s$' % (lib, toolset_pat, tags, ext),
|
||||
'boost_%s%s%s$' % (lib, tags, ext),
|
||||
'boost_%s%s$' % (lib, ext),
|
||||
'boost_%s' % lib]:
|
||||
self.to_log('Trying pattern %s' % pattern)
|
||||
file = find_lib(re.compile(pattern), files)
|
||||
if file:
|
||||
libs.append(format_lib_name(file.name))
|
||||
break
|
||||
else:
|
||||
self.end_msg('lib %s not found in %s' % (lib, path.abspath()))
|
||||
self.fatal('The configuration failed')
|
||||
return libs
|
||||
|
||||
return path.abspath(), match_libs(kw.get('lib', None), False), match_libs(kw.get('stlib', None), True)
|
||||
|
||||
@conf
|
||||
def _check_pthread_flag(self, *k, **kw):
|
||||
'''
|
||||
Computes which flags should be added to CXXFLAGS and LINKFLAGS to compile in multi-threading mode
|
||||
|
||||
Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3,
|
||||
boost/thread.hpp will trigger a #error if -pthread isn't used:
|
||||
boost/config/requires_threads.hpp:47:5: #error "Compiler threading support
|
||||
is not turned on. Please set the correct command line options for
|
||||
threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)"
|
||||
|
||||
Based on _BOOST_PTHREAD_FLAG(): https://github.com/tsuna/boost.m4/blob/master/build-aux/boost.m4
|
||||
'''
|
||||
|
||||
var = kw.get('uselib_store', 'BOOST')
|
||||
|
||||
self.start_msg('Checking the flags needed to use pthreads')
|
||||
|
||||
# The ordering *is* (sometimes) important. Some notes on the
|
||||
# individual items follow:
|
||||
# (none): in case threads are in libc; should be tried before -Kthread and
|
||||
# other compiler flags to prevent continual compiler warnings
|
||||
# -lpthreads: AIX (must check this before -lpthread)
|
||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||
# -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||
# -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads)
|
||||
# -pthreads: Solaris/GCC
|
||||
# -mthreads: MinGW32/GCC, Lynx/GCC
|
||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
||||
# doesn't hurt to check since this sometimes defines pthreads too;
|
||||
# also defines -D_REENTRANT)
|
||||
# ... -mt is also the pthreads flag for HP/aCC
|
||||
# -lpthread: GNU Linux, etc.
|
||||
# --thread-safe: KAI C++
|
||||
if Utils.unversioned_sys_platform() == "sunos":
|
||||
# On Solaris (at least, for some versions), libc contains stubbed
|
||||
# (non-functional) versions of the pthreads routines, so link-based
|
||||
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
|
||||
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
|
||||
# a function called by this macro, so we could check for that, but
|
||||
# who knows whether they'll stub that too in a future libc.) So,
|
||||
# we'll just look for -pthreads and -lpthread first:
|
||||
boost_pthread_flags = ["-pthreads", "-lpthread", "-mt", "-pthread"]
|
||||
else:
|
||||
boost_pthread_flags = ["", "-lpthreads", "-Kthread", "-kthread", "-llthread", "-pthread",
|
||||
"-pthreads", "-mthreads", "-lpthread", "--thread-safe", "-mt"]
|
||||
|
||||
for boost_pthread_flag in boost_pthread_flags:
|
||||
try:
|
||||
self.env.stash()
|
||||
self.env['CXXFLAGS_%s' % var] += [boost_pthread_flag]
|
||||
self.env['LINKFLAGS_%s' % var] += [boost_pthread_flag]
|
||||
self.check_cxx(code=PTHREAD_CODE, msg=None, use=var, execute=False)
|
||||
|
||||
self.end_msg(boost_pthread_flag)
|
||||
return
|
||||
except self.errors.ConfigurationError:
|
||||
self.env.revert()
|
||||
self.end_msg('None')
|
||||
|
||||
@conf
|
||||
def check_boost(self, *k, **kw):
|
||||
@@ -282,7 +392,10 @@ def check_boost(self, *k, **kw):
|
||||
if not self.env['CXX']:
|
||||
self.fatal('load a c++ compiler first, conf.load("compiler_cxx")')
|
||||
|
||||
params = {'lib': k and k[0] or kw.get('lib', None)}
|
||||
params = {
|
||||
'lib': k and k[0] or kw.get('lib', None),
|
||||
'stlib': kw.get('stlib', None)
|
||||
}
|
||||
for key, value in self.options.__dict__.items():
|
||||
if not key.startswith('boost_'):
|
||||
continue
|
||||
@@ -297,42 +410,53 @@ def check_boost(self, *k, **kw):
|
||||
self.env.BOOST_VERSION = versions[0]
|
||||
self.env.BOOST_VERSION_NUMBER = int(versions[1])
|
||||
self.end_msg("%d.%d.%d" % (int(versions[1]) / 100000,
|
||||
int(versions[1]) / 100 % 1000,
|
||||
int(versions[1]) % 100))
|
||||
int(versions[1]) / 100 % 1000,
|
||||
int(versions[1]) % 100))
|
||||
if Logs.verbose:
|
||||
Logs.pprint('CYAN', ' path : %s' % self.env['INCLUDES_%s' % var])
|
||||
|
||||
if not params['lib']:
|
||||
if not params['lib'] and not params['stlib']:
|
||||
return
|
||||
if 'static' in kw or 'static' in params:
|
||||
Logs.warn('boost: static parameter is deprecated, use stlib instead.')
|
||||
self.start_msg('Checking boost libs')
|
||||
suffix = params.get('static', None) and 'ST' or ''
|
||||
path, libs = self.boost_get_libs(**params)
|
||||
self.env['%sLIBPATH_%s' % (suffix, var)] = [path]
|
||||
self.env['%sLIB_%s' % (suffix, var)] = libs
|
||||
path, libs, stlibs = self.boost_get_libs(**params)
|
||||
self.env['LIBPATH_%s' % var] = [path]
|
||||
self.env['STLIBPATH_%s' % var] = [path]
|
||||
self.env['LIB_%s' % var] = libs
|
||||
self.env['STLIB_%s' % var] = stlibs
|
||||
self.end_msg('ok')
|
||||
if Logs.verbose:
|
||||
Logs.pprint('CYAN', ' path : %s' % path)
|
||||
Logs.pprint('CYAN', ' libs : %s' % libs)
|
||||
Logs.pprint('CYAN', ' shared libs : %s' % libs)
|
||||
Logs.pprint('CYAN', ' static libs : %s' % stlibs)
|
||||
|
||||
def has_shlib(lib):
|
||||
return params['lib'] and lib in params['lib']
|
||||
def has_stlib(lib):
|
||||
return params['stlib'] and lib in params['stlib']
|
||||
def has_lib(lib):
|
||||
return has_shlib(lib) or has_stlib(lib)
|
||||
if has_lib('thread'):
|
||||
# not inside try_link to make check visible in the output
|
||||
self._check_pthread_flag(k, kw)
|
||||
|
||||
def try_link():
|
||||
if 'system' in params['lib']:
|
||||
self.check_cxx(
|
||||
fragment=BOOST_SYSTEM_CODE,
|
||||
use=var,
|
||||
execute=False,
|
||||
)
|
||||
if 'thread' in params['lib']:
|
||||
self.check_cxx(
|
||||
fragment=BOOST_THREAD_CODE,
|
||||
use=var,
|
||||
execute=False,
|
||||
)
|
||||
if has_lib('system'):
|
||||
self.check_cxx(fragment=BOOST_ERROR_CODE, use=var, execute=False)
|
||||
if has_lib('thread'):
|
||||
self.check_cxx(fragment=BOOST_THREAD_CODE, use=var, execute=False)
|
||||
if has_lib('log'):
|
||||
if not has_lib('thread'):
|
||||
self.env['DEFINES_%s' % var] += ['BOOST_LOG_NO_THREADS']
|
||||
if has_shlib('log'):
|
||||
self.env['DEFINES_%s' % var] += ['BOOST_LOG_DYN_LINK']
|
||||
self.check_cxx(fragment=BOOST_LOG_CODE, use=var, execute=False)
|
||||
|
||||
if params.get('linkage_autodetect', False):
|
||||
self.start_msg("Attempting to detect boost linkage flags")
|
||||
toolset = self.boost_get_toolset(kw.get('toolset', ''))
|
||||
if toolset in ['vc']:
|
||||
if toolset in ('vc',):
|
||||
# disable auto-linking feature, causing error LNK1181
|
||||
# because the code wants to be linked against
|
||||
self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB']
|
||||
@@ -356,14 +480,14 @@ def check_boost(self, *k, **kw):
|
||||
try:
|
||||
try_link()
|
||||
self.end_msg("ok: winning cxxflags combination: %s" % (self.env["CXXFLAGS_%s" % var]))
|
||||
e = None
|
||||
exc = None
|
||||
break
|
||||
except Errors.ConfigurationError as exc:
|
||||
except Errors.ConfigurationError as e:
|
||||
self.env.revert()
|
||||
e = exc
|
||||
exc = e
|
||||
|
||||
if e is not None:
|
||||
self.end_msg("Could not auto-detect boost linking flags combination, you may report it to boost.py author", ex=e)
|
||||
if exc is not None:
|
||||
self.end_msg("Could not auto-detect boost linking flags combination, you may report it to boost.py author", ex=exc)
|
||||
self.fatal('The configuration failed')
|
||||
else:
|
||||
self.end_msg("Boost linkage flags auto-detection not implemented (needed ?) for this toolchain")
|
||||
@@ -376,3 +500,19 @@ def check_boost(self, *k, **kw):
|
||||
self.end_msg("Could not link against boost libraries using supplied options")
|
||||
self.fatal('The configuration failed')
|
||||
self.end_msg('ok')
|
||||
|
||||
|
||||
@feature('cxx')
|
||||
@after_method('apply_link')
|
||||
def install_boost(self):
|
||||
if install_boost.done or not Utils.is_win32 or not self.bld.cmd.startswith('install'):
|
||||
return
|
||||
install_boost.done = True
|
||||
inst_to = getattr(self, 'install_path', '${BINDIR}')
|
||||
for lib in self.env.LIB_BOOST:
|
||||
try:
|
||||
file = self.bld.find_file(self.env.cxxshlib_PATTERN % lib, self.env.LIBPATH_BOOST)
|
||||
self.bld.install_files(inst_to, self.bld.root.find_node(file))
|
||||
except:
|
||||
continue
|
||||
install_boost.done = False
|
||||
@@ -0,0 +1,63 @@
|
||||
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
from waflib.Configure import conf
|
||||
|
||||
OVERRIDE = '''
|
||||
class Base
|
||||
{
|
||||
virtual void
|
||||
f(int a);
|
||||
};
|
||||
|
||||
class Derived : public Base
|
||||
{
|
||||
virtual void
|
||||
f(int a) override;
|
||||
};
|
||||
'''
|
||||
|
||||
@conf
|
||||
def check_override(self):
|
||||
self.check_cxx(msg='Checking for override specifier',
|
||||
fragment=OVERRIDE,
|
||||
define_name='HAVE_CXX_OVERRIDE',
|
||||
features='cxx', mandatory=False)
|
||||
|
||||
FINAL = '''
|
||||
class Base
|
||||
{
|
||||
virtual void
|
||||
f(int a);
|
||||
};
|
||||
|
||||
class Derived : public Base
|
||||
{
|
||||
virtual void
|
||||
f(int a) final;
|
||||
};
|
||||
'''
|
||||
|
||||
@conf
|
||||
def check_final(self):
|
||||
self.check_cxx(msg='Checking for final specifier on method',
|
||||
fragment=FINAL,
|
||||
define_name='HAVE_CXX_FINAL',
|
||||
features='cxx', mandatory=False)
|
||||
|
||||
CLASS_FINAL = '''
|
||||
class A final
|
||||
{
|
||||
};
|
||||
'''
|
||||
|
||||
@conf
|
||||
def check_class_final(self):
|
||||
self.check_cxx(msg='Checking for final specifier on class',
|
||||
fragment=CLASS_FINAL,
|
||||
define_name='HAVE_CXX_CLASS_FINAL',
|
||||
features='cxx', mandatory=False)
|
||||
|
||||
def configure(conf):
|
||||
conf.check_override()
|
||||
conf.check_final()
|
||||
conf.check_class_final()
|
||||
@@ -1,10 +1,6 @@
|
||||
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
#
|
||||
# Copyright (c) 2014, Regents of the University of California
|
||||
#
|
||||
# GPL 3.0 license, see the COPYING.md file for more information
|
||||
|
||||
from waflib import TaskGen
|
||||
from waflib import TaskGen, Logs
|
||||
|
||||
def options(opt):
|
||||
opt.add_option('--with-coverage', action='store_true', default=False, dest='with_coverage',
|
||||
@@ -12,6 +8,8 @@ def options(opt):
|
||||
|
||||
def configure(conf):
|
||||
if conf.options.with_coverage:
|
||||
if not conf.options.debug:
|
||||
conf.fatal("Code coverage flags require debug mode compilation (add --debug)")
|
||||
conf.check_cxx(cxxflags=['-fprofile-arcs', '-ftest-coverage', '-fPIC'],
|
||||
linkflags=['-fprofile-arcs'], uselib_store='GCOV', mandatory=True)
|
||||
|
||||
|
||||
@@ -1,57 +1,58 @@
|
||||
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
#
|
||||
# Copyright (c) 2014, Regents of the University of California
|
||||
#
|
||||
# GPL 3.0 license, see the COPYING.md file for more information
|
||||
|
||||
from waflib import Logs, Configure
|
||||
from waflib import Logs, Configure, Utils
|
||||
|
||||
def options(opt):
|
||||
opt.add_option('--debug', '--with-debug', action='store_true', default=False, dest='debug',
|
||||
help='''Compile in debugging mode without all optimizations (-O0)''')
|
||||
opt.add_option('--with-c++11', action='store_true', default=False, dest='use_cxx11',
|
||||
help='''Enable C++11 mode (experimental, may not work)''')
|
||||
help='''Compile in debugging mode without optimizations (-O0 or -Og)''')
|
||||
|
||||
def configure(conf):
|
||||
areCustomCxxflagsPresent = (len(conf.env.CXXFLAGS) > 0)
|
||||
defaultFlags = []
|
||||
|
||||
if conf.options.use_cxx11:
|
||||
defaultFlags += ['-std=c++0x', '-std=c++11']
|
||||
cxx = conf.env['CXX_NAME'] # CXX_NAME represents generic name of the compiler
|
||||
if cxx == 'gcc':
|
||||
flags = GccFlags()
|
||||
elif cxx == 'clang':
|
||||
flags = ClangFlags()
|
||||
else:
|
||||
defaultFlags += ['-std=c++03', '-Wno-variadic-macros', '-Wno-c99-extensions']
|
||||
flags = CompilerFlags()
|
||||
Logs.warn('The code has not yet been tested with %s compiler' % cxx)
|
||||
|
||||
defaultFlags += ['-pedantic', '-Wall', '-Wno-long-long', '-Wno-unneeded-internal-declaration']
|
||||
areCustomCxxflagsPresent = (len(conf.env.CXXFLAGS) > 0)
|
||||
|
||||
# General flags are always applied (e.g., selecting C++11 mode)
|
||||
generalFlags = flags.getGeneralFlags(conf)
|
||||
conf.add_supported_cxxflags(generalFlags['CXXFLAGS'])
|
||||
conf.add_supported_linkflags(generalFlags['LINKFLAGS'])
|
||||
conf.env.DEFINES += generalFlags['DEFINES']
|
||||
|
||||
# Debug or optimized CXXFLAGS and LINKFLAGS are applied only if the
|
||||
# corresponding environment variables are not set.
|
||||
# DEFINES are always applied.
|
||||
if conf.options.debug:
|
||||
conf.define('_DEBUG', 1)
|
||||
defaultFlags += ['-O0',
|
||||
'-Og', # gcc >= 4.8
|
||||
'-g3',
|
||||
'-fcolor-diagnostics', # clang
|
||||
'-fdiagnostics-color', # gcc >= 4.9
|
||||
'-Werror',
|
||||
'-Wno-error=maybe-uninitialized', # Bug #1560
|
||||
]
|
||||
extraFlags = flags.getDebugFlags(conf)
|
||||
if areCustomCxxflagsPresent:
|
||||
missingFlags = [x for x in defaultFlags if x not in conf.env.CXXFLAGS]
|
||||
missingFlags = [x for x in extraFlags['CXXFLAGS'] if x not in conf.env.CXXFLAGS]
|
||||
if len(missingFlags) > 0:
|
||||
Logs.warn("Selected debug mode, but CXXFLAGS is set to a custom value '%s'"
|
||||
% " ".join(conf.env.CXXFLAGS))
|
||||
Logs.warn("Default flags '%s' are not activated" % " ".join(missingFlags))
|
||||
else:
|
||||
conf.add_supported_cxxflags(defaultFlags)
|
||||
else:
|
||||
defaultFlags += ['-O2', '-g']
|
||||
if not areCustomCxxflagsPresent:
|
||||
conf.add_supported_cxxflags(defaultFlags)
|
||||
extraFlags = flags.getOptimizedFlags(conf)
|
||||
|
||||
if not areCustomCxxflagsPresent:
|
||||
conf.add_supported_cxxflags(extraFlags['CXXFLAGS'])
|
||||
conf.add_supported_linkflags(extraFlags['LINKFLAGS'])
|
||||
|
||||
conf.env.DEFINES += extraFlags['DEFINES']
|
||||
|
||||
@Configure.conf
|
||||
def add_supported_cxxflags(self, cxxflags):
|
||||
"""
|
||||
Check which cxxflags are supported by compiler and add them to env.CXXFLAGS variable
|
||||
"""
|
||||
self.start_msg('Checking allowed flags for c++ compiler')
|
||||
if len(cxxflags) == 0:
|
||||
return
|
||||
|
||||
self.start_msg('Checking supported CXXFLAGS')
|
||||
|
||||
supportedFlags = []
|
||||
for flag in cxxflags:
|
||||
@@ -60,3 +61,123 @@ def add_supported_cxxflags(self, cxxflags):
|
||||
|
||||
self.end_msg(' '.join(supportedFlags))
|
||||
self.env.CXXFLAGS = supportedFlags + self.env.CXXFLAGS
|
||||
|
||||
@Configure.conf
|
||||
def add_supported_linkflags(self, linkflags):
|
||||
"""
|
||||
Check which linkflags are supported by compiler and add them to env.LINKFLAGS variable
|
||||
"""
|
||||
if len(linkflags) == 0:
|
||||
return
|
||||
|
||||
self.start_msg('Checking supported LINKFLAGS')
|
||||
|
||||
supportedFlags = []
|
||||
for flag in linkflags:
|
||||
if self.check_cxx(linkflags=['-Werror', flag], mandatory=False):
|
||||
supportedFlags += [flag]
|
||||
|
||||
self.end_msg(' '.join(supportedFlags))
|
||||
self.env.LINKFLAGS = supportedFlags + self.env.LINKFLAGS
|
||||
|
||||
|
||||
class CompilerFlags(object):
|
||||
def getGeneralFlags(self, conf):
|
||||
"""Get dict of CXXFLAGS, LINKFLAGS, and DEFINES that are always needed"""
|
||||
return {'CXXFLAGS': [], 'LINKFLAGS': [], 'DEFINES': []}
|
||||
|
||||
def getDebugFlags(self, conf):
|
||||
"""Get dict of CXXFLAGS, LINKFLAGS, and DEFINES that are needed only in debug mode"""
|
||||
return {'CXXFLAGS': [], 'LINKFLAGS': [], 'DEFINES': ['_DEBUG']}
|
||||
|
||||
def getOptimizedFlags(self, conf):
|
||||
"""Get dict of CXXFLAGS, LINKFLAGS, and DEFINES that are needed only in optimized mode"""
|
||||
return {'CXXFLAGS': [], 'LINKFLAGS': [], 'DEFINES': ['NDEBUG']}
|
||||
|
||||
class GccBasicFlags(CompilerFlags):
|
||||
"""
|
||||
This class defines basic flags that work for both gcc and clang compilers
|
||||
"""
|
||||
def getDebugFlags(self, conf):
|
||||
flags = super(GccBasicFlags, self).getDebugFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-O0',
|
||||
'-g3',
|
||||
'-pedantic',
|
||||
'-Wall',
|
||||
'-Wextra',
|
||||
'-Werror',
|
||||
'-Wno-unused-parameter',
|
||||
'-Wno-error=maybe-uninitialized', # Bug #1615
|
||||
]
|
||||
return flags
|
||||
|
||||
def getOptimizedFlags(self, conf):
|
||||
flags = super(GccBasicFlags, self).getOptimizedFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-O2',
|
||||
'-g',
|
||||
'-pedantic',
|
||||
'-Wall',
|
||||
'-Wextra',
|
||||
'-Wno-unused-parameter',
|
||||
]
|
||||
return flags
|
||||
|
||||
class GccFlags(GccBasicFlags):
|
||||
def getGeneralFlags(self, conf):
|
||||
flags = super(GccFlags, self).getGeneralFlags(conf)
|
||||
version = tuple(int(i) for i in conf.env['CC_VERSION'])
|
||||
if version < (4, 6, 0):
|
||||
conf.fatal('The version of gcc you are using (%s) is too old.\n' %
|
||||
'.'.join(conf.env['CC_VERSION']) +
|
||||
'The minimum supported gcc version is 4.6.0.')
|
||||
elif version < (4, 7, 0):
|
||||
flags['CXXFLAGS'] += ['-std=c++0x']
|
||||
else:
|
||||
flags['CXXFLAGS'] += ['-std=c++11']
|
||||
if version < (4, 8, 0):
|
||||
flags['DEFINES'] += ['_GLIBCXX_USE_NANOSLEEP'] # Bug #2499
|
||||
return flags
|
||||
|
||||
def getDebugFlags(self, conf):
|
||||
flags = super(GccFlags, self).getDebugFlags(conf)
|
||||
version = tuple(int(i) for i in conf.env['CC_VERSION'])
|
||||
if version < (5, 1, 0):
|
||||
flags['CXXFLAGS'] += ['-Wno-missing-field-initializers']
|
||||
flags['CXXFLAGS'] += ['-Og', # gcc >= 4.8
|
||||
'-fdiagnostics-color', # gcc >= 4.9
|
||||
]
|
||||
return flags
|
||||
|
||||
def getOptimizedFlags(self, conf):
|
||||
flags = super(GccFlags, self).getOptimizedFlags(conf)
|
||||
version = tuple(int(i) for i in conf.env['CC_VERSION'])
|
||||
if version < (5, 1, 0):
|
||||
flags['CXXFLAGS'] += ['-Wno-missing-field-initializers']
|
||||
flags['CXXFLAGS'] += ['-fdiagnostics-color'] # gcc >= 4.9
|
||||
return flags
|
||||
|
||||
class ClangFlags(GccBasicFlags):
|
||||
def getGeneralFlags(self, conf):
|
||||
flags = super(ClangFlags, self).getGeneralFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-std=c++11']
|
||||
if Utils.unversioned_sys_platform() == 'darwin':
|
||||
flags['CXXFLAGS'] += ['-stdlib=libc++']
|
||||
flags['LINKFLAGS'] += ['-stdlib=libc++']
|
||||
return flags
|
||||
|
||||
def getDebugFlags(self, conf):
|
||||
flags = super(ClangFlags, self).getDebugFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-fcolor-diagnostics',
|
||||
'-Wno-unused-local-typedef', # Bugs #2657 and #3209
|
||||
'-Wno-error=unneeded-internal-declaration', # Bug #1588
|
||||
'-Wno-error=deprecated-register',
|
||||
'-Wno-error=keyword-macro', # Bug #3235
|
||||
]
|
||||
return flags
|
||||
|
||||
def getOptimizedFlags(self, conf):
|
||||
flags = super(ClangFlags, self).getOptimizedFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-fcolor-diagnostics',
|
||||
'-Wno-unused-local-typedef', # Bugs #2657 and #3209
|
||||
]
|
||||
return flags
|
||||
@@ -85,7 +85,7 @@ class doxygen(Task.Task):
|
||||
|
||||
# Override with any parameters passed to the task generator
|
||||
if getattr(self.generator, 'pars', None):
|
||||
for k, v in self.generator.pars.iteritems():
|
||||
for k, v in self.generator.pars.items():
|
||||
self.pars[k] = v
|
||||
|
||||
self.doxy_inputs = getattr(self, 'doxy_inputs', [])
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
#
|
||||
# Copyright (c) 2014, Regents of the University of California
|
||||
#
|
||||
# GPL 3.0 license, see the COPYING.md file for more information
|
||||
|
||||
from waflib import Configure
|
||||
|
||||
IS_DEFAULT_CONSTRUCTIBLE_CHECK = '''
|
||||
#include <type_traits>
|
||||
static_assert(std::is_default_constructible<int>::value, "");
|
||||
'''
|
||||
|
||||
IS_MOVE_CONSTRUCTIBLE_CHECK = '''
|
||||
#include <type_traits>
|
||||
static_assert(std::is_move_constructible<int>::value, "");
|
||||
'''
|
||||
|
||||
def configure(conf):
|
||||
if conf.check_cxx(msg='Checking for std::is_default_constructible',
|
||||
fragment=IS_DEFAULT_CONSTRUCTIBLE_CHECK,
|
||||
features='cxx', mandatory=False):
|
||||
conf.define('HAVE_IS_DEFAULT_CONSTRUCTIBLE', 1)
|
||||
conf.env['HAVE_IS_DEFAULT_CONSTRUCTIBLE'] = True
|
||||
|
||||
if conf.check_cxx(msg='Checking for std::is_move_constructible',
|
||||
fragment=IS_MOVE_CONSTRUCTIBLE_CHECK,
|
||||
features='cxx', mandatory=False):
|
||||
conf.define('HAVE_IS_MOVE_CONSTRUCTIBLE', 1)
|
||||
conf.env['HAVE_IS_MOVE_CONSTRUCTIBLE'] = True
|
||||
@@ -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]
|
||||
|
||||
@@ -59,10 +59,10 @@ def checkWebsocket(self, **kw):
|
||||
|
||||
self.end_msg('.'.join(self.env['WEBSOCKET_VERSION']))
|
||||
|
||||
|
||||
self.env['INCLUDES_WEBSOCKET'] = websocketDir.parent.abspath()
|
||||
self.env['HAVE_WEBSOCKET'] = True
|
||||
self.define('HAVE_WEBSOCKET', 1)
|
||||
self.define('_WEBSOCKETPP_CPP11_STL_', 1)
|
||||
|
||||
except Errors.WafError as error:
|
||||
if isMandatory:
|
||||
@@ -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/65cc3765a892ee5928160ba478178e747233aa6c > 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")
|
||||
|
||||
+18
-1
@@ -18,7 +18,7 @@ volunteers.
|
||||
* Lixia Zhang <http://www.cs.ucla.edu/~lixia/>
|
||||
|
||||
|
||||
## All project authors and contributors and their affiliations:
|
||||
## Main project authors and their affiliations:
|
||||
|
||||
* University of California, Los Angeles
|
||||
|
||||
@@ -62,4 +62,21 @@ 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
|
||||
|
||||
The following is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS,
|
||||
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/>
|
||||
* Eric Newberry <http://ericnewberry.com>
|
||||
* Yukai Tu <tuyukai1994@gmail.com>
|
||||
* João Pereira <http://website.jpereira.co.uk>
|
||||
* Mathias Gibbens <gibmat@cs.arizona.edu>
|
||||
* Yanbiao Li <https://www.linkedin.com/pub/yanbiao-li/24/7a1/4ba>
|
||||
* Weiwei Liu <https://www.linkedin.com/in/weiweiliu10>
|
||||
* Spencer Lee <https://www.linkedin.com/in/spenlee>
|
||||
+30
@@ -1,3 +1,33 @@
|
||||
NFD is licensed under conditions of GNU General Public License version 3 or later.
|
||||
|
||||
NFD relies on third-party software and libraries, licensed under the following licenses:
|
||||
|
||||
- ndn-cxx library is licensed under conditions of
|
||||
[GNU Lesser General Public License version 3](https://github.com/named-data/ndn-cxx/blob/master/COPYING.md).
|
||||
|
||||
- Boost libraries licensed under conditions of
|
||||
[Boost Software License 1.0](http://www.boost.org/users/license.html)
|
||||
|
||||
- CryptoPP library is licensed under conditions of
|
||||
[Boost Software License 1.0](http://www.boost.org/users/license.html)
|
||||
|
||||
- SQLite is in [public domain](http://www.sqlite.org/copyright.html)
|
||||
|
||||
- WebSocket++ library licensed under conditions of
|
||||
[BSD license](https://github.com/zaphoyd/websocketpp/blob/ac5d7ea5af9734de965688b54a7860259887b537/COPYING)
|
||||
|
||||
- Libpcap library licensed under conditions of
|
||||
[a 3-clause BSD license](http://www.tcpdump.org/license.html).
|
||||
|
||||
- waf build system is licensed under conditions of
|
||||
[BSD license](https://github.com/named-data/ndn-cxx/blob/master/waf)
|
||||
|
||||
The GPL license is provided below in this file. For more information about these licenses, see
|
||||
http://www.gnu.org/licenses/
|
||||
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
==========================
|
||||
Version 3, 29 June 2007
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
NFD Installation Instructions
|
||||
=============================
|
||||
|
||||
See [`docs/install.rst`](https://github.com/named-data/NFD/blob/master/docs/INSTALL.rst)
|
||||
See [`docs/INSTALL.rst`](https://github.com/named-data/NFD/blob/master/docs/INSTALL.rst)
|
||||
for detailed NFD installation instructions.
|
||||
+8
-12
@@ -4,17 +4,15 @@ Notes for NFD developers
|
||||
Requirements
|
||||
------------
|
||||
|
||||
Contributions to NFD must be licensed under GPL 3.0 or compatible license. If you are
|
||||
choosing GPL 3.0, please use the following license boilerplate in all `.hpp` and `.cpp`
|
||||
files:
|
||||
|
||||
Include the following license boilerplate into all `.hpp` and `.cpp` files:
|
||||
|
||||
/* -*- 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) [Year(s)], [Copyright Holder(s)].
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -29,13 +27,11 @@ Include the following license boilerplate into all `.hpp` and `.cpp` files:
|
||||
*
|
||||
* 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/>.
|
||||
////// [optional part] //////
|
||||
*
|
||||
* \author Author's Name <email@domain>
|
||||
* \author Other Author's Name <another.email@domain>
|
||||
////// [end of optional part] //////
|
||||
*/
|
||||
|
||||
If you are affiliated to an NSF-supported NDN project institution, please use the [NDN Team License
|
||||
Boilerplate](http://redmine.named-data.net/projects/nfd/wiki/NDN_Team_License_Boilerplate_(NFD)).
|
||||
|
||||
Recommendations
|
||||
---------------
|
||||
|
||||
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
docs/release-notes-latest.rst
|
||||
@@ -0,0 +1,3 @@
|
||||
# Enable ndn-autoconfig to run in parallel with NFD. Disabled by default
|
||||
# enabled=true
|
||||
enabled=false
|
||||
+78
-24
@@ -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.
|
||||
@@ -40,15 +40,58 @@
|
||||
#define PROTECTED_WITH_TESTS_ELSE_PRIVATE private
|
||||
#endif
|
||||
|
||||
/** \def DECL_OVERRIDE
|
||||
* \brief expands to 'override' if compiler supports 'override' specifier,
|
||||
* otherwise expands to nothing
|
||||
*/
|
||||
#ifdef HAVE_CXX_OVERRIDE
|
||||
#define DECL_OVERRIDE override
|
||||
#else
|
||||
#define DECL_OVERRIDE
|
||||
#endif
|
||||
|
||||
/** \def DECL_FINAL
|
||||
* \brief expands to 'final' if compiler supports 'final' specifier on method,
|
||||
* otherwise expands to nothing
|
||||
*/
|
||||
#ifdef HAVE_CXX_FINAL
|
||||
#define DECL_FINAL final
|
||||
#else
|
||||
#define DECL_FINAL
|
||||
#endif
|
||||
|
||||
/** \def DECL_CLASS_FINAL
|
||||
* \brief expands to 'final' if compiler supports 'final' specifier on class,
|
||||
* otherwise expands to nothing
|
||||
*/
|
||||
#ifdef HAVE_CXX_CLASS_FINAL
|
||||
#define DECL_CLASS_FINAL final
|
||||
#else
|
||||
#define DECL_CLASS_FINAL
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <ndn-cxx/common.hpp>
|
||||
#include <ndn-cxx/interest.hpp>
|
||||
#include <ndn-cxx/data.hpp>
|
||||
#include <ndn-cxx/name.hpp>
|
||||
#include <ndn-cxx/encoding/block.hpp>
|
||||
#include <ndn-cxx/lp/nack.hpp>
|
||||
#include <ndn-cxx/util/backports.hpp>
|
||||
#include <ndn-cxx/util/face-uri.hpp>
|
||||
#include <ndn-cxx/util/signal.hpp>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
@@ -56,39 +99,50 @@
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
using std::size_t;
|
||||
|
||||
using boost::noncopyable;
|
||||
using boost::scoped_ptr;
|
||||
|
||||
using ndn::shared_ptr;
|
||||
using ndn::weak_ptr;
|
||||
using ndn::enable_shared_from_this;
|
||||
using ndn::make_shared;
|
||||
using ndn::static_pointer_cast;
|
||||
using ndn::dynamic_pointer_cast;
|
||||
using ndn::const_pointer_cast;
|
||||
using ndn::function;
|
||||
using ndn::bind;
|
||||
using ndn::ref;
|
||||
using ndn::cref;
|
||||
using std::shared_ptr;
|
||||
using std::unique_ptr;
|
||||
using std::weak_ptr;
|
||||
using std::make_shared;
|
||||
using ndn::make_unique;
|
||||
using std::enable_shared_from_this;
|
||||
|
||||
using std::static_pointer_cast;
|
||||
using std::dynamic_pointer_cast;
|
||||
using std::const_pointer_cast;
|
||||
|
||||
using std::function;
|
||||
using std::bind;
|
||||
using std::ref;
|
||||
using std::cref;
|
||||
|
||||
using ndn::to_string;
|
||||
|
||||
using ndn::Interest;
|
||||
using ndn::Data;
|
||||
using ndn::Name;
|
||||
using ndn::PartialName;
|
||||
using ndn::Exclude;
|
||||
using ndn::Link;
|
||||
using ndn::Block;
|
||||
using ndn::util::FaceUri;
|
||||
|
||||
namespace tlv {
|
||||
using namespace ndn::Tlv;
|
||||
}
|
||||
// Don't write "namespace tlv = ndn::tlv", because NFD can add other members into this namespace.
|
||||
using namespace ndn::tlv;
|
||||
} // namespace tlv
|
||||
|
||||
namespace lp = ndn::lp;
|
||||
namespace name = ndn::name;
|
||||
namespace time = ndn::time;
|
||||
namespace signal = ndn::util::signal;
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -0,0 +1,130 @@
|
||||
Starting NFD on Linux with systemd
|
||||
==================================
|
||||
|
||||
Newer versions of Ubuntu (starting with 15.04) and some other Linux distributions, including Debian
|
||||
use systemd to start system daemons, monitor their health, and restart them when they die.
|
||||
|
||||
Initial setup
|
||||
-------------
|
||||
|
||||
* Edit `nfd.service`, correcting the paths to the `nfd` executable, configuration, and
|
||||
``HOME`` directories.
|
||||
|
||||
* Copy the systemd config file for NFD to the proper directory
|
||||
|
||||
sudo cp nfd.service /etc/systemd/system
|
||||
|
||||
* Reload the systemd manager configuration
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
### Assumptions in the default scripts
|
||||
|
||||
* `nfd` is installed into `/usr/local/bin`
|
||||
* Configuraton file is `/usr/local/etc/ndn/nfd.conf`
|
||||
* `nfd` will be run as root
|
||||
* Log files will be written to `/usr/local/var/log/ndn` folder, which is owned by user `ndn`
|
||||
|
||||
### Creating users
|
||||
|
||||
If the `ndn` user and group do not exist, they need to be manually created.
|
||||
|
||||
# Create group `ndn`
|
||||
sudo addgroup --system ndn
|
||||
|
||||
# Create user `ndn`
|
||||
sudo adduser --system \
|
||||
--disabled-login \
|
||||
--ingroup ndn \
|
||||
--home /nonexistent \
|
||||
--gecos "NDN User" \
|
||||
--shell /bin/false \
|
||||
ndn
|
||||
|
||||
|
||||
### Creating folders
|
||||
|
||||
Folder `/usr/local/var/log/ndn` should be created and assigned proper user and group:
|
||||
|
||||
sudo mkdir -p /usr/local/var/log/ndn
|
||||
sudo chown -R ndn:ndn /usr/local/var/log/ndn
|
||||
|
||||
`HOME` directory for `nfd` should be created prior to starting. This is necessary to manage
|
||||
unique security credentials for the daemon.
|
||||
|
||||
# Create HOME and generate self-signed NDN certificate for nfd
|
||||
sudo sh -c ' \
|
||||
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
|
||||
|
||||
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 the security configuration of NFD is outside the scope of
|
||||
this document, at least the following change should be done in ``nfd.conf`` in the
|
||||
authorize section:
|
||||
|
||||
authorizations
|
||||
{
|
||||
authorize
|
||||
{
|
||||
certfile certs/localhost_daemons_nfd.ndncert
|
||||
privileges
|
||||
{
|
||||
faces
|
||||
fib
|
||||
strategy-choice
|
||||
}
|
||||
}
|
||||
|
||||
authorize
|
||||
{
|
||||
certfile any
|
||||
privileges
|
||||
{
|
||||
faces
|
||||
strategy-choice
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
While this configuration still allows the management of faces and updating strategy choice by
|
||||
anyone, only NFD's RIB Manager (i.e., NFD itself) is allowed to manage FIB.
|
||||
|
||||
As the final step to make this configuration work, nfd's self-signed certificate needs to
|
||||
be exported into the `localhost_daemons_nfd.ndncert` file:
|
||||
|
||||
sudo sh -c '\
|
||||
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 script, auto-start of the `nfd` daemon can be enabled with:
|
||||
|
||||
sudo systemctl enable nfd
|
||||
|
||||
To manually start it, use the following command:
|
||||
|
||||
sudo systemctl start nfd
|
||||
|
||||
Disable auto-start
|
||||
------------------
|
||||
|
||||
To stop the `nfd` daemon, use the following command:
|
||||
|
||||
sudo systemctl stop nfd
|
||||
|
||||
To permanently stop the `nfd` daemon and disable it from being automatically started on reboot,
|
||||
disable the service:
|
||||
|
||||
sudo systemctl disable nfd
|
||||
@@ -0,0 +1,42 @@
|
||||
# Copyright (c) 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: Eric Newberry <enewberry@email.arizona.edu>
|
||||
|
||||
[Unit]
|
||||
Description=NDN Forwarding Daemon
|
||||
Documentation=man:nfd man:nfdc man:nfd-status
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Environment=HOME=/usr/local/var/lib/ndn/nfd
|
||||
ExecStart=/usr/local/bin/nfd --config /usr/local/etc/ndn/nfd.conf
|
||||
ExecStartPost=/bin/sh -ec 'sleep 2; if [ -f /usr/local/etc/ndn/nfd-init.sh ]; then . /usr/local/etc/ndn/nfd-init.sh; fi'
|
||||
Restart=on-failure
|
||||
ProtectSystem=full
|
||||
PrivateTmp=yes
|
||||
PrivateDevices=yes
|
||||
ProtectHome=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
+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
|
||||
@@ -0,0 +1,58 @@
|
||||
/* -*- 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_CORE_ALGORITHM_HPP
|
||||
#define NFD_CORE_ALGORITHM_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
#include <boost/concept/requires.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
/** \brief finds the last element satisfying a predicate
|
||||
* \tparam It BidirectionalIterator
|
||||
* \tparam Pred UnaryPredicate
|
||||
*
|
||||
* \return Iterator to the last element satisfying the condition,
|
||||
* or \p last if no such element is found.
|
||||
*
|
||||
* Complexity: at most \p last-first invocations of \p p
|
||||
*/
|
||||
template<typename It, typename Pred>
|
||||
BOOST_CONCEPT_REQUIRES(
|
||||
((boost::BidirectionalIterator<It>))
|
||||
((boost::UnaryPredicate<Pred, typename std::iterator_traits<It>::value_type>)),
|
||||
(It)
|
||||
)
|
||||
find_last_if(It first, It last, Pred p)
|
||||
{
|
||||
std::reverse_iterator<It> firstR(first), lastR(last);
|
||||
auto found = std::find_if(lastR, firstR, p);
|
||||
return found == firstR ? last : std::prev(found.base());
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_CORE_ALGORITHM_HPP
|
||||
+51
-38
@@ -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/>.
|
||||
**/
|
||||
*/
|
||||
|
||||
#include "config-file.hpp"
|
||||
#include "logger.hpp"
|
||||
@@ -30,7 +31,10 @@
|
||||
|
||||
namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("ConfigFile");
|
||||
ConfigFile::ConfigFile(UnknownConfigSectionHandler unknownSectionCallback)
|
||||
: m_unknownSectionCallback(unknownSectionCallback)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ConfigFile::throwErrorOnUnknownSection(const std::string& filename,
|
||||
@@ -42,7 +46,7 @@ ConfigFile::throwErrorOnUnknownSection(const std::string& filename,
|
||||
msg += filename;
|
||||
msg += ": no module subscribed for section \"" + sectionName + "\"";
|
||||
|
||||
throw ConfigFile::Error(msg);
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error(msg));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -54,9 +58,21 @@ ConfigFile::ignoreUnknownSection(const std::string& filename,
|
||||
// do nothing
|
||||
}
|
||||
|
||||
ConfigFile::ConfigFile(UnknownConfigSectionHandler unknownSectionCallback)
|
||||
: m_unknownSectionCallback(unknownSectionCallback)
|
||||
bool
|
||||
ConfigFile::parseYesNo(const ConfigSection::value_type& option,
|
||||
const std::string& sectionName)
|
||||
{
|
||||
auto value = option.second.get_value<std::string>();
|
||||
|
||||
if (value == "yes") {
|
||||
return true;
|
||||
}
|
||||
else if (value == "no") {
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_THROW_EXCEPTION(Error("Invalid value \"" + value + "\" for option \"" +
|
||||
option.first + "\" in \"" + sectionName + "\" section"));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -75,7 +91,7 @@ ConfigFile::parse(const std::string& filename, bool isDryRun)
|
||||
{
|
||||
std::string msg = "Failed to read configuration file: ";
|
||||
msg += filename;
|
||||
throw Error(msg);
|
||||
BOOST_THROW_EXCEPTION(Error(msg));
|
||||
}
|
||||
parse(inputFile, isDryRun, filename);
|
||||
inputFile.close();
|
||||
@@ -88,7 +104,6 @@ ConfigFile::parse(const std::string& input, bool isDryRun, const std::string& fi
|
||||
parse(inputStream, isDryRun, filename);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ConfigFile::parse(std::istream& input, bool isDryRun, const std::string& filename)
|
||||
{
|
||||
@@ -102,42 +117,40 @@ ConfigFile::parse(std::istream& input, bool isDryRun, const std::string& filenam
|
||||
msg << "Failed to parse configuration file";
|
||||
msg << " " << filename;
|
||||
msg << " " << error.message() << " line " << error.line();
|
||||
throw Error(msg.str());
|
||||
BOOST_THROW_EXCEPTION(Error(msg.str()));
|
||||
}
|
||||
|
||||
process(isDryRun, filename);
|
||||
}
|
||||
|
||||
void
|
||||
ConfigFile::process(bool isDryRun, const std::string& filename)
|
||||
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) const
|
||||
{
|
||||
BOOST_ASSERT(!filename.empty());
|
||||
// NFD_LOG_DEBUG("processing..." << ((isDryRun)?("dry run"):("")));
|
||||
|
||||
if (m_global.begin() == m_global.end())
|
||||
{
|
||||
std::string msg = "Error processing configuration file: ";
|
||||
msg += filename;
|
||||
msg += " no data";
|
||||
throw Error(msg);
|
||||
if (m_global.begin() == m_global.end()) {
|
||||
std::string msg = "Error processing configuration file: ";
|
||||
msg += filename;
|
||||
msg += " no data";
|
||||
BOOST_THROW_EXCEPTION(Error(msg));
|
||||
}
|
||||
|
||||
for (const auto& i : m_global) {
|
||||
try {
|
||||
ConfigSectionHandler subscriber = m_subscriptions.at(i.first);
|
||||
subscriber(i.second, isDryRun, filename);
|
||||
}
|
||||
|
||||
for (ConfigSection::const_iterator i = m_global.begin(); i != m_global.end(); ++i)
|
||||
{
|
||||
const std::string& sectionName = i->first;
|
||||
const ConfigSection& section = i->second;
|
||||
|
||||
SubscriptionTable::iterator subscriberIt = m_subscriptions.find(sectionName);
|
||||
if (subscriberIt != m_subscriptions.end())
|
||||
{
|
||||
ConfigSectionHandler subscriber = subscriberIt->second;
|
||||
subscriber(section, isDryRun, filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_unknownSectionCallback(filename, sectionName, section, isDryRun);
|
||||
}
|
||||
catch (const std::out_of_range&) {
|
||||
m_unknownSectionCallback(filename, i.first, i.second, isDryRun);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+60
-21
@@ -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_CORE_CONFIG_FILE_HPP
|
||||
#define NFD_CORE_CONFIG_FILE_HPP
|
||||
@@ -47,7 +48,6 @@ typedef function<void(const std::string& /*filename*/,
|
||||
class ConfigFile : noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
class Error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
@@ -55,10 +55,10 @@ public:
|
||||
Error(const std::string& what)
|
||||
: std::runtime_error(what)
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
explicit
|
||||
ConfigFile(UnknownConfigSectionHandler unknownSectionCallback = throwErrorOnUnknownSection);
|
||||
|
||||
static void
|
||||
@@ -73,12 +73,32 @@ public:
|
||||
const ConfigSection& section,
|
||||
bool isDryRun);
|
||||
|
||||
/**
|
||||
* \brief parse a config option that can be either "yes" or "no"
|
||||
*
|
||||
* \return true if "yes", false if "no"
|
||||
* \throw Error the value is neither "yes" nor "no"
|
||||
*/
|
||||
static bool
|
||||
parseYesNo(const ConfigSection::value_type& option,
|
||||
const std::string& sectionName);
|
||||
|
||||
/**
|
||||
* \brief parse a numeric (integral or floating point) config option
|
||||
*
|
||||
* \return the numeric value of the parsed option
|
||||
* \throw Error the value cannot be converted to the specified type
|
||||
*/
|
||||
template <typename T>
|
||||
static typename std::enable_if<std::is_arithmetic<T>::value, T>::type
|
||||
parseNumber(const ConfigSection::value_type& option,
|
||||
const std::string& sectionName);
|
||||
|
||||
/// \brief setup notification of configuration file sections
|
||||
void
|
||||
addSectionHandler(const std::string& sectionName,
|
||||
ConfigSectionHandler subscriber);
|
||||
|
||||
|
||||
/**
|
||||
* \param filename file to parse
|
||||
* \param isDryRun true if performing a dry run of configuration, false otherwise
|
||||
@@ -91,7 +111,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,28 +121,47 @@ 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);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* \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
|
||||
process(bool isDryRun, const std::string& filename);
|
||||
parse(const ConfigSection& config, bool isDryRun, const std::string& filename);
|
||||
|
||||
private:
|
||||
void
|
||||
process(bool isDryRun, const std::string& filename) const;
|
||||
|
||||
private:
|
||||
UnknownConfigSectionHandler m_unknownSectionCallback;
|
||||
|
||||
typedef std::map<std::string, ConfigSectionHandler> SubscriptionTable;
|
||||
|
||||
SubscriptionTable m_subscriptions;
|
||||
|
||||
std::map<std::string, ConfigSectionHandler> m_subscriptions;
|
||||
ConfigSection m_global;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type
|
||||
ConfigFile::parseNumber(const ConfigSection::value_type& option,
|
||||
const std::string& sectionName)
|
||||
{
|
||||
auto value = option.second.get_value<std::string>();
|
||||
|
||||
try {
|
||||
return boost::lexical_cast<T>(value);
|
||||
}
|
||||
catch (const boost::bad_lexical_cast&) {
|
||||
BOOST_THROW_EXCEPTION(Error("Invalid value \"" + value + "\" for option \"" +
|
||||
option.first + "\" in \"" + sectionName + "\" section"));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
|
||||
#endif // NFD_CORE_CONFIG_FILE_HPP
|
||||
@@ -0,0 +1,141 @@
|
||||
/* -*- 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_CORE_COUNTER_HPP
|
||||
#define NFD_CORE_COUNTER_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
/** \brief represents a counter that encloses an integer value
|
||||
*
|
||||
* SimpleCounter is noncopyable, because increment should be called on the counter,
|
||||
* not a copy of it; it's implicitly convertible to an integral type to be observed
|
||||
*/
|
||||
class SimpleCounter
|
||||
{
|
||||
public:
|
||||
typedef uint64_t rep;
|
||||
|
||||
constexpr
|
||||
SimpleCounter()
|
||||
: m_value(0)
|
||||
{
|
||||
}
|
||||
|
||||
SimpleCounter(const SimpleCounter&) = delete;
|
||||
|
||||
SimpleCounter&
|
||||
operator=(const SimpleCounter&) = delete;
|
||||
|
||||
/** \brief observe the counter
|
||||
*/
|
||||
operator rep() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
/** \brief replace the counter value
|
||||
*/
|
||||
void
|
||||
set(rep value)
|
||||
{
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
protected:
|
||||
rep m_value;
|
||||
};
|
||||
|
||||
/** \brief represents a counter of number of packets
|
||||
*
|
||||
* \warning The counter value may wrap after exceeding the range of underlying integer type.
|
||||
*/
|
||||
class PacketCounter : public SimpleCounter
|
||||
{
|
||||
public:
|
||||
/** \brief increment the counter by one
|
||||
*/
|
||||
PacketCounter&
|
||||
operator++()
|
||||
{
|
||||
++m_value;
|
||||
return *this;
|
||||
}
|
||||
// postfix ++ operator is not provided because it's not needed
|
||||
};
|
||||
|
||||
/** \brief represents a counter of number of bytes
|
||||
*
|
||||
* \warning The counter value may wrap after exceeding the range of underlying integer type.
|
||||
*/
|
||||
class ByteCounter : public SimpleCounter
|
||||
{
|
||||
public:
|
||||
/** \brief increase the counter
|
||||
*/
|
||||
ByteCounter&
|
||||
operator+=(rep n)
|
||||
{
|
||||
m_value += n;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/** \brief provides a counter that observes the size of a table
|
||||
* \tparam T a type that provides a size() const member function
|
||||
*/
|
||||
template<typename T>
|
||||
class SizeCounter
|
||||
{
|
||||
public:
|
||||
typedef size_t rep;
|
||||
|
||||
constexpr
|
||||
SizeCounter(const T& table)
|
||||
: m_table(table)
|
||||
{
|
||||
}
|
||||
|
||||
SizeCounter(const SizeCounter&) = delete;
|
||||
|
||||
SizeCounter&
|
||||
operator=(const SizeCounter&) = delete;
|
||||
|
||||
/** \brief observe the counter
|
||||
*/
|
||||
operator rep() const
|
||||
{
|
||||
return m_table.size();
|
||||
}
|
||||
|
||||
private:
|
||||
const T& m_table;
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_CORE_COUNTER_HPP
|
||||
@@ -1,82 +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 "ethernet.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace nfd {
|
||||
namespace ethernet {
|
||||
|
||||
std::string
|
||||
Address::toString(char sep) const
|
||||
{
|
||||
char s[18]; // 12 digits + 5 separators + null terminator
|
||||
::snprintf(s, sizeof(s), "%02x%c%02x%c%02x%c%02x%c%02x%c%02x",
|
||||
elems[0], sep, elems[1], sep, elems[2], sep,
|
||||
elems[3], sep, elems[4], sep, elems[5]);
|
||||
return std::string(s);
|
||||
}
|
||||
|
||||
Address
|
||||
Address::fromString(const std::string& str)
|
||||
{
|
||||
unsigned short temp[ADDR_LEN];
|
||||
char sep[5][2]; // 5 * (1 separator char + 1 null terminator)
|
||||
int n = 0; // num of chars read from the input string
|
||||
|
||||
// ISO C++98 does not support the 'hh' type modifier
|
||||
/// \todo use SCNx8 (cinttypes) when we enable C++11
|
||||
int ret = ::sscanf(str.c_str(), "%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%n",
|
||||
&temp[0], &sep[0][0], &temp[1], &sep[1][0], &temp[2], &sep[2][0],
|
||||
&temp[3], &sep[3][0], &temp[4], &sep[4][0], &temp[5], &n);
|
||||
|
||||
if (ret < 11 || static_cast<size_t>(n) != str.length())
|
||||
return Address();
|
||||
|
||||
Address a;
|
||||
for (size_t i = 0; i < ADDR_LEN; ++i)
|
||||
{
|
||||
// check that all separators are actually the same char (: or -)
|
||||
if (i < 5 && sep[i][0] != sep[0][0])
|
||||
return Address();
|
||||
|
||||
// check that each value fits into a uint8_t
|
||||
if (temp[i] > 0xFF)
|
||||
return Address();
|
||||
|
||||
a[i] = static_cast<uint8_t>(temp[i]);
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& o, const Address& a)
|
||||
{
|
||||
return o << a.toString();
|
||||
}
|
||||
|
||||
} // namespace ethernet
|
||||
} // namespace nfd
|
||||
@@ -1,167 +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_CORE_ETHERNET_HPP
|
||||
#define NFD_CORE_ETHERNET_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#include <boost/array.hpp>
|
||||
|
||||
#define ETHERTYPE_NDN 0x8624
|
||||
|
||||
namespace nfd {
|
||||
namespace ethernet {
|
||||
|
||||
const size_t ADDR_LEN = 6; ///< Octets in one Ethernet address
|
||||
const size_t TYPE_LEN = 2; ///< Octets in Ethertype field
|
||||
const size_t HDR_LEN = 14; ///< Total octets in Ethernet header (without 802.1Q tag)
|
||||
const size_t TAG_LEN = 4; ///< Octets in 802.1Q tag (TPID + priority + VLAN)
|
||||
const size_t MIN_DATA_LEN = 46; ///< Min octets in Ethernet payload (assuming no 802.1Q tag)
|
||||
const size_t MAX_DATA_LEN = 1500; ///< Max octets in Ethernet payload
|
||||
const size_t CRC_LEN = 4; ///< Octets in Ethernet frame check sequence
|
||||
|
||||
|
||||
class Address : public boost::array<uint8_t, ADDR_LEN>
|
||||
{
|
||||
public:
|
||||
/// Constructs a null Ethernet address (00:00:00:00:00:00)
|
||||
Address();
|
||||
|
||||
/// Constructs a new Ethernet address with the given octets
|
||||
Address(uint8_t a1, uint8_t a2, uint8_t a3,
|
||||
uint8_t a4, uint8_t a5, uint8_t a6);
|
||||
|
||||
/// Constructs a new Ethernet address with the given octets
|
||||
explicit
|
||||
Address(const uint8_t octets[ADDR_LEN]);
|
||||
|
||||
/// Copy constructor
|
||||
Address(const Address& address);
|
||||
|
||||
/// True if this is a broadcast address (ff:ff:ff:ff:ff:ff)
|
||||
bool
|
||||
isBroadcast() const;
|
||||
|
||||
/// True if this is a multicast address
|
||||
bool
|
||||
isMulticast() const;
|
||||
|
||||
/// True if this is a null address (00:00:00:00:00:00)
|
||||
bool
|
||||
isNull() const;
|
||||
|
||||
/**
|
||||
* @brief Converts the address to a human-readable string
|
||||
*
|
||||
* @param sep A character used to visually separate the octets,
|
||||
* usually ':' (the default value) or '-'
|
||||
*/
|
||||
std::string
|
||||
toString(char sep = ':') const;
|
||||
|
||||
/**
|
||||
* @brief Creates an Address from a string containing an Ethernet address
|
||||
* in hexadecimal notation, with colons or hyphens as separators
|
||||
*
|
||||
* @param str The string to be parsed
|
||||
* @return Always an instance of Address, which will be null
|
||||
* if the parsing fails
|
||||
*/
|
||||
static Address
|
||||
fromString(const std::string& str);
|
||||
};
|
||||
|
||||
/// Returns the Ethernet broadcast address (ff:ff:ff:ff:ff:ff)
|
||||
inline Address
|
||||
getBroadcastAddress()
|
||||
{
|
||||
static Address bcast(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||
return bcast;
|
||||
}
|
||||
|
||||
/// Returns the default Ethernet multicast address for NDN
|
||||
inline Address
|
||||
getDefaultMulticastAddress()
|
||||
{
|
||||
static Address mcast(0x01, 0x00, 0x5E, 0x00, 0x17, 0xAA);
|
||||
return mcast;
|
||||
}
|
||||
|
||||
inline
|
||||
Address::Address()
|
||||
{
|
||||
assign(0);
|
||||
}
|
||||
|
||||
inline
|
||||
Address::Address(uint8_t a1, uint8_t a2, uint8_t a3, uint8_t a4, uint8_t a5, uint8_t a6)
|
||||
{
|
||||
elems[0] = a1;
|
||||
elems[1] = a2;
|
||||
elems[2] = a3;
|
||||
elems[3] = a4;
|
||||
elems[4] = a5;
|
||||
elems[5] = a6;
|
||||
}
|
||||
|
||||
inline
|
||||
Address::Address(const uint8_t octets[])
|
||||
{
|
||||
std::copy(octets, octets + size(), begin());
|
||||
}
|
||||
|
||||
inline
|
||||
Address::Address(const Address& address)
|
||||
{
|
||||
std::copy(address.begin(), address.end(), begin());
|
||||
}
|
||||
|
||||
inline bool
|
||||
Address::isBroadcast() const
|
||||
{
|
||||
return elems[0] == 0xFF && elems[1] == 0xFF && elems[2] == 0xFF &&
|
||||
elems[3] == 0xFF && elems[4] == 0xFF && elems[5] == 0xFF;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Address::isMulticast() const
|
||||
{
|
||||
return (elems[0] & 1) != 0;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Address::isNull() const
|
||||
{
|
||||
return elems[0] == 0x0 && elems[1] == 0x0 && elems[2] == 0x0 &&
|
||||
elems[3] == 0x0 && elems[4] == 0x0 && elems[5] == 0x0;
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& o, const Address& a);
|
||||
|
||||
} // namespace ethernet
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_FACE_ETHERNET_HPP
|
||||
@@ -1,356 +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,
|
||||
* 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_CORE_EVENT_EMITTER_HPP
|
||||
#define NFD_CORE_EVENT_EMITTER_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
struct empty
|
||||
{
|
||||
};
|
||||
|
||||
/** \class EventEmitter
|
||||
* \brief provides a lightweight event system
|
||||
*
|
||||
* To declare an event:
|
||||
* EventEmitter<TArgs> onEventName;
|
||||
* To subscribe to an event:
|
||||
* eventSource->onEventName += eventHandler;
|
||||
* Multiple functions can subscribe to the same event.
|
||||
* To trigger an event:
|
||||
* onEventName(args);
|
||||
* To clear event subscriptions:
|
||||
* onEventName.clear();
|
||||
*/
|
||||
|
||||
// four arguments
|
||||
template<typename T1 = empty, typename T2 = empty,
|
||||
typename T3 = empty, typename T4 = empty>
|
||||
class EventEmitter : noncopyable
|
||||
{
|
||||
public:
|
||||
/// represents a handler that can subscribe to the event
|
||||
typedef function<void(const T1&, const T2&,
|
||||
const T3&, const T4&)> Handler;
|
||||
|
||||
/// adds an subscription
|
||||
void
|
||||
operator+=(Handler handler);
|
||||
|
||||
/// returns true if there is no subscription,
|
||||
/// otherwise returns false
|
||||
bool
|
||||
isEmpty();
|
||||
|
||||
/// clears all subscriptions
|
||||
void
|
||||
clear();
|
||||
|
||||
/// triggers the event
|
||||
void
|
||||
operator()(const T1& a1, const T2& a2, const T3& a3, const T4& a4);
|
||||
|
||||
private:
|
||||
/// stores all subscribed handlers
|
||||
std::vector<Handler> m_handlers;
|
||||
};
|
||||
|
||||
// zero argument
|
||||
template<>
|
||||
class EventEmitter<empty, empty, empty, empty> : noncopyable
|
||||
{
|
||||
public:
|
||||
typedef function<void()> Handler;
|
||||
|
||||
void
|
||||
operator+=(Handler handler);
|
||||
|
||||
bool
|
||||
isEmpty();
|
||||
|
||||
void
|
||||
clear();
|
||||
|
||||
void
|
||||
operator()();
|
||||
|
||||
private:
|
||||
std::vector<Handler> m_handlers;
|
||||
};
|
||||
|
||||
|
||||
// one argument
|
||||
template<typename T1>
|
||||
class EventEmitter<T1, empty, empty, empty> : noncopyable
|
||||
{
|
||||
public:
|
||||
typedef function<void(const T1&)> Handler;
|
||||
|
||||
void
|
||||
operator+=(Handler handler);
|
||||
|
||||
bool
|
||||
isEmpty();
|
||||
|
||||
void
|
||||
clear();
|
||||
|
||||
void
|
||||
operator()(const T1& a1);
|
||||
|
||||
private:
|
||||
std::vector<Handler> m_handlers;
|
||||
};
|
||||
|
||||
|
||||
// two arguments
|
||||
template<typename T1, typename T2>
|
||||
class EventEmitter<T1, T2, empty, empty> : noncopyable
|
||||
{
|
||||
public:
|
||||
typedef function<void(const T1&, const T2&)> Handler;
|
||||
|
||||
void
|
||||
operator+=(Handler handler);
|
||||
|
||||
bool
|
||||
isEmpty();
|
||||
|
||||
void
|
||||
clear();
|
||||
|
||||
void
|
||||
operator()(const T1& a1, const T2& a2);
|
||||
|
||||
private:
|
||||
std::vector<Handler> m_handlers;
|
||||
};
|
||||
|
||||
|
||||
// three arguments
|
||||
template<typename T1, typename T2, typename T3>
|
||||
class EventEmitter<T1, T2, T3, empty> : noncopyable
|
||||
{
|
||||
public:
|
||||
typedef function<void(const T1&, const T2&, const T3&)> Handler;
|
||||
|
||||
void
|
||||
operator+=(Handler handler);
|
||||
|
||||
bool
|
||||
isEmpty();
|
||||
|
||||
void
|
||||
clear();
|
||||
|
||||
void
|
||||
operator()(const T1& a1, const T2& a2, const T3& a3);
|
||||
|
||||
private:
|
||||
std::vector<Handler> m_handlers;
|
||||
};
|
||||
|
||||
|
||||
// zero argument
|
||||
|
||||
inline void
|
||||
EventEmitter<empty, empty, empty, empty>::operator+=(Handler handler)
|
||||
{
|
||||
m_handlers.push_back(handler);
|
||||
}
|
||||
|
||||
inline bool
|
||||
EventEmitter<empty, empty, empty, empty>::isEmpty()
|
||||
{
|
||||
return m_handlers.empty();
|
||||
}
|
||||
|
||||
inline void
|
||||
EventEmitter<empty, empty, empty, empty>::clear()
|
||||
{
|
||||
return m_handlers.clear();
|
||||
}
|
||||
|
||||
inline void
|
||||
EventEmitter<empty, empty, empty, empty>::operator()()
|
||||
{
|
||||
std::vector<Handler>::iterator it;
|
||||
for (it = m_handlers.begin(); it != m_handlers.end(); ++it) {
|
||||
(*it)();
|
||||
if (m_handlers.empty()) // .clear has been called
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// one argument
|
||||
|
||||
template<typename T1>
|
||||
inline void
|
||||
EventEmitter<T1, empty, empty, empty>::operator+=(Handler handler)
|
||||
{
|
||||
m_handlers.push_back(handler);
|
||||
}
|
||||
|
||||
template<typename T1>
|
||||
inline bool
|
||||
EventEmitter<T1, empty, empty, empty>::isEmpty()
|
||||
{
|
||||
return m_handlers.empty();
|
||||
}
|
||||
|
||||
template<typename T1>
|
||||
inline void
|
||||
EventEmitter<T1, empty, empty, empty>::clear()
|
||||
{
|
||||
return m_handlers.clear();
|
||||
}
|
||||
|
||||
template<typename T1>
|
||||
inline void
|
||||
EventEmitter<T1, empty, empty, empty>::operator()(const T1& a1)
|
||||
{
|
||||
typename std::vector<Handler>::iterator it;
|
||||
for (it = m_handlers.begin(); it != m_handlers.end(); ++it) {
|
||||
(*it)(a1);
|
||||
if (m_handlers.empty()) // .clear has been called
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// two arguments
|
||||
|
||||
template<typename T1, typename T2>
|
||||
inline void
|
||||
EventEmitter<T1, T2, empty, empty>::operator+=(Handler handler)
|
||||
{
|
||||
m_handlers.push_back(handler);
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
inline bool
|
||||
EventEmitter<T1, T2, empty, empty>::isEmpty()
|
||||
{
|
||||
return m_handlers.empty();
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
inline void
|
||||
EventEmitter<T1, T2, empty, empty>::clear()
|
||||
{
|
||||
return m_handlers.clear();
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
inline void
|
||||
EventEmitter<T1, T2, empty, empty>::operator()
|
||||
(const T1& a1, const T2& a2)
|
||||
{
|
||||
typename std::vector<Handler>::iterator it;
|
||||
for (it = m_handlers.begin(); it != m_handlers.end(); ++it) {
|
||||
(*it)(a1, a2);
|
||||
if (m_handlers.empty()) // .clear has been called
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// three arguments
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
inline void
|
||||
EventEmitter<T1, T2, T3, empty>::operator+=(Handler handler)
|
||||
{
|
||||
m_handlers.push_back(handler);
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
inline bool
|
||||
EventEmitter<T1, T2, T3, empty>::isEmpty()
|
||||
{
|
||||
return m_handlers.empty();
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
inline void
|
||||
EventEmitter<T1, T2, T3, empty>::clear()
|
||||
{
|
||||
return m_handlers.clear();
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
inline void
|
||||
EventEmitter<T1, T2, T3, empty>::operator()
|
||||
(const T1& a1, const T2& a2, const T3& a3)
|
||||
{
|
||||
typename std::vector<Handler>::iterator it;
|
||||
for (it = m_handlers.begin(); it != m_handlers.end(); ++it) {
|
||||
(*it)(a1, a2, a3);
|
||||
if (m_handlers.empty()) // .clear has been called
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// four arguments
|
||||
|
||||
template<typename T1, typename T2, typename T3, typename T4>
|
||||
inline void
|
||||
EventEmitter<T1, T2, T3, T4>::operator+=(Handler handler)
|
||||
{
|
||||
m_handlers.push_back(handler);
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename T3, typename T4>
|
||||
inline bool
|
||||
EventEmitter<T1, T2, T3, T4>::isEmpty()
|
||||
{
|
||||
return m_handlers.empty();
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename T3, typename T4>
|
||||
inline void
|
||||
EventEmitter<T1, T2, T3, T4>::clear()
|
||||
{
|
||||
return m_handlers.clear();
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename T3, typename T4>
|
||||
inline void
|
||||
EventEmitter<T1, T2, T3, T4>::operator()
|
||||
(const T1& a1, const T2& a2, const T3& a3, const T4& a4)
|
||||
{
|
||||
typename std::vector<Handler>::iterator it;
|
||||
for (it = m_handlers.begin(); it != m_handlers.end(); ++it) {
|
||||
(*it)(a1, a2, a3, a4);
|
||||
if (m_handlers.empty()) // .clear has been called
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_CORE_EVENT_EMITTER_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/>.
|
||||
*/
|
||||
|
||||
#ifndef NFD_CORE_EXTENDED_ERROR_MESSAGE_HPP
|
||||
#define NFD_CORE_EXTENDED_ERROR_MESSAGE_HPP
|
||||
|
||||
#include <boost/exception/get_error_info.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
template<typename E>
|
||||
std::string
|
||||
getExtendedErrorMessage(const E& exception)
|
||||
{
|
||||
std::ostringstream errorMessage;
|
||||
errorMessage << exception.what();
|
||||
|
||||
const char* const* file = boost::get_error_info<boost::throw_file>(exception);
|
||||
const int* line = boost::get_error_info<boost::throw_line>(exception);
|
||||
const char* const* func = boost::get_error_info<boost::throw_function>(exception);
|
||||
if (file && line) {
|
||||
errorMessage << " [from " << *file << ":" << *line;
|
||||
if (func) {
|
||||
errorMessage << " in " << *func;
|
||||
}
|
||||
errorMessage << "]";
|
||||
}
|
||||
|
||||
return errorMessage.str();
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_CORE_EXTENDED_ERROR_MESSAGE_HPP
|
||||
@@ -1,163 +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,
|
||||
* 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 "face-uri.hpp"
|
||||
#include "core/logger.hpp"
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
#include "ethernet.hpp"
|
||||
#endif // HAVE_LIBPCAP
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
NFD_LOG_INIT("FaceUri");
|
||||
|
||||
namespace nfd {
|
||||
|
||||
FaceUri::FaceUri(const std::string& uri)
|
||||
{
|
||||
if (!parse(uri)) {
|
||||
throw Error("Malformed URI: " + uri);
|
||||
}
|
||||
}
|
||||
|
||||
FaceUri::FaceUri(const char* uri)
|
||||
{
|
||||
if (!parse(uri)) {
|
||||
throw Error("Malformed URI: " + std::string(uri));
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
FaceUri::parse(const std::string& uri)
|
||||
{
|
||||
m_scheme.clear();
|
||||
m_host.clear();
|
||||
m_isV6 = false;
|
||||
m_port.clear();
|
||||
m_path.clear();
|
||||
|
||||
static const boost::regex protocolExp("(\\w+\\d?)://([^/]*)(\\/[^?]*)?");
|
||||
boost::smatch protocolMatch;
|
||||
if (!boost::regex_match(uri, protocolMatch, protocolExp)) {
|
||||
return false;
|
||||
}
|
||||
m_scheme = protocolMatch[1];
|
||||
const std::string& authority = protocolMatch[2];
|
||||
m_path = protocolMatch[3];
|
||||
|
||||
// pattern for IPv6 address enclosed in [ ], with optional port number
|
||||
static const boost::regex v6Exp("^\\[([a-fA-F0-9:]+)\\](?:\\:(\\d+))?$");
|
||||
// pattern for Ethernet address in standard hex-digits-and-colons notation
|
||||
static const boost::regex etherExp("^\\[((?:[a-fA-F0-9]{1,2}\\:){5}(?:[a-fA-F0-9]{1,2}))\\]$");
|
||||
// pattern for IPv4-mapped IPv6 address, with optional port number
|
||||
static const boost::regex v4MappedV6Exp("^\\[::ffff:(\\d+(?:\\.\\d+){3})\\](?:\\:(\\d+))?$");
|
||||
// pattern for IPv4/hostname/fd/ifname, with optional port number
|
||||
static const boost::regex v4HostExp("^([^:]+)(?:\\:(\\d+))?$");
|
||||
|
||||
if (authority.empty()) {
|
||||
// UNIX, internal
|
||||
}
|
||||
else {
|
||||
boost::smatch match;
|
||||
m_isV6 = boost::regex_match(authority, match, v6Exp);
|
||||
if (m_isV6 ||
|
||||
boost::regex_match(authority, match, etherExp) ||
|
||||
boost::regex_match(authority, match, v4MappedV6Exp) ||
|
||||
boost::regex_match(authority, match, v4HostExp)) {
|
||||
m_host = match[1];
|
||||
m_port = match[2];
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
NFD_LOG_DEBUG("URI [" << uri << "] parsed into: " <<
|
||||
m_scheme << ", " << m_host << ", " << m_port << ", " << m_path);
|
||||
return true;
|
||||
}
|
||||
|
||||
FaceUri::FaceUri(const boost::asio::ip::tcp::endpoint& endpoint)
|
||||
{
|
||||
m_isV6 = endpoint.address().is_v6();
|
||||
m_scheme = m_isV6 ? "tcp6" : "tcp4";
|
||||
m_host = endpoint.address().to_string();
|
||||
m_port = boost::lexical_cast<std::string>(endpoint.port());
|
||||
}
|
||||
|
||||
FaceUri::FaceUri(const boost::asio::ip::udp::endpoint& endpoint)
|
||||
{
|
||||
m_isV6 = endpoint.address().is_v6();
|
||||
m_scheme = m_isV6 ? "udp6" : "udp4";
|
||||
m_host = endpoint.address().to_string();
|
||||
m_port = boost::lexical_cast<std::string>(endpoint.port());
|
||||
}
|
||||
|
||||
FaceUri::FaceUri(const boost::asio::ip::tcp::endpoint& endpoint, const std::string& scheme)
|
||||
: m_scheme(scheme)
|
||||
{
|
||||
m_isV6 = endpoint.address().is_v6();
|
||||
m_host = endpoint.address().to_string();
|
||||
m_port = boost::lexical_cast<std::string>(endpoint.port());
|
||||
}
|
||||
|
||||
#ifdef HAVE_UNIX_SOCKETS
|
||||
FaceUri::FaceUri(const boost::asio::local::stream_protocol::endpoint& endpoint)
|
||||
: m_isV6(false)
|
||||
{
|
||||
m_scheme = "unix";
|
||||
m_path = endpoint.path();
|
||||
}
|
||||
#endif // HAVE_UNIX_SOCKETS
|
||||
|
||||
FaceUri
|
||||
FaceUri::fromFd(int fd)
|
||||
{
|
||||
FaceUri uri;
|
||||
uri.m_scheme = "fd";
|
||||
uri.m_host = boost::lexical_cast<std::string>(fd);
|
||||
return uri;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
FaceUri::FaceUri(const ethernet::Address& address)
|
||||
: m_isV6(true)
|
||||
{
|
||||
m_scheme = "ether";
|
||||
m_host = address.toString();
|
||||
}
|
||||
#endif // HAVE_LIBPCAP
|
||||
|
||||
FaceUri
|
||||
FaceUri::fromDev(const std::string& ifname)
|
||||
{
|
||||
FaceUri uri;
|
||||
uri.m_scheme = "dev";
|
||||
uri.m_host = ifname;
|
||||
return uri;
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
@@ -1,219 +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_CORE_FACE_URI_H
|
||||
#define NFD_CORE_FACE_URI_H
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
namespace ethernet {
|
||||
class Address;
|
||||
} // namespace ethernet
|
||||
#endif // HAVE_LIBPCAP
|
||||
|
||||
/** \brief represents the underlying protocol and address used by a Face
|
||||
* \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#FaceUri
|
||||
*/
|
||||
class FaceUri
|
||||
{
|
||||
public:
|
||||
class Error : public std::invalid_argument
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
Error(const std::string& what)
|
||||
: std::invalid_argument(what)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
FaceUri();
|
||||
|
||||
/** \brief construct by parsing
|
||||
*
|
||||
* \param uri scheme://host[:port]/path
|
||||
* \throw FaceUri::Error if URI cannot be parsed
|
||||
*/
|
||||
explicit
|
||||
FaceUri(const std::string& uri);
|
||||
|
||||
// This overload is needed so that calls with string literal won't be
|
||||
// resolved to boost::asio::local::stream_protocol::endpoint overload.
|
||||
explicit
|
||||
FaceUri(const char* uri);
|
||||
|
||||
/// exception-safe parsing
|
||||
bool
|
||||
parse(const std::string& uri);
|
||||
|
||||
public: // scheme-specific construction
|
||||
/// construct tcp4 or tcp6 canonical FaceUri
|
||||
explicit
|
||||
FaceUri(const boost::asio::ip::tcp::endpoint& endpoint);
|
||||
|
||||
/// construct udp4 or udp6 canonical FaceUri
|
||||
explicit
|
||||
FaceUri(const boost::asio::ip::udp::endpoint& endpoint);
|
||||
|
||||
/// construct tcp canonical FaceUri with customized scheme
|
||||
FaceUri(const boost::asio::ip::tcp::endpoint& endpoint, const std::string& scheme);
|
||||
|
||||
#ifdef HAVE_UNIX_SOCKETS
|
||||
/// construct unix canonical FaceUri
|
||||
explicit
|
||||
FaceUri(const boost::asio::local::stream_protocol::endpoint& endpoint);
|
||||
#endif // HAVE_UNIX_SOCKETS
|
||||
|
||||
/// create fd FaceUri from file descriptor
|
||||
static FaceUri
|
||||
fromFd(int fd);
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
/// construct ether canonical FaceUri
|
||||
explicit
|
||||
FaceUri(const ethernet::Address& address);
|
||||
#endif // HAVE_LIBPCAP
|
||||
|
||||
/// create dev FaceUri from network device name
|
||||
static FaceUri
|
||||
fromDev(const std::string& ifname);
|
||||
|
||||
public: // getters
|
||||
/// get scheme (protocol)
|
||||
const std::string&
|
||||
getScheme() const;
|
||||
|
||||
/// get host (domain)
|
||||
const std::string&
|
||||
getHost() const;
|
||||
|
||||
/// get port
|
||||
const std::string&
|
||||
getPort() const;
|
||||
|
||||
/// get path
|
||||
const std::string&
|
||||
getPath() const;
|
||||
|
||||
/// write as a string
|
||||
std::string
|
||||
toString() const;
|
||||
|
||||
public: // EqualityComparable concept
|
||||
/// equality operator
|
||||
bool
|
||||
operator==(const FaceUri& rhs) const;
|
||||
|
||||
/// inequality operator
|
||||
bool
|
||||
operator!=(const FaceUri& rhs) const;
|
||||
|
||||
private:
|
||||
std::string m_scheme;
|
||||
std::string m_host;
|
||||
/// whether to add [] around host when writing string
|
||||
bool m_isV6;
|
||||
std::string m_port;
|
||||
std::string m_path;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const FaceUri& uri);
|
||||
};
|
||||
|
||||
inline
|
||||
FaceUri::FaceUri()
|
||||
: m_isV6(false)
|
||||
{
|
||||
}
|
||||
|
||||
inline const std::string&
|
||||
FaceUri::getScheme() const
|
||||
{
|
||||
return m_scheme;
|
||||
}
|
||||
|
||||
inline const std::string&
|
||||
FaceUri::getHost() const
|
||||
{
|
||||
return m_host;
|
||||
}
|
||||
|
||||
inline const std::string&
|
||||
FaceUri::getPort() const
|
||||
{
|
||||
return m_port;
|
||||
}
|
||||
|
||||
inline const std::string&
|
||||
FaceUri::getPath() const
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
inline std::string
|
||||
FaceUri::toString() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << *this;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
inline bool
|
||||
FaceUri::operator==(const FaceUri& rhs) const
|
||||
{
|
||||
return (m_scheme == rhs.m_scheme &&
|
||||
m_host == rhs.m_host &&
|
||||
m_isV6 == rhs.m_isV6 &&
|
||||
m_port == rhs.m_port &&
|
||||
m_path == rhs.m_path);
|
||||
}
|
||||
|
||||
inline bool
|
||||
FaceUri::operator!=(const FaceUri& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
inline std::ostream&
|
||||
operator<<(std::ostream& os, const FaceUri& uri)
|
||||
{
|
||||
os << uri.m_scheme << "://";
|
||||
if (uri.m_isV6) {
|
||||
os << "[" << uri.m_host << "]";
|
||||
}
|
||||
else {
|
||||
os << uri.m_host;
|
||||
}
|
||||
if (!uri.m_port.empty()) {
|
||||
os << ":" << uri.m_port;
|
||||
}
|
||||
os << uri.m_path;
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_CORE_FACE_URI_H
|
||||
+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) {
|
||||
}
|
||||
|
||||
BOOST_THROW_EXCEPTION(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()) {
|
||||
BOOST_THROW_EXCEPTION(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
|
||||
@@ -0,0 +1,74 @@
|
||||
/* -*- 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 "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>
|
||||
#include <type_traits>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
std::mutex g_logMutex;
|
||||
|
||||
Logger::Logger(const std::string& name, LogLevel level)
|
||||
: m_moduleName(name)
|
||||
, m_enabledLogLevel(level)
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
Logger::now()
|
||||
{
|
||||
using namespace ndn::time;
|
||||
|
||||
static const microseconds::rep ONE_SECOND = 1000000;
|
||||
microseconds::rep microsecondsSinceEpoch = duration_cast<microseconds>(
|
||||
system_clock::now().time_since_epoch()).count();
|
||||
|
||||
// 10 (whole seconds) + '.' + 6 (fraction) + '\0'
|
||||
static char buffer[10 + 1 + 6 + 1];
|
||||
BOOST_ASSERT_MSG(microsecondsSinceEpoch / ONE_SECOND <= 9999999999L,
|
||||
"whole seconds cannot fit in 10 characters");
|
||||
|
||||
static_assert(std::is_same<microseconds::rep, int_least64_t>::value,
|
||||
"PRIdLEAST64 is incompatible with microseconds::rep");
|
||||
// - std::snprintf not found in some environments
|
||||
// http://redmine.named-data.net/issues/2299 for more information
|
||||
snprintf(buffer, sizeof(buffer), "%" PRIdLEAST64 ".%06" PRIdLEAST64,
|
||||
microsecondsSinceEpoch / ONE_SECOND,
|
||||
microsecondsSinceEpoch % ONE_SECOND);
|
||||
|
||||
// It's okay to return a statically allocated buffer, because Logger::now() is invoked
|
||||
// only once per log macro.
|
||||
return buffer;
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
+47
-68
@@ -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,47 +21,49 @@
|
||||
*
|
||||
* 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_HPP
|
||||
#define NFD_CORE_LOGGER_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
#include <ndn-cxx/util/time.hpp>
|
||||
|
||||
/// \todo use when we enable C++11 (see todo in now())
|
||||
// #include <cinttypes>
|
||||
#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
|
||||
};
|
||||
|
||||
/** \brief provides logging for a module
|
||||
* \note This type is internal. Logger should be accessed through NFD_LOG_* macros.
|
||||
* \note This type is copyable because logger can be declared as a field of
|
||||
* (usually template) classes, and shouldn't prevent those classes to be copyable.
|
||||
*/
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
|
||||
Logger(const std::string& name, LogLevel level)
|
||||
: m_moduleName(name)
|
||||
, m_enabledLogLevel(level)
|
||||
{
|
||||
}
|
||||
Logger(const std::string& name, LogLevel level);
|
||||
|
||||
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
|
||||
@@ -81,29 +84,12 @@ public:
|
||||
m_moduleName = name;
|
||||
}
|
||||
|
||||
/// \brief return a string representation of time since epoch: seconds.microseconds
|
||||
static std::string
|
||||
now()
|
||||
{
|
||||
using namespace ndn::time;
|
||||
|
||||
static const microseconds::rep ONE_SECOND = 1000000;
|
||||
microseconds::rep microseconds_since_epoch =
|
||||
duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
|
||||
|
||||
// 10 (whole seconds) + '.' + 6 (fraction) + 1 (\0)
|
||||
char buffer[10 + 1 + 6 + 1];
|
||||
::snprintf(buffer, sizeof(buffer), "%lld.%06lld",
|
||||
static_cast<long long int>(microseconds_since_epoch / ONE_SECOND),
|
||||
static_cast<long long int>(microseconds_since_epoch % ONE_SECOND));
|
||||
|
||||
/// \todo use this version when we enable C++11 to avoid casting
|
||||
// ::snprintf(buffer, sizeof(buffer), "%" PRIdLEAST64 ".%06" PRIdLEAST64,
|
||||
// microseconds_since_epoch / ONE_SECOND,
|
||||
// microseconds_since_epoch % ONE_SECOND);
|
||||
|
||||
return std::string(buffer);
|
||||
}
|
||||
/** \return string representation of time since epoch: seconds.microseconds
|
||||
* \warning Return value is in a statically allocated buffer,
|
||||
* which subsequent calls will overwrite.
|
||||
*/
|
||||
static const char*
|
||||
now();
|
||||
|
||||
private:
|
||||
std::string m_moduleName;
|
||||
@@ -144,33 +130,26 @@ 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, expression) \
|
||||
do { \
|
||||
if (g_logger.isEnabled(::nfd::LOG_##level)) \
|
||||
std::clog << ::nfd::Logger::now() << " "#level": " \
|
||||
<< "[" << g_logger << "] " << expression << "\n"; \
|
||||
#define NFD_LOG(level, msg, expression) \
|
||||
do { \
|
||||
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, expression)
|
||||
#define NFD_LOG_DEBUG(expression) NFD_LOG(DEBUG, expression)
|
||||
#define NFD_LOG_INFO(expression) NFD_LOG(INFO, expression)
|
||||
#define NFD_LOG_ERROR(expression) NFD_LOG(ERROR, expression)
|
||||
#define NFD_LOG_TRACE(expression) NFD_LOG(TRACE, TRACE, expression)
|
||||
#define NFD_LOG_DEBUG(expression) NFD_LOG(DEBUG, DEBUG, expression)
|
||||
#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) NFD_LOG(FATAL, FATAL, expression)
|
||||
|
||||
// specialize WARN because the message is "WARNING" instead of "WARN"
|
||||
#define NFD_LOG_WARN(expression) \
|
||||
do { \
|
||||
if (g_logger.isEnabled(::nfd::LOG_WARN)) \
|
||||
std::clog << ::nfd::Logger::now() << " WARNING: " \
|
||||
<< "[" << g_logger << "] " << expression << "\n"; \
|
||||
} while (false)
|
||||
} // namespace nfd
|
||||
|
||||
#define NFD_LOG_FATAL(expression) \
|
||||
do { \
|
||||
std::clog << ::nfd::Logger::now() << " FATAL: " \
|
||||
<< "[" << g_logger << "] " << expression << "\n"; \
|
||||
} while (false)
|
||||
#endif // HAVE_CUSTOM_LOGGER
|
||||
|
||||
} //namespace nfd
|
||||
|
||||
#endif
|
||||
#endif // NFD_CORE_LOGGER_HPP
|
||||
@@ -1,87 +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_CORE_MAP_VALUE_ITERATOR_H
|
||||
#define NFD_CORE_MAP_VALUE_ITERATOR_H
|
||||
|
||||
#include "common.hpp"
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
/** \class MapValueIterator
|
||||
* \brief ForwardIterator to iterator over map values
|
||||
*/
|
||||
template<typename Map>
|
||||
class MapValueIterator
|
||||
: public boost::transform_iterator<
|
||||
function<const typename Map::mapped_type&(const typename Map::value_type&)>,
|
||||
typename Map::const_iterator>
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
MapValueIterator(typename Map::const_iterator it)
|
||||
: boost::transform_iterator<
|
||||
function<const typename Map::mapped_type&(const typename Map::value_type&)>,
|
||||
typename Map::const_iterator>(it, &takeSecond)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
static const typename Map::mapped_type&
|
||||
takeSecond(const typename Map::value_type& pair)
|
||||
{
|
||||
return pair.second;
|
||||
}
|
||||
};
|
||||
|
||||
/** \class MapValueReverseIterator
|
||||
* \brief ReverseIterator to iterator over map values
|
||||
*/
|
||||
template<typename Map>
|
||||
class MapValueReverseIterator
|
||||
: public boost::transform_iterator<
|
||||
function<const typename Map::mapped_type&(const typename Map::value_type&)>,
|
||||
typename Map::const_reverse_iterator>
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
MapValueReverseIterator(typename Map::const_reverse_iterator it)
|
||||
: boost::transform_iterator<
|
||||
function<const typename Map::mapped_type&(const typename Map::value_type&)>,
|
||||
typename Map::const_reverse_iterator>(it, &takeSecond)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
static const typename Map::mapped_type&
|
||||
takeSecond(const typename Map::value_type& pair)
|
||||
{
|
||||
return pair.second;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_CORE_MAP_VALUE_ITERATOR_H
|
||||
+136
-90
@@ -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,120 +21,165 @@
|
||||
*
|
||||
* 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 "network-interface.hpp"
|
||||
#include "core/logger.hpp"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
#include <ifaddrs.h> // for getifaddrs()
|
||||
|
||||
#include <arpa/inet.h> // for inet_ntop()
|
||||
#include <netinet/in.h> // for struct sockaddr_in{,6}
|
||||
#include <ifaddrs.h> // for getifaddrs()
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <net/if_arp.h> // for ARPHRD_* constants
|
||||
#include <netpacket/packet.h> // for struct sockaddr_ll
|
||||
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
||||
#include <net/if_dl.h> // for struct sockaddr_dl
|
||||
#else
|
||||
#error Platform not supported
|
||||
#include <net/if_types.h> // for IFT_* constants
|
||||
#endif
|
||||
|
||||
#endif // HAVE_IFADDRS_H
|
||||
|
||||
|
||||
NFD_LOG_INIT("NetworkInterfaceInfo");
|
||||
|
||||
namespace nfd {
|
||||
|
||||
std::list< shared_ptr<NetworkInterfaceInfo> >
|
||||
static_assert(std::is_standard_layout<NetworkInterfaceInfo>::value,
|
||||
"NetworkInterfaceInfo must be a standard layout type");
|
||||
#ifdef HAVE_IS_DEFAULT_CONSTRUCTIBLE
|
||||
static_assert(std::is_default_constructible<NetworkInterfaceInfo>::value,
|
||||
"NetworkInterfaceInfo must provide a default constructor");
|
||||
#endif
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
static shared_ptr<std::vector<NetworkInterfaceInfo>> s_debugNetworkInterfaces = nullptr;
|
||||
|
||||
void
|
||||
setDebugNetworkInterfaces(shared_ptr<std::vector<NetworkInterfaceInfo>> interfaces)
|
||||
{
|
||||
s_debugNetworkInterfaces = interfaces;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<NetworkInterfaceInfo>
|
||||
listNetworkInterfaces()
|
||||
{
|
||||
typedef std::map< std::string, shared_ptr<NetworkInterfaceInfo> > InterfacesMap;
|
||||
InterfacesMap ifmap;
|
||||
|
||||
ifaddrs* ifa_list;
|
||||
if (::getifaddrs(&ifa_list) < 0)
|
||||
throw std::runtime_error("getifaddrs() failed");
|
||||
|
||||
for (ifaddrs* ifa = ifa_list; ifa != 0; ifa = ifa->ifa_next)
|
||||
{
|
||||
shared_ptr<NetworkInterfaceInfo> netif;
|
||||
std::string ifname(ifa->ifa_name);
|
||||
InterfacesMap::iterator i = ifmap.find(ifname);
|
||||
if (i == ifmap.end())
|
||||
{
|
||||
netif = make_shared<NetworkInterfaceInfo>();
|
||||
netif->name = ifname;
|
||||
netif->flags = ifa->ifa_flags;
|
||||
ifmap[ifname] = netif;
|
||||
}
|
||||
else
|
||||
{
|
||||
netif = i->second;
|
||||
}
|
||||
|
||||
if (!ifa->ifa_addr)
|
||||
continue;
|
||||
|
||||
switch (ifa->ifa_addr->sa_family)
|
||||
{
|
||||
case AF_INET: {
|
||||
const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_addr);
|
||||
char address[INET_ADDRSTRLEN];
|
||||
if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address)))
|
||||
netif->ipv4Addresses.push_back(boost::asio::ip::address_v4::from_string(address));
|
||||
else
|
||||
NFD_LOG_WARN("inet_ntop() failed on " << ifname);
|
||||
}
|
||||
break;
|
||||
case AF_INET6: {
|
||||
const sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(ifa->ifa_addr);
|
||||
char address[INET6_ADDRSTRLEN];
|
||||
if (::inet_ntop(AF_INET6, &sin6->sin6_addr, address, sizeof(address)))
|
||||
netif->ipv6Addresses.push_back(boost::asio::ip::address_v6::from_string(address));
|
||||
else
|
||||
NFD_LOG_WARN("inet_ntop() failed on " << ifname);
|
||||
}
|
||||
break;
|
||||
#if defined(__linux__)
|
||||
case AF_PACKET: {
|
||||
const sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(ifa->ifa_addr);
|
||||
netif->index = sll->sll_ifindex;
|
||||
if (sll->sll_hatype == ARPHRD_ETHER && sll->sll_halen == ethernet::ADDR_LEN)
|
||||
netif->etherAddress = ethernet::Address(sll->sll_addr);
|
||||
else if (sll->sll_hatype != ARPHRD_LOOPBACK)
|
||||
NFD_LOG_WARN("Unrecognized hardware address on " << ifname);
|
||||
}
|
||||
break;
|
||||
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
||||
case AF_LINK: {
|
||||
const sockaddr_dl* sdl = reinterpret_cast<sockaddr_dl*>(ifa->ifa_addr);
|
||||
netif->index = sdl->sdl_index;
|
||||
netif->etherAddress = ethernet::Address(reinterpret_cast<uint8_t*>(LLADDR(sdl)));
|
||||
}
|
||||
break;
|
||||
#ifdef WITH_TESTS
|
||||
if (s_debugNetworkInterfaces != nullptr) {
|
||||
return *s_debugNetworkInterfaces;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (netif->isBroadcastCapable() && ifa->ifa_broadaddr != 0)
|
||||
{
|
||||
const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_broadaddr);
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
using namespace boost::asio::ip;
|
||||
using std::strerror;
|
||||
|
||||
char address[INET_ADDRSTRLEN];
|
||||
if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address)))
|
||||
netif->broadcastAddress = boost::asio::ip::address_v4::from_string(address);
|
||||
else
|
||||
NFD_LOG_WARN("inet_ntop() failed on " << ifname);
|
||||
}
|
||||
std::unordered_map<std::string, NetworkInterfaceInfo> ifmap;
|
||||
ifaddrs* ifa_list = nullptr;
|
||||
|
||||
if (::getifaddrs(&ifa_list) < 0)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(std::string("getifaddrs() failed: ") +
|
||||
strerror(errno)));
|
||||
|
||||
for (ifaddrs* ifa = ifa_list; ifa != nullptr; ifa = ifa->ifa_next) {
|
||||
std::string ifname(ifa->ifa_name);
|
||||
NetworkInterfaceInfo& netif = ifmap[ifname];
|
||||
netif.name = ifa->ifa_name;
|
||||
netif.flags = ifa->ifa_flags;
|
||||
|
||||
if (ifa->ifa_addr == nullptr)
|
||||
continue;
|
||||
|
||||
switch (ifa->ifa_addr->sa_family) {
|
||||
|
||||
case AF_INET: {
|
||||
const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_addr);
|
||||
char address[INET_ADDRSTRLEN];
|
||||
if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address))) {
|
||||
netif.ipv4Addresses.push_back(address_v4::from_string(address));
|
||||
NFD_LOG_TRACE(ifname << ": added IPv4 address " << address);
|
||||
}
|
||||
else
|
||||
NFD_LOG_WARN(ifname << ": inet_ntop(AF_INET) failed: " << strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
case AF_INET6: {
|
||||
const sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(ifa->ifa_addr);
|
||||
char address[INET6_ADDRSTRLEN];
|
||||
if (::inet_ntop(AF_INET6, &sin6->sin6_addr, address, sizeof(address))) {
|
||||
netif.ipv6Addresses.push_back(address_v6::from_string(address));
|
||||
NFD_LOG_TRACE(ifname << ": added IPv6 address " << address);
|
||||
}
|
||||
else
|
||||
NFD_LOG_WARN(ifname << ": inet_ntop(AF_INET6) failed: " << strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
case AF_PACKET: {
|
||||
const sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(ifa->ifa_addr);
|
||||
netif.index = sll->sll_ifindex;
|
||||
if (sll->sll_hatype == ARPHRD_ETHER && sll->sll_halen == ethernet::ADDR_LEN) {
|
||||
netif.etherAddress = ethernet::Address(sll->sll_addr);
|
||||
NFD_LOG_TRACE(ifname << ": added Ethernet address " << netif.etherAddress);
|
||||
}
|
||||
else if (sll->sll_hatype != ARPHRD_LOOPBACK) {
|
||||
NFD_LOG_DEBUG(ifname << ": ignoring link-layer address for unhandled hardware type "
|
||||
<< sll->sll_hatype);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
||||
case AF_LINK: {
|
||||
const sockaddr_dl* sdl = reinterpret_cast<sockaddr_dl*>(ifa->ifa_addr);
|
||||
netif.index = sdl->sdl_index;
|
||||
if (sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == ethernet::ADDR_LEN) {
|
||||
netif.etherAddress = ethernet::Address(reinterpret_cast<uint8_t*>(LLADDR(sdl)));
|
||||
NFD_LOG_TRACE(ifname << ": added Ethernet address " << netif.etherAddress);
|
||||
}
|
||||
else if (sdl->sdl_type != IFT_LOOP) {
|
||||
NFD_LOG_DEBUG(ifname << ": ignoring link-layer address for unhandled interface type "
|
||||
<< sdl->sdl_type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (netif.isBroadcastCapable() && ifa->ifa_broadaddr != nullptr) {
|
||||
const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_broadaddr);
|
||||
char address[INET_ADDRSTRLEN];
|
||||
if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address))) {
|
||||
netif.broadcastAddress = address_v4::from_string(address);
|
||||
NFD_LOG_TRACE(ifname << ": added IPv4 broadcast address " << address);
|
||||
}
|
||||
else
|
||||
NFD_LOG_WARN(ifname << ": inet_ntop(AF_INET) for broadaddr failed: " << strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
::freeifaddrs(ifa_list);
|
||||
|
||||
std::list< shared_ptr<NetworkInterfaceInfo> > list;
|
||||
BOOST_FOREACH(InterfacesMap::value_type elem, ifmap) {
|
||||
list.push_back(elem.second);
|
||||
std::vector<NetworkInterfaceInfo> v;
|
||||
v.reserve(ifmap.size());
|
||||
for (auto&& element : ifmap) {
|
||||
v.push_back(element.second);
|
||||
}
|
||||
|
||||
return list;
|
||||
return v;
|
||||
#else
|
||||
return {};
|
||||
#endif // HAVE_IFADDRS_H
|
||||
}
|
||||
|
||||
} // 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, 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,18 +21,23 @@
|
||||
*
|
||||
* 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_NETWORK_INTERFACE_HPP
|
||||
#define NFD_CORE_NETWORK_INTERFACE_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
#include "ethernet.hpp"
|
||||
|
||||
#include <ndn-cxx/util/ethernet.hpp>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
namespace ethernet = ndn::util::ethernet;
|
||||
|
||||
/** \brief contains information about a network interface
|
||||
*/
|
||||
class NetworkInterfaceInfo
|
||||
{
|
||||
public:
|
||||
@@ -82,9 +88,20 @@ NetworkInterfaceInfo::isUp() const
|
||||
return (flags & IFF_UP) != 0;
|
||||
}
|
||||
|
||||
std::list< shared_ptr<NetworkInterfaceInfo> >
|
||||
/** \brief List configured network interfaces on the system and their info
|
||||
* \warning invalid IP addresses (e.g., 0.0.0.0) may be returned in some environments
|
||||
*/
|
||||
std::vector<NetworkInterfaceInfo>
|
||||
listNetworkInterfaces();
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
/** \brief Set a list of network interfaces to be returned by subsequent listNetworkInterfaces call
|
||||
* \note To reset to normal behavior, use `setDebugNetworkInterfaces(nullptr);`
|
||||
*/
|
||||
void
|
||||
setDebugNetworkInterfaces(shared_ptr<std::vector<NetworkInterfaceInfo>> interfaces);
|
||||
#endif
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_CORE_NETWORK_INTERFACE_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, 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.
|
||||
@@ -22,74 +23,45 @@
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
#ifndef NFD_TOOLS_NETWORK_HPP
|
||||
#define NFD_TOOLS_NETWORK_HPP
|
||||
#include "network.hpp"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
namespace nfd {
|
||||
|
||||
class Network
|
||||
void
|
||||
Network::print(std::ostream& os) const
|
||||
{
|
||||
public:
|
||||
Network()
|
||||
{
|
||||
}
|
||||
os << m_minAddress << " <-> " << m_maxAddress;
|
||||
}
|
||||
|
||||
Network(const boost::asio::ip::address& minAddress,
|
||||
const boost::asio::ip::address& maxAddress)
|
||||
: m_minAddress(minAddress)
|
||||
, m_maxAddress(maxAddress)
|
||||
{
|
||||
}
|
||||
const Network&
|
||||
Network::getMaxRangeV4()
|
||||
{
|
||||
using boost::asio::ip::address_v4;
|
||||
static Network range = Network(address_v4(0), address_v4(0xFFFFFFFF));
|
||||
return range;
|
||||
}
|
||||
|
||||
void
|
||||
print(std::ostream& os) const
|
||||
{
|
||||
os << m_minAddress << " <-> " << m_maxAddress;
|
||||
}
|
||||
const Network&
|
||||
Network::getMaxRangeV6()
|
||||
{
|
||||
using boost::asio::ip::address_v6;
|
||||
static address_v6::bytes_type maxV6 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
|
||||
static Network range = Network(address_v6(), address_v6(maxV6));
|
||||
return range;
|
||||
}
|
||||
|
||||
bool
|
||||
doesContain(const boost::asio::ip::address& address) const
|
||||
{
|
||||
return (m_minAddress <= address && address <= m_maxAddress);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const Network&
|
||||
getMaxRangeV4()
|
||||
{
|
||||
using boost::asio::ip::address_v4;
|
||||
static Network range = Network(address_v4(0), address_v4(0xFFFFFFFF));
|
||||
return range;
|
||||
}
|
||||
|
||||
static const Network&
|
||||
getMaxRangeV6()
|
||||
{
|
||||
using boost::asio::ip::address_v6;
|
||||
static address_v6::bytes_type maxV6 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
|
||||
static Network range = Network(address_v6(), address_v6(maxV6));
|
||||
return range;
|
||||
}
|
||||
|
||||
private:
|
||||
boost::asio::ip::address m_minAddress;
|
||||
boost::asio::ip::address m_maxAddress;
|
||||
|
||||
friend std::istream&
|
||||
operator>>(std::istream& is, Network& network);
|
||||
|
||||
friend std::ostream&
|
||||
operator<<(std::ostream& os, const Network& network);
|
||||
};
|
||||
|
||||
inline std::ostream&
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const Network& network)
|
||||
{
|
||||
network.print(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::istream&
|
||||
std::istream&
|
||||
operator>>(std::istream& is, Network& network)
|
||||
{
|
||||
using namespace boost::asio;
|
||||
@@ -158,4 +130,4 @@ operator>>(std::istream& is, Network& network)
|
||||
return is;
|
||||
}
|
||||
|
||||
#endif // NFD_TOOLS_NETWORK_HPP
|
||||
} // namespace nfd
|
||||
@@ -21,74 +21,75 @@
|
||||
*
|
||||
* 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_TESTS_CORE_SIMPLE_NOTIFICATION_HPP
|
||||
#define NFD_TESTS_CORE_SIMPLE_NOTIFICATION_HPP
|
||||
#ifndef NFD_CORE_NETWORK_HPP
|
||||
#define NFD_CORE_NETWORK_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/utility/value_init.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace tests {
|
||||
|
||||
class SimpleNotification
|
||||
class Network
|
||||
{
|
||||
public:
|
||||
SimpleNotification()
|
||||
Network()
|
||||
{
|
||||
}
|
||||
|
||||
SimpleNotification(const std::string& message)
|
||||
: m_message(message)
|
||||
Network(const boost::asio::ip::address& minAddress,
|
||||
const boost::asio::ip::address& maxAddress)
|
||||
: m_minAddress(minAddress)
|
||||
, m_maxAddress(maxAddress)
|
||||
{
|
||||
}
|
||||
|
||||
~SimpleNotification()
|
||||
{
|
||||
}
|
||||
|
||||
Block
|
||||
wireEncode() const
|
||||
{
|
||||
ndn::EncodingBuffer buffer;
|
||||
prependByteArrayBlock(buffer,
|
||||
0x8888,
|
||||
reinterpret_cast<const uint8_t*>(m_message.c_str()),
|
||||
m_message.size());
|
||||
return buffer.block();
|
||||
}
|
||||
|
||||
void
|
||||
wireDecode(const Block& block)
|
||||
{
|
||||
m_message.assign(reinterpret_cast<const char*>(block.value()),
|
||||
block.value_size());
|
||||
print(std::ostream& os) const;
|
||||
|
||||
// error for testing
|
||||
if (!m_message.empty() && m_message[0] == '\x07')
|
||||
throw tlv::Error("0x07 error");
|
||||
bool
|
||||
doesContain(const boost::asio::ip::address& address) const
|
||||
{
|
||||
return (m_minAddress <= address && address <= m_maxAddress);
|
||||
}
|
||||
|
||||
public:
|
||||
const std::string&
|
||||
getMessage() const
|
||||
static const Network&
|
||||
getMaxRangeV4();
|
||||
|
||||
static const Network&
|
||||
getMaxRangeV6();
|
||||
|
||||
bool
|
||||
operator==(const Network& rhs) const
|
||||
{
|
||||
return m_message;
|
||||
return m_minAddress == rhs.m_minAddress && m_maxAddress == rhs.m_maxAddress;
|
||||
}
|
||||
|
||||
void
|
||||
setMessage(const std::string& message)
|
||||
bool
|
||||
operator!=(const Network& rhs) const
|
||||
{
|
||||
m_message = message;
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_message;
|
||||
boost::asio::ip::address m_minAddress;
|
||||
boost::asio::ip::address m_maxAddress;
|
||||
|
||||
friend std::istream&
|
||||
operator>>(std::istream& is, Network& network);
|
||||
|
||||
friend std::ostream&
|
||||
operator<<(std::ostream& os, const Network& network);
|
||||
};
|
||||
|
||||
} // namespace tests
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const Network& network);
|
||||
|
||||
std::istream&
|
||||
operator>>(std::istream& is, Network& network);
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_TESTS_CORE_SIMPLE_NOTIFICATION_HPP
|
||||
#endif // NFD_CORE_NETWORK_HPP
|
||||
@@ -1,81 +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,
|
||||
* 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_CORE_NOTIFICATION_STREAM_HPP
|
||||
#define NFD_CORE_NOTIFICATION_STREAM_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#include <ndn-cxx/encoding/encoding-buffer.hpp>
|
||||
#include <ndn-cxx/security/key-chain.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
/** \brief provides a publisher of Notification Stream
|
||||
* \sa http://redmine.named-data.net/projects/nfd/wiki/Notification
|
||||
*/
|
||||
template <class FaceBase>
|
||||
class NotificationStream : noncopyable
|
||||
{
|
||||
public:
|
||||
NotificationStream(FaceBase& face, const Name& prefix, ndn::KeyChain& keyChain)
|
||||
: m_face(face)
|
||||
, m_prefix(prefix)
|
||||
, m_keyChain(keyChain)
|
||||
, m_sequenceNo(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~NotificationStream()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T> void
|
||||
postNotification(const T& notification)
|
||||
{
|
||||
Name dataName = m_prefix;
|
||||
dataName.appendSequenceNumber(m_sequenceNo);
|
||||
|
||||
shared_ptr<Data> data = make_shared<Data>(dataName);
|
||||
data->setContent(notification.wireEncode());
|
||||
data->setFreshnessPeriod(time::seconds(1));
|
||||
|
||||
m_keyChain.sign(*data);
|
||||
m_face.put(*data);
|
||||
|
||||
++m_sequenceNo;
|
||||
}
|
||||
|
||||
private:
|
||||
FaceBase& m_face;
|
||||
const Name m_prefix;
|
||||
ndn::KeyChain& m_keyChain;
|
||||
uint64_t m_sequenceNo;
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_CORE_NOTIFICATION_STREAM_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,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/>.
|
||||
**/
|
||||
*/
|
||||
|
||||
#include "privilege-helper.hpp"
|
||||
#include "core/logger.hpp"
|
||||
@@ -32,15 +33,18 @@ namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("PrivilegeHelper");
|
||||
|
||||
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
uid_t PrivilegeHelper::s_normalUid = ::geteuid();
|
||||
gid_t PrivilegeHelper::s_normalGid = ::getegid();
|
||||
|
||||
uid_t PrivilegeHelper::s_privilegedUid = ::geteuid();
|
||||
gid_t PrivilegeHelper::s_privilegedGid = ::getegid();
|
||||
#endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
|
||||
void
|
||||
PrivilegeHelper::initialize(const std::string& userName, const std::string& groupName)
|
||||
{
|
||||
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
static const size_t MAX_GROUP_BUFFER_SIZE = 16384; // 16kB
|
||||
static const size_t MAX_PASSWD_BUFFER_SIZE = 16384;
|
||||
|
||||
@@ -126,11 +130,17 @@ PrivilegeHelper::initialize(const std::string& userName, const std::string& grou
|
||||
|
||||
s_normalUid = passwd.pw_uid;
|
||||
}
|
||||
#else
|
||||
if (!userName.empty() || !groupName.empty()) {
|
||||
throw Error("Dropping and raising privileges is not supported on this platform");
|
||||
}
|
||||
#endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
}
|
||||
|
||||
void
|
||||
PrivilegeHelper::drop()
|
||||
{
|
||||
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
NFD_LOG_TRACE("dropping to effective gid=" << s_normalGid);
|
||||
if (::setegid(s_normalGid) != 0)
|
||||
{
|
||||
@@ -150,11 +160,15 @@ PrivilegeHelper::drop()
|
||||
}
|
||||
|
||||
NFD_LOG_INFO("dropped to effective uid=" << ::geteuid() << " gid=" << ::getegid());
|
||||
#else
|
||||
NFD_LOG_WARN("Dropping privileges is not supported on this platform");
|
||||
#endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
}
|
||||
|
||||
void
|
||||
PrivilegeHelper::raise()
|
||||
{
|
||||
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
NFD_LOG_TRACE("elevating to effective uid=" << s_privilegedUid);
|
||||
if (::seteuid(s_privilegedUid) != 0)
|
||||
{
|
||||
@@ -173,6 +187,9 @@ PrivilegeHelper::raise()
|
||||
throw PrivilegeHelper::Error(error.str());
|
||||
}
|
||||
NFD_LOG_INFO("elevated to effective uid=" << ::geteuid() << " gid=" << ::getegid());
|
||||
#else
|
||||
NFD_LOG_WARN("Elevating privileges is not supported on this platform");
|
||||
#endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+17
-12
@@ -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_CORE_PRIVILEGE_HELPER_HPP
|
||||
#define NFD_CORE_PRIVILEGE_HELPER_HPP
|
||||
@@ -35,8 +36,11 @@ class PrivilegeHelper
|
||||
{
|
||||
public:
|
||||
|
||||
/// \brief PrivilegeHelper::Error represents a serious seteuid/gid failure and
|
||||
/// should only be caught by main in as part of a graceful program termination.
|
||||
/** \brief represents a serious seteuid/gid failure
|
||||
*
|
||||
* This should only be caught by main as part of a graceful program termination.
|
||||
* \note This is not an std::exception and BOOST_THROW_EXCEPTION should not be used.
|
||||
*/
|
||||
class Error
|
||||
{
|
||||
public:
|
||||
@@ -65,18 +69,19 @@ public:
|
||||
static void
|
||||
runElevated(function<void()> f);
|
||||
|
||||
private:
|
||||
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;
|
||||
|
||||
static uid_t s_privilegedUid;
|
||||
static gid_t s_privilegedGid;
|
||||
#endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
+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
|
||||
@@ -1,214 +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_CORE_RESOLVER_H
|
||||
#define NFD_CORE_RESOLVER_H
|
||||
|
||||
#include "common.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
#include "core/scheduler.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace resolver {
|
||||
|
||||
typedef function<bool (const boost::asio::ip::address& address)> AddressSelector;
|
||||
|
||||
struct AnyAddress {
|
||||
bool
|
||||
operator()(const boost::asio::ip::address& address)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct Ipv4Address {
|
||||
bool
|
||||
operator()(const boost::asio::ip::address& address)
|
||||
{
|
||||
return address.is_v4();
|
||||
}
|
||||
};
|
||||
|
||||
struct Ipv6Address {
|
||||
bool
|
||||
operator()(const boost::asio::ip::address& address)
|
||||
{
|
||||
return address.is_v6();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolver
|
||||
|
||||
template<class Protocol>
|
||||
class Resolver
|
||||
{
|
||||
public:
|
||||
struct Error : public std::runtime_error
|
||||
{
|
||||
Error(const std::string& what) : std::runtime_error(what) {}
|
||||
};
|
||||
|
||||
typedef function<void (const typename Protocol::endpoint& endpoint)> SuccessCallback;
|
||||
typedef function<void (const std::string& reason)> ErrorCallback;
|
||||
|
||||
typedef boost::asio::ip::basic_resolver< Protocol > resolver;
|
||||
|
||||
/** \brief Asynchronously resolve host and port
|
||||
*
|
||||
* If an address selector predicate is specified, then each resolved IP address
|
||||
* is checked against the predicate.
|
||||
*
|
||||
* Available address selector predicates:
|
||||
*
|
||||
* - resolver::AnyAddress()
|
||||
* - resolver::Ipv4Address()
|
||||
* - resolver::Ipv6Address()
|
||||
*/
|
||||
static void
|
||||
asyncResolve(const std::string& host, const std::string& port,
|
||||
const SuccessCallback& onSuccess,
|
||||
const ErrorCallback& onError,
|
||||
const nfd::resolver::AddressSelector& addressSelector = nfd::resolver::AnyAddress(),
|
||||
const time::seconds& timeout = time::seconds(4))
|
||||
{
|
||||
shared_ptr<Resolver> resolver =
|
||||
shared_ptr<Resolver>(new Resolver(onSuccess, onError,
|
||||
addressSelector));
|
||||
|
||||
resolver->asyncResolve(host, port, timeout, resolver);
|
||||
// resolver will be destroyed when async operation finishes or global IO service stops
|
||||
}
|
||||
|
||||
/** \brief Synchronously resolve host and port
|
||||
*
|
||||
* If an address selector predicate is specified, then each resolved IP address
|
||||
* is checked against the predicate.
|
||||
*
|
||||
* Available address selector predicates:
|
||||
*
|
||||
* - resolver::AnyAddress()
|
||||
* - resolver::Ipv4Address()
|
||||
* - resolver::Ipv6Address()
|
||||
*/
|
||||
static typename Protocol::endpoint
|
||||
syncResolve(const std::string& host, const std::string& port,
|
||||
const nfd::resolver::AddressSelector& addressSelector = nfd::resolver::AnyAddress())
|
||||
{
|
||||
Resolver resolver(SuccessCallback(), ErrorCallback(), addressSelector);
|
||||
|
||||
typename resolver::query query(host, port
|
||||
#if not defined(__FreeBSD__)
|
||||
, resolver::query::all_matching
|
||||
#endif
|
||||
);
|
||||
|
||||
typename resolver::iterator remoteEndpoint = resolver.m_resolver.resolve(query);
|
||||
typename resolver::iterator end;
|
||||
for (; remoteEndpoint != end; ++remoteEndpoint)
|
||||
{
|
||||
if (addressSelector(typename Protocol::endpoint(*remoteEndpoint).address()))
|
||||
return *remoteEndpoint;
|
||||
}
|
||||
throw Error("No endpoint matching the specified address selector found");
|
||||
}
|
||||
|
||||
private:
|
||||
Resolver(const SuccessCallback& onSuccess,
|
||||
const ErrorCallback& onError,
|
||||
const nfd::resolver::AddressSelector& addressSelector)
|
||||
: m_resolver(getGlobalIoService())
|
||||
, m_addressSelector(addressSelector)
|
||||
, m_onSuccess(onSuccess)
|
||||
, m_onError(onError)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
asyncResolve(const std::string& host, const std::string& port,
|
||||
const time::seconds& timeout,
|
||||
const shared_ptr<Resolver>& self)
|
||||
{
|
||||
typename resolver::query query(host, port
|
||||
#if not defined(__FreeBSD__)
|
||||
, resolver::query::all_matching
|
||||
#endif
|
||||
);
|
||||
|
||||
m_resolver.async_resolve(query,
|
||||
bind(&Resolver::onResolveSuccess, this, _1, _2, self));
|
||||
|
||||
m_resolveTimeout = scheduler::schedule(timeout,
|
||||
bind(&Resolver::onResolveError, this,
|
||||
"Timeout", self));
|
||||
}
|
||||
|
||||
void
|
||||
onResolveSuccess(const boost::system::error_code& error,
|
||||
typename resolver::iterator remoteEndpoint,
|
||||
const shared_ptr<Resolver>& self)
|
||||
{
|
||||
scheduler::cancel(m_resolveTimeout);
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (error == boost::system::errc::operation_canceled)
|
||||
return;
|
||||
|
||||
return m_onError("Remote endpoint hostname or port cannot be resolved: " +
|
||||
error.category().message(error.value()));
|
||||
}
|
||||
|
||||
typename resolver::iterator end;
|
||||
for (; remoteEndpoint != end; ++remoteEndpoint)
|
||||
{
|
||||
if (m_addressSelector(typename Protocol::endpoint(*remoteEndpoint).address()))
|
||||
return m_onSuccess(*remoteEndpoint);
|
||||
}
|
||||
|
||||
m_onError("No endpoint matching the specified address selector found");
|
||||
}
|
||||
|
||||
void
|
||||
onResolveError(const std::string& errorInfo,
|
||||
const shared_ptr<Resolver>& self)
|
||||
{
|
||||
m_resolver.cancel();
|
||||
m_onError(errorInfo);
|
||||
}
|
||||
|
||||
private:
|
||||
resolver m_resolver;
|
||||
EventId m_resolveTimeout;
|
||||
|
||||
nfd::resolver::AddressSelector m_addressSelector;
|
||||
SuccessCallback m_onSuccess;
|
||||
ErrorCallback m_onError;
|
||||
};
|
||||
|
||||
typedef Resolver<boost::asio::ip::tcp> TcpResolver;
|
||||
typedef Resolver<boost::asio::ip::udp> UdpResolver;
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_CORE_RESOLVER_H
|
||||
+57
-11
@@ -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,22 +21,25 @@
|
||||
*
|
||||
* 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 "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;
|
||||
}
|
||||
|
||||
@@ -57,5 +61,47 @@ resetGlobalScheduler()
|
||||
g_scheduler.reset();
|
||||
}
|
||||
|
||||
ScopedEventId::ScopedEventId()
|
||||
{
|
||||
}
|
||||
|
||||
ScopedEventId::ScopedEventId(const EventId& event)
|
||||
: m_event(event)
|
||||
{
|
||||
}
|
||||
|
||||
ScopedEventId::ScopedEventId(ScopedEventId&& other)
|
||||
: m_event(other.m_event)
|
||||
{
|
||||
other.release();
|
||||
}
|
||||
|
||||
ScopedEventId&
|
||||
ScopedEventId::operator=(const EventId& event)
|
||||
{
|
||||
if (m_event != event) {
|
||||
scheduler::cancel(m_event);
|
||||
m_event = event;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ScopedEventId::~ScopedEventId()
|
||||
{
|
||||
scheduler::cancel(m_event);
|
||||
}
|
||||
|
||||
void
|
||||
ScopedEventId::cancel()
|
||||
{
|
||||
scheduler::cancel(m_event);
|
||||
}
|
||||
|
||||
void
|
||||
ScopedEventId::release()
|
||||
{
|
||||
m_event.reset();
|
||||
}
|
||||
|
||||
} // namespace scheduler
|
||||
} // namespace nfd
|
||||
+51
-9
@@ -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_CORE_SCHEDULER_HPP
|
||||
#define NFD_CORE_SCHEDULER_HPP
|
||||
@@ -48,9 +49,50 @@ schedule(const time::nanoseconds& after, const Scheduler::Event& event);
|
||||
void
|
||||
cancel(const EventId& eventId);
|
||||
|
||||
} // namespace scheduler
|
||||
/** \brief cancels an event automatically upon destruction
|
||||
*/
|
||||
class ScopedEventId : noncopyable
|
||||
{
|
||||
public:
|
||||
ScopedEventId();
|
||||
|
||||
using scheduler::EventId;
|
||||
/** \brief implicit constructor from EventId
|
||||
* \param event the event to be cancelled upon destruction
|
||||
*/
|
||||
ScopedEventId(const EventId& event);
|
||||
|
||||
/** \brief move constructor
|
||||
*/
|
||||
ScopedEventId(ScopedEventId&& other);
|
||||
|
||||
/** \brief assigns an event
|
||||
*
|
||||
* If a different event has been assigned to this instance previously,
|
||||
* that event will be cancelled immediately.
|
||||
*/
|
||||
ScopedEventId&
|
||||
operator=(const EventId& event);
|
||||
|
||||
/** \brief cancels the event
|
||||
*/
|
||||
~ScopedEventId();
|
||||
|
||||
/** \brief cancels the event manually
|
||||
*/
|
||||
void
|
||||
cancel();
|
||||
|
||||
/** \brief releases the event so that it won't be disconnected
|
||||
* when this ScopedEventId is destructed
|
||||
*/
|
||||
void
|
||||
release();
|
||||
|
||||
private:
|
||||
EventId m_event;
|
||||
};
|
||||
|
||||
} // namespace scheduler
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -40,10 +40,14 @@ template <class FaceBase>
|
||||
class SegmentPublisher : noncopyable
|
||||
{
|
||||
public:
|
||||
SegmentPublisher(FaceBase& face, const Name& prefix, ndn::KeyChain& keyChain)
|
||||
SegmentPublisher(FaceBase& face,
|
||||
const Name& prefix,
|
||||
ndn::KeyChain& keyChain,
|
||||
const time::milliseconds& freshnessPeriod = getDefaultFreshness())
|
||||
: m_face(face)
|
||||
, m_prefix(prefix)
|
||||
, m_keyChain(keyChain)
|
||||
, m_freshnessPeriod(freshnessPeriod)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -59,6 +63,12 @@ public:
|
||||
return MAX_SEGMENT_SIZE;
|
||||
}
|
||||
|
||||
static constexpr time::milliseconds
|
||||
getDefaultFreshness()
|
||||
{
|
||||
return time::milliseconds(1000);
|
||||
}
|
||||
|
||||
void
|
||||
publish()
|
||||
{
|
||||
@@ -84,6 +94,7 @@ public:
|
||||
|
||||
shared_ptr<Data> data = make_shared<Data>(segmentName);
|
||||
data->setContent(segmentBegin, segmentEnd - segmentBegin);
|
||||
data->setFreshnessPeriod(m_freshnessPeriod);
|
||||
|
||||
segmentBegin = segmentEnd;
|
||||
if (segmentBegin >= end) {
|
||||
@@ -113,6 +124,7 @@ private:
|
||||
FaceBase& m_face;
|
||||
const Name m_prefix;
|
||||
ndn::KeyChain& m_keyChain;
|
||||
const time::milliseconds m_freshnessPeriod;
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
+21
-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,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/>.
|
||||
**/
|
||||
*/
|
||||
|
||||
#include "channel.hpp"
|
||||
|
||||
@@ -36,4 +37,17 @@ Channel::setUri(const FaceUri& uri)
|
||||
m_uri = uri;
|
||||
}
|
||||
|
||||
void
|
||||
connectFaceClosedSignal(Face& face, const std::function<void()>& f)
|
||||
{
|
||||
using face::FaceState;
|
||||
|
||||
face.afterStateChange.connect(
|
||||
[f] (FaceState oldState, FaceState newState) {
|
||||
if (newState == FaceState::CLOSED) {
|
||||
f();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
+32
-18
@@ -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_CHANNEL_HPP
|
||||
#define NFD_DAEMON_FACE_CHANNEL_HPP
|
||||
@@ -29,20 +30,23 @@
|
||||
|
||||
namespace nfd {
|
||||
|
||||
/**
|
||||
* \brief Prototype for the callback that is invoked when the face
|
||||
* is created (as a response to incoming connection or after
|
||||
* connection is established)
|
||||
*/
|
||||
typedef function<void(const shared_ptr<Face>& newFace)> FaceCreatedCallback;
|
||||
|
||||
/**
|
||||
* \brief Prototype for the callback that is invoked when the face
|
||||
* fails to be created
|
||||
*/
|
||||
typedef function<void(const std::string& reason)> FaceCreationFailedCallback;
|
||||
|
||||
|
||||
class Channel : noncopyable
|
||||
{
|
||||
public:
|
||||
/** \brief Prototype for the callback called when face is created
|
||||
* (as a response to incoming connection or after connection
|
||||
* is established)
|
||||
*/
|
||||
typedef function<void(const shared_ptr<Face>& newFace)> FaceCreatedCallback;
|
||||
|
||||
/** \brief Prototype for the callback that is called when face is failed to
|
||||
* get created
|
||||
*/
|
||||
typedef function<void(const std::string& reason)> ConnectFailedCallback;
|
||||
|
||||
virtual
|
||||
~Channel();
|
||||
|
||||
@@ -63,6 +67,16 @@ Channel::getUri() const
|
||||
return m_uri;
|
||||
}
|
||||
|
||||
/** \brief invokes a callback when the face is closed
|
||||
* \param face the face
|
||||
* \param f the callback to be invoked when the face enters CLOSED state
|
||||
*
|
||||
* This function connects a callback to the afterStateChange signal on the \p face,
|
||||
* and invokes \p f when the state becomes CLOSED.
|
||||
*/
|
||||
void
|
||||
connectFaceClosedSignal(Face& face, const std::function<void()>& f);
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_CHANNEL_HPP
|
||||
@@ -1,342 +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,
|
||||
* 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_FACE_DATAGRAM_FACE_HPP
|
||||
#define NFD_DAEMON_FACE_DATAGRAM_FACE_HPP
|
||||
|
||||
#include "face.hpp"
|
||||
#include "core/logger.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
class Unicast {};
|
||||
class Multicast {};
|
||||
|
||||
template<class Protocol, class Type = Unicast>
|
||||
class DatagramFace : public Face
|
||||
{
|
||||
public:
|
||||
typedef Protocol protocol;
|
||||
|
||||
/** \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);
|
||||
|
||||
virtual
|
||||
~DatagramFace();
|
||||
|
||||
// from Face
|
||||
virtual void
|
||||
sendInterest(const Interest& interest);
|
||||
|
||||
virtual void
|
||||
sendData(const Data& data);
|
||||
|
||||
virtual void
|
||||
close();
|
||||
|
||||
void
|
||||
receiveDatagram(const uint8_t* buffer,
|
||||
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
|
||||
handleSend(const boost::system::error_code& error,
|
||||
size_t nBytesSent,
|
||||
const Block& payload);
|
||||
|
||||
void
|
||||
handleReceive(const boost::system::error_code& error,
|
||||
size_t nBytesReceived);
|
||||
|
||||
void
|
||||
keepFaceAliveUntilAllHandlersExecuted(const shared_ptr<Face>& face);
|
||||
|
||||
void
|
||||
closeSocket();
|
||||
|
||||
protected:
|
||||
shared_ptr<typename protocol::socket> m_socket;
|
||||
uint8_t m_inputBuffer[MAX_NDN_PACKET_SIZE];
|
||||
bool m_hasBeenUsedRecently;
|
||||
|
||||
NFD_LOG_INCLASS_DECLARE();
|
||||
};
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
setOnDemand(isOnDemand);
|
||||
|
||||
m_socket->async_receive(boost::asio::buffer(m_inputBuffer, MAX_NDN_PACKET_SIZE), 0,
|
||||
bind(&DatagramFace<T, U>::handleReceive, this, _1, _2));
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline
|
||||
DatagramFace<T, U>::~DatagramFace()
|
||||
{
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::sendInterest(const Interest& interest)
|
||||
{
|
||||
this->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));
|
||||
|
||||
// anything else should be done here?
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::sendData(const Data& data)
|
||||
{
|
||||
this->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));
|
||||
|
||||
// anything else should be done here?
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::handleSend(const boost::system::error_code& error,
|
||||
size_t nBytesSent,
|
||||
const Block& payload)
|
||||
// 'payload' is unused; it's needed to retain the underlying Buffer
|
||||
{
|
||||
if (error != 0) {
|
||||
if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
|
||||
return;
|
||||
|
||||
if (!m_socket->is_open()) {
|
||||
fail("Tunnel closed");
|
||||
return;
|
||||
}
|
||||
|
||||
NFD_LOG_WARN("[id:" << this->getId()
|
||||
<< ",uri:" << this->getRemoteUri()
|
||||
<< "] Send operation failed, closing socket: "
|
||||
<< error.category().message(error.value()));
|
||||
|
||||
closeSocket();
|
||||
|
||||
if (error == boost::asio::error::eof) {
|
||||
fail("Tunnel closed");
|
||||
}
|
||||
else {
|
||||
fail("Send operation failed, closing socket: " +
|
||||
error.category().message(error.value()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NFD_LOG_TRACE("[id:" << this->getId()
|
||||
<< ",uri:" << this->getRemoteUri()
|
||||
<< "] Successfully sent: " << nBytesSent << " bytes");
|
||||
this->getMutableCounters().getNOutBytes() += nBytesSent;
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::close()
|
||||
{
|
||||
if (!m_socket->is_open())
|
||||
return;
|
||||
|
||||
NFD_LOG_INFO("[id:" << this->getId()
|
||||
<< ",uri:" << this->getRemoteUri()
|
||||
<< "] Close tunnel");
|
||||
|
||||
closeSocket();
|
||||
fail("Close tunnel");
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::handleReceive(const boost::system::error_code& error,
|
||||
size_t nBytesReceived)
|
||||
{
|
||||
NFD_LOG_DEBUG("handleReceive: " << nBytesReceived);
|
||||
receiveDatagram(m_inputBuffer, nBytesReceived, error);
|
||||
if (m_socket->is_open())
|
||||
m_socket->async_receive(boost::asio::buffer(m_inputBuffer, MAX_NDN_PACKET_SIZE), 0,
|
||||
bind(&DatagramFace<T, U>::handleReceive, this, _1, _2));
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::receiveDatagram(const uint8_t* buffer,
|
||||
size_t nBytesReceived,
|
||||
const boost::system::error_code& error)
|
||||
{
|
||||
if (error != 0 || nBytesReceived == 0) {
|
||||
if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
|
||||
return;
|
||||
|
||||
// this should be unnecessary, but just in case
|
||||
if (!m_socket->is_open()) {
|
||||
fail("Tunnel closed");
|
||||
return;
|
||||
}
|
||||
|
||||
NFD_LOG_WARN("[id:" << this->getId()
|
||||
<< ",uri:" << this->getRemoteUri()
|
||||
<< "] Receive operation failed: "
|
||||
<< error.category().message(error.value()));
|
||||
|
||||
closeSocket();
|
||||
|
||||
if (error == boost::asio::error::eof) {
|
||||
fail("Tunnel closed");
|
||||
}
|
||||
else {
|
||||
fail("Receive operation failed, closing socket: " +
|
||||
error.category().message(error.value()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NFD_LOG_TRACE("[id:" << this->getId()
|
||||
<< ",uri:" << this->getRemoteUri()
|
||||
<< "] Received: " << nBytesReceived << " bytes");
|
||||
this->getMutableCounters().getNInBytes() += nBytesReceived;
|
||||
|
||||
Block element;
|
||||
bool isOk = Block::fromBuffer(buffer, nBytesReceived, element);
|
||||
if (!isOk)
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << this->getId()
|
||||
<< ",uri:" << this->getRemoteUri()
|
||||
<< "] 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");
|
||||
// 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() << "]");
|
||||
// This message won't extend the face lifetime
|
||||
return;
|
||||
}
|
||||
|
||||
m_hasBeenUsedRecently = true;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::keepFaceAliveUntilAllHandlersExecuted(const shared_ptr<Face>& face)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::closeSocket()
|
||||
{
|
||||
NFD_LOG_DEBUG("[id:" << this->getId()
|
||||
<< ",uri:" << this->getRemoteUri()
|
||||
<< "] closeSocket");
|
||||
|
||||
boost::asio::io_service& io = m_socket->get_io_service();
|
||||
|
||||
// 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);
|
||||
// after this, handlers will be called with an error code
|
||||
|
||||
// ensure that the Face object is alive at least until all pending
|
||||
// handlers are dispatched
|
||||
io.post(bind(&DatagramFace<T, U>::keepFaceAliveUntilAllHandlersExecuted,
|
||||
this, this->shared_from_this()));
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramFace<T, U>::setOnDemand(bool isOnDemand)
|
||||
{
|
||||
Face::setOnDemand(isOnDemand);
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
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
|
||||
@@ -0,0 +1,252 @@
|
||||
/* -*- 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_FACE_DATAGRAM_TRANSPORT_HPP
|
||||
#define NFD_DAEMON_FACE_DATAGRAM_TRANSPORT_HPP
|
||||
|
||||
#include "transport.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
struct Unicast {};
|
||||
struct Multicast {};
|
||||
|
||||
/** \brief Implements Transport for datagram-based protocols.
|
||||
*
|
||||
* \tparam Protocol a datagram-based protocol in Boost.Asio
|
||||
*/
|
||||
template<class Protocol, class Addressing = Unicast>
|
||||
class DatagramTransport : public Transport
|
||||
{
|
||||
public:
|
||||
typedef Protocol protocol;
|
||||
|
||||
/** \brief Construct datagram transport.
|
||||
*
|
||||
* \param socket Protocol-specific socket for the created transport
|
||||
*/
|
||||
explicit
|
||||
DatagramTransport(typename protocol::socket&& socket);
|
||||
|
||||
/** \brief Receive datagram, translate buffer into packet, deliver to parent class.
|
||||
*/
|
||||
void
|
||||
receiveDatagram(const uint8_t* buffer, size_t nBytesReceived,
|
||||
const boost::system::error_code& error);
|
||||
|
||||
protected:
|
||||
virtual void
|
||||
doClose() DECL_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
doSend(Transport::Packet&& packet) DECL_OVERRIDE;
|
||||
|
||||
void
|
||||
handleSend(const boost::system::error_code& error,
|
||||
size_t nBytesSent, const Block& payload);
|
||||
|
||||
void
|
||||
handleReceive(const boost::system::error_code& error,
|
||||
size_t nBytesReceived);
|
||||
|
||||
void
|
||||
processErrorCode(const boost::system::error_code& error);
|
||||
|
||||
bool
|
||||
hasBeenUsedRecently() const;
|
||||
|
||||
void
|
||||
resetRecentUsage();
|
||||
|
||||
static EndpointId
|
||||
makeEndpointId(const typename protocol::endpoint& ep);
|
||||
|
||||
protected:
|
||||
typename protocol::socket m_socket;
|
||||
typename protocol::endpoint m_sender;
|
||||
|
||||
NFD_LOG_INCLASS_DECLARE();
|
||||
|
||||
private:
|
||||
std::array<uint8_t, ndn::MAX_NDN_PACKET_SIZE> m_receiveBuffer;
|
||||
bool m_hasBeenUsedRecently;
|
||||
};
|
||||
|
||||
|
||||
template<class T, class U>
|
||||
DatagramTransport<T, U>::DatagramTransport(typename DatagramTransport::protocol::socket&& socket)
|
||||
: m_socket(std::move(socket))
|
||||
, m_hasBeenUsedRecently(false)
|
||||
{
|
||||
m_socket.async_receive_from(boost::asio::buffer(m_receiveBuffer), m_sender,
|
||||
bind(&DatagramTransport<T, U>::handleReceive, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
void
|
||||
DatagramTransport<T, U>::doClose()
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
if (m_socket.is_open()) {
|
||||
// Cancel all outstanding operations and close the socket.
|
||||
// Use the non-throwing variants and ignore errors, if any.
|
||||
boost::system::error_code error;
|
||||
m_socket.cancel(error);
|
||||
m_socket.close(error);
|
||||
}
|
||||
|
||||
// Ensure that the Transport stays alive at least until
|
||||
// all pending handlers are dispatched
|
||||
getGlobalIoService().post([this] {
|
||||
this->setState(TransportState::CLOSED);
|
||||
});
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
void
|
||||
DatagramTransport<T, U>::doSend(Transport::Packet&& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
m_socket.async_send(boost::asio::buffer(packet.packet),
|
||||
bind(&DatagramTransport<T, U>::handleSend, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred,
|
||||
packet.packet));
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
void
|
||||
DatagramTransport<T, U>::receiveDatagram(const uint8_t* buffer, size_t nBytesReceived,
|
||||
const boost::system::error_code& error)
|
||||
{
|
||||
if (error)
|
||||
return processErrorCode(error);
|
||||
|
||||
NFD_LOG_FACE_TRACE("Received: " << nBytesReceived << " bytes");
|
||||
|
||||
bool isOk = false;
|
||||
Block element;
|
||||
std::tie(isOk, element) = Block::fromBuffer(buffer, nBytesReceived);
|
||||
if (!isOk) {
|
||||
NFD_LOG_FACE_WARN("Failed to parse incoming packet");
|
||||
// This packet won't extend the face lifetime
|
||||
return;
|
||||
}
|
||||
if (element.size() != nBytesReceived) {
|
||||
NFD_LOG_FACE_WARN("Received datagram size and decoded element size don't match");
|
||||
// This packet won't extend the face lifetime
|
||||
return;
|
||||
}
|
||||
m_hasBeenUsedRecently = true;
|
||||
|
||||
Transport::Packet tp(std::move(element));
|
||||
tp.remoteEndpoint = makeEndpointId(m_sender);
|
||||
this->receive(std::move(tp));
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
void
|
||||
DatagramTransport<T, U>::handleReceive(const boost::system::error_code& error,
|
||||
size_t nBytesReceived)
|
||||
{
|
||||
receiveDatagram(m_receiveBuffer.data(), nBytesReceived, error);
|
||||
|
||||
if (m_socket.is_open())
|
||||
m_socket.async_receive_from(boost::asio::buffer(m_receiveBuffer), m_sender,
|
||||
bind(&DatagramTransport<T, U>::handleReceive, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
void
|
||||
DatagramTransport<T, U>::handleSend(const boost::system::error_code& error,
|
||||
size_t nBytesSent, const Block& payload)
|
||||
// 'payload' is unused; it's needed to retain the underlying Buffer
|
||||
{
|
||||
if (error)
|
||||
return processErrorCode(error);
|
||||
|
||||
NFD_LOG_FACE_TRACE("Successfully sent: " << nBytesSent << " bytes");
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
void
|
||||
DatagramTransport<T, U>::processErrorCode(const boost::system::error_code& error)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
if (getState() == TransportState::CLOSING ||
|
||||
getState() == TransportState::FAILED ||
|
||||
getState() == TransportState::CLOSED ||
|
||||
error == boost::asio::error::operation_aborted)
|
||||
// transport is shutting down, ignore any errors
|
||||
return;
|
||||
|
||||
if (getPersistency() == ndn::nfd::FacePersistency::FACE_PERSISTENCY_PERMANENT) {
|
||||
NFD_LOG_FACE_DEBUG("Permanent face ignores error: " << error.message());
|
||||
return;
|
||||
}
|
||||
|
||||
if (error != boost::asio::error::eof)
|
||||
NFD_LOG_FACE_WARN("Send or receive operation failed: " << error.message());
|
||||
|
||||
this->setState(TransportState::FAILED);
|
||||
doClose();
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline bool
|
||||
DatagramTransport<T, U>::hasBeenUsedRecently() const
|
||||
{
|
||||
return m_hasBeenUsedRecently;
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline void
|
||||
DatagramTransport<T, U>::resetRecentUsage()
|
||||
{
|
||||
m_hasBeenUsedRecently = false;
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline Transport::EndpointId
|
||||
DatagramTransport<T, U>::makeEndpointId(const typename protocol::endpoint& ep)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_DATAGRAM_TRANSPORT_HPP
|
||||
@@ -1,336 +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,
|
||||
* 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 "ethernet-face.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include "core/network-interface.hpp"
|
||||
|
||||
#include <pcap/pcap.h>
|
||||
|
||||
#include <cstring> // for std::strncpy()
|
||||
#include <arpa/inet.h> // for htons() and ntohs()
|
||||
#include <net/ethernet.h> // for struct ether_header
|
||||
#include <net/if.h> // for struct ifreq
|
||||
#include <stdio.h> // for snprintf()
|
||||
#include <sys/ioctl.h> // for ioctl()
|
||||
#include <unistd.h> // for dup()
|
||||
|
||||
#if !defined(PCAP_NETMASK_UNKNOWN)
|
||||
/*
|
||||
* Value to pass to pcap_compile() as the netmask if you don't know what
|
||||
* the netmask is.
|
||||
*/
|
||||
#define PCAP_NETMASK_UNKNOWN 0xffffffff
|
||||
#endif
|
||||
|
||||
namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("EthernetFace");
|
||||
|
||||
EthernetFace::EthernetFace(const shared_ptr<boost::asio::posix::stream_descriptor>& socket,
|
||||
const shared_ptr<NetworkInterfaceInfo>& interface,
|
||||
const ethernet::Address& address)
|
||||
: Face(FaceUri(address), FaceUri::fromDev(interface->name))
|
||||
, m_socket(socket)
|
||||
, m_interfaceName(interface->name)
|
||||
, m_srcAddress(interface->etherAddress)
|
||||
, m_destAddress(address)
|
||||
{
|
||||
NFD_LOG_INFO("Creating ethernet face on " << m_interfaceName << ": "
|
||||
<< m_srcAddress << " <--> " << m_destAddress);
|
||||
pcapInit();
|
||||
|
||||
int fd = pcap_get_selectable_fd(m_pcap);
|
||||
if (fd < 0)
|
||||
throw Error("pcap_get_selectable_fd() failed");
|
||||
|
||||
// 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_interfaceMtu = getInterfaceMtu();
|
||||
NFD_LOG_DEBUG("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Interface MTU is: " << m_interfaceMtu);
|
||||
|
||||
char filter[100];
|
||||
::snprintf(filter, sizeof(filter),
|
||||
"(ether proto 0x%x) && (ether dst %s) && (not ether src %s)",
|
||||
ETHERTYPE_NDN,
|
||||
m_destAddress.toString().c_str(),
|
||||
m_srcAddress.toString().c_str());
|
||||
setPacketFilter(filter);
|
||||
|
||||
m_socket->async_read_some(boost::asio::null_buffers(),
|
||||
bind(&EthernetFace::handleRead, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
EthernetFace::~EthernetFace()
|
||||
{
|
||||
onFail.clear(); // no reason to call onFail anymore
|
||||
close();
|
||||
}
|
||||
|
||||
void
|
||||
EthernetFace::sendInterest(const Interest& interest)
|
||||
{
|
||||
onSendInterest(interest);
|
||||
sendPacket(interest.wireEncode());
|
||||
}
|
||||
|
||||
void
|
||||
EthernetFace::sendData(const Data& data)
|
||||
{
|
||||
onSendData(data);
|
||||
sendPacket(data.wireEncode());
|
||||
}
|
||||
|
||||
void
|
||||
EthernetFace::close()
|
||||
{
|
||||
if (m_pcap)
|
||||
{
|
||||
boost::system::error_code error;
|
||||
m_socket->close(error); // ignore errors
|
||||
pcap_close(m_pcap);
|
||||
m_pcap = 0;
|
||||
|
||||
fail("Face closed");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EthernetFace::pcapInit()
|
||||
{
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
errbuf[0] = '\0';
|
||||
m_pcap = pcap_create(m_interfaceName.c_str(), errbuf);
|
||||
if (!m_pcap)
|
||||
throw Error("pcap_create(): " + std::string(errbuf));
|
||||
|
||||
#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
|
||||
// Enable "immediate mode", effectively disabling any read buffering in the kernel.
|
||||
// This corresponds to the BIOCIMMEDIATE ioctl on BSD-like systems (including OS X)
|
||||
// where libpcap uses a BPF device. On Linux this forces libpcap not to use TPACKET_V3,
|
||||
// even if the kernel supports it, thus preventing bug #1511.
|
||||
pcap_set_immediate_mode(m_pcap, 1);
|
||||
#endif
|
||||
|
||||
/// \todo Do not rely on promisc mode, see task #1278
|
||||
if (!m_destAddress.isBroadcast())
|
||||
pcap_set_promisc(m_pcap, 1);
|
||||
|
||||
if (pcap_activate(m_pcap) < 0)
|
||||
throw Error("pcap_activate() failed");
|
||||
|
||||
if (pcap_set_datalink(m_pcap, DLT_EN10MB) < 0)
|
||||
throw Error("pcap_set_datalink(): " + std::string(pcap_geterr(m_pcap)));
|
||||
|
||||
if (pcap_setdirection(m_pcap, PCAP_D_IN) < 0)
|
||||
// no need to throw on failure, BPF will filter unwanted packets anyway
|
||||
NFD_LOG_WARN("pcap_setdirection(): " << pcap_geterr(m_pcap));
|
||||
}
|
||||
|
||||
void
|
||||
EthernetFace::setPacketFilter(const char* filterString)
|
||||
{
|
||||
bpf_program filter;
|
||||
if (pcap_compile(m_pcap, &filter, filterString, 1, PCAP_NETMASK_UNKNOWN) < 0)
|
||||
throw Error("pcap_compile(): " + std::string(pcap_geterr(m_pcap)));
|
||||
|
||||
int ret = pcap_setfilter(m_pcap, &filter);
|
||||
pcap_freecode(&filter);
|
||||
if (ret < 0)
|
||||
throw Error("pcap_setfilter(): " + std::string(pcap_geterr(m_pcap)));
|
||||
}
|
||||
|
||||
void
|
||||
EthernetFace::sendPacket(const ndn::Block& block)
|
||||
{
|
||||
if (!m_pcap)
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Trying to send on closed face");
|
||||
fail("Face closed");
|
||||
return;
|
||||
}
|
||||
|
||||
/// \todo Fragmentation
|
||||
if (block.size() > m_interfaceMtu)
|
||||
{
|
||||
NFD_LOG_ERROR("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Fragmentation not implemented: dropping packet larger than MTU");
|
||||
return;
|
||||
}
|
||||
|
||||
/// \todo Right now there is no reserve when packet is received, but
|
||||
/// we should reserve some space at the beginning and at the end
|
||||
ndn::EncodingBuffer buffer(block);
|
||||
|
||||
// pad with zeroes if the payload is too short
|
||||
if (block.size() < ethernet::MIN_DATA_LEN)
|
||||
{
|
||||
static const uint8_t padding[ethernet::MIN_DATA_LEN] = {0};
|
||||
buffer.appendByteArray(padding, ethernet::MIN_DATA_LEN - block.size());
|
||||
}
|
||||
|
||||
// construct and prepend the ethernet header
|
||||
static uint16_t ethertype = htons(ETHERTYPE_NDN);
|
||||
buffer.prependByteArray(reinterpret_cast<const uint8_t*>(ðertype), ethernet::TYPE_LEN);
|
||||
buffer.prependByteArray(m_srcAddress.data(), m_srcAddress.size());
|
||||
buffer.prependByteArray(m_destAddress.data(), m_destAddress.size());
|
||||
|
||||
// send the packet
|
||||
int sent = pcap_inject(m_pcap, buffer.buf(), buffer.size());
|
||||
if (sent < 0)
|
||||
{
|
||||
throw Error("pcap_inject(): " + std::string(pcap_geterr(m_pcap)));
|
||||
}
|
||||
else if (static_cast<size_t>(sent) < buffer.size())
|
||||
{
|
||||
throw Error("Failed to send packet");
|
||||
}
|
||||
|
||||
NFD_LOG_TRACE("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Successfully sent: " << block.size() << " bytes");
|
||||
this->getMutableCounters().getNOutBytes() += block.size();
|
||||
}
|
||||
|
||||
void
|
||||
EthernetFace::handleRead(const boost::system::error_code& error, size_t)
|
||||
{
|
||||
if (error)
|
||||
return processErrorCode(error);
|
||||
|
||||
pcap_pkthdr* pktHeader;
|
||||
const uint8_t* packet;
|
||||
int ret = pcap_next_ex(m_pcap, &pktHeader, &packet);
|
||||
if (ret < 0)
|
||||
{
|
||||
throw Error("pcap_next_ex(): " + std::string(pcap_geterr(m_pcap)));
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] pcap_next_ex() timed out");
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t length = pktHeader->caplen;
|
||||
if (length < ethernet::HDR_LEN + ethernet::MIN_DATA_LEN)
|
||||
throw Error("Received packet is too short");
|
||||
|
||||
const ether_header* eh = reinterpret_cast<const ether_header*>(packet);
|
||||
if (ntohs(eh->ether_type) != ETHERTYPE_NDN)
|
||||
throw Error("Unrecognized ethertype");
|
||||
|
||||
packet += ethernet::HDR_LEN;
|
||||
length -= ethernet::HDR_LEN;
|
||||
|
||||
/// \todo Reserve space in front and at the back
|
||||
/// of the underlying buffer
|
||||
Block element;
|
||||
bool isOk = Block::fromBuffer(packet, length, element);
|
||||
if (isOk)
|
||||
{
|
||||
NFD_LOG_TRACE("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Received: " << element.size() << " bytes");
|
||||
this->getMutableCounters().getNInBytes() += element.size();
|
||||
|
||||
if (!decodeAndDispatchInput(element))
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Received unrecognized block of type " << element.type());
|
||||
// ignore unknown packet
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Received block is invalid or too large to process");
|
||||
}
|
||||
}
|
||||
|
||||
m_socket->async_read_some(boost::asio::null_buffers(),
|
||||
bind(&EthernetFace::handleRead, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void
|
||||
EthernetFace::processErrorCode(const boost::system::error_code& error)
|
||||
{
|
||||
if (error == boost::system::errc::operation_canceled)
|
||||
// when socket is closed by someone
|
||||
return;
|
||||
|
||||
if (!m_pcap)
|
||||
{
|
||||
fail("Face closed");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string msg;
|
||||
if (error == boost::asio::error::eof)
|
||||
{
|
||||
msg = "Face closed";
|
||||
NFD_LOG_INFO("[id:" << getId() << ",endpoint:" << m_interfaceName << "] " << msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = "Receive operation failed, closing face: " + error.message();
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName << "] " << msg);
|
||||
}
|
||||
|
||||
close();
|
||||
fail(msg);
|
||||
}
|
||||
|
||||
size_t
|
||||
EthernetFace::getInterfaceMtu() const
|
||||
{
|
||||
size_t mtu = ethernet::MAX_DATA_LEN;
|
||||
|
||||
#ifdef SIOCGIFMTU
|
||||
ifreq ifr = boost::initialized_value;
|
||||
std::strncpy(ifr.ifr_name, m_interfaceName.c_str(), sizeof(ifr.ifr_name) - 1);
|
||||
|
||||
if (::ioctl(m_socket->native_handle(), SIOCGIFMTU, &ifr) < 0)
|
||||
{
|
||||
NFD_LOG_WARN("[id:" << getId() << ",endpoint:" << m_interfaceName
|
||||
<< "] Failed to get interface MTU, assuming " << mtu);
|
||||
}
|
||||
else
|
||||
{
|
||||
mtu = std::min(mtu, static_cast<size_t>(ifr.ifr_mtu));
|
||||
}
|
||||
#endif
|
||||
|
||||
return mtu;
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
@@ -1,115 +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,
|
||||
* 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_FACE_ETHERNET_FACE_HPP
|
||||
#define NFD_DAEMON_FACE_ETHERNET_FACE_HPP
|
||||
|
||||
#include "config.hpp"
|
||||
#include "ethernet.hpp"
|
||||
#include "face.hpp"
|
||||
|
||||
#ifndef HAVE_LIBPCAP
|
||||
#error "Cannot include this file when libpcap is not available"
|
||||
#endif
|
||||
|
||||
// forward declarations
|
||||
struct pcap;
|
||||
typedef pcap pcap_t;
|
||||
|
||||
namespace nfd {
|
||||
|
||||
class NetworkInterfaceInfo;
|
||||
|
||||
/**
|
||||
* \brief Implementation of Face abstraction that uses raw
|
||||
* Ethernet frames as underlying transport mechanism
|
||||
*/
|
||||
class EthernetFace : public Face
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief EthernetFace-related error
|
||||
*/
|
||||
struct Error : public Face::Error
|
||||
{
|
||||
Error(const std::string& what) : Face::Error(what) {}
|
||||
};
|
||||
|
||||
EthernetFace(const shared_ptr<boost::asio::posix::stream_descriptor>& socket,
|
||||
const shared_ptr<NetworkInterfaceInfo>& interface,
|
||||
const ethernet::Address& address);
|
||||
|
||||
virtual
|
||||
~EthernetFace();
|
||||
|
||||
/// send an Interest
|
||||
virtual void
|
||||
sendInterest(const Interest& interest);
|
||||
|
||||
/// send a Data
|
||||
virtual void
|
||||
sendData(const Data& data);
|
||||
|
||||
/**
|
||||
* \brief Close the face
|
||||
*
|
||||
* This terminates all communication on the face and cause
|
||||
* onFail() method event to be invoked
|
||||
*/
|
||||
virtual void
|
||||
close();
|
||||
|
||||
private:
|
||||
void
|
||||
pcapInit();
|
||||
|
||||
void
|
||||
setPacketFilter(const char* filterString);
|
||||
|
||||
void
|
||||
sendPacket(const ndn::Block& block);
|
||||
|
||||
void
|
||||
handleRead(const boost::system::error_code& error,
|
||||
size_t nBytesRead);
|
||||
|
||||
void
|
||||
processErrorCode(const boost::system::error_code& error);
|
||||
|
||||
size_t
|
||||
getInterfaceMtu() const;
|
||||
|
||||
private:
|
||||
shared_ptr<boost::asio::posix::stream_descriptor> m_socket;
|
||||
std::string m_interfaceName;
|
||||
ethernet::Address m_srcAddress;
|
||||
ethernet::Address m_destAddress;
|
||||
size_t m_interfaceMtu;
|
||||
pcap_t* m_pcap;
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_ETHERNET_FACE_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.
|
||||
@@ -24,72 +24,61 @@
|
||||
*/
|
||||
|
||||
#include "ethernet-factory.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
#include "core/network-interface.hpp"
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <pcap/pcap.h>
|
||||
#include "ethernet-transport.hpp"
|
||||
#include "generic-link-service.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("EthernetFactory");
|
||||
|
||||
shared_ptr<EthernetFace>
|
||||
EthernetFactory::createMulticastFace(const shared_ptr<NetworkInterfaceInfo> &interface,
|
||||
const ethernet::Address &address)
|
||||
shared_ptr<Face>
|
||||
EthernetFactory::createMulticastFace(const NetworkInterfaceInfo& interface,
|
||||
const ethernet::Address& address)
|
||||
{
|
||||
if (!address.isMulticast())
|
||||
throw Error(address.toString() + " is not a multicast address");
|
||||
BOOST_THROW_EXCEPTION(Error(address.toString() + " is not a multicast address"));
|
||||
|
||||
const std::string& name = interface->name;
|
||||
shared_ptr<EthernetFace> face = findMulticastFace(name, address);
|
||||
auto face = findMulticastFace(interface.name, address);
|
||||
if (face)
|
||||
return face;
|
||||
|
||||
shared_ptr<boost::asio::posix::stream_descriptor> socket =
|
||||
make_shared<boost::asio::posix::stream_descriptor>(ref(getGlobalIoService()));
|
||||
face::GenericLinkService::Options opts;
|
||||
opts.allowFragmentation = true;
|
||||
opts.allowReassembly = true;
|
||||
|
||||
face = make_shared<EthernetFace>(socket, interface, address);
|
||||
face->onFail += bind(&EthernetFactory::afterFaceFailed,
|
||||
this, name, address);
|
||||
m_multicastFaces[std::make_pair(name, address)] = face;
|
||||
auto linkService = make_unique<face::GenericLinkService>(opts);
|
||||
auto transport = make_unique<face::EthernetTransport>(interface, address);
|
||||
face = make_shared<Face>(std::move(linkService), std::move(transport));
|
||||
|
||||
auto key = std::make_pair(interface.name, address);
|
||||
m_multicastFaces[key] = face;
|
||||
connectFaceClosedSignal(*face, [this, key] { m_multicastFaces.erase(key); });
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetFactory::afterFaceFailed(const std::string& interfaceName,
|
||||
const ethernet::Address& address)
|
||||
EthernetFactory::createFace(const FaceUri& uri,
|
||||
ndn::nfd::FacePersistency persistency,
|
||||
const FaceCreatedCallback& onCreated,
|
||||
const FaceCreationFailedCallback& onConnectFailed)
|
||||
{
|
||||
NFD_LOG_DEBUG("afterFaceFailed: " << interfaceName << "/" << address);
|
||||
m_multicastFaces.erase(std::make_pair(interfaceName, address));
|
||||
BOOST_THROW_EXCEPTION(Error("EthernetFactory does not support 'createFace' operation"));
|
||||
}
|
||||
|
||||
shared_ptr<EthernetFace>
|
||||
std::vector<shared_ptr<const Channel>>
|
||||
EthernetFactory::getChannels() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
shared_ptr<Face>
|
||||
EthernetFactory::findMulticastFace(const std::string& interfaceName,
|
||||
const ethernet::Address& address) const
|
||||
{
|
||||
MulticastFaceMap::const_iterator i =
|
||||
m_multicastFaces.find(std::make_pair(interfaceName, address));
|
||||
auto i = m_multicastFaces.find({interfaceName, address});
|
||||
if (i != m_multicastFaces.end())
|
||||
return i->second;
|
||||
else
|
||||
return shared_ptr<EthernetFace>();
|
||||
}
|
||||
|
||||
void
|
||||
EthernetFactory::createFace(const FaceUri& uri,
|
||||
const FaceCreatedCallback& onCreated,
|
||||
const FaceConnectFailedCallback& onConnectFailed)
|
||||
{
|
||||
throw Error("EthernetFactory does not support 'createFace' operation");
|
||||
}
|
||||
|
||||
std::list<shared_ptr<const Channel> >
|
||||
EthernetFactory::getChannels() const
|
||||
{
|
||||
return std::list<shared_ptr<const Channel> >();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
@@ -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.
|
||||
@@ -21,18 +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/>.
|
||||
**/
|
||||
*/
|
||||
|
||||
#ifndef NFD_DAEMON_FACE_ETHERNET_FACTORY_HPP
|
||||
#define NFD_DAEMON_FACE_ETHERNET_FACTORY_HPP
|
||||
|
||||
#include "ethernet-face.hpp"
|
||||
#include "protocol-factory.hpp"
|
||||
#include "core/network-interface.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
class NetworkInterfaceInfo;
|
||||
|
||||
class EthernetFactory : public ProtocolFactory
|
||||
{
|
||||
public:
|
||||
@@ -49,14 +47,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map< std::pair<std::string, ethernet::Address>,
|
||||
shared_ptr<EthernetFace> > MulticastFaceMap;
|
||||
|
||||
// from ProtocolFactory
|
||||
virtual void
|
||||
createFace(const FaceUri& uri,
|
||||
const FaceCreatedCallback& onCreated,
|
||||
const FaceConnectFailedCallback& onConnectFailed);
|
||||
typedef std::map<std::pair<std::string, ethernet::Address>,
|
||||
shared_ptr<Face>> MulticastFaceMap;
|
||||
|
||||
/**
|
||||
* \brief Create an EthernetFace to communicate with the given multicast group
|
||||
@@ -71,10 +63,10 @@ public:
|
||||
* \returns always a valid shared pointer to an EthernetFace object,
|
||||
* an exception will be thrown if the creation fails
|
||||
*
|
||||
* \throws EthernetFactory::Error or EthernetFace::Error
|
||||
* \throws EthernetFactory::Error or EthernetTransport::Error
|
||||
*/
|
||||
shared_ptr<EthernetFace>
|
||||
createMulticastFace(const shared_ptr<NetworkInterfaceInfo>& interface,
|
||||
shared_ptr<Face>
|
||||
createMulticastFace(const NetworkInterfaceInfo& interface,
|
||||
const ethernet::Address& address);
|
||||
|
||||
/**
|
||||
@@ -83,23 +75,24 @@ public:
|
||||
const MulticastFaceMap&
|
||||
getMulticastFaces() const;
|
||||
|
||||
virtual std::list<shared_ptr<const Channel> >
|
||||
getChannels() const;
|
||||
public: // from ProtocolFactory
|
||||
virtual void
|
||||
createFace(const FaceUri& uri,
|
||||
ndn::nfd::FacePersistency persistency,
|
||||
const FaceCreatedCallback& onCreated,
|
||||
const FaceCreationFailedCallback& onConnectFailed) DECL_OVERRIDE;
|
||||
|
||||
virtual std::vector<shared_ptr<const Channel>>
|
||||
getChannels() const DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
void
|
||||
afterFaceFailed(const std::string& interfaceName,
|
||||
const ethernet::Address& address);
|
||||
|
||||
/**
|
||||
* \brief Look up EthernetFace using specified interface and address
|
||||
*
|
||||
* \returns shared pointer to the existing EthernetFace object or
|
||||
* empty shared pointer when such face does not exist
|
||||
*
|
||||
* \throws never
|
||||
* \returns shared pointer to the existing EthernetFace object
|
||||
* or nullptr when such face does not exist
|
||||
*/
|
||||
shared_ptr<EthernetFace>
|
||||
shared_ptr<Face>
|
||||
findMulticastFace(const std::string& interfaceName,
|
||||
const ethernet::Address& address) const;
|
||||
|
||||
@@ -107,14 +100,12 @@ private:
|
||||
MulticastFaceMap m_multicastFaces;
|
||||
};
|
||||
|
||||
|
||||
inline const EthernetFactory::MulticastFaceMap&
|
||||
EthernetFactory::getMulticastFaces() const
|
||||
{
|
||||
return m_multicastFaces;
|
||||
}
|
||||
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_ETHERNET_FACTORY_HPP
|
||||
@@ -0,0 +1,418 @@
|
||||
/* -*- 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 "ethernet-transport.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
|
||||
#include <pcap/pcap.h>
|
||||
|
||||
#include <cerrno> // for errno
|
||||
#include <cstring> // for memcpy(), strerror(), strncpy()
|
||||
#include <arpa/inet.h> // for htons() and ntohs()
|
||||
#include <net/ethernet.h> // for struct ether_header
|
||||
#include <net/if.h> // for struct ifreq
|
||||
#include <stdio.h> // for snprintf()
|
||||
#include <sys/ioctl.h> // for ioctl()
|
||||
#include <unistd.h> // for dup()
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <netpacket/packet.h> // for struct packet_mreq
|
||||
#include <sys/socket.h> // for setsockopt()
|
||||
#endif
|
||||
|
||||
#ifdef SIOCADDMULTI
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
#include <net/if_dl.h> // for struct sockaddr_dl
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(PCAP_NETMASK_UNKNOWN)
|
||||
/*
|
||||
* Value to pass to pcap_compile() as the netmask if you don't know what
|
||||
* the netmask is.
|
||||
*/
|
||||
#define PCAP_NETMASK_UNKNOWN 0xffffffff
|
||||
#endif
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
NFD_LOG_INIT("EthernetTransport");
|
||||
|
||||
EthernetTransport::EthernetTransport(const NetworkInterfaceInfo& interface,
|
||||
const ethernet::Address& mcastAddress)
|
||||
: m_pcap(nullptr, pcap_close)
|
||||
, m_socket(getGlobalIoService())
|
||||
, m_srcAddress(interface.etherAddress)
|
||||
, m_destAddress(mcastAddress)
|
||||
, m_interfaceName(interface.name)
|
||||
#if defined(__linux__)
|
||||
, m_interfaceIndex(interface.index)
|
||||
#endif
|
||||
#ifdef _DEBUG
|
||||
, m_nDropped(0)
|
||||
#endif
|
||||
{
|
||||
this->setLocalUri(FaceUri::fromDev(interface.name));
|
||||
this->setRemoteUri(FaceUri(mcastAddress));
|
||||
this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
|
||||
this->setPersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
|
||||
this->setLinkType(ndn::nfd::LINK_TYPE_MULTI_ACCESS);
|
||||
|
||||
NFD_LOG_FACE_INFO("Creating transport");
|
||||
|
||||
pcapInit();
|
||||
|
||||
int fd = pcap_get_selectable_fd(m_pcap.get());
|
||||
if (fd < 0)
|
||||
BOOST_THROW_EXCEPTION(Error("pcap_get_selectable_fd failed"));
|
||||
|
||||
// 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));
|
||||
|
||||
// do this after assigning m_socket because getInterfaceMtu uses it
|
||||
this->setMtu(getInterfaceMtu());
|
||||
|
||||
char filter[110];
|
||||
// note #1: we cannot use std::snprintf because it's not available
|
||||
// on some platforms (see #2299)
|
||||
// note #2: "not vlan" must appear last in the filter expression, or the
|
||||
// rest of the filter won't work as intended (see pcap-filter(7))
|
||||
snprintf(filter, sizeof(filter),
|
||||
"(ether proto 0x%x) && (ether dst %s) && (not ether src %s) && (not vlan)",
|
||||
ethernet::ETHERTYPE_NDN,
|
||||
m_destAddress.toString().c_str(),
|
||||
m_srcAddress.toString().c_str());
|
||||
setPacketFilter(filter);
|
||||
|
||||
if (!m_destAddress.isBroadcast() && !joinMulticastGroup()) {
|
||||
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(&EthernetTransport::handleRead, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void EthernetTransport::beforeChangePersistency(ndn::nfd::FacePersistency newPersistency)
|
||||
{
|
||||
if (newPersistency != ndn::nfd::FACE_PERSISTENCY_PERMANENT) {
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("EthernetTransport supports only FACE_PERSISTENCY_PERMANENT"));
|
||||
}
|
||||
}
|
||||
|
||||
void EthernetTransport::doSend(Transport::Packet&& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
sendPacket(packet.packet);
|
||||
}
|
||||
|
||||
void EthernetTransport::doClose()
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
if (m_socket.is_open()) {
|
||||
// Cancel all outstanding operations and close the socket.
|
||||
// Use the non-throwing variants and ignore errors, if any.
|
||||
boost::system::error_code error;
|
||||
m_socket.cancel(error);
|
||||
m_socket.close(error);
|
||||
}
|
||||
m_pcap.reset();
|
||||
|
||||
// Ensure that the Transport stays alive at least
|
||||
// until all pending handlers are dispatched
|
||||
getGlobalIoService().post([this] {
|
||||
this->setState(TransportState::CLOSED);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
EthernetTransport::pcapInit()
|
||||
{
|
||||
char errbuf[PCAP_ERRBUF_SIZE] = {};
|
||||
m_pcap.reset(pcap_create(m_interfaceName.c_str(), errbuf));
|
||||
if (!m_pcap)
|
||||
BOOST_THROW_EXCEPTION(Error("pcap_create: " + std::string(errbuf)));
|
||||
|
||||
#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
|
||||
// Enable "immediate mode", effectively disabling any read buffering in the kernel.
|
||||
// This corresponds to the BIOCIMMEDIATE ioctl on BSD-like systems (including OS X)
|
||||
// where libpcap uses a BPF device. On Linux this forces libpcap not to use TPACKET_V3,
|
||||
// even if the kernel supports it, thus preventing bug #1511.
|
||||
pcap_set_immediate_mode(m_pcap.get(), 1);
|
||||
#endif
|
||||
|
||||
if (pcap_activate(m_pcap.get()) < 0)
|
||||
BOOST_THROW_EXCEPTION(Error("pcap_activate failed"));
|
||||
|
||||
if (pcap_set_datalink(m_pcap.get(), DLT_EN10MB) < 0)
|
||||
BOOST_THROW_EXCEPTION(Error("pcap_set_datalink: " + std::string(pcap_geterr(m_pcap.get()))));
|
||||
|
||||
if (pcap_setdirection(m_pcap.get(), PCAP_D_IN) < 0)
|
||||
// no need to throw on failure, BPF will filter unwanted packets anyway
|
||||
NFD_LOG_FACE_WARN("pcap_setdirection failed: " << pcap_geterr(m_pcap.get()));
|
||||
}
|
||||
|
||||
void
|
||||
EthernetTransport::setPacketFilter(const char* filterString)
|
||||
{
|
||||
bpf_program filter;
|
||||
if (pcap_compile(m_pcap.get(), &filter, filterString, 1, PCAP_NETMASK_UNKNOWN) < 0)
|
||||
BOOST_THROW_EXCEPTION(Error("pcap_compile: " + std::string(pcap_geterr(m_pcap.get()))));
|
||||
|
||||
int ret = pcap_setfilter(m_pcap.get(), &filter);
|
||||
pcap_freecode(&filter);
|
||||
if (ret < 0)
|
||||
BOOST_THROW_EXCEPTION(Error("pcap_setfilter: " + std::string(pcap_geterr(m_pcap.get()))));
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetTransport::joinMulticastGroup()
|
||||
{
|
||||
#if defined(__linux__)
|
||||
packet_mreq mr{};
|
||||
mr.mr_ifindex = m_interfaceIndex;
|
||||
mr.mr_type = PACKET_MR_MULTICAST;
|
||||
mr.mr_alen = m_destAddress.size();
|
||||
std::memcpy(mr.mr_address, m_destAddress.data(), m_destAddress.size());
|
||||
|
||||
if (::setsockopt(m_socket.native_handle(), SOL_PACKET,
|
||||
PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == 0)
|
||||
return true; // success
|
||||
|
||||
NFD_LOG_FACE_WARN("setsockopt(PACKET_ADD_MEMBERSHIP) failed: " << std::strerror(errno));
|
||||
#endif
|
||||
|
||||
#if defined(SIOCADDMULTI)
|
||||
ifreq ifr{};
|
||||
std::strncpy(ifr.ifr_name, m_interfaceName.c_str(), sizeof(ifr.ifr_name) - 1);
|
||||
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
// see bug #2327
|
||||
using boost::asio::ip::udp;
|
||||
udp::socket sock(getGlobalIoService(), udp::v4());
|
||||
int fd = sock.native_handle();
|
||||
|
||||
/*
|
||||
* Differences between Linux and the BSDs (including OS X):
|
||||
* o BSD does not have ifr_hwaddr; use ifr_addr instead.
|
||||
* o While OS X seems to accept both AF_LINK and AF_UNSPEC as the address
|
||||
* family, FreeBSD explicitly requires AF_LINK, so we have to use AF_LINK
|
||||
* and sockaddr_dl instead of the generic sockaddr structure.
|
||||
* o BSD's sockaddr (and sockaddr_dl in particular) contains an additional
|
||||
* field, sa_len (sdl_len), which must be set to the total length of the
|
||||
* structure, including the length field itself.
|
||||
* o We do not specify the interface name, thus sdl_nlen is left at 0 and
|
||||
* LLADDR is effectively the same as sdl_data.
|
||||
*/
|
||||
sockaddr_dl* sdl = reinterpret_cast<sockaddr_dl*>(&ifr.ifr_addr);
|
||||
sdl->sdl_len = sizeof(ifr.ifr_addr);
|
||||
sdl->sdl_family = AF_LINK;
|
||||
sdl->sdl_alen = m_destAddress.size();
|
||||
std::memcpy(LLADDR(sdl), m_destAddress.data(), m_destAddress.size());
|
||||
|
||||
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();
|
||||
|
||||
ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
|
||||
std::memcpy(ifr.ifr_hwaddr.sa_data, m_destAddress.data(), m_destAddress.size());
|
||||
|
||||
static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= ethernet::ADDR_LEN,
|
||||
"ifr_hwaddr in struct ifreq is too small on this platform");
|
||||
#endif
|
||||
|
||||
if (::ioctl(fd, SIOCADDMULTI, &ifr) == 0)
|
||||
return true; // success
|
||||
|
||||
NFD_LOG_FACE_WARN("ioctl(SIOCADDMULTI) failed: " << std::strerror(errno));
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetTransport::sendPacket(const ndn::Block& block)
|
||||
{
|
||||
/// \todo Right now there is no reserve when packet is received, but
|
||||
/// we should reserve some space at the beginning and at the end
|
||||
ndn::EncodingBuffer buffer(block);
|
||||
|
||||
// pad with zeroes if the payload is too short
|
||||
if (block.size() < ethernet::MIN_DATA_LEN) {
|
||||
static const uint8_t padding[ethernet::MIN_DATA_LEN] = {};
|
||||
buffer.appendByteArray(padding, ethernet::MIN_DATA_LEN - block.size());
|
||||
}
|
||||
|
||||
// construct and prepend the ethernet header
|
||||
static uint16_t ethertype = htons(ethernet::ETHERTYPE_NDN);
|
||||
buffer.prependByteArray(reinterpret_cast<const uint8_t*>(ðertype), ethernet::TYPE_LEN);
|
||||
buffer.prependByteArray(m_srcAddress.data(), m_srcAddress.size());
|
||||
buffer.prependByteArray(m_destAddress.data(), m_destAddress.size());
|
||||
|
||||
// send the packet
|
||||
int sent = pcap_inject(m_pcap.get(), buffer.buf(), buffer.size());
|
||||
if (sent < 0)
|
||||
NFD_LOG_FACE_ERROR("pcap_inject failed: " << pcap_geterr(m_pcap.get()));
|
||||
else if (static_cast<size_t>(sent) < buffer.size())
|
||||
NFD_LOG_FACE_ERROR("Failed to send the full frame: bufsize=" << buffer.size() << " sent=" << sent);
|
||||
else
|
||||
// print block size because we don't want to count the padding in buffer
|
||||
NFD_LOG_FACE_TRACE("Successfully sent: " << block.size() << " bytes");
|
||||
}
|
||||
|
||||
void
|
||||
EthernetTransport::handleRead(const boost::system::error_code& error, size_t)
|
||||
{
|
||||
if (error)
|
||||
return processErrorCode(error);
|
||||
|
||||
pcap_pkthdr* header;
|
||||
const uint8_t* packet;
|
||||
|
||||
// read the pcap header and packet data
|
||||
int ret = pcap_next_ex(m_pcap.get(), &header, &packet);
|
||||
if (ret < 0)
|
||||
NFD_LOG_FACE_ERROR("pcap_next_ex failed: " << pcap_geterr(m_pcap.get()));
|
||||
else if (ret == 0)
|
||||
NFD_LOG_FACE_WARN("Read timeout");
|
||||
else
|
||||
processIncomingPacket(header, packet);
|
||||
|
||||
#ifdef _DEBUG
|
||||
pcap_stat ps{};
|
||||
ret = pcap_stats(m_pcap.get(), &ps);
|
||||
if (ret < 0) {
|
||||
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_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(&EthernetTransport::handleRead, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void
|
||||
EthernetTransport::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_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);
|
||||
|
||||
// in some cases VLAN-tagged frames may survive the BPF filter,
|
||||
// make sure we do not process those frames (see #3348)
|
||||
if (ntohs(eh->ether_type) != ethernet::ETHERTYPE_NDN)
|
||||
return;
|
||||
|
||||
// check that our BPF filter is working correctly
|
||||
BOOST_ASSERT_MSG(ethernet::Address(eh->ether_dhost) == m_destAddress,
|
||||
"Received frame addressed to a different multicast group");
|
||||
BOOST_ASSERT_MSG(sourceAddress != m_srcAddress,
|
||||
"Received frame sent by this host");
|
||||
|
||||
packet += ethernet::HDR_LEN;
|
||||
length -= ethernet::HDR_LEN;
|
||||
|
||||
bool isOk = false;
|
||||
Block element;
|
||||
std::tie(isOk, element) = Block::fromBuffer(packet, length);
|
||||
if (!isOk) {
|
||||
NFD_LOG_FACE_WARN("Received invalid packet from " << sourceAddress.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
NFD_LOG_FACE_TRACE("Received: " << element.size() << " bytes from " << sourceAddress.toString());
|
||||
|
||||
Transport::Packet tp(std::move(element));
|
||||
static_assert(sizeof(tp.remoteEndpoint) >= ethernet::ADDR_LEN,
|
||||
"Transport::Packet::remoteEndpoint is too small");
|
||||
std::memcpy(&tp.remoteEndpoint, sourceAddress.data(), sourceAddress.size());
|
||||
this->receive(std::move(tp));
|
||||
}
|
||||
|
||||
void
|
||||
EthernetTransport::processErrorCode(const boost::system::error_code& error)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
if (getState() == TransportState::CLOSING ||
|
||||
getState() == TransportState::FAILED ||
|
||||
getState() == TransportState::CLOSED ||
|
||||
error == boost::asio::error::operation_aborted)
|
||||
// transport is shutting down, ignore any errors
|
||||
return;
|
||||
|
||||
NFD_LOG_FACE_WARN("Receive operation failed: " << error.message());
|
||||
}
|
||||
|
||||
size_t
|
||||
EthernetTransport::getInterfaceMtu()
|
||||
{
|
||||
#ifdef SIOCGIFMTU
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
// see bug #2328
|
||||
using boost::asio::ip::udp;
|
||||
udp::socket sock(getGlobalIoService(), udp::v4());
|
||||
int fd = sock.native_handle();
|
||||
#else
|
||||
int fd = m_socket.native_handle();
|
||||
#endif
|
||||
|
||||
ifreq ifr{};
|
||||
std::strncpy(ifr.ifr_name, m_interfaceName.c_str(), sizeof(ifr.ifr_name) - 1);
|
||||
|
||||
if (::ioctl(fd, SIOCGIFMTU, &ifr) == 0) {
|
||||
NFD_LOG_FACE_DEBUG("Interface MTU is " << ifr.ifr_mtu);
|
||||
return static_cast<size_t>(ifr.ifr_mtu);
|
||||
}
|
||||
|
||||
NFD_LOG_FACE_WARN("Failed to get interface MTU: " << std::strerror(errno));
|
||||
#endif
|
||||
|
||||
NFD_LOG_FACE_DEBUG("Assuming default MTU of " << ethernet::MAX_DATA_LEN);
|
||||
return ethernet::MAX_DATA_LEN;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,155 @@
|
||||
/* -*- 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_FACE_ETHERNET_TRANSPORT_HPP
|
||||
#define NFD_DAEMON_FACE_ETHERNET_TRANSPORT_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
#include "transport.hpp"
|
||||
#include "core/network-interface.hpp"
|
||||
|
||||
#ifndef HAVE_LIBPCAP
|
||||
#error "Cannot include this file when libpcap is not available"
|
||||
#endif
|
||||
|
||||
// forward declarations
|
||||
struct pcap;
|
||||
typedef pcap pcap_t;
|
||||
struct pcap_pkthdr;
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
/**
|
||||
* \brief A multicast Transport that uses raw Ethernet II frames
|
||||
*/
|
||||
class EthernetTransport DECL_CLASS_FINAL : public Transport
|
||||
{
|
||||
public:
|
||||
class Error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
Error(const std::string& what)
|
||||
: std::runtime_error(what)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates an Ethernet-based transport for multicast communication
|
||||
*/
|
||||
EthernetTransport(const NetworkInterfaceInfo& interface,
|
||||
const ethernet::Address& mcastAddress);
|
||||
|
||||
protected:
|
||||
virtual void
|
||||
beforeChangePersistency(ndn::nfd::FacePersistency newPersistency) DECL_FINAL;
|
||||
|
||||
virtual void
|
||||
doClose() DECL_FINAL;
|
||||
|
||||
private:
|
||||
virtual void
|
||||
doSend(Transport::Packet&& packet) DECL_FINAL;
|
||||
|
||||
/**
|
||||
* @brief Allocates and initializes a libpcap context for live capture
|
||||
*/
|
||||
void
|
||||
pcapInit();
|
||||
|
||||
/**
|
||||
* @brief Installs a BPF filter on the receiving socket
|
||||
*
|
||||
* @param filterString string containing the source BPF program
|
||||
*/
|
||||
void
|
||||
setPacketFilter(const char* filterString);
|
||||
|
||||
/**
|
||||
* @brief Enables receiving frames addressed to our MAC multicast group
|
||||
*
|
||||
* @return true if successful, false otherwise
|
||||
*/
|
||||
bool
|
||||
joinMulticastGroup();
|
||||
|
||||
/**
|
||||
* @brief Sends the specified TLV block on the network wrapped in an Ethernet frame
|
||||
*/
|
||||
void
|
||||
sendPacket(const ndn::Block& block);
|
||||
|
||||
/**
|
||||
* @brief Receive callback
|
||||
*/
|
||||
void
|
||||
handleRead(const boost::system::error_code& error, size_t nBytesRead);
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
/**
|
||||
* @brief Processes an incoming frame as captured by libpcap
|
||||
*
|
||||
* @param header pointer to capture metadata
|
||||
* @param packet pointer to the received frame, including the link-layer header
|
||||
*/
|
||||
void
|
||||
processIncomingPacket(const pcap_pkthdr* header, const uint8_t* packet);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Handles errors encountered by Boost.Asio on the receive path
|
||||
*/
|
||||
void
|
||||
processErrorCode(const boost::system::error_code& error);
|
||||
|
||||
/**
|
||||
* @brief Returns the MTU of the underlying network interface
|
||||
*/
|
||||
size_t
|
||||
getInterfaceMtu();
|
||||
|
||||
private:
|
||||
unique_ptr<pcap_t, void(*)(pcap_t*)> m_pcap;
|
||||
boost::asio::posix::stream_descriptor m_socket;
|
||||
|
||||
ethernet::Address m_srcAddress;
|
||||
ethernet::Address m_destAddress;
|
||||
std::string m_interfaceName;
|
||||
#if defined(__linux__)
|
||||
int m_interfaceIndex;
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
/// number of packets dropped by the kernel, as reported by libpcap
|
||||
unsigned int m_nDropped;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_ETHERNET_TRANSPORT_HPP
|
||||
@@ -0,0 +1,49 @@
|
||||
/* -*- 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 "face-counters.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
FaceCounters::FaceCounters(const LinkService::Counters& linkServiceCounters,
|
||||
const Transport::Counters& transportCounters)
|
||||
: nInInterests(linkServiceCounters.nInInterests)
|
||||
, nOutInterests(linkServiceCounters.nOutInterests)
|
||||
, nInData(linkServiceCounters.nInData)
|
||||
, nOutData(linkServiceCounters.nOutData)
|
||||
, nInNacks(linkServiceCounters.nInNacks)
|
||||
, nOutNacks(linkServiceCounters.nOutNacks)
|
||||
, nInPackets(transportCounters.nInPackets)
|
||||
, nOutPackets(transportCounters.nOutPackets)
|
||||
, nInBytes(transportCounters.nInBytes)
|
||||
, nOutBytes(transportCounters.nOutBytes)
|
||||
, m_linkServiceCounters(linkServiceCounters)
|
||||
, m_transportCounters(transportCounters)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
+53
-213
@@ -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,226 +26,66 @@
|
||||
#ifndef NFD_DAEMON_FACE_FACE_COUNTERS_HPP
|
||||
#define NFD_DAEMON_FACE_FACE_COUNTERS_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
#include "link-service.hpp"
|
||||
#include "transport.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
/** \brief represents a counter of number of packets
|
||||
/** \brief gives access to counters provided by Face
|
||||
*
|
||||
* This type is a facade that exposes common counters of a Face.
|
||||
*
|
||||
* get<T>() can be used to access extended counters provided by
|
||||
* LinkService or Transport of the Face.
|
||||
*/
|
||||
// PacketCounter is noncopyable, because increment should be called on the counter,
|
||||
// not a copy of it; it's implicitly convertible to uint64_t to be observed
|
||||
class PacketCounter : noncopyable
|
||||
class FaceCounters
|
||||
{
|
||||
public:
|
||||
typedef uint64_t rep;
|
||||
FaceCounters(const LinkService::Counters& linkServiceCounters,
|
||||
const Transport::Counters& transportCounters);
|
||||
|
||||
PacketCounter()
|
||||
: m_value(0)
|
||||
{
|
||||
}
|
||||
|
||||
operator rep() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
PacketCounter&
|
||||
operator++()
|
||||
{
|
||||
++m_value;
|
||||
return *this;
|
||||
}
|
||||
// postfix ++ operator is not provided because it's not needed
|
||||
|
||||
void
|
||||
set(rep value)
|
||||
{
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
private:
|
||||
rep m_value;
|
||||
};
|
||||
|
||||
/** \brief represents a counter of number of bytes
|
||||
*/
|
||||
// ByteCounter is noncopyable, because increment should be called on the counter,
|
||||
// not a copy of it; it's implicitly convertible to uint64_t to be observed
|
||||
class ByteCounter : noncopyable
|
||||
{
|
||||
public:
|
||||
typedef uint64_t rep;
|
||||
|
||||
ByteCounter()
|
||||
: m_value(0)
|
||||
{
|
||||
}
|
||||
|
||||
operator rep() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
ByteCounter&
|
||||
operator+=(rep n)
|
||||
{
|
||||
m_value += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
set(rep value)
|
||||
{
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
private:
|
||||
rep m_value;
|
||||
};
|
||||
|
||||
/** \brief contains network layer packet counters
|
||||
*/
|
||||
class NetworkLayerCounters : noncopyable
|
||||
{
|
||||
public:
|
||||
/// incoming Interest
|
||||
const PacketCounter&
|
||||
getNInInterests() const
|
||||
{
|
||||
return m_nInInterests;
|
||||
}
|
||||
|
||||
PacketCounter&
|
||||
getNInInterests()
|
||||
{
|
||||
return m_nInInterests;
|
||||
}
|
||||
|
||||
/// incoming Data
|
||||
const PacketCounter&
|
||||
getNInDatas() const
|
||||
{
|
||||
return m_nInDatas;
|
||||
}
|
||||
|
||||
PacketCounter&
|
||||
getNInDatas()
|
||||
{
|
||||
return m_nInDatas;
|
||||
}
|
||||
|
||||
/// outgoing Interest
|
||||
const PacketCounter&
|
||||
getNOutInterests() const
|
||||
{
|
||||
return m_nOutInterests;
|
||||
}
|
||||
|
||||
PacketCounter&
|
||||
getNOutInterests()
|
||||
{
|
||||
return m_nOutInterests;
|
||||
}
|
||||
|
||||
/// outgoing Data
|
||||
const PacketCounter&
|
||||
getNOutDatas() const
|
||||
{
|
||||
return m_nOutDatas;
|
||||
}
|
||||
|
||||
PacketCounter&
|
||||
getNOutDatas()
|
||||
{
|
||||
return m_nOutDatas;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** \brief copy current obseverations to a struct
|
||||
* \param recipient an object with set methods for counters
|
||||
/** \return counters provided by LinkService
|
||||
* \tparam T LinkService counters type
|
||||
* \throw std::bad_cast counters type mismatch
|
||||
*/
|
||||
template<typename R>
|
||||
void
|
||||
copyTo(R& recipient) const
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_base_of<LinkService::Counters, T>::value, const T&>::type
|
||||
get() const
|
||||
{
|
||||
recipient.setNInInterests(this->getNInInterests());
|
||||
recipient.setNInDatas(this->getNInDatas());
|
||||
recipient.setNOutInterests(this->getNOutInterests());
|
||||
recipient.setNOutDatas(this->getNOutDatas());
|
||||
return dynamic_cast<const T&>(m_linkServiceCounters);
|
||||
}
|
||||
|
||||
/** \return counters provided by Transport
|
||||
* \tparam T Transport counters type
|
||||
* \throw std::bad_cast counters type mismatch
|
||||
*/
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_base_of<Transport::Counters, T>::value, const T&>::type
|
||||
get() const
|
||||
{
|
||||
return dynamic_cast<const T&>(m_transportCounters);
|
||||
}
|
||||
|
||||
public:
|
||||
const PacketCounter& nInInterests;
|
||||
const PacketCounter& nOutInterests;
|
||||
const PacketCounter& nInData;
|
||||
const PacketCounter& nOutData;
|
||||
const PacketCounter& nInNacks;
|
||||
const PacketCounter& nOutNacks;
|
||||
|
||||
const PacketCounter& nInPackets;
|
||||
const PacketCounter& nOutPackets;
|
||||
const ByteCounter& nInBytes;
|
||||
const ByteCounter& nOutBytes;
|
||||
|
||||
private:
|
||||
PacketCounter m_nInInterests;
|
||||
PacketCounter m_nInDatas;
|
||||
PacketCounter m_nOutInterests;
|
||||
PacketCounter m_nOutDatas;
|
||||
};
|
||||
|
||||
/** \brief contains link layer byte counters
|
||||
*/
|
||||
class LinkLayerCounters : noncopyable
|
||||
{
|
||||
public:
|
||||
/// received bytes
|
||||
const ByteCounter&
|
||||
getNInBytes() const
|
||||
{
|
||||
return m_nInBytes;
|
||||
}
|
||||
|
||||
ByteCounter&
|
||||
getNInBytes()
|
||||
{
|
||||
return m_nInBytes;
|
||||
}
|
||||
|
||||
/// sent bytes
|
||||
const ByteCounter&
|
||||
getNOutBytes() const
|
||||
{
|
||||
return m_nOutBytes;
|
||||
}
|
||||
|
||||
ByteCounter&
|
||||
getNOutBytes()
|
||||
{
|
||||
return m_nOutBytes;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** \brief copy current obseverations to a struct
|
||||
* \param recipient an object with set methods for counters
|
||||
*/
|
||||
template<typename R>
|
||||
void
|
||||
copyTo(R& recipient) const
|
||||
{
|
||||
recipient.setNInBytes(this->getNInBytes());
|
||||
recipient.setNOutBytes(this->getNOutBytes());
|
||||
}
|
||||
|
||||
private:
|
||||
ByteCounter m_nInBytes;
|
||||
ByteCounter m_nOutBytes;
|
||||
};
|
||||
|
||||
/** \brief contains counters on face
|
||||
*/
|
||||
class FaceCounters : public NetworkLayerCounters, public LinkLayerCounters
|
||||
{
|
||||
public:
|
||||
/** \brief copy current obseverations to a struct
|
||||
* \param recipient an object with set methods for counters
|
||||
*/
|
||||
template<typename R>
|
||||
void
|
||||
copyTo(R& recipient) const
|
||||
{
|
||||
this->NetworkLayerCounters::copyTo(recipient);
|
||||
this->LinkLayerCounters::copyTo(recipient);
|
||||
}
|
||||
const LinkService::Counters& m_linkServiceCounters;
|
||||
const Transport::Counters& m_transportCounters;
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_FACE_COUNTERS_HPP
|
||||
@@ -0,0 +1,93 @@
|
||||
/* -*- 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_FACE_FACE_LOG_HPP
|
||||
#define NFD_DAEMON_FACE_FACE_LOG_HPP
|
||||
|
||||
#include "core/logger.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
/** \brief for internal use by FaceLogging macros
|
||||
*
|
||||
* FaceLogHelper wraps a Face, LinkService, or Transport object.
|
||||
*
|
||||
* std::ostream& operator<<(std::ostream& os, const FaceLogHelper<T>& flh)
|
||||
* should be specialized to print "[id=888,local=scheme://local/uri,remote=scheme://remote/uri] "
|
||||
* which appears as part of the log message.
|
||||
*/
|
||||
template<typename T>
|
||||
class FaceLogHelper
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
FaceLogHelper(const T& obj1)
|
||||
: obj(obj1)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
const T& obj;
|
||||
};
|
||||
|
||||
/** \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, LinkService, Transport subclasses.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define NFD_LOG_FACE(level, msg) NFD_LOG_##level( \
|
||||
::nfd::face::FaceLogHelper< \
|
||||
typename std::remove_cv< \
|
||||
typename std::remove_reference<decltype(*this)>::type \
|
||||
>::type \
|
||||
>(*this) \
|
||||
<< 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 face
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_FACE_LOG_HPP
|
||||
+27
-115
@@ -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,120 +24,32 @@
|
||||
*/
|
||||
|
||||
#include "face.hpp"
|
||||
#include "face-flags.hpp"
|
||||
#include "core/logger.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
Face::Face(const FaceUri& remoteUri, const FaceUri& localUri, bool isLocal)
|
||||
: m_id(INVALID_FACEID)
|
||||
, m_isLocal(isLocal)
|
||||
, m_remoteUri(remoteUri)
|
||||
, m_localUri(localUri)
|
||||
, m_isOnDemand(false)
|
||||
, m_isFailed(false)
|
||||
Face::Face(unique_ptr<LinkService> service, unique_ptr<Transport> transport)
|
||||
: afterReceiveInterest(service->afterReceiveInterest)
|
||||
, afterReceiveData(service->afterReceiveData)
|
||||
, afterReceiveNack(service->afterReceiveNack)
|
||||
, afterStateChange(transport->afterStateChange)
|
||||
, m_id(INVALID_FACEID)
|
||||
, m_service(std::move(service))
|
||||
, m_transport(std::move(transport))
|
||||
, m_counters(m_service->getCounters(), m_transport->getCounters())
|
||||
{
|
||||
onReceiveInterest += bind(&PacketCounter::operator++, &m_counters.getNInInterests());
|
||||
onReceiveData += bind(&PacketCounter::operator++, &m_counters.getNInDatas());
|
||||
onSendInterest += bind(&PacketCounter::operator++, &m_counters.getNOutInterests());
|
||||
onSendData += bind(&PacketCounter::operator++, &m_counters.getNOutDatas());
|
||||
m_service->setFaceAndTransport(*this, *m_transport);
|
||||
m_transport->setFaceAndLinkService(*this, *m_service);
|
||||
}
|
||||
|
||||
Face::~Face()
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceLogHelper<Face>& flh)
|
||||
{
|
||||
const Face& face = flh.obj;
|
||||
os << "[id=" << face.getId() << ",local=" << face.getLocalUri() <<
|
||||
",remote=" << face.getRemoteUri() << "] ";
|
||||
return os;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Face::decodeAndDispatchInput(const Block& element)
|
||||
{
|
||||
try {
|
||||
/// \todo Ensure lazy field decoding process
|
||||
|
||||
if (element.type() == tlv::Interest)
|
||||
{
|
||||
shared_ptr<Interest> i = make_shared<Interest>();
|
||||
i->wireDecode(element);
|
||||
this->onReceiveInterest(*i);
|
||||
}
|
||||
else if (element.type() == tlv::Data)
|
||||
{
|
||||
shared_ptr<Data> d = make_shared<Data>();
|
||||
d->wireDecode(element);
|
||||
this->onReceiveData(*d);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (tlv::Error&) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Face::fail(const std::string& reason)
|
||||
{
|
||||
if (m_isFailed) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_isFailed = true;
|
||||
this->onFail(reason);
|
||||
|
||||
this->onFail.clear();
|
||||
}
|
||||
|
||||
ndn::nfd::FaceStatus
|
||||
Face::getFaceStatus() const
|
||||
{
|
||||
ndn::nfd::FaceStatus status;
|
||||
status.setFaceId(getId())
|
||||
.setRemoteUri(getRemoteUri().toString())
|
||||
.setLocalUri(getLocalUri().toString())
|
||||
.setFlags(getFaceFlags(*this));
|
||||
|
||||
this->getCounters().copyTo(status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
} //namespace nfd
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
+238
-178
@@ -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,190 +23,265 @@
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NFD_DAEMON_FACE_FACE_HPP
|
||||
#define NFD_DAEMON_FACE_FACE_HPP
|
||||
#ifndef NFD_DAEMON_FACE_HPP
|
||||
#define NFD_DAEMON_FACE_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
#include "core/event-emitter.hpp"
|
||||
#include "core/face-uri.hpp"
|
||||
#include "transport.hpp"
|
||||
#include "link-service.hpp"
|
||||
#include "face-counters.hpp"
|
||||
|
||||
#include <ndn-cxx/management/nfd-face-status.hpp>
|
||||
#include "face-log.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
/** \class FaceId
|
||||
* \brief identifies a face
|
||||
/** \brief identifies a face
|
||||
*/
|
||||
typedef int FaceId;
|
||||
typedef uint64_t FaceId;
|
||||
|
||||
/// indicates an invalid FaceId
|
||||
const FaceId INVALID_FACEID = -1;
|
||||
|
||||
const FaceId INVALID_FACEID = 0;
|
||||
/// identifies the InternalFace used in management
|
||||
const FaceId FACEID_INTERNAL_FACE = 1;
|
||||
/// identifies a packet comes from the ContentStore, in LocalControlHeader incomingFaceId
|
||||
/// identifies a packet comes from the ContentStore
|
||||
const FaceId FACEID_CONTENT_STORE = 254;
|
||||
/// identifies the NullFace that drops every packet
|
||||
const FaceId FACEID_NULL = 255;
|
||||
/// upper bound of reserved FaceIds
|
||||
const FaceId FACEID_RESERVED_MAX = 255;
|
||||
|
||||
|
||||
/// pratical limit of packet size in octets
|
||||
const size_t MAX_NDN_PACKET_SIZE = 8800;
|
||||
|
||||
|
||||
/** \brief represents a face
|
||||
/** \brief indicates the state of a face
|
||||
*/
|
||||
class Face : noncopyable, public enable_shared_from_this<Face>
|
||||
typedef TransportState FaceState;
|
||||
|
||||
/** \brief generalization of a network interface
|
||||
*
|
||||
* A face generalizes a network interface.
|
||||
* It provides best-effort network-layer packet delivery services
|
||||
* on a physical interface, an overlay tunnel, or a link to a local application.
|
||||
*
|
||||
* A face combines two parts: LinkService and Transport.
|
||||
* Transport is the lower part, which provides best-effort TLV block deliveries.
|
||||
* LinkService is the upper part, which translates between network-layer packets
|
||||
* and TLV blocks, and may provide additional services such as fragmentation and reassembly.
|
||||
*/
|
||||
class Face
|
||||
#ifndef WITH_TESTS
|
||||
DECL_CLASS_FINAL
|
||||
#endif
|
||||
: public enable_shared_from_this<Face>, noncopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Face-related error
|
||||
Face(unique_ptr<LinkService> service, unique_ptr<Transport> transport);
|
||||
|
||||
LinkService*
|
||||
getLinkService();
|
||||
|
||||
Transport*
|
||||
getTransport();
|
||||
|
||||
public: // upper interface connected to forwarding
|
||||
/** \brief sends Interest on Face
|
||||
*/
|
||||
class Error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
Error(const std::string& what)
|
||||
: std::runtime_error(what)
|
||||
{
|
||||
}
|
||||
};
|
||||
void
|
||||
sendInterest(const Interest& interest);
|
||||
|
||||
Face(const FaceUri& remoteUri, const FaceUri& localUri, bool isLocal = false);
|
||||
|
||||
virtual
|
||||
~Face();
|
||||
|
||||
/// fires when an Interest is received
|
||||
EventEmitter<Interest> onReceiveInterest;
|
||||
|
||||
/// fires when a Data is received
|
||||
EventEmitter<Data> onReceiveData;
|
||||
|
||||
/// fires when an Interest is sent out
|
||||
EventEmitter<Interest> onSendInterest;
|
||||
|
||||
/// fires when a Data is sent out
|
||||
EventEmitter<Data> onSendData;
|
||||
|
||||
/// fires when face disconnects or fails to perform properly
|
||||
EventEmitter<std::string/*reason*/> onFail;
|
||||
|
||||
/// send an Interest
|
||||
virtual void
|
||||
sendInterest(const Interest& interest) = 0;
|
||||
|
||||
/// send a Data
|
||||
virtual void
|
||||
sendData(const Data& data) = 0;
|
||||
|
||||
/** \brief Close the face
|
||||
*
|
||||
* This terminates all communication on the face and cause
|
||||
* onFail() method event to be invoked
|
||||
/** \brief sends Data on Face
|
||||
*/
|
||||
virtual void
|
||||
close() = 0;
|
||||
void
|
||||
sendData(const Data& data);
|
||||
|
||||
public: // attributes
|
||||
/** \brief sends Nack on Face
|
||||
*/
|
||||
void
|
||||
sendNack(const lp::Nack& nack);
|
||||
|
||||
/** \brief signals on Interest received
|
||||
*/
|
||||
signal::Signal<LinkService, Interest>& afterReceiveInterest;
|
||||
|
||||
/** \brief signals on Data received
|
||||
*/
|
||||
signal::Signal<LinkService, Data>& afterReceiveData;
|
||||
|
||||
/** \brief signals on Nack received
|
||||
*/
|
||||
signal::Signal<LinkService, lp::Nack>& afterReceiveNack;
|
||||
|
||||
public: // static properties
|
||||
/** \return face ID
|
||||
*/
|
||||
FaceId
|
||||
getId() const;
|
||||
|
||||
/** \brief Set the description
|
||||
/** \brief sets face ID
|
||||
* \note Normally, this should only be invoked by FaceTable.
|
||||
*/
|
||||
void
|
||||
setId(FaceId id);
|
||||
|
||||
/** \return a FaceUri representing local endpoint
|
||||
*/
|
||||
FaceUri
|
||||
getLocalUri() const;
|
||||
|
||||
/** \return a FaceUri representing remote endpoint
|
||||
*/
|
||||
FaceUri
|
||||
getRemoteUri() const;
|
||||
|
||||
/** \return whether face is local or non-local for scope control purpose
|
||||
*/
|
||||
ndn::nfd::FaceScope
|
||||
getScope() const;
|
||||
|
||||
/** \return face persistency setting
|
||||
*/
|
||||
ndn::nfd::FacePersistency
|
||||
getPersistency() const;
|
||||
|
||||
/** \brief changes face persistency setting
|
||||
*/
|
||||
void
|
||||
setPersistency(ndn::nfd::FacePersistency persistency);
|
||||
|
||||
/** \return whether face is point-to-point or multi-access
|
||||
*/
|
||||
ndn::nfd::LinkType
|
||||
getLinkType() const;
|
||||
|
||||
public: // dynamic properties
|
||||
/** \return face state
|
||||
*/
|
||||
FaceState
|
||||
getState() const;
|
||||
|
||||
/** \brief signals after face state changed
|
||||
*/
|
||||
signal::Signal<Transport, FaceState/*old*/, FaceState/*new*/>& afterStateChange;
|
||||
|
||||
/** \return expiration time of the face
|
||||
* \retval time::steady_clock::TimePoint::max() the face has an indefinite lifetime
|
||||
*/
|
||||
time::steady_clock::TimePoint
|
||||
getExpirationTime() const;
|
||||
|
||||
/** \brief request the face to be closed
|
||||
*
|
||||
* This is typically invoked by mgmt on set description command
|
||||
*/
|
||||
virtual void
|
||||
setDescription(const std::string& description);
|
||||
|
||||
/// Get the description
|
||||
virtual const std::string&
|
||||
getDescription() const;
|
||||
|
||||
/** \brief Get whether face is connected to a local app
|
||||
*/
|
||||
bool
|
||||
isLocal() const;
|
||||
|
||||
/** \brief Get whether packets sent this Face may reach multiple peers
|
||||
* This operation is effective only if face is in UP or DOWN state,
|
||||
* otherwise it has no effect.
|
||||
* The face changes state to CLOSING, and performs cleanup procedure.
|
||||
* The state will be changed to CLOSED when cleanup is complete, which may
|
||||
* happen synchronously or asynchronously.
|
||||
*
|
||||
* In this base class this property is always false.
|
||||
* \warning the face must not be deallocated until its state changes to CLOSED
|
||||
*/
|
||||
virtual bool
|
||||
isMultiAccess() const;
|
||||
|
||||
/** \brief Get whether underlying communication is up
|
||||
*
|
||||
* In this base class this property is always true.
|
||||
*/
|
||||
virtual bool
|
||||
isUp() const;
|
||||
|
||||
/** \brief Get whether face is created on demand or explicitly via FaceManagement protocol
|
||||
*/
|
||||
bool
|
||||
isOnDemand() const;
|
||||
void
|
||||
close();
|
||||
|
||||
const FaceCounters&
|
||||
getCounters() const;
|
||||
|
||||
/** \return a FaceUri that represents the remote endpoint
|
||||
*/
|
||||
const FaceUri&
|
||||
getRemoteUri() const;
|
||||
|
||||
/** \return a FaceUri that represents the local endpoint (NFD side)
|
||||
*/
|
||||
const FaceUri&
|
||||
getLocalUri() const;
|
||||
|
||||
/** \return FaceStatus data structure filled with the current Face status
|
||||
*/
|
||||
virtual ndn::nfd::FaceStatus
|
||||
getFaceStatus() const;
|
||||
|
||||
protected:
|
||||
// this is a non-virtual method
|
||||
bool
|
||||
decodeAndDispatchInput(const Block& element);
|
||||
|
||||
FaceCounters&
|
||||
getMutableCounters();
|
||||
|
||||
void
|
||||
setOnDemand(bool isOnDemand);
|
||||
|
||||
/** \brief fail the face and raise onFail event if it's UP; otherwise do nothing
|
||||
*/
|
||||
void
|
||||
fail(const std::string& reason);
|
||||
|
||||
private:
|
||||
void
|
||||
setId(FaceId faceId);
|
||||
|
||||
private:
|
||||
FaceId m_id;
|
||||
std::string m_description;
|
||||
bool m_isLocal; // for scoping purposes
|
||||
unique_ptr<LinkService> m_service;
|
||||
unique_ptr<Transport> m_transport;
|
||||
FaceCounters m_counters;
|
||||
FaceUri m_remoteUri;
|
||||
FaceUri m_localUri;
|
||||
bool m_isOnDemand;
|
||||
bool m_isFailed;
|
||||
|
||||
// allow setting FaceId
|
||||
friend class FaceTable;
|
||||
};
|
||||
|
||||
|
||||
inline bool
|
||||
Face::isLocal() const
|
||||
inline LinkService*
|
||||
Face::getLinkService()
|
||||
{
|
||||
return m_isLocal;
|
||||
return m_service.get();
|
||||
}
|
||||
|
||||
inline Transport*
|
||||
Face::getTransport()
|
||||
{
|
||||
return m_transport.get();
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::sendInterest(const Interest& interest)
|
||||
{
|
||||
m_service->sendInterest(interest);
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::sendData(const Data& data)
|
||||
{
|
||||
m_service->sendData(data);
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::sendNack(const lp::Nack& nack)
|
||||
{
|
||||
m_service->sendNack(nack);
|
||||
}
|
||||
|
||||
inline FaceId
|
||||
Face::getId() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::setId(FaceId id)
|
||||
{
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
inline FaceUri
|
||||
Face::getLocalUri() const
|
||||
{
|
||||
return m_transport->getLocalUri();
|
||||
}
|
||||
|
||||
inline FaceUri
|
||||
Face::getRemoteUri() const
|
||||
{
|
||||
return m_transport->getRemoteUri();
|
||||
}
|
||||
|
||||
inline ndn::nfd::FaceScope
|
||||
Face::getScope() const
|
||||
{
|
||||
return m_transport->getScope();
|
||||
}
|
||||
|
||||
inline ndn::nfd::FacePersistency
|
||||
Face::getPersistency() const
|
||||
{
|
||||
return m_transport->getPersistency();
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::setPersistency(ndn::nfd::FacePersistency persistency)
|
||||
{
|
||||
return m_transport->setPersistency(persistency);
|
||||
}
|
||||
|
||||
inline ndn::nfd::LinkType
|
||||
Face::getLinkType() const
|
||||
{
|
||||
return m_transport->getLinkType();
|
||||
}
|
||||
|
||||
inline FaceState
|
||||
Face::getState() const
|
||||
{
|
||||
return m_transport->getState();
|
||||
}
|
||||
|
||||
inline time::steady_clock::TimePoint
|
||||
Face::getExpirationTime() const
|
||||
{
|
||||
return m_transport->getExpirationTime();
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::close()
|
||||
{
|
||||
m_transport->close();
|
||||
}
|
||||
|
||||
inline const FaceCounters&
|
||||
@@ -215,36 +290,21 @@ Face::getCounters() const
|
||||
return m_counters;
|
||||
}
|
||||
|
||||
inline FaceCounters&
|
||||
Face::getMutableCounters()
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceLogHelper<Face>& flh);
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_base_of<Face, T>::value, std::ostream&>::type
|
||||
operator<<(std::ostream& os, const FaceLogHelper<T>& flh)
|
||||
{
|
||||
return m_counters;
|
||||
return os << FaceLogHelper<Face>(flh.obj);
|
||||
}
|
||||
|
||||
inline const FaceUri&
|
||||
Face::getRemoteUri() const
|
||||
{
|
||||
return m_remoteUri;
|
||||
}
|
||||
} // namespace face
|
||||
|
||||
inline const FaceUri&
|
||||
Face::getLocalUri() const
|
||||
{
|
||||
return m_localUri;
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::setOnDemand(bool isOnDemand)
|
||||
{
|
||||
m_isOnDemand = isOnDemand;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Face::isOnDemand() const
|
||||
{
|
||||
return m_isOnDemand;
|
||||
}
|
||||
using face::FaceId;
|
||||
using face::Face;
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_FACE_HPP
|
||||
#endif // NFD_DAEMON_FACE_HPP
|
||||
@@ -0,0 +1,313 @@
|
||||
/* -*- 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 "generic-link-service.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
NFD_LOG_INIT("GenericLinkService");
|
||||
|
||||
GenericLinkServiceCounters::GenericLinkServiceCounters(const LpReassembler& reassembler)
|
||||
: nReassembling(reassembler)
|
||||
{
|
||||
}
|
||||
|
||||
GenericLinkService::Options::Options()
|
||||
: allowLocalFields(false)
|
||||
, allowFragmentation(false)
|
||||
, allowReassembly(false)
|
||||
{
|
||||
}
|
||||
|
||||
GenericLinkService::GenericLinkService(const GenericLinkService::Options& options)
|
||||
: GenericLinkServiceCounters(m_reassembler)
|
||||
, m_options(options)
|
||||
, m_fragmenter(m_options.fragmenterOptions, this)
|
||||
, m_reassembler(m_options.reassemblerOptions, this)
|
||||
, m_lastSeqNo(-2)
|
||||
{
|
||||
m_reassembler.beforeTimeout.connect(bind([this] { ++this->nReassemblyTimeouts; }));
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::doSendInterest(const Interest& interest)
|
||||
{
|
||||
lp::Packet lpPacket(interest.wireEncode());
|
||||
|
||||
if (m_options.allowLocalFields) {
|
||||
encodeLocalFields(interest, lpPacket);
|
||||
}
|
||||
|
||||
this->sendNetPacket(std::move(lpPacket));
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::doSendData(const Data& data)
|
||||
{
|
||||
lp::Packet lpPacket(data.wireEncode());
|
||||
|
||||
if (m_options.allowLocalFields) {
|
||||
encodeLocalFields(data, lpPacket);
|
||||
}
|
||||
|
||||
this->sendNetPacket(std::move(lpPacket));
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::doSendNack(const lp::Nack& nack)
|
||||
{
|
||||
lp::Packet lpPacket(nack.getInterest().wireEncode());
|
||||
lpPacket.add<lp::NackField>(nack.getHeader());
|
||||
|
||||
if (m_options.allowLocalFields) {
|
||||
encodeLocalFields(nack, lpPacket);
|
||||
}
|
||||
|
||||
this->sendNetPacket(std::move(lpPacket));
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::encodeLocalFields(const ndn::TagHost& netPkt, lp::Packet& lpPacket)
|
||||
{
|
||||
shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = netPkt.getTag<lp::IncomingFaceIdTag>();
|
||||
if (incomingFaceIdTag != nullptr) {
|
||||
lpPacket.add<lp::IncomingFaceIdField>(*incomingFaceIdTag);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::sendNetPacket(lp::Packet&& pkt)
|
||||
{
|
||||
std::vector<lp::Packet> frags;
|
||||
const ssize_t mtu = this->getTransport()->getMtu();
|
||||
if (m_options.allowFragmentation && mtu != MTU_UNLIMITED) {
|
||||
bool isOk = false;
|
||||
std::tie(isOk, frags) = m_fragmenter.fragmentPacket(pkt, mtu);
|
||||
if (!isOk) {
|
||||
// fragmentation failed (warning is logged by LpFragmenter)
|
||||
++this->nFragmentationErrors;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
frags.push_back(pkt);
|
||||
}
|
||||
|
||||
if (frags.size() > 1) {
|
||||
// sequence is needed only if packet is fragmented
|
||||
this->assignSequences(frags);
|
||||
}
|
||||
else {
|
||||
// even if indexed fragmentation is enabled, the fragmenter should not
|
||||
// fragment the packet if it can fit in MTU
|
||||
BOOST_ASSERT(frags.size() > 0);
|
||||
BOOST_ASSERT(!frags.front().has<lp::FragIndexField>());
|
||||
BOOST_ASSERT(!frags.front().has<lp::FragCountField>());
|
||||
}
|
||||
|
||||
for (const lp::Packet& frag : frags) {
|
||||
Transport::Packet tp(frag.wireEncode());
|
||||
if (mtu != MTU_UNLIMITED && tp.packet.size() > static_cast<size_t>(mtu)) {
|
||||
++this->nOutOverMtu;
|
||||
NFD_LOG_FACE_WARN("attempt to send packet over MTU limit");
|
||||
continue;
|
||||
}
|
||||
this->sendPacket(std::move(tp));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::assignSequence(lp::Packet& pkt)
|
||||
{
|
||||
pkt.set<lp::SequenceField>(++m_lastSeqNo);
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
|
||||
{
|
||||
std::for_each(pkts.begin(), pkts.end(), bind(&GenericLinkService::assignSequence, this, _1));
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::doReceivePacket(Transport::Packet&& packet)
|
||||
{
|
||||
try {
|
||||
lp::Packet pkt(packet.packet);
|
||||
|
||||
if (!pkt.has<lp::FragmentField>()) {
|
||||
NFD_LOG_FACE_TRACE("received IDLE packet: DROP");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((pkt.has<lp::FragIndexField>() || pkt.has<lp::FragCountField>()) &&
|
||||
!m_options.allowReassembly) {
|
||||
NFD_LOG_FACE_WARN("received fragment, but reassembly disabled: DROP");
|
||||
return;
|
||||
}
|
||||
|
||||
bool isReassembled = false;
|
||||
Block netPkt;
|
||||
lp::Packet firstPkt;
|
||||
std::tie(isReassembled, netPkt, firstPkt) = m_reassembler.receiveFragment(packet.remoteEndpoint,
|
||||
pkt);
|
||||
if (isReassembled) {
|
||||
this->decodeNetPacket(netPkt, firstPkt);
|
||||
}
|
||||
}
|
||||
catch (const tlv::Error& e) {
|
||||
++this->nInLpInvalid;
|
||||
NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::decodeNetPacket(const Block& netPkt, const lp::Packet& firstPkt)
|
||||
{
|
||||
try {
|
||||
switch (netPkt.type()) {
|
||||
case tlv::Interest:
|
||||
if (firstPkt.has<lp::NackField>()) {
|
||||
this->decodeNack(netPkt, firstPkt);
|
||||
}
|
||||
else {
|
||||
this->decodeInterest(netPkt, firstPkt);
|
||||
}
|
||||
break;
|
||||
case tlv::Data:
|
||||
this->decodeData(netPkt, firstPkt);
|
||||
break;
|
||||
default:
|
||||
++this->nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("unrecognized network-layer packet TLV-TYPE " << netPkt.type() << ": DROP");
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (const tlv::Error& e) {
|
||||
++this->nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstPkt)
|
||||
{
|
||||
BOOST_ASSERT(netPkt.type() == tlv::Interest);
|
||||
BOOST_ASSERT(!firstPkt.has<lp::NackField>());
|
||||
|
||||
// forwarding expects Interest to be created with make_shared
|
||||
auto interest = make_shared<Interest>(netPkt);
|
||||
|
||||
if (firstPkt.has<lp::NextHopFaceIdField>()) {
|
||||
if (m_options.allowLocalFields) {
|
||||
interest->setTag(make_shared<lp::NextHopFaceIdTag>(firstPkt.get<lp::NextHopFaceIdField>()));
|
||||
}
|
||||
else {
|
||||
NFD_LOG_FACE_WARN("received NextHopFaceId, but local fields disabled: DROP");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::CachePolicyField>()) {
|
||||
++this->nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("received CachePolicy with Interest: DROP");
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::IncomingFaceIdField>()) {
|
||||
NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
|
||||
}
|
||||
|
||||
this->receiveInterest(*interest);
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt)
|
||||
{
|
||||
BOOST_ASSERT(netPkt.type() == tlv::Data);
|
||||
|
||||
// forwarding expects Data to be created with make_shared
|
||||
auto data = make_shared<Data>(netPkt);
|
||||
|
||||
if (firstPkt.has<lp::NackField>()) {
|
||||
++this->nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("received Nack with Data: DROP");
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::NextHopFaceIdField>()) {
|
||||
++this->nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("received NextHopFaceId with Data: DROP");
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::CachePolicyField>()) {
|
||||
if (m_options.allowLocalFields) {
|
||||
// In case of an invalid CachePolicyType, get<lp::CachePolicyField> will throw,
|
||||
// so it's unnecessary to check here.
|
||||
data->setTag(make_shared<lp::CachePolicyTag>(firstPkt.get<lp::CachePolicyField>()));
|
||||
}
|
||||
else {
|
||||
NFD_LOG_FACE_WARN("received CachePolicy, but local fields disabled: IGNORE");
|
||||
}
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::IncomingFaceIdField>()) {
|
||||
NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
|
||||
}
|
||||
|
||||
this->receiveData(*data);
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt)
|
||||
{
|
||||
BOOST_ASSERT(netPkt.type() == tlv::Interest);
|
||||
BOOST_ASSERT(firstPkt.has<lp::NackField>());
|
||||
|
||||
lp::Nack nack((Interest(netPkt)));
|
||||
nack.setHeader(firstPkt.get<lp::NackField>());
|
||||
|
||||
if (firstPkt.has<lp::NextHopFaceIdField>()) {
|
||||
++this->nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("received NextHopFaceId with Nack: DROP");
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::CachePolicyField>()) {
|
||||
++this->nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("received CachePolicy with Nack: DROP");
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::IncomingFaceIdField>()) {
|
||||
NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
|
||||
}
|
||||
|
||||
this->receiveNack(nack);
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,250 @@
|
||||
/* -*- 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_FACE_GENERIC_LINK_SERVICE_HPP
|
||||
#define NFD_DAEMON_FACE_GENERIC_LINK_SERVICE_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
#include "core/logger.hpp"
|
||||
|
||||
#include "link-service.hpp"
|
||||
#include "lp-fragmenter.hpp"
|
||||
#include "lp-reassembler.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
/** \brief counters provided by GenericLinkService
|
||||
* \note The type name 'GenericLinkServiceCounters' is implementation detail.
|
||||
* Use 'GenericLinkService::Counters' in public API.
|
||||
*/
|
||||
class GenericLinkServiceCounters : public virtual LinkService::Counters
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
GenericLinkServiceCounters(const LpReassembler& reassembler);
|
||||
|
||||
/** \brief count of failed fragmentations
|
||||
*/
|
||||
PacketCounter nFragmentationErrors;
|
||||
|
||||
/** \brief count of outgoing LpPackets dropped due to exceeding MTU limit
|
||||
*
|
||||
* If this counter is non-zero, the operator should enable fragmentation.
|
||||
*/
|
||||
PacketCounter nOutOverMtu;
|
||||
|
||||
/** \brief count of invalid LpPackets dropped before reassembly
|
||||
*/
|
||||
PacketCounter nInLpInvalid;
|
||||
|
||||
/** \brief count of network-layer packets currently being reassembled
|
||||
*/
|
||||
SizeCounter<LpReassembler> nReassembling;
|
||||
|
||||
/** \brief count of dropped partial network-layer packets due to reassembly timeout
|
||||
*/
|
||||
PacketCounter nReassemblyTimeouts;
|
||||
|
||||
/** \brief count of invalid reassembled network-layer packets dropped
|
||||
*/
|
||||
PacketCounter nInNetInvalid;
|
||||
};
|
||||
|
||||
/** \brief GenericLinkService is a LinkService that implements the NDNLPv2 protocol
|
||||
* \sa http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
|
||||
*/
|
||||
class GenericLinkService : public LinkService
|
||||
, protected virtual GenericLinkServiceCounters
|
||||
{
|
||||
public:
|
||||
/** \brief Options that control the behavior of GenericLinkService
|
||||
*/
|
||||
class Options
|
||||
{
|
||||
public:
|
||||
Options();
|
||||
|
||||
public:
|
||||
/** \brief enables encoding of IncomingFaceId, and decoding of NextHopFaceId and CachePolicy
|
||||
*/
|
||||
bool allowLocalFields;
|
||||
|
||||
/** \brief enables fragmentation
|
||||
*/
|
||||
bool allowFragmentation;
|
||||
|
||||
/** \brief options for fragmentation
|
||||
*/
|
||||
LpFragmenter::Options fragmenterOptions;
|
||||
|
||||
/** \brief enables reassembly
|
||||
*/
|
||||
bool allowReassembly;
|
||||
|
||||
/** \brief options for reassembly
|
||||
*/
|
||||
LpReassembler::Options reassemblerOptions;
|
||||
};
|
||||
|
||||
/** \brief counters provided by GenericLinkService
|
||||
*/
|
||||
typedef GenericLinkServiceCounters Counters;
|
||||
|
||||
explicit
|
||||
GenericLinkService(const Options& options = Options());
|
||||
|
||||
/** \brief get Options used by GenericLinkService
|
||||
*/
|
||||
const Options&
|
||||
getOptions() const;
|
||||
|
||||
/** \brief sets Options used by GenericLinkService
|
||||
*/
|
||||
void
|
||||
setOptions(const Options& options);
|
||||
|
||||
virtual const Counters&
|
||||
getCounters() const DECL_OVERRIDE;
|
||||
|
||||
private: // send path
|
||||
/** \brief send Interest
|
||||
*/
|
||||
void
|
||||
doSendInterest(const Interest& interest) DECL_OVERRIDE;
|
||||
|
||||
/** \brief send Data
|
||||
*/
|
||||
void
|
||||
doSendData(const Data& data) DECL_OVERRIDE;
|
||||
|
||||
/** \brief send Nack
|
||||
*/
|
||||
void
|
||||
doSendNack(const ndn::lp::Nack& nack) DECL_OVERRIDE;
|
||||
|
||||
/** \brief encode local fields from tags onto outgoing LpPacket
|
||||
* \param pkt LpPacket containing a complete network layer packet
|
||||
*/
|
||||
static void
|
||||
encodeLocalFields(const ndn::TagHost& netPkt, lp::Packet& lpPacket);
|
||||
|
||||
/** \brief send a complete network layer packet
|
||||
* \param pkt LpPacket containing a complete network layer packet
|
||||
*/
|
||||
void
|
||||
sendNetPacket(lp::Packet&& pkt);
|
||||
|
||||
/** \brief assign a sequence number to an LpPacket
|
||||
*/
|
||||
void
|
||||
assignSequence(lp::Packet& pkt);
|
||||
|
||||
/** \brief assign consecutive sequence numbers to LpPackets
|
||||
*/
|
||||
void
|
||||
assignSequences(std::vector<lp::Packet>& pkts);
|
||||
|
||||
private: // receive path
|
||||
/** \brief receive Packet from Transport
|
||||
*/
|
||||
void
|
||||
doReceivePacket(Transport::Packet&& packet) DECL_OVERRIDE;
|
||||
|
||||
/** \brief decode incoming network-layer packet
|
||||
* \param netPkt reassembled network-layer packet
|
||||
* \param firstPkt LpPacket of first fragment
|
||||
*
|
||||
* If decoding is successful, a receive signal is emitted;
|
||||
* otherwise, a warning is logged.
|
||||
*/
|
||||
void
|
||||
decodeNetPacket(const Block& netPkt, const lp::Packet& firstPkt);
|
||||
|
||||
/** \brief decode incoming Interest
|
||||
* \param netPkt reassembled network-layer packet; TLV-TYPE must be Interest
|
||||
* \param firstPkt LpPacket of first fragment; must not have Nack field
|
||||
*
|
||||
* If decoding is successful, receiveInterest signal is emitted;
|
||||
* otherwise, a warning is logged.
|
||||
*
|
||||
* \throw tlv::Error parse error in an LpHeader field
|
||||
*/
|
||||
void
|
||||
decodeInterest(const Block& netPkt, const lp::Packet& firstPkt);
|
||||
|
||||
/** \brief decode incoming Interest
|
||||
* \param netPkt reassembled network-layer packet; TLV-TYPE must be Data
|
||||
* \param firstPkt LpPacket of first fragment
|
||||
*
|
||||
* If decoding is successful, receiveData signal is emitted;
|
||||
* otherwise, a warning is logged.
|
||||
*
|
||||
* \throw tlv::Error parse error in an LpHeader field
|
||||
*/
|
||||
void
|
||||
decodeData(const Block& netPkt, const lp::Packet& firstPkt);
|
||||
|
||||
/** \brief decode incoming Interest
|
||||
* \param netPkt reassembled network-layer packet; TLV-TYPE must be Interest
|
||||
* \param firstPkt LpPacket of first fragment; must have Nack field
|
||||
*
|
||||
* If decoding is successful, receiveNack signal is emitted;
|
||||
* otherwise, a warning is logged.
|
||||
*
|
||||
* \throw tlv::Error parse error in an LpHeader field
|
||||
*/
|
||||
void
|
||||
decodeNack(const Block& netPkt, const lp::Packet& firstPkt);
|
||||
|
||||
private:
|
||||
Options m_options;
|
||||
LpFragmenter m_fragmenter;
|
||||
LpReassembler m_reassembler;
|
||||
lp::Sequence m_lastSeqNo;
|
||||
};
|
||||
|
||||
inline const GenericLinkService::Options&
|
||||
GenericLinkService::getOptions() const
|
||||
{
|
||||
return m_options;
|
||||
}
|
||||
|
||||
inline void
|
||||
GenericLinkService::setOptions(const GenericLinkService::Options& options)
|
||||
{
|
||||
m_options = options;
|
||||
}
|
||||
|
||||
inline const GenericLinkService::Counters&
|
||||
GenericLinkService::getCounters() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_GENERIC_LINK_SERVICE_HPP
|
||||
@@ -0,0 +1,53 @@
|
||||
/* -*- 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 "internal-face.hpp"
|
||||
#include "generic-link-service.hpp"
|
||||
#include "internal-transport.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
std::tuple<shared_ptr<Face>, shared_ptr<ndn::Face>>
|
||||
makeInternalFace(ndn::KeyChain& clientKeyChain)
|
||||
{
|
||||
GenericLinkService::Options serviceOpts;
|
||||
serviceOpts.allowLocalFields = true;
|
||||
|
||||
auto face = make_shared<Face>(make_unique<GenericLinkService>(serviceOpts),
|
||||
make_unique<InternalForwarderTransport>());
|
||||
|
||||
auto forwarderTransport = static_cast<InternalForwarderTransport*>(face->getTransport());
|
||||
auto clientTransport = make_shared<InternalClientTransport>();
|
||||
clientTransport->connectToForwarder(forwarderTransport);
|
||||
|
||||
auto clientFace = make_shared<ndn::Face>(clientTransport, getGlobalIoService(), clientKeyChain);
|
||||
|
||||
return std::make_tuple(face, clientFace);
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,51 @@
|
||||
/* -*- 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_FACE_INTERNAL_FACE_HPP
|
||||
#define NFD_DAEMON_FACE_INTERNAL_FACE_HPP
|
||||
|
||||
#include "face.hpp"
|
||||
#include <ndn-cxx/face.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
/** \brief make a pair of forwarder-side face and client-side face
|
||||
* that are connected with each other
|
||||
*
|
||||
* Network-layer packets sent by one face will be received by the other face
|
||||
* after io.poll().
|
||||
*
|
||||
* \param clientKeyChain A KeyChain used by client-side face to sign
|
||||
* prefix registration commands.
|
||||
* \return a forwarder-side face and a client-side face connected with each other
|
||||
*/
|
||||
std::tuple<shared_ptr<Face>, shared_ptr<ndn::Face>>
|
||||
makeInternalFace(ndn::KeyChain& clientKeyChain);
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_INTERNAL_FACE_HPP
|
||||
@@ -0,0 +1,139 @@
|
||||
/* -*- 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 "internal-transport.hpp"
|
||||
#include "core/global-io.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
NFD_LOG_INCLASS_DEFINE(InternalForwarderTransport, "InternalForwarderTransport");
|
||||
|
||||
InternalForwarderTransport::InternalForwarderTransport(
|
||||
const FaceUri& localUri, const FaceUri& remoteUri,
|
||||
ndn::nfd::FaceScope scope, ndn::nfd::LinkType linkType)
|
||||
{
|
||||
this->setLocalUri(localUri);
|
||||
this->setRemoteUri(remoteUri);
|
||||
this->setScope(scope);
|
||||
this->setPersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
|
||||
this->setLinkType(linkType);
|
||||
this->setMtu(MTU_UNLIMITED);
|
||||
|
||||
NFD_LOG_FACE_INFO("Creating transport");
|
||||
}
|
||||
|
||||
void
|
||||
InternalForwarderTransport::beforeChangePersistency(ndn::nfd::FacePersistency newPersistency)
|
||||
{
|
||||
if (newPersistency != ndn::nfd::FACE_PERSISTENCY_PERMANENT) {
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("InternalForwarderTransport supports only FACE_PERSISTENCY_PERMANENT"));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
InternalForwarderTransport::receiveFromLink(const Block& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
Packet p;
|
||||
p.packet = packet;
|
||||
this->receive(std::move(p));
|
||||
}
|
||||
|
||||
void
|
||||
InternalForwarderTransport::doSend(Packet&& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
this->emitSignal(afterSend, packet.packet);
|
||||
}
|
||||
|
||||
void
|
||||
InternalForwarderTransport::doClose()
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
this->setState(TransportState::CLOSED);
|
||||
}
|
||||
|
||||
NFD_LOG_INCLASS_DEFINE(InternalClientTransport, "InternalClientTransport");
|
||||
|
||||
static void
|
||||
asyncReceive(InternalTransportBase* recipient, const Block& packet)
|
||||
{
|
||||
getGlobalIoService().post([packet, recipient] {
|
||||
recipient->receiveFromLink(packet);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
InternalClientTransport::connectToForwarder(InternalForwarderTransport* forwarderTransport)
|
||||
{
|
||||
NFD_LOG_DEBUG(__func__ << " " << forwarderTransport);
|
||||
|
||||
m_fwToClientTransmitConn.disconnect();
|
||||
m_clientToFwTransmitConn.disconnect();
|
||||
m_fwTransportStateConn.disconnect();
|
||||
|
||||
if (forwarderTransport != nullptr) {
|
||||
m_fwToClientTransmitConn = forwarderTransport->afterSend.connect(bind(&asyncReceive, this, _1));
|
||||
m_clientToFwTransmitConn = this->afterSend.connect(bind(&asyncReceive, forwarderTransport, _1));
|
||||
m_fwTransportStateConn = forwarderTransport->afterStateChange.connect(
|
||||
[this] (TransportState oldState, TransportState newState) {
|
||||
if (newState == TransportState::CLOSED) {
|
||||
this->connectToForwarder(nullptr);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
InternalClientTransport::receiveFromLink(const Block& packet)
|
||||
{
|
||||
if (m_receiveCallback) {
|
||||
m_receiveCallback(packet);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
InternalClientTransport::send(const Block& wire)
|
||||
{
|
||||
this->emitSignal(afterSend, wire);
|
||||
}
|
||||
|
||||
void
|
||||
InternalClientTransport::send(const Block& header, const Block& payload)
|
||||
{
|
||||
ndn::EncodingBuffer encoder(header.size() + payload.size(), header.size() + payload.size());
|
||||
encoder.appendByteArray(header.wire(), header.size());
|
||||
encoder.appendByteArray(payload.wire(), payload.size());
|
||||
|
||||
this->send(encoder.block());
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,130 @@
|
||||
/* -*- 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_FACE_INTERNAL_TRANSPORT_HPP
|
||||
#define NFD_DAEMON_FACE_INTERNAL_TRANSPORT_HPP
|
||||
|
||||
#include "transport.hpp"
|
||||
#include <ndn-cxx/transport/transport.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
/** \brief abstracts a transport that can be paired with another
|
||||
*/
|
||||
class InternalTransportBase
|
||||
{
|
||||
public:
|
||||
/** \brief causes the transport to receive a link-layer packet
|
||||
*/
|
||||
virtual void
|
||||
receiveFromLink(const Block& packet) = 0;
|
||||
|
||||
signal::Signal<InternalTransportBase, Block> afterSend;
|
||||
|
||||
protected:
|
||||
DECLARE_SIGNAL_EMIT(afterSend)
|
||||
};
|
||||
|
||||
/** \brief implements a forwarder-side transport that can be paired with another
|
||||
*/
|
||||
class InternalForwarderTransport : public face::Transport, public InternalTransportBase
|
||||
{
|
||||
public:
|
||||
InternalForwarderTransport(const FaceUri& localUri = FaceUri("internal://"),
|
||||
const FaceUri& remoteUri = FaceUri("internal://"),
|
||||
ndn::nfd::FaceScope scope = ndn::nfd::FACE_SCOPE_LOCAL,
|
||||
ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_POINT_TO_POINT);
|
||||
|
||||
virtual void
|
||||
receiveFromLink(const Block& packet) DECL_OVERRIDE;
|
||||
|
||||
protected:
|
||||
virtual void
|
||||
beforeChangePersistency(ndn::nfd::FacePersistency newPersistency) DECL_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
doClose() DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
virtual void
|
||||
doSend(Packet&& packet) DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
NFD_LOG_INCLASS_DECLARE();
|
||||
};
|
||||
|
||||
/** \brief implements a client-side transport that can be paired with another
|
||||
*/
|
||||
class InternalClientTransport : public ndn::Transport, public InternalTransportBase
|
||||
{
|
||||
public:
|
||||
/** \brief connect to a forwarder-side transport
|
||||
* \param forwarderTransport the forwarder-side transport to connect to; may be nullptr
|
||||
*
|
||||
* The connected forwarder-side transport will be disconnected automatically if this method
|
||||
* is called again, or if that transport is closed.
|
||||
* It's safe to use InternalClientTransport without a connected forwarder-side transport:
|
||||
* all sent packets would be lost, and nothing would be received.
|
||||
*/
|
||||
void
|
||||
connectToForwarder(InternalForwarderTransport* forwarderTransport);
|
||||
|
||||
virtual void
|
||||
receiveFromLink(const Block& packet) DECL_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
close() DECL_OVERRIDE
|
||||
{
|
||||
}
|
||||
|
||||
virtual void
|
||||
pause() DECL_OVERRIDE
|
||||
{
|
||||
}
|
||||
|
||||
virtual void
|
||||
resume() DECL_OVERRIDE
|
||||
{
|
||||
}
|
||||
|
||||
virtual void
|
||||
send(const Block& wire) DECL_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
send(const Block& header, const Block& payload) DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
NFD_LOG_INCLASS_DECLARE();
|
||||
|
||||
signal::ScopedConnection m_fwToClientTransmitConn;
|
||||
signal::ScopedConnection m_clientToFwTransmitConn;
|
||||
signal::ScopedConnection m_fwTransportStateConn;
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_INTERNAL_TRANSPORT_HPP
|
||||
@@ -0,0 +1,132 @@
|
||||
/* -*- 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 "link-service.hpp"
|
||||
#include "face.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
NFD_LOG_INIT("LinkService");
|
||||
|
||||
LinkService::LinkService()
|
||||
: m_face(nullptr)
|
||||
, m_transport(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
LinkService::~LinkService()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
LinkService::setFaceAndTransport(Face& face, Transport& transport)
|
||||
{
|
||||
BOOST_ASSERT(m_face == nullptr);
|
||||
BOOST_ASSERT(m_transport == nullptr);
|
||||
|
||||
m_face = &face;
|
||||
m_transport = &transport;
|
||||
}
|
||||
|
||||
void
|
||||
LinkService::sendInterest(const Interest& interest)
|
||||
{
|
||||
BOOST_ASSERT(m_transport != nullptr);
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
++this->nOutInterests;
|
||||
|
||||
doSendInterest(interest);
|
||||
}
|
||||
|
||||
void
|
||||
LinkService::sendData(const Data& data)
|
||||
{
|
||||
BOOST_ASSERT(m_transport != nullptr);
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
++this->nOutData;
|
||||
|
||||
doSendData(data);
|
||||
}
|
||||
|
||||
void
|
||||
LinkService::sendNack(const ndn::lp::Nack& nack)
|
||||
{
|
||||
BOOST_ASSERT(m_transport != nullptr);
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
++this->nOutNacks;
|
||||
|
||||
doSendNack(nack);
|
||||
}
|
||||
|
||||
void
|
||||
LinkService::receiveInterest(const Interest& interest)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
++this->nInInterests;
|
||||
|
||||
afterReceiveInterest(interest);
|
||||
}
|
||||
|
||||
void
|
||||
LinkService::receiveData(const Data& data)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
++this->nInData;
|
||||
|
||||
afterReceiveData(data);
|
||||
}
|
||||
|
||||
void
|
||||
LinkService::receiveNack(const ndn::lp::Nack& nack)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
++this->nInNacks;
|
||||
|
||||
afterReceiveNack(nack);
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceLogHelper<LinkService>& flh)
|
||||
{
|
||||
const Face* face = flh.obj.getFace();
|
||||
if (face == nullptr) {
|
||||
os << "[id=0,local=unknown,remote=unknown] ";
|
||||
}
|
||||
else {
|
||||
os << "[id=" << face->getId() << ",local=" << face->getLocalUri()
|
||||
<< ",remote=" << face->getRemoteUri() << "] ";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,244 @@
|
||||
/* -*- 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_FACE_LINK_SERVICE_HPP
|
||||
#define NFD_DAEMON_FACE_LINK_SERVICE_HPP
|
||||
|
||||
#include "core/counter.hpp"
|
||||
#include "transport.hpp"
|
||||
#include "face-log.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
class Face;
|
||||
|
||||
/** \brief counters provided by LinkService
|
||||
* \note The type name 'LinkServiceCounters' is implementation detail.
|
||||
* Use 'LinkService::Counters' in public API.
|
||||
*/
|
||||
class LinkServiceCounters
|
||||
{
|
||||
public:
|
||||
/** \brief count of incoming Interests
|
||||
*/
|
||||
PacketCounter nInInterests;
|
||||
|
||||
/** \brief count of outgoing Interests
|
||||
*/
|
||||
PacketCounter nOutInterests;
|
||||
|
||||
/** \brief count of incoming Data
|
||||
*/
|
||||
PacketCounter nInData;
|
||||
|
||||
/** \brief count of outgoing Data
|
||||
*/
|
||||
PacketCounter nOutData;
|
||||
|
||||
/** \brief count of incoming Nacks
|
||||
*/
|
||||
PacketCounter nInNacks;
|
||||
|
||||
/** \brief count of outgoing Nacks
|
||||
*/
|
||||
PacketCounter nOutNacks;
|
||||
};
|
||||
|
||||
/** \brief the upper part of a Face
|
||||
* \sa Face
|
||||
*/
|
||||
class LinkService : protected virtual LinkServiceCounters, noncopyable
|
||||
{
|
||||
public:
|
||||
/** \brief counters provided by LinkService
|
||||
*/
|
||||
typedef LinkServiceCounters Counters;
|
||||
|
||||
public:
|
||||
LinkService();
|
||||
|
||||
virtual
|
||||
~LinkService();
|
||||
|
||||
/** \brief set Face and Transport for LinkService
|
||||
* \pre setFaceAndTransport has not been called
|
||||
*/
|
||||
void
|
||||
setFaceAndTransport(Face& face, Transport& transport);
|
||||
|
||||
/** \return Face to which this LinkService is attached
|
||||
*/
|
||||
const Face*
|
||||
getFace() const;
|
||||
|
||||
/** \return Transport to which this LinkService is attached
|
||||
*/
|
||||
const Transport*
|
||||
getTransport() const;
|
||||
|
||||
/** \return Transport to which this LinkService is attached
|
||||
*/
|
||||
Transport*
|
||||
getTransport();
|
||||
|
||||
virtual const Counters&
|
||||
getCounters() const;
|
||||
|
||||
public: // upper interface to be used by forwarding
|
||||
/** \brief send Interest
|
||||
* \pre setTransport has been called
|
||||
*/
|
||||
void
|
||||
sendInterest(const Interest& interest);
|
||||
|
||||
/** \brief send Data
|
||||
* \pre setTransport has been called
|
||||
*/
|
||||
void
|
||||
sendData(const Data& data);
|
||||
|
||||
/** \brief send Nack
|
||||
* \pre setTransport has been called
|
||||
*/
|
||||
void
|
||||
sendNack(const ndn::lp::Nack& nack);
|
||||
|
||||
/** \brief signals on Interest received
|
||||
*/
|
||||
signal::Signal<LinkService, Interest> afterReceiveInterest;
|
||||
|
||||
/** \brief signals on Data received
|
||||
*/
|
||||
signal::Signal<LinkService, Data> afterReceiveData;
|
||||
|
||||
/** \brief signals on Nack received
|
||||
*/
|
||||
signal::Signal<LinkService, lp::Nack> afterReceiveNack;
|
||||
|
||||
public: // lower interface to be invoked by Transport
|
||||
/** \brief performs LinkService specific operations to receive a lower-layer packet
|
||||
*/
|
||||
void
|
||||
receivePacket(Transport::Packet&& packet);
|
||||
|
||||
protected: // upper interface to be invoked in subclass (receive path termination)
|
||||
/** \brief delivers received Interest to forwarding
|
||||
*/
|
||||
void
|
||||
receiveInterest(const Interest& interest);
|
||||
|
||||
/** \brief delivers received Data to forwarding
|
||||
*/
|
||||
void
|
||||
receiveData(const Data& data);
|
||||
|
||||
/** \brief delivers received Nack to forwarding
|
||||
*/
|
||||
void
|
||||
receiveNack(const lp::Nack& nack);
|
||||
|
||||
protected: // lower interface to be invoked in subclass (send path termination)
|
||||
/** \brief sends a lower-layer packet via Transport
|
||||
*/
|
||||
void
|
||||
sendPacket(Transport::Packet&& packet);
|
||||
|
||||
private: // upper interface to be overridden in subclass (send path entrypoint)
|
||||
/** \brief performs LinkService specific operations to send an Interest
|
||||
*/
|
||||
virtual void
|
||||
doSendInterest(const Interest& interest) = 0;
|
||||
|
||||
/** \brief performs LinkService specific operations to send a Data
|
||||
*/
|
||||
virtual void
|
||||
doSendData(const Data& data) = 0;
|
||||
|
||||
/** \brief performs LinkService specific operations to send a Nack
|
||||
*/
|
||||
virtual void
|
||||
doSendNack(const lp::Nack& nack) = 0;
|
||||
|
||||
private: // lower interface to be overridden in subclass
|
||||
virtual void
|
||||
doReceivePacket(Transport::Packet&& packet) = 0;
|
||||
|
||||
private:
|
||||
Face* m_face;
|
||||
Transport* m_transport;
|
||||
};
|
||||
|
||||
inline const Face*
|
||||
LinkService::getFace() const
|
||||
{
|
||||
return m_face;
|
||||
}
|
||||
|
||||
inline const Transport*
|
||||
LinkService::getTransport() const
|
||||
{
|
||||
return m_transport;
|
||||
}
|
||||
|
||||
inline Transport*
|
||||
LinkService::getTransport()
|
||||
{
|
||||
return m_transport;
|
||||
}
|
||||
|
||||
inline const LinkService::Counters&
|
||||
LinkService::getCounters() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void
|
||||
LinkService::receivePacket(Transport::Packet&& packet)
|
||||
{
|
||||
doReceivePacket(std::move(packet));
|
||||
}
|
||||
|
||||
inline void
|
||||
LinkService::sendPacket(Transport::Packet&& packet)
|
||||
{
|
||||
m_transport->send(std::move(packet));
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceLogHelper<LinkService>& flh);
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_base_of<LinkService, T>::value &&
|
||||
!std::is_same<LinkService, T>::value, std::ostream&>::type
|
||||
operator<<(std::ostream& os, const FaceLogHelper<T>& flh)
|
||||
{
|
||||
return os << FaceLogHelper<LinkService>(flh.obj);
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_LINK_SERVICE_HPP
|
||||
@@ -1,210 +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_FACE_LOCAL_FACE_HPP
|
||||
#define NFD_DAEMON_FACE_LOCAL_FACE_HPP
|
||||
|
||||
#include "face.hpp"
|
||||
#include <ndn-cxx/management/nfd-control-parameters.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
using ndn::nfd::LocalControlFeature;
|
||||
using ndn::nfd::LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID;
|
||||
using ndn::nfd::LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID;
|
||||
|
||||
/** \brief represents a face
|
||||
*/
|
||||
class LocalFace : public Face
|
||||
{
|
||||
public:
|
||||
LocalFace(const FaceUri& remoteUri, const FaceUri& localUri);
|
||||
|
||||
/** \brief get whether any LocalControlHeader feature is enabled
|
||||
*
|
||||
* \returns true if any feature is enabled.
|
||||
*/
|
||||
bool
|
||||
isLocalControlHeaderEnabled() const;
|
||||
|
||||
/** \brief get whether a specific LocalControlHeader feature is enabled
|
||||
*
|
||||
* \param feature The feature.
|
||||
* \returns true if the specified feature is enabled.
|
||||
*/
|
||||
bool
|
||||
isLocalControlHeaderEnabled(LocalControlFeature feature) const;
|
||||
|
||||
/** \brief enable or disable a LocalControlHeader feature
|
||||
*
|
||||
* \param feature The feature. Cannot be LOCAL_CONTROL_FEATURE_ANY
|
||||
* or LOCAL_CONTROL_FEATURE_MAX
|
||||
*/
|
||||
void
|
||||
setLocalControlHeaderFeature(LocalControlFeature feature, bool enabled = true);
|
||||
|
||||
public:
|
||||
|
||||
static const size_t LOCAL_CONTROL_FEATURE_MAX = 3; /// upper bound of LocalControlFeature enum
|
||||
static const size_t LOCAL_CONTROL_FEATURE_ANY = 0; /// any feature
|
||||
|
||||
protected:
|
||||
// statically overridden from Face
|
||||
|
||||
/** \brief Decode block into Interest/Data, considering potential LocalControlHeader
|
||||
*
|
||||
* If LocalControlHeader is present, the encoded data is filtered out, based
|
||||
* on enabled features on the face.
|
||||
*/
|
||||
bool
|
||||
decodeAndDispatchInput(const Block& element);
|
||||
|
||||
// LocalFace-specific methods
|
||||
|
||||
/** \brief Check if LocalControlHeader needs to be included, taking into account
|
||||
* both set parameters in supplied LocalControlHeader and features
|
||||
* enabled on the local face.
|
||||
*/
|
||||
bool
|
||||
isEmptyFilteredLocalControlHeader(const ndn::nfd::LocalControlHeader& header) const;
|
||||
|
||||
/** \brief Create LocalControlHeader, considering enabled features
|
||||
*/
|
||||
template<class Packet>
|
||||
Block
|
||||
filterAndEncodeLocalControlHeader(const Packet& packet);
|
||||
|
||||
private:
|
||||
std::vector<bool> m_localControlHeaderFeatures;
|
||||
};
|
||||
|
||||
inline
|
||||
LocalFace::LocalFace(const FaceUri& remoteUri, const FaceUri& localUri)
|
||||
: Face(remoteUri, localUri, true)
|
||||
, m_localControlHeaderFeatures(LocalFace::LOCAL_CONTROL_FEATURE_MAX)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool
|
||||
LocalFace::isLocalControlHeaderEnabled() const
|
||||
{
|
||||
return m_localControlHeaderFeatures[LOCAL_CONTROL_FEATURE_ANY];
|
||||
}
|
||||
|
||||
inline bool
|
||||
LocalFace::isLocalControlHeaderEnabled(LocalControlFeature feature) const
|
||||
{
|
||||
BOOST_ASSERT(0 < feature &&
|
||||
static_cast<size_t>(feature) < m_localControlHeaderFeatures.size());
|
||||
return m_localControlHeaderFeatures[feature];
|
||||
}
|
||||
|
||||
inline void
|
||||
LocalFace::setLocalControlHeaderFeature(LocalControlFeature feature, bool enabled/* = true*/)
|
||||
{
|
||||
BOOST_ASSERT(0 < feature &&
|
||||
static_cast<size_t>(feature) < m_localControlHeaderFeatures.size());
|
||||
|
||||
m_localControlHeaderFeatures[feature] = enabled;
|
||||
|
||||
m_localControlHeaderFeatures[LOCAL_CONTROL_FEATURE_ANY] =
|
||||
std::find(m_localControlHeaderFeatures.begin() + 1,
|
||||
m_localControlHeaderFeatures.end(), true) <
|
||||
m_localControlHeaderFeatures.end();
|
||||
// 'find(..) < .end()' instead of 'find(..) != .end()' due to LLVM Bug 16816
|
||||
}
|
||||
|
||||
inline bool
|
||||
LocalFace::decodeAndDispatchInput(const Block& element)
|
||||
{
|
||||
try {
|
||||
const Block& payload = ndn::nfd::LocalControlHeader::getPayload(element);
|
||||
|
||||
// If received LocalControlHeader, but it is not enabled on the face
|
||||
if ((&payload != &element) && !this->isLocalControlHeaderEnabled())
|
||||
return false;
|
||||
|
||||
if (payload.type() == tlv::Interest)
|
||||
{
|
||||
shared_ptr<Interest> i = make_shared<Interest>();
|
||||
i->wireDecode(payload);
|
||||
if (&payload != &element)
|
||||
{
|
||||
i->getLocalControlHeader().wireDecode(element,
|
||||
false,
|
||||
this->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
|
||||
}
|
||||
|
||||
this->onReceiveInterest(*i);
|
||||
}
|
||||
else if (payload.type() == tlv::Data)
|
||||
{
|
||||
shared_ptr<Data> d = make_shared<Data>();
|
||||
d->wireDecode(payload);
|
||||
|
||||
/// \todo Uncomment and correct the following when we have more
|
||||
/// options in LocalControlHeader that apply for incoming
|
||||
/// Data packets (if ever)
|
||||
// if (&payload != &element)
|
||||
// {
|
||||
//
|
||||
// d->getLocalControlHeader().wireDecode(element,
|
||||
// false,
|
||||
// false);
|
||||
// }
|
||||
|
||||
this->onReceiveData(*d);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (tlv::Error&) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool
|
||||
LocalFace::isEmptyFilteredLocalControlHeader(const ndn::nfd::LocalControlHeader& header) const
|
||||
{
|
||||
if (!this->isLocalControlHeaderEnabled())
|
||||
return true;
|
||||
|
||||
return header.empty(this->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID),
|
||||
false);
|
||||
}
|
||||
|
||||
template<class Packet>
|
||||
inline Block
|
||||
LocalFace::filterAndEncodeLocalControlHeader(const Packet& packet)
|
||||
{
|
||||
return packet.getLocalControlHeader().wireEncode(packet,
|
||||
this->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID),
|
||||
false);
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_LOCAL_FACE_HPP
|
||||
@@ -0,0 +1,162 @@
|
||||
/* -*- 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 "lp-fragmenter.hpp"
|
||||
#include "link-service.hpp"
|
||||
#include <ndn-cxx/encoding/tlv.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
NFD_LOG_INIT("LpFragmenter");
|
||||
|
||||
static_assert(lp::tlv::LpPacket < 253, "LpPacket TLV-TYPE must fit in 1 octet");
|
||||
static_assert(lp::tlv::Sequence < 253, "Sequence TLV-TYPE must fit in 1 octet");
|
||||
static_assert(lp::tlv::FragIndex < 253, "FragIndex TLV-TYPE must fit in 1 octet");
|
||||
static_assert(lp::tlv::FragCount < 253, "FragCount TLV-TYPE must fit in 1 octet");
|
||||
static_assert(lp::tlv::Fragment < 253, "Fragment TLV-TYPE must fit in 1 octet");
|
||||
|
||||
/** \brief maximum overhead on a single fragment,
|
||||
* not counting other NDNLPv2 headers
|
||||
*/
|
||||
static const size_t MAX_SINGLE_FRAG_OVERHEAD =
|
||||
1 + 9 + // LpPacket TLV-TYPE and TLV-LENGTH
|
||||
1 + 1 + 8 + // Sequence TLV
|
||||
1 + 9; // Fragment TLV-TYPE and TLV-LENGTH
|
||||
|
||||
/** \brief maximum overhead of adding fragmentation to payload,
|
||||
* not counting other NDNLPv2 headers
|
||||
*/
|
||||
static const size_t MAX_FRAG_OVERHEAD =
|
||||
1 + 9 + // LpPacket TLV-TYPE and TLV-LENGTH
|
||||
1 + 1 + 8 + // Sequence TLV
|
||||
1 + 1 + 8 + // FragIndex TLV
|
||||
1 + 1 + 8 + // FragCount TLV
|
||||
1 + 9; // Fragment TLV-TYPE and TLV-LENGTH
|
||||
|
||||
LpFragmenter::Options::Options()
|
||||
: nMaxFragments(400)
|
||||
{
|
||||
}
|
||||
|
||||
LpFragmenter::LpFragmenter(const LpFragmenter::Options& options, const LinkService* linkService)
|
||||
: m_options(options)
|
||||
, m_linkService(linkService)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
LpFragmenter::setOptions(const Options& options)
|
||||
{
|
||||
m_options = options;
|
||||
}
|
||||
|
||||
const LinkService*
|
||||
LpFragmenter::getLinkService() const
|
||||
{
|
||||
return m_linkService;
|
||||
}
|
||||
|
||||
std::tuple<bool, std::vector<lp::Packet>>
|
||||
LpFragmenter::fragmentPacket(const lp::Packet& packet, size_t mtu)
|
||||
{
|
||||
BOOST_ASSERT(packet.has<lp::FragmentField>());
|
||||
BOOST_ASSERT(!packet.has<lp::FragIndexField>());
|
||||
BOOST_ASSERT(!packet.has<lp::FragCountField>());
|
||||
|
||||
if (MAX_SINGLE_FRAG_OVERHEAD + packet.wireEncode().size() <= mtu) {
|
||||
// fast path: fragmentation not needed
|
||||
// To qualify for fast path, the packet must have space for adding a sequence number,
|
||||
// because another NDNLPv2 feature may require the sequence number.
|
||||
return std::make_tuple(true, std::vector<lp::Packet>{packet});
|
||||
}
|
||||
|
||||
ndn::Buffer::const_iterator netPktBegin, netPktEnd;
|
||||
std::tie(netPktBegin, netPktEnd) = packet.get<lp::FragmentField>();
|
||||
size_t netPktSize = std::distance(netPktBegin, netPktEnd);
|
||||
|
||||
// compute size of other NDNLPv2 headers to be placed on the first fragment
|
||||
size_t firstHeaderSize = 0;
|
||||
const Block& packetWire = packet.wireEncode();
|
||||
if (packetWire.type() == lp::tlv::LpPacket) {
|
||||
for (const Block& element : packetWire.elements()) {
|
||||
if (element.type() != lp::tlv::Fragment) {
|
||||
firstHeaderSize += element.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// compute payload size
|
||||
if (MAX_FRAG_OVERHEAD + firstHeaderSize + 1 > mtu) { // 1-octet fragment
|
||||
NFD_LOG_FACE_WARN("fragmentation error, MTU too small for first fragment: DROP");
|
||||
return std::make_tuple(false, std::vector<lp::Packet>{});
|
||||
}
|
||||
size_t firstPayloadSize = std::min(netPktSize, mtu - firstHeaderSize - MAX_FRAG_OVERHEAD);
|
||||
size_t payloadSize = mtu - MAX_FRAG_OVERHEAD;
|
||||
size_t fragCount = 1 + ((netPktSize - firstPayloadSize) / payloadSize) +
|
||||
((netPktSize - firstPayloadSize) % payloadSize != 0);
|
||||
|
||||
// compute FragCount
|
||||
if (fragCount > m_options.nMaxFragments) {
|
||||
NFD_LOG_FACE_WARN("fragmentation error, FragCount over limit: DROP");
|
||||
return std::make_pair(false, std::vector<lp::Packet>{});
|
||||
}
|
||||
|
||||
// populate fragments
|
||||
std::vector<lp::Packet> frags(fragCount);
|
||||
frags.front() = packet; // copy input packet to preserve other NDNLPv2 fields
|
||||
size_t fragIndex = 0;
|
||||
auto fragBegin = netPktBegin,
|
||||
fragEnd = fragBegin + firstPayloadSize;
|
||||
while (fragBegin < netPktEnd) {
|
||||
lp::Packet& frag = frags[fragIndex];
|
||||
frag.add<lp::FragIndexField>(fragIndex);
|
||||
frag.add<lp::FragCountField>(fragCount);
|
||||
frag.set<lp::FragmentField>(std::make_pair(fragBegin, fragEnd));
|
||||
BOOST_ASSERT(frag.wireEncode().size() <= mtu);
|
||||
|
||||
++fragIndex;
|
||||
fragBegin = fragEnd;
|
||||
fragEnd = std::min(netPktEnd, fragBegin + payloadSize);
|
||||
}
|
||||
BOOST_ASSERT(fragIndex == fragCount);
|
||||
|
||||
return std::make_pair(true, frags);
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceLogHelper<LpFragmenter>& flh)
|
||||
{
|
||||
if (flh.obj.getLinkService() == nullptr) {
|
||||
os << "[id=0,local=unknown,remote=unknown] ";
|
||||
}
|
||||
else {
|
||||
os << FaceLogHelper<LinkService>(*flh.obj.getLinkService());
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,92 @@
|
||||
/* -*- 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_FACE_LP_FRAGMENTER_HPP
|
||||
#define NFD_DAEMON_FACE_LP_FRAGMENTER_HPP
|
||||
|
||||
#include "face-log.hpp"
|
||||
|
||||
#include <ndn-cxx/lp/packet.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
class LinkService;
|
||||
|
||||
/** \brief fragments network-layer packets into NDNLPv2 link-layer packets
|
||||
* \sa http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
|
||||
*/
|
||||
class LpFragmenter
|
||||
{
|
||||
public:
|
||||
/** \brief Options that control the behavior of LpFragmenter
|
||||
*/
|
||||
class Options
|
||||
{
|
||||
public:
|
||||
Options();
|
||||
|
||||
public:
|
||||
/** \brief maximum number of fragments in a packet
|
||||
*/
|
||||
size_t nMaxFragments;
|
||||
};
|
||||
|
||||
explicit
|
||||
LpFragmenter(const Options& options = Options(), const LinkService* linkService = nullptr);
|
||||
|
||||
/** \brief set options for fragmenter
|
||||
*/
|
||||
void
|
||||
setOptions(const Options& options);
|
||||
|
||||
/** \return LinkService that owns this instance
|
||||
*
|
||||
* This is only used for logging, and may be nullptr.
|
||||
*/
|
||||
const LinkService*
|
||||
getLinkService() const;
|
||||
|
||||
/** \brief fragments a network-layer packet into link-layer packets
|
||||
* \param packet an LpPacket that contains a network-layer packet;
|
||||
* must have Fragment field, must not have FragIndex and FragCount fields
|
||||
* \param mtu maximum allowable LpPacket size after fragmentation and sequence number assignment
|
||||
* \return whether fragmentation succeeded, fragmented packets without sequence number
|
||||
*/
|
||||
std::tuple<bool, std::vector<lp::Packet>>
|
||||
fragmentPacket(const lp::Packet& packet, size_t mtu);
|
||||
|
||||
private:
|
||||
Options m_options;
|
||||
const LinkService* m_linkService;
|
||||
};
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceLogHelper<LpFragmenter>& flh);
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_LP_FRAGMENTER_HPP
|
||||
@@ -0,0 +1,176 @@
|
||||
/* -*- 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 "lp-reassembler.hpp"
|
||||
#include "link-service.hpp"
|
||||
#include <numeric>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
NFD_LOG_INIT("LpReassembler");
|
||||
|
||||
LpReassembler::Options::Options()
|
||||
: nMaxFragments(400)
|
||||
, reassemblyTimeout(time::milliseconds(500))
|
||||
{
|
||||
}
|
||||
|
||||
LpReassembler::LpReassembler(const LpReassembler::Options& options, const LinkService* linkService)
|
||||
: m_options(options)
|
||||
, m_linkService(linkService)
|
||||
{
|
||||
}
|
||||
|
||||
std::tuple<bool, Block, lp::Packet>
|
||||
LpReassembler::receiveFragment(Transport::EndpointId remoteEndpoint, const lp::Packet& packet)
|
||||
{
|
||||
BOOST_ASSERT(packet.has<lp::FragmentField>());
|
||||
|
||||
static auto FALSE_RETURN = std::make_tuple(false, Block(), lp::Packet());
|
||||
|
||||
// read and check FragIndex and FragCount
|
||||
uint64_t fragIndex = 0;
|
||||
uint64_t fragCount = 1;
|
||||
if (packet.has<lp::FragIndexField>()) {
|
||||
fragIndex = packet.get<lp::FragIndexField>();
|
||||
}
|
||||
if (packet.has<lp::FragCountField>()) {
|
||||
fragCount = packet.get<lp::FragCountField>();
|
||||
}
|
||||
|
||||
if (fragIndex >= fragCount) {
|
||||
NFD_LOG_FACE_WARN("reassembly error, FragIndex>=FragCount: DROP");
|
||||
return FALSE_RETURN;
|
||||
}
|
||||
|
||||
if (fragCount > m_options.nMaxFragments) {
|
||||
NFD_LOG_FACE_WARN("reassembly error, FragCount over limit: DROP");
|
||||
return FALSE_RETURN;
|
||||
}
|
||||
|
||||
// check for fast path
|
||||
if (fragIndex == 0 && fragCount == 1) {
|
||||
ndn::Buffer::const_iterator fragBegin, fragEnd;
|
||||
std::tie(fragBegin, fragEnd) = packet.get<lp::FragmentField>();
|
||||
Block netPkt(&*fragBegin, std::distance(fragBegin, fragEnd));
|
||||
return std::make_tuple(true, netPkt, packet);
|
||||
}
|
||||
|
||||
// check Sequence and compute message identifier
|
||||
if (!packet.has<lp::SequenceField>()) {
|
||||
NFD_LOG_FACE_WARN("reassembly error, Sequence missing: DROP");
|
||||
return FALSE_RETURN;
|
||||
}
|
||||
lp::Sequence messageIdentifier = packet.get<lp::SequenceField>() - fragIndex;
|
||||
Key key = std::make_tuple(remoteEndpoint, messageIdentifier);
|
||||
|
||||
// add to PartialPacket
|
||||
PartialPacket& pp = m_partialPackets[key];
|
||||
if (pp.fragCount == 0) { // new PartialPacket
|
||||
pp.fragCount = fragCount;
|
||||
pp.nReceivedFragments = 0;
|
||||
pp.fragments.resize(fragCount);
|
||||
}
|
||||
else {
|
||||
if (fragCount != pp.fragCount) {
|
||||
NFD_LOG_FACE_WARN("reassembly error, FragCount changed: DROP");
|
||||
return FALSE_RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
if (pp.fragments[fragIndex].has<lp::SequenceField>()) {
|
||||
NFD_LOG_FACE_TRACE("fragment already received: DROP");
|
||||
return FALSE_RETURN;
|
||||
}
|
||||
|
||||
pp.fragments[fragIndex] = packet;
|
||||
++pp.nReceivedFragments;
|
||||
|
||||
// check complete condition
|
||||
if (pp.nReceivedFragments == pp.fragCount) {
|
||||
Block reassembled = doReassembly(key);
|
||||
lp::Packet firstFrag(std::move(pp.fragments[0]));
|
||||
m_partialPackets.erase(key);
|
||||
return std::make_tuple(true, reassembled, firstFrag);
|
||||
}
|
||||
|
||||
// set drop timer
|
||||
pp.dropTimer = scheduler::schedule(m_options.reassemblyTimeout,
|
||||
bind(&LpReassembler::timeoutPartialPacket, this, key));
|
||||
|
||||
return FALSE_RETURN;
|
||||
}
|
||||
|
||||
Block
|
||||
LpReassembler::doReassembly(const Key& key)
|
||||
{
|
||||
PartialPacket& pp = m_partialPackets[key];
|
||||
|
||||
size_t payloadSize = std::accumulate(pp.fragments.begin(), pp.fragments.end(), 0,
|
||||
[&] (size_t sum, const lp::Packet& pkt) -> size_t {
|
||||
ndn::Buffer::const_iterator fragBegin, fragEnd;
|
||||
std::tie(fragBegin, fragEnd) = pkt.get<lp::FragmentField>();
|
||||
return sum + std::distance(fragBegin, fragEnd);
|
||||
});
|
||||
|
||||
ndn::Buffer fragBuffer(payloadSize);
|
||||
ndn::Buffer::iterator it = fragBuffer.begin();
|
||||
|
||||
for (const lp::Packet& frag : pp.fragments) {
|
||||
ndn::Buffer::const_iterator fragBegin, fragEnd;
|
||||
std::tie(fragBegin, fragEnd) = frag.get<lp::FragmentField>();
|
||||
it = std::copy(fragBegin, fragEnd, it);
|
||||
}
|
||||
|
||||
return Block(&*(fragBuffer.cbegin()), std::distance(fragBuffer.cbegin(), fragBuffer.cend()));
|
||||
}
|
||||
|
||||
void
|
||||
LpReassembler::timeoutPartialPacket(const Key& key)
|
||||
{
|
||||
auto it = m_partialPackets.find(key);
|
||||
if (it == m_partialPackets.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->beforeTimeout(std::get<0>(key), it->second.nReceivedFragments);
|
||||
m_partialPackets.erase(it);
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceLogHelper<LpReassembler>& flh)
|
||||
{
|
||||
if (flh.obj.getLinkService() == nullptr) {
|
||||
os << "[id=0,local=unknown,remote=unknown] ";
|
||||
}
|
||||
else {
|
||||
os << FaceLogHelper<LinkService>(*flh.obj.getLinkService());
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,160 @@
|
||||
/* -*- 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_FACE_LP_REASSEMBLER_HPP
|
||||
#define NFD_DAEMON_FACE_LP_REASSEMBLER_HPP
|
||||
|
||||
#include "core/scheduler.hpp"
|
||||
#include "face-log.hpp"
|
||||
#include "transport.hpp"
|
||||
|
||||
#include <ndn-cxx/lp/packet.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
class LinkService;
|
||||
|
||||
/** \brief reassembles fragmented network-layer packets
|
||||
* \sa http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
|
||||
*/
|
||||
class LpReassembler : noncopyable
|
||||
{
|
||||
public:
|
||||
/** \brief Options that control the behavior of LpReassembler
|
||||
*/
|
||||
class Options
|
||||
{
|
||||
public:
|
||||
Options();
|
||||
|
||||
public:
|
||||
/** \brief maximum number of fragments in a packet
|
||||
*
|
||||
* LpPackets with FragCount over this limit are dropped.
|
||||
*/
|
||||
size_t nMaxFragments;
|
||||
|
||||
/** \brief timeout before a partially reassembled packet is dropped
|
||||
*/
|
||||
time::nanoseconds reassemblyTimeout;
|
||||
};
|
||||
|
||||
explicit
|
||||
LpReassembler(const Options& options = Options(), const LinkService* linkService = nullptr);
|
||||
|
||||
/** \brief set options for reassembler
|
||||
*/
|
||||
void
|
||||
setOptions(const Options& options);
|
||||
|
||||
/** \return LinkService that owns this instance
|
||||
*
|
||||
* This is only used for logging, and may be nullptr.
|
||||
*/
|
||||
const LinkService*
|
||||
getLinkService() const;
|
||||
|
||||
/** \brief adds received fragment to buffer
|
||||
* \param remoteEndpoint endpoint whose sends the packet
|
||||
* \param packet received fragment;
|
||||
* must have Fragment field
|
||||
* \return whether network-layer packet has been completely received,
|
||||
* the reassembled network-layer packet,
|
||||
* and the first fragment for inspecting other NDNLPv2 headers
|
||||
* \throw tlv::Error packet is malformed
|
||||
*/
|
||||
std::tuple<bool, Block, lp::Packet>
|
||||
receiveFragment(Transport::EndpointId remoteEndpoint, const lp::Packet& packet);
|
||||
|
||||
/** \brief count of partial packets
|
||||
*/
|
||||
size_t
|
||||
size() const;
|
||||
|
||||
/** \brief signals before a partial packet is dropped due to timeout
|
||||
*
|
||||
* If a partial packet is incomplete and no new fragment is received
|
||||
* within Options::reassemblyTimeout, it would be dropped due to timeout.
|
||||
* Before it's erased, this signal is emitted with the remote endpoint,
|
||||
* and the number of fragments being dropped.
|
||||
*/
|
||||
signal::Signal<LpReassembler, Transport::EndpointId, size_t> beforeTimeout;
|
||||
|
||||
private:
|
||||
/** \brief holds all fragments of packet until reassembled
|
||||
*/
|
||||
struct PartialPacket
|
||||
{
|
||||
std::vector<lp::Packet> fragments;
|
||||
size_t fragCount; ///< total fragments
|
||||
size_t nReceivedFragments; ///< number of received fragments
|
||||
scheduler::ScopedEventId dropTimer;
|
||||
};
|
||||
|
||||
/** \brief index key for PartialPackets
|
||||
*/
|
||||
typedef std::tuple<
|
||||
Transport::EndpointId, // remoteEndpoint
|
||||
lp::Sequence // message identifier (sequence of the first fragment)
|
||||
> Key;
|
||||
|
||||
Block
|
||||
doReassembly(const Key& key);
|
||||
|
||||
void
|
||||
timeoutPartialPacket(const Key& key);
|
||||
|
||||
private:
|
||||
Options m_options;
|
||||
std::map<Key, PartialPacket> m_partialPackets;
|
||||
const LinkService* m_linkService;
|
||||
};
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceLogHelper<LpReassembler>& flh);
|
||||
|
||||
inline void
|
||||
LpReassembler::setOptions(const Options& options)
|
||||
{
|
||||
m_options = options;
|
||||
}
|
||||
|
||||
inline const LinkService*
|
||||
LpReassembler::getLinkService() const
|
||||
{
|
||||
return m_linkService;
|
||||
}
|
||||
|
||||
inline size_t
|
||||
LpReassembler::size() const
|
||||
{
|
||||
return m_partialPackets.size();
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_LP_REASSEMBLER_HPP
|
||||
@@ -1,87 +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,
|
||||
* 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 "multicast-udp-face.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
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)
|
||||
{
|
||||
NFD_LOG_INFO("Creating multicast UDP face for group " << m_multicastGroup);
|
||||
}
|
||||
|
||||
const MulticastUdpFace::protocol::endpoint&
|
||||
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)
|
||||
{
|
||||
onSendInterest(interest);
|
||||
|
||||
NFD_LOG_DEBUG("Sending interest");
|
||||
sendBlock(interest.wireEncode());
|
||||
}
|
||||
|
||||
void
|
||||
MulticastUdpFace::sendData(const Data& data)
|
||||
{
|
||||
/// \todo After this method implements duplicate suppression, onSendData event should
|
||||
/// be triggered only when data is actually sent out
|
||||
onSendData(data);
|
||||
|
||||
NFD_LOG_DEBUG("Sending data");
|
||||
sendBlock(data.wireEncode());
|
||||
}
|
||||
|
||||
bool
|
||||
MulticastUdpFace::isMultiAccess() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
@@ -1,72 +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,
|
||||
* 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_FACE_MULTICAST_UDP_FACE_HPP
|
||||
#define NFD_DAEMON_FACE_MULTICAST_UDP_FACE_HPP
|
||||
|
||||
#include "datagram-face.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
/**
|
||||
* \brief Implementation of Face abstraction that uses
|
||||
* multicast UDP as underlying transport mechanism
|
||||
*/
|
||||
class MulticastUdpFace : public DatagramFace<boost::asio::ip::udp, Multicast>
|
||||
{
|
||||
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);
|
||||
|
||||
const protocol::endpoint&
|
||||
getMulticastGroup() const;
|
||||
|
||||
// from Face
|
||||
virtual void
|
||||
sendInterest(const Interest& interest);
|
||||
|
||||
virtual void
|
||||
sendData(const Data& data);
|
||||
|
||||
virtual bool
|
||||
isMultiAccess() const;
|
||||
|
||||
private:
|
||||
void
|
||||
sendBlock(const Block& block);
|
||||
|
||||
private:
|
||||
protocol::endpoint m_multicastGroup;
|
||||
shared_ptr<protocol::socket> m_sendSocket;
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_MULTICAST_UDP_FACE_HPP
|
||||
@@ -0,0 +1,102 @@
|
||||
/* -*- 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 "multicast-udp-transport.hpp"
|
||||
#include "udp-protocol.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
NFD_LOG_INCLASS_2TEMPLATE_SPECIALIZATION_DEFINE(DatagramTransport, MulticastUdpTransport::protocol,
|
||||
Multicast, "MulticastUdpTransport");
|
||||
|
||||
MulticastUdpTransport::MulticastUdpTransport(const protocol::endpoint& localEndpoint,
|
||||
const protocol::endpoint& multicastGroup,
|
||||
protocol::socket&& recvSocket,
|
||||
protocol::socket&& sendSocket)
|
||||
: DatagramTransport(std::move(recvSocket))
|
||||
, m_multicastGroup(multicastGroup)
|
||||
, m_sendSocket(std::move(sendSocket))
|
||||
{
|
||||
this->setLocalUri(FaceUri(localEndpoint));
|
||||
this->setRemoteUri(FaceUri(multicastGroup));
|
||||
this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
|
||||
this->setPersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
|
||||
this->setLinkType(ndn::nfd::LINK_TYPE_MULTI_ACCESS);
|
||||
this->setMtu(udp::computeMtu(localEndpoint));
|
||||
|
||||
NFD_LOG_FACE_INFO("Creating transport");
|
||||
}
|
||||
|
||||
void
|
||||
MulticastUdpTransport::beforeChangePersistency(ndn::nfd::FacePersistency newPersistency)
|
||||
{
|
||||
if (newPersistency != ndn::nfd::FACE_PERSISTENCY_PERMANENT) {
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("MulticastUdpTransport supports only FACE_PERSISTENCY_PERMANENT"));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MulticastUdpTransport::doSend(Transport::Packet&& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
m_sendSocket.async_send_to(boost::asio::buffer(packet.packet), m_multicastGroup,
|
||||
bind(&MulticastUdpTransport::handleSend, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred,
|
||||
packet.packet));
|
||||
}
|
||||
|
||||
void
|
||||
MulticastUdpTransport::doClose()
|
||||
{
|
||||
if (m_sendSocket.is_open()) {
|
||||
NFD_LOG_FACE_TRACE("Closing sending socket");
|
||||
|
||||
// Cancel all outstanding operations and close the socket.
|
||||
// Use the non-throwing variants and ignore errors, if any.
|
||||
boost::system::error_code error;
|
||||
m_sendSocket.cancel(error);
|
||||
m_sendSocket.close(error);
|
||||
}
|
||||
|
||||
DatagramTransport::doClose();
|
||||
}
|
||||
|
||||
template<>
|
||||
Transport::EndpointId
|
||||
DatagramTransport<boost::asio::ip::udp, Multicast>::makeEndpointId(const protocol::endpoint& ep)
|
||||
{
|
||||
// IPv6 multicast is not supported
|
||||
BOOST_ASSERT(ep.address().is_v4());
|
||||
|
||||
return (static_cast<uint64_t>(ep.port()) << 32) |
|
||||
static_cast<uint64_t>(ep.address().to_v4().to_ulong());
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,79 @@
|
||||
/* -*- 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_FACE_MULTICAST_UDP_TRANSPORT_HPP
|
||||
#define NFD_DAEMON_FACE_MULTICAST_UDP_TRANSPORT_HPP
|
||||
|
||||
#include "datagram-transport.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
// Explicit specialization of makeEndpointId for the UDP multicast case.
|
||||
// Note that this "shall be declared before the first use of the specialization
|
||||
// that would cause an implicit instantiation to take place, in every translation
|
||||
// unit in which such a use occurs".
|
||||
template<>
|
||||
Transport::EndpointId
|
||||
DatagramTransport<boost::asio::ip::udp, Multicast>::makeEndpointId(const protocol::endpoint& ep);
|
||||
|
||||
/**
|
||||
* \brief A Transport that communicates on a UDP multicast group
|
||||
*/
|
||||
class MulticastUdpTransport DECL_CLASS_FINAL : public DatagramTransport<boost::asio::ip::udp, Multicast>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Creates a UDP-based transport for multicast communication
|
||||
* \param localEndpoint local endpoint
|
||||
* \param multicastGroup multicast group
|
||||
* \param recvSocket socket used to receive packets
|
||||
* \param sendSocket socket used to send to the multicast group
|
||||
*/
|
||||
MulticastUdpTransport(const protocol::endpoint& localEndpoint,
|
||||
const protocol::endpoint& multicastGroup,
|
||||
protocol::socket&& recvSocket,
|
||||
protocol::socket&& sendSocket);
|
||||
|
||||
protected:
|
||||
virtual void
|
||||
beforeChangePersistency(ndn::nfd::FacePersistency newPersistency) DECL_FINAL;
|
||||
|
||||
private:
|
||||
virtual void
|
||||
doSend(Transport::Packet&& packet) DECL_FINAL;
|
||||
|
||||
virtual void
|
||||
doClose() DECL_FINAL;
|
||||
|
||||
private:
|
||||
protocol::endpoint m_multicastGroup;
|
||||
protocol::socket m_sendSocket;
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_MULTICAST_UDP_TRANSPORT_HPP
|
||||
@@ -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
|
||||
@@ -1,70 +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_FACE_NDNLP_PARSE_HPP
|
||||
#define NFD_DAEMON_FACE_NDNLP_PARSE_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
#include "ndnlp-tlv.hpp"
|
||||
|
||||
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
|
||||
* NdnlpSequence
|
||||
* NdnlpFragIndex?
|
||||
* NdnlpFragCount?
|
||||
* NdnlpPayload
|
||||
*/
|
||||
class NdnlpData
|
||||
{
|
||||
public:
|
||||
/** \brief parse a NdnlpData packet
|
||||
*
|
||||
* \exception ParseError packet is malformated
|
||||
*/
|
||||
void
|
||||
wireDecode(const Block& wire);
|
||||
|
||||
public:
|
||||
uint64_t m_seq;
|
||||
uint16_t m_fragIndex;
|
||||
uint16_t m_fragCount;
|
||||
Block m_payload;
|
||||
};
|
||||
|
||||
} // namespace ndnlp
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_NDNLP_PARSE_HPP
|
||||
@@ -1,137 +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-partial-message-store.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace ndnlp {
|
||||
|
||||
PartialMessage::PartialMessage()
|
||||
: m_fragCount(0)
|
||||
, m_received(0)
|
||||
, m_totalLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
PartialMessage::add(uint16_t fragIndex, uint16_t fragCount, const Block& payload)
|
||||
{
|
||||
if (m_received == 0) { // first packet
|
||||
m_fragCount = fragCount;
|
||||
m_payloads.resize(fragCount);
|
||||
}
|
||||
|
||||
if (m_fragCount != fragCount || fragIndex >= m_fragCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_payloads[fragIndex].empty()) { // duplicate
|
||||
return false;
|
||||
}
|
||||
|
||||
m_payloads[fragIndex] = payload;
|
||||
++m_received;
|
||||
m_totalLength += payload.value_size();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PartialMessage::isComplete() const
|
||||
{
|
||||
return m_received == m_fragCount;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
return Block(buffer);
|
||||
}
|
||||
|
||||
PartialMessageStore::PartialMessageStore(const time::nanoseconds& idleDuration)
|
||||
: m_idleDuration(idleDuration)
|
||||
{
|
||||
}
|
||||
|
||||
PartialMessageStore::~PartialMessageStore()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
PartialMessageStore::receiveNdnlpData(const Block& pkt)
|
||||
{
|
||||
NdnlpData parsed;
|
||||
parsed.wireDecode(pkt);
|
||||
if (parsed.m_fragCount == 1) { // single fragment
|
||||
this->onReceive(parsed.m_payload.blockFromValue());
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t messageIdentifier = parsed.m_seq - parsed.m_fragIndex;
|
||||
shared_ptr<PartialMessage> pm = m_partialMessages[messageIdentifier];
|
||||
if (!static_cast<bool>(pm)) {
|
||||
m_partialMessages[messageIdentifier] = pm = make_shared<PartialMessage>();
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PartialMessageStore::scheduleCleanup(uint64_t messageIdentifier,
|
||||
shared_ptr<PartialMessage> partialMessage)
|
||||
{
|
||||
partialMessage->m_expiry = scheduler::schedule(m_idleDuration,
|
||||
bind(&PartialMessageStore::cleanup, this, messageIdentifier));
|
||||
}
|
||||
|
||||
void
|
||||
PartialMessageStore::cleanup(uint64_t messageIdentifier)
|
||||
{
|
||||
std::map<uint64_t, shared_ptr<PartialMessage> >::iterator it =
|
||||
m_partialMessages.find(messageIdentifier);
|
||||
if (it == m_partialMessages.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
scheduler::cancel(it->second->m_expiry);
|
||||
m_partialMessages.erase(it);
|
||||
}
|
||||
|
||||
} // namespace ndnlp
|
||||
} // namespace nfd
|
||||
@@ -1,106 +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_FACE_NDNLP_PARTIAL_MESSAGE_STORE_HPP
|
||||
#define NFD_DAEMON_FACE_NDNLP_PARTIAL_MESSAGE_STORE_HPP
|
||||
|
||||
#include "ndnlp-parse.hpp"
|
||||
#include "core/event-emitter.hpp"
|
||||
#include "core/scheduler.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace ndnlp {
|
||||
|
||||
/** \brief represents a partially received message
|
||||
*/
|
||||
class PartialMessage : noncopyable
|
||||
{
|
||||
public:
|
||||
PartialMessage();
|
||||
|
||||
bool
|
||||
add(uint16_t fragIndex, uint16_t fragCount, const Block& payload);
|
||||
|
||||
bool
|
||||
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
|
||||
*/
|
||||
Block
|
||||
reassemble();
|
||||
|
||||
public:
|
||||
EventId m_expiry;
|
||||
|
||||
private:
|
||||
size_t m_fragCount;
|
||||
size_t m_received;
|
||||
std::vector<Block> m_payloads;
|
||||
size_t m_totalLength;
|
||||
};
|
||||
|
||||
/** \brief provides reassembly feature at receiver
|
||||
*/
|
||||
class PartialMessageStore : noncopyable
|
||||
{
|
||||
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
|
||||
*/
|
||||
void
|
||||
receiveNdnlpData(const Block& pkt);
|
||||
|
||||
/// fires when network layer packet is received
|
||||
EventEmitter<Block> onReceive;
|
||||
|
||||
private:
|
||||
void
|
||||
scheduleCleanup(uint64_t messageIdentifier, shared_ptr<PartialMessage> partialMessage);
|
||||
|
||||
void
|
||||
cleanup(uint64_t messageIdentifier);
|
||||
|
||||
private:
|
||||
std::map<uint64_t, shared_ptr<PartialMessage> > m_partialMessages;
|
||||
|
||||
time::nanoseconds m_idleDuration;
|
||||
};
|
||||
|
||||
} // namespace ndnlp
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_NDNLP_PARTIAL_MESSAGE_STORE_HPP
|
||||
@@ -1,90 +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_FACE_NDNLP_SEQUENCE_GENERATOR_HPP
|
||||
#define NFD_DAEMON_FACE_NDNLP_SEQUENCE_GENERATOR_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace ndnlp {
|
||||
|
||||
/** \brief represents a block of sequence numbers
|
||||
*/
|
||||
class SequenceBlock
|
||||
{
|
||||
public:
|
||||
SequenceBlock(uint64_t start, size_t count);
|
||||
|
||||
/** \return{ the pos-th sequence number }
|
||||
*/
|
||||
uint64_t
|
||||
operator[](size_t pos) const;
|
||||
|
||||
size_t
|
||||
count() const;
|
||||
|
||||
private:
|
||||
uint64_t m_start;
|
||||
size_t m_count;
|
||||
};
|
||||
|
||||
inline uint64_t
|
||||
SequenceBlock::operator[](size_t pos) const
|
||||
{
|
||||
if (pos >= m_count)
|
||||
throw std::out_of_range("pos");
|
||||
return m_start + static_cast<uint64_t>(pos);
|
||||
}
|
||||
|
||||
inline size_t
|
||||
SequenceBlock::count() const
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
/** \class SequenceGenerator
|
||||
* \brief generates sequence numbers
|
||||
*/
|
||||
class SequenceGenerator : noncopyable
|
||||
{
|
||||
public:
|
||||
SequenceGenerator();
|
||||
|
||||
/** \brief generates a block of consecutive sequence numbers
|
||||
*
|
||||
* This block must not overlap with a recent block.
|
||||
*/
|
||||
SequenceBlock
|
||||
nextBlock(size_t count);
|
||||
|
||||
private:
|
||||
/// next sequence number
|
||||
uint64_t m_next;
|
||||
};
|
||||
|
||||
} // namespace ndnlp
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_NDNLP_SEQUENCE_GENERATOR_HPP
|
||||
@@ -1,130 +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-slicer.hpp"
|
||||
|
||||
#include <ndn-cxx/encoding/encoding-buffer.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace ndnlp {
|
||||
|
||||
Slicer::Slicer(size_t mtu)
|
||||
: m_mtu(mtu)
|
||||
{
|
||||
this->estimateOverhead();
|
||||
}
|
||||
|
||||
Slicer::~Slicer()
|
||||
{
|
||||
}
|
||||
|
||||
template<bool T>
|
||||
static inline size_t
|
||||
Slicer_encodeFragment(ndn::EncodingImpl<T>& blk,
|
||||
uint64_t seq, uint16_t fragIndex, uint16_t fragCount,
|
||||
const uint8_t* payload, size_t payloadSize)
|
||||
{
|
||||
size_t totalLength = 0;
|
||||
|
||||
// NdnlpPayload
|
||||
size_t payloadLength = blk.prependByteArray(payload, payloadSize);
|
||||
totalLength += payloadLength;
|
||||
totalLength += blk.prependVarNumber(payloadLength);
|
||||
totalLength += blk.prependVarNumber(tlv::NdnlpPayload);
|
||||
|
||||
bool needFragIndexAndCount = fragCount > 1;
|
||||
if (needFragIndexAndCount) {
|
||||
// NdnlpFragCount
|
||||
size_t fragCountLength = blk.prependNonNegativeInteger(fragCount);
|
||||
totalLength += fragCountLength;
|
||||
totalLength += blk.prependVarNumber(fragCountLength);
|
||||
totalLength += blk.prependVarNumber(tlv::NdnlpFragCount);
|
||||
|
||||
// NdnlpFragIndex
|
||||
size_t fragIndexLength = blk.prependNonNegativeInteger(fragIndex);
|
||||
totalLength += fragIndexLength;
|
||||
totalLength += blk.prependVarNumber(fragIndexLength);
|
||||
totalLength += blk.prependVarNumber(tlv::NdnlpFragIndex);
|
||||
}
|
||||
|
||||
// NdnlpSequence
|
||||
uint64_t sequenceBE = htobe64(seq);
|
||||
size_t sequenceLength = blk.prependByteArray(
|
||||
reinterpret_cast<uint8_t*>(&sequenceBE), sizeof(sequenceBE));
|
||||
totalLength += sequenceLength;
|
||||
totalLength += blk.prependVarNumber(sequenceLength);
|
||||
totalLength += blk.prependVarNumber(tlv::NdnlpSequence);
|
||||
|
||||
// NdnlpData
|
||||
totalLength += blk.prependVarNumber(totalLength);
|
||||
totalLength += blk.prependVarNumber(tlv::NdnlpData);
|
||||
|
||||
return totalLength;
|
||||
}
|
||||
|
||||
void
|
||||
Slicer::estimateOverhead()
|
||||
{
|
||||
ndn::EncodingEstimator estimator;
|
||||
size_t estimatedSize = Slicer_encodeFragment(estimator,
|
||||
0, 0, 2, 0, m_mtu);
|
||||
|
||||
size_t overhead = estimatedSize - m_mtu;
|
||||
m_maxPayload = m_mtu - overhead;
|
||||
}
|
||||
|
||||
PacketArray
|
||||
Slicer::slice(const Block& block)
|
||||
{
|
||||
BOOST_ASSERT(block.hasWire());
|
||||
const uint8_t* networkPacket = block.wire();
|
||||
size_t networkPacketSize = block.size();
|
||||
|
||||
uint16_t fragCount = static_cast<uint16_t>(
|
||||
(networkPacketSize / m_maxPayload) +
|
||||
(networkPacketSize % m_maxPayload == 0 ? 0 : 1)
|
||||
);
|
||||
PacketArray pa = make_shared<std::vector<Block> >();
|
||||
pa->reserve(fragCount);
|
||||
SequenceBlock seqBlock = m_seqgen.nextBlock(fragCount);
|
||||
|
||||
for (uint16_t fragIndex = 0; fragIndex < fragCount; ++fragIndex) {
|
||||
size_t payloadOffset = fragIndex * m_maxPayload;
|
||||
const uint8_t* payload = networkPacket + payloadOffset;
|
||||
size_t payloadSize = std::min(m_maxPayload, networkPacketSize - payloadOffset);
|
||||
|
||||
ndn::EncodingBuffer buffer(m_mtu, 0);
|
||||
size_t pktSize = Slicer_encodeFragment(buffer,
|
||||
seqBlock[fragIndex], fragIndex, fragCount, payload, payloadSize);
|
||||
|
||||
BOOST_ASSERT(pktSize <= m_mtu);
|
||||
|
||||
pa->push_back(buffer.block());
|
||||
}
|
||||
|
||||
return pa;
|
||||
}
|
||||
|
||||
} // namespace ndnlp
|
||||
} // namespace nfd
|
||||
Loaded 100 of 494 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user