tools: nfdc face create command accepts local FaceUri
refs #4017 Change-Id: I2d13403f13c30146c53744828ba2a37a6fab7de2
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user