tools: nfdc face create command accepts local FaceUri

refs #4017

Change-Id: I2d13403f13c30146c53744828ba2a37a6fab7de2
This commit is contained in:
Junxiao Shi
2017-04-01 14:35:21 +00:00
parent 78e32b0ee2
commit 0d97692b40
3 changed files with 117 additions and 31 deletions
+27 -8
View File
@@ -3,9 +3,9 @@ nfdc-face
SYNOPSIS
--------
| nfdc face [list]
| nfdc face [list [[remote] <FACEURI>] [local <FACEURI>] [scheme <SCHEME>]]
| nfdc face show [id] <FACEID>
| nfdc face create [remote] <FACEURI> [[persistency] <PERSISTENCY>]
| nfdc face create [remote] <FACEURI> [[persistency] <PERSISTENCY>] [local <FACEURI>]
| nfdc face destroy [face] <FACEID|FACEURI>
| nfdc channel [list]
@@ -16,11 +16,14 @@ It could be a physical network interface to communicate on a physical link,
an overlay communication channel between NFD and a remote node,
or an inter-process communication channel between NFD and a local application.
The **nfdc face list** command shows a list of faces, their properties, and statistics.
The **nfdc face list** command shows a list of faces, their properties, and statistics,
optionally filtered by remote endpoint, local endpoint, and FaceUri scheme.
When multiple filters are specified, returned faces must satisfy all filters.
The **nfdc face show** command shows properties and statistics of one specific face.
The **nfdc face create** command creates a unicast UDP or TCP face.
The **nfdc face create** command creates a UDP unicast, TCP, or Ethernet unicast face.
Local FaceUri is required for creating Ethernet unicast faces; otherwise it must be omitted.
The **nfdc face destroy** command destroys an existing face.
@@ -34,14 +37,30 @@ OPTIONS
It is displayed in the output of **nfdc face list** and **nfdc face create** commands.
<FACEURI>
An URI representing the remote endpoint of a face.
Its syntax is:
A URI representing the remote or local endpoint of a face.
Examples:
- udp[4|6]://<IP-or-host>[:<port>]
- tcp[4|6]://<IP-or-host>[:<port>]
- udp4://192.0.2.1:6363
- udp6://[2001:db8::1]:6363
- udp://example.net
- tcp4://192.0.2.1:6363
- tcp6://[2001:db8::1]:6363
- tcp://example.net
- unix:///var/run/nfd.sock
- fd://6
- ether://[08:00:27:01:01:01]
- dev://eth0
When a hostname is specified, a DNS query is used to obtain the IP address.
<SCHEME>
The scheme portion of either remote or local endpoint.
Examples:
- udp4
- unix
- dev
<PERSISTENCY>
Either "persistent" or "permanent".
A "persistent" face (the default) is closed when a socket error occurs.
+40
View File
@@ -247,6 +247,7 @@ BOOST_AUTO_TEST_CASE(Creating)
ControlParameters req = MOCK_NFD_MGMT_REQUIRE_COMMAND_IS("/localhost/nfd/faces/create");
BOOST_REQUIRE(req.hasUri());
BOOST_CHECK_EQUAL(req.getUri(), "udp4://159.242.33.78:6363");
BOOST_CHECK(!req.hasLocalUri());
BOOST_REQUIRE(req.hasFacePersistency());
BOOST_CHECK_EQUAL(req.getFacePersistency(), FacePersistency::FACE_PERSISTENCY_PERSISTENT);
@@ -262,6 +263,29 @@ BOOST_AUTO_TEST_CASE(Creating)
BOOST_CHECK(err.is_empty());
}
BOOST_AUTO_TEST_CASE(CreatingWithLocalUri)
{
this->processInterest = [this] (const Interest& interest) {
ControlParameters req = MOCK_NFD_MGMT_REQUIRE_COMMAND_IS("/localhost/nfd/faces/create");
BOOST_REQUIRE(req.hasUri());
BOOST_CHECK_EQUAL(req.getUri(), "udp4://22.91.89.51:19903");
BOOST_REQUIRE(req.hasLocalUri());
BOOST_CHECK_EQUAL(req.getLocalUri(), "udp4://98.68.23.71:6363");
BOOST_REQUIRE(req.hasFacePersistency());
BOOST_CHECK_EQUAL(req.getFacePersistency(), FacePersistency::FACE_PERSISTENCY_PERMANENT);
ControlParameters resp;
resp.setFaceId(301)
.setFacePersistency(FacePersistency::FACE_PERSISTENCY_PERMANENT);
this->succeedCommand(interest, resp);
};
this->execute("face create udp://22.91.89.51:19903 permanent local udp://98.68.23.71");
BOOST_CHECK_EQUAL(exitCode, 0);
BOOST_CHECK(out.is_equal("face-created id=301 remote=udp4://22.91.89.51:19903 persistency=permanent\n"));
BOOST_CHECK(err.is_empty());
}
BOOST_AUTO_TEST_CASE(UpgradingPersistency)
{
bool hasUpdateCommand = false;
@@ -319,6 +343,22 @@ BOOST_AUTO_TEST_CASE(SamePersistency)
BOOST_CHECK(err.is_empty());
}
BOOST_AUTO_TEST_CASE(ErrorCanonizeRemote)
{
this->execute("face create invalid://");
BOOST_CHECK_EQUAL(exitCode, 4);
BOOST_CHECK(out.is_empty());
BOOST_CHECK(err.is_equal("Error when canonizing 'invalid://': scheme not supported\n"));
}
BOOST_AUTO_TEST_CASE(ErrorCanonizeLocal)
{
this->execute("face create udp4://24.37.20.47:6363 local invalid://");
BOOST_CHECK_EQUAL(exitCode, 4);
BOOST_CHECK(out.is_empty());
BOOST_CHECK(err.is_equal("Error when canonizing 'invalid://': scheme not supported\n"));
}
BOOST_AUTO_TEST_CASE(ErrorCreate)
{
this->processInterest = nullptr; // no response
+50 -23
View File
@@ -52,7 +52,8 @@ FaceModule::registerCommands(CommandParser& parser)
defFaceCreate
.setTitle("create a face")
.addArg("remote", ArgValueType::FACE_URI, Required::YES, Positional::YES)
.addArg("persistency", ArgValueType::FACE_PERSISTENCY, Required::NO, Positional::YES);
.addArg("persistency", ArgValueType::FACE_PERSISTENCY, Required::NO, Positional::YES)
.addArg("local", ArgValueType::FACE_URI, Required::NO, Positional::NO);
parser.addCommand(defFaceCreate, &FaceModule::create);
CommandDefinition defFaceDestroy("face", "destroy");
@@ -147,23 +148,30 @@ persistencyLessThan(FacePersistency x, FacePersistency y)
void
FaceModule::create(ExecuteContext& ctx)
{
auto faceUri = ctx.args.get<FaceUri>("remote");
auto remoteUri = ctx.args.get<FaceUri>("remote");
auto localUri = ctx.args.getOptional<FaceUri>("local");
auto persistency = ctx.args.get<FacePersistency>("persistency", FacePersistency::FACE_PERSISTENCY_PERSISTENT);
FaceUri canonicalUri;
FaceUri canonicalRemote;
ndn::optional<FaceUri> canonicalLocal;
auto handleCanonizeError = [&] (const FaceUri& faceUri, const std::string& error) {
ctx.exitCode = 4;
ctx.err << "Error when canonizing '" << faceUri << "': " << error << '\n';
};
auto printPositiveResult = [&] (const std::string& actionSummary, const ControlParameters& resp) {
text::ItemAttributes ia;
ctx.out << actionSummary << ' '
<< ia("id") << resp.getFaceId()
<< ia("remote") << canonicalUri
<< ia("remote") << canonicalRemote
<< ia("persistency") << resp.getFacePersistency()
<< '\n';
///\todo #3956 display local=localUri before 'remote' field
///\todo #3956 display local FaceUri before 'remote' field
};
auto handle409 = [&] (const ControlResponse& resp) {
ControlParameters respParams(resp.getBody());
if (respParams.getUri() != canonicalUri.toString()) {
if (respParams.getUri() != canonicalRemote.toString()) {
// we are conflicting with a different face, which is a general error
return false;
}
@@ -183,24 +191,43 @@ FaceModule::create(ExecuteContext& ctx)
return true;
};
faceUri.canonize(
[&] (const FaceUri& canonicalUri1) {
canonicalUri = canonicalUri1;
ctx.controller.start<ndn::nfd::FaceCreateCommand>(
ControlParameters().setUri(canonicalUri.toString()).setFacePersistency(persistency),
bind(printPositiveResult, "face-created", _1),
[&] (const ControlResponse& resp) {
if (resp.getCode() == 409 && handle409(resp)) {
return;
}
ctx.makeCommandFailureHandler("creating face")(resp); // invoke general error handler
},
ctx.makeCommandOptions());
},
[&] (const std::string& canonizeError) {
ctx.exitCode = 4;
ctx.err << "Error when canonizing FaceUri: " << canonizeError << '\n';
auto doCreateFace = [&] {
ControlParameters params;
params.setUri(canonicalRemote.toString());
if (canonicalLocal) {
params.setLocalUri(canonicalLocal->toString());
}
params.setFacePersistency(persistency);
ctx.controller.start<ndn::nfd::FaceCreateCommand>(
params,
bind(printPositiveResult, "face-created", _1),
[&] (const ControlResponse& resp) {
if (resp.getCode() == 409 && handle409(resp)) {
return;
}
ctx.makeCommandFailureHandler("creating face")(resp); // invoke general error handler
},
ctx.makeCommandOptions());
};
remoteUri.canonize(
[&] (const FaceUri& canonicalUri) {
canonicalRemote = canonicalUri;
if (localUri) {
localUri->canonize(
[&] (const FaceUri& canonicalUri) {
canonicalLocal = canonicalUri;
doCreateFace();
},
bind(handleCanonizeError, *localUri, _1),
ctx.face.getIoService(), ctx.getTimeout());
}
else {
doCreateFace();
}
},
bind(handleCanonizeError, remoteUri, _1),
ctx.face.getIoService(), ctx.getTimeout());
ctx.face.processEvents();