face: Gracefully handle tlv::Error when received TLV block is malformed
Change-Id: I954b13d0e26fec7bc7fe23edcbc015dfac654ef8
Refs: #1494
diff --git a/daemon/face/face.cpp b/daemon/face/face.cpp
index d0d42db..46dbcf6 100644
--- a/daemon/face/face.cpp
+++ b/daemon/face/face.cpp
@@ -90,24 +90,29 @@
bool
Face::decodeAndDispatchInput(const Block& element)
{
- /// \todo Ensure lazy field decoding process
+ try {
+ /// \todo Ensure lazy field decoding process
- if (element.type() == tlv::Interest)
- {
- shared_ptr<Interest> i = make_shared<Interest>();
- i->wireDecode(element);
- this->onReceiveInterest(*i);
- }
- else if (element.type() == tlv::Data)
- {
- shared_ptr<Data> d = make_shared<Data>();
- d->wireDecode(element);
- this->onReceiveData(*d);
- }
- else
+ if (element.type() == tlv::Interest)
+ {
+ shared_ptr<Interest> i = make_shared<Interest>();
+ i->wireDecode(element);
+ this->onReceiveInterest(*i);
+ }
+ else if (element.type() == tlv::Data)
+ {
+ shared_ptr<Data> d = make_shared<Data>();
+ d->wireDecode(element);
+ this->onReceiveData(*d);
+ }
+ else
+ return false;
+
+ return true;
+ }
+ catch (tlv::Error&) {
return false;
-
- return true;
+ }
}
} //namespace nfd
diff --git a/daemon/face/local-face.hpp b/daemon/face/local-face.hpp
index 118dce7..e1c34c3 100644
--- a/daemon/face/local-face.hpp
+++ b/daemon/face/local-face.hpp
@@ -138,47 +138,52 @@
inline bool
LocalFace::decodeAndDispatchInput(const Block& element)
{
- const Block& payload = ndn::nfd::LocalControlHeader::getPayload(element);
+ try {
+ const Block& payload = ndn::nfd::LocalControlHeader::getPayload(element);
- // If received LocalControlHeader, but it is not enabled on the face
- if ((&payload != &element) && !this->isLocalControlHeaderEnabled())
+ // If received LocalControlHeader, but it is not enabled on the face
+ if ((&payload != &element) && !this->isLocalControlHeaderEnabled())
+ return false;
+
+ if (payload.type() == tlv::Interest)
+ {
+ shared_ptr<Interest> i = make_shared<Interest>();
+ i->wireDecode(payload);
+ if (&payload != &element)
+ {
+ i->getLocalControlHeader().wireDecode(element,
+ false,
+ this->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
+ }
+
+ this->onReceiveInterest(*i);
+ }
+ else if (payload.type() == tlv::Data)
+ {
+ shared_ptr<Data> d = make_shared<Data>();
+ d->wireDecode(payload);
+
+ /// \todo Uncomment and correct the following when we have more
+ /// options in LocalControlHeader that apply for incoming
+ /// Data packets (if ever)
+ // if (&payload != &element)
+ // {
+ //
+ // d->getLocalControlHeader().wireDecode(element,
+ // false,
+ // false);
+ // }
+
+ this->onReceiveData(*d);
+ }
+ else
+ return false;
+
+ return true;
+ }
+ catch (tlv::Error&) {
return false;
-
- if (payload.type() == tlv::Interest)
- {
- shared_ptr<Interest> i = make_shared<Interest>();
- i->wireDecode(payload);
- if (&payload != &element)
- {
- i->getLocalControlHeader().wireDecode(element,
- false,
- this->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
- }
-
- this->onReceiveInterest(*i);
- }
- else if (payload.type() == tlv::Data)
- {
- shared_ptr<Data> d = make_shared<Data>();
- d->wireDecode(payload);
-
- /// \todo Uncomment and correct the following when we have more
- /// options in LocalControlHeader that apply for incoming
- /// Data packets (if ever)
- // if (&payload != &element)
- // {
- //
- // d->getLocalControlHeader().wireDecode(element,
- // false,
- // false);
- // }
-
- this->onReceiveData(*d);
- }
- else
- return false;
-
- return true;
+ }
}
inline bool
diff --git a/tests/daemon/face/dummy-stream-sender.hpp b/tests/daemon/face/dummy-stream-sender.hpp
new file mode 100644
index 0000000..af0e114
--- /dev/null
+++ b/tests/daemon/face/dummy-stream-sender.hpp
@@ -0,0 +1,116 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NFD_TESTS_DAEMON_FACE_DUMMY_STREAM_SENDER_HPP
+#define NFD_TESTS_DAEMON_FACE_DUMMY_STREAM_SENDER_HPP
+
+#include "core/scheduler.hpp"
+#include "core/global-io.hpp"
+
+namespace nfd {
+namespace tests {
+
+
+template<class Protocol, class Dataset>
+class DummyStreamSender : public Dataset
+{
+public:
+ typedef typename Protocol::endpoint Endpoint;
+ typedef typename Protocol::socket Socket;
+
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+ };
+
+ DummyStreamSender()
+ : socket(getGlobalIoService())
+ {
+ }
+
+ void
+ start(const Endpoint& endpoint)
+ {
+ socket.async_connect(endpoint,
+ bind(&DummyStreamSender::onSuccessfullConnect, this, _1));
+ }
+
+ void
+ onSuccessfullConnect(const boost::system::error_code& error)
+ {
+ if (error)
+ {
+ throw Error("Connection aborted");
+ }
+
+ // This value may need to be adjusted if some dataset exceeds 100k
+ socket.set_option(boost::asio::socket_base::send_buffer_size(100000));
+
+ for (typename Dataset::Container::iterator i = this->data.begin();
+ i != this->data.end(); ++i)
+ {
+ socket.async_send(boost::asio::buffer(*i),
+ bind(&DummyStreamSender::onSendFinished, this, _1, false));
+ }
+
+ socket.async_send(boost::asio::buffer(static_cast<const uint8_t*>(0), 0),
+ bind(&DummyStreamSender::onSendFinished, this, _1, true));
+ }
+
+ void
+ onSendFinished(const boost::system::error_code& error, bool isFinal)
+ {
+ if (error) {
+ throw Error("Connection aborted");
+ }
+
+ if (isFinal) {
+ scheduler::schedule(ndn::time::seconds(1),
+ bind(&DummyStreamSender::stop, this));
+ }
+ }
+
+ void
+ stop()
+ {
+ // Terminate test
+ boost::system::error_code error;
+ socket.shutdown(Socket::shutdown_both, error);
+ socket.close(error);
+ }
+
+public:
+ Socket socket;
+};
+
+} // namespace tests
+} // namespace nfd
+
+#endif // NFD_TESTS_DAEMON_FACE_DUMMY_STREAM_SENDER_HPP
diff --git a/tests/daemon/face/packet-datasets.cpp b/tests/daemon/face/packet-datasets.cpp
new file mode 100644
index 0000000..86e01cd
--- /dev/null
+++ b/tests/daemon/face/packet-datasets.cpp
@@ -0,0 +1,66 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "packet-datasets.hpp"
+#include "tests/test-common.hpp"
+
+#include <boost/foreach.hpp>
+
+namespace nfd {
+namespace tests {
+
+BOOST_FIXTURE_TEST_SUITE(Datasets, BaseFixture)
+
+BOOST_AUTO_TEST_CASE(Currupted)
+{
+ {
+ typedef CorruptedInterest Dataset;
+ Dataset dataset;
+
+ BOOST_FOREACH(Dataset::Container::value_type& data, dataset.data)
+ {
+ Block block(data.buf(), data.size());
+
+ BOOST_CHECK_THROW((Interest(block)), tlv::Error);
+ }
+ }
+
+ {
+ typedef CorruptedInterestWithLocalControlHeader Dataset;
+ Dataset dataset;
+
+ BOOST_FOREACH(Dataset::Container::value_type& data, dataset.data)
+ {
+ Block block(data.buf(), data.size());
+
+ BOOST_CHECK_THROW(ndn::nfd::LocalControlHeader::getPayload(block), tlv::Error);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace nfd
diff --git a/tests/daemon/face/packet-datasets.hpp b/tests/daemon/face/packet-datasets.hpp
new file mode 100644
index 0000000..373f4e6
--- /dev/null
+++ b/tests/daemon/face/packet-datasets.hpp
@@ -0,0 +1,91 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NFD_TESTS_DAEMON_FACE_PACKET_DATASETS_HPP
+#define NFD_TESTS_DAEMON_FACE_PACKET_DATASETS_HPP
+
+#include "tests/test-common.hpp"
+
+namespace nfd {
+namespace tests {
+
+class CorruptedInterestWithLocalControlHeader
+{
+public:
+ typedef std::vector<ndn::Buffer> Container;
+
+ static std::string
+ getName()
+ {
+ return "CorruptedInterestWithLocalControlHeader";
+ }
+
+ CorruptedInterestWithLocalControlHeader()
+ {
+ static const uint8_t interest[] = {
+ 0x50, 0x22, 0x51, 0x81, 0x0a, 0x05, 0x1d, 0x07, 0x14, 0x08, 0x05, 0x6c, 0x6f, 0x63, 0x61,
+ 0x6c, 0x08, 0x03, 0x6e, 0x64, 0x6e, 0x08, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x09,
+ 0x02, 0x12, 0x00, 0x0a, 0x01, 0x01
+ };
+
+ data.push_back(ndn::Buffer(interest, sizeof(interest)));
+ }
+public:
+ Container data;
+};
+
+class CorruptedInterest
+{
+public:
+ typedef std::vector<ndn::Buffer> Container;
+
+ static std::string
+ getName()
+ {
+ return "CorruptedInterest";
+ }
+
+ CorruptedInterest()
+ {
+ static const uint8_t interest[] = {
+ 0x05, 0x1d, 0x07, 0x84, 0x08, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x08, 0x03, 0x6e, 0x64,
+ 0x6e, 0x08, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x09, 0x02, 0x12, 0x00, 0x0a, 0x01,
+ 0x01
+ };
+
+ data.push_back(ndn::Buffer(interest, sizeof(interest)));
+ }
+public:
+ Container data;
+};
+
+
+typedef boost::mpl::vector< CorruptedInterestWithLocalControlHeader,
+ CorruptedInterest> CorruptedPackets;
+
+} // namespace tests
+} // namespace nfd
+
+#endif // NFD_TESTS_DAEMON_FACE_PACKET_DATASETS_HPP
diff --git a/tests/daemon/face/tcp.cpp b/tests/daemon/face/tcp.cpp
index bc3ac30..166f257 100644
--- a/tests/daemon/face/tcp.cpp
+++ b/tests/daemon/face/tcp.cpp
@@ -23,10 +23,14 @@
**/
#include "face/tcp-factory.hpp"
+#include "core/resolver.hpp"
+#include "core/network-interface.hpp"
#include <ndn-cxx/security/key-chain.hpp>
#include "tests/test-common.hpp"
#include "tests/limited-io.hpp"
+#include "dummy-stream-sender.hpp"
+#include "packet-datasets.hpp"
namespace nfd {
namespace tests {
@@ -223,28 +227,19 @@
// integrated tests needs to check that TcpFace for non-loopback fails these tests...
- Interest interest1("ndn:/TpnzGvW9R");
- Data data1 ("ndn:/KfczhUqVix");
- data1.setContent(0, 0);
- Interest interest2("ndn:/QWiIMfj5sL");
- Data data2 ("ndn:/XNBV796f");
- data2.setContent(0, 0);
+ shared_ptr<Interest> interest1 = makeInterest("ndn:/TpnzGvW9R");
+ shared_ptr<Data> data1 = makeData("ndn:/KfczhUqVix");
+ shared_ptr<Interest> interest2 = makeInterest("ndn:/QWiIMfj5sL");
+ shared_ptr<Data> data2 = makeData("ndn:/XNBV796f");
- ndn::SignatureSha256WithRsa fakeSignature;
- fakeSignature.setValue(ndn::dataBlock(tlv::SignatureValue, reinterpret_cast<const uint8_t*>(0), 0));
-
- // set fake signature on data1 and data2
- data1.setSignature(fakeSignature);
- data2.setSignature(fakeSignature);
-
- face1->sendInterest(interest1);
- face1->sendInterest(interest1);
- face1->sendInterest(interest1);
- face1->sendData (data1 );
- face2->sendInterest(interest2);
- face2->sendData (data2 );
- face2->sendData (data2 );
- face2->sendData (data2 );
+ face1->sendInterest(*interest1);
+ face1->sendInterest(*interest1);
+ face1->sendInterest(*interest1);
+ face1->sendData (*data1 );
+ face2->sendInterest(*interest2);
+ face2->sendData (*data2 );
+ face2->sendData (*data2 );
+ face2->sendData (*data2 );
BOOST_CHECK_MESSAGE(limitedIo.run(8, time::seconds(10)) == LimitedIo::EXCEED_OPS,
"TcpChannel error: cannot send or receive Interest/Data packets");
@@ -255,10 +250,10 @@
BOOST_REQUIRE_EQUAL(face2_receivedInterests.size(), 3);
BOOST_REQUIRE_EQUAL(face2_receivedDatas .size(), 1);
- BOOST_CHECK_EQUAL(face1_receivedInterests[0].getName(), interest2.getName());
- BOOST_CHECK_EQUAL(face1_receivedDatas [0].getName(), data2.getName());
- BOOST_CHECK_EQUAL(face2_receivedInterests[0].getName(), interest1.getName());
- BOOST_CHECK_EQUAL(face2_receivedDatas [0].getName(), data1.getName());
+ BOOST_CHECK_EQUAL(face1_receivedInterests[0].getName(), interest2->getName());
+ BOOST_CHECK_EQUAL(face1_receivedDatas [0].getName(), data2->getName());
+ BOOST_CHECK_EQUAL(face2_receivedInterests[0].getName(), interest1->getName());
+ BOOST_CHECK_EQUAL(face2_receivedDatas [0].getName(), data1->getName());
const FaceCounters& counters1 = face1->getCounters();
BOOST_CHECK_EQUAL(counters1.getNInInterests() , 1);
@@ -309,24 +304,15 @@
// integrated tests needs to check that TcpFace for non-loopback fails these tests...
- Interest interest1("ndn:/TpnzGvW9R");
- Data data1 ("ndn:/KfczhUqVix");
- data1.setContent(0, 0);
- Interest interest2("ndn:/QWiIMfj5sL");
- Data data2 ("ndn:/XNBV796f");
- data2.setContent(0, 0);
+ shared_ptr<Interest> interest1 = makeInterest("ndn:/TpnzGvW9R");
+ shared_ptr<Data> data1 = makeData("ndn:/KfczhUqVix");
+ shared_ptr<Interest> interest2 = makeInterest("ndn:/QWiIMfj5sL");
+ shared_ptr<Data> data2 = makeData("ndn:/XNBV796f");
- ndn::SignatureSha256WithRsa fakeSignature;
- fakeSignature.setValue(ndn::dataBlock(tlv::SignatureValue, reinterpret_cast<const uint8_t*>(0), 0));
-
- // set fake signature on data1 and data2
- data1.setSignature(fakeSignature);
- data2.setSignature(fakeSignature);
-
- face1->sendInterest(interest1);
- face1->sendData (data1 );
- face2->sendInterest(interest2);
- face2->sendData (data2 );
+ face1->sendInterest(*interest1);
+ face1->sendData (*data1 );
+ face2->sendInterest(*interest2);
+ face2->sendData (*data2 );
BOOST_CHECK_MESSAGE(limitedIo.run(4, time::seconds(10)) == LimitedIo::EXCEED_OPS,
"TcpChannel error: cannot send or receive Interest/Data packets");
@@ -337,10 +323,10 @@
BOOST_REQUIRE_EQUAL(face2_receivedInterests.size(), 1);
BOOST_REQUIRE_EQUAL(face2_receivedDatas .size(), 1);
- BOOST_CHECK_EQUAL(face1_receivedInterests[0].getName(), interest2.getName());
- BOOST_CHECK_EQUAL(face1_receivedDatas [0].getName(), data2.getName());
- BOOST_CHECK_EQUAL(face2_receivedInterests[0].getName(), interest1.getName());
- BOOST_CHECK_EQUAL(face2_receivedDatas [0].getName(), data1.getName());
+ BOOST_CHECK_EQUAL(face1_receivedInterests[0].getName(), interest2->getName());
+ BOOST_CHECK_EQUAL(face1_receivedDatas [0].getName(), data2->getName());
+ BOOST_CHECK_EQUAL(face2_receivedInterests[0].getName(), interest1->getName());
+ BOOST_CHECK_EQUAL(face2_receivedDatas [0].getName(), data1->getName());
}
BOOST_FIXTURE_TEST_CASE(MultipleAccepts, EndToEndFixture)
@@ -434,6 +420,127 @@
}
+
+
+class SimpleEndToEndFixture : protected BaseFixture
+{
+public:
+ void
+ onFaceCreated(const shared_ptr<Face>& face)
+ {
+ face->onReceiveInterest +=
+ bind(&SimpleEndToEndFixture::onReceiveInterest, this, _1);
+ face->onReceiveData +=
+ bind(&SimpleEndToEndFixture::onReceiveData, this, _1);
+ face->onFail +=
+ bind(&SimpleEndToEndFixture::onFail, this, face);
+
+ if (static_cast<bool>(dynamic_pointer_cast<LocalFace>(face))) {
+ static_pointer_cast<LocalFace>(face)->setLocalControlHeaderFeature(
+ LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);
+
+ static_pointer_cast<LocalFace>(face)->setLocalControlHeaderFeature(
+ LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);
+ }
+
+ limitedIo.afterOp();
+ }
+
+ void
+ onConnectFailed(const std::string& reason)
+ {
+ BOOST_CHECK_MESSAGE(false, reason);
+
+ limitedIo.afterOp();
+ }
+
+ void
+ onReceiveInterest(const Interest& interest)
+ {
+ receivedInterests.push_back(interest);
+
+ limitedIo.afterOp();
+ }
+
+ void
+ onReceiveData(const Data& data)
+ {
+ receivedDatas.push_back(data);
+
+ limitedIo.afterOp();
+ }
+
+ void
+ onFail(const shared_ptr<Face>& face)
+ {
+ limitedIo.afterOp();
+ }
+
+public:
+ LimitedIo limitedIo;
+
+ std::vector<Interest> receivedInterests;
+ std::vector<Data> receivedDatas;
+};
+
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(LocalFaceCorruptedInput, Dataset,
+ CorruptedPackets, SimpleEndToEndFixture)
+{
+ TcpFactory factory;
+
+ shared_ptr<TcpChannel> channel = factory.createChannel("127.0.0.1", "20070");
+ channel->listen(bind(&SimpleEndToEndFixture::onFaceCreated, this, _1),
+ bind(&SimpleEndToEndFixture::onConnectFailed, this, _1));
+ BOOST_REQUIRE_EQUAL(channel->isListening(), true);
+
+ DummyStreamSender<boost::asio::ip::tcp, Dataset> sender;
+ sender.start(Resolver<boost::asio::ip::tcp>::syncResolve("127.0.0.1", "20070"));
+
+ BOOST_CHECK_MESSAGE(limitedIo.run(LimitedIo::UNLIMITED_OPS,
+ time::seconds(1)) == LimitedIo::EXCEED_TIME,
+ "Exception thrown for " + Dataset::getName());
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(FaceCorruptedInput, Dataset,
+ CorruptedPackets, SimpleEndToEndFixture)
+{
+ // tests with non-local Face
+ std::string someIpv4Address;
+ std::list< shared_ptr<NetworkInterfaceInfo> > ifs = listNetworkInterfaces();
+ for (std::list< shared_ptr<NetworkInterfaceInfo> >::const_iterator i = ifs.begin();
+ i != ifs.end();
+ ++i)
+ {
+ if (!(*i)->isLoopback() && (*i)->isUp() && !(*i)->ipv4Addresses.empty())
+ {
+ someIpv4Address = (*i)->ipv4Addresses[0].to_string();
+ break;
+ }
+ }
+ if (someIpv4Address.empty())
+ {
+ BOOST_TEST_MESSAGE("Test with non-local Face cannot be run "
+ "(no non-local interface with IPv4 address available)");
+ return;
+ }
+
+ TcpFactory factory;
+
+ shared_ptr<TcpChannel> channel = factory.createChannel(someIpv4Address, "20070");
+ channel->listen(bind(&SimpleEndToEndFixture::onFaceCreated, this, _1),
+ bind(&SimpleEndToEndFixture::onConnectFailed, this, _1));
+ BOOST_REQUIRE_EQUAL(channel->isListening(), true);
+
+
+ DummyStreamSender<boost::asio::ip::tcp, Dataset> sender;
+ sender.start(Resolver<boost::asio::ip::tcp>::syncResolve(someIpv4Address, "20070"));
+
+ BOOST_CHECK_MESSAGE(limitedIo.run(LimitedIo::UNLIMITED_OPS,
+ time::seconds(1)) == LimitedIo::EXCEED_TIME,
+ "Exception thrown for " + Dataset::getName());
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace tests
diff --git a/tests/daemon/face/unix-stream.cpp b/tests/daemon/face/unix-stream.cpp
index 4181aa1..06ff5d3 100644
--- a/tests/daemon/face/unix-stream.cpp
+++ b/tests/daemon/face/unix-stream.cpp
@@ -26,6 +26,8 @@
#include "tests/test-common.hpp"
#include "tests/limited-io.hpp"
+#include "dummy-stream-sender.hpp"
+#include "packet-datasets.hpp"
namespace nfd {
namespace tests {
@@ -178,28 +180,19 @@
face2->onReceiveData +=
bind(&EndToEndFixture::face2_onReceiveData, this, _1);
- Interest interest1("ndn:/TpnzGvW9R");
- Data data1 ("ndn:/KfczhUqVix");
- data1.setContent(0, 0);
- Interest interest2("ndn:/QWiIMfj5sL");
- Data data2 ("ndn:/XNBV796f");
- data2.setContent(0, 0);
+ shared_ptr<Interest> interest1 = makeInterest("ndn:/TpnzGvW9R");
+ shared_ptr<Data> data1 = makeData("ndn:/KfczhUqVix");
+ shared_ptr<Interest> interest2 = makeInterest("ndn:/QWiIMfj5sL");
+ shared_ptr<Data> data2 = makeData("ndn:/XNBV796f");
- ndn::SignatureSha256WithRsa fakeSignature;
- fakeSignature.setValue(ndn::dataBlock(tlv::SignatureValue, reinterpret_cast<const uint8_t*>(0), 0));
-
- // set fake signature on data1 and data2
- data1.setSignature(fakeSignature);
- data2.setSignature(fakeSignature);
-
- face1->sendInterest(interest1);
- face1->sendInterest(interest1);
- face1->sendInterest(interest1);
- face1->sendData (data1 );
- face2->sendInterest(interest2);
- face2->sendData (data2 );
- face2->sendData (data2 );
- face2->sendData (data2 );
+ face1->sendInterest(*interest1);
+ face1->sendInterest(*interest1);
+ face1->sendInterest(*interest1);
+ face1->sendData (*data1 );
+ face2->sendInterest(*interest2);
+ face2->sendData (*data2 );
+ face2->sendData (*data2 );
+ face2->sendData (*data2 );
BOOST_CHECK_MESSAGE(limitedIo.run(8, time::seconds(1)) == LimitedIo::EXCEED_OPS,
"UnixStreamChannel error: cannot send or receive Interest/Data packets");
@@ -209,10 +202,10 @@
BOOST_REQUIRE_EQUAL(face2_receivedInterests.size(), 3);
BOOST_REQUIRE_EQUAL(face2_receivedDatas .size(), 1);
- BOOST_CHECK_EQUAL(face1_receivedInterests[0].getName(), interest2.getName());
- BOOST_CHECK_EQUAL(face1_receivedDatas [0].getName(), data2.getName());
- BOOST_CHECK_EQUAL(face2_receivedInterests[0].getName(), interest1.getName());
- BOOST_CHECK_EQUAL(face2_receivedDatas [0].getName(), data1.getName());
+ BOOST_CHECK_EQUAL(face1_receivedInterests[0].getName(), interest2->getName());
+ BOOST_CHECK_EQUAL(face1_receivedDatas [0].getName(), data2->getName());
+ BOOST_CHECK_EQUAL(face2_receivedInterests[0].getName(), interest1->getName());
+ BOOST_CHECK_EQUAL(face2_receivedDatas [0].getName(), data1->getName());
const FaceCounters& counters1 = face1->getCounters();
BOOST_CHECK_EQUAL(counters1.getNInInterests() , 1);
@@ -267,24 +260,15 @@
face2->onReceiveInterest += bind(&EndToEndFixture::face2_onReceiveInterest, this, _1);
face2->onReceiveData += bind(&EndToEndFixture::face2_onReceiveData, this, _1);
- Interest interest1("ndn:/TpnzGvW9R");
- Data data1 ("ndn:/KfczhUqVix");
- data1.setContent(0, 0);
- Interest interest2("ndn:/QWiIMfj5sL");
- Data data2 ("ndn:/XNBV796f");
- data2.setContent(0, 0);
+ shared_ptr<Interest> interest1 = makeInterest("ndn:/TpnzGvW9R");
+ shared_ptr<Data> data1 = makeData("ndn:/KfczhUqVix");
+ shared_ptr<Interest> interest2 = makeInterest("ndn:/QWiIMfj5sL");
+ shared_ptr<Data> data2 = makeData("ndn:/XNBV796f");
- ndn::SignatureSha256WithRsa fakeSignature;
- fakeSignature.setValue(ndn::dataBlock(tlv::SignatureValue, reinterpret_cast<const uint8_t*>(0), 0));
-
- // set fake signature on data1 and data2
- data1.setSignature(fakeSignature);
- data2.setSignature(fakeSignature);
-
- face1->sendInterest(interest1);
- face1->sendData (data1 );
- face2->sendInterest(interest2);
- face2->sendData (data2 );
+ face1->sendInterest(*interest1);
+ face1->sendData (*data1 );
+ face2->sendInterest(*interest2);
+ face2->sendData (*data2 );
BOOST_CHECK_MESSAGE(limitedIo.run(4, time::seconds(1)) == LimitedIo::EXCEED_OPS,
"UnixStreamChannel error: cannot send or receive Interest/Data packets");
@@ -294,10 +278,10 @@
BOOST_REQUIRE_EQUAL(face2_receivedInterests.size(), 1);
BOOST_REQUIRE_EQUAL(face2_receivedDatas .size(), 1);
- BOOST_CHECK_EQUAL(face1_receivedInterests[0].getName(), interest2.getName());
- BOOST_CHECK_EQUAL(face1_receivedDatas [0].getName(), data2.getName());
- BOOST_CHECK_EQUAL(face2_receivedInterests[0].getName(), interest1.getName());
- BOOST_CHECK_EQUAL(face2_receivedDatas [0].getName(), data1.getName());
+ BOOST_CHECK_EQUAL(face1_receivedInterests[0].getName(), interest2->getName());
+ BOOST_CHECK_EQUAL(face1_receivedDatas [0].getName(), data2->getName());
+ BOOST_CHECK_EQUAL(face2_receivedInterests[0].getName(), interest1->getName());
+ BOOST_CHECK_EQUAL(face2_receivedDatas [0].getName(), data1->getName());
}
static inline void
@@ -329,19 +313,8 @@
face2->onReceiveData +=
bind(&EndToEndFixture::face2_onReceiveData, this, _1);
- Interest interest1("ndn:/TpnzGvW9R");
- Data data1 ("ndn:/KfczhUqVix");
- data1.setContent(0, 0);
- Interest interest2("ndn:/QWiIMfj5sL");
- Data data2 ("ndn:/XNBV796f");
- data2.setContent(0, 0);
-
- ndn::SignatureSha256WithRsa fakeSignature;
- fakeSignature.setValue(ndn::dataBlock(tlv::SignatureValue, reinterpret_cast<const uint8_t*>(0), 0));
-
- // set fake signature on data1 and data2
- data1.setSignature(fakeSignature);
- data2.setSignature(fakeSignature);
+ shared_ptr<Interest> interest1 = makeInterest("ndn:/TpnzGvW9R");
+ shared_ptr<Data> data1 = makeData("ndn:/KfczhUqVix");
face1->setLocalControlHeaderFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);
face1->setLocalControlHeaderFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);
@@ -357,15 +330,15 @@
////////////////////////////////////////////////////////
- interest1.setIncomingFaceId(11);
- interest1.setNextHopFaceId(111);
+ interest1->setIncomingFaceId(11);
+ interest1->setNextHopFaceId(111);
- face1->sendInterest(interest1);
+ face1->sendInterest(*interest1);
- data1.setIncomingFaceId(22);
- data1.getLocalControlHeader().setNextHopFaceId(222);
+ data1->setIncomingFaceId(22);
+ data1->getLocalControlHeader().setNextHopFaceId(222);
- face1->sendData (data1);
+ face1->sendData(*data1);
//
@@ -387,14 +360,14 @@
using namespace boost::asio;
std::vector<const_buffer> interestWithHeader;
- Block iHeader = interest1.getLocalControlHeader().wireEncode(interest1, true, true);
- Block iPayload = interest1.wireEncode();
+ Block iHeader = interest1->getLocalControlHeader().wireEncode(*interest1, true, true);
+ Block iPayload = interest1->wireEncode();
interestWithHeader.push_back(buffer(iHeader.wire(), iHeader.size()));
interestWithHeader.push_back(buffer(iPayload.wire(), iPayload.size()));
std::vector<const_buffer> dataWithHeader;
- Block dHeader = data1.getLocalControlHeader().wireEncode(data1, true, true);
- Block dPayload = data1.wireEncode();
+ Block dHeader = data1->getLocalControlHeader().wireEncode(*data1, true, true);
+ Block dPayload = data1->wireEncode();
dataWithHeader.push_back(buffer(dHeader.wire(), dHeader.size()));
dataWithHeader.push_back(buffer(dPayload.wire(), dPayload.size()));
@@ -417,6 +390,87 @@
BOOST_CHECK_EQUAL(face1_receivedDatas[0].getLocalControlHeader().hasNextHopFaceId(), false);
}
+
+class SimpleEndToEndFixture : protected BaseFixture
+{
+public:
+ void
+ onFaceCreated(const shared_ptr<Face>& face)
+ {
+ face->onReceiveInterest +=
+ bind(&SimpleEndToEndFixture::onReceiveInterest, this, _1);
+ face->onReceiveData +=
+ bind(&SimpleEndToEndFixture::onReceiveData, this, _1);
+ face->onFail +=
+ bind(&SimpleEndToEndFixture::onFail, this, face);
+
+ if (static_cast<bool>(dynamic_pointer_cast<LocalFace>(face))) {
+ static_pointer_cast<LocalFace>(face)->setLocalControlHeaderFeature(
+ LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);
+
+ static_pointer_cast<LocalFace>(face)->setLocalControlHeaderFeature(
+ LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);
+ }
+
+ limitedIo.afterOp();
+ }
+
+ void
+ onConnectFailed(const std::string& reason)
+ {
+ BOOST_CHECK_MESSAGE(false, reason);
+
+ limitedIo.afterOp();
+ }
+
+ void
+ onReceiveInterest(const Interest& interest)
+ {
+ receivedInterests.push_back(interest);
+
+ limitedIo.afterOp();
+ }
+
+ void
+ onReceiveData(const Data& data)
+ {
+ receivedDatas.push_back(data);
+
+ limitedIo.afterOp();
+ }
+
+ void
+ onFail(const shared_ptr<Face>& face)
+ {
+ limitedIo.afterOp();
+ }
+
+public:
+ LimitedIo limitedIo;
+
+ std::vector<Interest> receivedInterests;
+ std::vector<Data> receivedDatas;
+};
+
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(CorruptedInput, Dataset,
+ CorruptedPackets, SimpleEndToEndFixture)
+{
+ UnixStreamFactory factory;
+
+ shared_ptr<UnixStreamChannel> channel = factory.createChannel(CHANNEL_PATH1);
+ channel->listen(bind(&SimpleEndToEndFixture::onFaceCreated, this, _1),
+ bind(&SimpleEndToEndFixture::onConnectFailed, this, _1));
+
+ DummyStreamSender<stream_protocol, Dataset> sender;
+ sender.start(stream_protocol::endpoint(CHANNEL_PATH1));
+
+ BOOST_CHECK_MESSAGE(limitedIo.run(LimitedIo::UNLIMITED_OPS,
+ time::seconds(1)) == LimitedIo::EXCEED_TIME,
+ "Exception thrown for " + Dataset::getName());
+}
+
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace tests