291 Commits

Author SHA1 Message Date
Davide Pesavento 36b78ea6ee ci: add build testing against named-data PPA
Change-Id: I42c0901dc152986706b0c7b7f908dff80c23064b
2023-11-25 23:11:24 -05:00
Davide Pesavento 7e9d7e4f9a Switch to Face::getIoContext()
Change-Id: Ice05b0b8e9af4ed4651abcf6fc4ea6b84c34da7c
2023-11-11 15:00:03 -05:00
Davide Pesavento 816767b4c2 build: disable -Wnon-virtual-dtor compiler warning
See also named-data/NFD@0a05f7aea6

Change-Id: If93d766fa8ee2b0cb6a0eb8ff9febc2dc0a4cac0
2023-10-17 15:40:22 -04:00
Davide Pesavento 2ab04a2b9f build: require boost >= 1.71.0
Refs: #5276
Change-Id: Ib62b24b041e21b2c017cd9c290f7d5dc09003d63
2023-09-15 22:08:22 -04:00
Davide Pesavento b6e10dd86a build: use python f-strings
Change-Id: I5a6537d263d8bd6297b0975f34c90dd76b9468cd
2023-09-11 21:41:24 -04:00
Davide Pesavento 4a9e0b194b build: update waf to version 2.0.26
Change-Id: I8fa8a8906617769f7cc511848b9e64fd6a314334
2023-08-19 01:48:02 -04:00
Junxiao Shi 869d73e924 Change namespace of DummyClientFace, Signal, Segmenter
refs #3940

Change-Id: I67ca0ecb8c916aab411a2f90454e0d25925978cd
2023-08-10 22:52:26 +00:00
Davide Pesavento dd808b0bae build: enable a few more compiler warnings
Refactor default-compiler-flags.py to reduce duplication

Change-Id: I40bf0b1d94356dcaac3bdfebd66af920ef3d5aff
2023-08-06 16:00:02 -04:00
Davide Pesavento 8148cd4a96 build: decrease level of debug information produced by default
Refs: #5279
Change-Id: Ie73909de8c51300abb00c873af722d730e6b70e1
2023-08-06 14:01:32 -04:00
Davide Pesavento 0df0e1c5b0 dissect: avoid deprecated overload of ndn::escape
Change-Id: Ifb9ffa1400b4109b4400f59367a079dac3a4e792
2023-04-25 15:50:05 -04:00
Davide Pesavento 003e45a9f3 build: fix detection of libpcap on Ubuntu 23.04
Beginning with version 1.10.2, pcap-config treats
unrecognized command-line options as an error.

Change-Id: Iba62d6d4586cf505c68032338048d04597baff96
2023-04-25 15:25:03 -04:00
Davide Pesavento 3653daedb6 tests: use std::optional
Change-Id: I53feb53061cd8374bc296b7dfd13175d7c7d4e37
2023-03-13 17:44:22 -04:00
Davide Pesavento ad26607467 build: drop official support for Ubuntu 18.04 and macOS 10.15
Increase the minimum required version of clang to 7.0 on linux, because
older versions fail to compile libstdc++'s implementation of std::variant

Change-Id: I5cde13b8789fceb5715d5496aeed7f9050ec801d
2023-03-07 21:14:42 -05:00
Davide Pesavento a22a742de4 build: switch source archive to xz compression
Change-Id: I8ec1968161aa6c85bf9ba7dd7859e81b160fabfb
2023-02-14 23:56:46 -05:00
Davide Pesavento c2297b11d2 ci: adopt reusable workflows from named-data/actions
Change-Id: I372cc2fa1b26cede28982bbd88ca445eb08eef5c
2023-02-08 13:22:22 -05:00
Davide Pesavento db9613e5fd Minor README improvements; fix outdated URLs
Change-Id: Ia57f83892471ad85a2301ba4c8ab3df144581000
2023-01-21 02:22:27 -05:00
Davide Pesavento 3b4ee2f130 Prepare release 22.12
Refs: #5250
Change-Id: Icc0cfa76328fd4faef152edc3330fa2c95857668
2022-12-31 01:55:06 -05:00
Davide Pesavento be4f1891bd build: update waf to version 2.0.24
Change-Id: Ia27b29d77dd8b4d0714e4e724f5814eefacfe4d5
2022-12-02 20:33:45 -05:00
Davide Pesavento d66fb491df dissect: recognize TLV elements related to Certificate and SafeBag
And drop obsolete types

Change-Id: Iadf2a323a52cd12b93981b99d68103d934d5d508
2022-11-30 19:52:35 -05:00
Davide Pesavento 6f16856fc2 ci: add Xcode 14.1
Change-Id: I0dbc2eec5a50239415361292a0597ffa19b05ce1
2022-11-14 19:40:04 -05:00
Davide Pesavento b61e3e2174 putchunks: use ndn-cxx's Segmenter
Change-Id: I2a2bdac2983cce45c6e6d8f5b41a5609b4a98c48
2022-11-11 14:38:52 -05:00
Davide Pesavento 3d7b03372b build: link with lld if available
Change-Id: I14c83c7038abd5d1b58eee3d8a3b6db127ef4b58
2022-10-05 15:30:02 -04:00
Varun Patil 0168d281c6 dissect-wireshark: add type, len, bin fields
Change-Id: Ib5134f03f0d4ecc3bc19bddb9a87c4a573fbc196
2022-09-18 16:37:00 -07:00
Davide Pesavento 6b430e963a tests: delete unused code
Change-Id: I305e9d1a46b69196ab89a0de8ddb90ee9ce263ad
2022-09-18 18:55:05 -04:00
Davide Pesavento b97a1122e3 ci: refresh GitHub Actions matrix
* Add ubuntu-22.04, remove 18.04
 * Add macos-12, remove 10.15

Change-Id: I66908bb493100d9c7a6edda2a72e3a536b81b337
2022-08-12 18:26:07 -04:00
Davide Pesavento bd3642f31d ci: auto-detect the OS instead of relying on NODE_LABELS
And remove WAF_JOBS: waf already defaults to the number of available
CPUs, which is appropriate in most cases, and we can always use the
built-in JOBS variable to override it where necessary.

Change-Id: Id132b9ef8467a563694222ccc64a676cdc076e17
2022-08-12 18:19:31 -04:00
Davide Pesavento 423e58a503 build+ci: support macOS on arm64
Refs: #5135
Change-Id: I25a6a77eb6c60e00548704eaea88eb1ca2afc200
2022-08-12 15:51:42 -04:00
Davide Pesavento f597d07ec9 build: support CentOS Stream 9, drop CentOS 8
Refs: #5181
Change-Id: I289930c9658137e1637357f81c762ebb331474c8
2022-07-08 17:52:51 -04:00
Sichen Song 40eae0328b catchunks: avoid excess window decrease in certain conditions
Refs: #5202
Change-Id: I7eeed18fbdfc3ef7a5a277da34f9de0c7068a61d
2022-05-23 21:46:03 -04:00
Davide Pesavento 832d2300ee tests: remove unused KeyChainFixture::makeCert()
If similar functionality is needed in the future,
KeyChain::makeCertificate() should be used instead.

Change-Id: I918a957b70e1516db2b319bd0587d3daa62c18d1
2022-05-13 14:26:51 -04:00
Davide Pesavento f36375232f tests: expect a certificate name in KeyLocator
Refs: #5112
Change-Id: I0481f0f03671530d47d33d27416a33ab52ab3ae1
2022-04-20 17:05:06 -04:00
Davide Pesavento 824c45b503 ci: require gcovr 5.1 for code coverage reports
Stop passing `-j`, it wasn't very useful and it's broken in gcovr 5.1

Change-Id: I12ef24e809b5a500f5c237b29c603c0058ca73fc
2022-04-19 16:10:42 -04:00
Davide Pesavento 242d5063f7 dissect+peek: avoid deprecated ndn-cxx functions
Change-Id: Ibd9f8ad30e315f537d1560db823372af3d58d713
2022-03-12 16:08:34 -05:00
Davide Pesavento 96412a18d8 build: align minimum clang dependency with ndn-cxx
ndn-cxx requires clang 6 or later, so there's no point
supporting older versions in ndn-tools

Change-Id: I7be683abd4fce12c85187c0b5abf2ee288bbe908
2022-03-05 14:45:04 -05:00
Davide Pesavento b04c52b044 build: raise minimum build requirements
* Hard-depend on gcc >= 7.4 and clang >= 5.0, which have
   almost complete C++17 support
 * Require Xcode 10 on macOS but recommend 11.3 or later
 * Boost >= 1.65.1 is now a hard requirement

Change-Id: I76eb915b226e8f5dd5c5fdbde9b23befc2a37c90
2022-02-20 15:40:02 -05:00
Davide Pesavento b3570c614a build: switch to C++17
Change-Id: Id6217b5c993f3e4726e89773128b565e5f136bb6
2022-02-20 15:35:23 -05:00
Davide Pesavento ebea9094a3 Prepare release 22.02
Change-Id: If7e6cb33fb658fa91549a2cbbd2e3f992e20103e
2022-02-18 11:30:32 -05:00
Davide Pesavento 5998428e9c Avoid deprecated ndn-cxx functions
Change-Id: I5d9ac045740267db783ff724c938b659b49c40ee
2022-02-16 22:41:03 -05:00
Junxiao Shi ed0017bd07 dump: replace pcap_lookupdev with pcap_findalldevs
pcap_lookupdev API is deprecated in favor of pcap_findalldevs.

refs #4797

Change-Id: I0f2a9d17368daa500c1fae0281f0c8171c93415b
2022-02-04 02:16:39 +00:00
Junxiao Shi fd2d1012c7 ndnpeek: replace --link-file with --fwhint
refs #4207, #5187

Change-Id: I8213e971520d3edab631634a03bf7950d265dc11
2022-01-11 18:20:38 +00:00
Davide Pesavento 50882ebf1d build: update waf to version 2.0.23
Change-Id: I2afeee792c0b6627d979c7c175862ae25507599b
2021-12-29 13:23:23 -05:00
Davide Pesavento 84eb4873c8 dissect-wireshark: recognize ForwardingHint
Refs: #4185
Change-Id: I42619aaedf7aa4dbb32d204c46c67a8df541a272
2021-12-20 21:11:22 -05:00
Davide Pesavento 38dca3952a dissect-wireshark: update TLV type of IncomingFaceId
Refs: #5185
Change-Id: I9949f55b64882db61179aba4d5b3395f26c47533
2021-12-20 20:50:45 -05:00
Davide Pesavento 585e18a5e3 dissect-wireshark: minor cleanups
Change-Id: I4b62396b1ff574537f46df5c4f3489d54006b80e
2021-11-27 23:00:16 -05:00
Davide Pesavento 918652862c dissect-wireshark: fix decoding of several fields
HopLimit and PitToken are not NonNegativeIntegers.
ApplicationParameters and Content are not strings but arbitrary bytes.
Recognize "None" values in NackReason and CachePolicyType.

Refs: #3197, #4517
Change-Id: I18c55a638bf5985d8ec4a1f2a76dba7b7e4407ad
2021-11-27 22:46:54 -05:00
Davide Pesavento 89b52d4639 dissect-wireshark: recognize ParametersSha256DigestComponent
Refs: #4517
Change-Id: I385cdee9d30fb6b1832a0c366f8eb808488fbbaa
2021-11-27 22:46:17 -05:00
Davide Pesavento 200014a739 dissect-wireshark: remove support for obsolete TLV elements
Change-Id: I83cf827c89acb99784b4ab421feda76113de5c39
2021-11-27 21:25:45 -05:00
Davide Pesavento 79482ec462 dissect: add signed Interest fields and more name component types
Change-Id: Id009dbf254e17e7fc497385ca6868ae085abb82f
2021-11-24 21:07:36 -05:00
Davide Pesavento 2c8ec07ae5 ci: add macOS 11 Big Sur
Remove all traces of Travis CI

Change-Id: Ic0a802db8a2ec5dfef093321b3bc0a7c736b5a5c
2021-09-30 00:04:23 -04:00
Davide Pesavento 8c35390e61 ci: use gcovr 5.0 to generate code coverage reports
Change-Id: I680b476bb93cffff389071437e7a818f16b6334d
2021-08-30 19:10:36 -04:00
Davide Pesavento c4343232bc ci: restrict token permissions and add badges to README.md
Change-Id: I057fab1370f4f3941bf3fe1de9c6d99198e3bd71
2021-08-13 23:17:05 -04:00
Davide Pesavento f8d9a531dd Eradicate all uses of std::bind()
Change-Id: I6e1ccf2d87b76142e6d519c1a288d03022e4d167
2021-07-30 20:35:06 -04:00
Davide Pesavento e8c82ef8a1 ci: add GitHub Actions
Change-Id: Ic7ed7356fef4af465843b44a5cefd0458c78774d
2021-07-30 19:50:03 -04:00
Eric Newberry a209f6747f docs: use typed name components instead of markers
refs #5044

Change-Id: I3083fd733dabca549e5e21d47b42e2dd1e4ea802
2021-03-26 11:02:31 -07:00
Davide Pesavento 7c4246ca67 putchunks: increase the default segment size to 8000 bytes
Change-Id: I16c2e21f168c77259d6bdc47b86fceb258521517
2021-03-12 20:00:32 -05:00
Davide Pesavento f8a14d88cb chunks: add --naming-convention option
Refs: #5109
Change-Id: I98170dd362663900900e9f792ffb5340ad96fe3a
2021-03-12 00:42:03 -05:00
Davide Pesavento a420e97fed dissect: no longer dissect Content element by default
Use the new -c/--content option to enable it

Change-Id: Id5692b53a0921918bb029ad653b9f5504ab5e4ab
2021-02-25 18:25:26 -05:00
Davide Pesavento 3f588caea2 dissect: do not try to dissect the TLV-VALUE of SignatureValue
Change-Id: Idd3fce801d7ca7f0bc8a8c8972ceea43c2735c18
2021-02-24 15:48:33 -05:00
Davide Pesavento 7ef5cf7f24 dissect: use Unicode characters to draw the TLV tree on the terminal
Change-Id: If92176528361cb57f5e5a0a31a9c501d7fff54e7
2021-01-29 00:20:24 -05:00
Davide Pesavento 9b1fd4b332 dissect: print offset of parsing error
Change-Id: I2209a16330e513b46abe2dfcc57ca780b3478b82
2021-01-26 22:16:02 -05:00
Davide Pesavento 6929b4344a poke: change the short form of --freshness to -f
For consistency with ndnpingserver and ndnputchunks

Change-Id: I82afc6de29e207d65bf885b0acbabfc9da05a5a7
2021-01-26 17:07:58 -05:00
Davide Pesavento 814ad34909 poke+pingserver: remove deprecated command-line options
Change-Id: Ic5518f1ca54edcb4a4c4fbe16f96b207dc867ebf
2021-01-26 16:08:53 -05:00
Davide Pesavento a0e6b60e8f Cleanup includes in common.hpp
Change-Id: I1bb08a44726de5c880e6bc2f016506e6083e919b
2021-01-21 19:47:04 -05:00
Davide Pesavento 3047ba4741 ci+docs: CentOS renamed the PowerTools repo to lowercase
Change-Id: I3868d1763c5b9d060603e440627ad8990de3ae4e
2020-12-27 20:00:06 -05:00
Davide Pesavento 6677762595 tests: sync common testing infrastructure with ndn-cxx and NFD
And upgrade waf to version 2.0.21

Change-Id: Id713e0f3035badd97ca7fc03f76e50085b9a266c
2020-11-24 15:18:18 -05:00
Eric Newberry 374f4e47b5 Prepare release 0.7.1
refs #5129

Change-Id: Idb9c7ccbf764be3d61b9a58dd0bd4ecfca5c63d5
2020-10-08 16:20:15 -07:00
Davide Pesavento 02ec47c8ac ci: add clang 12 (dev snapshot) to Travis CI build matrix
Change-Id: I45266be56d700434b84aab5f5954828f5df1b598
2020-08-09 02:23:07 -04:00
Davide Pesavento 9a1b65d0da ci: disable frames in lcov HTML coverage report
Change-Id: Ie7ecce199aefc37b95d721f1032ac69ebe3f8338
2020-08-06 17:27:58 -04:00
Davide Pesavento 352755871f tests: avoid deprecated Data::getSignature()
Change-Id: Ica204fe6cd60f070b49f9ec5b72c0f68a32065d6
2020-07-27 18:02:03 -04:00
Davide Pesavento d653afaf01 ci: add Xcode 11.6 and 12 to Travis CI build matrix
Change-Id: I14c9635b56dac2c7988734d72adf8c41c5c5540e
2020-07-01 22:35:25 -04:00
Alexander Afanasyev 28181ee93a Adjust includes for the updated locations of ndn-cxx security headers
Change-Id: Ia4a82d7a4a56bfa88e62adab6a1e31bbe459e773
2020-06-06 17:53:32 -04:00
Alexander Afanasyev 298c4355c3 Rename VERSION to VERSION.info to avoid conflicts with modern STL
On case-insensitive file systems (e.g., macOS), inclusion of the new
standard <version> header resulted in unexpected inclusion of VERSION
file.

Change-Id: Ib08d8e9efa0f6ed0cee6843b818b773485dc73d8
2020-05-31 15:40:28 -04:00
Davide Pesavento b07d7a96da build: align minimum build dependencies with ndn-cxx
* Recommend boost >= 1.65.1 and gcc >= 7.4.0
 * Require clang >= 4.0, or Xcode >= 9.0 on macOS
 * Silence an ABI-related diagnostic message from gcc on armv7

Refs: #5087, #5106
Change-Id: I88ef0e0f183736f19ac414a84baebb0e1073381b
2020-05-14 02:25:24 -04:00
Davide Pesavento 8a2907ea04 ci: avoid exceeding Travis time limit on arm64
Change-Id: I9c3802e07c49ed33460b6f2341950ad0b6bee71a
2020-04-16 00:02:23 -04:00
Davide Pesavento d5c2447b3a ci: build ndn-cxx with AddressSanitizer
Change-Id: I706ab29efe61c17511b87b477151d9a2a8e055bc
2020-04-01 18:28:51 -04:00
Davide Pesavento fce3963fc0 ci: use https URL in git clone command
Change-Id: I35c7ffa2e03957084b74c2db183780a70b5aab27
2020-03-31 23:16:55 -04:00
Davide Pesavento d8398820f1 ci: add CentOS 8 support; drop CentOS 7
Refs: #5040, #5087
Change-Id: Ia680fecc41d16d21d7b03f117a30a2966cf46679
2020-03-29 21:39:11 -04:00
Davide Pesavento a1a9d704ba build: switch to python3
Refs: #5095
Change-Id: I7e7a3a5cd49d69c6e389060ccf8fe30599ebd876
2020-03-29 01:04:31 -04:00
Davide Pesavento 4ab5eed35d tests: fix ndndump unit tests with latest ndn-cxx
Change-Id: Ib2a149266644cb40780e1c34b9885c70d31829b2
2020-03-12 20:50:04 -04:00
Davide Pesavento 9fa6a78e17 ci: update Travis configuration
* Add testing on arm64, ppc64le, and s390x with select compiler versions
 * Drop all versions of gcc < 7 and clang < 5
 * Add clang 11 (development branch)
 * Reenable ASan on Linux with clang 7, the upstream bug has been fixed
 * Drop Xcode 9.2 (macOS 10.12 is no longer supported)
 * Upgrade Xcode 11 to 11.3
 * Workaround issue with missing /usr/local/opt/openssl on macOS
 * Various cleanups

Change-Id: Ifc7224cf3e79c74225efefc278bcb547ac862698
2020-03-10 19:47:06 -04:00
Eric Newberry 3b0fccd9bb docs: restructure and update AUTHORS.md
refs #5078

Change-Id: Icb0b798ef13fa96bb46b8c0376bcffac1c9e78cd
2020-02-04 15:03:10 -08:00
Davide Pesavento 9b70f57f8d build: upgrade waf to version 2.0.19
Change-Id: I5c4829bb8e80c27f57ad9b993c106445461f42a2
2020-01-15 01:05:26 -05:00
Davide Pesavento 7d14815aaf build: increase version number
Refs: #5045
Change-Id: I95b8f09faafdebec9d734a7c6c3fcf7b52d4e25c
2020-01-15 01:03:41 -05:00
Davide Pesavento 6ab7f911e0 Prepare release 0.7
Refs: #5045
Change-Id: I8765d3b68f2703ea28739f2f5b893a48f17293bd
2020-01-13 21:26:06 -05:00
Davide Pesavento a8600b0a6a tests: avoid deprecated boost headers; define BOOST_TEST_MODULE
Change-Id: Ie1e731e0943e635be36d65ea0dc02c348c17f05a
2019-12-22 18:52:36 -05:00
Davide Pesavento 2cd6ae8495 build: pass pkg_config_path to check_cfg() when looking for libndn-cxx
Instead of modifying os.environ

Refs: #5042
Change-Id: Ic39e871be1a6da027383a1a7d54be4f6611df15b
2019-11-04 00:11:07 -05:00
Klaus Schneider 4a2e89d88f catchunks: Improve CUBIC performance for lossy networks
Change-Id: I4baea5dcbc02d5c4a989330603e059daa55e767f
refs: #5036
2019-10-29 19:33:16 -07:00
Davide Pesavento 296b385c58 catchunks: add --no-version-discovery option
Refs: #5021
Change-Id: I37bb1f86c1a6d63ab28fbe116e75d1047c110217
2019-10-20 16:00:16 -04:00
Davide Pesavento 97a33b200d catchunks: simplify internal options handling
Change-Id: I537a281f6c996c2544c145ab9cc01a54272c8efa
2019-10-18 12:51:10 -04:00
Davide Pesavento 32c0df2e9e catchunks: silence new clang-10 warning "final-dtor-non-final-class"
Change-Id: I50052872199fb6ca621f4abe5ab2636735604373
2019-10-18 12:41:18 -04:00
Davide Pesavento 327fb4b0fd dump: update test cases for packet format v0.3
Refs: #4567, #4709
Change-Id: If14cfb8221182aa2c79add024108d5e3a21a189f
2019-10-14 19:01:27 -04:00
Davide Pesavento cbef7b8393 ci: upgrade Travis config to Ubuntu 18.04
Also in this commit:

 * Drop clang 3.8 (no easy way to install it on 18.04)
 * Add clang 10 (trunk)
 * Drop Xcode 8.3
 * Upgrade Xcode 10.2 to 10.3
 * Output folding markers to improve readability of CI logs

Change-Id: I7e6105f100110c74d6e947612fd3df81f7cbf43c
2019-10-09 00:15:13 -04:00
Davide Pesavento 11c69910f3 dump: add missing include
Change-Id: I617a9580216e4c579eebac702309b3610a8c6dcf
2019-09-01 01:30:13 -04:00
Davide Pesavento c214e073d8 peek: add --hop-limit option
Change-Id: I1d0179f498ce70166085e6934e015ff4c00b4858
2019-08-22 20:46:30 -04:00
Davide Pesavento 9602823383 peek: add --app-params and --app-params-file options
Change-Id: Ic1afb118d2e1a58d99d046e072a9df439e0020b3
2019-08-22 20:45:40 -04:00
Davide Pesavento 5e3773dd5a catchunks: switch to RttEstimatorWithStats
Refs: #4887
Change-Id: I8d49eff6ff4a7dc9ff49ffacc0744e50695128d2
2019-08-22 15:35:08 -04:00
Davide Pesavento 50cf6db473 peek: change --link-file option to expect a raw binary file
Change-Id: I952ebc55616307a939c4ecb5ae4019e27b7342bb
2019-07-29 20:40:10 -04:00
Davide Pesavento 0d4b182304 pingserver: change the short form of --freshness to -f
-x is still accepted but will print a deprecation warning

Change-Id: Ibc2e9750006a450c85d19c432ec1a02416cdc174
2019-07-27 19:35:13 -04:00
Davide Pesavento 7de32c1f2d poke: add --signing-info option
Supersedes --digest and --identity, which are now deprecated.

Change-Id: Ia4c57659874f134af0192aa1ca721ec1a58e7901
2019-07-27 16:53:46 -04:00
Davide Pesavento 0da1f44c79 chunks+peek+ping: use correct underlying type for time::milliseconds
Change-Id: I3f46f846401eccc0c11d3abcd1a5ebff89056f7d
2019-07-26 19:06:36 -04:00
Davide Pesavento 6a1396e2e0 poke: rename -f/--force option to -u/--unsolicited
The old name will still be accepted for some time,
but will print a deprecation warning if used.

This commit also improves --help output.

Change-Id: I2ebac82423a5276109f4b40b382312bd852419de
2019-07-26 19:05:45 -04:00
Davide Pesavento 6752d943ef catchunks: remove previously deprecated options
Change-Id: I0a7154dfd8879337f40524261fc854807dbc3d22
2019-07-26 19:00:20 -04:00
Davide Pesavento c5243b40f4 poke: don't respond if the Interest cannot be satisfied
Change-Id: I616e974ff041a4a2c9fd738e98c83c28a21a47de
2019-07-26 13:30:16 -04:00
Davide Pesavento b3ae634086 poke: add --verbose option
Change-Id: I435f01cf6625bebbea40a0f808d8456fafb01fe1
2019-07-25 21:07:16 -04:00
Davide Pesavento de01c81a92 poke: wait indefinitely if --timeout is not specified
Change-Id: I0051e65d27780d8b58a0c0febf3572b0c6a23e8c
2019-07-25 19:24:04 -04:00
Davide Pesavento 94dff006fc poke: exit with status 3 on timeout
Change-Id: Idb021fe1fa1c3d40dbcfc87d4b1dadbea6cb28f6
2019-07-25 19:20:22 -04:00
Davide Pesavento 87434bef4b poke: exit with status 5 if prefix registration fails
Change-Id: I2147570c37146011c9a4e8c024b74bcafdf18e4e
2019-07-25 19:04:23 -04:00
Davide Pesavento e75861eddb poke: code modernization and cleanup
Change-Id: Ia0d5f0b1bc495636f8fac127bec735cc35af66a7
2019-07-25 17:41:09 -04:00
Davide Pesavento c1eb2fcf4b ci: add Xcode 11 to Travis CI build matrix
Also reenable ASan on Linux with clang 9, it seems to be working now.

Change-Id: I7be5aef0e17dc42918ce991592f149a47dd85a6e
2019-07-17 15:44:33 -04:00
Davide Pesavento ba56066683 catchunks: adapt to recent RttEstimator API changes
Refs: #4887
Change-Id: Ie39a1c5f7ad8b225397f41bb0f3c4d7c2a9cdb2a
2019-06-26 22:48:14 -04:00
Davide Pesavento 0353bae5f6 ci: add gcc-9 to Travis CI build matrix
Change-Id: I719ef56d484ca6a743afe2ddd7486a2f43f59ad3
2019-06-24 20:47:00 -04:00
Davide Pesavento 65d115569e peek: code modernization and cleanup
Change-Id: I42d706aa02ab03557d708c729f65716c1c2d3494
2019-06-24 20:46:35 -04:00
Jeff Thompson 526ff43cdb peek: with --verbose, show Data name and Nack reason
Closes: https://github.com/named-data/ndn-tools/pull/2
Change-Id: I70fa2dd164caa9cbf986b0931c38c360a8d1b6ed
2019-06-09 01:33:36 -04:00
Davide Pesavento 70576403fe catchunks: use ndn-cxx's RttEstimator
Refs: #4887
Change-Id: If24bea40a22909bf0fd9e49ec7b18330dbe336f2
2019-06-07 16:42:21 -04:00
Junxiao Shi 9619295e9e tests: add FreshnessPeriod where MustBeFresh is used
refs #4913

Change-Id: I72366c3d84072bae61716b0cc229470124a2a0d5
2019-05-22 15:45:12 +00:00
Davide Pesavento 6cc1dfbdfd Prepare release 0.6.4
Refs: #4916
Change-Id: I8aa91d5314016e7f9698e4ee457f5a8d22f3ad67
2019-04-27 21:16:36 -04:00
Davide Pesavento 630b0087b4 ci: adapt to new repo layout for CentOS boost RPMs
Change-Id: I3e9d4279c66676c52630907a8190ca13d8a5a6ae
2019-04-20 16:36:55 -04:00
Davide Pesavento 786a7f2a38 Sync sphinx build config with ndn-cxx, improve README.md
Change-Id: Ib47bbe35f41b3a23523c0f66d7e5f321d7f82c2e
2019-04-14 17:34:30 -04:00
Davide Pesavento 84d8477ae6 catchunks: get rid of the last few remaining uses of Selectors
Refs: #4556
Change-Id: Ibe0e909c21b57aaa47c325bdef5852cb5e38482b
2019-04-08 19:00:25 -04:00
Davide Pesavento 105cd9e3a2 Parameters => ApplicationParameters
Refs: #4658
Change-Id: I8b69ab5e27612eecf068c6bf0ddb4b434cc29824
2019-04-08 19:00:01 -04:00
Klaus Schneider e90a3580d6 putchunks: include man files and add signing info
Change-Id: I3dc8fa2c690ce0bd052734d24f33ba5cd154b3c7
2019-04-05 12:51:37 -07:00
Chavoosh Ghasemi bb2d280580 catchunks: remove modular version discovery
refs: #4832, #4556
Change-Id: I99b4f42d1457c74321c9b6ae84f793a93c4c1436
2019-03-29 08:54:24 -07:00
Klaus Schneider 9e5122bafc catchunks: Implement CUBIC window adaptation
Also increase the RTT estimator multiplier k to 8.

Change-Id: I68c5096ac0da854f071bab5f7519b1c144f20ca1
refs: #4861
2019-03-21 20:03:34 -07:00
Davide Pesavento bf2c51716a chunks+ping: follow ndn::Scheduler API changes
Refs: #4883
Change-Id: I8aa48fe4f0613f529763f2efaf799c5db48a0b2c
2019-03-20 19:08:09 -04:00
Davide Pesavento c16ec575b8 ci: update .travis.yml
Change-Id: Ibc9443172511a27a056f685d893ec4182bc2f3ad
2019-03-18 18:40:48 -04:00
Davide Pesavento da85e25e59 Rename translation units containing main() to main.cpp
Also unify style of argv declaration

Change-Id: I1dcb8689b1cd38e042a0b1f05be7f98bd2d487ed
2019-03-18 18:24:20 -04:00
Davide Pesavento e4687a1d57 Remove abandoned ndn-pib tool
It has been broken and unmaintained for more than two years

Refs: #4205
Change-Id: I221c2b7f58a46ecd929241aff63199e059afd754
2019-03-18 18:23:42 -04:00
schneiderklaus d8197df500 catchunks: refactor in preparation for CUBIC pipeline.
Rename AIMD pipeline to "Adaptive Pipeline".
Remove "aimd-" from command line options.

Change-Id: Ie5689cf3c0b90bedb322fd42dbf289f8a04e56d2
refs: #4861
2019-03-17 22:50:57 -07:00
Davide Pesavento aacc7daf62 ndn::util::scheduler => ndn::scheduler
Refs: #4883
Change-Id: Icea8dd28ea1a24169ab97eff50a6b51aaab17708
2019-03-16 23:29:07 -04:00
schneiderklaus 8ff3abde93 catchunks: increase retx limit and improve statistics
Increased the retx limit from 3 to 15 (default in Linux TCP).
Added statistics about skipped retransmission.
Cleaned up statistic output.

Change-Id: I66ce9ac9fa08f7492f84bec48b7464ddb1228ab1
refs: #4861 #4603
2019-03-15 19:45:37 -07:00
Chavoosh Ghasemi 0c6fcb58ba catchunks: remove iterative version discovery method
refs: #4556
Change-Id: I22f35ea3c96a9eea32d478b13a52f9b3fba8442f
2019-03-06 08:40:48 -08:00
Chavoosh Ghasemi d8f9af2689 catchunks: add metadata-based version discovery
refs: #4556
Change-Id: I1100d1a4f14da8e66d190a7909185d67f7aa92a7
2019-03-01 12:45:17 -08:00
Chavoosh Ghasemi 5cb67014d3 catchunks: pass versioned name to onDiscoverySuccess signal
refs: #4556
Change-Id: I599bafcf70647bd806236f87f24d7a22f73a3505
2019-02-26 16:06:27 -08:00
Md Ashiqur Rahman 25c37f1557 ci: add support for CentOS 7
Refs: #4610
Change-Id: Ibf68c3040663dadfc61f0c9d9e92ff2d486b803a
2019-02-26 12:52:22 -05:00
Davide Pesavento 7b9837bbda dump: fix compilation on CentOS 7
Refs: #4852
Change-Id: I2550d26f709f645ee3d6b2e0f63a6698525e1a76
2019-02-26 02:00:14 -05:00
Davide Pesavento 80baddfb82 Replace all uses of BOOST_THROW_EXCEPTION with NDN_THROW
Refs: #4834
Change-Id: I1851f0b03f1192763b367ee6afba6860717420e7
2019-02-23 15:51:59 -05:00
Davide Pesavento ae37cf3eab build: do not look for unneeded libraries
Also a few cleanups in wscripts

Change-Id: Ia5b470d4adcf5697d8c0a31ba1204e5355951308
2019-02-20 18:19:22 -05:00
Davide Pesavento 252b70708d dissect-wireshark: update Interest Parameters TLV type
Refs: #4780
Change-Id: I4c1d2f50cd7355b273e5d63b7acc1af15b87344d
2019-02-10 20:02:14 -05:00
Alexander Afanasyev d5449e5656 Prepare release 0.6.3
Refs #4821
Change-Id: I46bc4f23085b2adf518e049b4543ae0ec12ba2c4
2019-02-04 14:39:23 -05:00
Junxiao Shi 06d008c184 chunks+poke+ping: use PendingInterestHandle and RegisteredPrefixHandle
refs #4316, #3919

Change-Id: Ia95362067a9024964cf67543c76375144b8a2782
2019-02-04 08:26:59 +00:00
Chavoosh Ghasemi 79991a0660 putchunks: respond to RDR discovery Interests
Change-Id: Id1039246304a3069f158aecf21724568db434958
refs: #4556
2019-02-02 21:41:19 -08:00
Junxiao Shi 7664b12f2a chunks+ping: don't pass Scheduler to ScopedEventId
It's no longer necessary.

refs #4698

Change-Id: I17ff7362bc46686057fa0df203c6b745e013b1d3
2019-01-23 16:45:17 +00:00
Davide Pesavento 3347eaad8e build: various cleanups
This commit also updates waf to version 2.0.14

Change-Id: I9334f10451589e8141583f85e6cefcf199f68490
2019-01-19 22:02:08 -05:00
Davide Pesavento cb903eac38 Add systemd unit file for ndnpingserver
Change-Id: I0b0b6358c2619a5251428d8e44df60cc06aec28a
Refs: #4594
2019-01-19 21:37:03 -05:00
Davide Pesavento 4e2a542b3b Add git .mailmap
Change-Id: Ied42430f18e83d3e012b6a3324242aa34e0eadf3
2019-01-09 19:28:13 -05:00
Davide Pesavento e1b18a6856 build: ensure /usr/local/include is treated as system include path on FreeBSD
Also use the LLD linker by default on FreeBSD.

Change-Id: Ic50f9478fdce0c34c52e8ad2f743391f23c1b35f
Refs: #4790
2018-12-19 01:17:42 -05:00
ashiqopu 1f0cad703b ci: install gcovr via apt
Change-Id: Ic1d1bf7cf1ff25ec4bd181061ebf87edb4dbb0a6
refs: #4771
2018-11-25 01:22:54 +00:00
Davide Pesavento f66e40a0ee Use the official markdown version of the GPLv3
Change-Id: I87a0a46a976a031088c39d5ad04cb05d238f082e
2018-11-21 17:53:42 -05:00
Davide Pesavento 162bdbbcb2 ci: fix several issues with preinstalled homebrew packages on Travis
Change-Id: Ibd0f5755f436dab119f6b6804973833d1e28ba7b
2018-11-06 16:00:44 -05:00
Ryan Wickman 2c9933c94f chunks: fix impossible RTT values
Change-Id: Ia7386c6186362be5c50ea291a949fd40ec0224b4
Refs: #4604
2018-10-14 18:26:34 -04:00
Alexander Afanasyev a8b03df84d Prepare release 0.6.2
Change-Id: Ib3810a4383ce24b473464f63c435251466a256dc
2018-09-18 11:52:06 -04:00
Davide Pesavento 4f1d13db23 ci: enable LeakSanitizer
Change-Id: Icc8d21434771533f873eb1fa7ff6530b3e8b3038
2018-09-11 20:32:25 -04:00
Davide Pesavento 88beb4d0f5 build+ci: sync compilation flags and Travis-CI matrix with ndn-cxx
Change-Id: If44e87e190fdf74f32adf38546109bfce618c5ea
Refs: #4721
2018-09-11 18:14:18 -04:00
Davide Pesavento 3f2f48616e ci: introduce helper to preserve select env variables under sudo
Change-Id: I317a3c03d7188501f819b79ddfa6f0a2946a9866
Refs: #4610
2018-09-11 17:56:55 -04:00
Junxiao Shi 20d5a0b9fd ping: set CanBePrefix=false
This commit also sets CanBePrefix in ndndump and ndnpoke tests.

refs #4581

Change-Id: Ie91839426acc02f1879495312ad7ef131e8dac57
2018-08-14 09:26:11 -06:00
Davide Pesavento 2bdda1d185 pingserver: add --quiet option
Change-Id: I7e61383e587044fd65a50e4dee58a020d3b292ad
Refs: #4673
2018-08-09 19:35:49 -04:00
Davide Pesavento 5923bf814b pingserver: code cleanup
Change-Id: Ifdb75174f54aa26619594d4f1b919396a1012998
2018-08-09 18:53:45 -04:00
Davide Pesavento 0ca7e69023 dump: add IPv6 support
Change-Id: Id9d10cf1080d2d7f98e9a48216c6564c6bbf8607
Refs: #3861
2018-08-05 02:21:06 -04:00
Davide Pesavento f912653a7b dump: stricter parsing of IP/TCP/UDP headers
Also make the tool output more compact

Change-Id: Ia29806596f6da16e65c6ee1087bac3c7177fe971
2018-08-04 18:31:06 -04:00
Davide Pesavento b6b176c7b9 dump: refactor packet parsing code into per-protocol functions
Change-Id: I96af9cb6397e34dde401ba38964601fb50ce4960
2018-08-02 21:51:08 -04:00
Alexander Afanasyev 4fb67ea932 dissect-wireshark: Add support for dissecting PPP frames
This commit also fixes Info column output: before this change, the
column was showing KeyLocator name for data packets, instead of name of
the data packet.

Change-Id: I742d943662916072b1f08ff6050564ff34a698b4
2018-08-02 08:18:28 -06:00
Davide Pesavento 4a1b21d699 dump: add udp port 56363 to the default pcap filter
Change-Id: If13ac4732705e60f2f11494760f13b50d5e8259d
2018-07-26 20:57:26 -04:00
Davide Pesavento d1b1bf6666 dump: handle exceptions thrown by lp::Packet::wireDecode()
Change-Id: Ia3bd8a4f57c70313a589c197ee453f517664ec43
Refs: #3943
2018-07-26 18:27:16 -04:00
Davide Pesavento b5b8f95024 dump: add -t option to suppress printing per-packet timestamp
Change-Id: I4e0e44c62451629428d2d065692a0cb497a9203a
2018-07-26 18:25:47 -04:00
Davide Pesavento 24c0861e33 dump: capture in promisc mode by default, with an option to disable it
Change-Id: I75d9580616f0af588291897b27fe376921fef11f
2018-07-26 18:25:15 -04:00
Davide Pesavento c3d65c9a79 dump: print libpcap version in --version output
Change-Id: Id6a0844df218a068a2b8b7d359273c4852bcabcc
2018-07-26 13:01:21 -04:00
Davide Pesavento fb42a3db83 dump: enable optimizations in pcap_compile
Change-Id: Ide7b7fb262af741cccbbaf2faf7cbd92c50eb6af
2018-07-26 12:33:14 -04:00
Davide Pesavento ecd44803c7 dump: code cleanup
Change-Id: Ib0978d590dd033ee3e747f5987aa3f63af3d0faf
2018-07-25 03:05:37 -04:00
Davide Pesavento 051db00f35 dump: stop using tcpdump headers
Change-Id: Ied249b29a3e5bc41facc7228af618e44f2c286a8
2018-07-22 18:56:16 -04:00
Davide Pesavento 302941eec2 build: require clang >= 3.6
Change-Id: I609c6ae59ce78db79bb686d2a53e9f1f26dcaaef
2018-07-22 00:36:51 -04:00
Davide Pesavento 78de735ab0 dump: remove dependency on Boost.Regex
Use std::regex instead.

Change-Id: Icb0f88a3f01d16ca53089cdc764d529687eaca81
2018-07-22 00:35:45 -04:00
Eric Newberry 468dbdf326 poke: use unsetInterestFilter on Face instead of shutdown
refs #4642

Change-Id: I7b73c7bcde0763226a15d465046db2f4b7bb9b05
2018-06-23 23:36:09 -07:00
Ryan Wickman 034f30f27a chunks: fix aimd hanging with files less than chunk size
refs: #4439

Change-Id: Ie3ef5d81e6baf154ade97beda183bc6b16764085
2018-06-11 11:28:47 -07:00
Eric Newberry 2f041d20af poke: add unit testing
refs #3740

Change-Id: I170068cf69463e92b2019cc27747777d224c0232
2018-06-06 14:44:15 -07:00
Davide Pesavento 60f8cc12e2 build: switch to C++14
Cleanup core/common.hpp

Change-Id: I6566b0224e24716691d5896462aa7613547ed950
Refs: #3076
2018-06-06 16:25:38 -04:00
Junxiao Shi 89db73c443 dissect-wireshark: improve NDNLPv2 support
* Support 8-octet NonNegativeInteger.
* Recognize PitToken.
* Recognize CongestionMark.
* Recognize Ack.
* Recognize TxSequence.

refs #4463

Change-Id: I3b003400726df975d067ff46a5ebe645ea774b8b
2018-05-27 15:22:49 +00:00
Davide Pesavento 26ea1ac2aa build: require gcc >= 5.3
Change-Id: Ie8877a9047c96030f138745a19768fcfa11da855
Refs: #4462
2018-05-10 20:30:47 -04:00
Junxiao Shi c687af62d1 dissect-wireshark: show Name and FinalBlockId as URIs
refs #3106

Change-Id: I0c43bb07588839b553f4584ce2ca44b3819e3d78
2018-05-06 16:35:38 -07:00
Davide Pesavento 4a43e87b5a Prepare for 0.6.1 release
Change-Id: I962d75dd53d205d7e341d6f139e0aac3d08405ef
Refs: #4564
2018-05-04 13:21:55 -07:00
Davide Pesavento 79d12c66d8 ci: add gcc-8 to Travis-CI build matrix
Change-Id: I063949b929c929aef9e5ad55d83152ab5c9c73d3
2018-04-30 19:28:46 -04:00
Davide Pesavento a2d4b1480b dissect: recognize CanBePrefix, HopLimit, Parameters
Change-Id: Iba04c0d569348e5d138891ee11815d220aefb1af
Refs: #4590
2018-04-23 11:30:51 -04:00
Davide Pesavento 969cd5add4 chunks+peek: stop using deprecated {get,set}FinalBlockId
Change-Id: I64ae1c33a6f83af34b3db3d5f48cee3f3e7b7cb1
Refs: #4526
2018-04-23 11:28:45 -04:00
Junxiao Shi ac4b546be8 dissect-wireshark: recognize CanBePrefix, HopLimit, Parameters
refs #4517

Change-Id: I9ea61a070286bbc460ff7f64fb66092a891dcadb
2018-04-17 02:26:17 +00:00
Junxiao Shi b54aabdb89 peek: drop Selectors support
refs #4571

Change-Id: Iac6d07864746b0decfed6cb9dc3518b4999f83e3
2018-04-16 19:36:24 +00:00
Eric Newberry 5820ed3cc0 build: find Boost lib architecture automatically
refs #4573

Change-Id: I9bf17e414a5f774ad8638d494ceb68909e79348c
2018-04-07 16:36:57 -07:00
Chavoosh Ghasemi 75309aeedb chunks: show correct packet loss stats in AIMD pipeline output
Besides, AIMD pipeline prints a proper message when no RTT
measurements are available.

Change-Id: I9cbda88a005ba33cba753468f8f60f0d39281ab7
refs: #4437, #4551
2018-04-01 23:25:36 -04:00
Davide Pesavento e7d95a72ba ci: update .travis.yml
Change-Id: If5f808b7b0613b07baadedb057009cc2b37f73da
2018-03-12 15:01:31 -07:00
Alexander Afanasyev 20c85cb868 build: Cleanup and update of build scripts
Change-Id: I7fb5b8696d3b068249ae16b117bd27646d990dc3
2018-03-11 17:16:15 -04:00
Davide Pesavento 1aa91434cb build: update waf to version 2.0.6
Change-Id: I38e892c5a7768f0951523c8b6611f4417eff0152
2018-02-22 13:36:50 -05:00
susmit 48cb0b6f2e Prepare for 0.6 release
Change-Id: Iac0e2ac841f48429b62fb48632f9920673450bf4
Refs: #4497
2018-02-19 13:07:02 -05:00
Davide Pesavento cc2c717b62 tests: sync global configuration with NFD
Change-Id: I29fafbf63300d65c967958f48123ea888d14b9b2
Refs: #4255
2018-01-21 21:41:03 -05:00
Junxiao Shi 1fda67dc75 dissect-wireshark: display type+name in Info column
refs #3105

Change-Id: If8887282af9bdf53214bdd4727da3d5a7899f8d0
2018-01-12 21:35:31 +00:00
Davide Pesavento 9a659d0c3b ci: update Travis-CI configuration
* Add clang-6.0 to the build matrix (allowed to fail)
 * Remove unsupported OSX-10.10 configuration
 * Upgrade xcode9 to xcode9.2
 * Various simplifications

Change-Id: I507196dbbe97ffdc16c49ac029e03dc327afd935
2018-01-10 02:55:43 -05:00
Davide Pesavento f6991e1a61 chunks: print summary by default
Introduce -q/--quiet option to suppress all output.

Change-Id: Ib529849cb1ca8975d11ce6689e2d88708291d1c4
Refs: #4421
2018-01-09 15:32:50 -05:00
Chavoosh Ghasemi 3dae1090cf chunks: include RTT stats in final summary
Change-Id: I9cc7cba4c8fe1f7d7a2d68c96a7db2c04774bc19
Refs: #4406
2018-01-09 15:32:34 -05:00
Nick Gordon 83f9a91944 docs: mention the contributing guide
refs #4415

Change-Id: I358826140561be52f90cad75f0414173625ad979
2018-01-07 19:35:19 +00:00
Davide Pesavento 44b3b23ae6 chunks: respect --retries=-1 in AIMD pipeline
Change-Id: I72a88285500c5083e1a0a1ad32a317e92747d812
Refs: #4409
2017-12-23 16:59:33 -05:00
Klaus Schneider 2c3083dc77 catchunks: Change the default pipeline to AIMD
The fixed pipeline needs manual tuning, and by default cannot fully
utilize the given link capacity.

refs: #4402

Change-Id: I9aec7aa8d3dda0abf6a8ae4742919849f15c1e63
2017-12-18 14:52:46 -07:00
Davide Pesavento dc4cb4bf3a tests: fix -Wunused-lambda-capture warning with clang-5
Change-Id: Iff794e9573df3957cef0900986ce822e10845035
2017-11-21 13:40:22 -05:00
Chavoosh Ghasemi 641f593969 chunks: react to congestion marks
Change-Id: I96efe1bc3ec7a54080c76676892114f2c79003ed
refs: #4289
2017-11-18 22:30:15 +00:00
Davide Pesavento e9c69855c4 chunks: consolidate accounting of received data into onData()
Change-Id: Ib47381d3f69b482d60af8b07d002135944b17604
2017-11-04 20:24:08 -04:00
Davide Pesavento b587cfd779 chunks: move getNextSegmentNo() to PipelineInterests base class
This hides the "excluded segment" logic from subclasses and
reduces code duplication.

Change-Id: I9f7b5b88e6010e4e16a0876e79fc2ecb9ff8dc00
2017-11-04 20:21:38 -04:00
Chavoosh Ghasemi 4d36ed5889 chunks: Print summary for all pipeline types
refs #4299

Change-Id: Ia8f7d2a57a030fef6e1d6b2d75c9d03af679a724
2017-10-31 23:17:31 +00:00
Davide Pesavento 1928024363 ci: add Xcode 9.0 to Travis-CI build matrix
Change-Id: I57cb563e442d81162f23dfb2561099851d668637
2017-10-20 01:51:49 -04:00
Alexander Afanasyev eacd617151 Prepare release 0.5
Change-Id: I196869398c577fb0f1c702218a22bc90dd0d3716
Refs: #4275
2017-10-17 09:57:47 -04:00
Alexander Afanasyev 11e74eb20f build: Add -isystem and set specialized flags as a last configuration step
This change prevents global flags from interacting with library/feature
detection scripts.

Change-Id: Ib7b1d230f77668cad31cffdd18962cba41c856e9
Refs: #4296
2017-09-22 12:56:21 -04:00
Davide Pesavento b5e06e6658 ci: add clang-5.0 build job to Travis-CI
Change-Id: I35807fe2befbea21579cb348dde914732269bbb1
2017-09-19 18:54:29 -04:00
Davide Pesavento 6f76afcf06 chunks: refactor Producer options handling
Change-Id: I10331ad9fa33cce1133bc3270cadf65b3e31c93b
2017-09-19 18:43:51 -04:00
Davide Pesavento 06807dcdb4 chunks: drop pointless init of virtual base from abstract class
Change-Id: I8d47dc5bdcb1d12f808d729d71a2bbdc0b87daf4
2017-09-19 15:54:52 -04:00
Davide Pesavento 887336ca8d chunks: declare DiscoverVersion destructor virtual
The concrete subclasses are deleted polymorphically
through a unique_ptr<DiscoverVersion>.

Also add -Wnon-virtual-dtor to the default CXXFLAGS
to prevent this from happening in the future.

Change-Id: If00a99566a54c7af4cd27df6fe68dcdef4cb4e82
2017-09-19 15:25:23 -04:00
Klaus Schneider 7072e1604a ndncatchunks: Reduce initial timeout of iterative version discovery
Reduce the default timeout to 300ms.
Provide a parameter '--discovery-timeout' to raise it, if necessary.
Reduce the number of timeouts for version discovery from 2 to 1.

refs: #4291

Change-Id: I459645ab074ed9b15a74baed39f45903fcb31ff1
2017-09-17 11:51:19 -07:00
Klaus Schneider 59ec95a15e ndnputchunks: display some output by default.
Will display some messages without the need of the '-v' parameter.
'-v' still adds the additional output per incoming Interest.

Also adds '-q' flag to disable all output except errors.

refs: #4286

Change-Id: I81116182403cd3f3e9d9bd63be64c1ff3a4552ee
2017-09-15 22:21:02 -07:00
Davide Pesavento 0ebecab714 chunks: fix build with clang-5.0
Change-Id: Ic856ba6cf0437d935a65f1fd258b1bad16810701
2017-09-12 15:54:15 -04:00
Eric Newberry 6035cd5907 docs: change license boilerplate opener to /*
refs #4163

Change-Id: I8043bbb0d0675469b980522a027a3dbbe9294106
2017-08-28 02:07:34 -07:00
Davide Pesavento 07238e844c ci: stop installing cryptopp/crypto++
Change-Id: I5c24e4e257f8ebf1550d0eaa1cfe6697d3f50a1c
Refs: #3946
2017-08-26 13:21:57 -04:00
Davide Pesavento c07027069f Fix compilation with Boost 1.65.0
Also sync default-compiler-flags.py with NFD

Change-Id: Ib39118567428e8fe2ac73f2b7cbd96fe1a9598b8
Refs: #4259, #4248
2017-08-25 23:43:02 -04:00
Davide Pesavento 44660cf226 ci: use two parallel build jobs on Travis-CI
Change-Id: I734c5826f37e1027484ef9723933e8954dba00a8
2017-08-16 00:44:23 -04:00
Davide Pesavento 5485ca9ce2 ci: preserve PATH when running waf under sudo
Change-Id: I090dd49d1d8f78007b1b7684af7563fbedac770a
Refs: #4186
2017-08-13 21:58:39 -04:00
Davide Pesavento bf28cd76ee tests: remove obsolete makeLink helper function
This is a quick fix for a build error caused by the removal
of some deprecated functions from ndn-cxx.

Change-Id: I4df5bdd426743774b08f5966eed28a27f2af1279
Refs: #4055
2017-08-13 21:55:14 -04:00
Junxiao Shi a5b60cc017 peek: transform Link into ForwardingHint
refs #4055

Change-Id: I7b06e1882809ec9edde8447d82db2257431504a3
2017-07-26 01:35:48 +00:00
Junxiao Shi f860649549 chunks: switch to v2::ValidatorNull
refs #4089

Change-Id: If23ca4d202ad1b61ee1e56ba0e15a8750c184e03
2017-07-23 03:44:34 +00:00
Junxiao Shi c9575a6aa3 tests: include ndn-cxx/net/ethernet.hpp
It has been renamed from ndn-cxx/util/ethernet.hpp.

refs #3940

Change-Id: I1a35d4f8bd1a188e023ba6ee12e7e4f8e179c2c4
2017-07-01 06:16:02 +00:00
Davide Pesavento f085ed10e5 ci: greatly expand Travis-CI build matrix
Change-Id: I2455e2751db9cd4f660c38ad4696925b1fda5cd8
2017-06-30 14:59:52 -04:00
Davide Pesavento 1eecc17e16 ci: speed up Travis-CI osx jobs by upgrading only the packages we need
Change-Id: I624f06b456357235648ff75f5158e6d694be2cb3
2017-06-24 14:30:42 -04:00
Davide Pesavento dd0e1959bb build: sync default-compiler-flags.py with ndn-cxx
- explicitly require clang >= 3.4
 - move -Og to basic debug flags (supported by clang since 4.0)
 - use gold linker and enable linker optimizations

Change-Id: I26d8d6d6ea16b1878831cb3a7259541e147b8b0e
2017-06-24 13:37:13 -04:00
Ashlesh Gawande 70750cf10d ci: check boost version change on OSX
refs #3321

Change-Id: I40d572c74257ddd104a2dcd803d8ea7dfb7d8fe7
2017-05-27 17:10:34 +00:00
Junxiao Shi 20b2297739 ping+tests: switch to ndn-cxx KeyChain v2
refs #4089

Change-Id: I21b3b09acdea9c1de61a14e2652b4fa763f2a7a0
2017-05-25 22:37:43 -07:00
Eric Newberry bfd66ade98 tests: use new default value of ChildSelector
refs #3944

Change-Id: Ic233da39fb516e0ece871c16415398362f087868
2017-05-25 00:35:05 -07:00
Davide Pesavento 931dfe8a63 ci: improve lcov HTML output
In particular, demangle C++ symbols in the function coverage view.

Change-Id: I882a88fda77c468e26b935ad6088b4254e875151
2017-04-29 20:33:45 -04:00
Alexander Afanasyev 339161aca3 Prepare release 0.4
Change-Id: Id00ffc0edb4b3fa0bb4826f3e48af21e982955d4
2017-01-22 12:02:58 -08:00
Davide Pesavento 958896e4c0 chunks: more cleanups to enhance code readability
Change-Id: I451d3c484dd476682ccb1be1f26535e18a34ab87
2017-01-20 15:56:36 -05:00
Davide Pesavento 92998fe2e1 chunks: respect common options in AIMD pipeline
Change-Id: Ic759950be9b6335efa2119c4cfbd22e3911b69ab
2017-01-20 15:55:54 -05:00
Eric Newberry 716ab60f05 build+ci: add code coverage support
This commit also adds GlobalConfigurationFixture to ensure that running
unit tests doesn't interact with system configuration (e.g., doesn't use
or alter user certificates).

Change-Id: I621ce14425a777c94d41b8132cd2858d91235b4d
Refs: #3808
2017-01-18 17:37:05 -08:00
Davide Pesavento bf1c069b7f chunks: code cleanups
* Introduce getSegmentFromPacket() helper function
  * Use signed arithmetic for some quantities to avoid conversion issues
  * Move start time handling to PipelineInterests base class

Change-Id: I275acac1ad93e4a72374d03fad0a1d7348d70976
2017-01-16 02:35:59 -05:00
Davide Pesavento cd65c2c204 chunks: don't blindly call Scheduler::cancellAllEvents()
Instead, keep track of the event we schedule and cancel only that one.

Change-Id: I9a2ae73073537bb1b67bceef85670add741cd542
2017-01-15 16:47:01 -05:00
Alexander Afanasyev dc304c21b7 ci: Fix macOS build with Travis-CI
Change-Id: Iabdfd71c4ba8b3c35f6de117da3b42b61cb1dc4e
2017-01-11 13:29:39 -08:00
Alexander Afanasyev 1b05b0a8fb pib: Disable PIB tool by default, it needs refactoring
Change-Id: Ib441ba491428c2f7531ff27545d8eeee4c1efb69
2017-01-11 09:56:50 -08:00
Eric Newberry 59869d2d9c build: derive version string at build-time
refs #2749

Change-Id: Id1d164ff4b1fd5c7e9440a241ab299661ed933c4
2017-01-08 22:33:46 -08:00
Eric Newberry 82ea0fa9a0 docs: add missing dependency libpcap-dev to INSTALL.md
refs #3623

Change-Id: If14220787aeb5dad9fc88f3dfa629118b222adda
2016-12-28 21:44:44 -07:00
Eric Newberry 9737aa886b ci: speed up code-coverage jobs
refs #3809

Change-Id: Ia811a5ca79ba9aa30744aa2269f681528446445f
2016-12-28 01:20:24 -07:00
Eric Newberry f162839c11 ping: remove potential divide-by-zero in StatisticsCollector
refs #3504

Change-Id: I38c1a5079e2884e53a4fff2311c98b553f42c2a3
2016-12-26 17:25:03 -07:00
Junxiao Shi 022bddf47d dump: recognize LINUX_SLL link-type
refs #3061

Change-Id: Idf50a70f17a1c9ffedbed5697ca11070d35e95a3
2016-11-24 23:15:20 +00:00
Junxiao Shi 1c71bcdcd7 dump: minor error message fix
refs #3683

Change-Id: I40b89fcfb93e469006f24764786fc70331671b21
2016-11-24 04:00:42 +00:00
Junxiao Shi 5e384792db dissect-wireshark: display Nonce value only
Previously, TLV-TYPE and TLV-LENGTH are incorrectly included in Nonce row.

refs #3107

Change-Id: I101c8d2962ddb81230c653ae95ff50e5f45a8c43
2016-11-24 03:59:06 +00:00
Junxiao Shi 3ebb9cb728 dissect: warn when specified file cannot be opened
refs #3539

Change-Id: Ife650100469e1123f0f6610a25422e98020f1f49
2016-11-23 14:58:55 +00:00
Zipeng Wang 574eeb05dd dissect-wireshark: Add initial support for NDNLPv2 packet dissecting
Change-Id: I813bc4d600e69bef07d6b79a3a461b00941b1eb8
Refs: #3197
2016-11-18 12:28:36 +09:00
Eric Newberry e16bc31651 build: load sanitizers last in wscript to prevent boost link failure
refs #3828

Change-Id: I52c93e8c75c4690314fdb4767a5427cf9f9c225a
2016-11-04 01:00:27 +00:00
Weiwei Liu 245d791ef7 chunks: AIMD congestion control
refs #3636

Change-Id: Ia5e601201219048eb5c745bba9627e4916dac31a
2016-11-01 21:26:01 -07:00
Eric Newberry 2547a5288d ci: set Travis CI Xcode version and update NODE_LABELS to 10.11
refs #3833

Change-Id: I23c9f7aa0957ee445a591d20a5a1b5e87cdf9165
2016-10-31 16:05:51 -07:00
Davide Pesavento 6a2b3dab98 ci: ensure XML test reports do not clobber the output of previous runs
Change-Id: I5ad31d571d296b6cd85012786ab3d4370f98fbea
Refs: #3750
2016-10-15 04:10:37 +00:00
Alexander Afanasyev fc4aa0d727 build: Do not fail the build in debug mode when using deprecated declarations
The original motivation of this change was to avoid compilation failure
in debug mode on macOS 10.12.

Change-Id: I881473fb166e2d3da62f80bb67331e86c422fc8d
Refs: #3795
2016-10-15 00:57:33 +00:00
Zhuo Li b355889743 peek: Refactor ndnpeek and add unit tests
Change-Id: Ib34c4431bdc268c5a7ef2fccf0946b0d19d69ab6
Refs: #3558
2016-10-07 18:25:04 +02:00
Weiwei Liu 72c96d23f0 chunks: fix misinformation in README
refs #3771

Change-Id: Ia0100cbfaf4da11d4ca561cf3c686415c3e91945
2016-09-27 23:06:21 -07:00
Weiwei Liu 13fda5be9b chunks: change default version discovery to 'iterative'
refs #3771

Change-Id: I67c2589776a122b2e0d790b37e63617eccee9196
2016-09-28 03:29:07 +00:00
Weiwei Liu 85de8424e0 chunks: improve help text of ndnputchunks
refs #3772

Change-Id: I17c3be0cca53904f160c61893abac28edfc73134
2016-09-28 03:28:31 +00:00
Davide Pesavento b5a5745c78 Add Travis CI badge to README
Change-Id: Ibf4fe0b4325bba33bf2bb0aad737b55e792a1476
2016-09-20 19:18:25 +02:00
Davide Pesavento 956ac311b8 ci: sync jenkins scripts with NFD
Change-Id: I43689bcf51bbe7a1c3118d8b0c226b56077fb4ed
2016-09-20 19:11:30 +02:00
Davide Pesavento 525c1071b1 ci: enable AddressSanitizer for unit tests
Change-Id: Iffd1f16938c77ccbe03bec776ccee3206b5e68aa
Refs: #2589
2016-09-17 18:43:14 +02:00
Davide Pesavento 013de9bc86 tests: filename and test suite name corrections in pib and ping
This commit splits IdentityManagementFixture from IdentityManagementTimeFixture,
and copies its API from NFD repository.

refs #3018

Change-Id: I14dc66dd6eacc83ef2761c0c484173168d98dcef
2016-09-01 12:06:56 +00:00
Davide Pesavento f0a301dd60 build+core: fix version number
v0.3 was tagged a long time ago.

Change-Id: Ifca6f01e0aac1b01303ae9fe5b40b3f354b9bb41
2016-08-14 11:44:53 +02:00
Davide Pesavento 89d9175e7c build: add waf-tool to simplify building with AddressSanitizer & friends
Change-Id: If36e52f5e49d94ad5846165c50504d06d7d3c4d0
Refs: #2589
2016-08-14 11:34:09 +02:00
Alexander Afanasyev 244feac1d1 pib: Fix compilation error with new version of ndn-cxx library
Change-Id: I6903ebc9bd169851ee7eac6b7a2d375296a4b913
Refs: #3083
2016-08-01 19:18:31 -07:00
Alexander Afanasyev e4a2b03245 ci: Update of Travis CI build file
There are no functional changes, just small simplification and
beautification.

Change-Id: Icf90be347152db168f43800db02339cc809d015e
2016-08-01 14:26:45 -07:00
Weiwei Liu 05d9209741 chunks: fix memory error in Consumer::run
Change-Id: Ic137b88d4ab46ade788d2ae5c0aba59902167f7b
Refs: #3636
2016-07-27 11:40:49 -07:00
Junxiao Shi e65c6d7eae dissect-wireshark: fix tvb overflow
refs #3603

Change-Id: Ibb56398e59f70a8498329def0344a0cf67ee375e
2016-07-24 21:53:19 +00:00
Junxiao Shi c75996344f dump: improve error messages
refs #3683

Change-Id: I84f9fe14567d6197d959769e53217a174ad6d80a
2016-07-24 20:46:24 +00:00
Junxiao Shi c1c2b83766 dump: code style corrections
refs #3683

Change-Id: I694e04f418fd084f4f1b59693a336dea1b205ad3
2016-07-24 20:45:36 +00:00
Junxiao Shi 7809e30b59 pib+tests: don't use deprecated block helpers
This commit also copies makeInterest, makeData, signData, makeLink, makeNack
functions in tests/test-common.hpp from NFD repository.

refs #2950

Change-Id: I1b95007bb0121e04a39bdec8553db5d8ab7c3e84
2016-07-23 14:11:25 +00:00
Junxiao Shi 523fcb1256 pib: correct build target path
refs #3018

Change-Id: I98be301026b7c0cd9469ef6d9732ff9b28560d76
2016-07-20 14:02:36 +00:00
Junxiao Shi b098e9f3c4 chunks: fix DiscoverVersionIterative build error
refs #3681

Change-Id: I00109197d05bc480a249f74b123e9a553acb25a3
2016-07-20 14:00:40 +00:00
Weiwei Liu e476501b49 chunks: modularize pipeline implementation
Change-Id: Iaa5acbb02a583858db6204716947cceeae793a65
Refs: #3636
2016-07-14 22:05:10 +02:00
Junxiao Shi aa1b3c9fc4 tests: don't use makeDummyClientFace
refs #3383

Change-Id: Ia19d16b1f92c5f386c1bbdf3cb4c81aad24f36a0
2016-07-14 14:56:53 +00:00
Teng Liang 6288486984 ndnping: recognize and trace Nack
Change-Id: If47877892c75ae0849375f36430a66e02fb7a608
refs: #3335
2016-07-12 19:18:44 -07:00
Junxiao Shi 6fd1695bb2 tests: don't install unit-tests
refs #3312

Change-Id: I6e8a9a820356b178580a84284ce790ebff1b1964
2016-07-06 20:52:25 +00:00
Alexander Afanasyev d2300731ed docs+build: Fix build on Ubuntu 16.04
python-sphinx on Ubuntu 16.04 requires `master_doc` to exist, otherwise
failing the build of manpages, even though this `master_doc` is never
used in manpages.

Change-Id: I8252cd8d24cfcc0403fdf551519944692e206380
2016-05-04 16:45:14 -07:00
Davide Pesavento 52401cea4d build: require gcc >= 4.8.2 and boost >= 1.54.0
Change-Id: I075413f6dfa1183682c4432cf96a47323cc6c43a
Refs: #3599
2016-05-03 18:41:32 +02:00
Davide Pesavento 0e8edde5d1 ci: Ubuntu 12.04 is no longer supported
Change-Id: Ib14e3b7f7ac085a1415470fbbfae8b071045c2fe
Refs: #3599, #3600
2016-05-03 18:41:32 +02:00
Davide Pesavento 4a1edc661a ci: update Travis-CI to use Ubuntu Linux 14.04 (trusty) and OS X 10.9 VMs
Change-Id: I692ca5514562eb9dc2da2a7ddf64fb7e82a429ab
Refs: #3360
2016-05-03 18:41:32 +02:00
Davide Pesavento 25625ca1a0 chunks: stop using non-public NDN_CXX_DECL_FINAL macro
Change-Id: I853a55044164756c51cc1fa7212e9229aed77229
Refs: #3599, #3613
2016-05-03 18:41:32 +02:00
Teng Liang 2864b9df7d ndnpeek: switch to Face::expressInterest that handles nack
Change-Id: Ic290f8817c9a3b2a9d098fa0c1bc5c38fc2367cd
refs: #3263
2016-03-25 10:08:46 -07:00
Teng Liang 799390a4e4 ndnpeek: add --link-file option
Change-Id: Idbf283a5ae23be76f9eb2752906c8aec21b2fede
Refs: #3112
2016-03-14 08:06:20 -07:00
Vince Lehman f8852b3206 dump: Update docs to include NACK capture feature
refs: #3463

Change-Id: I01618d03afdeecb329c74a3575b242b3d501abb1
2016-03-11 12:04:03 -08:00
Teng Liang d4ab87fb12 ndnpeek: switch from getopt to boost::program_options
Change-Id: Idf47e6b6eb6c082708e423c16f7eb503b81deabd
Refs: #3112
2016-03-10 13:55:35 -07:00
Vince Lehman 277ecf085e dump: Capture and print network NACK packets
refs: #3463

Change-Id: I3aed0d3668378305404f9713cc110e13eec434e5
2016-03-06 22:01:16 -08:00
Alexander Afanasyev 821a01431b build: Fix compatibility with Python 3
Change-Id: I5a7b332eb43b44ca528c27db762bf8e7e1f022e6
Refs: #3499
2016-03-03 09:34:36 -08:00
Junxiao Shi ae2c9f73ad ping: protocol definition
refs #3460

Change-Id: I539f2e5144a8a5370aa1f91201eaa608d5f1ecc1
2016-02-16 09:03:24 -07:00
Andrea Tosatto 672b9a7093 chunks: segmented file transfer
refs #3071

Change-Id: I88e4fc1a8e33a0d61a95e2291cccc7b998647489
2016-01-19 16:26:15 +01:00
Davide Pesavento 28ae2cbee0 build: fix missing tool name in 'configure --help' output
Change-Id: I00a106c6a8c4c6ebbbfcf1a0db1ad98a66af18f6
2016-01-14 22:30:39 +01:00
Davide Pesavento 3e79c9cda4 build: enable -Wextra by default
Change-Id: I0e4615d4dfbbf0a7bf3e509bf2ad3d72b92993cb
Refs: #3293
2015-11-01 21:40:58 +01:00
Junxiao Shi e02fb52090 peek: verbose output
refs #3268

Change-Id: I59fd0e4f6537088346edaff8e785e6f8c8fffa6d
2015-10-18 08:45:09 -07:00
Junxiao Shi c8a0a25a67 build: disable clang's unused-local-typedef warning and keyword-macro error
unused-local-typedef is disabled completely.
keyword-macro is downgraded from an error to a warning.

This commit also enables color diagnostics on release builds.

refs #3209 #3235

Change-Id: Ibce2da95dffb88abc384e6c98911d4ac900a880a
2015-10-05 16:43:34 -07:00
202 changed files with 12809 additions and 13073 deletions
+16
View File
@@ -0,0 +1,16 @@
name: CI
on:
push:
workflow_dispatch:
permissions: {}
jobs:
Ubuntu:
uses: named-data/actions/.github/workflows/jenkins-script-ubuntu.yml@v1
macOS:
uses: named-data/actions/.github/workflows/jenkins-script-macos.yml@v1
PPA:
uses: named-data/actions/.github/workflows/ppa.yml@v1
with:
extra-deps: libboost-program-options-dev libpcap-dev
+10
View File
@@ -0,0 +1,10 @@
name: Docs
on:
push:
workflow_dispatch:
permissions: {}
jobs:
man:
uses: named-data/actions/.github/workflows/docs-man.yml@v1
+22 -10
View File
@@ -1,17 +1,29 @@
# Emacs temp files
# Emacs
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
.\#*
# OS X
.DS_*
# Visual Studio Code
.vscode/
# waf build system
.waf-1*
.waf3-*
.lock*
build/
# macOS
.DS_Store
.AppleDouble
.LSOverride
._*
# Waf build system
/build/
.waf-*-*/
.waf3-*-*/
.lock-waf*
# Compiled python code
*.pyc
__pycache__/
*.py[cod]
# Other
VERSION
/VERSION.info
+46 -4
View File
@@ -1,10 +1,52 @@
#!/usr/bin/env bash
set -e
set -eo pipefail
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
case $(uname) in
Linux)
if [[ -e /etc/os-release ]]; then
source /etc/os-release
else
source /usr/lib/os-release
fi
export ID VERSION_ID
export ID_LIKE="${ID} ${ID_LIKE} linux"
export PATH="${HOME}/.local/bin${PATH:+:}${PATH}"
;;
Darwin)
# Emulate a subset of os-release(5)
export ID=macos
export VERSION_ID=$(sw_vers -productVersion)
export PATH="/usr/local/bin${PATH:+:}${PATH}"
if [[ -x /opt/homebrew/bin/brew ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -x /usr/local/bin/brew ]]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
;;
esac
for file in "$DIR"/.jenkins.d/*; do
export CACHE_DIR=${CACHE_DIR:-/tmp}
if [[ $JOB_NAME == *"code-coverage" ]]; then
export DISABLE_ASAN=yes
export DISABLE_HEADERS_CHECK=yes
fi
# https://reproducible-builds.org/docs/source-date-epoch/
export SOURCE_DATE_EPOCH=$(git log -1 --format=%ct)
for file in .jenkins.d/*; do
[[ -f $file && -x $file ]] || continue
echo "Run: $file"
if [[ -n $GITHUB_ACTIONS ]]; then
label=$(basename "$file" | sed -E 's/[[:digit:]]+-(.*)\..*/\1/')
echo "::group::${label}"
fi
echo "\$ $file"
"$file"
if [[ -n $GITHUB_ACTIONS ]]; then
echo "::endgroup::"
fi
done
+33 -19
View File
@@ -1,25 +1,39 @@
#!/usr/bin/env bash
set -e
set -eo pipefail
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
source "$JDIR"/util.sh
APT_PKGS=(build-essential pkg-config python3-minimal
libboost-all-dev libssl-dev libsqlite3-dev
libpcap-dev)
FORMULAE=(boost openssl pkg-config)
PIP_PKGS=()
case $JOB_NAME in
*code-coverage)
APT_PKGS+=(lcov python3-pip)
PIP_PKGS+=('gcovr~=5.2')
;;
*Docs)
APT_PKGS+=(python3-pip)
PIP_PKGS+=(sphinx)
;;
esac
if has OSX $NODE_LABELS; then
set -x
brew update
brew upgrade
brew install boost pkg-config cryptopp
brew cleanup
fi
set -x
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
if [[ $ID == macos ]]; then
if [[ -n $GITHUB_ACTIONS ]]; then
export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1
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
brew update
brew install --formula "${FORMULAE[@]}"
elif [[ $ID_LIKE == *debian* ]]; then
sudo apt-get -qq update
sudo apt-get -qy install "${APT_PKGS[@]}"
elif [[ $ID_LIKE == *fedora* ]]; then
sudo dnf -y install gcc-c++ libasan lld pkgconf-pkg-config python3 \
boost-devel openssl-devel sqlite-devel \
libpcap-devel
fi
if (( ${#PIP_PKGS[@]} )); then
pip3 install --user --upgrade --upgrade-strategy=eager "${PIP_PKGS[@]}"
fi
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
set -exo pipefail
pushd "$CACHE_DIR" >/dev/null
INSTALLED_VERSION=
if [[ $ID == macos ]]; then
BOOST=$(brew list --formula --versions boost)
OLD_BOOST=$(cat boost.txt || :)
if [[ $OLD_BOOST != $BOOST ]]; then
echo "$BOOST" > boost.txt
INSTALLED_VERSION=NONE
fi
fi
if [[ -z $INSTALLED_VERSION ]]; then
INSTALLED_VERSION=$(git -C ndn-cxx rev-parse HEAD 2>/dev/null || echo NONE)
fi
sudo rm -rf ndn-cxx-latest
git clone --depth 1 https://github.com/named-data/ndn-cxx.git ndn-cxx-latest
LATEST_VERSION=$(git -C ndn-cxx-latest 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 -f /usr/local/bin/ndnsec*
sudo rm -fr /usr/local/include/ndn-cxx
sudo rm -f /usr/local/lib{,64}/libndn-cxx*
sudo rm -f /usr/local/lib{,64}/pkgconfig/libndn-cxx.pc
pushd ndn-cxx >/dev/null
./waf --color=yes configure --without-osx-keychain
./waf --color=yes build
sudo ./waf --color=yes install
popd >/dev/null
popd >/dev/null
if [[ $ID_LIKE == *fedora* ]]; then
sudo tee /etc/ld.so.conf.d/ndn.conf >/dev/null <<< /usr/local/lib64
fi
if [[ $ID_LIKE == *linux* ]]; then
sudo ldconfig
fi
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -eo pipefail
if [[ -z $DISABLE_ASAN ]]; then
ASAN="--with-sanitizer=address"
fi
if [[ $JOB_NAME == *"code-coverage" ]]; then
COVERAGE="--with-coverage"
fi
set -x
if [[ $JOB_NAME != *"code-coverage" && $JOB_NAME != *"limited-build" ]]; then
# Build in release mode with tests
./waf --color=yes configure --with-tests
./waf --color=yes build
# Cleanup
./waf --color=yes distclean
# Build in release mode without tests
./waf --color=yes configure
./waf --color=yes build
# Cleanup
./waf --color=yes distclean
fi
# Build in debug mode with tests
./waf --color=yes configure --debug --with-tests $ASAN $COVERAGE
./waf --color=yes build
# (tests will be run against the debug version)
# Install
sudo ./waf --color=yes install
-42
View File
@@ -1,42 +0,0 @@
#!/usr/bin/env bash
set -x
set -e
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
source "$JDIR"/util.sh
pushd /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
-17
View File
@@ -1,17 +0,0 @@
#!/usr/bin/env bash
set -x
set -e
# Cleanup
sudo ./waf -j1 --color=yes distclean
# Configure/build in release mode without tests
./waf -j1 --color=yes configure
./waf -j1 --color=yes build
# Cleanup
sudo ./waf -j1 --color=yes distclean
# Configure/build in debug mode with tests
./waf -j1 --color=yes configure --with-tests --debug
./waf -j1 --color=yes build
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -eo pipefail
# https://github.com/google/sanitizers/wiki/AddressSanitizerFlags
ASAN_OPTIONS="color=always"
ASAN_OPTIONS+=":check_initialization_order=1"
ASAN_OPTIONS+=":detect_stack_use_after_return=1"
ASAN_OPTIONS+=":strict_init_order=1"
ASAN_OPTIONS+=":strict_string_checks=1"
ASAN_OPTIONS+=":detect_invalid_pointer_pairs=2"
ASAN_OPTIONS+=":strip_path_prefix=${PWD}/"
export ASAN_OPTIONS
# https://www.boost.org/doc/libs/release/libs/test/doc/html/boost_test/runtime_config/summary.html
export BOOST_TEST_BUILD_INFO=1
export BOOST_TEST_COLOR_OUTPUT=1
export BOOST_TEST_DETECT_MEMORY_LEAK=0
export BOOST_TEST_LOGGER=HRF,test_suite,stdout:XML,all,build/xunit-log.xml
set -x
# Prepare environment
rm -rf ~/.ndn
# Run unit tests
./build/unit-tests
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
set -exo pipefail
if [[ $JOB_NAME == *"code-coverage" ]]; then
# Generate an XML report (Cobertura format) and a detailed HTML report using gcovr
# Note: trailing slashes are important in the paths below. Do not remove them!
gcovr --object-directory build \
--filter tools/ \
--exclude-throw-branches \
--exclude-unreachable-branches \
--cobertura build/coverage.xml \
--html-details build/gcovr/ \
--print-summary
# Generate a detailed HTML report using lcov
lcov --quiet \
--capture \
--directory . \
--exclude "$PWD/tests/*" \
--no-external \
--rc lcov_branch_coverage=1 \
--output-file build/coverage.info
genhtml --branch-coverage \
--demangle-cpp \
--legend \
--output-directory build/lcov \
--title "ndn-tools unit tests" \
build/coverage.info
fi
-6
View File
@@ -1,6 +0,0 @@
#!/usr/bin/env bash
set -x
set -e
rm -rf $HOME/.ndn
./build/unit-tests -l test_suite
+26 -20
View File
@@ -1,30 +1,36 @@
CONTINUOUS INTEGRATION SCRIPTS
==============================
# Continuous Integration Scripts
Environment Variables Used in Build Scripts
-------------------------------------------
## Environment Variables
- `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.
- `ID`: lower-case string that identifies the operating system, for example: `ID=ubuntu`,
`ID=centos`. See [os-release(5)] for more information. On macOS, where `os-release` is
not available, we emulate it by setting `ID=macos`.
The list should include at least `[OS_TYPE]`, `[DISTRO_TYPE]`, and `[DISTRO_VERSION]`.
- `ID_LIKE`: space-separated list of operating system identifiers that are closely related
to the running OS. See [os-release(5)] for more information. The listed values are used
by the CI scripts to select the proper behavior for different platforms and OS flavors.
Possible values for Linux OS:
Examples:
* `[OS_TYPE]`: `Linux`
* `[DISTRO_TYPE]`: `Ubuntu`
* `[DISTRO_VERSION]`: `Ubuntu-12.04`, `Ubuntu-14.04`, `Ubuntu-15.04`
- On CentOS, `ID_LIKE="centos rhel fedora linux"`
- On Ubuntu, `ID_LIKE="ubuntu debian linux"`
Possible values of OSX OS:
- `VERSION_ID`: identifies the operating system version, excluding any release code names.
See [os-release(5)] for more information. Examples: `VERSION_ID=42`, `VERSION_ID=22.04`.
* `[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`: defines the type of the current CI job. Depending on the job type, the CI
scripts can perform different tasks.
- `JOB_NAME`: optional variable to define type of the job. Depending on the defined job type,
the build scripts can perform different tasks.
Supported values:
Possible values:
- empty: default build task
- `code-coverage`: debug build with tests and code coverage analysis
- `limited-build`: only a single debug build with tests
* empty: default build process
* `code-coverage` (Linux OS is assumed): build process with code coverage analysis
- `CACHE_DIR`: directory containing cached files from previous builds, e.g., a compiled
version of ndn-cxx. If not set, `/tmp` is used.
- `DISABLE_ASAN`: disable building with AddressSanitizer. This is automatically set for
the `code-coverage` job type.
[os-release(5)]: https://www.freedesktop.org/software/systemd/man/os-release.html
-9
View File
@@ -1,9 +0,0 @@
has() {
local p=$1
shift
local x
for x in "$@"; do
[[ "${x}" == "${p}" ]] && return 0
done
return 1
}
+4
View File
@@ -0,0 +1,4 @@
<aa@cs.fiu.edu> <alexander.afanasyev@ucla.edu>
<davidepesa@gmail.com> <davide.pesavento@lip6.fr>
<enewberry@email.arizona.edu> <enewberry@cs.arizona.edu>
Md Ashiqur Rahman <marahman@email.arizona.edu>
-19
View File
@@ -1,19 +0,0 @@
sudo: true
language: cpp
os:
- linux
- osx
compiler:
- gcc
- clang
matrix:
exclude:
- os: linux
compiler: clang
- os: osx
compiler: gcc
script:
- 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
+430 -275
View File
@@ -13,37 +13,37 @@
This is an extra tool, not bundled with the default waf binary.
To add the boost tool to the waf file:
$ ./waf-light --tools=compat15,boost
or, if you have waf >= 1.6.2
or, if you have waf >= 1.6.2
$ ./waf update --files=boost
When using this tool, the wscript will look like:
def options(opt):
opt.load('compiler_cxx boost')
def options(opt):
opt.load('compiler_cxx boost')
def configure(conf):
conf.load('compiler_cxx boost')
conf.check_boost(lib='system filesystem')
def configure(conf):
conf.load('compiler_cxx boost')
conf.check_boost(lib='system filesystem')
def build(bld):
bld(source='main.cpp', target='app', use='BOOST')
def build(bld):
bld(source='main.cpp', target='app', use='BOOST')
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,
self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB']
self.env['CXXFLAGS_%s' % var] += ['/MD', '/EHsc']
self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB']
self.env['CXXFLAGS_%s' % var] += ['/MD', '/EHsc']
Passing `--boost-linkage_autodetect` might help ensuring having a correct linkage in some basic cases.
'''
@@ -52,327 +52,482 @@ 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/homebrew/lib', '/opt/local/lib', '/sw/lib', '/lib']
BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/homebrew/include', '/opt/local/include', '/sw/include']
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_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>
int main() { BOOST_LOG_TRIVIAL(info) << "boost_log is working"; }
'''
BOOST_LOG_SETUP_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(info) << "boost_log_setup is working";
}
'''
# 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'
detect_clang = lambda env: (PLATFORM == 'darwin') and 'clang-darwin' or 'clang'
detect_mingw = lambda env: (re.search('MinGW', env.CXX[0])) and 'mgw' or 'gcc'
BOOST_TOOLSETS = {
'borland': 'bcb',
'clang': detect_clang,
'como': 'como',
'cw': 'cw',
'darwin': 'xgcc',
'edg': 'edg',
'g++': detect_mingw,
'gcc': detect_mingw,
'icpc': detect_intel,
'intel': detect_intel,
'kcc': 'kcc',
'kylix': 'bck',
'mipspro': 'mp',
'mingw': 'mgw',
'msvc': 'vc',
'qcc': 'qcc',
'sun': 'sw',
'sunc++': 'sw',
'tru64cxx': 'tru',
'vacpp': 'xlc'
'borland': 'bcb',
'clang': detect_clang,
'como': 'como',
'cw': 'cw',
'darwin': 'xgcc',
'edg': 'edg',
'g++': detect_mingw,
'gcc': detect_mingw,
'icpc': detect_intel,
'intel': detect_intel,
'kcc': 'kcc',
'kylix': 'bck',
'mipspro': 'mp',
'mingw': 'mgw',
'msvc': 'vc',
'qcc': 'qcc',
'sun': 'sw',
'sunc++': 'sw',
'tru64cxx': 'tru',
'vacpp': 'xlc'
}
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''')
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)')
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''')
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)')
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)
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''')
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-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 (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)')
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)
@conf
def __boost_get_version_file(self, d):
dnode = self.root.find_dir(d)
if dnode:
return dnode.find_node(BOOST_VERSION_FILE)
return None
if not d:
return None
dnode = self.root.find_dir(d)
if dnode:
return dnode.find_node(BOOST_VERSION_FILE)
return None
@conf
def boost_get_version(self, d):
"""silently retrieve the boost version number"""
node = self.__boost_get_version_file(d)
if node:
try:
txt = node.read()
except (OSError, IOError):
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(":")
"""silently retrieve the boost version number"""
node = self.__boost_get_version_file(d)
if node:
try:
txt = node.read()
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
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:
if self.__boost_get_version_file(d):
return d
if includes:
self.end_msg('headers not found in %s' % includes)
self.fatal('The configuration failed')
else:
self.end_msg('headers not found, please provide a --boost-includes argument (see help)')
self.fatal('The configuration failed')
includes = k and k[0] or kw.get('includes', None)
if includes and self.__boost_get_version_file(includes):
return includes
for d in self.environ.get('INCLUDE', '').split(';') + BOOST_INCLUDES:
if self.__boost_get_version_file(d):
return d
if includes:
self.end_msg('headers not found in %s' % includes, 'YELLOW')
self.fatal('The configuration failed')
else:
self.end_msg('headers not found, please provide a --boost-includes argument (see help)', 'YELLOW')
self.fatal('The configuration failed')
@conf
def boost_get_toolset(self, cc):
toolset = cc
if not cc:
build_platform = Utils.unversioned_sys_platform()
if build_platform in BOOST_TOOLSETS:
cc = build_platform
else:
cc = self.env.CXX_NAME
if cc in BOOST_TOOLSETS:
toolset = BOOST_TOOLSETS[cc]
return isinstance(toolset, str) and toolset or toolset(self.env)
toolset = cc
if not cc:
build_platform = Utils.unversioned_sys_platform()
if build_platform in BOOST_TOOLSETS:
cc = build_platform
else:
cc = self.env.CXX_NAME
if cc in BOOST_TOOLSETS:
toolset = BOOST_TOOLSETS[cc]
return isinstance(toolset, str) and toolset or toolset(self.env)
@conf
def __boost_get_libs_path(self, *k, **kw):
''' return the lib path and all the files in it '''
if 'files' in kw:
return self.root.find_dir('.'), Utils.to_list(kw['files'])
libs = k and k[0] or kw.get('libs', None)
if libs:
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:
path = self.root.find_dir(d)
if path:
files = path.ant_glob('*boost_*')
if files:
break
path = self.root.find_dir(d + '64')
if path:
files = path.ant_glob('*boost_*')
if files:
break
if not path:
if libs:
self.end_msg('libs not found in %s' % libs)
self.fatal('The configuration failed')
else:
self.end_msg('libs not found, please provide a --boost-libs argument (see help)')
self.fatal('The configuration failed')
''' return the lib path and all the files in it '''
if 'files' in kw:
return self.root.find_dir('.'), Utils.to_list(kw['files'])
libs = k and k[0] or kw.get('libs', None)
if libs:
path = self.root.find_dir(libs)
files = path.ant_glob('*boost_*')
if not libs or not files:
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_*')
if files:
break
path = self.root.find_dir(d + '64')
if path:
files = path.ant_glob('*boost_*')
if files:
break
if not path:
if libs:
self.end_msg('libs not found in %s' % libs, 'YELLOW')
self.fatal('The configuration failed')
else:
self.end_msg('libs not found, please provide a --boost-libs argument (see help)', 'YELLOW')
self.fatal('The configuration failed')
self.to_log('Found the boost path in %r with the libraries:' % path)
for x in files:
self.to_log(' %r' % x)
return path, files
self.to_log('Found the boost path in %r with the libraries:' % path)
for x in files:
self.to_log(' %r' % x)
return path, files
@conf
def boost_get_libs(self, *k, **kw):
'''
return the lib path and the required libs
according to the parameters
'''
path, files = self.__boost_get_libs_path(**kw)
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
def find_lib(re_lib, files):
for file in files:
if re_lib.search(file.name):
self.to_log('Found boost lib %s' % file)
return file
return None
def format_lib_name(name):
if name.startswith('lib') and self.env.CC_NAME != 'msvc':
name = name[3:]
return name[:name.rfind('.')]
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
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()), 'YELLOW')
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
'''
return the lib path and the required libs
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 ''
toolset = self.boost_get_toolset(kw.get('toolset', ''))
toolset_pat = '(-%s[0-9]{0,3})+' % toolset
version = '(-%s)+' % self.env.BOOST_VERSION
def find_lib(re_lib, files):
for file in files:
if re_lib.search(file.name):
self.to_log('Found boost lib %s' % file)
return file
return None
var = kw.get('uselib_store', 'BOOST')
def format_lib_name(name):
if name.startswith('lib') and self.env.CC_NAME != 'msvc':
name = name[3:]
return name[:name.rfind('.')]
self.start_msg('Checking the flags needed to use pthreads')
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')
return path.abspath(), libs
# 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, quiet=True)
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):
"""
Initialize boost libraries to be used.
"""
Initialize boost libraries to be used.
Keywords: you can pass the same parameters as with the command line (without "--boost-").
Note that the command line has the priority, and should preferably be used.
"""
if not self.env['CXX']:
self.fatal('load a c++ compiler first, conf.load("compiler_cxx")')
Keywords: you can pass the same parameters as with the command line (without "--boost-").
Note that the command line has the priority, and should preferably be used.
"""
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)}
for key, value in self.options.__dict__.items():
if not key.startswith('boost_'):
continue
key = key[len('boost_'):]
params[key] = value and value or kw.get(key, '')
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
key = key[len('boost_'):]
params[key] = value and value or kw.get(key, '')
var = kw.get('uselib_store', 'BOOST')
var = kw.get('uselib_store', 'BOOST')
self.start_msg('Checking boost includes')
self.env['INCLUDES_%s' % var] = inc = self.boost_get_includes(**params)
versions = self.boost_get_version(inc)
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))
if Logs.verbose:
Logs.pprint('CYAN', ' path : %s' % self.env['INCLUDES_%s' % var])
if not self.env.DONE_FIND_BOOST_COMMON:
self.find_program('dpkg-architecture', var='DPKG_ARCHITECTURE', mandatory=False)
if self.env.DPKG_ARCHITECTURE:
deb_host_multiarch = self.cmd_and_log([self.env.DPKG_ARCHITECTURE[0], '-qDEB_HOST_MULTIARCH'])
BOOST_LIBS.insert(0, '/usr/lib/%s' % deb_host_multiarch.strip())
if not params['lib']:
return
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
self.end_msg('ok')
if Logs.verbose:
Logs.pprint('CYAN', ' path : %s' % path)
Logs.pprint('CYAN', ' libs : %s' % libs)
self.start_msg('Checking boost includes')
self.env['INCLUDES_%s' % var] = inc = self.boost_get_includes(**params)
versions = self.boost_get_version(inc)
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))
if Logs.verbose:
Logs.pprint('CYAN', ' path : %s' % self.env['INCLUDES_%s' % var])
self.env.DONE_FIND_BOOST_COMMON = True
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')
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(' '.join(libs + stlibs))
if Logs.verbose:
Logs.pprint('CYAN', ' path : %s' % path)
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 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') or has_lib('log_setup'):
if not has_lib('thread'):
self.env['DEFINES_%s' % var] += ['BOOST_LOG_NO_THREADS']
if has_shlib('log') or has_shlib('log_setup'):
self.env['DEFINES_%s' % var] += ['BOOST_LOG_DYN_LINK']
if has_lib('log_setup'):
self.check_cxx(fragment=BOOST_LOG_SETUP_CODE, use=var, execute=False)
else:
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',):
# disable auto-linking feature, causing error LNK1181
# because the code wants to be linked against
self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB']
# if no dlls are present, we guess the .lib files are not stubs
has_dlls = False
for x in Utils.listdir(path):
if x.endswith(self.env.cxxshlib_PATTERN % ''):
has_dlls = True
break
if not has_dlls:
self.env['STLIBPATH_%s' % var] = [path]
self.env['STLIB_%s' % var] = libs
del self.env['LIB_%s' % var]
del self.env['LIBPATH_%s' % var]
# we attempt to play with some known-to-work CXXFLAGS combinations
for cxxflags in (['/MD', '/EHsc'], []):
self.env.stash()
self.env['CXXFLAGS_%s' % var] += cxxflags
try:
try_link()
self.end_msg('ok: winning cxxflags combination: %s' % (self.env['CXXFLAGS_%s' % var]))
exc = None
break
except Errors.ConfigurationError as e:
self.env.revert()
exc = 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')
self.fatal('The configuration failed')
else:
self.start_msg('Checking for boost linkage')
try:
try_link()
except Errors.ConfigurationError as e:
self.end_msg('Could not link against boost libraries using supplied options', 'YELLOW')
self.fatal('The configuration failed')
self.end_msg('ok')
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 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']:
# disable auto-linking feature, causing error LNK1181
# because the code wants to be linked against
self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB']
# if no dlls are present, we guess the .lib files are not stubs
has_dlls = False
for x in Utils.listdir(path):
if x.endswith(self.env.cxxshlib_PATTERN % ''):
has_dlls = True
break
if not has_dlls:
self.env['STLIBPATH_%s' % var] = [path]
self.env['STLIB_%s' % var] = libs
del self.env['LIB_%s' % var]
del self.env['LIBPATH_%s' % var]
# we attempt to play with some known-to-work CXXFLAGS combinations
for cxxflags in (['/MD', '/EHsc'], []):
self.env.stash()
self.env["CXXFLAGS_%s" % var] += cxxflags
try:
try_link()
self.end_msg("ok: winning cxxflags combination: %s" % (self.env["CXXFLAGS_%s" % var]))
e = None
break
except Errors.ConfigurationError as exc:
self.env.revert()
e = exc
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)
self.fatal('The configuration failed')
else:
self.end_msg("Boost linkage flags auto-detection not implemented (needed ?) for this toolchain")
self.fatal('The configuration failed')
else:
self.start_msg('Checking for boost linkage')
try:
try_link()
except Errors.ConfigurationError as e:
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
+22
View File
@@ -0,0 +1,22 @@
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
from waflib import TaskGen
def options(opt):
opt.add_option('--with-coverage', action='store_true', default=False,
help='Add compiler flags to enable code coverage information')
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)
@TaskGen.feature('cxx','cc')
@TaskGen.after('process_source')
def add_coverage(self):
if getattr(self, 'use', ''):
self.use += ' GCOV'
else:
self.use = 'GCOV'
+167 -80
View File
@@ -1,54 +1,91 @@
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
from waflib import Logs, Configure, Utils
import platform
from waflib import Configure, Logs, Utils
def options(opt):
opt.add_option('--debug', '--with-debug', action='store_true', default=False, dest='debug',
help='''Compile in debugging mode without optimizations (-O0 or -Og)''')
opt.add_option('--debug', '--with-debug', action='store_true', default=False,
help='Compile in debugging mode with minimal optimizations (-Og)')
def configure(conf):
cxx = conf.env['CXX_NAME'] # CXX_NAME represents generic name of the compiler
conf.start_msg('Checking C++ compiler version')
cxx = conf.env.CXX_NAME # generic name of the compiler
ccver = tuple(int(i) for i in conf.env.CC_VERSION)
ccverstr = '.'.join(conf.env.CC_VERSION)
errmsg = ''
warnmsg = ''
if cxx == 'gcc':
flags = GccFlags()
if ccver < (7, 4, 0):
errmsg = ('The version of gcc you are using is too old.\n'
'The minimum supported gcc version is 9.3.')
elif ccver < (9, 3, 0):
warnmsg = ('Using a version of gcc older than 9.3 is not '
'officially supported and may result in build failures.')
conf.flags = GccFlags()
elif cxx == 'clang':
flags = ClangFlags()
if Utils.unversioned_sys_platform() == 'darwin':
if ccver < (10, 0, 0):
errmsg = ('The version of Xcode you are using is too old.\n'
'The minimum supported Xcode version is 12.4.')
elif ccver < (12, 0, 0):
warnmsg = ('Using a version of Xcode older than 12.4 is not '
'officially supported and may result in build failures.')
elif ccver < (7, 0, 0):
errmsg = ('The version of clang you are using is too old.\n'
'The minimum supported clang version is 7.0.')
conf.flags = ClangFlags()
else:
flags = CompilerFlags()
Logs.warn('The code has not been yet tested with %s compiler' % cxx)
warnmsg = f'{cxx} compiler is unsupported'
conf.flags = CompilerFlags()
areCustomCxxflagsPresent = (len(conf.env.CXXFLAGS) > 0)
if errmsg:
conf.end_msg(ccverstr, color='RED')
conf.fatal(errmsg)
elif warnmsg:
conf.end_msg(ccverstr, color='YELLOW')
Logs.warn('WARNING: ' + warnmsg)
else:
conf.end_msg(ccverstr)
# General flags will alway be applied (e.g., selecting C++11 mode)
generalFlags = flags.getGeneralFlags(conf)
conf.areCustomCxxflagsPresent = len(conf.env.CXXFLAGS) > 0
# General flags are always applied (e.g., selecting C++ language standard)
generalFlags = conf.flags.getGeneralFlags(conf)
conf.add_supported_cxxflags(generalFlags['CXXFLAGS'])
conf.add_supported_linkflags(generalFlags['LINKFLAGS'])
conf.env.DEFINES += generalFlags['DEFINES']
# Debug or optimization CXXFLAGS and LINKFLAGS will be applied only if the
@Configure.conf
def check_compiler_flags(conf):
# Debug or optimized CXXFLAGS and LINKFLAGS are applied only if the
# corresponding environment variables are not set.
# DEFINES will be always applied
# DEFINES are always applied.
if conf.options.debug:
extraFlags = flags.getDebugFlags(conf)
if areCustomCxxflagsPresent:
extraFlags = conf.flags.getDebugFlags(conf)
if conf.areCustomCxxflagsPresent:
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))
if missingFlags:
Logs.warn('Selected debug mode, but CXXFLAGS is set to a custom value "%s"'
% ' '.join(conf.env.CXXFLAGS))
Logs.warn('Default flags "%s" will not be used' % ' '.join(missingFlags))
else:
extraFlags = flags.getOptimizedFlags(conf)
extraFlags = conf.flags.getOptimizedFlags(conf)
if not areCustomCxxflagsPresent:
if not conf.areCustomCxxflagsPresent:
conf.add_supported_cxxflags(extraFlags['CXXFLAGS'])
conf.add_supported_cxxflags(extraFlags['LINKFLAGS'])
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
Check which cxxflags are supported by the active compiler and add them to env.CXXFLAGS variable.
"""
if len(cxxflags) == 0:
return
@@ -56,17 +93,19 @@ def add_supported_cxxflags(self, cxxflags):
self.start_msg('Checking supported CXXFLAGS')
supportedFlags = []
for flag in cxxflags:
if self.check_cxx(cxxflags=['-Werror', flag], mandatory=False):
supportedFlags += [flag]
for flags in cxxflags:
flags = Utils.to_list(flags)
if self.check_cxx(cxxflags=['-Werror'] + flags, mandatory=False):
supportedFlags += flags
self.end_msg(' '.join(supportedFlags))
self.env.CXXFLAGS = supportedFlags + self.env.CXXFLAGS
self.env.prepend_value('CXXFLAGS', supportedFlags)
@Configure.conf
def add_supported_linkflags(self, linkflags):
"""
Check which linkflags are supported by compiler and add them to env.LINKFLAGS variable
Check which linkflags are supported by the active compiler and add them to env.LINKFLAGS variable.
"""
if len(linkflags) == 0:
return
@@ -74,80 +113,128 @@ def add_supported_linkflags(self, linkflags):
self.start_msg('Checking supported LINKFLAGS')
supportedFlags = []
for flag in linkflags:
if self.check_cxx(linkflags=['-Werror', flag], mandatory=False):
supportedFlags += [flag]
for flags in linkflags:
flags = Utils.to_list(flags)
if self.check_cxx(linkflags=['-Werror'] + flags, mandatory=False):
supportedFlags += flags
self.end_msg(' '.join(supportedFlags))
self.env.LINKFLAGS = supportedFlags + self.env.LINKFLAGS
self.env.prepend_value('LINKFLAGS', supportedFlags)
class CompilerFlags(object):
class CompilerFlags:
def getCompilerVersion(self, conf):
return tuple(int(i) for i in conf.env.CC_VERSION)
def getGeneralFlags(self, conf):
"""Get dict {'CXXFLAGS':[...], LINKFLAGS:[...], DEFINES:[...]} that are always needed"""
return {'CXXFLAGS': [], 'LINKFLAGS': [], 'DEFINES': []}
"""Get dict of CXXFLAGS, LINKFLAGS, and DEFINES that are always needed"""
return {
'CXXFLAGS': [],
'LINKFLAGS': [],
'DEFINES': ['BOOST_ASIO_NO_DEPRECATED', 'BOOST_FILESYSTEM_NO_DEPRECATED'],
}
def getDebugFlags(self, conf):
"""Get tuple {CXXFLAGS, LINKFLAGS, DEFINES} that are needed in debug mode"""
"""Get dict of CXXFLAGS, LINKFLAGS, and DEFINES that are needed only in debug mode"""
return {'CXXFLAGS': [], 'LINKFLAGS': [], 'DEFINES': ['_DEBUG']}
def getOptimizedFlags(self, conf):
"""Get tuple {CXXFLAGS, LINKFLAGS, DEFINES} that are needed in optimized mode"""
"""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 base flags that work for gcc and clang compiler"""
class GccClangCommonFlags(CompilerFlags):
"""
This class defines common flags that work for both gcc and clang compilers.
"""
def getGeneralFlags(self, conf):
flags = super().getGeneralFlags(conf)
flags['CXXFLAGS'] += ['-std=c++17']
if Utils.unversioned_sys_platform() != 'darwin':
flags['LINKFLAGS'] += ['-fuse-ld=lld']
return flags
__cxxFlags = [
'-fdiagnostics-color',
'-Wall',
'-Wextra',
'-Wpedantic',
'-Wenum-conversion',
'-Wextra-semi',
'-Wno-unused-parameter',
]
__linkFlags = ['-Wl,-O1']
def getDebugFlags(self, conf):
flags = super(GccBasicFlags, self).getDebugFlags(conf)
flags['CXXFLAGS'] += ['-pedantic', '-Wall',
'-O0',
'-g3',
'-Werror',
'-Wno-error=maybe-uninitialized', # Bug #1615
]
flags = super().getDebugFlags(conf)
flags['CXXFLAGS'] += ['-Og', '-g'] + self.__cxxFlags + [
'-Werror',
'-Wno-error=deprecated-declarations', # Bug #3795
'-Wno-error=maybe-uninitialized', # Bug #1615
]
flags['LINKFLAGS'] += self.__linkFlags
return flags
def getOptimizedFlags(self, conf):
flags = super(GccBasicFlags, self).getOptimizedFlags(conf)
flags['CXXFLAGS'] += ['-pedantic', '-Wall', '-O2', '-g']
flags = super().getOptimizedFlags(conf)
flags['CXXFLAGS'] += ['-O2', '-g1'] + self.__cxxFlags
flags['LINKFLAGS'] += self.__linkFlags
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
class GccFlags(GccClangCommonFlags):
__cxxFlags = [
'-Wcatch-value=2',
'-Wcomma-subscript', # enabled by default in C++20
'-Wduplicated-branches',
'-Wduplicated-cond',
'-Wlogical-op',
'-Wredundant-tags',
'-Wvolatile', # enabled by default in C++20
]
def getDebugFlags(self, conf):
flags = super(GccFlags, self).getDebugFlags(conf)
flags['CXXFLAGS'] += ['-Og', # gcc >= 4.8
'-fdiagnostics-color', # gcc >= 4.9
]
flags = super().getDebugFlags(conf)
flags['CXXFLAGS'] += self.__cxxFlags
if platform.machine() == 'armv7l':
flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
return flags
class ClangFlags(GccBasicFlags):
def getGeneralFlags(self, conf):
flags = super(ClangFlags, self).getGeneralFlags(conf)
flags['CXXFLAGS'] += ['-std=c++11',
'-Wno-error=unneeded-internal-declaration', # Bug #1588
'-Wno-error=deprecated-register',
]
if Utils.unversioned_sys_platform() == "darwin":
flags['CXXFLAGS'] += ['-stdlib=libc++']
flags['LINKFLAGS'] += ['-stdlib=libc++']
def getOptimizedFlags(self, conf):
flags = super().getOptimizedFlags(conf)
flags['CXXFLAGS'] += self.__cxxFlags
if platform.machine() == 'armv7l':
flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
return flags
class ClangFlags(GccClangCommonFlags):
def getGeneralFlags(self, conf):
flags = super().getGeneralFlags(conf)
if Utils.unversioned_sys_platform() == 'darwin':
# Bug #4296
brewdir = '/opt/homebrew' if platform.machine() == 'arm64' else '/usr/local'
flags['CXXFLAGS'] += [
['-isystem', f'{brewdir}/include'], # for Homebrew
['-isystem', '/opt/local/include'], # for MacPorts
]
elif Utils.unversioned_sys_platform() == 'freebsd':
# Bug #4790
flags['CXXFLAGS'] += [['-isystem', '/usr/local/include']]
return flags
__cxxFlags = [
'-Wundefined-func-template',
'-Wno-unused-local-typedef', # Bugs #2657 and #3209
]
def getDebugFlags(self, conf):
flags = super(ClangFlags, self).getDebugFlags(conf)
flags['CXXFLAGS'] += ['-fcolor-diagnostics']
flags = super().getDebugFlags(conf)
flags['CXXFLAGS'] += self.__cxxFlags
return flags
def getOptimizedFlags(self, conf):
flags = super().getOptimizedFlags(conf)
flags['CXXFLAGS'] += self.__cxxFlags
return flags
+22
View File
@@ -0,0 +1,22 @@
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def options(opt):
opt.add_option('--with-sanitizer', action='store', default='', dest='sanitizers',
help='Comma-separated list of compiler sanitizers to enable [default=none]')
def configure(conf):
for san in conf.options.sanitizers.split(','):
if not san:
continue
sanflag = '-fsanitize=%s' % san
conf.start_msg('Checking if compiler supports %s' % sanflag)
if conf.check_cxx(cxxflags=['-Werror', sanflag, '-fno-omit-frame-pointer'],
linkflags=[sanflag], mandatory=False):
conf.end_msg('yes')
conf.env.append_unique('CXXFLAGS', [sanflag, '-fno-omit-frame-pointer'])
conf.env.append_unique('LINKFLAGS', [sanflag])
else:
conf.end_msg('no', color='RED')
conf.fatal('%s sanitizer is not supported by the current compiler' % san)
+8 -8
View File
@@ -44,28 +44,28 @@ def apply_sphinx(self):
task.inputs.append(conf)
confdir = conf.parent.abspath()
buildername = getattr(self, "builder", "html")
srcdir = getattr(self, "srcdir", confdir)
outdir = self.path.find_or_declare(getattr(self, "outdir", buildername)).get_bld()
doctreedir = getattr(self, "doctreedir", os.path.join(outdir.abspath(), ".doctrees"))
buildername = getattr(self, 'builder', 'html')
srcdir = getattr(self, 'srcdir', confdir)
outdir = self.path.find_or_declare(getattr(self, 'outdir', buildername)).get_bld()
doctreedir = getattr(self, 'doctreedir', os.path.join(outdir.abspath(), '.doctrees'))
task.env['BUILDERNAME'] = buildername
task.env['SRCDIR'] = srcdir
task.env['DOCTREEDIR'] = doctreedir
task.env['OUTDIR'] = outdir.abspath()
task.env['VERSION'] = "version=%s" % self.VERSION
task.env['RELEASE'] = "release=%s" % self.VERSION
task.env['VERSION'] = 'version=%s' % self.version
task.env['RELEASE'] = 'release=%s' % getattr(self, 'release', self.version)
import imp
confData = imp.load_source('sphinx_conf', conf.abspath())
if buildername == "man":
if buildername == 'man':
for i in confData.man_pages:
target = outdir.find_or_declare('%s.%d' % (i[1], i[4]))
task.outputs.append(target)
if self.install_path:
self.bld.install_files("%s/man%d/" % (self.install_path, i[4]), target)
self.bld.install_files('%s/man%d/' % (self.install_path, i[4]), target)
else:
task.outputs.append(outdir)
+31 -16
View File
@@ -1,18 +1,33 @@
# ndn-tools authors
# ndn-tools Authors
## All project authors and contributors
The following lists maintainers, primary developers, and all much-appreciated contributors to ndn-tools in alphabetical order.
The specific contributions of individual authors can be obtained from the git history of the [official ndn-tools repository](https://github.com/named-data/ndn-tools).
If you would like to become a contributor to the official repository, please follow the recommendations in <https://github.com/named-data/.github/blob/main/CONTRIBUTING.md>.
The following is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS,
people who have reported bugs, submitted patches, and implemented new features
in ndn-tools:
* Jerald Paul Abraham <http://www.cs.arizona.edu/people/jeraldabraham/>
* Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
* Davide Pesavento <http://www.lip6.fr/actualite/personnes-fiche.php?ident=D1469>
* Junxiao Shi <http://www.cs.arizona.edu/people/shijunxiao/>
* Eric Newberry <http://ericnewberry.com/>
* Xiaoke Jiang <http://netarchlab.tsinghua.edu.cn/~shock/>
* Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
* Qi Zhao <https://www.linkedin.com/pub/qi-zhao/73/835/9a3>
* Seunghyun Yoo <http://relue2718.com/>
* Seungbae Kim <https://sites.google.com/site/sbkimcv/>
* Jerald Paul Abraham <https://cs.arizona.edu/~jeraldabraham>
* ***(Maintainer)*** Alexander Afanasyev <https://users.cs.fiu.edu/~afanasyev>
* Stephanie DiBenedetto
* Ashlesh Gawande <https://www.linkedin.com/in/agawande>
* Chavoosh Ghasemi <https://chavoosh.github.io>
* Nick Gordon <https://github.com/gorgonical>
* Xiaoke Jiang <http://netarchlab.tsinghua.edu.cn/~shock>
* Seungbae Kim <https://sites.google.com/site/sbkimcv>
* Vince Lehman <http://vslehman.com>
* Zhuo Li <https://github.com/mrzhuoli>
* Teng Liang <https://cs.arizona.edu/~philoliang>
* Weiwei Liu <https://www.linkedin.com/in/weiweiliu10>
* Eric Newberry <https://ericnewberry.com>
* João Pereira <http://www.jpereira.co.uk>
* ***(Maintainer)*** Davide Pesavento <https://github.com/Pesa>
* Klaus Schneider <https://cs.arizona.edu/~klaus>
* Wentao Shang <https://irl.cs.ucla.edu/~wentao>
* Susmit Shannigrahi <https://susm.it>
* Junxiao Shi <https://cs.arizona.edu/~shijunxiao>
* Jeff Thompson <https://remap.ucla.edu/jeff-thompson>
* Andrea Tosatto <https://linkedin.com/in/tosattoandrea>
* Zipeng Wang <https://github.com/zpwang2113>
* Ryan Wickman <https://rwickman.github.io>
* Seunghyun Yoo <https://relue2718.com>
* Qianshan Yu
* Yingdi Yu <https://irl.cs.ucla.edu/~yingdi>
* Qi Zhao <https://web.cs.ucla.edu/~qi.zhao>
+354 -356
View File
File diff suppressed because it is too large Load Diff
+17 -10
View File
@@ -4,19 +4,26 @@ This document describes how to build and install ndn-tools.
## Prerequisites
Building ndn-tools requires [ndn-cxx](http://named-data.net/doc/ndn-cxx/current/)
to be installed.
Please see [Getting Started with ndn-cxx](http://named-data.net/doc/ndn-cxx/current/INSTALL.html)
on how to install ndn-cxx.
Note: if you have installed ndn-cxx from a binary package, please make sure development headers
are installed (if using Ubuntu PPA, `ndn-cxx-dev` package is needed).
* Install the [ndn-cxx](https://github.com/named-data/ndn-cxx) library and its dependencies.
Check out [the documentation](https://docs.named-data.net/ndn-cxx/current/INSTALL.html) for
detailed installation instructions. All platforms supported by ndn-cxx are also supported
by ndn-tools.
Any operating system and compiler supported by ndn-cxx are supported by ndn-tools.
*Note*: If you have installed ndn-cxx from a binary package, please make sure the development
headers are installed (e.g., if using Ubuntu PPA, the `libndn-cxx-dev` package is needed).
* Install `libpcap` (except on macOS where it is provided by the base system).
On Debian and Ubuntu:
sudo apt install libpcap-dev
On CentOS and Fedora:
sudo dnf install libpcap-devel
## Build Steps
Waf meta build system is used by ndn-tools.
To configure, compile, and install ndn-tools, type the following commands
in ndn-tools source directory:
@@ -24,6 +31,6 @@ in ndn-tools source directory:
./waf
sudo ./waf install
To uninstall ndn-tools:
To uninstall:
sudo ./waf uninstall
+65 -58
View File
@@ -1,13 +1,14 @@
# Notes for ndn-tools Developers
# Notes for ndn-tools developers
## Licensing Requirements
Contributions to ndn-tools MUST be licensed under GPL 3.0 or a compatible license.
If you choose GPL 3.0, include the following license boilerplate into all C++ code files:
Contributions to ndn-tools must be licensed under the GPL v3 or a compatible license.
If you choose the GPL v3, please use the following license boilerplate in all `.hpp`
and `.cpp` files:
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) [Year(s)], [Copyright Holder(s)].
/*
* Copyright (c) [Year(s)] [Copyright Holder(s)].
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -26,91 +27,97 @@ If you choose GPL 3.0, include the following license boilerplate into all C++ co
## Directory Structure and Build Script
All tools are placed in subdirectories under `tools/` directory.
All tools are placed in subdirectories of the [`tools`](tools) directory.
A tool can consist of one or more programs.
For instance, a pair of consumer and producer programs that are designed to work together
should be considered a single tool, not two separate tools.
Each tool MUST have a `wscript` build script in its subdirectory.
It will be invoked if this tool is selected for the build.
It SHOULD compile the programs into `build/bin` directory (`target='../../bin/foo'`).
Each tool must have a `wscript` build script in its subdirectory. This script will be
invoked automatically if the corresponding tool is selected for the build. It should
compile the source code and produce one or more binaries in the `build/bin` directory
(e.g., use `target='../../bin/foo'`).
### Shared Modules
Modules shared among multiple tools SHOULD be placed in `core/` directory.
Modules shared among multiple tools should be placed in the [`core`](core) directory.
They are available for use in all tools.
A header in `core/` can be included in a tool like `#include "core/foo.hpp"`.
`wscript` of a tool can link a program with modules in `core/` with `use='core-objects'`.
The `wscript` of a tool can link a program with modules in `core/` with `use='core-objects'`.
### Documentation
`README.md` in the subdirectory of a tool SHOULD give a brief description.
A file named `README.md` in the subdirectory of each tool should provide a brief
description.
Manual pages for each program SHOULD be written in reStructuredText format
and placed in `manpages/` directory.
Manual pages for each program should be written in reStructuredText format
and placed in the [`manpages`](manpages) directory.
## Code Guidelines
C++ code SHOULD conform to
[ndn-cxx code style](http://named-data.net/doc/ndn-cxx/current/code-style.html).
C++ code should conform to the
[ndn-cxx code style](https://docs.named-data.net/ndn-cxx/current/code-style.html).
### Namespace
Types in each tool SHOULD be declared in a sub-namespace under `namespace ndn`.
For example, a tool in `tools/foo` directory has namespace `ndn::foo`.
Types in each tool should be declared in a sub-namespace inside `namespace ndn`.
For example, a tool in `tools/foo` directory has namespace `ndn::foo`.
This allows the tool to reference ndn-cxx types with unqualified name lookup.
This also prevents name conflicts between ndn-cxx and tools.
Types in `core/` SHOULD be declared directly under `namespace ndn`,
Types in `core/` should be declared directly inside `namespace ndn`,
or in a sub-namespace if desired.
`using namespace` SHOULD NOT be used except within block scope.
### main Function
The main function of a program SHOULD be declared within its sub-namespace.
This allows it to reference types in ndn-cxx and the tool with unqualified name lookup.
The `main` function of a program should be declared as a static function in
the namespace of the corresponding tool. This allows referencing types in
ndn-cxx and the tool via unqualified name lookup.
Then, another main function in global namespace needs to be defined
to call the main function in sub-namespace.
Then, another (non-static) `main` function must be defined in the global
namespace, and from there call the `main` function in the tool namespace.
For example:
These two functions should appear in a file named `main.cpp` in the tool's
subdirectory.
namespace ndn {
namespace foo {
class Bar
{
public:
explicit
Bar(Face& face);
void
run();
};
int
main(int argc, char** argv)
{
Face face;
Bar program(face);
program.run();
return 0;
}
} // namespace foo
} // namespace ndn
int
main(int argc, char** argv)
{
return ndn::foo::main(argc, argv);
}
Example:
```cpp
namespace ndn {
namespace foo {
class Bar
{
public:
explicit
Bar(Face& face);
void
run();
};
static int
main(int argc, char* argv[])
{
Face face;
Bar program(face);
program.run();
return 0;
}
} // namespace foo
} // namespace ndn
int
main(int argc, char* argv[])
{
return ndn::foo::main(argc, argv);
}
```
### Command Line Arguments
[Boost.Program\_options](http://www.boost.org/doc/libs/1_48_0/doc/html/program_options.html) is
preferred over getopt(3) for parsing command line arguments.
[Boost.Program\_options](https://www.boost.org/doc/libs/1_71_0/doc/html/program_options.html)
is strongly preferred over `getopt(3)` for parsing command line arguments.
+35 -16
View File
@@ -1,21 +1,40 @@
# NDN Essential Tools
**ndn-tools** is a collection of essential tools for
[Named Data Networking](http://named-data.net/).
These tools are recommended to be installed on all NDN nodes.
Tools in this collection include:
[![CI](https://github.com/named-data/ndn-tools/actions/workflows/ci.yml/badge.svg)](https://github.com/named-data/ndn-tools/actions/workflows/ci.yml)
[![Docs](https://github.com/named-data/ndn-tools/actions/workflows/docs.yml/badge.svg)](https://github.com/named-data/ndn-tools/actions/workflows/docs.yml)
![Language](https://img.shields.io/badge/C%2B%2B-17-blue)
![Latest version](https://img.shields.io/github/v/tag/named-data/ndn-tools?label=Latest%20version)
* [peek](tools/peek): transmit a single packet between a consumer and a producer
* [ping](tools/ping): test reachability between two nodes
* [dump](tools/dump): analyze traffic on wire
* [dissect](tools/dissect): inspect TLV structure of NDN packet format
* [dissect-wireshark](tools/dissect-wireshark): Wireshark extension to inspect TLV structure of NDN
packets
* [pib](tools/pib): a service to manage the public information of keys and publish certificates
This repository contains a collection of basic tools for [Named Data Networking (NDN)](https://named-data.net/).
The tools currently included are:
See [INSTALL.md](INSTALL.md) for build instructions.
* [**peek**](tools/peek): transmit a single Interest/Data packet between a consumer
and a producer
* [**chunks**](tools/chunks): segmented file transfer between a consumer and a producer
* [**ping**](tools/ping): test reachability between two NDN nodes
* [**dump**](tools/dump): capture and analyze live traffic on an NDN network
* [**dissect**](tools/dissect): inspect the TLV structure of an NDN packet
* [**dissect-wireshark**](tools/dissect-wireshark): Wireshark extension to inspect
the TLV structure of NDN packets
Please file bug reports and feature requests on
[ndn-tools Redmine site](http://redmine.named-data.net/projects/ndn-tools).
You may contribute code on [NDN Gerrit](http://gerrit.named-data.net).
GitHub pull requests are not accepted.
## Installation
See [`INSTALL.md`](INSTALL.md) for build instructions.
## Reporting bugs
Please submit any bug reports or feature requests to the
[ndn-tools issue tracker](https://redmine.named-data.net/projects/ndn-tools/issues).
## Contributing
Contributions to ndn-tools are greatly appreciated and can be made through our
[Gerrit code review site](https://gerrit.named-data.net/).
If you are new to the NDN software community, please read our
[Contributor's Guide](https://github.com/named-data/.github/blob/main/CONTRIBUTING.md)
and [`README-dev.md`](README-dev.md) to get started.
## License
ndn-tools is free software distributed under the GNU General Public License version 3.
See [`COPYING.md`](COPYING.md) for details.
+302
View File
@@ -0,0 +1,302 @@
# Release Notes
## Version 22.12
The minimum build requirements have been increased as follows:
- Either GCC >= 7.4.0 or Clang >= 6.0 is required on Linux
- On macOS, Xcode 11.3 or later is recommended; older versions may still work but are
not officially supported
- Boost >= 1.65.1 is required on all platforms
- Sphinx 4.0 or later is required to build the manual pages
chunks:
- Avoid excess window decrease in certain conditions (Issue #5202)
- Use ndn-cxx's `Segmenter` class (Issue #4702)
dissect:
- Recognize several TLV elements that appear in `Certificate` and `SafeBag`
- Remove support for obsolete TLV types
dissect-wireshark:
- Expose `type`, `len`, and `bin` fields
build system:
- Switch to C++17
- macOS 12 (Monterey) and 13 (Ventura) running on arm64 are now supported out-of-the-box
(Issue #5135)
- CentOS Stream 9 is now supported; CentOS 8 has been dropped (Issue #5181)
- Stop using the `gold` linker on Linux; prefer instead linking with `lld` if installed
- Upgrade `waf` to version 2.0.24
## Version 22.02
Starting with this release, ndn-tools switched to a date-based versioning scheme:
`YEAR.MONTH[.PATCH]` (`YY.0M[.MICRO]` in [CalVer](https://calver.org/) notation).
chunks:
- Add `--naming-convention` command-line option (Issue #5109)
- Increase the default segment size to 8000 bytes
dissect:
- Support `InterestSignature` fields and more types of name components
- The `Content` field is no longer dissected by default; use the new `--content` option
to enable it
- Minor cosmetic improvements to the tool output
dissect-wireshark:
- Remove support for obsolete TLV elements
- Recognize `ForwardingHint` (Issue #4185)
- Recognize `ParametersSha256DigestComponent`
- Fix decoding of several TLV elements such as `HopLimit` and `PitToken`
- Update the TLV type of `IncomingFaceId` (Issue #5185)
peek:
- Replace `--link-file` option with `--fwhint` and adapt to the new `ForwardingHint`
format (Issues #4207, #5187)
poke:
- Remove deprecated `--force` option; use `--unsolicited` instead
- Remove deprecated `--identity` and `--digest` options; use `--signing-info` instead
- Change the short form of `--freshness` to `-f`
pingserver:
- Remove deprecated `-x` alias for the `--freshness` option
build system:
- Upgrade `waf` to version 2.0.23
## Version 0.7.1
The build requirements have been increased to require Clang >= 4.0, Xcode >= 9.0, and Python >= 3.6.
Meanwhile, it is *recommended* to use GCC >= 7.4.0 and Boost >= 1.65.1.
This release contains minor build fixes and code cleanups.
## Version 0.7
chunks:
- Add `--no-version-discovery` option to ndncatchunks (Issue #5021)
- Improve CUBIC performance on lossy networks (Issue #5036)
- Switch to ndn-cxx's `RttEstimatorWithStats` class (Issue #4887)
- Remove previously deprecated options `-d` and `-t` from ndncatchunks
ping:
- Change the short form of ndnpingserver's `--freshness` option to `-f`,
for consistency with ndnputchunks
peek:
- Add `--app-params`, `--app-params-file`, and `--hop-limit` options
- The `--link-file` option now expects a raw binary file
- Print Data name and Nack reason if `--verbose` is specified
- Code cleanup
- Manual page improvements
poke:
- Add `--signing-info` option, replacing `--digest` and `--identity` which are
now deprecated
- Add `--verbose` option
- Wait indefinitely if `--timeout` is not specified
- The program now exits with status 3 when a timeout occurs and with status 5
if prefix registration fails
- Rename `--force` option to `--unsolicited`
- Code cleanup
- Major rewrite of the manual page
## Version 0.6.4
chunks:
- Add metadata-based version discovery and remove iterative discovery (Issue #4556)
- Remove manual selection of version discovery method via `-d` option (Issue #4832)
- Implement CUBIC congestion window adaptation in ndncatchunks (Issue #4861)
- Increase the default retransmission limit from 3 to 15 (Issue #4861)
- Improve stats printed by ndncatchunks after transfer completes (Issue #4603)
- Add manual page for ndnputchunks
dissect & dissect-wireshark:
- Follow packet specification changes to renumber the `Parameters` element and
rename it to `ApplicationParameters` (Issues #4658, #4780)
dump:
- Fix compilation on CentOS 7 (Issue #4852)
pib:
- Completely remove this obsolete and unmaintained tool (Issue #4205)
## Version 0.6.3
chunks:
- Fix impossible RTT values (Issue #4604)
- Add support for RDR metadata in ndnputchunks (Issue #4556)
- Use `PendingInterestHandle` and `RegisteredPrefixHandle` (Issues #4316, #3919)
ping:
- Add systemd unit file for ndnpingserver (Issue #4594)
- Use `PendingInterestHandle` and `RegisteredPrefixHandle` (Issues #4316, #3919)
poke:
- Use `PendingInterestHandle` and `RegisteredPrefixHandle` (Issues #4316, #3919)
build system:
- Upgrade `waf` to version 2.0.14 and other improvements
## Version 0.6.2
The build requirements have been upgraded to gcc >= 5.3 or clang >= 3.6, boost >= 1.58,
openssl >= 1.0.2. This effectively drops support for all versions of Ubuntu older than 16.04
that use distribution-provided compilers and packages.
The compilation now uses the C++14 standard.
chunks:
- Fix AIMD hanging with files smaller than the chunk size (Issue #4439)
dissect-wireshark:
- Show `Name` and `FinalBlockId` as URIs (Issue #3106)
- Improve NDNLPv2 support (Issue #4463)
- Add support for dissecting PPP frames
dump:
- Remove dependency on Boost.Regex
- Stop using tcpdump headers files
- Compile pcap filter with optimizations enabled
- Capture in promiscuous mode by default, add an option to disable it
- Add `-t` option to suppress printing per-packet timestamp
- Properly handle exceptions thrown by `lp::Packet::wireDecode()` (Issue #3943)
- Add UDP port 56363 to the default pcap filter
- Stricter parsing of IP/TCP/UDP headers
- Add IPv6 support
- Code cleanup
poke:
- Use `Face::unsetInterestFilter` instead of `shutdown` (Issue #4642)
- Improve unit testing (Issue #3740)
ping:
- Add `--quiet` option to ndnpingserver (Issue #4673)
- Set `CanBePrefix=false` in Interests sent by ndnping (Issue #4581)
- Code cleanup
## Version 0.6.1
chunks:
- Show correct packet loss stats in final summary (Issue #4437)
- Avoid printing meaningless values when no RTT measurements are available (Issue #4551)
dissect:
- Recognize `CanBePrefix`, `HopLimit`, and `Parameters` TLV elements (Issue #4590)
dissect-wireshark:
- Recognize `CanBePrefix`, `HopLimit`, and `Parameters` TLV elements (Issue #4517)
peek:
- Drop `Selectors` support (Issue #4571)
- Add `-P/--prefix` option to set `CanBePrefix` in the Interest packet
build system:
- Upgrade `waf` to version 2.0.6 and other improvements
## Version 0.6
chunks:
- Change the default Interest pipeline to AIMD (Issue #4402)
- Include RTT stats in final summary (Issue #4406)
- Respect `--retries=-1` in the AIMD pipeline (Issue #4409)
- React to congestion marks by default as a timeout event (can be disabled using
`--aimd-ignore-cong-marks`) (Issue #4289)
- Print a final summary of the transfer regardless of the pipeline type, and even if
`--verbose` was not specified (Issue #4421)
## Version 0.5
all:
- Switch to version 2 of certificates, `KeyChain`, and `Validator` (Issue #4089)
- Compilation fixes (Issue #4259)
chunks:
- Make `ndnputchunks` display some output by default; a new `-q` flag makes the tool
completely silent, except for errors (Issue #4286)
- Refactor `ndnputchunks` options handling
- Reduce initial timeout of iterative version discovery in `ndncatchunks` (Issue #4291)
- Fix potential `ndncatchunks` crash on exit
peek:
- Convert use of `Link` into `ForwardingHint` (Issue #4055)
## Version 0.4
As of this version, NDN Essential Tools require a modern compiler (gcc >= 4.8.2, clang >= 3.4)
and a relatively new version of the Boost libraries (>= 1.54). This means that the code no
longer compiles with the packaged version of gcc and Boost libraries on Ubuntu 12.04.
NDN Essential Tools can still be compiled on such systems, but require a separate
installation of a newer version of the compiler (e.g., clang-3.4) and dependencies.
chunks:
- Change default version discovery to iterative
- Improve help text of `ndnputchunks`
- Fix `DiscoverVersionIterative` build error
- Modularize Interest pipeline implementation
- Add AIMD congestion control (Issue #3636)
- Code cleanup and improvements
dissect-wireshark:
- Add initial support for NDNLPv2 (Issue #3197)
- Fix potential memory overflow
dump:
- Add support for Linux cooked-mode capture (SLL) (Issue #3061)
- Improve error messages
pib:
- Disable by default (can be compiled with ndn-cxx version 0.5.0)
- Fix compilation error with new version of ndn-cxx library
- Avoid use of deprecated block helpers
- Correct build target path
ping:
- Recognize and trace NACK
- Fix potential divide-by-zero bug in `StatisticsCollector` (Issue #3504)
peek:
- Recognize and properly handle NACK
- Refactor implementation
## Version 0.3
chunks: **New** (pair of) tool(s) for segmented file transfer
peek:
- Allow verbose output
- Switch from `getopt` to `boost::program_options`
- Add `--link-file` option
ping:
- Document ndnping protocol
dump:
- Capture and print network NACK packets
- Update docs to include NACK capture feature
build system:
- Enable `-Wextra` by default
- Fix missing tool name in `configure --help` output
- Fix compatibility with Python 3
## Version 0.2
Code improvements and two new tools:
- PIB service to manage the public information of keys and publish certificates
(Issue 3018)
- A Wireshark dissector for NDN packets (Issue 3092)
## Version 0.1
Initial release of NDN Essential Tools, featuring:
- ndnpeek, ndnpoke: a pair of programs to request and make available for
retrieval a single Data packet.
- ndnping, ndnpingserver: reachability testing tools for Named Data Networking.
- ndndump: a traffic analysis tool that captures NDN packets on the wire.
- ndn-dissect: an NDN packet format inspector. It reads zero or more NDN
packets from either an input file or the standard input, and displays the
Type-Length-Value (TLV) structure of those packets on the standard output.
+24 -22
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -38,45 +38,47 @@
#define PROTECTED_WITH_TESTS_ELSE_PRIVATE private
#endif
#include <cinttypes>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <limits>
#include <memory>
#include <optional>
#include <stdexcept>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include <boost/asio.hpp>
#include <boost/assert.hpp>
#include <boost/core/noncopyable.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/noncopyable.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/parsers.hpp>
#include <ndn-cxx/data.hpp>
#include <ndn-cxx/face.hpp>
#include <ndn-cxx/interest.hpp>
#include <ndn-cxx/name.hpp>
#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/security/signing-helpers.hpp>
#include <ndn-cxx/security/signing-info.hpp>
#include <ndn-cxx/util/backports.hpp>
#include <ndn-cxx/util/exception.hpp>
#include <ndn-cxx/util/scheduler.hpp>
#include <ndn-cxx/util/scheduler-scoped-event-id.hpp>
#include <ndn-cxx/util/signal.hpp>
#include <ndn-cxx/util/time.hpp>
namespace ndn {
using std::shared_ptr;
using std::unique_ptr;
using std::make_shared;
using std::make_unique;
using std::size_t;
using boost::noncopyable;
namespace signal = util::signal;
namespace scheduler = util::scheduler;
} // namespace ndn
#define FORWARD_TO_MEM_FN(func) \
[this] (auto&&... args) { this->func(std::forward<decltype(args)>(args)...); }
#endif // NDN_TOOLS_CORE_COMMON_HPP
+45
View File
@@ -0,0 +1,45 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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 ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "core/program-options-ext.hpp"
namespace ndn {
void
validate(boost::any& v, const std::vector<std::string>& values, Name*, int)
{
using namespace boost::program_options;
validators::check_first_occurrence(v);
const std::string& s = validators::get_single_string(values);
try {
v = Name(s);
} catch (const Name::Error&) {
throw invalid_option_value(s);
}
}
} // namespace ndn
@@ -1,6 +1,12 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California.
/*
* Copyright (c) 2014-2022, 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 ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -15,52 +21,22 @@
*
* You should have received a copy of the GNU General Public License along with
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* @author Yingdi Yu <yingdi@cs.ucla.edu>
*/
#ifndef NDN_TOOLS_PIB_LIST_QUERY_PROCESSOR_HPP
#define NDN_TOOLS_PIB_LIST_QUERY_PROCESSOR_HPP
#ifndef NDN_TOOLS_CORE_PROGRAM_OPTIONS_EXT_HPP
#define NDN_TOOLS_CORE_PROGRAM_OPTIONS_EXT_HPP
#include "pib-db.hpp"
#include "encoding/list-param.hpp"
#include <ndn-cxx/interest.hpp>
#include <utility>
#include <ndn-cxx/name.hpp>
#include <boost/program_options/value_semantic.hpp>
namespace ndn {
namespace pib {
class ListQueryProcessor : noncopyable
{
public:
class Error : public std::runtime_error
{
public:
explicit
Error(const std::string& what)
: std::runtime_error(what)
{
}
};
/**
* @brief Provide a Boost.Program_options custom validator for ndn::Name type.
*/
void
validate(boost::any& v, const std::vector<std::string>& values, Name*, int);
/**
* @brief Constructor
*
* @param db The pib database.
*/
explicit
ListQueryProcessor(PibDb& db);
std::pair<bool, Block>
operator()(const Interest& interest);
private:
static const size_t LIST_QUERY_LENGTH;
const PibDb& m_db;
};
} // namespace pib
} // namespace ndn
#endif // NDN_TOOLS_PIB_LIST_QUERY_PROCESSOR_HPP
#endif // NDN_TOOLS_CORE_PROGRAM_OPTIONS_EXT_HPP
+6 -8
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Arizona Board of Regents.
/*
* Copyright (c) 2014-2022, Arizona Board of Regents.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -17,12 +17,10 @@
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "version.hpp"
#include "core/version.hpp"
namespace ndn {
namespace tools {
namespace ndn::tools {
const char VERSION[] = "0.2";
const char VERSION[] = "@VERSION_BUILD@";
} // namespace tools
} // namespace ndn
} // namespace ndn::tools
+7 -8
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Arizona Board of Regents.
/*
* Copyright (c) 2014-2022, Arizona Board of Regents.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -20,16 +20,15 @@
#ifndef NDN_TOOLS_CORE_VERSION_HPP
#define NDN_TOOLS_CORE_VERSION_HPP
#include "common.hpp"
#include "core/common.hpp"
namespace ndn {
namespace tools {
namespace ndn::tools {
/** \brief version of ndn-tools
/**
* \brief The version of ndn-tools.
*/
extern const char VERSION[];
} // namespace tools
} // namespace ndn
} // namespace ndn::tools
#endif // NDN_TOOLS_CORE_VERSION_HPP
+43 -10
View File
@@ -1,16 +1,49 @@
# General information about the project.
project = u'NDN Essential Tools'
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Options for manual page output ---------------------------------------
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
project = 'NDN Essential Tools'
copyright = 'Copyright © 2014-2023 Named Data Networking Project.'
author = 'Named Data Networking Project'
# The short X.Y version.
#version = ''
# The full version, including alpha/beta/rc tags.
#release = ''
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
today_fmt = '%Y-%m-%d'
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
needs_sphinx = '4.0'
extensions = []
templates_path = ['_templates']
exclude_patterns = ['Thumbs.db', '.DS_Store']
# -- Options for manual page output ------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-manual-page-output
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('ndnpeek', 'ndnpeek', 'simple consumer to send one Interest and expect one Data', None, 1),
('ndnpoke', 'ndnpoke', 'simple producer to publish one Data', None, 1),
('ndnping', 'ndnping', 'reachability testing client', None, 1),
('ndnpingserver', 'ndnpingserver', 'reachability testing server', None, 1),
('ndndump', 'ndndump', 'traffic analysis tool', None, 8),
('ndn-dissect', 'ndn-dissect', 'NDN packet format inspector', None, 1),
('ndn-pib', 'ndn-pib', 'NDN PIB service', None, 1),
('ndnpeek', 'ndnpeek', 'simple consumer to send one Interest and receive one Data', [], 1),
('ndnpoke', 'ndnpoke', 'simple producer to publish one Data', [], 1),
('ndnping', 'ndnping', 'reachability testing client', [], 1),
('ndnpingserver', 'ndnpingserver', 'reachability testing server', [], 1),
('ndnputchunks', 'ndnputchunks', 'producer program with content segmentation', [], 1),
('ndndump', 'ndndump', 'traffic analysis tool', [], 8),
('ndn-dissect', 'ndn-dissect', 'NDN packet format inspector', [], 1),
]
+8
View File
@@ -0,0 +1,8 @@
.. toctree::
ndn-dissect
ndndump
ndnpeek
ndnping
ndnpingserver
ndnpoke
ndnputchunks
+24 -19
View File
@@ -1,38 +1,43 @@
ndn-dissect
===========
Usage
-----
Synopsis
--------
::
ndn-dissect [-hV] [input-file]
**ndn-dissect** [**-h**] [**-c**] [**-V**] [*file*]
Description
-----------
``ndn-dissect`` is an NDN packet format inspector.
It reads zero or more NDN packets from either an input file or the standard input,
and displays the Type-Length-Value (TLV) structure of those packets on the standard output.
:program:`ndn-dissect` is an NDN packet format inspector.
It reads zero or more NDN packets from either an input file or the standard
input, and displays the Type-Length-Value (TLV) structure of those packets
on the standard output.
Options
-------
``-h``
Print help and exit.
.. option:: -h, --help
``-V``
Print version and exit.
Print help and exit.
``input-file``
The file to read packets from.
If no :option:`input-file` is given, the standard input is used.
.. option:: -c, --content
Dissect the value of Content elements as well. By default, the value of a
Content element is treated as an opaque blob and is not dissected further.
.. option:: -V, --version
Print program version and exit.
.. option:: file
The file to read packets from.
If no *file* is given, or if *file* is "-", the standard input is used.
Examples
--------
Inspect the response to Interest ``ndn:/app1/video``
Inspect the response to Interest ``/app1/video``::
::
ndnpeek ndn:/app1/video | ndn-dissect
ndnpeek /app1/video | ndn-dissect
-35
View File
@@ -1,35 +0,0 @@
ndn-pib
========
``ndn-pib`` is a public key and certificate management and publishing service.
Usage
-----
::
ndn-pib [-h] -o owner -d database_dir -t tpm_locator
Description
-----------
This command will start a PIB service process which serves signing key lookup/management for local
applications and also public the public key certificate of signing keys. The lookup/management
interface listens on a prefix "/localhost/pib/[OwnerName]" and accept five types of command (get,
default, list, update, delete). More details can be found at `Public key Info Base (PIB) Service
<http://redmine.named-data.net/projects/ndn-cxx/wiki/PublicKey_Info_Base>`__
Since PIB service is queried through Interest/Data exchange, NFD is required to run before this
command is executed.
This command requires three arguments: ``owner`` specify the owner of the pib service, which is also
the third name component in the local lookup/management prefix; ``database_dir`` is the path to the
database where all the public key, certificate, identity are stored and managed; ``tpm_locator`` is
locator of a TPM which stores the corresponding private key of the public keys in PIB.
Example
-------
::
$ ndn-pib -o alice -d /var/pib -t tpm-file:/var/ndn/tpm
+48 -26
View File
@@ -6,54 +6,76 @@ Usage
::
ndndump [-hV] [-i interface] [-r file] [-f filter] [expression]
ndndump [-hvV] [-i INTERFACE] [-r FILE] [-f FILTER] [PCAP-FILTER]
Description
-----------
:program:`ndndump` is a traffic analysis tool that captures Interest and Data packets on the wire,
and displays brief information about captured packets.
:program:`ndndump` is a traffic analysis tool that captures NDN packets on the wire and
displays brief information about them.
Currently, :program:`ndndump` is capable of extracting Interest and Data packets from:
Currently, :program:`ndndump` is capable of extracting Interest, Data, and Nack packets from:
* Ethernet, when bare Interest/Data is transmitted without NDNLP header
* Ethernet frame
* PPP link (e.g., pcap trace from ndnSIM)
* IPv4 UDP unicast tunnel
* IPv4 UDP multicast group
* IPv6 TCP tunnel, when Interest/Data is aligned to the front of a TCP segment
* IPv4 TCP tunnel, when Interest/Data/Nack is aligned to the beginning of a TCP segment
For more complex scenarios, including the case of NDN packets that span multiple IP fragments
or multiple TCP segments, it is recommended to use the **NDN Wireshark dissector**, either via
:manpage:`wireshark(1)` or :manpage:`tshark(1)`.
Options
-------
``-h``
Print help and exit.
.. option:: -h, --help
``-V``
Print version and exit.
Print help and exit.
``-i``
Listen on :option:`interface`.
If unspecified, ndndump searches the system interface list for the lowest numbered,
configured up interface (excluding loopback).
.. option:: -i INTERFACE, --interface=INTERFACE
``-r``
Read packets from :option:`file` (which was created with :manpage:`tcpdump(8)` using its -w option).
Listen on *INTERFACE*.
If unspecified, ndndump searches the system interface list for the lowest numbered,
configured up interface (excluding loopback).
On Linux, a value of "any" can be used to capture packets from all interfaces.
Note that captures on the "any" pseudo-interface will not be done in promiscuous mode.
``-v``
Produce verbose output.
.. option:: -r FILE, --read=FILE
``-f``
Print a packet only if its Name matches the regular expression :option:`filter`.
Read packets from *FILE*, which can be created by :manpage:`tcpdump(8)` with its
``-w`` option, or by similar programs.
``expression``
Selects which packets will be analyzed, in :manpage:`pcap-filter(7)` format.
If no :option:`expression` is given, a default expression is implied which can be seen with ``-h`` option.
.. option:: -f FILTER, --filter=FILTER
Print a packet only if its name matches the regular expression *FILTER*.
.. option:: -p, --no-promiscuous-mode
Do not put the interface into promiscuous mode.
.. option:: -t, --no-timestamp
Do not print a timestamp for each packet.
.. option:: -v, --verbose
Produce verbose output.
.. option:: -V, --version
Print ndndump and libpcap version strings and exit.
.. option:: PCAP-FILTER
:option:`PCAP-FILTER` is an expression in :manpage:`pcap-filter(7)` format that
selects which packets will be analyzed.
If no :option:`PCAP-FILTER` is given, a default filter is used. The default filter
can be seen with the :option:`--help` option.
Examples
--------
Capture on eth1 and print packets containing "ping":
::
Capture on eth1 and print packets containing "ping"::
ndndump -i eth1 -f '.*ping.*'
+55 -28
View File
@@ -1,56 +1,83 @@
ndnpeek
=======
Usage
-----
Synopsis
--------
::
ndnpeek [-h] [-f] [-r] [-m min] [-M max] [-l lifetime] [-p] [-w timeout] name
**ndnpeek** [-h] [-P] [-f] [-l *lifetime*] [-H *hops*] [-A *parameters*]
[-p] [-w *timeout*] [-v] [-V] *name*
Description
-----------
``ndnpeek`` is a simple consumer program that sends one Interest and expects one Data
packet in response. The full Data packet (in TLV format) is written to stdout. The
program terminates with return code 0 if Data arrives, and with return code 1 when timeout
occurs.
:program:`ndnpeek` is a simple consumer program that sends one Interest and
expects one Data packet in response. By default, the full Data packet (in TLV
format) is written to the standard output.
``name`` is interpreted as the Interest name.
*name* is interpreted as the Interest name.
Options
-------
``-h``
Print help and exit
``-h, --help``
Print help and exit.
``-f``
If specified, set ``MustBeFresh`` selector in the Interest packet.
``-P, --prefix``
If specified, include ``CanBePrefix`` element in the Interest packet.
``-r``
Set ``ChildSelector=1`` (the rightmost child) selector.
``-f, --fresh``
If specified, include ``MustBeFresh`` element in the Interest packet.
``-m``
Set ``min`` as the ``MinSuffixComponents`` selector.
``-F, --fwhint <name>``
Add a delegation name to the ``ForwardingHint`` of the Interest packet.
This option may be repeated to specify multiple delegation names.
``-M``
Set ``max`` as the ``MaxSuffixComponents`` selector.
``-l``
``-l, --lifetime <lifetime>``
Set ``lifetime`` (in milliseconds) as the ``InterestLifetime``.
``-p``
``-H, --hop-limit <hops>``
Set the Interest's ``HopLimit`` to the specified number of hops.
``-A, --app-params <parameters>``
Set the Interest's ``ApplicationParameters`` from a base64-encoded string.
``--app-params-file <file>``
Set the Interest's ``ApplicationParameters`` from the specified file.
``-p, --payload``
If specified, print the received payload only, not the full packet.
``-w``
Timeout after ``timeout`` milliseconds.
``-w, --timeout <timeout>``
Quit the program after ``timeout`` milliseconds, even if no reply has been received.
``-v, --verbose``
Turn on verbose output.
``-V, --version``
Print version and exit.
Exit Status
-----------
0: Success
1: An unspecified error occurred
2: Malformed command line
3: Operation timed out
4: Nack received
Examples
--------
Send Interest for ``ndn:/app1/video`` and print the received payload only
Send an Interest for ``/app1/video`` and print the received payload only::
::
ndnpeek -p /app1/video
ndnpeek -p ndn:/app1/video
Send an Interest for ``/app2/foo``, requesting fresh content, with an InterestLifetime
of 8 seconds, and with the ApplicationParameters containing the ASCII string "hello";
print the performed operations verbosely but discard the received Data packet::
ndnpeek -vf -l 8000 -A "aGVsbG8=" /app2/foo >/dev/null
+29 -30
View File
@@ -1,25 +1,23 @@
ndnping
=======
ndnpingserver
=============
Usage
-----
Synopsis
--------
::
ndnpingserver [-h] [-V] [-x freshness] [-p satisfy] [-t] [-s size] prefix
**ndnpingserver** [-h] [-f *freshness*] [-p *count*] [-s *size*] [-t] [-q] [-V] *prefix*
Description
-----------
``ndnpingserver`` listens for the specified Interest prefix and sends Data packets when an Interest
under that prefix is received. Once ``ndnpingserver`` either reaches the specified total number of
Interests to be satisfied or receives an interrupt signal, it prints the number of Data packets
sent.
:program:`ndnpingserver` listens for the specified Interest prefix and sends Data packets when
an Interest under that prefix is received. Once :program:`ndnpingserver` either reaches the
specified total number of Interests to be satisfied or receives an interrupt signal, it prints
the number of Data packets sent.
``prefix`` is interpreted as the Interest prefix to listen for. The FreshnessPeriod of Data packets
is set with the -x option (default 1000ms). The content is by default empty, but if a size is
specified with the '-s' option, it contains the specified number of the letter "a". Finally, the
Data is signed with an SHA256 digest.
*prefix* is interpreted as the Interest prefix to listen for. The FreshnessPeriod of Data packets
is set with the **-f** option (default 1 second). The content is by default empty, but if a size
is specified with the **-s** option, it contains the specified number of the letter "a". Finally,
the Data is signed with a SHA-256 digest.
Options
-------
@@ -27,27 +25,28 @@ Options
``-h``
Print help and exit.
``-V``
Print version and exit.
``-x``
Set freshness period in milliseconds (minimum 1000ms).
``-f``
Set freshness period in milliseconds.
``-p``
Set maximum number of pings to satisfy.
``-t``
Prints a timestamp with received Data and timeouts.
Maximum number of pings to satisfy. A value of 0 means no limit.
``-s``
Specify the size of the response payload.
Size of the response payload.
``-t``
Print a timestamp before each log message.
``-q``
Do not print a log message each time a ping is received.
``-V``
Print version and exit.
Examples
--------
Listen on ``ndn:/edu/arizona`` and response to at most 4 pings, printing timestamp on each received
ping
Listen on ``/edu/arizona`` and respond to at most 4 pings, printing the timestamp
on each received ping::
::
ndnpingserver -p 4 -t ndn:/edu/arizona
ndnpingserver -p 4 -t /edu/arizona
+48 -30
View File
@@ -1,54 +1,72 @@
ndnpoke
=======
Usage
-----
Synopsis
--------
::
ndnpoke [-h] [-f] [-D] [-i identity] [-F] [-x freshness] [-w timeout] name
**ndnpoke** [-h] [-f *freshness*] [-F] [-S *info*] [-u\|\ -w *timeout*] [-v] [-V] *name*
Description
-----------
``ndnpoke`` is a simple producer program that reads payload from stdin and publishes it
as a single NDN Data packet. The Data packet is published either as a response to the
incoming Interest for the given ``name``, or forcefully pushed to the local NDN
forwarder's cache if ``-f`` flag is specified.
The program terminates with return code 0 if Data is sent and with return code 1 when
timeout occurs.
:program:`ndnpoke` is a simple producer program that reads a payload from the standard
input and publishes it as a single Data packet. The Data packet is either sent as a
response to an incoming Interest matching *name*, or immediately pushed to the local
NDN forwarder as "unsolicited Data" if the **-u** flag is specified.
Options
-------
``-h``
Print usage and exit.
``-h, --help``
Print help and exit.
``-f``
If specified, send Data without waiting for Interest.
``-f, --freshness <freshness>``
Set ``freshness`` (in milliseconds) as the ``FreshnessPeriod``.
``-D``
If specified, use ``DigestSha256`` signature instead of default ``SignatureSha256WithRsa``.
``-F, --final``
Set the ``FinalBlockId`` to the last component of *name*.
``-i``
Use ``identity`` to sign the created Data packet.
``-S, --signing-info <info>``
Specify the parameters used to sign the Data packet. If omitted, the default key of
the default identity is used. The general syntax is ``<scheme>:<name>``. The most
common supported combinations are as follows:
``-F``
Set ``FinalBlockId`` to the last component of specified name.
* Sign with the default certificate of the default key of an identity: ``id:/<my-identity>``.
* Sign with the default certificate of a specific key: ``key:/<my-identity>/ksk-1``.
* Sign with a specific certificate: ``cert:/<my-identity>/KEY/ksk-1/ID-CERT/v=1``.
* Sign with a SHA-256 digest: ``id:/localhost/identity/digest-sha256``. Note that this
is only a hash function, not a real signature, but it can significantly speed up
packet signing operations.
``-x``
Set ``FreshnessPeriod`` in milliseconds.
``-u, --unsolicited``
Send the Data packet without waiting for an incoming Interest.
``-w``
Wait at most ``timeout`` milliseconds for the incoming Interest. If no Interest arrives
within the ``timeout``, the Data packet will not be published.
``-w, --timeout <timeout>``
Quit the program after ``timeout`` milliseconds, even if no Interest has been received.
``-v, --verbose``
Turn on verbose output.
``-V, --version``
Print version and exit.
Exit Status
-----------
0: Success
1: An unspecified error occurred
2: Malformed command line
3: No Interests received before the timeout
5: Prefix registration failed
Examples
--------
Create Data packet with content ``hello`` with the name ``ndn:/app/video`` and wait at
most 3 seconds for the incoming Interest for it::
Create a Data packet with content ``hello`` and name ``/app/video`` and wait at
most 3 seconds for a matching Interest to arrive::
echo "Hello" | build/bin/ndnpoke -w 3000 ndn:/app/video
echo "hello" | ndnpoke -w 3000 /app/video
+98
View File
@@ -0,0 +1,98 @@
ndnputchunks
============
Synopsis
--------
**ndnputchunks** [*option*]... *name*
Description
-----------
:program:`ndnputchunks` is a producer program that reads a file from the standard input
and makes it available as NDN Data segments.
Version and segment number components are appended to the specified *name* as needed,
according to the `NDN naming conventions`_.
.. _NDN naming conventions: https://named-data.net/publications/techreports/ndn-tr-22-3-ndn-memo-naming-conventions/
Options
-------
.. option:: -h, --help
Print help and exit.
.. option:: -f, --freshness MILLISECS
FreshnessPeriod of the published Data packets, in milliseconds.
The default is 10000 (10 seconds).
.. option:: -s, --size BYTES
Maximum chunk size, in bytes. The default is 8000 bytes.
.. option:: -N, --naming-convention CONVENTION
Select the convention used to encode NDN name components. The available choices are:
* ``marker`` (shorthand: ``m`` or ``1``) for the old marker-based encoding;
* ``typed`` (shorthand: ``t`` or ``2``) for the new encoding based on typed name components.
If this option is not specified, the ndn-cxx library's default is used.
.. option:: -S, --signing-info STRING
Specify the parameters used to sign the Data packets. If omitted, the default key
of the default identity is used. The general syntax is ``<scheme>:<name>``. The
most common supported combinations are as follows:
* Sign with the default certificate of the default key of an identity: ``id:/<my-identity>``.
* Sign with the default certificate of a specific key: ``key:/<my-identity>/ksk-1``.
* Sign with a specific certificate: ``cert:/<my-identity>/KEY/ksk-1/ID-CERT/v=1``.
* Sign with a SHA-256 digest: ``id:/localhost/identity/digest-sha256``. Note that this
is only a hash function, not a real signature, but it can significantly speed up
packet signing operations.
.. option:: -p, --print-data-version
Print version of the published Data to the standard output.
.. option:: -q, --quiet
Turn off all non-error output.
.. option:: -v, --verbose
Produce verbose output.
.. option:: -V, --version
Print program version and exit.
Examples
--------
The following command will publish the text of the GPL-3 license under the ``/localhost/demo/gpl3``
prefix::
ndnputchunks /localhost/demo/gpl3 < /usr/share/common-licenses/GPL-3
To see the published version, you can run the program with the **-p** option::
ndnputchunks -p /localhost/demo/gpl3 < /usr/share/common-licenses/GPL-3
This command will print the published version to the standard output.
To publish Data with a specific version, you must append a version component to the end of the
prefix. The version component must follow the aforementioned NDN naming conventions.
For example, the following command will publish version 1615519151142 of ``/localhost/demo/gpl3``
using the "typed" naming convention::
ndnputchunks -Nt /localhost/demo/gpl3/v=1615519151142 < /usr/share/common-licenses/GPL-3
See Also
--------
.. target-notes::
-10
View File
@@ -1,10 +0,0 @@
def build(bld):
if not bld.env['SPHINX_BUILD']:
return
bld(features='sphinx',
builder='man',
outdir='.',
config='./conf.py',
source=bld.path.ant_glob('*.rst'),
install_path='${MANDIR}/',
VERSION=bld.env['VERSION'])
+65
View File
@@ -0,0 +1,65 @@
# Copyright (c) 2015-2019, 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 ndn-tools (Named Data Networking Essential Tools).
# See AUTHORS.md for complete list of ndn-tools authors and contributors.
#
# ndn-tools 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.
#
# ndn-tools 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
# ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
[Unit]
Description=NDN Ping Server
Documentation=man:ndnpingserver(1)
BindsTo=nfd.service
After=nfd.service
[Service]
Environment=HOME=%S/ndn/ndnping
EnvironmentFile=-@SYSCONFDIR@/default/ndnping
ExecStart=@BINDIR@/ndnpingserver ${PREFIX} $FLAGS
Restart=on-failure
RestartPreventExitStatus=2
User=ndn
CapabilityBoundingSet=
LockPersonality=yes
MemoryDenyWriteExecute=yes
NoNewPrivileges=yes
PrivateDevices=yes
PrivateNetwork=yes
PrivateTmp=yes
PrivateUsers=yes
ProtectControlGroups=yes
ProtectHome=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
# systemd older than v232 doesn't support a value of "strict" for ProtectSystem,
# so it will ignore that line and use ProtectSystem=full; with newer systemd,
# the latter assignment is recognized and takes precedence, resulting in an
# effective setting of ProtectSystem=strict
ProtectSystem=full
ProtectSystem=strict
RestrictAddressFamilies=AF_UNIX
RestrictNamespaces=yes
RestrictRealtime=yes
StateDirectory=ndn/ndnping
SystemCallArchitectures=native
SystemCallErrorNumber=EPERM
SystemCallFilter=~@aio @chown @clock @cpu-emulation @debug @keyring @module @mount @obsolete @privileged @raw-io @reboot @resources @setuid @swap
[Install]
WantedBy=multi-user.target
WantedBy=nfd.service
+12 -9
View File
@@ -1,23 +1,26 @@
ndn-tool unit tests
===================
# ndn-tools unit tests
## Assumptions
Unit tests for a tool `foo` should be placed in the folder `foo` and build script for the tool
should define `foo-objects` that includes all object files for the tool, except object files
defining main function.
Unit tests for a tool `foo` should be placed in the folder `foo` and the build script
for the tool should define `foo-objects` that includes all object files for that tool,
except the object that contains the `main()` function.
For example,
For example:
bld(features='cxx',
name='tool-subtool-objects',
```python
def build(bld):
bld.objects(
target='tool-subtool-objects',
source=bld.path.ant_glob('subtool/*.cpp', excl='subtool/main.cpp'),
use='core-objects')
bld(features='cxx cxxprogram',
bld.program(
name='subtool',
target='../../bin/subtool',
source='subtool/main.cpp',
use='tool-subtool-objects')
bld(name='tool-objects',
use='tool-subtool-objects')
```
+3 -4
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
/*
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -30,8 +30,7 @@
#pragma GCC system_header
#pragma clang system_header
#include <boost/concept_check.hpp>
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include <boost/test/output_test_stream.hpp>
#endif // NDN_TOOLS_TESTS_BOOST_TEST_HPP
+172
View File
@@ -0,0 +1,172 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016-2023, Regents of the University of California,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Andrea Tosatto
*/
#include "tools/chunks/catchunks/consumer.hpp"
#include "tools/chunks/catchunks/discover-version.hpp"
#include "tools/chunks/catchunks/pipeline-interests.hpp"
#include "tests/test-common.hpp"
#include "tests/io-fixture.hpp"
#include <ndn-cxx/security/validator-null.hpp>
#include <ndn-cxx/util/dummy-client-face.hpp>
#include <boost/test/tools/output_test_stream.hpp>
namespace ndn::chunks::tests {
using namespace ndn::tests;
using boost::test_tools::output_test_stream;
BOOST_AUTO_TEST_SUITE(Chunks)
BOOST_AUTO_TEST_SUITE(TestConsumer)
BOOST_AUTO_TEST_CASE(InOrderData)
{
// Segment order: 0 1 2 3
const std::string name("/ndn/chunks/test");
const std::vector<std::string> testStrings {
"",
"a1b2c3%^&(#$&%^$$/><",
"123456789123456789123456789123456789123456789123456789123456789"
"123456789123456789123456789123456789123456789123456789123456789",
"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. "
"Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur "
"ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla "
"consequat massa Donec pede justo,"
};
DummyClientFace face;
output_test_stream output("");
Consumer cons(security::getAcceptAllValidator(), output);
auto interest = makeInterest(name, true);
for (size_t i = 0; i < testStrings.size(); ++i) {
output.flush();
auto data = makeData(Name(name).appendVersion(1).appendSegment(i));
data->setContent(make_span(reinterpret_cast<const uint8_t*>(testStrings[i].data()),
testStrings[i].size()));
cons.m_bufferedData[i] = data;
cons.writeInOrderData();
BOOST_CHECK(output.is_equal(testStrings[i]));
}
}
BOOST_AUTO_TEST_CASE(OutOfOrderData)
{
// Segment order: 1 0 2
const std::string name("/ndn/chunks/test");
const std::vector<std::string> testStrings {
"a1b2c3%^&(#$&%^$$/><",
"123456789123456789123456789123456789123456789123456789123456789"
"123456789123456789123456789123456789123456789123456789123456789",
"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. "
"Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur "
"ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla "
"consequat massa Donec pede justo,"
};
DummyClientFace face;
output_test_stream output("");
Consumer cons(security::getAcceptAllValidator(), output);
auto interest = makeInterest(name, true);
std::vector<shared_ptr<Data>> dataStore;
for (size_t i = 0; i < testStrings.size(); ++i) {
auto data = makeData(Name(name).appendVersion(1).appendSegment(i));
data->setContent(make_span(reinterpret_cast<const uint8_t*>(testStrings[i].data()),
testStrings[i].size()));
dataStore.push_back(data);
}
output.flush();
cons.m_bufferedData[1] = dataStore[1];
cons.writeInOrderData();
BOOST_CHECK(output.is_equal(""));
output.flush();
cons.m_bufferedData[0] = dataStore[0];
cons.writeInOrderData();
BOOST_CHECK(output.is_equal(testStrings[0] + testStrings[1]));
output.flush();
cons.m_bufferedData[2] = dataStore[2];
cons.writeInOrderData();
BOOST_CHECK(output.is_equal(testStrings[2]));
}
class PipelineInterestsDummy final : public PipelineInterests
{
public:
using PipelineInterests::PipelineInterests;
private:
void
doRun() final
{
isPipelineRunning = true;
}
void
doCancel() final
{
}
public:
bool isPipelineRunning = false;
};
BOOST_FIXTURE_TEST_CASE(RunBasic, IoFixture)
{
DummyClientFace face(m_io);
Options options;
Consumer consumer(security::getAcceptAllValidator());
Name prefix = Name("/ndn/chunks/test").appendVersion(1);
auto discover = make_unique<DiscoverVersion>(face, prefix, options);
auto pipeline = make_unique<PipelineInterestsDummy>(face, options);
auto pipelinePtr = pipeline.get();
BOOST_CHECK_EQUAL(pipelinePtr->isPipelineRunning, false);
consumer.run(std::move(discover), std::move(pipeline));
this->advanceClocks(1_ms);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 0); // no discovery Interests are issued
BOOST_CHECK_EQUAL(pipelinePtr->isPipelineRunning, true);
}
BOOST_AUTO_TEST_SUITE_END() // TestConsumer
BOOST_AUTO_TEST_SUITE_END() // Chunks
} // namespace ndn::chunks::tests
+216
View File
@@ -0,0 +1,216 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016-2023, Regents of the University of California,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Chavoosh Ghasemi
*/
#include "tools/chunks/catchunks/discover-version.hpp"
#include "tests/test-common.hpp"
#include "tests/io-fixture.hpp"
#include "tests/key-chain-fixture.hpp"
#include <ndn-cxx/metadata-object.hpp>
#include <ndn-cxx/util/dummy-client-face.hpp>
namespace ndn::chunks::tests {
using namespace ndn::tests;
class DiscoverVersionFixture : public IoFixture, public KeyChainFixture
{
public:
void
run(const Name& prefix)
{
discover = make_unique<DiscoverVersion>(face, prefix, opt);
discover->onDiscoverySuccess.connect([this] (const Name& versionedName) {
isDiscoveryFinished = true;
discoveredName = versionedName;
if (!versionedName.empty() && versionedName[-1].isVersion())
discoveredVersion = versionedName[-1].toVersion();
});
discover->onDiscoveryFailure.connect([this] (const std::string&) {
isDiscoveryFinished = true;
});
discover->run();
advanceClocks(1_ns);
}
protected:
const Name name = "/ndn/chunks/test";
const uint64_t version = 1449227841747;
DummyClientFace face{m_io};
Options opt;
unique_ptr<DiscoverVersion> discover;
std::optional<Name> discoveredName;
std::optional<uint64_t> discoveredVersion;
bool isDiscoveryFinished = false;
};
BOOST_AUTO_TEST_SUITE(Chunks)
BOOST_FIXTURE_TEST_SUITE(TestDiscoverVersion, DiscoverVersionFixture)
BOOST_AUTO_TEST_CASE(Disabled)
{
opt.disableVersionDiscovery = true;
run(name);
// no version discovery Interest is expressed
BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
BOOST_CHECK_EQUAL(discoveredName.value(), name);
BOOST_CHECK_EQUAL(discoveredVersion.has_value(), false);
}
BOOST_AUTO_TEST_CASE(NameWithVersion)
{
// start with a name that already contains a version component
Name versionedName = Name(name).appendVersion(version);
run(versionedName);
// no version discovery Interest is expressed
BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
BOOST_CHECK_EQUAL(discoveredName.value(), versionedName);
BOOST_CHECK_EQUAL(discoveredVersion.value(), version);
}
BOOST_AUTO_TEST_CASE(Success)
{
run(name);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
Interest discoveryInterest = MetadataObject::makeDiscoveryInterest(name);
auto lastInterest = face.sentInterests.back();
BOOST_CHECK_EQUAL(lastInterest.getName(), discoveryInterest.getName());
// send back a metadata packet with a valid versioned name
MetadataObject mobject;
mobject.setVersionedName(Name(name).appendVersion(version));
face.receive(mobject.makeData(lastInterest.getName(), m_keyChain));
advanceClocks(1_ns);
BOOST_CHECK_EQUAL(discoveredVersion.value(), version);
}
BOOST_AUTO_TEST_CASE(InvalidDiscoveredVersionedName)
{
run(name);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
// send back a metadata packet with an invalid versioned name
MetadataObject mobject;
mobject.setVersionedName(name);
face.receive(mobject.makeData(face.sentInterests.back().getName(), m_keyChain));
// finish discovery process without a resolved version number
BOOST_CHECK_EQUAL(isDiscoveryFinished, true);
BOOST_CHECK_EQUAL(discoveredName.has_value(), false);
BOOST_CHECK_EQUAL(discoveredVersion.has_value(), false);
}
BOOST_AUTO_TEST_CASE(InvalidMetadataPacket)
{
run(name);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
// send back an invalid metadata packet
Data data(face.sentInterests.back().getName());
data.setFreshnessPeriod(1_s);
data.setContentType(tlv::ContentType_Key);
face.receive(signData(data));
// finish discovery process without a resolved version number
BOOST_CHECK_EQUAL(isDiscoveryFinished, true);
BOOST_CHECK_EQUAL(discoveredName.has_value(), false);
BOOST_CHECK_EQUAL(discoveredVersion.has_value(), false);
}
BOOST_AUTO_TEST_CASE(MaxRetriesExceeded)
{
opt.maxRetriesOnTimeoutOrNack = 3;
run(name);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
// timeout or nack discovery Interests
for (int retries = 0; retries < opt.maxRetriesOnTimeoutOrNack * 2; ++retries) {
if (retries % 2 == 0) {
advanceClocks(opt.interestLifetime);
}
else {
face.receive(makeNack(face.sentInterests.back(), lp::NackReason::DUPLICATE));
advanceClocks(1_ns);
}
BOOST_CHECK_EQUAL(isDiscoveryFinished, false);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), retries + 2);
}
// timeout the last sent Interest
advanceClocks(opt.interestLifetime);
// finish discovery process without a resolved version number
BOOST_CHECK_EQUAL(isDiscoveryFinished, true);
BOOST_CHECK_EQUAL(discoveredName.has_value(), false);
BOOST_CHECK_EQUAL(discoveredVersion.has_value(), false);
}
BOOST_AUTO_TEST_CASE(SuccessAfterNackAndTimeout)
{
opt.maxRetriesOnTimeoutOrNack = 3;
run(name);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
// timeout or nack discovery Interests
for (int retries = 0; retries < opt.maxRetriesOnTimeoutOrNack * 2; ++retries) {
if (retries % 2 == 0) {
advanceClocks(opt.interestLifetime);
}
else {
face.receive(makeNack(face.sentInterests.back(), lp::NackReason::DUPLICATE));
advanceClocks(1_ns);
}
BOOST_CHECK_EQUAL(isDiscoveryFinished, false);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), retries + 2);
}
// satisfy the last Interest with a valid metadata packet
MetadataObject mobject;
mobject.setVersionedName(Name(name).appendVersion(version));
face.receive(mobject.makeData(face.sentInterests.back().getName(), m_keyChain));
advanceClocks(1_ns);
BOOST_CHECK_EQUAL(discoveredVersion.value(), version);
}
BOOST_AUTO_TEST_SUITE_END() // TestDiscoverVersion
BOOST_AUTO_TEST_SUITE_END() // Chunks
} // namespace ndn::chunks::tests
+643
View File
@@ -0,0 +1,643 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016-2022, Regents of the University of California,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Weiwei Liu
* @author Chavoosh Ghasemi
* @author Klaus Schneider
*/
#include "tools/chunks/catchunks/pipeline-interests-aimd.hpp"
#include "pipeline-interests-fixture.hpp"
namespace ndn::chunks::tests {
using namespace ndn::tests;
class PipelineInterestAimdFixture : public PipelineInterestsFixture
{
protected:
PipelineInterestAimdFixture()
{
opt.isQuiet = true;
createPipeline();
}
void
createPipeline()
{
auto pline = make_unique<PipelineInterestsAimd>(face, rttEstimator, opt);
pipeline = pline.get();
setPipeline(std::move(pline));
}
private:
static shared_ptr<RttEstimatorWithStats::Options>
makeRttEstimatorOptions()
{
auto rttOptions = make_shared<RttEstimatorWithStats::Options>();
rttOptions->alpha = 0.125;
rttOptions->beta = 0.25;
rttOptions->k = 4;
rttOptions->initialRto = 1_s;
rttOptions->minRto = 200_ms;
rttOptions->maxRto = 4_s;
rttOptions->rtoBackoffMultiplier = 2;
return rttOptions;
}
protected:
Options opt;
RttEstimatorWithStats rttEstimator{makeRttEstimatorOptions()};
PipelineInterestsAdaptive* pipeline;
static constexpr double MARGIN = 0.001;
};
BOOST_AUTO_TEST_SUITE(Chunks)
BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsAimd, PipelineInterestAimdFixture)
BOOST_AUTO_TEST_CASE(SlowStart)
{
nDataSegments = 4;
pipeline->m_ssthresh = 8.0;
BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
double preCwnd = pipeline->m_cwnd;
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
for (uint64_t i = 0; i < nDataSegments - 1; ++i) {
face.receive(*makeDataWithSegment(i));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_CLOSE(pipeline->m_cwnd - preCwnd, 1, MARGIN);
preCwnd = pipeline->m_cwnd;
}
BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments - 1);
}
BOOST_AUTO_TEST_CASE(CongestionAvoidance)
{
nDataSegments = 7;
pipeline->m_ssthresh = 4.0;
BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
double preCwnd = pipeline->m_cwnd;
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
for (uint64_t i = 0; i < pipeline->m_ssthresh; ++i) { // slow start
face.receive(*makeDataWithSegment(i));
advanceClocks(time::nanoseconds(1));
preCwnd = pipeline->m_cwnd;
}
BOOST_CHECK_CLOSE(preCwnd, 4.5, MARGIN);
for (uint64_t i = pipeline->m_ssthresh; i < nDataSegments - 1; ++i) { // congestion avoidance
face.receive(*makeDataWithSegment(i));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_CLOSE(pipeline->m_cwnd - preCwnd, opt.aiStep / floor(preCwnd), MARGIN);
preCwnd = pipeline->m_cwnd;
}
BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments -1);
}
BOOST_AUTO_TEST_CASE(Timeout)
{
nDataSegments = 8;
pipeline->m_ssthresh = 4.0;
BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
// receive segment 0, 1, and 2
for (uint64_t i = 0; i < 3; ++i) {
face.receive(*makeDataWithSegment(i));
advanceClocks(time::nanoseconds(1));
}
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 3);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.25, MARGIN);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 7); // request for segment 7 has been sent
advanceClocks(time::milliseconds(100));
// receive segment 4
face.receive(*makeDataWithSegment(4));
advanceClocks(time::nanoseconds(1));
// receive segment 5
face.receive(*makeDataWithSegment(5));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.75, MARGIN);
BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all the segment requests have been sent
BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 0);
BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 0);
BOOST_CHECK_EQUAL(pipeline->m_nMarkDecr, 0);
BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 0);
BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 0);
// timeout segment 3 & 6
advanceClocks(time::milliseconds(150));
BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 2);
BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 1);
BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 1);
BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.375, MARGIN); // window size drop to 1/2 of previous size
BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 1);
// receive segment 6, retransmit 3
face.receive(*makeDataWithSegment(6));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.875, MARGIN); // congestion avoidance
BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 2);
BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 2);
BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, pipeline->m_nRetransmitted + pipeline->m_nSkippedRetx);
}
BOOST_AUTO_TEST_CASE(CongestionMarksWithCwa)
{
nDataSegments = 7;
pipeline->m_ssthresh = 4.0;
BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
// receive segments 0 to 4
for (uint64_t i = 0; i < 5; ++i) {
face.receive(*makeDataWithSegment(i));
advanceClocks(time::nanoseconds(1));
}
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.75, MARGIN);
// receive segment 5 with congestion mark
face.receive(*makeDataWithSegmentAndCongMark(5));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.375, MARGIN); // window size drops to 1/2 of previous size
BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
// receive the last segment with congestion mark
face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.375, MARGIN); // conservative window adaption (window size should not decrease)
BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
// make sure no interest is retransmitted for marked data packets
BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
// check number of received marked data packets
BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
}
BOOST_AUTO_TEST_CASE(CongestionMarksWithoutCwa)
{
opt.disableCwa = true;
createPipeline();
nDataSegments = 7;
pipeline->m_ssthresh = 4.0;
BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
// receive segments 0 to 4
for (uint64_t i = 0; i < 5; ++i) {
face.receive(*makeDataWithSegment(i));
advanceClocks(time::nanoseconds(1));
}
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.75, MARGIN);
// receive segment 5 with congestion mark
face.receive(*makeDataWithSegmentAndCongMark(5));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.375, MARGIN); // window size drops to 1/2 of previous size
BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
// receive the last segment with congestion mark
face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, PipelineInterestsAdaptive::MIN_SSTHRESH,
MARGIN); // window size should decrease, as cwa is disabled
BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
// make sure no interest is retransmitted for marked data packets
BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
// check number of received marked data packets
BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
}
BOOST_AUTO_TEST_CASE(IgnoreCongestionMarks)
{
opt.ignoreCongMarks = true;
createPipeline();
nDataSegments = 7;
pipeline->m_ssthresh = 4.0;
BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
// receive segments 0 to 5
for (uint64_t i = 0; i < 6; ++i) {
face.receive(*makeDataWithSegment(i));
advanceClocks(time::nanoseconds(1));
}
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 5.0, MARGIN);
BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
// receive the last segment with congestion mark
face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 5.2, MARGIN); // window size increases
BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
// make sure no interest is retransmitted for marked data packet
BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
// check number of received marked data packets
BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 1);
}
BOOST_AUTO_TEST_CASE(Nack)
{
nDataSegments = 5;
pipeline->m_cwnd = 10.0;
run(name);
advanceClocks(time::nanoseconds(1));
face.receive(*makeDataWithSegment(0));
advanceClocks(time::nanoseconds(1));
face.receive(*makeDataWithSegment(1));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 10);
// receive a nack with NackReason::DUPLICATE for segment 1
auto nack1 = makeNack(face.sentInterests[1], lp::NackReason::DUPLICATE);
face.receive(nack1);
advanceClocks(time::nanoseconds(1));
// nack1 is ignored
BOOST_CHECK_EQUAL(hasFailed, false);
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
// receive a nack with NackReason::CONGESTION for segment 2
auto nack2 = makeNack(face.sentInterests[2], lp::NackReason::CONGESTION);
face.receive(nack2);
advanceClocks(time::nanoseconds(1));
// segment 2 is retransmitted
BOOST_CHECK_EQUAL(pipeline->m_retxCount[2], 1);
// receive a nack with NackReason::NONE for segment 3
auto nack3 = makeNack(face.sentInterests[3], lp::NackReason::NONE);
face.receive(nack3);
advanceClocks(time::nanoseconds(1));
// Other types of Nack will trigger a failure
BOOST_CHECK_EQUAL(hasFailed, true);
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
}
BOOST_AUTO_TEST_CASE(FinalBlockIdNotSetAtBeginning)
{
nDataSegments = 4;
pipeline->m_cwnd = 4;
run(name);
advanceClocks(time::nanoseconds(1));
// receive segment 0 without FinalBlockId
face.receive(*makeDataWithSegment(0, false));
advanceClocks(time::nanoseconds(1));
// interests for segment 0 - 5 have been sent
BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 1);
BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, false);
// pending interests: segment 1, 2, 3, 4, 5
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 5);
// receive segment 1 with FinalBlockId
face.receive(*makeDataWithSegment(1));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
// pending interests for segment 1, 4, 5 haven been removed
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
}
BOOST_AUTO_TEST_CASE(FailureBeforeFinalBlockIdReceived)
{
// failed to retrieve segNo while the FinalBlockId has not yet been
// set, and later received a FinalBlockId >= segNo, i.e. segNo is
// part of the content.
nDataSegments = 4;
pipeline->m_cwnd = 4;
run(name);
advanceClocks(time::nanoseconds(1));
// receive segment 0 without FinalBlockId
face.receive(*makeDataWithSegment(0, false));
advanceClocks(time::nanoseconds(1));
// receive segment 1 without FinalBlockId
face.receive(*makeDataWithSegment(1, false));
advanceClocks(time::nanoseconds(1));
// interests for segment 0 - 7 have been sent
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
// receive nack with NackReason::NONE for segment 3
auto nack = makeNack(face.sentInterests[3], lp::NackReason::NONE);
face.receive(nack);
advanceClocks(time::nanoseconds(1));
// error not triggered
// pending interests for segment > 3 haven been removed
BOOST_CHECK_EQUAL(hasFailed, false);
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 1);
// receive segment 2 with FinalBlockId
face.receive(*makeDataWithSegment(2));
advanceClocks(time::nanoseconds(1));
// error triggered since segment 3 is part of the content
BOOST_CHECK_EQUAL(hasFailed, true);
}
BOOST_AUTO_TEST_CASE(SpuriousFailureBeforeFinalBlockIdReceived)
{
// failed to retrieve segNo while the FinalBlockId has not yet been
// set, and later received a FinalBlockId < segNo, i.e. segNo is
// not part of the content, and it was actually a spurious failure
nDataSegments = 4;
pipeline->m_cwnd = 4;
run(name);
advanceClocks(time::nanoseconds(1));
// receive segment 0 without FinalBlockId
face.receive(*makeDataWithSegment(0, false));
advanceClocks(time::nanoseconds(1));
// receive segment 1 without FinalBlockId
face.receive(*makeDataWithSegment(1, false));
advanceClocks(time::nanoseconds(1));
// interests for segment 0 - 7 have been sent
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
// receive nack with NackReason::NONE for segment 4
auto nack = makeNack(face.sentInterests[4], lp::NackReason::NONE);
face.receive(nack);
advanceClocks(time::nanoseconds(1));
// error not triggered
// pending interests for segment > 3 have been removed
BOOST_CHECK_EQUAL(hasFailed, false);
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
// receive segment 2 with FinalBlockId
face.receive(*makeDataWithSegment(2));
advanceClocks(time::nanoseconds(1));
// timeout segment 3
advanceClocks(time::seconds(1));
// segment 3 is retransmitted
BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
// receive segment 3
face.receive(*makeDataWithSegment(3));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(hasFailed, false);
}
BOOST_AUTO_TEST_CASE(SegmentInfoMaintenance)
{
// test that m_segmentInfo is properly maintained when
// a segment is received after two consecutive timeouts
nDataSegments = 3;
run(name);
advanceClocks(time::nanoseconds(1));
// receive segment 0
face.receive(*makeDataWithSegment(0));
advanceClocks(time::nanoseconds(1));
// receive segment 1
face.receive(*makeDataWithSegment(1));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
// check if segment 2's state is FirstTimeSent
auto it = pipeline->m_segmentInfo.find(2);
BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
BOOST_CHECK(it->second.state == SegmentState::FirstTimeSent);
// timeout segment 2 twice
advanceClocks(time::milliseconds(400), 3);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
// check if segment 2's state is Retransmitted
it = pipeline->m_segmentInfo.find(2);
BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
BOOST_CHECK(it->second.state == SegmentState::Retransmitted);
// check if segment 2 was retransmitted twice
BOOST_CHECK_EQUAL(pipeline->m_retxCount.at(2), 2);
// receive segment 2 the first time
face.receive(*makeDataWithSegment(2));
advanceClocks(time::nanoseconds(1));
// check if segment 2 was erased from m_segmentInfo
it = pipeline->m_segmentInfo.find(2);
BOOST_CHECK(it == pipeline->m_segmentInfo.end());
auto prevRtt = rttEstimator.getAvgRtt();
auto prevRto = rttEstimator.getEstimatedRto();
// receive segment 2 the second time
face.receive(*makeDataWithSegment(2));
advanceClocks(time::nanoseconds(1));
// nothing changed
it = pipeline->m_segmentInfo.find(2);
BOOST_CHECK(it == pipeline->m_segmentInfo.end());
BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
BOOST_CHECK_EQUAL(rttEstimator.getAvgRtt(), prevRtt);
BOOST_CHECK_EQUAL(rttEstimator.getEstimatedRto(), prevRto);
}
BOOST_AUTO_TEST_CASE(Bug5202)
{
// If an interest is pending during a window decrease, it should not trigger
// another window decrease when it times out.
// This test emulates a network where RTT = 20ms and transmission time = 1ms.
// adding small sample to RTT estimator. This should set rto = 200ms
rttEstimator.addMeasurement(time::nanoseconds(1));
BOOST_REQUIRE_EQUAL(rttEstimator.getEstimatedRto(), time::milliseconds(200));
nDataSegments = 300;
pipeline->m_ssthresh = 0;
pipeline->m_cwnd = 20;
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(face.sentInterests.size(), 20);
advanceClocks(time::milliseconds(20));
// Segment 1 is lost. Receive segment 0 and 2-99
face.receive(*makeDataWithSegment(0));
advanceClocks(time::milliseconds(1));
for (uint64_t i = 2; i <= 99; ++i) {
face.receive(*makeDataWithSegment(i));
advanceClocks(time::milliseconds(1));
}
// Segment 100 is lost. Receive segment 100 to 181
for (uint64_t i = 101; i <= 181; ++i) {
face.receive(*makeDataWithSegment(i));
advanceClocks(time::milliseconds(1));
}
// 200ms passed after sending segment 1, check for timeout
BOOST_CHECK_GT(pipeline->m_cwnd, 27./2);
BOOST_CHECK_LT(pipeline->m_cwnd, 28./2);
BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 1);
BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 1);
// Receive segment 182 to 300
for (uint64_t i = 182; i <= 300; ++i) {
face.receive(*makeDataWithSegment(i));
advanceClocks(time::milliseconds(1));
}
// The second packet should timeout now
BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 2);
// This timeout should NOT trigger another window decrease
BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 1);
}
BOOST_AUTO_TEST_CASE(PrintSummaryWithNoRttMeasurements)
{
// test the console ouptut when no RTT measurement is available,
// to make sure a proper message will be printed out
std::stringstream ss;
// change the underlying buffer and save the old buffer
auto oldBuf = std::cerr.rdbuf(ss.rdbuf());
pipeline->printSummary();
std::string line;
bool found = false;
while (std::getline(ss, line)) {
if (line == "RTT stats unavailable") {
found = true;
break;
}
}
BOOST_CHECK(found);
std::cerr.rdbuf(oldBuf); // reset
}
BOOST_AUTO_TEST_CASE(StopsWhenFileSizeLessThanChunkSize)
{
// test to see if the program doesn't hang,
// when transfer is complete, for files less than the chunk size
// (i.e. when only one segment is sent/received)
createPipeline();
nDataSegments = 1;
run(name);
advanceClocks(time::nanoseconds(1));
face.receive(*makeDataWithSegment(0));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
BOOST_CHECK_EQUAL(pipeline->m_segmentInfo.size(), 0);
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
}
BOOST_AUTO_TEST_SUITE_END() // TestPipelineInterestsAimd
BOOST_AUTO_TEST_SUITE_END() // Chunks
} // namespace ndn::chunks::tests
+560
View File
@@ -0,0 +1,560 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016-2022, Regents of the University of California,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Weiwei Liu
* @author Chavoosh Ghasemi
* @author Klaus Schneider
*/
#include "tools/chunks/catchunks/pipeline-interests-cubic.hpp"
#include "pipeline-interests-fixture.hpp"
namespace ndn::chunks::tests {
using namespace ndn::tests;
class PipelineInterestCubicFixture : public PipelineInterestsFixture
{
protected:
PipelineInterestCubicFixture()
{
opt.isQuiet = true;
createPipeline();
}
void
createPipeline()
{
auto pline = make_unique<PipelineInterestsCubic>(face, rttEstimator, opt);
pipeline = pline.get();
setPipeline(std::move(pline));
}
private:
static shared_ptr<RttEstimatorWithStats::Options>
makeRttEstimatorOptions()
{
auto rttOptions = make_shared<RttEstimatorWithStats::Options>();
rttOptions->alpha = 0.125;
rttOptions->beta = 0.25;
rttOptions->k = 8;
rttOptions->initialRto = 1_s;
rttOptions->minRto = 200_ms;
rttOptions->maxRto = 4_s;
rttOptions->rtoBackoffMultiplier = 2;
return rttOptions;
}
protected:
Options opt;
RttEstimatorWithStats rttEstimator{makeRttEstimatorOptions()};
PipelineInterestsCubic* pipeline;
static constexpr double MARGIN = 0.001;
};
BOOST_AUTO_TEST_SUITE(Chunks)
BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsCubic, PipelineInterestCubicFixture)
BOOST_AUTO_TEST_CASE(SlowStart)
{
nDataSegments = 4;
BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
double preCwnd = pipeline->m_cwnd;
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
for (uint64_t i = 0; i < nDataSegments - 1; ++i) {
face.receive(*makeDataWithSegment(i));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_CLOSE(pipeline->m_cwnd - preCwnd, 1, MARGIN);
preCwnd = pipeline->m_cwnd;
}
BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments - 1);
}
BOOST_AUTO_TEST_CASE(Timeout)
{
nDataSegments = 8;
BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
// receive segment 0, 1, and 2
for (uint64_t i = 0; i < 3; ++i) {
face.receive(*makeDataWithSegment(i));
advanceClocks(time::nanoseconds(1));
}
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 3);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 5, MARGIN);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 8); // request for segment #7 has been sent
advanceClocks(time::milliseconds(100));
// receive segment 4
face.receive(*makeDataWithSegment(4));
advanceClocks(time::nanoseconds(1));
// receive segment 5
face.receive(*makeDataWithSegment(5));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 7.0, MARGIN);
BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all the segment requests have been sent
BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 0);
BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 0);
BOOST_CHECK_EQUAL(pipeline->m_nMarkDecr, 0);
BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 0);
BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 0);
// timeout segment 3 & 6
advanceClocks(time::milliseconds(150));
BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 3);
BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 3);
BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 1);
BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.9, MARGIN); // window size drop to 0.7x of previous size
BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
// receive segment 6, retransmit 3
face.receive(*makeDataWithSegment(6));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.9, MARGIN); // congestion avoidance
BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 3);
BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 3);
BOOST_CHECK_EQUAL(pipeline->m_nTimeouts,
pipeline->m_nRetransmitted + pipeline->m_nSkippedRetx);
}
BOOST_AUTO_TEST_CASE(CongestionMarksWithCwa)
{
nDataSegments = 7;
BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
// receive segments 0 to 4
for (uint64_t i = 0; i < 5; ++i) {
face.receive(*makeDataWithSegment(i));
advanceClocks(time::nanoseconds(1));
}
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 7.0, MARGIN);
// receive segment 5 with congestion mark
face.receive(*makeDataWithSegmentAndCongMark(5));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.9, MARGIN); // window size drops to 0.7x of previous size
BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
// receive the last segment with congestion mark
face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.9, MARGIN); // conservative window adaption (window size should not decrease)
BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
// make sure no interest is retransmitted for marked data packets
BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
// check number of received marked data packets
BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
}
BOOST_AUTO_TEST_CASE(CongestionMarksWithoutCwa)
{
opt.disableCwa = true;
createPipeline();
nDataSegments = 7;
BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
// receive segments 0 to 4
for (uint64_t i = 0; i < 5; ++i) {
face.receive(*makeDataWithSegment(i));
advanceClocks(time::nanoseconds(1));
}
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 7.0, MARGIN);
// receive segment 5 with congestion mark
face.receive(*makeDataWithSegmentAndCongMark(5));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.9, MARGIN); // window size drops to 0.7x of previous size
BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
// receive the last segment with congestion mark
face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 3.43, MARGIN); // window size should decrease, as cwa is disabled
BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
// make sure no interest is retransmitted for marked data packets
BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
// check number of received marked data packets
BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
}
BOOST_AUTO_TEST_CASE(IgnoreCongestionMarks)
{
opt.ignoreCongMarks = true;
createPipeline();
nDataSegments = 7;
BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
// receive segments 0 to 5
for (uint64_t i = 0; i < 6; ++i) {
face.receive(*makeDataWithSegment(i));
advanceClocks(time::nanoseconds(1));
}
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 8.0, MARGIN);
BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
// receive the last segment with congestion mark
face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
BOOST_CHECK_CLOSE(pipeline->m_cwnd, 9.0, MARGIN); // window size increases
BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
// make sure no interest is retransmitted for marked data packet
BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
// check number of received marked data packets
BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 1);
}
BOOST_AUTO_TEST_CASE(Nack)
{
nDataSegments = 5;
pipeline->m_cwnd = 10.0;
run(name);
advanceClocks(time::nanoseconds(1));
face.receive(*makeDataWithSegment(0));
advanceClocks(time::nanoseconds(1));
face.receive(*makeDataWithSegment(1));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 10);
// receive a nack with NackReason::DUPLICATE for segment 1
auto nack1 = makeNack(face.sentInterests[1], lp::NackReason::DUPLICATE);
face.receive(nack1);
advanceClocks(time::nanoseconds(1));
// nack1 is ignored
BOOST_CHECK_EQUAL(hasFailed, false);
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
// receive a nack with NackReason::CONGESTION for segment 2
auto nack2 = makeNack(face.sentInterests[2], lp::NackReason::CONGESTION);
face.receive(nack2);
advanceClocks(time::nanoseconds(1));
// segment 2 is retransmitted
BOOST_CHECK_EQUAL(pipeline->m_retxCount[2], 1);
// receive a nack with NackReason::NONE for segment 3
auto nack3 = makeNack(face.sentInterests[3], lp::NackReason::NONE);
face.receive(nack3);
advanceClocks(time::nanoseconds(1));
// Other types of Nack will trigger a failure
BOOST_CHECK_EQUAL(hasFailed, true);
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
}
BOOST_AUTO_TEST_CASE(FinalBlockIdNotSetAtBeginning)
{
nDataSegments = 4;
pipeline->m_cwnd = 4;
run(name);
advanceClocks(time::nanoseconds(1));
// receive segment 0 without FinalBlockId
face.receive(*makeDataWithSegment(0, false));
advanceClocks(time::nanoseconds(1));
// interests for segment 0 - 5 have been sent
BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 1);
BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, false);
// pending interests: segment 1, 2, 3, 4, 5
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 5);
// receive segment 1 with FinalBlockId
face.receive(*makeDataWithSegment(1));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
// pending interests for segment 1, 4, 5 haven been removed
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
}
BOOST_AUTO_TEST_CASE(FailureBeforeFinalBlockIdReceived)
{
// failed to retrieve segNo while the FinalBlockId has not yet been
// set, and later received a FinalBlockId >= segNo, i.e. segNo is
// part of the content.
nDataSegments = 4;
pipeline->m_cwnd = 4;
run(name);
advanceClocks(time::nanoseconds(1));
// receive segment 0 without FinalBlockId
face.receive(*makeDataWithSegment(0, false));
advanceClocks(time::nanoseconds(1));
// receive segment 1 without FinalBlockId
face.receive(*makeDataWithSegment(1, false));
advanceClocks(time::nanoseconds(1));
// interests for segment 0 - 7 have been sent
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
// receive nack with NackReason::NONE for segment 3
auto nack = makeNack(face.sentInterests[3], lp::NackReason::NONE);
face.receive(nack);
advanceClocks(time::nanoseconds(1));
// error not triggered
// pending interests for segment > 3 haven been removed
BOOST_CHECK_EQUAL(hasFailed, false);
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 1);
// receive segment 2 with FinalBlockId
face.receive(*makeDataWithSegment(2));
advanceClocks(time::nanoseconds(1));
// error triggered since segment 3 is part of the content
BOOST_CHECK_EQUAL(hasFailed, true);
}
BOOST_AUTO_TEST_CASE(SpuriousFailureBeforeFinalBlockIdReceived)
{
// failed to retrieve segNo while the FinalBlockId has not yet been
// set, and later received a FinalBlockId < segNo, i.e. segNo is
// not part of the content, and it was actually a spurious failure
nDataSegments = 4;
pipeline->m_cwnd = 4;
run(name);
advanceClocks(time::nanoseconds(1));
// receive segment 0 without FinalBlockId
face.receive(*makeDataWithSegment(0, false));
advanceClocks(time::nanoseconds(1));
// receive segment 1 without FinalBlockId
face.receive(*makeDataWithSegment(1, false));
advanceClocks(time::nanoseconds(1));
// interests for segment 0 - 7 have been sent
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
// receive nack with NackReason::NONE for segment 4
auto nack = makeNack(face.sentInterests[4], lp::NackReason::NONE);
face.receive(nack);
advanceClocks(time::nanoseconds(1));
// error not triggered
// pending interests for segment > 3 have been removed
BOOST_CHECK_EQUAL(hasFailed, false);
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
// receive segment 2 with FinalBlockId
face.receive(*makeDataWithSegment(2));
advanceClocks(time::nanoseconds(1));
// timeout segment 3
advanceClocks(time::seconds(1));
// segment 3 is retransmitted
BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
// receive segment 3
face.receive(*makeDataWithSegment(3));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(hasFailed, false);
}
BOOST_AUTO_TEST_CASE(SegmentInfoMaintenance)
{
// test that m_segmentInfo is properly maintained when
// a segment is received after two consecutive timeouts
nDataSegments = 3;
run(name);
advanceClocks(time::nanoseconds(1));
// receive segment 0
face.receive(*makeDataWithSegment(0));
advanceClocks(time::nanoseconds(1));
// receive segment 1
face.receive(*makeDataWithSegment(1));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
// check if segment 2's state is FirstTimeSent
auto it = pipeline->m_segmentInfo.find(2);
BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
BOOST_CHECK(it->second.state == SegmentState::FirstTimeSent);
// timeout segment 2 twice
advanceClocks(time::milliseconds(400), 3);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
// check if segment 2's state is Retransmitted
it = pipeline->m_segmentInfo.find(2);
BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
BOOST_CHECK(it->second.state == SegmentState::Retransmitted);
// check if segment 2 was retransmitted twice
BOOST_CHECK_EQUAL(pipeline->m_retxCount.at(2), 2);
// receive segment 2 the first time
face.receive(*makeDataWithSegment(2));
advanceClocks(time::nanoseconds(1));
// check if segment 2 was erased from m_segmentInfo
it = pipeline->m_segmentInfo.find(2);
BOOST_CHECK(it == pipeline->m_segmentInfo.end());
auto prevRtt = rttEstimator.getAvgRtt();
auto prevRto = rttEstimator.getEstimatedRto();
// receive segment 2 the second time
face.receive(*makeDataWithSegment(2));
advanceClocks(time::nanoseconds(1));
// nothing changed
it = pipeline->m_segmentInfo.find(2);
BOOST_CHECK(it == pipeline->m_segmentInfo.end());
BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
BOOST_CHECK_EQUAL(rttEstimator.getAvgRtt(), prevRtt);
BOOST_CHECK_EQUAL(rttEstimator.getEstimatedRto(), prevRto);
}
BOOST_AUTO_TEST_CASE(PrintSummaryWithNoRttMeasurements)
{
// test the console ouptut when no RTT measurement is available,
// to make sure a proper message will be printed out
std::stringstream ss;
// change the underlying buffer and save the old buffer
auto oldBuf = std::cerr.rdbuf(ss.rdbuf());
pipeline->printSummary();
std::string line;
bool found = false;
while (std::getline(ss, line)) {
if (line == "RTT stats unavailable") {
found = true;
break;
}
}
BOOST_CHECK(found);
std::cerr.rdbuf(oldBuf); // reset
}
BOOST_AUTO_TEST_CASE(StopsWhenFileSizeLessThanChunkSize)
{
// test to see if the program doesn't hang,
// when transfer is complete, for files less than the chunk size
// (i.e. when only one segment is sent/received)
createPipeline();
nDataSegments = 1;
run(name);
advanceClocks(time::nanoseconds(1));
face.receive(*makeDataWithSegment(0));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
BOOST_CHECK_EQUAL(pipeline->m_segmentInfo.size(), 0);
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
}
BOOST_AUTO_TEST_SUITE_END() // TestPipelineInterestsCubic
BOOST_AUTO_TEST_SUITE_END() // Chunks
} // namespace ndn::chunks::tests
+299
View File
@@ -0,0 +1,299 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016-2022, Regents of the University of California,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Andrea Tosatto
* @author Chavoosh Ghasemi
*/
#include "tools/chunks/catchunks/pipeline-interests-fixed.hpp"
#include "tools/chunks/catchunks/data-fetcher.hpp"
#include "pipeline-interests-fixture.hpp"
namespace ndn::chunks::tests {
class PipelineInterestFixedFixture : public PipelineInterestsFixture
{
public:
PipelineInterestFixedFixture()
{
opt.interestLifetime = 1_s;
opt.maxRetriesOnTimeoutOrNack = 3;
opt.isQuiet = true;
opt.maxPipelineSize = 5;
createPipeline();
}
void
createPipeline()
{
auto pline = make_unique<PipelineInterestsFixed>(face, opt);
pipeline = pline.get();
setPipeline(std::move(pline));
}
protected:
Options opt;
PipelineInterestsFixed* pipeline;
};
BOOST_AUTO_TEST_SUITE(Chunks)
BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsFixed, PipelineInterestFixedFixture)
BOOST_AUTO_TEST_CASE(FullPipeline)
{
nDataSegments = 13;
BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
for (uint64_t i = 0; i < nDataSegments - 1; ++i) {
face.receive(*makeDataWithSegment(i));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, i + 1);
if (i < nDataSegments - opt.maxPipelineSize) {
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize + i + 1);
// check if the interest for the segment i is well formed
const auto& sentInterest = face.sentInterests[i];
BOOST_CHECK_EQUAL(sentInterest.getCanBePrefix(), false);
BOOST_CHECK_EQUAL(sentInterest.getMustBeFresh(), opt.mustBeFresh);
BOOST_CHECK_EQUAL(Name(name).isPrefixOf(sentInterest.getName()), true);
BOOST_CHECK_EQUAL(getSegmentFromPacket(sentInterest), i);
}
else {
// all the interests have been sent for all the segments
BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments);
}
}
BOOST_CHECK_EQUAL(hasFailed, false);
advanceClocks(ndn::DEFAULT_INTEREST_LIFETIME, opt.maxRetriesOnTimeoutOrNack + 1);
BOOST_CHECK_EQUAL(hasFailed, true);
}
BOOST_AUTO_TEST_CASE(TimeoutAllSegments)
{
nDataSegments = 13;
BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
for (int i = 0; i < opt.maxRetriesOnTimeoutOrNack; ++i) {
advanceClocks(opt.interestLifetime);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize * (i + 2));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 0);
// A single retry for every pipeline element
for (size_t j = 0; j < opt.maxPipelineSize; ++j) {
const auto& interest = face.sentInterests[(opt.maxPipelineSize * (i + 1)) + j];
BOOST_CHECK_EQUAL(static_cast<size_t>(getSegmentFromPacket(interest)), j);
}
}
advanceClocks(opt.interestLifetime);
BOOST_CHECK_EQUAL(hasFailed, true);
}
BOOST_AUTO_TEST_CASE(TimeoutAfterFinalBlockIdReceived)
{
// the FinalBlockId is sent with the first segment, after the first segment failure the pipeline
// should fail
nDataSegments = 18;
BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
// send a single segment for each pipeline element but not the first element
advanceClocks(opt.interestLifetime);
for (uint64_t i = 1; i < opt.maxPipelineSize; ++i) {
face.receive(*makeDataWithSegment(i));
advanceClocks(time::nanoseconds(1));
}
// send a single data packet for each pipeline element
advanceClocks(opt.interestLifetime, opt.maxRetriesOnTimeoutOrNack - 1);
for (uint64_t i = 0; i < opt.maxPipelineSize; ++i) {
face.receive(*makeDataWithSegment(opt.maxPipelineSize + i));
advanceClocks(time::nanoseconds(1));
}
advanceClocks(opt.interestLifetime);
size_t interestAfterFailure = face.sentInterests.size();
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
BOOST_CHECK_EQUAL(hasFailed, true);
// these new segments should not generate new interests
advanceClocks(opt.interestLifetime);
for (uint64_t i = 0; i < opt.maxPipelineSize; ++i) {
face.receive(*makeDataWithSegment(opt.maxPipelineSize * 2 + i - 1));
advanceClocks(time::nanoseconds(1));
}
// no more interests after a failure
advanceClocks(opt.interestLifetime, opt.maxRetriesOnTimeoutOrNack);
BOOST_CHECK_EQUAL(interestAfterFailure, face.sentInterests.size());
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
}
BOOST_AUTO_TEST_CASE(TimeoutBeforeFinalBlockIdReceived)
{
// the FinalBlockId is sent only with the last segment, all segments are sent except for the
// second one (segment #1); all segments are received correctly until the FinalBlockId is received
nDataSegments = 22;
BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
advanceClocks(opt.interestLifetime);
for (uint64_t i = 2; i < opt.maxPipelineSize; ++i) {
face.receive(*makeDataWithSegment(i, false));
advanceClocks(time::nanoseconds(1));
const auto& lastInterest = face.sentInterests.back();
BOOST_CHECK_EQUAL(getSegmentFromPacket(lastInterest), opt.maxPipelineSize + i - 2);
}
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize * 3 - 2);
// nack for the first pipeline element (segment #0)
auto nack = make_shared<lp::Nack>(face.sentInterests[opt.maxPipelineSize]);
nack->setReason(lp::NackReason::DUPLICATE);
face.receive(*nack);
// all the pipeline elements are two retries near the timeout error, but not the
// second (segment #1) that is only one retry near the timeout
advanceClocks(opt.interestLifetime, opt.maxRetriesOnTimeoutOrNack - 1);
BOOST_CHECK_EQUAL(hasFailed, false);
// data for the first pipeline element (segment #0)
face.receive(*makeDataWithSegment(0, false));
BOOST_CHECK_EQUAL(hasFailed, false);
// data for all the pipeline element, but not the second (segment #1)
for (uint64_t i = opt.maxPipelineSize; i < nDataSegments; ++i) {
if (i == nDataSegments - 1) {
face.receive(*makeDataWithSegment(i, true));
}
else {
face.receive(*makeDataWithSegment(i, false));
}
advanceClocks(time::nanoseconds(1));
}
// timeout for the second pipeline element (segment #1), this should trigger an error
advanceClocks(opt.interestLifetime);
BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments - 1);
BOOST_CHECK_EQUAL(hasFailed, true);
}
BOOST_AUTO_TEST_CASE(SegmentReceivedAfterTimeout)
{
// the FinalBlockId is never sent, all the pipeline elements with a segment number greater than
// segment #0 will fail, after this failure also segment #0 fail and this should trigger an error
nDataSegments = 22;
BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
advanceClocks(opt.interestLifetime);
// nack for the first pipeline element (segment #0)
auto nack = make_shared<lp::Nack>(face.sentInterests[opt.maxPipelineSize]);
nack->setReason(lp::NackReason::DUPLICATE);
face.receive(*nack);
BOOST_CHECK_EQUAL(hasFailed, false);
// timeout for all the pipeline elements, but not the first (segment #0)
advanceClocks(opt.interestLifetime, opt.maxRetriesOnTimeoutOrNack);
BOOST_CHECK_EQUAL(hasFailed, false);
// data for the first pipeline element (segment #0), this should trigger an error because the
// other pipeline elements failed
face.receive(*makeDataWithSegment(0, false));
advanceClocks(time::nanoseconds(1));
BOOST_CHECK_EQUAL(pipeline->m_nReceived, 1);
BOOST_CHECK_EQUAL(hasFailed, true);
}
BOOST_AUTO_TEST_CASE(CongestionAllSegments)
{
nDataSegments = 13;
BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
run(name);
advanceClocks(time::nanoseconds(1));
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
// send nack for all the pipeline elements first interest
for (size_t i = 0; i < opt.maxPipelineSize; i++) {
auto nack = make_shared<lp::Nack>(face.sentInterests[i]);
nack->setReason(lp::NackReason::CONGESTION);
face.receive(*nack);
advanceClocks(time::nanoseconds(1));
}
// send nack for all the pipeline elements interests after the first
for (int i = 1; i <= opt.maxRetriesOnTimeoutOrNack; ++i) {
time::milliseconds backoffTime(static_cast<uint64_t>(std::pow(2, i)));
if (backoffTime > DataFetcher::MAX_CONGESTION_BACKOFF_TIME)
backoffTime = DataFetcher::MAX_CONGESTION_BACKOFF_TIME;
advanceClocks(backoffTime);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize * (i +1));
// A single retry for every pipeline element
for (size_t j = 0; j < opt.maxPipelineSize; ++j) {
const auto& interest = face.sentInterests[(opt.maxPipelineSize * i) + j];
BOOST_CHECK_LT(static_cast<size_t>(getSegmentFromPacket(interest)), opt.maxPipelineSize);
}
for (size_t j = 0; j < opt.maxPipelineSize; j++) {
auto nack = make_shared<lp::Nack>(face.sentInterests[(opt.maxPipelineSize * i) + j]);
nack->setReason(lp::NackReason::CONGESTION);
face.receive(*nack);
advanceClocks(time::nanoseconds(1));
}
}
BOOST_CHECK_EQUAL(hasFailed, true);
}
BOOST_AUTO_TEST_SUITE_END() // TestPipelineInterests
BOOST_AUTO_TEST_SUITE_END() // Chunks
} // namespace ndn::chunks::tests
@@ -0,0 +1,91 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016-2023, Regents of the University of California,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Andrea Tosatto
* @author Davide Pesavento
* @author Weiwei Liu
* @author Chavoosh Ghasemi
*/
#ifndef NDN_TOOLS_TESTS_CHUNKS_PIPELINE_INTERESTS_FIXTURE_HPP
#define NDN_TOOLS_TESTS_CHUNKS_PIPELINE_INTERESTS_FIXTURE_HPP
#include "tools/chunks/catchunks/pipeline-interests.hpp"
#include "tests/test-common.hpp"
#include "tests/io-fixture.hpp"
#include <ndn-cxx/util/dummy-client-face.hpp>
namespace ndn::chunks::tests {
using namespace ndn::tests;
class PipelineInterestsFixture : public IoFixture
{
protected:
void
setPipeline(unique_ptr<PipelineInterests> pline)
{
m_pipeline = std::move(pline);
}
shared_ptr<Data>
makeDataWithSegment(uint64_t segmentNo, bool setFinalBlockId = true) const
{
auto data = make_shared<Data>(Name(name).appendVersion(0).appendSegment(segmentNo));
if (setFinalBlockId)
data->setFinalBlock(name::Component::fromSegment(nDataSegments - 1));
return signData(data);
}
shared_ptr<Data>
makeDataWithSegmentAndCongMark(uint64_t segmentNo,
uint64_t congestionMark = 1,
bool setFinalBlockId = true) const
{
auto data = makeDataWithSegment(segmentNo, setFinalBlockId);
data->setCongestionMark(congestionMark);
return data;
}
void
run(const Name& name, uint64_t version = 0)
{
m_pipeline->run(Name(name).appendVersion(version),
[] (const Data&) {},
[this] (const std::string&) { hasFailed = true; });
}
protected:
DummyClientFace face{m_io};
Name name{"/ndn/chunks/test"};
uint64_t nDataSegments = 0;
bool hasFailed = false;
private:
unique_ptr<PipelineInterests> m_pipeline;
};
} // namespace ndn::chunks::tests
#endif // NDN_TOOLS_TESTS_CHUNKS_PIPELINE_INTERESTS_FIXTURE_HPP
+219
View File
@@ -0,0 +1,219 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016-2023, Regents of the University of California,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Andrea Tosatto
*/
#include "tools/chunks/putchunks/producer.hpp"
#include "tests/test-common.hpp"
#include "tests/io-fixture.hpp"
#include "tests/key-chain-fixture.hpp"
#include <ndn-cxx/metadata-object.hpp>
#include <ndn-cxx/security/pib/identity.hpp>
#include <ndn-cxx/security/pib/key.hpp>
#include <ndn-cxx/util/dummy-client-face.hpp>
#include <cmath>
#include <sstream>
namespace ndn::chunks::tests {
using namespace ndn::tests;
class ProducerFixture : public IoFixture, public KeyChainFixture
{
protected:
ProducerFixture()
{
options.maxSegmentSize = 40;
options.isQuiet = true;
}
protected:
DummyClientFace face{m_io, {true, true}};
Name prefix = "/ndn/chunks/test";
Producer::Options options;
uint64_t version = 1449227841747;
Name keyLocatorName = m_keyChain.createIdentity("/putchunks/producer")
.getDefaultKey().getDefaultCertificate().getName();
std::istringstream testString{
"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget "
"dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, "
"nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, "
"sem. Nulla consequat massa Donec pede justo,"s};
};
BOOST_AUTO_TEST_SUITE(Chunks)
BOOST_FIXTURE_TEST_SUITE(TestProducer, ProducerFixture)
BOOST_AUTO_TEST_CASE(InputData)
{
const std::vector<std::string> testStrings{
"",
"a1b2c3%^&(#$&%^$$/><",
"123456789123456789123456789123456789123456789123456789123456789"
"123456789123456789123456789123456789123456789123456789123456789",
"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. "
"Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur "
"ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla "
"consequat massa Donec pede justo,"
};
for (const auto& str : testStrings) {
std::istringstream input(str);
Producer prod(prefix, face, m_keyChain, input, options);
size_t expectedSize = str.empty() ? 1 : std::ceil(static_cast<double>(str.size()) / options.maxSegmentSize);
BOOST_CHECK_EQUAL(prod.m_store.size(), expectedSize);
}
}
BOOST_AUTO_TEST_CASE(RequestSegmentUnspecifiedVersion)
{
Producer producer(prefix, face, m_keyChain, testString, options);
m_io.poll();
size_t nSegments = std::ceil(static_cast<double>(testString.str().size()) / options.maxSegmentSize);
// version request
face.receive(*makeInterest(prefix, true));
face.processEvents();
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
auto lastData = face.sentData.back();
BOOST_REQUIRE_EQUAL(lastData.getName().size(), prefix.size() + 2);
BOOST_CHECK_EQUAL(lastData.getName()[-1].toSegment(), 0);
BOOST_CHECK_EQUAL(lastData.getFinalBlock().value().toSegment(), nSegments - 1);
BOOST_CHECK_EQUAL(lastData.getKeyLocator().value().getName(), keyLocatorName);
// segment request
Name nameWithVersion(prefix);
nameWithVersion.append(lastData.getName()[-2]);
size_t requestSegmentNo = 1;
face.receive(*makeInterest(nameWithVersion.appendSegment(requestSegmentNo), true));
face.processEvents();
BOOST_REQUIRE_EQUAL(face.sentData.size(), 2);
lastData = face.sentData.back();
BOOST_REQUIRE_EQUAL(lastData.getName().size(), prefix.size() + 2);
BOOST_CHECK_EQUAL(lastData.getName()[-1].toSegment(), requestSegmentNo);
BOOST_CHECK_EQUAL(lastData.getFinalBlock().value().toSegment(), nSegments - 1);
BOOST_CHECK_EQUAL(lastData.getKeyLocator().value().getName(), keyLocatorName);
}
BOOST_AUTO_TEST_CASE(RequestSegmentSpecifiedVersion)
{
Producer producer(prefix.appendVersion(version), face, m_keyChain, testString, options);
m_io.poll();
size_t nSegments = std::ceil(static_cast<double>(testString.str().size()) / options.maxSegmentSize);
// version request
face.receive(*makeInterest(prefix, true));
face.processEvents();
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
auto lastData = face.sentData.back();
BOOST_REQUIRE_EQUAL(lastData.getName().size(), prefix.size() + 1);
BOOST_CHECK_EQUAL(lastData.getName()[-2].toVersion(), version);
BOOST_CHECK_EQUAL(lastData.getName()[-1].toSegment(), 0);
BOOST_CHECK_EQUAL(lastData.getFinalBlock().value().toSegment(), nSegments - 1);
BOOST_CHECK_EQUAL(lastData.getKeyLocator().value().getName(), keyLocatorName);
// segment request
Name nameWithVersion(prefix);
size_t requestSegmentNo = 1;
face.receive(*makeInterest(nameWithVersion.appendSegment(requestSegmentNo), true));
face.processEvents();
BOOST_REQUIRE_EQUAL(face.sentData.size(), 2);
lastData = face.sentData.back();
BOOST_REQUIRE_EQUAL(lastData.getName().size(), prefix.size() + 1);
BOOST_CHECK_EQUAL(lastData.getName()[-2].toVersion(), version);
BOOST_CHECK_EQUAL(lastData.getName()[-1].toSegment(), requestSegmentNo);
BOOST_CHECK_EQUAL(lastData.getFinalBlock().value().toSegment(), nSegments - 1);
BOOST_CHECK_EQUAL(lastData.getKeyLocator().value().getName(), keyLocatorName);
}
BOOST_AUTO_TEST_CASE(RequestNotExistingSegment)
{
Producer producer(prefix, face, m_keyChain, testString, options);
m_io.poll();
size_t nSegments = std::ceil(static_cast<double>(testString.str().size()) / options.maxSegmentSize);
// version request
face.receive(*makeInterest(prefix, true));
face.processEvents();
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
auto lastData = face.sentData.back();
BOOST_REQUIRE_EQUAL(lastData.getName().size(), prefix.size() + 2);
BOOST_CHECK_EQUAL(lastData.getName()[-1].toSegment(), 0);
BOOST_CHECK_EQUAL(lastData.getFinalBlock().value().toSegment(), nSegments - 1);
BOOST_CHECK_EQUAL(lastData.getKeyLocator().value().getName(), keyLocatorName);
// segment request
Name nameWithVersion(prefix);
nameWithVersion.append(lastData.getName()[-2]);
face.receive(*makeInterest(nameWithVersion.appendSegment(nSegments), true));
face.processEvents();
// no new data
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
}
BOOST_AUTO_TEST_CASE(RequestMetadata)
{
Producer producer(prefix.appendVersion(version), face, m_keyChain, testString, options);
m_io.poll();
// ask for metadata with a valid discovery interest
face.receive(MetadataObject::makeDiscoveryInterest(Name(prefix).getPrefix(-1)));
face.processEvents();
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
auto lastData = face.sentData.back();
// check the name of metadata packet
BOOST_CHECK(MetadataObject::isValidName(lastData.getName()));
// make metadata object from metadata packet
MetadataObject mobject(lastData);
BOOST_CHECK_EQUAL(mobject.getVersionedName(), prefix);
// ask for metadata with an invalid discovery interest
face.receive(MetadataObject::makeDiscoveryInterest(Name(prefix).getPrefix(-1))
.setCanBePrefix(false));
face.processEvents();
// we expect Nack in response to a discovery interest without CanBePrefix
BOOST_CHECK_EQUAL(face.sentNacks.size(), 1);
}
BOOST_AUTO_TEST_SUITE_END() // TestProducer
BOOST_AUTO_TEST_SUITE_END() // Chunks
} // namespace ndn::chunks::tests
+58
View File
@@ -0,0 +1,58 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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 ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tests/clock-fixture.hpp"
namespace ndn::tests {
ClockFixture::ClockFixture()
: m_steadyClock(make_shared<time::UnitTestSteadyClock>())
, m_systemClock(make_shared<time::UnitTestSystemClock>())
{
time::setCustomClocks(m_steadyClock, m_systemClock);
}
ClockFixture::~ClockFixture()
{
time::setCustomClocks(nullptr, nullptr);
}
void
ClockFixture::advanceClocks(time::nanoseconds tick, time::nanoseconds total)
{
BOOST_ASSERT(tick > time::nanoseconds::zero());
BOOST_ASSERT(total >= time::nanoseconds::zero());
while (total > time::nanoseconds::zero()) {
auto t = std::min(tick, total);
m_steadyClock->advance(t);
m_systemClock->advance(t);
total -= t;
afterTick();
}
}
} // namespace ndn::tests
+87
View File
@@ -0,0 +1,87 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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 ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NDN_TOOLS_TESTS_CLOCK_FIXTURE_HPP
#define NDN_TOOLS_TESTS_CLOCK_FIXTURE_HPP
#include <ndn-cxx/util/time-unit-test-clock.hpp>
namespace ndn::tests {
/** \brief A test fixture that overrides steady clock and system clock.
*/
class ClockFixture
{
public:
virtual
~ClockFixture();
/** \brief Advance steady and system clocks.
*
* Clocks are advanced in increments of \p tick for \p nTicks ticks.
* afterTick() is called after each tick.
*
* Exceptions thrown during I/O events are propagated to the caller.
* Clock advancement will stop in the event of an exception.
*/
void
advanceClocks(time::nanoseconds tick, size_t nTicks = 1)
{
advanceClocks(tick, tick * nTicks);
}
/** \brief Advance steady and system clocks.
*
* Clocks are advanced in increments of \p tick for \p total time.
* The last increment might be shorter than \p tick.
* afterTick() is called after each tick.
*
* Exceptions thrown during I/O events are propagated to the caller.
* Clock advancement will stop in the event of an exception.
*/
void
advanceClocks(time::nanoseconds tick, time::nanoseconds total);
protected:
ClockFixture();
private:
/** \brief Called by advanceClocks() after each clock advancement (tick).
*
* The base class implementation is a no-op.
*/
virtual void
afterTick()
{
}
protected:
shared_ptr<time::UnitTestSteadyClock> m_steadyClock;
shared_ptr<time::UnitTestSystemClock> m_systemClock;
};
} // namespace ndn::tests
#endif // NDN_TOOLS_TESTS_CLOCK_FIXTURE_HPP
+93
View File
@@ -25,6 +25,8 @@ Expected result of the dissection:
- NDN interests are dissected from packets 1, 2, 3, and 8.
- NDN data packet is dissected from defragmented packets 4, 5, 6, and 7.
- In packet 1, the "Info" column of Wireshark shows: `Interest /ndn/broadcast/ndnrtc-chatrooms/2366d310b15ba97a62c8734d4a760174f78d14446be3d70a54ee80d3ed19c83b`
- In packet 7, the "Info" column of Wireshark shows: `Data /example/testApp/1/testApp/%FD%00%00%01O%23E%07%ED`
### 2. IPv6 UDP
@@ -105,3 +107,94 @@ Trace summary: Short capture, containing an NDN interest multicasted directly in
Expected result of the dissection:
- interest packet is dissected from packet 6.
### 8. tvb Overflow
Trace file: `bug3603.pcap`
Trace summary: A Data whose payload could be read as incomplete TLV and may cause tvb overflow
if parser does not check packet length.
Expected result of the dissection:
- data packet is dissected at packet 12 without Lua error.
### 9. NDNLPv2
Trace file: `ndnlpv2.pcap`
Trace summary: Handcrafted NDNLPv2 packets.
(`xxd -p -r < ndnlpv2.hex > ndnlpv2.pcap`).
Expected result of the dissection: 12 "Ethernet (NDN)" frames.
1. LpPacket contains 12 unrecognized fields. The 10th and 12th fields are labelled "ignored".
2. No special requirements.
3. "Sequence: 12732154106453800448". "FragIndex: 0". "FragCount: 2". Fragment exists.
4. "Sequence: 12732154106453800449". "FragIndex: 1". "FragCount: 2". Fragment exists.
5. "NackReason: Congestion". The "Info" column shows "Nack /A".
6. "NackReason: Duplicate".
7. "NackReason: NoRoute".
8. "NackReason: 1".
9. Nack exists, but NackReason does not exist.
10. "PitToken: 15047039637272254167".
11. "CongestionMark: 1". "TxSequence: 16204482402681480935".
12. There are eight Ack fields. First is "Ack: 16204482402681480704". Eighth is "Ack: 16204482402681480711".
### 10. NDNLPv2 (random)
Trace file: `ndnlpv2-more.pcap`
Trace summary: Short capture of randomly generated NDNLPv2 packets (see
https://gist.github.com/cawka/fcdde58cc4dc94d789025ab8300076dc) with multiple fields set to various
values. Given the random generation, some fields are semantically meaningless.
Expected results of the dissection:
- 10 NDN (NDNLPv2) packets extracted from the reassembled TCP stream
- the dissection results include Fragment (Interest/Data), Sequence (number), FragIndex (number),
FragCount (number), Nack (various reasons), NextHopFaceId, IncomingFaceId, CachingPolicy, and
unknown fields
### 11. NDN Packet Format v0.3
Trace file: `packet03.pcap`
Trace summary: Handcrafted packets in NDN Packet Format v0.3
(`xxd -p -r < packet03.hex > packet03.pcap`).
All packets are valid and do not contain unrecognized TLV elements.
Expected results of the dissection:
- Packet 1 is recognized as "Interest" and contains `CanBePrefix: Yes`, `MustBeFresh: Yes`,
`HopLimit: 214`, as well as a "ForwardingHint" and an "ApplicationParameters" field.
- Packet 2 is recognized as "Interest" and has `Name: /params-sha256=41/7=B/C/252=D/256=E/65535=E/sha256digest=ee357c5791dcaa4494d9b301047b875d8833caa76dada3e95837bbc3eaf7b300`.
- Packet 3 is recognized as "Data" and has `Name: /`.
### 12. URI Scheme
Trace file: `nameuri.pcap`
Trace summary: Handcrafted packet for testing URI encoding in Name and FinalBlockId
(`xxd -p -r < nameuri.hex > nameuri.pcap`).
Expected results of the dissection:
- Packet 1 is recognized as "Data".
- Its name has eight components.
- First name component is `NameComponent: ...`.
- Second name component is `NameComponent: ....`.
- Third name component is `NameComponent: .....`.
- Fourth name component is `NameComponent: .A`.
- Fifth name component is `NameComponent: %00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F`.
Notice that digits, HYPHEN (`-`), and PERIOD (`.`) are not percent-encoded.
- Sixth name component is `NameComponent: %40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F`.
Notice that upper case letters, lower case letters, UNDERSCORE (`_`), and TILDE (`~`) are not percent-encoded.
- Seventh name component is `NameComponent: %80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF`.
- Eighth name component is `NameComponent: %C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF`.
- FinalBlockId and its nested NameComponent are both `%02`.
### 13. PPP
Trace file: `ppp.pcap`
Trace summary: 8 packets created in a simple ndnSIM scenario
Expected results of the dissection:
- 4 interests (packets 1, 2, 5, 6), each carried in an LpPacket fragment
- 4 data packets (packets 3, 4, 7, 8), also each carried in an LpPacket fragment
Binary file not shown.
+41
View File
@@ -0,0 +1,41 @@
A1B2C3D4
00020004
00000000
00000000
00010000
00000001
# packet 1
00000000
00000000
00000159
00000159
01005E0017AA
000000000000
8624
## Data
06FD0147
## Name
07FD0115
0800
08012E
08022E2E
08022E41
0840000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F
0840404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F
0840808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF
0840C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF
## MetaInfo
1405
1A03080102
## SignatureInfo
1603
1B0100
## SignatureValue
1720612A79399E60304A9F701C1ECAC7956BF2F1B046E6C6F0D6C29B3FE3A29BAD76
Binary file not shown.
Binary file not shown.
+218
View File
@@ -0,0 +1,218 @@
A1B2C3D4
00020004
00000000
00000000
00010000
00000001
# packet 1
00000000
00000000
00000030
00000030
01005E0017AA
000000000000
8624
## LpPacket with unrecognized headers
6420
5500
5600
5700
5800
5900
6000
6100
6300
FD032400
FD032500
FD032600
FD032700
# packet 2
00000000
00000000
00000029
00000029
01005E0017AA
000000000000
8624
## LpPacket with reordered headers
6419
530102
5108B0B1B2B3B4B5B600
5007 050B0703080141
520100
# packet 3
00000000
00000000
00000029
00000029
01005E0017AA
000000000000
8624
## first half of fragmented Interest
6419
5108B0B1B2B3B4B5B600
520100
530102
5007
050B0703080141
# packet 4
00000000
00000000
00000028
00000028
01005E0017AA
000000000000
8624
## second half of fragmented Interest
6418
5108B0B1B2B3B4B5B601
520101
530102
5006
0A04A0A1A2A3
# packet 5
00000000
00000000
00000028
00000028
01005E0017AA
000000000000
8624
## Nack~Congestion
6418
FD032005 FD03210132
500D
050B07030801410A04A0A1A2A3
# packet 6
00000000
00000000
00000028
00000028
01005E0017AA
000000000000
8624
## Nack~Duplicate
6418
FD032005 FD03210164
500D
050B07030801410A04A0A1A2A3
# packet 7
00000000
00000000
00000028
00000028
01005E0017AA
000000000000
8624
## Nack~NoRoute
6418
FD032005 FD03210196
500D
050B07030801410A04A0A1A2A3
# packet 8
00000000
00000000
00000028
00000028
01005E0017AA
000000000000
8624
## Nack unrecognized reason
6418
FD032005 FD03210101
500D
050B07030801410A04A0A1A2A3
# packet 9
00000000
00000000
00000023
00000023
01005E0017AA
000000000000
8624
## Nack no reason
6413
FD032000
500D
050B07030801410A04A0A1A2A3
# packet 10
00000000
00000000
00000029
00000029
01005E0017AA
000000000000
8624
## Interest with PIT token
6419
6208D0D1D2D3D4D5D6D7
500D
050B07030801410A04A0A1A2A3
# packet 11
00000000
00000000
0000004E
0000004E
01005E0017AA
000000000000
8624
## Data with CongestionMark=1 and TxSequence
643E
FD03400101
FD034808E0E1E2E3E4E5E6E7
502B
0629 0700 16031B0100 1720612A79399E60304A9F701C1ECAC7956BF2F1B046E6C6F0D6C29B3FE3A29BAD76
# packet 12
00000000
00000000
00000070
00000070
01005E0017AA
000000000000
8624
## IDLE packet with Acks
6460
FD034408E0E1E2E3E4E5E600
FD034408E0E1E2E3E4E5E601
FD034408E0E1E2E3E4E5E602
FD034408E0E1E2E3E4E5E603
FD034408E0E1E2E3E4E5E604
FD034408E0E1E2E3E4E5E605
FD034408E0E1E2E3E4E5E606
FD034408E0E1E2E3E4E5E607
Binary file not shown.
+58
View File
@@ -0,0 +1,58 @@
A1B2C3D4
00020004
00000000
00000000
00010000
00000001
# packet 1
00000000
00000000
00000039
00000039
01005E0017AA
000000000000
8624
## Interest with CanBePrefix, MustBeFresh, HopLimit, ApplicationParameters
0529
0703080149
2100
1200
1E0B 1F09 1E023E15 0703080148
0A044ACB1E4C
0C0276A1
2201D6
2404C0C1C2C3
# packet 2
00000000
00000000
00000050
00000050
01005E0017AA
000000000000
8624
## Interest Name contains typed name components
0540
0738 020141 070142 080143 FC0144 FD01000145 FDFFFF0145 0120EE357C5791DCAA4494D9B301047B875D8833CAA76DADA3E95837BBC3EAF7B300
0A044ACB1E4C
# packet 3
00000000
00000000
00000039
00000039
01005E0017AA
000000000000
8624
## Data without MetaInfo or Content
0629
0700
16031B0100
1720612A79399E60304A9F701C1ECAC7956BF2F1B046E6C6F0D6C29B3FE3A29BAD76
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+494
View File
@@ -0,0 +1,494 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2023, University of Memphis,
* University Pierre & Marie Curie, Sorbonne University.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tools/dump/ndndump.hpp"
#include "tests/test-common.hpp"
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <boost/endian/conversion.hpp>
#include <boost/test/tools/output_test_stream.hpp>
#include <ndn-cxx/encoding/encoding-buffer.hpp>
#include <ndn-cxx/lp/fields.hpp>
#include <ndn-cxx/lp/packet.hpp>
#include <ndn-cxx/net/ethernet.hpp>
namespace ndn::dump::tests {
namespace endian = boost::endian;
using namespace ndn::tests;
class StdCoutRedirector
{
public:
StdCoutRedirector(std::ostream& os)
{
// Redirect std::cout to the specified output stream
originalBuffer = std::cout.rdbuf(os.rdbuf());
}
~StdCoutRedirector()
{
// Revert state for std::cout
std::cout.rdbuf(originalBuffer);
}
private:
std::streambuf* originalBuffer;
};
class NdnDumpFixture
{
protected:
NdnDumpFixture()
{
dump.m_dataLinkType = DLT_EN10MB;
}
template<typename Packet>
void
receive(const Packet& packet)
{
EncodingBuffer buffer(packet.wireEncode());
receiveEthernet(buffer);
}
void
receiveEthernet(EncodingBuffer& buffer, uint16_t ethertype = s_ethertypeNdn)
{
ethernet::Address host;
// Ethernet header
buffer.prependBytes({reinterpret_cast<const uint8_t*>(&ethertype), ethernet::TYPE_LEN});
buffer.prependBytes(host);
buffer.prependBytes(host);
// pcap header
pcap_pkthdr pkthdr{};
pkthdr.caplen = pkthdr.len = buffer.size();
{
StdCoutRedirector redirect(output);
dump.printPacket(&pkthdr, buffer.data());
}
}
void
receiveIp4(EncodingBuffer& buffer, const ip* ipHeader)
{
buffer.prependBytes({reinterpret_cast<const uint8_t*>(ipHeader), sizeof(ip)});
receiveEthernet(buffer, s_ethertypeIp4);
}
void
receiveIp6(EncodingBuffer& buffer, const ip6_hdr* ip6Header)
{
buffer.prependBytes({reinterpret_cast<const uint8_t*>(ip6Header), sizeof(ip6_hdr)});
receiveEthernet(buffer, s_ethertypeIp6);
}
void
receiveTcp4(EncodingBuffer& buffer, const tcphdr* tcpHeader)
{
buffer.prependBytes({reinterpret_cast<const uint8_t*>(tcpHeader), sizeof(tcphdr)});
ip ipHeader{};
ipHeader.ip_v = 4;
ipHeader.ip_hl = 5;
ipHeader.ip_len = endian::native_to_big(static_cast<uint16_t>(buffer.size() + sizeof(ipHeader)));
ipHeader.ip_ttl = 1;
ipHeader.ip_p = IPPROTO_TCP;
receiveIp4(buffer, &ipHeader);
}
void
receiveUdp4(EncodingBuffer& buffer, const udphdr* udpHeader)
{
buffer.prependBytes({reinterpret_cast<const uint8_t*>(udpHeader), sizeof(udphdr)});
ip ipHeader{};
ipHeader.ip_v = 4;
ipHeader.ip_hl = 5;
ipHeader.ip_len = endian::native_to_big(static_cast<uint16_t>(buffer.size() + sizeof(ipHeader)));
ipHeader.ip_ttl = 1;
ipHeader.ip_p = IPPROTO_UDP;
receiveIp4(buffer, &ipHeader);
}
void
readFile(const std::string& filename)
{
StdCoutRedirector redirect(output);
dump.inputFile = filename;
dump.run();
}
protected:
NdnDump dump;
boost::test_tools::output_test_stream output;
static inline const uint16_t s_ethertypeNdn = endian::native_to_big(ethernet::ETHERTYPE_NDN);
static inline const uint16_t s_ethertypeIp4 = endian::native_to_big(uint16_t(ETHERTYPE_IP));
static inline const uint16_t s_ethertypeIp6 = endian::native_to_big(uint16_t(ETHERTYPE_IPV6));
};
BOOST_AUTO_TEST_SUITE(Dump)
BOOST_FIXTURE_TEST_SUITE(TestNdnDump, NdnDumpFixture)
BOOST_AUTO_TEST_CASE(Interest)
{
auto interest = makeInterest("/test", false, DEFAULT_INTEREST_LIFETIME, 1);
this->receive(*interest);
BOOST_CHECK(output.is_equal("0.000000 Ethernet, INTEREST: /test?Nonce=00000001\n"));
this->receive(interest->setCanBePrefix(true));
BOOST_CHECK(output.is_equal("0.000000 Ethernet, INTEREST: /test?CanBePrefix&Nonce=00000001\n"));
this->receive(interest->setInterestLifetime(50_ms));
BOOST_CHECK(output.is_equal("0.000000 Ethernet, INTEREST: /test?CanBePrefix&Nonce=00000001&Lifetime=50\n"));
}
BOOST_AUTO_TEST_CASE(Data)
{
auto data = makeData("/test");
this->receive(*data);
BOOST_CHECK(output.is_equal("0.000000 Ethernet, DATA: /test\n"));
this->receive(data->setContentType(tlv::ContentType_Key));
BOOST_CHECK(output.is_equal("0.000000 Ethernet, DATA: /test\n"));
this->receive(data->setFreshnessPeriod(42_h));
BOOST_CHECK(output.is_equal("0.000000 Ethernet, DATA: /test\n"));
}
BOOST_AUTO_TEST_CASE(Nack)
{
auto interest = makeInterest("/test", false, DEFAULT_INTEREST_LIFETIME, 1);
auto nack = makeNack(*interest, lp::NackReason::DUPLICATE);
lp::Packet lpPacket(interest->wireEncode());
lpPacket.add<lp::NackField>(nack.getHeader());
this->receive(lpPacket);
BOOST_CHECK(output.is_equal("0.000000 Ethernet, NDNLPv2, NACK (Duplicate): /test?Nonce=00000001\n"));
}
BOOST_AUTO_TEST_CASE(LpFragment)
{
const uint8_t data[10] = {
0x06, 0x08, // Data packet
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
};
Buffer buffer(data, 4);
lp::Packet lpPacket;
lpPacket.add<lp::FragmentField>(std::make_pair(buffer.begin(), buffer.end()));
lpPacket.add<lp::FragIndexField>(0);
lpPacket.add<lp::FragCountField>(2);
lpPacket.add<lp::SequenceField>(1000);
this->receive(lpPacket);
BOOST_CHECK(output.is_equal("0.000000 Ethernet, NDNLPv2 fragment\n"));
}
BOOST_AUTO_TEST_CASE(LpIdle)
{
lp::Packet lpPacket;
this->receive(lpPacket);
BOOST_CHECK(output.is_equal("0.000000 Ethernet, NDNLPv2 idle\n"));
}
BOOST_AUTO_TEST_CASE(IncompleteNdnPacket)
{
const uint8_t interest[] = {
0x05, 0x0E, // Interest
0x07, 0x06, // Name
0x08, 0x04, // NameComponent
0x74, 0x65, 0x73, 0x74,
0x0a, 0x04, // Nonce
0x00, 0x00, 0x00, 0x01
};
EncodingBuffer buffer;
buffer.prependBytes(make_span(interest).first(4));
this->receiveEthernet(buffer);
BOOST_CHECK(output.is_equal("0.000000 Ethernet, NDN truncated packet, length 4\n"));
}
BOOST_AUTO_TEST_CASE(UnsupportedNdnPacket)
{
EncodingBuffer buffer(encoding::makeEmptyBlock(tlv::Name));
this->receiveEthernet(buffer);
BOOST_CHECK(output.is_equal("0.000000 Ethernet, [Unsupported NDN packet type 7]\n"));
}
BOOST_AUTO_TEST_CASE(UnsupportedEtherType)
{
EncodingBuffer pkt;
uint16_t type = ETHERTYPE_ARP;
endian::native_to_big_inplace(type);
this->receiveEthernet(pkt, type);
BOOST_CHECK(output.is_equal("0.000000 [Unsupported ethertype 0x806]\n"));
}
BOOST_AUTO_TEST_CASE(MalformedIpv4Header)
{
dump.wantTimestamp = false;
uint8_t theAnswer = 42;
EncodingBuffer pkt1;
pkt1.prependBytes({theAnswer});
this->receiveEthernet(pkt1, s_ethertypeIp4);
BOOST_CHECK(output.is_equal("IP truncated header, length 1\n"));
ip ipHdr2{};
ipHdr2.ip_v = 7;
EncodingBuffer pkt2;
this->receiveIp4(pkt2, &ipHdr2);
BOOST_CHECK(output.is_equal("IP bad version 7\n"));
ip ipHdr3{};
ipHdr3.ip_v = 4;
ipHdr3.ip_hl = 2;
EncodingBuffer pkt3;
this->receiveIp4(pkt3, &ipHdr3);
BOOST_CHECK(output.is_equal("IP bad header length 8\n"));
ip ipHdr4{};
ipHdr4.ip_v = 4;
ipHdr4.ip_hl = 5;
ipHdr4.ip_len = 10;
endian::native_to_big_inplace(ipHdr4.ip_len);
EncodingBuffer pkt4;
this->receiveIp4(pkt4, &ipHdr4);
BOOST_CHECK(output.is_equal("IP bad length 10\n"));
ip ipHdr5{};
ipHdr5.ip_v = 4;
ipHdr5.ip_hl = 5;
ipHdr5.ip_len = 1000;
endian::native_to_big_inplace(ipHdr5.ip_len);
EncodingBuffer pkt5;
this->receiveIp4(pkt5, &ipHdr5);
BOOST_CHECK(output.is_equal("IP truncated packet, 980 bytes missing\n"));
}
BOOST_AUTO_TEST_CASE(MalformedIpv6Header)
{
dump.wantTimestamp = false;
uint8_t theAnswer = 42;
EncodingBuffer pkt1;
pkt1.prependBytes({theAnswer});
this->receiveEthernet(pkt1, s_ethertypeIp6);
BOOST_CHECK(output.is_equal("IP6 truncated header, length 1\n"));
ip6_hdr ip6Hdr2{};
ip6Hdr2.ip6_vfc = 10 << 4;
EncodingBuffer pkt2;
this->receiveIp6(pkt2, &ip6Hdr2);
BOOST_CHECK(output.is_equal("IP6 bad version 10\n"));
ip6_hdr ip6Hdr3{};
ip6Hdr3.ip6_vfc = 6 << 4;
ip6Hdr3.ip6_plen = 1400;
endian::native_to_big_inplace(ip6Hdr3.ip6_plen);
EncodingBuffer pkt3;
this->receiveIp6(pkt3, &ip6Hdr3);
BOOST_CHECK(output.is_equal("IP6 truncated payload, 1400 bytes missing\n"));
}
BOOST_AUTO_TEST_CASE(UnsupportedIpProto)
{
dump.wantTimestamp = false;
ip ipHdr{};
ipHdr.ip_v = 4;
ipHdr.ip_hl = 5;
ipHdr.ip_len = sizeof(ipHdr);
endian::native_to_big_inplace(ipHdr.ip_len);
ipHdr.ip_p = IPPROTO_SCTP;
EncodingBuffer pkt1;
this->receiveIp4(pkt1, &ipHdr);
BOOST_CHECK(output.is_equal("IP 0.0.0.0 > 0.0.0.0, [Unsupported IP proto 132]\n"));
ip6_hdr ip6Hdr{};
ip6Hdr.ip6_vfc = 6 << 4;
ip6Hdr.ip6_nxt = IPPROTO_NONE;
EncodingBuffer pkt2;
this->receiveIp6(pkt2, &ip6Hdr);
BOOST_CHECK(output.is_equal("IP6 :: > ::, [No next header]\n"));
}
BOOST_AUTO_TEST_CASE(MalformedTcpHeader)
{
dump.wantTimestamp = false;
tcphdr tcpHdr1{};
tcpHdr1.TH_OFF = 0x2;
EncodingBuffer pkt1;
this->receiveTcp4(pkt1, &tcpHdr1);
BOOST_CHECK(output.is_equal("IP 0.0.0.0 > 0.0.0.0, TCP bad header length 8\n"));
tcphdr tcpHdr2{};
tcpHdr2.TH_OFF = 0xf;
EncodingBuffer pkt2;
this->receiveTcp4(pkt2, &tcpHdr2);
BOOST_CHECK(output.is_equal("IP 0.0.0.0 > 0.0.0.0, TCP truncated header, 40 bytes missing\n"));
}
BOOST_AUTO_TEST_CASE(MalformedUdpHeader)
{
dump.wantTimestamp = false;
udphdr udpHdr1{};
udpHdr1.UH_LEN = 3;
endian::native_to_big_inplace(udpHdr1.UH_LEN);
EncodingBuffer pkt1;
this->receiveUdp4(pkt1, &udpHdr1);
BOOST_CHECK(output.is_equal("IP 0.0.0.0 > 0.0.0.0, UDP bad length 3\n"));
udphdr udpHdr2{};
udpHdr2.UH_LEN = 1000;
endian::native_to_big_inplace(udpHdr2.UH_LEN);
EncodingBuffer pkt2;
this->receiveUdp4(pkt2, &udpHdr2);
BOOST_CHECK(output.is_equal("IP 0.0.0.0 > 0.0.0.0, UDP truncated packet, 992 bytes missing\n"));
}
BOOST_AUTO_TEST_CASE(InvalidTlvLength)
{
dump.wantTimestamp = false;
this->readFile("tests/dump/invalid-tlv-length.pcap");
const std::string expected =
"IP 128.196.203.36 > 128.187.81.12, TCP, length 147, NDNLPv2 invalid packet: "
"TLV-LENGTH of sub-element of type 5 exceeds TLV-VALUE boundary of parent block\n";
BOOST_CHECK(output.is_equal(expected));
}
BOOST_AUTO_TEST_CASE(UnrecognizedLpField)
{
dump.wantTimestamp = false;
this->readFile("tests/dump/unrecognized-lp-field.pcap");
const std::string expected =
"IP 128.196.203.36 > 128.187.81.12, TCP, length 800, "
"NDNLPv2 invalid packet: unrecognized field 4 cannot be ignored\n";
BOOST_CHECK(output.is_equal(expected));
}
BOOST_AUTO_TEST_CASE(NoTimestamp)
{
dump.wantTimestamp = false;
lp::Packet lpPacket;
this->receive(lpPacket);
BOOST_CHECK(output.is_equal("Ethernet, NDNLPv2 idle\n"));
}
BOOST_AUTO_TEST_CASE(FromFile)
{
dump.pcapFilter = "";
this->readFile("tests/dump/nack.pcap");
const std::string expected =
"1571091605.129263 IP 127.0.0.1 > 127.0.0.1, TCP, length 36, "
"INTEREST: /producer/nack/no-route?Nonce=827bcac4\n"
"1571091605.129702 IP 127.0.0.1 > 127.0.0.1, TCP, length 49, "
"NDNLPv2, NACK (NoRoute): /producer/nack/no-route?Nonce=827bcac4\n";
BOOST_CHECK(output.is_equal(expected));
}
BOOST_AUTO_TEST_CASE(LinuxSllTcp4)
{
dump.wantTimestamp = false;
this->readFile("tests/dump/linux-sll-tcp4.pcap");
const std::string expected =
"IP 162.211.64.84 > 131.179.196.46, TCP, length 41, INTEREST: /ndn/edu/arizona/ping/8202?Nonce=cf062c3f\n"
"IP 131.179.196.46 > 162.211.64.84, TCP, length 403, DATA: /ndn/edu/arizona/ping/8202\n";
BOOST_CHECK(output.is_equal(expected));
}
BOOST_AUTO_TEST_CASE(LinuxSllUdp4)
{
dump.wantTimestamp = false;
this->readFile("tests/dump/linux-sll-udp4.pcap");
const std::string expected =
"IP 162.211.64.84 > 131.179.196.46, UDP, length 42, INTEREST: /ndn/edu/arizona/ping/31044?Nonce=f33c0bbd\n"
"IP 131.179.196.46 > 162.211.64.84, UDP, length 404, DATA: /ndn/edu/arizona/ping/31044\n";
BOOST_CHECK(output.is_equal(expected));
}
BOOST_AUTO_TEST_CASE(LinuxSllTcp6)
{
dump.wantTimestamp = false;
this->readFile("tests/dump/linux-sll-tcp6.pcap");
const std::string expected =
"IP6 2602:fff6:d:b317::39f8 > 2001:660:3302:282c:160::163, TCP, length 42, "
"INTEREST: /ndn/edu/arizona/ping/19573?Nonce=7b9e5b2e\n"
"IP6 2001:660:3302:282c:160::163 > 2602:fff6:d:b317::39f8, TCP, length 404, "
"DATA: /ndn/edu/arizona/ping/19573\n"
"IP6 2001:660:3302:282c:160::163 > 2602:fff6:d:b317::39f8, TCP, length 56, "
"invalid network packet: Unrecognized element of critical type 9\n";
BOOST_CHECK(output.is_equal(expected));
}
BOOST_AUTO_TEST_CASE(LinuxSllUdp6)
{
dump.wantTimestamp = false;
this->readFile("tests/dump/linux-sll-udp6.pcap");
const std::string expected =
"IP6 2602:fff6:d:b317::39f8 > 2001:660:3302:282c:160::163, UDP, length 39, "
"INTEREST: /ndn/edu/arizona/ping/18?Nonce=7e351222\n"
"IP6 2001:660:3302:282c:160::163 > 2602:fff6:d:b317::39f8, UDP, length 401, "
"DATA: /ndn/edu/arizona/ping/18\n"
"IP6 2001:660:3302:282c:160::163 > 2602:fff6:d:b317::39f8, UDP, length 56, "
"invalid network packet: Unrecognized element of critical type 9\n";
BOOST_CHECK(output.is_equal(expected));
}
BOOST_AUTO_TEST_SUITE_END() // TestNdnDump
BOOST_AUTO_TEST_SUITE_END() // Dump
} // namespace ndn::dump::tests
Binary file not shown.
@@ -1,58 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* @author Yingdi Yu <yingdi@cs.ucla.edu>
*/
#include "identity-management-time-fixture.hpp"
namespace ndn {
namespace tests {
IdentityManagementTimeFixture::IdentityManagementTimeFixture()
: m_keyChainTmpPath(boost::filesystem::path(TMP_TESTS_PATH) / "PibIdMgmtTimeTest")
, m_keyChain(std::string("pib-sqlite3:").append(m_keyChainTmpPath.string()),
std::string("tpm-file:").append(m_keyChainTmpPath.string()))
{
}
IdentityManagementTimeFixture::~IdentityManagementTimeFixture()
{
for (const auto& identity : m_identities) {
m_keyChain.deleteIdentity(identity);
}
boost::filesystem::remove_all(m_keyChainTmpPath);
}
bool
IdentityManagementTimeFixture::addIdentity(const Name& identity, const KeyParams& params)
{
try {
m_keyChain.createIdentity(identity, params);
m_identities.push_back(identity);
return true;
}
catch (std::runtime_error&) {
return false;
}
}
} // namespace tests
} // namespace ndn
@@ -1,61 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* @author Yingdi Yu <yingdi@cs.ucla.edu>
*/
#ifndef NDN_TOOLS_TESTS_IDENTITY_MANAGEMENT_TIME_FIXTURE_HPP
#define NDN_TOOLS_TESTS_IDENTITY_MANAGEMENT_TIME_FIXTURE_HPP
#include <ndn-cxx/security/key-chain.hpp>
#include <vector>
#include <boost/filesystem.hpp>
#include "tests/test-common.hpp"
namespace ndn {
namespace tests {
/**
* @brief IdentityManagementTimeFixture is a test suite level fixture.
* Test cases in the suite can use this fixture to create identities.
* Identities added via addIdentity method are automatically deleted
* during test teardown.
*/
class IdentityManagementTimeFixture : public tests::UnitTestTimeFixture
{
public:
IdentityManagementTimeFixture();
~IdentityManagementTimeFixture();
/// @brief add identity, return true if succeed.
bool
addIdentity(const Name& identity, const KeyParams& params = KeyChain::DEFAULT_KEY_PARAMS);
protected:
boost::filesystem::path m_keyChainTmpPath;
KeyChain m_keyChain;
std::vector<Name> m_identities;
};
} // namespace tests
} // namespace ndn
#endif // NDN_TOOLS_TESTS_IDENTITY_MANAGEMENT_TIME_FIXTURE_HPP
+53
View File
@@ -0,0 +1,53 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2023, 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 ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NDN_TOOLS_TESTS_IO_FIXTURE_HPP
#define NDN_TOOLS_TESTS_IO_FIXTURE_HPP
#include "tests/clock-fixture.hpp"
#include <boost/asio/io_context.hpp>
namespace ndn::tests {
class IoFixture : public ClockFixture
{
private:
void
afterTick() final
{
if (m_io.stopped()) {
m_io.restart();
}
m_io.poll();
}
protected:
boost::asio::io_context m_io;
};
} // namespace ndn::tests
#endif // NDN_TOOLS_TESTS_IO_FIXTURE_HPP
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California.
/*
* Copyright (c) 2013-2022 Regents of the University of California.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -17,25 +17,22 @@
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ndn-cxx/encoding/block.hpp>
#include <fstream>
#ifndef NDN_TOOLS_TESTS_KEY_CHAIN_FIXTURE_HPP
#define NDN_TOOLS_TESTS_KEY_CHAIN_FIXTURE_HPP
namespace ndn {
namespace dissect {
#include <ndn-cxx/security/key-chain.hpp>
class NdnDissect : noncopyable
namespace ndn::tests {
/**
* @brief A fixture providing an in-memory KeyChain.
*/
class KeyChainFixture
{
public:
void
dissect(std::ostream& os, std::istream& is);
private:
void
printType(std::ostream& os, uint32_t type);
void
printBlock(std::ostream& os, const Block& block);
protected:
ndn::KeyChain m_keyChain{"pib-memory:", "tpm-memory:"};
};
} // namespace dissect
} // namespace ndn
} // namespace ndn::tests
#endif // NDN_TOOLS_TESTS_KEY_CHAIN_FIXTURE_HPP
+4 -6
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
/*
* Copyright (c) 2014-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,7 +23,5 @@
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#define BOOST_TEST_MAIN 1
#define BOOST_TEST_DYN_LINK 1
#include "boost-test.hpp"
#define BOOST_TEST_MODULE ndn-tools
#include "tests/boost-test.hpp"
+320
View File
@@ -0,0 +1,320 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2023, Arizona Board of Regents.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tools/peek/ndnpeek/ndnpeek.hpp"
#include "tests/test-common.hpp"
#include "tests/io-fixture.hpp"
#include <ndn-cxx/util/dummy-client-face.hpp>
#include <boost/test/tools/output_test_stream.hpp>
namespace ndn::peek::tests {
using namespace ndn::tests;
using boost::test_tools::output_test_stream;
class CoutRedirector : noncopyable
{
public:
explicit
CoutRedirector(std::ostream& destination)
{
m_originalBuf = std::cout.rdbuf(destination.rdbuf());
}
~CoutRedirector()
{
std::cout.rdbuf(m_originalBuf);
}
private:
std::streambuf* m_originalBuf;
};
static PeekOptions
makeDefaultOptions()
{
PeekOptions opt;
opt.name = "/peek/test";
return opt;
}
class NdnPeekFixture : public IoFixture
{
protected:
void
initialize(const PeekOptions& opts = makeDefaultOptions())
{
peek = make_unique<NdnPeek>(face, opts);
}
protected:
DummyClientFace face{m_io};
output_test_stream output;
unique_ptr<NdnPeek> peek;
};
class OutputFull
{
public:
static PeekOptions
makeOptions()
{
return makeDefaultOptions();
}
static void
checkOutput(output_test_stream& output, const Data& data)
{
const Block& block = data.wireEncode();
std::string expected(reinterpret_cast<const char*>(block.data()), block.size());
BOOST_CHECK(output.is_equal(expected));
}
static void
checkOutput(output_test_stream& output, const lp::Nack& nack)
{
const Block& block = nack.getHeader().wireEncode();
std::string expected(reinterpret_cast<const char*>(block.data()), block.size());
BOOST_CHECK(output.is_equal(expected));
}
};
class OutputPayloadOnly
{
public:
static PeekOptions
makeOptions()
{
PeekOptions opt = makeDefaultOptions();
opt.wantPayloadOnly = true;
return opt;
}
static void
checkOutput(output_test_stream& output, const Data& data)
{
const Block& block = data.getContent();
std::string expected(reinterpret_cast<const char*>(block.value()), block.value_size());
BOOST_CHECK(output.is_equal(expected));
}
static void
checkOutput(output_test_stream& output, const lp::Nack& nack)
{
std::string expected = boost::lexical_cast<std::string>(nack.getReason()) + '\n';
BOOST_CHECK(output.is_equal(expected));
}
};
BOOST_AUTO_TEST_SUITE(Peek)
BOOST_FIXTURE_TEST_SUITE(TestNdnPeek, NdnPeekFixture)
using OutputChecks = std::tuple<OutputFull, OutputPayloadOnly>;
BOOST_AUTO_TEST_CASE_TEMPLATE(Default, OutputCheck, OutputChecks)
{
auto options = OutputCheck::makeOptions();
initialize(options);
auto data = makeData(options.name);
data->setContent({'n', 'd', 'n', 'p', 'e', 'e', 'k'});
{
CoutRedirector redir(output);
peek->start();
this->advanceClocks(25_ms, 4);
face.receive(*data);
}
OutputCheck::checkOutput(output, *data);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
const auto& interest = face.sentInterests.back();
BOOST_CHECK_EQUAL(interest.getCanBePrefix(), false);
BOOST_CHECK_EQUAL(interest.getMustBeFresh(), false);
BOOST_CHECK_EQUAL(interest.getForwardingHint().empty(), true);
BOOST_CHECK_EQUAL(interest.getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
BOOST_CHECK(interest.getHopLimit() == std::nullopt);
BOOST_CHECK(!interest.hasApplicationParameters());
BOOST_CHECK(peek->getResult() == NdnPeek::Result::DATA);
}
BOOST_AUTO_TEST_CASE_TEMPLATE(NonDefault, OutputCheck, OutputChecks)
{
auto options = OutputCheck::makeOptions();
options.canBePrefix = true;
options.mustBeFresh = true;
options.forwardingHint.emplace_back("/fh");
options.interestLifetime = 200_ms;
options.hopLimit = 64;
initialize(options);
auto data = makeData(Name(options.name).append("suffix"));
data->setFreshnessPeriod(1_s);
data->setContent({'n', 'd', 'n', 'p', 'e', 'e', 'k'});
{
CoutRedirector redir(output);
peek->start();
this->advanceClocks(25_ms, 4);
face.receive(*data);
}
OutputCheck::checkOutput(output, *data);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
const auto& interest = face.sentInterests.back();
BOOST_CHECK_EQUAL(interest.getCanBePrefix(), true);
BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
BOOST_TEST(interest.getForwardingHint() == std::vector<Name>({"/fh"}),
boost::test_tools::per_element());
BOOST_CHECK_EQUAL(interest.getInterestLifetime(), 200_ms);
BOOST_CHECK(interest.getHopLimit() == 64);
BOOST_CHECK(!interest.hasApplicationParameters());
BOOST_CHECK(peek->getResult() == NdnPeek::Result::DATA);
}
BOOST_AUTO_TEST_CASE_TEMPLATE(ReceiveNackWithReason, OutputCheck, OutputChecks)
{
auto options = OutputCheck::makeOptions();
initialize(options);
lp::Nack nack;
{
CoutRedirector redir(output);
peek->start();
this->advanceClocks(25_ms, 4);
nack = makeNack(face.sentInterests.at(0), lp::NackReason::NO_ROUTE);
face.receive(nack);
}
OutputCheck::checkOutput(output, nack);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
BOOST_CHECK(peek->getResult() == NdnPeek::Result::NACK);
}
BOOST_AUTO_TEST_CASE_TEMPLATE(ReceiveNackWithoutReason, OutputCheck, OutputChecks)
{
auto options = OutputCheck::makeOptions();
initialize(options);
lp::Nack nack;
{
CoutRedirector redir(output);
peek->start();
this->advanceClocks(25_ms, 4);
nack = makeNack(face.sentInterests.at(0), lp::NackReason::NONE);
face.receive(nack);
}
OutputCheck::checkOutput(output, nack);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
BOOST_CHECK(peek->getResult() == NdnPeek::Result::NACK);
}
BOOST_AUTO_TEST_CASE(ApplicationParameters)
{
auto options = makeDefaultOptions();
options.applicationParameters = make_shared<Buffer>("hello", 5);
initialize(options);
peek->start();
this->advanceClocks(25_ms, 4);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
BOOST_CHECK_EQUAL(face.sentInterests.back().getCanBePrefix(), false);
BOOST_CHECK_EQUAL(face.sentInterests.back().getMustBeFresh(), false);
BOOST_CHECK_EQUAL(face.sentInterests.back().getForwardingHint().empty(), true);
BOOST_CHECK_EQUAL(face.sentInterests.back().getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
BOOST_CHECK_EQUAL(face.sentInterests.back().hasApplicationParameters(), true);
BOOST_CHECK_EQUAL(face.sentInterests.back().getApplicationParameters(), "2405 68656C6C6F"_block);
}
BOOST_AUTO_TEST_CASE(NoTimeout)
{
auto options = makeDefaultOptions();
options.interestLifetime = 1_s;
options.timeout = std::nullopt;
initialize(options);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
peek->start();
this->advanceClocks(100_ms, 9);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 1);
BOOST_CHECK(peek->getResult() == NdnPeek::Result::UNKNOWN);
this->advanceClocks(100_ms, 2);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
BOOST_CHECK(peek->getResult() == NdnPeek::Result::TIMEOUT);
}
BOOST_AUTO_TEST_CASE(TimeoutLessThanLifetime)
{
auto options = makeDefaultOptions();
options.interestLifetime = 200_ms;
options.timeout = 100_ms;
initialize(options);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
peek->start();
this->advanceClocks(25_ms, 6);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
BOOST_CHECK(peek->getResult() == NdnPeek::Result::TIMEOUT);
}
BOOST_AUTO_TEST_CASE(TimeoutGreaterThanLifetime)
{
auto options = makeDefaultOptions();
options.interestLifetime = 50_ms;
options.timeout = 200_ms;
initialize(options);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
peek->start();
this->advanceClocks(25_ms, 4);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
BOOST_CHECK(peek->getResult() == NdnPeek::Result::TIMEOUT);
}
BOOST_AUTO_TEST_CASE(OversizedPacket)
{
auto options = makeDefaultOptions();
options.applicationParameters = make_shared<Buffer>(MAX_NDN_PACKET_SIZE);
initialize(options);
peek->start();
BOOST_CHECK_THROW(this->advanceClocks(1_ms, 10), Face::OversizedPacketError);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
}
BOOST_AUTO_TEST_SUITE_END() // TestNdnPeek
BOOST_AUTO_TEST_SUITE_END() // Peek
} // namespace ndn::peek::tests
+257
View File
@@ -0,0 +1,257 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2023, 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 ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tools/peek/ndnpoke/ndnpoke.hpp"
#include "tests/test-common.hpp"
#include "tests/io-fixture.hpp"
#include "tests/key-chain-fixture.hpp"
#include <ndn-cxx/util/dummy-client-face.hpp>
namespace ndn::peek::tests {
using namespace ndn::tests;
template<bool WANT_PREFIX_REG_REPLY = true>
class NdnPokeFixture : public IoFixture, public KeyChainFixture
{
protected:
NdnPokeFixture()
{
m_keyChain.createIdentity("/test-id");
}
void
initialize(const PokeOptions& opts = makeDefaultOptions())
{
poke = make_unique<NdnPoke>(face, m_keyChain, payload, opts);
}
static PokeOptions
makeDefaultOptions()
{
PokeOptions opt;
opt.name = "/poke/test";
return opt;
}
protected:
DummyClientFace face{m_io, m_keyChain, {true, WANT_PREFIX_REG_REPLY}};
std::stringstream payload{"Hello, world!\n"};
unique_ptr<NdnPoke> poke;
};
BOOST_AUTO_TEST_SUITE(Peek)
BOOST_FIXTURE_TEST_SUITE(TestNdnPoke, NdnPokeFixture<>)
BOOST_AUTO_TEST_CASE(Basic)
{
initialize();
poke->start();
this->advanceClocks(1_ms, 10);
// Check for prefix registration
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
BOOST_CHECK_EQUAL(face.sentInterests.front().getName().getPrefix(4), "/localhost/nfd/rib/register");
face.receive(*makeInterest("/poke/test"));
this->advanceClocks(1_ms, 10);
BOOST_CHECK(poke->getResult() == NdnPoke::Result::DATA_SENT);
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
BOOST_CHECK_EQUAL(face.sentData.back().getName(), "/poke/test");
BOOST_CHECK(!face.sentData.back().getFinalBlock());
BOOST_CHECK_EQUAL(face.sentData.back().getFreshnessPeriod(), 0_ms);
BOOST_CHECK_EQUAL(face.sentData.back().getContentType(), tlv::ContentType_Blob);
BOOST_CHECK_EQUAL(face.sentData.back().getContent(), "150E48656C6C6F2C20776F726C64210A"_block);
BOOST_CHECK_EQUAL(face.sentData.back().getSignatureType(), tlv::SignatureSha256WithEcdsa);
// Check for prefix unregistration
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 2); // One for registration, one for unregistration
BOOST_CHECK_EQUAL(face.sentInterests.back().getName().getPrefix(4), "/localhost/nfd/rib/unregister");
}
BOOST_AUTO_TEST_CASE(NoMatch)
{
initialize();
poke->start();
this->advanceClocks(1_ms, 10);
face.receive(*makeInterest("/poke/test/foo"));
this->advanceClocks(1_ms, 10);
BOOST_CHECK(poke->getResult() == NdnPoke::Result::UNKNOWN);
BOOST_CHECK_EQUAL(face.sentData.size(), 0);
face.receive(*makeInterest("/poke/test"));
this->advanceClocks(1_ms, 10);
BOOST_CHECK(poke->getResult() == NdnPoke::Result::DATA_SENT);
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
BOOST_CHECK_EQUAL(face.sentData.back().getName(), "/poke/test");
}
BOOST_AUTO_TEST_CASE(FreshnessPeriod)
{
auto options = makeDefaultOptions();
options.freshnessPeriod = 1_s;
initialize(options);
poke->start();
this->advanceClocks(1_ms, 10);
face.receive(*makeInterest("/poke/test"));
this->advanceClocks(1_ms, 10);
BOOST_CHECK(poke->getResult() == NdnPoke::Result::DATA_SENT);
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
BOOST_CHECK_EQUAL(face.sentData.back().getName(), "/poke/test");
BOOST_CHECK(!face.sentData.back().getFinalBlock());
BOOST_CHECK_EQUAL(face.sentData.back().getFreshnessPeriod(), 1_s);
BOOST_CHECK_EQUAL(face.sentData.back().getSignatureType(), tlv::SignatureSha256WithEcdsa);
}
BOOST_AUTO_TEST_CASE(FinalBlockId)
{
auto options = makeDefaultOptions();
options.name = "/poke/test/123";
options.wantFinalBlockId = true;
initialize(options);
poke->start();
this->advanceClocks(1_ms, 10);
face.receive(*makeInterest(options.name));
this->advanceClocks(1_ms, 10);
BOOST_CHECK(poke->getResult() == NdnPoke::Result::DATA_SENT);
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
BOOST_CHECK_EQUAL(face.sentData.back().getName(), options.name);
BOOST_REQUIRE(face.sentData.back().getFinalBlock());
BOOST_CHECK_EQUAL(*(face.sentData.back().getFinalBlock()), name::Component("123"));
BOOST_CHECK_EQUAL(face.sentData.back().getFreshnessPeriod(), 0_ms);
BOOST_CHECK_EQUAL(face.sentData.back().getSignatureType(), tlv::SignatureSha256WithEcdsa);
}
BOOST_AUTO_TEST_CASE(DigestSha256)
{
auto options = makeDefaultOptions();
options.signingInfo.setSha256Signing();
initialize(options);
poke->start();
this->advanceClocks(1_ms, 10);
face.receive(*makeInterest("/poke/test"));
this->advanceClocks(1_ms, 10);
BOOST_CHECK(poke->getResult() == NdnPoke::Result::DATA_SENT);
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
BOOST_CHECK_EQUAL(face.sentData.back().getName(), "/poke/test");
BOOST_CHECK(!face.sentData.back().getFinalBlock());
BOOST_CHECK_EQUAL(face.sentData.back().getFreshnessPeriod(), 0_ms);
BOOST_CHECK_EQUAL(face.sentData.back().getSignatureType(), tlv::DigestSha256);
}
BOOST_AUTO_TEST_CASE(Unsolicited)
{
auto options = makeDefaultOptions();
options.wantUnsolicited = true;
initialize(options);
poke->start();
this->advanceClocks(1_ms, 10);
BOOST_CHECK(poke->getResult() == NdnPoke::Result::DATA_SENT);
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
BOOST_CHECK_EQUAL(face.sentData.back().getName(), "/poke/test");
BOOST_CHECK(!face.sentData.back().getFinalBlock());
BOOST_CHECK_EQUAL(face.sentData.back().getFreshnessPeriod(), 0_ms);
BOOST_CHECK_EQUAL(face.sentData.back().getSignatureType(), tlv::SignatureSha256WithEcdsa);
}
BOOST_AUTO_TEST_CASE(Timeout)
{
auto options = makeDefaultOptions();
options.timeout = 4_s;
initialize(options);
poke->start();
this->advanceClocks(1_ms, 10);
// Check for prefix registration
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
BOOST_CHECK_EQUAL(face.sentInterests.front().getName().getPrefix(4), "/localhost/nfd/rib/register");
this->advanceClocks(1_s, 4);
BOOST_CHECK(poke->getResult() == NdnPoke::Result::TIMEOUT);
BOOST_CHECK_EQUAL(face.sentData.size(), 0);
// Check for prefix unregistration
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 2); // One for registration, one for unregistration
BOOST_CHECK_EQUAL(face.sentInterests.back().getName().getPrefix(4), "/localhost/nfd/rib/unregister");
}
BOOST_FIXTURE_TEST_CASE(PrefixRegTimeout, NdnPokeFixture<false>)
{
initialize();
poke->start();
this->advanceClocks(1_ms, 10);
// Check for prefix registration
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
BOOST_CHECK_EQUAL(face.sentInterests.front().getName().getPrefix(4), "/localhost/nfd/rib/register");
this->advanceClocks(1_s, 10);
BOOST_CHECK(poke->getResult() == NdnPoke::Result::PREFIX_REG_FAIL);
BOOST_CHECK_EQUAL(face.sentData.size(), 0);
}
BOOST_AUTO_TEST_CASE(OversizedPacket)
{
payload << std::string(MAX_NDN_PACKET_SIZE, 'A');
initialize();
poke->start();
this->advanceClocks(1_ms, 10);
face.receive(*makeInterest("/poke/test"));
BOOST_CHECK_THROW(face.processEvents(), Face::OversizedPacketError);
// No point in checking getResult() here. The exception is thrown from processEvents(),
// not from put(), so the result is still DATA_SENT even though no packets were sent.
BOOST_CHECK_EQUAL(face.sentData.size(), 0);
}
BOOST_AUTO_TEST_SUITE_END() // TestNdnPoke
BOOST_AUTO_TEST_SUITE_END() // Peek
} // namespace ndn::peek::tests
-132
View File
@@ -1,132 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* @author Yingdi Yu <yingdi@cs.ucla.edu>
*/
#include "tools/pib/cert-publisher.hpp"
#include "../identity-management-time-fixture.hpp"
#include <ndn-cxx/util/dummy-client-face.hpp>
#include <boost/filesystem.hpp>
#include "tests/test-common.hpp"
namespace ndn {
namespace pib {
namespace tests {
class CertPublisherFixture : public ndn::tests::IdentityManagementTimeFixture
{
public:
CertPublisherFixture()
: tmpPath(boost::filesystem::path(TMP_TESTS_PATH) / "DbTest")
, db(tmpPath.c_str())
, face(util::makeDummyClientFace(io, {true, true}))
{
}
~CertPublisherFixture()
{
boost::filesystem::remove_all(tmpPath);
}
boost::asio::io_service io;
boost::filesystem::path tmpPath;
PibDb db;
shared_ptr<util::DummyClientFace> face;
};
BOOST_FIXTURE_TEST_SUITE(PibCertPublisher, CertPublisherFixture)
BOOST_AUTO_TEST_CASE(Basic)
{
// Initialize id1
Name id1("/test/identity");
addIdentity(id1);
Name certName111 = m_keyChain.getDefaultCertificateNameForIdentity(id1);
shared_ptr<IdentityCertificate> cert111 = m_keyChain.getCertificate(certName111);
Name keyName11 = cert111->getPublicKeyName();
advanceClocks(io, time::milliseconds(100));
shared_ptr<IdentityCertificate> cert112 = m_keyChain.selfSign(keyName11);
Name certName112 = cert112->getName();
CertPublisher certPublisher(*face, db);
// Add a certificate
db.addCertificate(*cert111);
advanceClocks(io, time::milliseconds(2), 50);
BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 0);
auto interest111 = make_shared<Interest>(cert111->getName().getPrefix(-1));
face->receive(*interest111);
advanceClocks(io, time::milliseconds(2), 50);
BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
BOOST_CHECK(face->sentDatas[0].wireEncode() == cert111->wireEncode());
face->sentDatas.clear();
// Add another certificate
db.addCertificate(*cert112);
advanceClocks(io, time::milliseconds(2), 50);
BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 0);
auto interest112 = make_shared<Interest>(cert112->getName().getPrefix(-1));
face->receive(*interest112);
advanceClocks(io, time::milliseconds(2), 50);
BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
BOOST_CHECK(face->sentDatas[0].wireEncode() == cert111->wireEncode());
face->sentDatas.clear();
Exclude exclude;
exclude.excludeOne(cert111->getName().get(-1));
interest112->setExclude(exclude);
face->receive(*interest112);
advanceClocks(io, time::milliseconds(2), 50);
BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
BOOST_CHECK(face->sentDatas[0].wireEncode() == cert112->wireEncode());
face->sentDatas.clear();
// delete a certificate
db.deleteCertificate(certName112);
face->receive(*interest112);
advanceClocks(io, time::milliseconds(2), 50);
BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 0);
face->receive(*interest111);
advanceClocks(io, time::milliseconds(2), 50);
BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
BOOST_CHECK(face->sentDatas[0].wireEncode() == cert111->wireEncode());
face->sentDatas.clear();
// delete another certificate
db.deleteCertificate(certName111);
face->receive(*interest112);
advanceClocks(io, time::milliseconds(2), 50);
BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 0);
face->receive(*interest111);
advanceClocks(io, time::milliseconds(2), 50);
BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 0);
}
BOOST_AUTO_TEST_SUITE_END()
} // namespace tests
} // namespace pib
} // namespace ndn
-75
View File
@@ -1,75 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* @author Yingdi Yu <yingdi@cs.ucla.edu>
*/
#include "tools/pib/key-cache.hpp"
#include "tests/test-common.hpp"
namespace ndn {
namespace pib {
namespace tests {
BOOST_AUTO_TEST_SUITE(PibKeyCache)
BOOST_AUTO_TEST_CASE(Basic)
{
KeyCache keyCache(3);
Name name1("/1");
Name name2("/2");
Name name3("/3");
Name name4("/4");
auto key1 = make_shared<PublicKey>();
auto key2 = make_shared<PublicKey>();
auto key3 = make_shared<PublicKey>();
auto key4 = make_shared<PublicKey>();
keyCache.insert(name1, key1);
keyCache.insert(name2, key2);
keyCache.insert(name3, key3);
BOOST_CHECK_EQUAL(keyCache.size(), 3);
BOOST_CHECK(static_cast<bool>(keyCache.find(name1)));
BOOST_CHECK(static_cast<bool>(keyCache.find(name2)));
BOOST_CHECK(static_cast<bool>(keyCache.find(name3)));
BOOST_CHECK(!static_cast<bool>(keyCache.find(name4)));
keyCache.insert(name1, key1);
keyCache.insert(name4, key4);
BOOST_CHECK_EQUAL(keyCache.size(), 3);
BOOST_CHECK(static_cast<bool>(keyCache.find(name1)));
BOOST_CHECK(!static_cast<bool>(keyCache.find(name2)));
BOOST_CHECK(static_cast<bool>(keyCache.find(name3)));
BOOST_CHECK(static_cast<bool>(keyCache.find(name4)));
keyCache.erase(name1);
BOOST_CHECK_EQUAL(keyCache.size(), 2);
BOOST_CHECK(!static_cast<bool>(keyCache.find(name1)));
BOOST_CHECK(static_cast<bool>(keyCache.find(name3)));
BOOST_CHECK(static_cast<bool>(keyCache.find(name4)));
}
BOOST_AUTO_TEST_SUITE_END()
} // namespace tests
} // namespace pib
} // namespace ndn
-474
View File
@@ -1,474 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* @author Yingdi Yu <yingdi@cs.ucla.edu>
*/
#include "tools/pib/pib-db.hpp"
#include "../identity-management-time-fixture.hpp"
#include <boost/filesystem.hpp>
#include "tests/test-common.hpp"
namespace ndn {
namespace pib {
namespace tests {
class PibDbTestFixture : public ndn::tests::IdentityManagementTimeFixture
{
public:
PibDbTestFixture()
: tmpPath(boost::filesystem::path(TMP_TESTS_PATH) / "DbTest")
, db(tmpPath.c_str())
{
}
~PibDbTestFixture()
{
boost::filesystem::remove_all(tmpPath);
}
boost::asio::io_service io;
boost::filesystem::path tmpPath;
PibDb db;
std::vector<Name> deletedIds;
std::vector<Name> deletedKeys;
std::vector<Name> deletedCerts;
std::vector<Name> insertedCerts;
};
BOOST_FIXTURE_TEST_SUITE(PibPibDb, PibDbTestFixture)
BOOST_AUTO_TEST_CASE(MgmtTest)
{
Name testUser("/localhost/pib/test/mgmt");
addIdentity(testUser);
Name testUserCertName = m_keyChain.getDefaultCertificateNameForIdentity(testUser);
shared_ptr<IdentityCertificate> testUserCert = m_keyChain.getCertificate(testUserCertName);
BOOST_CHECK_EQUAL(db.getOwnerName(), "");
BOOST_CHECK(db.getMgmtCertificate() == nullptr);
db.updateMgmtCertificate(*testUserCert);
BOOST_CHECK_EQUAL(db.getOwnerName(), "test");
BOOST_REQUIRE(db.getMgmtCertificate() != nullptr);
BOOST_CHECK_EQUAL(db.getMgmtCertificate()->getName(), testUserCertName);
db.setTpmLocator("tpmLocator");
BOOST_CHECK_EQUAL(db.getTpmLocator(), "tpmLocator");
Name testUser2("/localhost/pib/test2/mgmt");
addIdentity(testUser2);
Name testUser2CertName = m_keyChain.getDefaultCertificateNameForIdentity(testUser2);
shared_ptr<IdentityCertificate> testUser2Cert = m_keyChain.getCertificate(testUser2CertName);
BOOST_CHECK_THROW(db.updateMgmtCertificate(*testUser2Cert), PibDb::Error);
Name testUserKeyName2 = m_keyChain.generateRsaKeyPairAsDefault(testUser);
shared_ptr<IdentityCertificate> testUserCert2 = m_keyChain.selfSign(testUserKeyName2);
BOOST_CHECK_NO_THROW(db.updateMgmtCertificate(*testUserCert2));
BOOST_REQUIRE(db.getMgmtCertificate() != nullptr);
BOOST_CHECK_EQUAL(db.getMgmtCertificate()->getName(),
testUserCert2->getName());
}
BOOST_AUTO_TEST_CASE(IdentityTest)
{
db.identityDeleted.connect([this] (const Name& id) {
this->deletedIds.push_back(id);
});
Name identity("/test/identity");
Name identity2("/test/identity2");
// Add an identity: /test/identity
// Since there is no default identity,
// the new added identity will be set as the default identity.
BOOST_CHECK_EQUAL(db.getDefaultIdentity(), PibDb::NON_EXISTING_IDENTITY);
db.addIdentity(identity);
BOOST_CHECK(db.hasIdentity(identity));
BOOST_CHECK_EQUAL(db.getDefaultIdentity(), identity);
// Add the second identity: /test/identity2
// Since the default identity exists,
// the new added identity will not be set as the default identity.
db.addIdentity(identity2);
BOOST_CHECK_EQUAL(db.hasIdentity(identity2), true);
BOOST_CHECK_EQUAL(db.getDefaultIdentity(), identity);
// Set the second identity: /test/identity2 as default explicitly
db.setDefaultIdentity(identity2);
BOOST_CHECK_EQUAL(db.getDefaultIdentity(), identity2);
// Delete identity /test/identity2, which is also the default one
// This will trigger the identityDeleted signal
// and also causes no default identity.
db.deleteIdentity(identity2);
BOOST_CHECK_EQUAL(db.hasIdentity(identity2), false);
BOOST_CHECK_EQUAL(db.hasIdentity(identity), true);
BOOST_CHECK_EQUAL(deletedIds.size(), 1);
BOOST_CHECK_EQUAL(deletedIds[0], identity2);
BOOST_CHECK_EQUAL(db.getDefaultIdentity(), PibDb::NON_EXISTING_IDENTITY);
deletedIds.clear();
// Add the second identity back
// Since there is no default identity (though another identity still exists),
// the second identity will be set as default.
db.addIdentity(identity2);
BOOST_CHECK_EQUAL(db.hasIdentity(identity2), true);
BOOST_CHECK_EQUAL(db.getDefaultIdentity(), identity2);
// Delete identity /test/identity
db.deleteIdentity(identity);
BOOST_CHECK_EQUAL(db.hasIdentity(identity), false);
BOOST_CHECK_EQUAL(db.hasIdentity(identity2), true);
BOOST_CHECK_EQUAL(deletedIds.size(), 1);
BOOST_CHECK_EQUAL(deletedIds[0], identity);
deletedIds.clear();
// Delete identity /test/identity2
db.deleteIdentity(identity2);
BOOST_CHECK_EQUAL(db.hasIdentity(identity), false);
BOOST_CHECK_EQUAL(db.hasIdentity(identity2), false);
BOOST_CHECK_EQUAL(deletedIds.size(), 1);
BOOST_CHECK_EQUAL(deletedIds[0], identity2);
deletedIds.clear();
}
BOOST_AUTO_TEST_CASE(KeyTest)
{
db.identityDeleted.connect([this] (const Name& id) {
this->deletedIds.push_back(id);
});
db.keyDeleted.connect([this] (const Name& key) {
this->deletedKeys.push_back(key);
});
// Initialize id1
Name id1("/test/identity");
addIdentity(id1);
Name certName111 = m_keyChain.getDefaultCertificateNameForIdentity(id1);
shared_ptr<IdentityCertificate> cert111 = m_keyChain.getCertificate(certName111);
Name keyName11 = cert111->getPublicKeyName();
PublicKey& key11 = cert111->getPublicKeyInfo();
advanceClocks(io, time::milliseconds(100));
Name keyName12 = m_keyChain.generateRsaKeyPairAsDefault(id1);
shared_ptr<IdentityCertificate> cert121 = m_keyChain.selfSign(keyName12);
PublicKey& key12 = cert121->getPublicKeyInfo();
// Initialize id2
advanceClocks(io, time::milliseconds(100));
Name id2("/test/identity2");
addIdentity(id2);
Name certName211 = m_keyChain.getDefaultCertificateNameForIdentity(id2);
shared_ptr<IdentityCertificate> cert211 = m_keyChain.getCertificate(certName211);
Name keyName21 = cert211->getPublicKeyName();
PublicKey& key21 = cert211->getPublicKeyInfo();
advanceClocks(io, time::milliseconds(100));
Name keyName22 = m_keyChain.generateRsaKeyPairAsDefault(id2);
shared_ptr<IdentityCertificate> cert221 = m_keyChain.selfSign(keyName22);
PublicKey& key22 = cert221->getPublicKeyInfo();
// Add a key, the corresponding identity should be added as well
// Since the PIB does not have any default identity set before,
// the added identity will be set as default.
// Since there is no default key for the identity,
// the added key will be set as default.
BOOST_CHECK_EQUAL(db.getDefaultKeyNameOfIdentity(id1), PibDb::NON_EXISTING_KEY);
BOOST_CHECK(db.getKey(keyName11) == nullptr);
db.addKey(keyName11, key11);
BOOST_CHECK(db.hasIdentity(id1));
BOOST_CHECK(db.getKey(keyName11) != nullptr);
BOOST_CHECK_EQUAL(db.getDefaultIdentity(), id1);
BOOST_CHECK_EQUAL(db.getDefaultKeyNameOfIdentity(id1), keyName11);
// Add the second key of /test/identity.
// Since the default key of /test/identity has been set,
// The new added key will not be set as default.
db.addKey(keyName12, key12);
BOOST_CHECK(db.getKey(keyName12) != nullptr);
BOOST_CHECK_EQUAL(db.getDefaultKeyNameOfIdentity(id1), keyName11);
// Explicitly set the second key as the default key of /test/identity
db.setDefaultKeyNameOfIdentity(keyName12);
BOOST_CHECK_EQUAL(db.getDefaultKeyNameOfIdentity(id1), keyName12);
// Delete the second key which is also the default key.
// This will trigger the keyDeleted signal.
// This will also cause no default key for /test/identity
db.deleteKey(keyName12);
BOOST_CHECK_EQUAL(db.hasKey(keyName12), false);
BOOST_CHECK_EQUAL(db.hasKey(keyName11), true);
BOOST_CHECK_EQUAL(db.hasKey(keyName22), false);
BOOST_CHECK_EQUAL(db.hasKey(keyName21), false);
BOOST_CHECK_EQUAL(deletedKeys.size(), 1);
BOOST_CHECK_EQUAL(deletedKeys[0], keyName12);
deletedKeys.clear();
// Add the second key back.
// Since there is no default key of /test/identity (although another key still exists)
// The second key will be set as the default key of /test/identity
BOOST_CHECK_EQUAL(db.getDefaultKeyNameOfIdentity(id1), PibDb::NON_EXISTING_KEY);
db.addKey(keyName12, key12);
BOOST_CHECK_EQUAL(db.getDefaultKeyNameOfIdentity(id1), keyName12);
// Prepare test for identity deletion
db.addKey(keyName21, key21);
db.addKey(keyName22, key22);
BOOST_CHECK_EQUAL(db.hasKey(keyName12), true);
BOOST_CHECK_EQUAL(db.hasKey(keyName22), true);
BOOST_CHECK_EQUAL(db.hasKey(keyName21), true);
BOOST_CHECK_EQUAL(db.hasIdentity(id2), true);
// Delete the identity.
// All keys of the identity should also be deleted,
// and the keyDeleted signal should be triggered twice.
db.deleteIdentity(id1);
BOOST_CHECK_EQUAL(db.hasIdentity(id1), false);
BOOST_CHECK_EQUAL(db.hasIdentity(id2), true);
BOOST_CHECK_EQUAL(db.hasKey(keyName11), false);
BOOST_CHECK_EQUAL(db.hasKey(keyName12), false);
BOOST_CHECK_EQUAL(db.hasKey(keyName21), true);
BOOST_CHECK_EQUAL(db.hasKey(keyName22), true);
BOOST_CHECK_EQUAL(deletedKeys.size(), 2);
BOOST_CHECK(std::find(deletedKeys.begin(), deletedKeys.end(), keyName11) !=
deletedKeys.end());
BOOST_CHECK(std::find(deletedKeys.begin(), deletedKeys.end(), keyName12) !=
deletedKeys.end());
BOOST_CHECK_EQUAL(deletedIds.size(), 1);
BOOST_CHECK_EQUAL(deletedIds[0], id1);
}
BOOST_AUTO_TEST_CASE(CertTest)
{
db.identityDeleted.connect([this] (const Name& id) {
this->deletedIds.push_back(id);
});
db.keyDeleted.connect([this] (const Name& key) {
this->deletedKeys.push_back(key);
});
db.certificateDeleted.connect([this] (const Name& certificate) {
this->deletedCerts.push_back(certificate);
});
db.certificateInserted.connect([this] (const Name& certificate) {
this->insertedCerts.push_back(certificate);
});
// Initialize id1
Name id1("/test/identity");
addIdentity(id1);
Name certName111 = m_keyChain.getDefaultCertificateNameForIdentity(id1);
shared_ptr<IdentityCertificate> cert111 = m_keyChain.getCertificate(certName111);
Name keyName11 = cert111->getPublicKeyName();
advanceClocks(io, time::milliseconds(100));
shared_ptr<IdentityCertificate> cert112 = m_keyChain.selfSign(keyName11);
Name certName112 = cert112->getName();
advanceClocks(io, time::milliseconds(100));
Name keyName12 = m_keyChain.generateRsaKeyPairAsDefault(id1);
shared_ptr<IdentityCertificate> cert121 = m_keyChain.selfSign(keyName12);
Name certName121 = cert121->getName();
advanceClocks(io, time::milliseconds(100));
shared_ptr<IdentityCertificate> cert122 = m_keyChain.selfSign(keyName12);
Name certName122 = cert122->getName();
// Initialize id2
advanceClocks(io, time::milliseconds(100));
Name id2("/test/identity2");
addIdentity(id2);
Name certName211 = m_keyChain.getDefaultCertificateNameForIdentity(id2);
shared_ptr<IdentityCertificate> cert211 = m_keyChain.getCertificate(certName211);
Name keyName21 = cert211->getPublicKeyName();
advanceClocks(io, time::milliseconds(100));
shared_ptr<IdentityCertificate> cert212 = m_keyChain.selfSign(keyName21);
Name certName212 = cert212->getName();
advanceClocks(io, time::milliseconds(100));
Name keyName22 = m_keyChain.generateRsaKeyPairAsDefault(id2);
shared_ptr<IdentityCertificate> cert221 = m_keyChain.selfSign(keyName22);
Name certName221 = cert221->getName();
advanceClocks(io, time::milliseconds(100));
shared_ptr<IdentityCertificate> cert222 = m_keyChain.selfSign(keyName22);
Name certName222 = cert222->getName();
// Add a certificate
// This will also add the corresponding key and identity.
// Since there is no default setting before,
// The certificate will be set as the default one of the key, and so be the key and identity
BOOST_CHECK_EQUAL(db.hasCertificate(certName111), false);
BOOST_CHECK_EQUAL(db.hasKey(keyName11), false);
BOOST_CHECK_EQUAL(db.hasIdentity(id1), false);
BOOST_CHECK_EQUAL(db.getDefaultCertNameOfKey(keyName11), PibDb::NON_EXISTING_CERTIFICATE);
db.addCertificate(*cert111);
BOOST_CHECK_EQUAL(db.hasCertificate(certName111), true);
BOOST_CHECK_EQUAL(db.hasKey(keyName11), true);
BOOST_CHECK_EQUAL(db.hasIdentity(id1), true);
BOOST_CHECK_EQUAL(db.getDefaultIdentity(), id1);
BOOST_CHECK_EQUAL(db.getDefaultKeyNameOfIdentity(id1), keyName11);
BOOST_CHECK_EQUAL(db.getDefaultCertNameOfKey(keyName11), certName111);
BOOST_CHECK_EQUAL(insertedCerts.size(), 1);
BOOST_CHECK(std::find(insertedCerts.begin(), insertedCerts.end(), certName111) !=
insertedCerts.end());
insertedCerts.clear();
// Add the second certificate of the same key
// Since default certificate already exists, no default setting changes.
BOOST_CHECK(db.getCertificate(certName112) == nullptr);
db.addCertificate(*cert112);
BOOST_CHECK(db.getCertificate(certName112) != nullptr);
BOOST_CHECK_EQUAL(db.getDefaultCertNameOfKey(keyName11), certName111);
BOOST_CHECK_EQUAL(insertedCerts.size(), 1);
BOOST_CHECK(std::find(insertedCerts.begin(), insertedCerts.end(), certName112) !=
insertedCerts.end());
insertedCerts.clear();
// Explicitly set the second certificate as the default one of the key.
db.setDefaultCertNameOfKey(certName112);
BOOST_CHECK_EQUAL(db.getDefaultCertNameOfKey(keyName11), certName112);
// Delete the default certificate
// This will trigger certificateDeleted signal
// and also causes no default certificate for the key.
db.deleteCertificate(certName112);
BOOST_CHECK_EQUAL(db.hasCertificate(certName112), false);
BOOST_CHECK_EQUAL(db.hasCertificate(certName111), true);
BOOST_CHECK_EQUAL(deletedCerts.size(), 1);
BOOST_CHECK_EQUAL(deletedCerts[0], certName112);
BOOST_CHECK_EQUAL(db.getDefaultCertNameOfKey(keyName11), PibDb::NON_EXISTING_CERTIFICATE);
deletedCerts.clear();
// Add the second certificate back
// Since there is no default certificate of the key (though another certificate still exists),
// the new added certificate will be set as default
db.addCertificate(*cert112);
BOOST_CHECK(db.getCertificate(certName112) != nullptr);
BOOST_CHECK_EQUAL(db.getDefaultCertNameOfKey(keyName11), certName112);
insertedCerts.clear();
// Add entries for delete tests
db.addCertificate(*cert111); // already exists no certInserted signal emitted
db.addCertificate(*cert112); // already exists no certInserted signal emitted
db.addCertificate(*cert121);
db.addCertificate(*cert122);
db.addCertificate(*cert211);
db.addCertificate(*cert212);
db.addCertificate(*cert221);
db.addCertificate(*cert222);
BOOST_CHECK_EQUAL(insertedCerts.size(), 6);
BOOST_CHECK(std::find(insertedCerts.begin(), insertedCerts.end(), certName121) !=
insertedCerts.end());
BOOST_CHECK(std::find(insertedCerts.begin(), insertedCerts.end(), certName122) !=
insertedCerts.end());
BOOST_CHECK(std::find(insertedCerts.begin(), insertedCerts.end(), certName211) !=
insertedCerts.end());
BOOST_CHECK(std::find(insertedCerts.begin(), insertedCerts.end(), certName212) !=
insertedCerts.end());
BOOST_CHECK(std::find(insertedCerts.begin(), insertedCerts.end(), certName221) !=
insertedCerts.end());
BOOST_CHECK(std::find(insertedCerts.begin(), insertedCerts.end(), certName222) !=
insertedCerts.end());
insertedCerts.clear();
// Delete the key.
// All the related certificates will be deleted as well.
db.deleteKey(keyName11);
BOOST_CHECK_EQUAL(db.hasCertificate(certName112), false);
BOOST_CHECK_EQUAL(db.hasCertificate(certName111), false);
BOOST_CHECK_EQUAL(db.hasCertificate(certName122), true);
BOOST_CHECK_EQUAL(db.hasCertificate(certName121), true);
BOOST_CHECK_EQUAL(db.hasCertificate(certName212), true);
BOOST_CHECK_EQUAL(db.hasCertificate(certName211), true);
BOOST_CHECK_EQUAL(db.hasCertificate(certName222), true);
BOOST_CHECK_EQUAL(db.hasCertificate(certName221), true);
BOOST_CHECK_EQUAL(db.hasKey(keyName11), false);
BOOST_CHECK_EQUAL(db.hasKey(keyName12), true);
BOOST_CHECK_EQUAL(db.hasKey(keyName21), true);
BOOST_CHECK_EQUAL(db.hasKey(keyName22), true);
BOOST_CHECK_EQUAL(deletedCerts.size(), 2);
BOOST_CHECK(std::find(deletedCerts.begin(), deletedCerts.end(), certName111) !=
deletedCerts.end());
BOOST_CHECK(std::find(deletedCerts.begin(), deletedCerts.end(), certName112) !=
deletedCerts.end());
BOOST_CHECK_EQUAL(deletedKeys.size(), 1);
BOOST_CHECK_EQUAL(deletedKeys[0], keyName11);
deletedCerts.clear();
deletedKeys.clear();
// Recover deleted entries
db.addCertificate(*cert111);
db.addCertificate(*cert112);
// Delete the identity
// All the related certificates and keys will be deleted as well.
BOOST_CHECK_EQUAL(db.hasCertificate(certName111), true);
BOOST_CHECK_EQUAL(db.hasCertificate(certName112), true);
BOOST_CHECK_EQUAL(db.hasKey(keyName11), true);
BOOST_CHECK_EQUAL(db.hasIdentity(id1), true);
db.deleteIdentity(id1);
BOOST_CHECK_EQUAL(db.hasCertificate(certName112), false);
BOOST_CHECK_EQUAL(db.hasCertificate(certName111), false);
BOOST_CHECK_EQUAL(db.hasCertificate(certName122), false);
BOOST_CHECK_EQUAL(db.hasCertificate(certName121), false);
BOOST_CHECK_EQUAL(db.hasCertificate(certName212), true);
BOOST_CHECK_EQUAL(db.hasCertificate(certName211), true);
BOOST_CHECK_EQUAL(db.hasCertificate(certName222), true);
BOOST_CHECK_EQUAL(db.hasCertificate(certName221), true);
BOOST_CHECK_EQUAL(db.hasKey(keyName11), false);
BOOST_CHECK_EQUAL(db.hasKey(keyName12), false);
BOOST_CHECK_EQUAL(db.hasKey(keyName21), true);
BOOST_CHECK_EQUAL(db.hasKey(keyName22), true);
BOOST_CHECK_EQUAL(db.hasIdentity(id1), false);
BOOST_CHECK_EQUAL(db.hasIdentity(id2), true);
BOOST_CHECK_EQUAL(deletedCerts.size(), 4);
BOOST_CHECK(std::find(deletedCerts.begin(), deletedCerts.end(), certName111) !=
deletedCerts.end());
BOOST_CHECK(std::find(deletedCerts.begin(), deletedCerts.end(), certName112) !=
deletedCerts.end());
BOOST_CHECK(std::find(deletedCerts.begin(), deletedCerts.end(), certName121) !=
deletedCerts.end());
BOOST_CHECK(std::find(deletedCerts.begin(), deletedCerts.end(), certName122) !=
deletedCerts.end());
BOOST_CHECK_EQUAL(deletedKeys.size(), 2);
BOOST_CHECK(std::find(deletedKeys.begin(), deletedKeys.end(), keyName11) !=
deletedKeys.end());
BOOST_CHECK(std::find(deletedKeys.begin(), deletedKeys.end(), keyName12) !=
deletedCerts.end());
BOOST_CHECK_EQUAL(deletedIds.size(), 1);
BOOST_CHECK_EQUAL(deletedIds[0], id1);
}
BOOST_AUTO_TEST_SUITE_END()
} // namespace tests
} // namespace pib
} // namespace ndn
-137
View File
@@ -1,137 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* @author Yingdi Yu <yingdi@cs.ucla.edu>
*/
#include "tools/pib/pib-validator.hpp"
#include "tools/pib/encoding/update-param.hpp"
#include "tools/pib/encoding/delete-param.hpp"
#include <ndn-cxx/security/key-chain.hpp>
#include "../identity-management-time-fixture.hpp"
#include <boost/filesystem.hpp>
#include "tests/test-common.hpp"
namespace ndn {
namespace pib {
namespace tests {
class PibValidatorFixture : public ndn::tests::IdentityManagementTimeFixture
{
public:
PibValidatorFixture()
: tmpPath(boost::filesystem::path(TMP_TESTS_PATH) / "DbTest")
, db(tmpPath.c_str())
{
}
~PibValidatorFixture()
{
boost::filesystem::remove_all(tmpPath);
}
boost::asio::io_service io;
boost::filesystem::path tmpPath;
PibDb db;
bool isProcessed;
};
BOOST_FIXTURE_TEST_SUITE(PibPibValidator, PibValidatorFixture)
BOOST_AUTO_TEST_CASE(Basic)
{
PibValidator validator(db);
Name testUser("/localhost/pib/test/mgmt");
BOOST_REQUIRE(addIdentity(testUser, RsaKeyParams()));
Name testUserCertName = m_keyChain.getDefaultCertificateNameForIdentity(testUser);
shared_ptr<IdentityCertificate> testUserCert = m_keyChain.getCertificate(testUserCertName);
advanceClocks(io, time::milliseconds(100));
Name testUser2("/localhost/pib/test2/mgmt");
BOOST_REQUIRE(addIdentity(testUser2, RsaKeyParams()));
db.updateMgmtCertificate(*testUserCert);
advanceClocks(io, time::milliseconds(100));
Name normalId("/normal/id");
BOOST_REQUIRE(addIdentity(normalId, RsaKeyParams()));
Name normalIdCertName = m_keyChain.getDefaultCertificateNameForIdentity(normalId);
shared_ptr<IdentityCertificate> normalIdCert = m_keyChain.getCertificate(normalIdCertName);
db.addIdentity(normalId);
db.addKey(normalIdCert->getPublicKeyName(), normalIdCert->getPublicKeyInfo());
db.addCertificate(*normalIdCert);
Name command1("/localhost/pib/test/verb/param");
shared_ptr<Interest> interest1 = make_shared<Interest>(command1);
m_keyChain.signByIdentity(*interest1, testUser);
// "test" user is trusted for any command about itself, OK.
isProcessed = false;
validator.validate(*interest1,
[this] (const shared_ptr<const Interest>&) {
isProcessed = true;
BOOST_CHECK(true);
},
[this] (const shared_ptr<const Interest>&, const std::string&) {
isProcessed = true;
BOOST_CHECK(false);
});
BOOST_CHECK(isProcessed);
Name command2("/localhost/pib/test/verb/param");
shared_ptr<Interest> interest2 = make_shared<Interest>(command2);
m_keyChain.signByIdentity(*interest2, testUser2);
// "test2" user is NOT trusted for any command about other user, MUST fail
isProcessed = false;
validator.validate(*interest2,
[this] (const shared_ptr<const Interest>&) {
isProcessed = true;
BOOST_CHECK(false);
},
[this] (const shared_ptr<const Interest>&, const std::string&) {
isProcessed = true;
BOOST_CHECK(true);
});
BOOST_CHECK(isProcessed);
Name command3("/localhost/pib/test/verb/param");
shared_ptr<Interest> interest3 = make_shared<Interest>(command3);
m_keyChain.signByIdentity(*interest3, normalId);
// "normalId" is in "test" pib, can be trusted for some commands about "test".
// Detail checking is needed, but it is not the job of Validator, OK.
isProcessed = false;
validator.validate(*interest3,
[this] (const shared_ptr<const Interest>&) {
isProcessed = true;
BOOST_CHECK(true);
},
[this] (const shared_ptr<const Interest>&, const std::string&) {
isProcessed = true;
BOOST_CHECK(false);
});
BOOST_CHECK(isProcessed);
}
BOOST_AUTO_TEST_SUITE_END()
} // namespace tests
} // namespace pib
} // namespace ndn
-1389
View File
File diff suppressed because it is too large Load Diff
-64
View File
@@ -1,64 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* @author Yingdi Yu <yingdi@cs.ucla.edu>
*/
#include "tools/pib/response-cache.hpp"
#include "tests/test-common.hpp"
namespace ndn {
namespace pib {
namespace tests {
BOOST_AUTO_TEST_SUITE(PibResponseCache)
BOOST_AUTO_TEST_CASE(Basic)
{
ResponseCache cache;
Name dataName("/test/data");
dataName.appendVersion();
shared_ptr<Data> data = make_shared<Data>(dataName);
Name dataNameNoVersion("/test/data");
Name anotherDataName("/test/another");
BOOST_CHECK_EQUAL(static_cast<bool>(cache.find(dataNameNoVersion)), false);
BOOST_CHECK_EQUAL(static_cast<bool>(cache.find(dataName, true)), false);
cache.insert(*data);
BOOST_CHECK(static_cast<bool>(cache.find(dataNameNoVersion)));
BOOST_CHECK(static_cast<bool>(cache.find(dataName, true)));
BOOST_CHECK_EQUAL(static_cast<bool>(cache.find(anotherDataName)), false);
BOOST_CHECK_EQUAL(static_cast<bool>(cache.find(anotherDataName, true)), false);
cache.erase(dataNameNoVersion);
BOOST_CHECK_EQUAL(static_cast<bool>(cache.find(dataNameNoVersion)), false);
BOOST_CHECK_EQUAL(static_cast<bool>(cache.find(dataName, true)), false);
}
BOOST_AUTO_TEST_SUITE_END()
} // namespace tests
} // namespace pib
} // namespace ndn
+60 -85
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Arizona Board of Regents.
/*
* Copyright (c) 2014-2023, Arizona Board of Regents.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -18,104 +18,79 @@
*/
#include "tools/ping/client/ping.hpp"
#include <ndn-cxx/util/dummy-client-face.hpp>
#include "tests/test-common.hpp"
#include "tests/io-fixture.hpp"
namespace ndn {
namespace ping {
namespace client {
namespace tests {
#include <ndn-cxx/util/dummy-client-face.hpp>
namespace ndn::ping::client::tests {
using namespace ndn::tests;
BOOST_AUTO_TEST_SUITE(PingClientPing)
BOOST_AUTO_TEST_SUITE(Ping)
BOOST_AUTO_TEST_SUITE(TestClient)
class SequenceNumberIncrementFixture : public UnitTestTimeFixture
using client::Ping;
BOOST_FIXTURE_TEST_CASE(Basic, IoFixture)
{
protected:
SequenceNumberIncrementFixture()
: face(util::makeDummyClientFace(io, {false, true}))
, pingOptions(makeOptions())
, ping(*face, pingOptions)
, numPings(0)
, lastPingSeq(pingOptions.startSeq)
{
ping.afterResponse.connect(bind(&SequenceNumberIncrementFixture::onResponse, this, _1));
ping.afterTimeout.connect(bind(&SequenceNumberIncrementFixture::onTimeout, this, _1));
}
public:
void
onResponse(uint64_t seq)
{
numPings++;
lastPingSeq = seq;
if (numPings == maxPings) {
face->shutdown();
io.stop();
}
}
void
onTimeout(uint64_t seq)
{
numPings++;
lastPingSeq = seq;
if (numPings == maxPings) {
face->shutdown();
io.stop();
}
}
private:
static Options
makeOptions()
{
Options opt;
opt.prefix = "ndn:/test-prefix";
opt.shouldAllowStaleData = false;
opt.shouldGenerateRandomSeq = false;
opt.shouldPrintTimestamp = false;
opt.nPings = 4;
opt.interval = time::milliseconds(100);
opt.timeout = time::milliseconds(1000);
opt.startSeq = 1000;
return opt;
}
protected:
boost::asio::io_service io;
shared_ptr<util::DummyClientFace> face;
DummyClientFace face(m_io, {true, true});
Options pingOptions;
Ping ping;
uint32_t numPings;
uint32_t maxPings;
uint64_t lastPingSeq;
KeyChain keyChain;
};
pingOptions.prefix = "/test-prefix";
pingOptions.shouldAllowStaleData = false;
pingOptions.shouldGenerateRandomSeq = false;
pingOptions.shouldPrintTimestamp = false;
pingOptions.nPings = 4;
pingOptions.interval = 100_ms;
pingOptions.timeout = 2_s;
pingOptions.startSeq = 1000;
Ping ping(face, pingOptions);
int nFinishSignals = 0;
std::vector<uint64_t> dataSeqs;
std::vector<uint64_t> nackSeqs;
std::vector<uint64_t> timeoutSeqs;
ping.afterData.connect([&] (uint64_t seq, auto&&...) { dataSeqs.push_back(seq); });
ping.afterNack.connect([&] (uint64_t seq, auto&&...) { nackSeqs.push_back(seq); });
ping.afterTimeout.connect([&] (uint64_t seq, auto&&...) { timeoutSeqs.push_back(seq); });
ping.afterFinish.connect([&] {
BOOST_REQUIRE_EQUAL(dataSeqs.size(), 2);
BOOST_REQUIRE_EQUAL(nackSeqs.size(), 1);
BOOST_REQUIRE_EQUAL(timeoutSeqs.size(), 1);
BOOST_CHECK_EQUAL(dataSeqs[0], 1000);
BOOST_CHECK_EQUAL(nackSeqs[0], 1001);
BOOST_CHECK_EQUAL(dataSeqs[1], 1002);
BOOST_CHECK_EQUAL(timeoutSeqs[0], 1003);
nFinishSignals++;
});
BOOST_FIXTURE_TEST_CASE(SequenceNumberIncrement, SequenceNumberIncrementFixture)
{
maxPings = 4;
ping.start();
this->advanceClocks(io, time::milliseconds(1), 400);
this->advanceClocks(1_ms, 500);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 4);
face->receive(*makeData("ndn:/test-prefix/ping/1000"));
face->receive(*makeData("ndn:/test-prefix/ping/1001"));
face->receive(*makeData("ndn:/test-prefix/ping/1002"));
face->receive(*makeData("ndn:/test-prefix/ping/1003"));
auto data = makeData("/test-prefix/ping/1000");
data->setFreshnessPeriod(1_s);
face.receive(*data);
io.run();
face.receive(makeNack(face.sentInterests[1], lp::NackReason::DUPLICATE));
BOOST_REQUIRE_EQUAL(1003, lastPingSeq);
BOOST_REQUIRE_EQUAL(4, numPings);
data = makeData("/test-prefix/ping/1002");
data->setFreshnessPeriod(1_s);
face.receive(*data);
this->advanceClocks(100_ms, 20);
// /test-prefix/ping/1003 is unanswered and will timeout
BOOST_CHECK_EQUAL(nFinishSignals, 1);
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END() // TestClient
BOOST_AUTO_TEST_SUITE_END() // Ping
} // namespace tests
} // namespace client
} // namespace ping
} // namespace ndn
} // namespace ndn::ping::client::tests
+89 -35
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Arizona Board of Regents.
/*
* Copyright (c) 2014-2023, Arizona Board of Regents.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -18,56 +18,44 @@
*/
#include "tools/ping/client/statistics-collector.hpp"
#include <ndn-cxx/util/dummy-client-face.hpp>
#include "tests/test-common.hpp"
namespace ndn {
namespace ping {
namespace client {
namespace tests {
#include <ndn-cxx/util/dummy-client-face.hpp>
using namespace ndn::tests;
namespace ndn::ping::client::tests {
class StatisticsCollectorFixture
{
protected:
StatisticsCollectorFixture()
: face(util::makeDummyClientFace())
, pingOptions(makeOptions())
, pingProgram(*face, pingOptions)
, sc(pingProgram, pingOptions)
{
}
private:
static Options
makeOptions()
{
Options opt;
opt.prefix = "ndn:/ping-prefix";
opt.prefix = "/ping-prefix";
opt.shouldAllowStaleData = false;
opt.shouldGenerateRandomSeq = false;
opt.shouldPrintTimestamp = false;
opt.nPings = 5;
opt.interval = time::milliseconds(100);
opt.timeout = time::milliseconds(2000);
opt.interval = 100_ms;
opt.timeout = 2_s;
opt.startSeq = 1;
return opt;
}
protected:
shared_ptr<util::DummyClientFace> face;
Options pingOptions;
Ping pingProgram;
StatisticsCollector sc;
DummyClientFace face;
Options pingOptions{makeOptions()};
Ping pingProgram{face, pingOptions};
StatisticsCollector sc{pingProgram, pingOptions};
};
BOOST_FIXTURE_TEST_SUITE(PingClientStatisticsCollector, StatisticsCollectorFixture)
BOOST_AUTO_TEST_SUITE(Ping)
BOOST_FIXTURE_TEST_SUITE(TestStatisticsCollector, StatisticsCollectorFixture)
BOOST_AUTO_TEST_CASE(Resp50msResp50ms)
{
sc.recordResponse(time::milliseconds(50));
sc.recordData(time::milliseconds(50));
Statistics stats1 = sc.computeStatistics();
BOOST_CHECK_EQUAL(stats1.prefix, pingOptions.prefix);
@@ -80,7 +68,7 @@ BOOST_AUTO_TEST_CASE(Resp50msResp50ms)
BOOST_CHECK_CLOSE(stats1.avgRtt, 50.0, 0.001);
BOOST_CHECK_CLOSE(stats1.stdDevRtt, 0.0, 0.001);
sc.recordResponse(time::milliseconds(50));
sc.recordData(time::milliseconds(50));
Statistics stats2 = sc.computeStatistics();
BOOST_CHECK_EQUAL(stats2.prefix, pingOptions.prefix);
@@ -96,8 +84,8 @@ BOOST_AUTO_TEST_CASE(Resp50msResp50ms)
BOOST_AUTO_TEST_CASE(Resp50msResp100ms)
{
sc.recordResponse(time::milliseconds(50));
sc.recordResponse(time::milliseconds(100));
sc.recordData(time::milliseconds(50));
sc.recordData(time::milliseconds(100));
Statistics stats = sc.computeStatistics();
BOOST_CHECK_EQUAL(stats.prefix, pingOptions.prefix);
@@ -120,12 +108,19 @@ BOOST_AUTO_TEST_CASE(LossLoss)
BOOST_CHECK_EQUAL(stats.prefix, pingOptions.prefix);
BOOST_CHECK_EQUAL(stats.nSent, 2);
BOOST_CHECK_EQUAL(stats.nReceived, 0);
BOOST_CHECK_EQUAL(stats.nNacked, 0);
BOOST_CHECK_CLOSE(stats.packetLossRate, 1.0, 0.001);
BOOST_CHECK_CLOSE(stats.packetNackedRate, 0.0, 0.001);
BOOST_CHECK_CLOSE(stats.minRtt, std::numeric_limits<double>::max(), 0.001);
BOOST_CHECK_CLOSE(stats.maxRtt, 0.0, 0.001);
BOOST_CHECK_CLOSE(stats.sumRtt, 0.0, 0.001);
BOOST_CHECK(std::isnan(stats.avgRtt));
BOOST_CHECK(std::isnan(stats.stdDevRtt));
}
BOOST_AUTO_TEST_CASE(Resp50msLoss)
{
sc.recordResponse(time::milliseconds(50));
sc.recordData(time::milliseconds(50));
sc.recordTimeout();
Statistics stats = sc.computeStatistics();
@@ -140,9 +135,68 @@ BOOST_AUTO_TEST_CASE(Resp50msLoss)
BOOST_CHECK_CLOSE(stats.stdDevRtt, 0.0, 0.001);
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(NackNack)
{
sc.recordNack();
sc.recordNack();
} // namespace tests
} // namespace client
} // namespace ping
} // namespace ndn
Statistics stats = sc.computeStatistics();
BOOST_CHECK_EQUAL(stats.prefix, pingOptions.prefix);
BOOST_CHECK_EQUAL(stats.nSent, 2);
BOOST_CHECK_EQUAL(stats.nNacked, 2);
BOOST_CHECK_EQUAL(stats.nReceived, 0);
BOOST_CHECK_CLOSE(stats.packetNackedRate, 1.0, 0.001);
}
BOOST_AUTO_TEST_CASE(Resp50msNack)
{
sc.recordData(time::milliseconds(50));
sc.recordNack();
Statistics stats = sc.computeStatistics();
BOOST_CHECK_EQUAL(stats.prefix, pingOptions.prefix);
BOOST_CHECK_EQUAL(stats.nSent, 2);
BOOST_CHECK_EQUAL(stats.nReceived, 1);
BOOST_CHECK_CLOSE(stats.minRtt, 50.0, 0.001);
BOOST_CHECK_CLOSE(stats.maxRtt, 50.0, 0.001);
BOOST_CHECK_CLOSE(stats.sumRtt, 50.0, 0.001);
BOOST_CHECK_CLOSE(stats.avgRtt, 50.0, 0.001);
BOOST_CHECK_CLOSE(stats.stdDevRtt, 0.0, 0.001);
BOOST_CHECK_EQUAL(stats.nNacked, 1);
BOOST_CHECK_CLOSE(stats.packetNackedRate, 0.5, 0.001);
}
BOOST_AUTO_TEST_CASE(NackLoss)
{
sc.recordNack();
sc.recordTimeout();
Statistics stats = sc.computeStatistics();
BOOST_CHECK_EQUAL(stats.prefix, pingOptions.prefix);
BOOST_CHECK_EQUAL(stats.nSent, 2);
BOOST_CHECK_EQUAL(stats.nReceived, 0);
BOOST_CHECK_EQUAL(stats.nNacked, 1);
BOOST_CHECK_CLOSE(stats.packetNackedRate, 0.5, 0.001);
BOOST_CHECK_CLOSE(stats.packetLossRate, 0.5, 0.001);
}
BOOST_AUTO_TEST_CASE(NoneSent)
{
Statistics stats = sc.computeStatistics();
BOOST_CHECK_EQUAL(stats.prefix, pingOptions.prefix);
BOOST_CHECK_EQUAL(stats.nSent, 0);
BOOST_CHECK_EQUAL(stats.nReceived, 0);
BOOST_CHECK_EQUAL(stats.nNacked, 0);
BOOST_CHECK(std::isnan(stats.packetLossRate));
BOOST_CHECK(std::isnan(stats.packetNackedRate));
BOOST_CHECK_CLOSE(stats.minRtt, std::numeric_limits<double>::max(), 0.001);
BOOST_CHECK_CLOSE(stats.maxRtt, 0.0, 0.001);
BOOST_CHECK_CLOSE(stats.sumRtt, 0.0, 0.001);
BOOST_CHECK(std::isnan(stats.avgRtt));
BOOST_CHECK(std::isnan(stats.stdDevRtt));
}
BOOST_AUTO_TEST_SUITE_END() // TestStatisticsCollector
BOOST_AUTO_TEST_SUITE_END() // Ping
} // namespace ndn::ping::client::tests
+63 -75
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Arizona Board of Regents.
/*
* Copyright (c) 2015-2023, Arizona Board of Regents.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -17,84 +17,78 @@
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tools/ping/server/ping-server.hpp"
#include "tools/ping/client/ping.hpp"
#include <ndn-cxx/util/dummy-client-face.hpp>
#include "tools/ping/server/ping-server.hpp"
#include "tests/test-common.hpp"
#include "../identity-management-time-fixture.hpp"
#include "tests/io-fixture.hpp"
#include "tests/key-chain-fixture.hpp"
namespace ndn {
namespace ping {
namespace tests {
#include <ndn-cxx/util/dummy-client-face.hpp>
#include <boost/asio/post.hpp>
namespace ndn::ping::tests {
using namespace ndn::tests;
class PingIntegratedFixture : public IdentityManagementTimeFixture
class PingIntegratedFixture : public IoFixture, public KeyChainFixture
{
public:
protected:
PingIntegratedFixture()
: serverFace(util::makeDummyClientFace(io, {false, true}))
, clientFace(util::makeDummyClientFace(io, {false, true}))
, numResponses(0)
, wantLoss(false)
{
serverFace->onSendInterest.connect([this] (const Interest& interest) {
io.post([=] { if (!wantLoss) { clientFace->receive(interest); } });
serverFace.onSendInterest.connect([this] (const auto& interest) {
receive(clientFace, interest);
});
clientFace->onSendInterest.connect([this] (const Interest& interest) {
io.post([=] { if (!wantLoss) { serverFace->receive(interest); } });
clientFace.onSendInterest.connect([this] (const auto& interest) {
receive(serverFace, interest);
});
serverFace->onSendData.connect([this] (const Data& data) {
io.post([=] { if (!wantLoss) { clientFace->receive(data); } });
serverFace.onSendData.connect([this] (const auto& data) {
receive(clientFace, data);
});
clientFace->onSendData.connect([this] (const Data& data) {
io.post([=] { if (!wantLoss) { serverFace->receive(data); } });
clientFace.onSendData.connect([this] (const auto& data) {
receive(serverFace, data);
});
}
void onTimeout(uint64_t seq)
template<typename Packet>
void
receive(DummyClientFace& face, const Packet& pkt)
{
numResponses++;
if (numResponses == maxResponses) {
serverFace->shutdown();
clientFace->shutdown();
io.stop();
}
boost::asio::post(m_io, [=, &face] {
if (!wantLoss) {
face.receive(pkt);
}
});
}
void onData(uint64_t seq)
void
onFinish()
{
numResponses++;
if (numResponses == maxResponses) {
serverFace->shutdown();
clientFace->shutdown();
io.stop();
}
serverFace.shutdown();
clientFace.shutdown();
m_io.stop();
}
public:
boost::asio::io_service io;
shared_ptr<util::DummyClientFace> serverFace;
shared_ptr<util::DummyClientFace> clientFace;
protected:
DummyClientFace serverFace{m_io, m_keyChain, {false, true}};
DummyClientFace clientFace{m_io, m_keyChain, {false, true}};
std::unique_ptr<server::PingServer> server;
std::unique_ptr<client::Ping> client;
int maxResponses;
int numResponses;
bool wantLoss;
bool wantLoss = false;
};
BOOST_AUTO_TEST_SUITE(PingIntegrated)
BOOST_AUTO_TEST_SUITE(Ping)
BOOST_FIXTURE_TEST_SUITE(TestIntegrated, PingIntegratedFixture)
BOOST_FIXTURE_TEST_CASE(Normal, PingIntegratedFixture)
BOOST_AUTO_TEST_CASE(Normal)
{
server::Options serverOpts;
serverOpts.prefix = "ndn:/test-prefix";
serverOpts.freshnessPeriod = time::milliseconds(5000);
serverOpts.freshnessPeriod = 5_s;
serverOpts.nMaxPings = 4;
serverOpts.shouldPrintTimestamp = false;
serverOpts.wantTimestamp = false;
serverOpts.payloadSize = 0;
server.reset(new server::PingServer(*serverFace, m_keyChain, serverOpts));
server = make_unique<server::PingServer>(serverFace, m_keyChain, serverOpts);
BOOST_REQUIRE_EQUAL(0, server->getNPings());
server->start();
@@ -104,32 +98,30 @@ BOOST_FIXTURE_TEST_CASE(Normal, PingIntegratedFixture)
clientOpts.shouldGenerateRandomSeq = false;
clientOpts.shouldPrintTimestamp = false;
clientOpts.nPings = 4;
clientOpts.interval = time::milliseconds(100);
clientOpts.timeout = time::milliseconds(2000);
clientOpts.interval = 100_ms;
clientOpts.timeout = 2_s;
clientOpts.startSeq = 1000;
client.reset(new client::Ping(*clientFace, clientOpts));
client->afterResponse.connect(bind(&PingIntegratedFixture::onData, this, _1));
client->afterTimeout.connect(bind(&PingIntegratedFixture::onTimeout, this, _1));
maxResponses = 4;
client = make_unique<client::Ping>(clientFace, clientOpts);
client->afterFinish.connect([this] { onFinish(); });
client->start();
this->advanceClocks(io, time::milliseconds(1), 400);
io.run();
advanceClocks(1_ms, 400);
m_io.run();
BOOST_REQUIRE_EQUAL(4, server->getNPings());
BOOST_CHECK_EQUAL(4, server->getNPings());
}
BOOST_FIXTURE_TEST_CASE(Timeout, PingIntegratedFixture)
BOOST_AUTO_TEST_CASE(Timeout)
{
wantLoss = true;
server::Options serverOpts;
serverOpts.prefix = "ndn:/test-prefix";
serverOpts.freshnessPeriod = time::milliseconds(5000);
serverOpts.freshnessPeriod = 5_s;
serverOpts.nMaxPings = 4;
serverOpts.shouldPrintTimestamp = false;
serverOpts.wantTimestamp = false;
serverOpts.payloadSize = 0;
server.reset(new server::PingServer(*serverFace, m_keyChain, serverOpts));
server = make_unique<server::PingServer>(serverFace, m_keyChain, serverOpts);
BOOST_REQUIRE_EQUAL(0, server->getNPings());
server->start();
@@ -139,24 +131,20 @@ BOOST_FIXTURE_TEST_CASE(Timeout, PingIntegratedFixture)
clientOpts.shouldGenerateRandomSeq = false;
clientOpts.shouldPrintTimestamp = false;
clientOpts.nPings = 4;
clientOpts.interval = time::milliseconds(100);
clientOpts.timeout = time::milliseconds(500);
clientOpts.interval = 100_ms;
clientOpts.timeout = 500_ms;
clientOpts.startSeq = 1000;
client.reset(new client::Ping(*clientFace, clientOpts));
numResponses = 0;
maxResponses = 4;
client->afterResponse.connect(bind(&PingIntegratedFixture::onData, this, _1));
client->afterTimeout.connect(bind(&PingIntegratedFixture::onTimeout, this, _1));
client = make_unique<client::Ping>(clientFace, clientOpts);
client->afterFinish.connect([this] { onFinish(); });
client->start();
this->advanceClocks(io, time::milliseconds(1), 1000);
io.run();
advanceClocks(1_ms, 1000);
m_io.run();
BOOST_REQUIRE_EQUAL(0, server->getNPings());
BOOST_CHECK_EQUAL(0, server->getNPings());
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END() // TestIntegrated
BOOST_AUTO_TEST_SUITE_END() // Ping
} // namespace tests
} // namespace ping
} // namespace ndn
} // namespace ndn::ping::tests
+34 -43
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Arizona Board of Regents.
/*
* Copyright (c) 2014-2023, Arizona Board of Regents.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -18,40 +18,30 @@
*/
#include "tools/ping/server/ping-server.hpp"
#include <ndn-cxx/util/dummy-client-face.hpp>
#include "tests/test-common.hpp"
#include "../../identity-management-time-fixture.hpp"
#include "tests/io-fixture.hpp"
#include "tests/key-chain-fixture.hpp"
namespace ndn {
namespace ping {
namespace server {
namespace tests {
#include <ndn-cxx/util/dummy-client-face.hpp>
namespace ndn::ping::server::tests {
using namespace ndn::tests;
BOOST_AUTO_TEST_SUITE(PingServerPingServer)
class CreatePingServerFixture : public IdentityManagementTimeFixture
class PingServerFixture : public IoFixture, public KeyChainFixture
{
protected:
CreatePingServerFixture()
: face(util::makeDummyClientFace(io, {false, true}))
, pingOptions(makeOptions())
, pingServer(*face, m_keyChain, pingOptions)
{
}
Interest
makePingInterest(int seq) const
{
Name name(pingOptions.prefix);
name.append("ping");
name.append(std::to_string(seq));
Interest interest(name);
interest.setMustBeFresh(true);
interest.setInterestLifetime(time::milliseconds(2000));
return interest;
name.append("ping")
.append(to_string(seq));
return Interest(name)
.setMustBeFresh(true)
.setInterestLifetime(2_s);
}
private:
@@ -59,39 +49,40 @@ private:
makeOptions()
{
Options opt;
opt.prefix = "ndn:/test-prefix";
opt.freshnessPeriod = time::milliseconds(5000);
opt.prefix = "/test-prefix";
opt.freshnessPeriod = 5_s;
opt.nMaxPings = 2;
opt.shouldPrintTimestamp = false;
opt.payloadSize = 0;
opt.wantTimestamp = false;
opt.wantQuiet = true;
return opt;
}
protected:
boost::asio::io_service io;
shared_ptr<util::DummyClientFace> face;
Options pingOptions;
PingServer pingServer;
DummyClientFace face{m_io, m_keyChain, {false, true}};
Options pingOptions{makeOptions()};
PingServer pingServer{face, m_keyChain, pingOptions};
};
BOOST_FIXTURE_TEST_CASE(CreatePingServer, CreatePingServerFixture)
BOOST_AUTO_TEST_SUITE(Ping)
BOOST_AUTO_TEST_SUITE(TestServer)
BOOST_FIXTURE_TEST_CASE(Receive, PingServerFixture)
{
BOOST_REQUIRE_EQUAL(0, pingServer.getNPings());
BOOST_TEST(pingServer.getNPings() == 0);
pingServer.start();
this->advanceClocks(io, time::milliseconds(1), 200);
advanceClocks(1_ms, 200);
face->receive(makePingInterest(1000));
face->receive(makePingInterest(1001));
face.receive(makePingInterest(1000));
face.receive(makePingInterest(1001));
io.run();
m_io.run();
BOOST_REQUIRE_EQUAL(2, pingServer.getNPings());
BOOST_TEST(pingServer.getNPings() == 2);
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END() // TestServer
BOOST_AUTO_TEST_SUITE_END() // Ping
} // namespace tests
} // namespace server
} // namespace ping
} // namespace ndn
} // namespace ndn::ping::server::tests
+20 -22
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Arizona Board of Regents.
/*
* Copyright (c) 2014-2022 Arizona Board of Regents.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -17,22 +17,23 @@
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
// #include "unit-under-test.hpp"
// Unit being tested MUST be included first, to ensure header compiles on its own.
// The unit being tested should be included first, to ensure the header compiles on its own.
// For further information about test naming conventions, see
// http://redmine.named-data.net/projects/nfd/wiki/UnitTesting
// https://redmine.named-data.net/projects/nfd/wiki/UnitTesting
//#include "unit-under-test.hpp"
#include "tests/test-common.hpp"
#include "tests/io-fixture.hpp" // optional, for IoFixture
//#include "tests/key-chain-fixture.hpp" // optional, for KeyChainFixture
namespace ndn {
namespace tool_name {
namespace tests {
// Unit tests SHOULD go inside ndn::tool_name::tests namespace.
// Unit tests should go inside the ndn::tool_name::tests namespace.
namespace ndn::tool_name::tests {
// Common fixtures in ndn::tests can be imported.
// Common fixtures in ndn::tests can be imported if needed.
using namespace ndn::tests;
// See http://redmine.named-data.net/projects/nfd/wiki/UnitTesting on how to name a test suite.
// See https://redmine.named-data.net/projects/nfd/wiki/UnitTesting
// for a guide on how to name a test suite.
BOOST_AUTO_TEST_SUITE(TestSkeleton)
BOOST_AUTO_TEST_CASE(Test1)
@@ -40,22 +41,19 @@ BOOST_AUTO_TEST_CASE(Test1)
int i = 0;
// For reference of available Boost.Test macros, see
// http://www.boost.org/doc/libs/1_48_0/libs/test/doc/html/utf/testing-tools/reference.html
// https://www.boost.org/doc/libs/1_71_0/libs/test/doc/html/boost_test/testing_tools/summary.html
BOOST_REQUIRE_NO_THROW(i = 1);
BOOST_REQUIRE_EQUAL(i, 1);
BOOST_CHECK_EQUAL(i, 1);
}
// Use UnitTestTimeFixture to mock clocks.
BOOST_FIXTURE_TEST_CASE(Test2, UnitTestTimeFixture)
// Use ClockFixture or IoFixture to mock clocks.
BOOST_FIXTURE_TEST_CASE(Test2, IoFixture)
{
// this->advanceClocks increments mock clocks.
boost::asio::io_service io;
this->advanceClocks(io, time::milliseconds(500));
// advanceClocks() increments mock clocks.
advanceClocks(500_ms);
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END() // TestSkeleton
} // namespace tests
} // namespace tool_name
} // namespace ndn
} // namespace ndn::tool_name::tests
+67
View File
@@ -0,0 +1,67 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2023, 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 ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tests/test-common.hpp"
namespace ndn::tests {
shared_ptr<Interest>
makeInterest(const Name& name, bool canBePrefix, std::optional<time::milliseconds> lifetime,
std::optional<Interest::Nonce> nonce)
{
auto interest = std::make_shared<Interest>(name);
interest->setCanBePrefix(canBePrefix);
if (lifetime) {
interest->setInterestLifetime(*lifetime);
}
interest->setNonce(nonce);
return interest;
}
shared_ptr<Data>
makeData(const Name& name)
{
auto data = std::make_shared<Data>(name);
return signData(data);
}
Data&
signData(Data& data)
{
data.setSignatureInfo(SignatureInfo(tlv::NullSignature));
data.setSignatureValue(std::make_shared<Buffer>());
data.wireEncode();
return data;
}
lp::Nack
makeNack(Interest interest, lp::NackReason reason)
{
lp::Nack nack(std::move(interest));
nack.setReason(reason);
return nack;
}
} // namespace ndn::tests
+47 -104
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
/*
* Copyright (c) 2014-2023, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,121 +26,64 @@
#ifndef NDN_TOOLS_TESTS_TEST_COMMON_HPP
#define NDN_TOOLS_TESTS_TEST_COMMON_HPP
#include "boost-test.hpp"
#include "core/common.hpp"
#include "tests/boost-test.hpp"
#include <ndn-cxx/util/time-unit-test-clock.hpp>
#include <ndn-cxx/name.hpp>
#include <ndn-cxx/interest.hpp>
#include <ndn-cxx/data.hpp>
#include <ndn-cxx/signature.hpp>
#include <ndn-cxx/security/signature-sha256-with-rsa.hpp>
namespace ndn::tests {
#include <boost/asio/io_service.hpp>
namespace ndn {
namespace tests {
/** \brief a test fixture that overrides steady clock and system clock
/**
* \brief Create an Interest
*/
class UnitTestTimeFixture
{
protected:
UnitTestTimeFixture()
: steadyClock(make_shared<time::UnitTestSteadyClock>())
, systemClock(make_shared<time::UnitTestSystemClock>())
{
time::setCustomClocks(steadyClock, systemClock);
}
shared_ptr<Interest>
makeInterest(const Name& name, bool canBePrefix = false,
std::optional<time::milliseconds> lifetime = std::nullopt,
std::optional<Interest::Nonce> nonce = std::nullopt);
~UnitTestTimeFixture()
{
time::setCustomClocks(nullptr, nullptr);
}
/**
* \brief Create a Data with a null (i.e., empty) signature
*
* If a "real" signature is desired, use KeyChainFixture and sign again with `m_keyChain`.
*/
shared_ptr<Data>
makeData(const Name& name);
/** \brief advance steady and system clocks
*
* Clocks are advanced in increments of \p tick for \p nTicks ticks.
* After each tick, the supplied io_service is polled to process pending I/O events.
*
* Exceptions thrown during I/O events are propagated to the caller.
* Clock advancing would stop in case of an exception.
*/
void
advanceClocks(boost::asio::io_service& io,
const time::nanoseconds& tick, size_t nTicks = 1)
{
BOOST_ASSERT(nTicks >= 0);
this->advanceClocks(io, tick, tick * nTicks);
}
/** \brief advance steady and system clocks
*
* Clocks are advanced in increments of \p tick for \p total time.
* The last increment might be shorter than \p tick.
* After each tick, the supplied io_service is polled to process pending I/O events.
*
* Exceptions thrown during I/O events are propagated to the caller.
* Clock advancing would stop in case of an exception.
*/
void
advanceClocks(boost::asio::io_service& io,
const time::nanoseconds& tick, const time::nanoseconds& total)
{
BOOST_ASSERT(tick > time::nanoseconds::zero());
BOOST_ASSERT(total >= time::nanoseconds::zero());
time::nanoseconds remaining = total;
while (remaining > time::nanoseconds::zero()) {
if (remaining >= tick) {
steadyClock->advance(tick);
systemClock->advance(tick);
remaining -= tick;
}
else {
steadyClock->advance(remaining);
systemClock->advance(remaining);
remaining = time::nanoseconds::zero();
}
if (io.stopped())
io.reset();
io.poll();
}
}
protected:
shared_ptr<time::UnitTestSteadyClock> steadyClock;
shared_ptr<time::UnitTestSystemClock> systemClock;
};
inline shared_ptr<Interest>
makeInterest(const Name& name)
{
return make_shared<Interest>(name);
}
/**
* \brief Add a null signature to \p data
*/
Data&
signData(Data& data);
/**
* \brief Add a null signature to \p data
*/
inline shared_ptr<Data>
signData(const shared_ptr<Data>& data)
signData(shared_ptr<Data> data)
{
ndn::SignatureSha256WithRsa fakeSignature;
fakeSignature.setValue(ndn::dataBlock(tlv::SignatureValue,
static_cast<const uint8_t*>(nullptr), 0));
data->setSignature(fakeSignature);
data->wireEncode();
signData(*data);
return data;
}
inline shared_ptr<Data>
makeData(const Name& name)
/**
* \brief Create a Nack
*/
lp::Nack
makeNack(Interest interest, lp::NackReason reason);
/**
* \brief Replace a name component in a packet
* \param[in,out] pkt the packet
* \param index the index of the name component to replace
* \param args arguments to name::Component constructor
*/
template<typename Packet, typename ...Args>
void
setNameComponent(Packet& pkt, ssize_t index, Args&& ...args)
{
shared_ptr<Data> data = make_shared<Data>(name);
return signData(data);
Name name = pkt.getName();
name.set(index, name::Component(std::forward<Args>(args)...));
pkt.setName(name);
}
} // namespace tests
} // namespace ndn
} // namespace ndn::tests
#endif // NDN_TOOLS_TESTS_TEST_COMMON_HPP
+6 -10
View File
@@ -2,13 +2,9 @@
top = '..'
def build(bld):
if not bld.env['WITH_TESTS']:
return
bld(target='../unit-tests',
features='cxx cxxprogram',
source=bld.path.ant_glob(['*.cpp'] + ['%s/**/*.cpp' % tool for tool in bld.env['BUILD_TOOLS']]),
use=['core-objects'] + ['%s-objects' % tool for tool in bld.env['BUILD_TOOLS']],
headers='../common.hpp boost-test.hpp',
defines='TMP_TESTS_PATH=\"%s/tmp-tests\"' % bld.bldnode,
)
bld.program(
target=f'{top}/unit-tests',
name='unit-tests',
source=bld.path.ant_glob(['*.cpp'] + [f'{tool}/**/*.cpp' for tool in bld.env.BUILD_TOOLS]),
use=['BOOST_TESTS', 'core-objects'] + [f'{tool}-objects' for tool in bld.env.BUILD_TOOLS],
install_path=None)
+76
View File
@@ -0,0 +1,76 @@
# ndncatchunks and ndnputchunks
**ndncatchunks** and **ndnputchunks** are a pair of programs to transfer a file as Data segments.
* **ndnputchunks** is a producer program that reads a file from the standard input, and makes
it available as a set of NDN Data segments. It appends version and segment number components
to the specified name as needed, according to the [NDN naming conventions](
https://named-data.net/publications/techreports/ndn-tr-22-3-ndn-memo-naming-conventions/).
* **ndncatchunks** is a consumer program that fetches Data segments of a file, optionally
discovering the latest version of the file, and writes the content of the retrieved file to
the standard output.
## Version discovery in ndncatchunks
If a version component is present at the end of the user-specified NDN name, the provided version
number will be used, without any version discovery process. Otherwise, discovery Interest(s) will
be sent out to fetch metadata of the solicited content from which the Data version will be resolved.
For more information about the packet format and naming conventions of Interest and Data packets
used for version discovery in ndncatchunks, please refer to:
[Realtime Data Retrieval (RDR) protocol](https://redmine.named-data.net/projects/ndn-tlv/wiki/RDR).
## Interest pipeline types in ndncatchunks
* `fixed`: maintains a fixed-size window of Interests in flight; the window size is configurable
via a command line option and defaults to 1.
* `aimd` : adjusts the window size via additive-increase/multiplicative-decrease (AIMD).
By default, it uses a Conservative Window Adaptation, that is, the congestion window
will be decreased at most once per round-trip-time.
* `cubic`: adjusts the window size similar to the TCP CUBIC algorithm.
For details about both aimd and cubic please refer to:
[A Practical Congestion Control Scheme for Named Data
Networking](https://conferences2.sigcomm.org/acm-icn/2016/proceedings/p21-schneider.pdf).
The default Interest pipeline type is `cubic`.
## Usage examples
### Publishing
The following command will publish the text of the GPL-3 license under the `/localhost/demo/gpl3`
prefix:
ndnputchunks /localhost/demo/gpl3 < /usr/share/common-licenses/GPL-3
To find the published version you have to start ndnputchunks with the `-p` command line option,
for example:
ndnputchunks -p /localhost/demo/gpl3 < /usr/share/common-licenses/GPL-3
This command will print the published version to standard output.
To publish Data with a specific version, you need to append a version component to the end of the
prefix. The version component must follow the aforementioned NDN naming conventions. For example,
the following command will publish the version 1449078495094 of the `/localhost/demo/gpl3` prefix:
ndnputchunks -Nt /localhost/demo/gpl3/v=1449078495094 < /usr/share/common-licenses/GPL-3
If the specified version component is not valid, ndnputchunks will exit with an error. If no version
component is specified, one will be generated and appended to the name.
### Retrieval
To retrieve the latest version of a published file, the following command can be used:
ndncatchunks /localhost/demo/gpl3
To fetch a specific version of a published file, you can specify the version number at the end of
the name. For example, if the version is known to be 1449078495094, the following command
will fetch that exact version of the file (without version discovery):
ndncatchunks -Nt /localhost/demo/gpl3/v=1449078495094
For more information, run the programs with `--help` as argument.
+88
View File
@@ -0,0 +1,88 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016-2022, Regents of the University of California,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Wentao Shang
* @author Steve DiBenedetto
* @author Andrea Tosatto
*/
#include "consumer.hpp"
namespace ndn::chunks {
Consumer::Consumer(security::Validator& validator, std::ostream& os)
: m_validator(validator)
, m_outputStream(os)
{
}
void
Consumer::run(unique_ptr<DiscoverVersion> discover, unique_ptr<PipelineInterests> pipeline)
{
m_discover = std::move(discover);
m_pipeline = std::move(pipeline);
m_nextToPrint = 0;
m_bufferedData.clear();
m_discover->onDiscoverySuccess.connect([this] (const Name& versionedName) {
m_pipeline->run(versionedName,
FORWARD_TO_MEM_FN(handleData),
[] (const std::string& msg) { NDN_THROW(std::runtime_error(msg)); });
});
m_discover->onDiscoveryFailure.connect([] (const std::string& msg) {
NDN_THROW(std::runtime_error(msg));
});
m_discover->run();
}
void
Consumer::handleData(const Data& data)
{
auto dataPtr = data.shared_from_this();
m_validator.validate(data,
[this, dataPtr] (const Data& data) {
if (data.getContentType() == ndn::tlv::ContentType_Nack) {
NDN_THROW(ApplicationNackError(data));
}
// 'data' passed to callback comes from DataValidationState and was not created with make_shared
m_bufferedData[getSegmentFromPacket(data)] = dataPtr;
writeInOrderData();
},
[] (const Data&, const security::ValidationError& error) {
NDN_THROW(DataValidationError(error));
});
}
void
Consumer::writeInOrderData()
{
for (auto it = m_bufferedData.begin();
it != m_bufferedData.end() && it->first == m_nextToPrint;
it = m_bufferedData.erase(it), ++m_nextToPrint) {
const Block& content = it->second->getContent();
m_outputStream.write(reinterpret_cast<const char*>(content.value()), content.value_size());
}
}
} // namespace ndn::chunks
+104
View File
@@ -0,0 +1,104 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016-2022, Regents of the University of California,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Wentao Shang
* @author Steve DiBenedetto
* @author Andrea Tosatto
*/
#ifndef NDN_TOOLS_CHUNKS_CATCHUNKS_CONSUMER_HPP
#define NDN_TOOLS_CHUNKS_CATCHUNKS_CONSUMER_HPP
#include "discover-version.hpp"
#include "pipeline-interests.hpp"
#include <ndn-cxx/security/validation-error.hpp>
#include <ndn-cxx/security/validator.hpp>
#include <map>
namespace ndn::chunks {
/**
* @brief Segmented version consumer
*
* Discover the latest version of the data published under a specified prefix, and retrieve all the
* segments associated to that version. The segments are fetched in order and written to a
* user-specified stream in the same order.
*/
class Consumer : noncopyable
{
public:
class ApplicationNackError : public std::runtime_error
{
public:
explicit
ApplicationNackError(const Data& data)
: std::runtime_error("Application generated Nack: " + boost::lexical_cast<std::string>(data))
{
}
};
class DataValidationError : public std::runtime_error
{
public:
explicit
DataValidationError(const security::ValidationError& error)
: std::runtime_error(boost::lexical_cast<std::string>(error))
{
}
};
/**
* @brief Create the consumer
*/
explicit
Consumer(security::Validator& validator, std::ostream& os = std::cout);
/**
* @brief Run the consumer
*/
void
run(unique_ptr<DiscoverVersion> discover, unique_ptr<PipelineInterests> pipeline);
private:
void
handleData(const Data& data);
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
void
writeInOrderData();
private:
security::Validator& m_validator;
std::ostream& m_outputStream;
unique_ptr<DiscoverVersion> m_discover;
unique_ptr<PipelineInterests> m_pipeline;
uint64_t m_nextToPrint = 0;
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
std::map<uint64_t, shared_ptr<const Data>> m_bufferedData;
};
} // namespace ndn::chunks
#endif // NDN_TOOLS_CHUNKS_CATCHUNKS_CONSUMER_HPP
+171
View File
@@ -0,0 +1,171 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016-2023, Regents of the University of California,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Andrea Tosatto
* @author Davide Pesavento
*/
#include "data-fetcher.hpp"
#include <cmath>
namespace ndn::chunks {
shared_ptr<DataFetcher>
DataFetcher::fetch(Face& face, const Interest& interest, int maxNackRetries, int maxTimeoutRetries,
DataCallback onData, FailureCallback onNack, FailureCallback onTimeout,
bool isVerbose)
{
auto dataFetcher = shared_ptr<DataFetcher>(new DataFetcher(face,
maxNackRetries,
maxTimeoutRetries,
std::move(onData),
std::move(onNack),
std::move(onTimeout),
isVerbose));
dataFetcher->expressInterest(interest, dataFetcher);
return dataFetcher;
}
DataFetcher::DataFetcher(Face& face, int maxNackRetries, int maxTimeoutRetries,
DataCallback onData, FailureCallback onNack, FailureCallback onTimeout,
bool isVerbose)
: m_face(face)
, m_scheduler(m_face.getIoContext())
, m_onData(std::move(onData))
, m_onNack(std::move(onNack))
, m_onTimeout(std::move(onTimeout))
, m_maxNackRetries(maxNackRetries)
, m_maxTimeoutRetries(maxTimeoutRetries)
, m_isVerbose(isVerbose)
{
BOOST_ASSERT(m_onData != nullptr);
}
void
DataFetcher::cancel()
{
if (isRunning()) {
m_isStopped = true;
m_pendingInterest.cancel();
m_scheduler.cancelAllEvents();
}
}
void
DataFetcher::expressInterest(const Interest& interest, const shared_ptr<DataFetcher>& self)
{
m_nCongestionRetries = 0;
m_pendingInterest = m_face.expressInterest(interest,
[=] (auto&&... args) { handleData(std::forward<decltype(args)>(args)..., self); },
[=] (auto&&... args) { handleNack(std::forward<decltype(args)>(args)..., self); },
[=] (auto&&... args) { handleTimeout(std::forward<decltype(args)>(args)..., self); });
}
void
DataFetcher::handleData(const Interest& interest, const Data& data,
const shared_ptr<DataFetcher>& self)
{
if (!isRunning())
return;
m_isStopped = true;
m_onData(interest, data);
}
void
DataFetcher::handleNack(const Interest& interest, const lp::Nack& nack,
const shared_ptr<DataFetcher>& self)
{
if (!isRunning())
return;
if (m_maxNackRetries != MAX_RETRIES_INFINITE)
++m_nNacks;
if (m_isVerbose)
std::cerr << "Received Nack with reason " << nack.getReason()
<< " for Interest " << interest << "\n";
if (m_nNacks <= m_maxNackRetries || m_maxNackRetries == MAX_RETRIES_INFINITE) {
Interest newInterest(interest);
newInterest.refreshNonce();
switch (nack.getReason()) {
case lp::NackReason::DUPLICATE: {
expressInterest(newInterest, self);
break;
}
case lp::NackReason::CONGESTION: {
time::milliseconds backoffTime(static_cast<uint64_t>(std::pow(2, m_nCongestionRetries)));
if (backoffTime > MAX_CONGESTION_BACKOFF_TIME) {
backoffTime = MAX_CONGESTION_BACKOFF_TIME;
}
else {
m_nCongestionRetries++;
}
m_scheduler.schedule(backoffTime, [=] { expressInterest(newInterest, self); });
break;
}
default: {
m_hasError = true;
if (m_onNack)
m_onNack(interest, "Could not retrieve data for " + interest.getName().toUri() +
", reason: " + boost::lexical_cast<std::string>(nack.getReason()));
break;
}
}
}
else {
m_hasError = true;
if (m_onNack)
m_onNack(interest, "Reached the maximum number of nack retries (" + to_string(m_maxNackRetries) +
") while retrieving data for " + interest.getName().toUri());
}
}
void
DataFetcher::handleTimeout(const Interest& interest, const shared_ptr<DataFetcher>& self)
{
if (!isRunning())
return;
if (m_maxTimeoutRetries != MAX_RETRIES_INFINITE)
++m_nTimeouts;
if (m_isVerbose)
std::cerr << "Timeout for Interest " << interest << "\n";
if (m_nTimeouts <= m_maxTimeoutRetries || m_maxTimeoutRetries == MAX_RETRIES_INFINITE) {
Interest newInterest(interest);
newInterest.refreshNonce();
expressInterest(newInterest, self);
}
else {
m_hasError = true;
if (m_onTimeout)
m_onTimeout(interest, "Reached the maximum number of timeout retries (" + to_string(m_maxTimeoutRetries) +
") while retrieving data for " + interest.getName().toUri());
}
}
} // namespace ndn::chunks
+130
View File
@@ -0,0 +1,130 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016-2022, Regents of the University of California,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Andrea Tosatto
* @author Davide Pesavento
*/
#ifndef NDN_TOOLS_CHUNKS_CATCHUNKS_DATA_FETCHER_HPP
#define NDN_TOOLS_CHUNKS_CATCHUNKS_DATA_FETCHER_HPP
#include "core/common.hpp"
namespace ndn::chunks {
/**
* @brief Fetch data for a given interest and handle timeout or nack error with retries.
*
* To instantiate a DataFetcher you need to use the static method fetch, this will also express the
* interest. After a timeout or nack is received, the same interest with a different nonce will be
* requested for a maximum number of time specified by the class user. There are separate retry
* counters for timeouts and nacks.
*
* A specified callback is called after the data matching the expressed interest is received. A
* different callback is called in case one of the retries counter reach the maximum. This callback
* can be different for timeout and nack. The data callback must be defined but the others callback
* are optional.
*
*/
class DataFetcher
{
public:
/**
* @brief means that there is no maximum number of retries,
* i.e. fetching must be retried indefinitely
*/
static constexpr int MAX_RETRIES_INFINITE = -1;
/**
* @brief ceiling value for backoff time used in congestion handling
*/
static constexpr time::milliseconds MAX_CONGESTION_BACKOFF_TIME = 10_s;
using FailureCallback = std::function<void(const Interest& interest, const std::string& reason)>;
/**
* @brief instantiate a DataFetcher object and start fetching data
*
* @param onData callback for segment correctly received, must not be empty
*/
static shared_ptr<DataFetcher>
fetch(Face& face, const Interest& interest, int maxNackRetries, int maxTimeoutRetries,
DataCallback onData, FailureCallback onTimeout, FailureCallback onNack,
bool isVerbose);
/**
* @brief stop data fetching without error and calling any callback
*/
void
cancel();
bool
isRunning() const
{
return !m_isStopped && !m_hasError;
}
bool
hasError() const
{
return m_hasError;
}
private:
DataFetcher(Face& face, int maxNackRetries, int maxTimeoutRetries,
DataCallback onData, FailureCallback onNack, FailureCallback onTimeout,
bool isVerbose);
void
expressInterest(const Interest& interest, const shared_ptr<DataFetcher>& self);
void
handleData(const Interest& interest, const Data& data, const shared_ptr<DataFetcher>& self);
void
handleNack(const Interest& interest, const lp::Nack& nack, const shared_ptr<DataFetcher>& self);
void
handleTimeout(const Interest& interest, const shared_ptr<DataFetcher>& self);
private:
Face& m_face;
Scheduler m_scheduler;
PendingInterestHandle m_pendingInterest;
DataCallback m_onData;
FailureCallback m_onNack;
FailureCallback m_onTimeout;
int m_maxNackRetries;
int m_maxTimeoutRetries;
int m_nNacks = 0;
int m_nTimeouts = 0;
uint32_t m_nCongestionRetries = 0;
bool m_isVerbose = false;
bool m_isStopped = false;
bool m_hasError = false;
};
} // namespace ndn::chunks
#endif // NDN_TOOLS_CHUNKS_CATCHUNKS_DATA_FETCHER_HPP
@@ -0,0 +1,95 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016-2022, Regents of the University of California,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Wentao Shang
* @author Steve DiBenedetto
* @author Andrea Tosatto
* @author Chavoosh Ghasemi
*/
#include "discover-version.hpp"
#include "data-fetcher.hpp"
#include <ndn-cxx/metadata-object.hpp>
namespace ndn::chunks {
DiscoverVersion::DiscoverVersion(Face& face, const Name& prefix, const Options& options)
: m_face(face)
, m_prefix(prefix)
, m_options(options)
{
}
void
DiscoverVersion::run()
{
if (m_options.disableVersionDiscovery || (!m_prefix.empty() && m_prefix[-1].isVersion())) {
onDiscoverySuccess(m_prefix);
return;
}
Interest interest = MetadataObject::makeDiscoveryInterest(m_prefix)
.setInterestLifetime(m_options.interestLifetime);
m_fetcher = DataFetcher::fetch(m_face, interest,
m_options.maxRetriesOnTimeoutOrNack,
m_options.maxRetriesOnTimeoutOrNack,
FORWARD_TO_MEM_FN(handleData),
[this] (const auto&, const auto& reason) {
onDiscoveryFailure(reason);
},
[this] (const auto&, const auto& reason) {
onDiscoveryFailure(reason);
},
m_options.isVerbose);
}
void
DiscoverVersion::handleData(const Interest& interest, const Data& data)
{
if (m_options.isVerbose)
std::cerr << "Data: " << data << "\n";
// make a metadata object from received metadata packet
MetadataObject mobject;
try {
mobject = MetadataObject(data);
}
catch (const tlv::Error& e) {
onDiscoveryFailure("Invalid metadata packet: "s + e.what());
return;
}
if (mobject.getVersionedName().empty() || !mobject.getVersionedName()[-1].isVersion()) {
onDiscoveryFailure(mobject.getVersionedName().toUri() + " is not a valid versioned name");
return;
}
if (m_options.isVerbose) {
std::cerr << "Discovered Data version: " << mobject.getVersionedName()[-1] << "\n";
}
onDiscoverySuccess(mobject.getVersionedName());
}
} // namespace ndn::chunks
@@ -0,0 +1,77 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016-2023, Regents of the University of California,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University.
*
* This file is part of ndn-tools (Named Data Networking Essential Tools).
* See AUTHORS.md for complete list of ndn-tools authors and contributors.
*
* ndn-tools 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.
*
* ndn-tools 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
* ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Wentao Shang
* @author Steve DiBenedetto
* @author Andrea Tosatto
* @author Chavoosh Ghasemi
*/
#ifndef NDN_TOOLS_CHUNKS_CATCHUNKS_DISCOVER_VERSION_HPP
#define NDN_TOOLS_CHUNKS_CATCHUNKS_DISCOVER_VERSION_HPP
#include "options.hpp"
#include <ndn-cxx/util/signal.hpp>
namespace ndn::chunks {
class DataFetcher;
/**
* @brief Service for discovering the latest Data version.
*
* DiscoverVersion's user is notified once after identifying the latest retrievable version or
* on failure to find any Data version.
*/
class DiscoverVersion
{
public:
DiscoverVersion(Face& face, const Name& prefix, const Options& options);
/**
* @brief Signal emitted when the versioned name of Data is found.
*/
signal::Signal<DiscoverVersion, Name> onDiscoverySuccess;
/**
* @brief Signal emitted when a failure occurs.
*/
signal::Signal<DiscoverVersion, std::string> onDiscoveryFailure;
void
run();
private:
void
handleData(const Interest& interest, const Data& data);
private:
Face& m_face;
const Name m_prefix;
const Options& m_options;
shared_ptr<DataFetcher> m_fetcher;
};
} // namespace ndn::chunks
#endif // NDN_TOOLS_CHUNKS_CATCHUNKS_DISCOVER_VERSION_HPP

Some files were not shown because too many files have changed in this diff Show More