Refactor management protocol specific option types to ControlParameters Add control parameter field enforcement Add missing control response "success" message bodies Update fib management protocol response codes and behavior Merge local control header manager into face manager Refactor references of nfd::LocalControlHeaderFeature enum to ndn::nfd::LocalControlFeature Remove "control-header" privilege from default configuration refs: #1397, #1399, #1400 Change-Id: Id042daf00b3cee1f1c7fa38d2e4a4ff6d95c15c6
409 lines
14 KiB
C++
409 lines
14 KiB
C++
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
|
/**
|
|
* Copyright (C) 2014 Named Data Networking Project
|
|
* See COPYING for copyright and distribution information.
|
|
*/
|
|
|
|
#include "face/unix-stream-factory.hpp"
|
|
#include <ndn-cpp-dev/security/key-chain.hpp>
|
|
|
|
#include "tests/test-common.hpp"
|
|
#include "tests/core/limited-io.hpp"
|
|
|
|
namespace nfd {
|
|
namespace tests {
|
|
|
|
using namespace boost::asio::local;
|
|
|
|
#define CHANNEL_PATH1 "unix-stream-test.1.sock"
|
|
#define CHANNEL_PATH2 "unix-stream-test.2.sock"
|
|
|
|
BOOST_FIXTURE_TEST_SUITE(FaceUnixStream, BaseFixture)
|
|
|
|
BOOST_AUTO_TEST_CASE(ChannelMap)
|
|
{
|
|
UnixStreamFactory factory;
|
|
|
|
shared_ptr<UnixStreamChannel> channel1 = factory.createChannel(CHANNEL_PATH1);
|
|
shared_ptr<UnixStreamChannel> channel1a = factory.createChannel(CHANNEL_PATH1);
|
|
BOOST_CHECK_EQUAL(channel1, channel1a);
|
|
std::string channel1uri = channel1->getUri().toString();
|
|
BOOST_CHECK_EQUAL(channel1uri.find("unix:///"), 0); // third '/' is the path separator
|
|
BOOST_CHECK_EQUAL(channel1uri.rfind(CHANNEL_PATH1),
|
|
channel1uri.size() - std::string(CHANNEL_PATH1).size());
|
|
|
|
shared_ptr<UnixStreamChannel> channel2 = factory.createChannel(CHANNEL_PATH2);
|
|
BOOST_CHECK_NE(channel1, channel2);
|
|
}
|
|
|
|
class EndToEndFixture : protected BaseFixture
|
|
{
|
|
public:
|
|
void
|
|
client_onConnect(const boost::system::error_code& error)
|
|
{
|
|
BOOST_CHECK_MESSAGE(!error, error.message());
|
|
|
|
m_limitedIo.afterOp();
|
|
}
|
|
|
|
void
|
|
channel1_onFaceCreated(const shared_ptr<Face>& newFace)
|
|
{
|
|
BOOST_CHECK(!static_cast<bool>(m_face1));
|
|
m_face1 = static_pointer_cast<UnixStreamFace>(newFace);
|
|
m_face1->onReceiveInterest +=
|
|
bind(&EndToEndFixture::face1_onReceiveInterest, this, _1);
|
|
m_face1->onReceiveData +=
|
|
bind(&EndToEndFixture::face1_onReceiveData, this, _1);
|
|
|
|
m_limitedIo.afterOp();
|
|
}
|
|
|
|
void
|
|
channel1_onConnectFailed(const std::string& reason)
|
|
{
|
|
BOOST_CHECK_MESSAGE(false, reason);
|
|
|
|
m_limitedIo.afterOp();
|
|
}
|
|
|
|
void
|
|
face1_onReceiveInterest(const Interest& interest)
|
|
{
|
|
m_face1_receivedInterests.push_back(interest);
|
|
|
|
m_limitedIo.afterOp();
|
|
}
|
|
|
|
void
|
|
face1_onReceiveData(const Data& data)
|
|
{
|
|
m_face1_receivedDatas.push_back(data);
|
|
|
|
m_limitedIo.afterOp();
|
|
}
|
|
|
|
void
|
|
face2_onReceiveInterest(const Interest& interest)
|
|
{
|
|
m_face2_receivedInterests.push_back(interest);
|
|
|
|
m_limitedIo.afterOp();
|
|
}
|
|
|
|
void
|
|
face2_onReceiveData(const Data& data)
|
|
{
|
|
m_face2_receivedDatas.push_back(data);
|
|
|
|
m_limitedIo.afterOp();
|
|
}
|
|
|
|
void
|
|
channel_onFaceCreated(const shared_ptr<Face>& newFace)
|
|
{
|
|
m_faces.push_back(static_pointer_cast<UnixStreamFace>(newFace));
|
|
|
|
m_limitedIo.afterOp();
|
|
}
|
|
|
|
void
|
|
channel_onConnectFailed(const std::string& reason)
|
|
{
|
|
BOOST_CHECK_MESSAGE(false, reason);
|
|
|
|
m_limitedIo.afterOp();
|
|
}
|
|
|
|
protected:
|
|
LimitedIo m_limitedIo;
|
|
|
|
shared_ptr<UnixStreamFace> m_face1;
|
|
std::vector<Interest> m_face1_receivedInterests;
|
|
std::vector<Data> m_face1_receivedDatas;
|
|
shared_ptr<UnixStreamFace> m_face2;
|
|
std::vector<Interest> m_face2_receivedInterests;
|
|
std::vector<Data> m_face2_receivedDatas;
|
|
|
|
std::list< shared_ptr<UnixStreamFace> > m_faces;
|
|
};
|
|
|
|
|
|
BOOST_FIXTURE_TEST_CASE(EndToEnd, EndToEndFixture)
|
|
{
|
|
UnixStreamFactory factory;
|
|
|
|
shared_ptr<UnixStreamChannel> channel1 = factory.createChannel(CHANNEL_PATH1);
|
|
channel1->listen(bind(&EndToEndFixture::channel1_onFaceCreated, this, _1),
|
|
bind(&EndToEndFixture::channel1_onConnectFailed, this, _1));
|
|
|
|
shared_ptr<stream_protocol::socket> client =
|
|
make_shared<stream_protocol::socket>(boost::ref(g_io));
|
|
client->async_connect(stream_protocol::endpoint(CHANNEL_PATH1),
|
|
bind(&EndToEndFixture::client_onConnect, this, _1));
|
|
|
|
BOOST_CHECK_MESSAGE(m_limitedIo.run(2, time::seconds(1)) == LimitedIo::EXCEED_OPS,
|
|
"UnixStreamChannel error: cannot connect or cannot accept connection");
|
|
|
|
BOOST_REQUIRE(static_cast<bool>(m_face1));
|
|
|
|
std::string face1uri = m_face1->getUri().toString();
|
|
BOOST_CHECK_EQUAL(face1uri.find("unix:///"), 0); // third '/' is the path separator
|
|
BOOST_CHECK_EQUAL(face1uri.rfind(CHANNEL_PATH1),
|
|
face1uri.size() - std::string(CHANNEL_PATH1).size());
|
|
|
|
m_face2 = make_shared<UnixStreamFace>(client);
|
|
m_face2->onReceiveInterest +=
|
|
bind(&EndToEndFixture::face2_onReceiveInterest, this, _1);
|
|
m_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);
|
|
|
|
m_face1->sendInterest(interest1);
|
|
m_face1->sendInterest(interest1);
|
|
m_face1->sendInterest(interest1);
|
|
m_face1->sendData (data1 );
|
|
m_face2->sendInterest(interest2);
|
|
m_face2->sendData (data2 );
|
|
m_face2->sendData (data2 );
|
|
m_face2->sendData (data2 );
|
|
|
|
BOOST_CHECK_MESSAGE(m_limitedIo.run(8, time::seconds(1)) == LimitedIo::EXCEED_OPS,
|
|
"UnixStreamChannel error: cannot send or receive Interest/Data packets");
|
|
|
|
BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
|
|
BOOST_REQUIRE_EQUAL(m_face1_receivedDatas .size(), 3);
|
|
BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 3);
|
|
BOOST_REQUIRE_EQUAL(m_face2_receivedDatas .size(), 1);
|
|
|
|
BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getName(), interest2.getName());
|
|
BOOST_CHECK_EQUAL(m_face1_receivedDatas [0].getName(), data2.getName());
|
|
BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getName(), interest1.getName());
|
|
BOOST_CHECK_EQUAL(m_face2_receivedDatas [0].getName(), data1.getName());
|
|
|
|
const FaceCounters& counters1 = m_face1->getCounters();
|
|
BOOST_CHECK_EQUAL(counters1.getInInterest() , 1);
|
|
BOOST_CHECK_EQUAL(counters1.getInData() , 3);
|
|
BOOST_CHECK_EQUAL(counters1.getOutInterest(), 3);
|
|
BOOST_CHECK_EQUAL(counters1.getOutData() , 1);
|
|
|
|
const FaceCounters& counters2 = m_face2->getCounters();
|
|
BOOST_CHECK_EQUAL(counters2.getInInterest() , 3);
|
|
BOOST_CHECK_EQUAL(counters2.getInData() , 1);
|
|
BOOST_CHECK_EQUAL(counters2.getOutInterest(), 1);
|
|
BOOST_CHECK_EQUAL(counters2.getOutData() , 3);
|
|
}
|
|
|
|
BOOST_FIXTURE_TEST_CASE(MultipleAccepts, EndToEndFixture)
|
|
{
|
|
UnixStreamFactory factory;
|
|
|
|
shared_ptr<UnixStreamChannel> channel = factory.createChannel(CHANNEL_PATH1);
|
|
channel->listen(bind(&EndToEndFixture::channel_onFaceCreated, this, _1),
|
|
bind(&EndToEndFixture::channel_onConnectFailed, this, _1));
|
|
|
|
shared_ptr<stream_protocol::socket> client1 =
|
|
make_shared<stream_protocol::socket>(boost::ref(g_io));
|
|
client1->async_connect(stream_protocol::endpoint(CHANNEL_PATH1),
|
|
bind(&EndToEndFixture::client_onConnect, this, _1));
|
|
|
|
BOOST_CHECK_MESSAGE(m_limitedIo.run(2, time::seconds(1)) == LimitedIo::EXCEED_OPS,
|
|
"UnixStreamChannel error: cannot connect or cannot accept connection");
|
|
|
|
BOOST_CHECK_EQUAL(m_faces.size(), 1);
|
|
|
|
shared_ptr<stream_protocol::socket> client2 =
|
|
make_shared<stream_protocol::socket>(boost::ref(g_io));
|
|
client2->async_connect(stream_protocol::endpoint(CHANNEL_PATH1),
|
|
bind(&EndToEndFixture::client_onConnect, this, _1));
|
|
|
|
BOOST_CHECK_MESSAGE(m_limitedIo.run(2, time::seconds(1)) == LimitedIo::EXCEED_OPS,
|
|
"UnixStreamChannel error: cannot accept multiple connections");
|
|
|
|
BOOST_CHECK_EQUAL(m_faces.size(), 2);
|
|
|
|
// now close one of the faces
|
|
m_faces.front()->close();
|
|
|
|
// we should still be able to send/receive with the other one
|
|
m_face1 = m_faces.back();
|
|
m_face1->onReceiveInterest +=
|
|
bind(&EndToEndFixture::face1_onReceiveInterest, this, _1);
|
|
m_face1->onReceiveData +=
|
|
bind(&EndToEndFixture::face1_onReceiveData, this, _1);
|
|
|
|
m_face2 = make_shared<UnixStreamFace>(client2);
|
|
m_face2->onReceiveInterest +=
|
|
bind(&EndToEndFixture::face2_onReceiveInterest, this, _1);
|
|
m_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);
|
|
|
|
m_face1->sendInterest(interest1);
|
|
m_face1->sendData (data1 );
|
|
m_face2->sendInterest(interest2);
|
|
m_face2->sendData (data2 );
|
|
|
|
BOOST_CHECK_MESSAGE(m_limitedIo.run(4, time::seconds(1)) == LimitedIo::EXCEED_OPS,
|
|
"UnixStreamChannel error: cannot send or receive Interest/Data packets");
|
|
|
|
BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
|
|
BOOST_REQUIRE_EQUAL(m_face1_receivedDatas .size(), 1);
|
|
BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 1);
|
|
BOOST_REQUIRE_EQUAL(m_face2_receivedDatas .size(), 1);
|
|
|
|
BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getName(), interest2.getName());
|
|
BOOST_CHECK_EQUAL(m_face1_receivedDatas [0].getName(), data2.getName());
|
|
BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getName(), interest1.getName());
|
|
BOOST_CHECK_EQUAL(m_face2_receivedDatas [0].getName(), data1.getName());
|
|
}
|
|
|
|
static inline void
|
|
noOp()
|
|
{
|
|
}
|
|
|
|
BOOST_FIXTURE_TEST_CASE(UnixStreamFaceLocalControlHeader, EndToEndFixture)
|
|
{
|
|
UnixStreamFactory factory;
|
|
|
|
shared_ptr<UnixStreamChannel> channel1 = factory.createChannel(CHANNEL_PATH1);
|
|
channel1->listen(bind(&EndToEndFixture::channel1_onFaceCreated, this, _1),
|
|
bind(&EndToEndFixture::channel1_onConnectFailed, this, _1));
|
|
|
|
shared_ptr<stream_protocol::socket> client =
|
|
make_shared<stream_protocol::socket>(boost::ref(g_io));
|
|
client->async_connect(stream_protocol::endpoint(CHANNEL_PATH1),
|
|
bind(&EndToEndFixture::client_onConnect, this, _1));
|
|
|
|
BOOST_CHECK_MESSAGE(m_limitedIo.run(2, time::seconds(1)) == LimitedIo::EXCEED_OPS,
|
|
"UnixStreamChannel error: cannot connect or cannot accept connection");
|
|
|
|
BOOST_REQUIRE(static_cast<bool>(m_face1));
|
|
|
|
m_face2 = make_shared<UnixStreamFace>(client);
|
|
m_face2->onReceiveInterest +=
|
|
bind(&EndToEndFixture::face2_onReceiveInterest, this, _1);
|
|
m_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);
|
|
|
|
m_face1->setLocalControlHeaderFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);
|
|
m_face1->setLocalControlHeaderFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);
|
|
|
|
BOOST_CHECK(m_face1->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
|
|
BOOST_CHECK(m_face1->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
|
|
|
|
m_face2->setLocalControlHeaderFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);
|
|
m_face2->setLocalControlHeaderFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);
|
|
|
|
BOOST_CHECK(m_face2->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
|
|
BOOST_CHECK(m_face2->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
|
|
|
|
////////////////////////////////////////////////////////
|
|
|
|
interest1.setIncomingFaceId(11);
|
|
interest1.setNextHopFaceId(111);
|
|
|
|
m_face1->sendInterest(interest1);
|
|
|
|
data1.setIncomingFaceId(22);
|
|
data1.getLocalControlHeader().setNextHopFaceId(222);
|
|
|
|
m_face1->sendData (data1);
|
|
|
|
//
|
|
|
|
BOOST_CHECK_MESSAGE(m_limitedIo.run(2, time::seconds(1)) == LimitedIo::EXCEED_OPS,
|
|
"UnixStreamChannel error: cannot send or receive Interest/Data packets");
|
|
|
|
BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 1);
|
|
BOOST_REQUIRE_EQUAL(m_face2_receivedDatas .size(), 1);
|
|
|
|
// sending allows only IncomingFaceId, receiving allows only NextHopFaceId
|
|
BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getLocalControlHeader().hasIncomingFaceId(), false);
|
|
BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getLocalControlHeader().hasNextHopFaceId(), false);
|
|
|
|
BOOST_CHECK_EQUAL(m_face2_receivedDatas[0].getLocalControlHeader().hasIncomingFaceId(), false);
|
|
BOOST_CHECK_EQUAL(m_face2_receivedDatas[0].getLocalControlHeader().hasNextHopFaceId(), false);
|
|
|
|
////////////////////////////////////////////////////////
|
|
|
|
using namespace boost::asio;
|
|
|
|
std::vector<const_buffer> interestWithHeader;
|
|
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();
|
|
dataWithHeader.push_back(buffer(dHeader.wire(), dHeader.size()));
|
|
dataWithHeader.push_back(buffer(dPayload.wire(), dPayload.size()));
|
|
|
|
//
|
|
|
|
client->async_send(interestWithHeader, bind(&noOp));
|
|
client->async_send(dataWithHeader, bind(&noOp));
|
|
|
|
BOOST_CHECK_MESSAGE(m_limitedIo.run(2, time::seconds(1)) == LimitedIo::EXCEED_OPS,
|
|
"UnixStreamChannel error: cannot send or receive Interest/Data packets");
|
|
|
|
BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
|
|
BOOST_REQUIRE_EQUAL(m_face1_receivedDatas .size(), 1);
|
|
|
|
BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getLocalControlHeader().hasIncomingFaceId(), false);
|
|
BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getLocalControlHeader().hasNextHopFaceId(), true);
|
|
BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getNextHopFaceId(), 111);
|
|
|
|
BOOST_CHECK_EQUAL(m_face1_receivedDatas[0].getLocalControlHeader().hasIncomingFaceId(), false);
|
|
BOOST_CHECK_EQUAL(m_face1_receivedDatas[0].getLocalControlHeader().hasNextHopFaceId(), false);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|
|
|
|
} // namespace tests
|
|
} // namespace nfd
|