Initial commit
diff --git a/src/main/java/com/intel/jndn/management/ControlResponse.java b/src/main/java/com/intel/jndn/management/ControlResponse.java
new file mode 100644
index 0000000..c221d7c
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/ControlResponse.java
@@ -0,0 +1,40 @@
+/*
+ * File name: ControlResponse.java
+ *
+ * Purpose: Represent a ControlResponse, a Data packet sent in response to a
+ * ControlCommand to the NFD, see http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+ *
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management;
+
+import java.util.List;
+import net.named_data.jndn.ControlParameters;
+import net.named_data.jndn.Data;
+import net.named_data.jndn.encoding.EncodingException;
+
+/**
+ *
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class ControlResponse {
+ public int StatusCode;
+ public String StatusText;
+ public List<ControlParameters> Body;
+
+ /**
+ * Decode input as a ControlResponse in NDN-TLV and set the fields of the
+ * new object
+ *
+ * @param data
+ * @return
+ */
+ public static ControlResponse decode(Data data) throws EncodingException{
+ ControlResponseDecoder decoder = new ControlResponseDecoder();
+ ControlResponse response = new ControlResponse();
+ decoder.decodeControlResponse(response, data.getContent().buf());
+ return response;
+ }
+}
diff --git a/src/main/java/com/intel/jndn/management/ControlResponseDecoder.java b/src/main/java/com/intel/jndn/management/ControlResponseDecoder.java
new file mode 100644
index 0000000..f52c35a
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/ControlResponseDecoder.java
@@ -0,0 +1,68 @@
+/*
+ * File name: ControlParametersDecoder.java
+ *
+ * Purpose: See http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+ *
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import net.named_data.jndn.ControlParameters;
+import net.named_data.jndn.encoding.EncodingException;
+import net.named_data.jndn.encoding.TlvWireFormat;
+import net.named_data.jndn.encoding.tlv.Tlv;
+import net.named_data.jndn.encoding.tlv.TlvDecoder;
+import net.named_data.jndn.util.Blob;
+
+/**
+ *
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class ControlResponseDecoder extends TlvWireFormat {
+
+ /**
+ * Use TLV codes from jndn.encoding.tlv.Tlv.java See
+ * http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+ */
+ public final static int ControlResponse = 101;
+ public final static int ControlResponse_StatusCode = 102;
+ public final static int ControlResponse_StatusText = 103;
+
+ /**
+ * Decode a ControlResponse TLV object; see
+ * http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+ *
+ * @param controlResponse
+ * @param input
+ * @throws EncodingException
+ */
+ public void decodeControlResponse(ControlResponse controlResponse, ByteBuffer input) throws EncodingException {
+ TlvDecoder decoder = new TlvDecoder(input);
+ int endOffset = decoder.readNestedTlvsStart(ControlResponse);
+
+ // parse
+ controlResponse.StatusCode = (int) decoder.readNonNegativeIntegerTlv(ControlResponse_StatusCode);
+ Blob statusText = new Blob(decoder.readBlobTlv(ControlResponse_StatusText), true); // copy because buffer is immutable
+ controlResponse.StatusText = statusText.toString();
+ controlResponse.Body = new ArrayList<>();
+ while (decoder.peekType(Tlv.ControlParameters_ControlParameters, endOffset)) {
+ ByteBuffer copyInput = input.duplicate();
+ copyInput.position(decoder.getOffset());
+ int internalEndOffset = decoder.readNestedTlvsStart(Tlv.ControlParameters_ControlParameters);
+ // decode
+ ControlParameters copyParameters = new ControlParameters();
+ copyParameters.wireDecode(copyInput);
+ controlResponse.Body.add(copyParameters);
+ decoder.seek(internalEndOffset);
+ //
+ decoder.finishNestedTlvs(internalEndOffset);
+ }
+
+ // etc...
+ decoder.finishNestedTlvs(endOffset);
+ }
+}
diff --git a/src/main/java/com/intel/jndn/management/FacePersistency.java b/src/main/java/com/intel/jndn/management/FacePersistency.java
new file mode 100644
index 0000000..2f2b5e6
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/FacePersistency.java
@@ -0,0 +1,32 @@
+/*
+ * File name: FacePersistency.java
+ *
+ * Purpose: Indicate whether the face is persistent; used by FaceStatus
+ * See http://redmine.named-data.net/projects/nfd/widi/FaceMgmt
+ *
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management;
+
+/**
+ * Indicate whether the face is persistent; used by FaceStatus
+ * See http://redmine.named-data.net/projects/nfd/widi/FaceMgmt
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public enum FacePersistency {
+
+ PERSISTENT(0),
+ ON_DEMAND(1),
+ PERMANENT(2);
+
+ FacePersistency(int value) {
+ value_ = value;
+ }
+
+ public final int getNumericValue() {
+ return value_;
+ }
+ private final int value_;
+}
diff --git a/src/main/java/com/intel/jndn/management/FaceScope.java b/src/main/java/com/intel/jndn/management/FaceScope.java
new file mode 100644
index 0000000..17028c5
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/FaceScope.java
@@ -0,0 +1,32 @@
+/*
+ * File name: FaceScope.java
+ *
+ * Purpose: Indicate whether the face is local for scope control purposes;
+ * used by FaceStatus. See http://redmine.named-data.net/projects/nfd/widi/FaceMgmt
+ *
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management;
+
+/**
+ * Indicate whether the face is local for scope control purposes; used by FaceStatus
+ * See http://redmine.named-data.net/projects/nfd/widi/FaceMgmt
+ *
+ * @author andrew
+ */
+public enum FaceScope {
+
+ LOCAL(0),
+ NON_LOCAL(1);
+
+ FaceScope(int value) {
+ value_ = value;
+ }
+
+ public final int getNumericValue() {
+ return value_;
+ }
+ private final int value_;
+}
diff --git a/src/main/java/com/intel/jndn/management/FaceStatus.java b/src/main/java/com/intel/jndn/management/FaceStatus.java
new file mode 100644
index 0000000..f0a992b
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/FaceStatus.java
@@ -0,0 +1,49 @@
+/*
+ * File name: FaceStatus.java
+ *
+ * Purpose: Represent a FaceStatus object from /localhost/nfd/faces/list;
+ * see http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt for details
+ *
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management;
+
+import java.util.List;
+import net.named_data.jndn.Data;
+import net.named_data.jndn.encoding.EncodingException;
+
+/**
+ * Represent a FaceStatus object from /localhost/nfd/faces/list;
+ * see http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt for details
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class FaceStatus {
+
+ public int faceId;
+ public String uri; // can't use URI because some are invalid syntax
+ public String localUri; // can't use URI because some are invalid syntax
+ public int expirationPeriod;
+ public FaceScope faceScope;
+ public FacePersistency facePersistency;
+ public LinkType linkType;
+ public int inInterests;
+ public int outInterests;
+ public int inDatas;
+ public int outDatas;
+ public int inBytes;
+ public int outBytes;
+
+ /**
+ * Helper method for decoding a list of face statuses from
+ * /localhost/nfd/faces/list
+ * @param data
+ * @return
+ * @throws EncodingException
+ */
+ public static List<FaceStatus> decode(Data data) throws EncodingException{
+ FaceStatusDecoder decoder = new FaceStatusDecoder();
+ return decoder.decodeFaces(data.getContent().buf());
+ }
+}
diff --git a/src/main/java/com/intel/jndn/management/FaceStatusDecoder.java b/src/main/java/com/intel/jndn/management/FaceStatusDecoder.java
new file mode 100644
index 0000000..346f2cb
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/FaceStatusDecoder.java
@@ -0,0 +1,97 @@
+/*
+ * File name: FaceStatusDecoder.java
+ *
+ * Purpose: Decode lists of FaceStatus objects from /localhost/nfd/faces/list
+ *
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import net.named_data.jndn.encoding.EncodingException;
+import net.named_data.jndn.encoding.tlv.TlvDecoder;
+import net.named_data.jndn.util.Blob;
+
+/**
+ * Decode lists of FaceStatus objects from /localhost/nfd/faces/list
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class FaceStatusDecoder {
+
+ /**
+ * Spec from http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+ */
+ public static final int FACE_ID = 105;
+ public static final int URI = 114;
+ public static final int EXPIRATION_PERIOD = 109;
+
+ /**
+ * Spec from http://redmine.named-data.net/projects/nfd/widi/FaceMgmt
+ */
+ public static final int FACE_STATUS = 128;
+ public static final int LOCAL_URI = 129;
+ public static final int CHANNEL_STATUS = 130;
+ public static final int FACE_SCOPE = 132;
+ public static final int FACE_PERSISTENCY = 133;
+ public static final int LINK_TYPE = 134;
+ public static final int N_IN_INTERESTS = 144;
+ public static final int N_IN_DATAS = 145;
+ public static final int N_OUT_INTERESTS = 146;
+ public static final int N_OUT_DATAS = 147;
+ public static final int N_IN_BYTES = 148;
+ public static final int N_OUT_BYTES = 149;
+
+ /**
+ * Decode a list of faces according to
+ * http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt
+ * @param buffer
+ * @return
+ * @throws EncodingException
+ */
+ public List<FaceStatus> decodeFaces(ByteBuffer buffer) throws EncodingException{
+ ArrayList<FaceStatus> faces = new ArrayList<>();
+ TlvDecoder decoder = new TlvDecoder(buffer);
+ int parentEndOffset;
+ do{
+ parentEndOffset = decoder.readNestedTlvsStart(FACE_STATUS);
+ faces.add(decodeFaceStatus(decoder, parentEndOffset));
+ decoder.finishNestedTlvs(parentEndOffset);
+ }
+ while(parentEndOffset < buffer.limit());
+ return faces;
+ }
+
+ /**
+ * Decode one face status using the current decoder
+ * @param buffer
+ * @return
+ * @throws EncodingException
+ */
+ private static FaceStatus decodeFaceStatus(TlvDecoder decoder, int parentEndOffset) throws EncodingException{
+ FaceStatus status = new FaceStatus();
+
+ // parse
+ status.faceId = (int) decoder.readNonNegativeIntegerTlv(FACE_ID);
+ Blob uri = new Blob(decoder.readBlobTlv(URI), true); // copy because buffer is immutable
+ status.uri = uri.toString();
+ Blob localUri = new Blob(decoder.readBlobTlv(LOCAL_URI), true); // copy because buffer is immutable
+ status.localUri = localUri.toString();
+ status.expirationPeriod = (int) decoder.readOptionalNonNegativeIntegerTlv(EXPIRATION_PERIOD, parentEndOffset);
+ status.faceScope = FaceScope.values()[(int) decoder.readNonNegativeIntegerTlv(FACE_SCOPE)];
+ status.facePersistency = FacePersistency.values()[(int) decoder.readNonNegativeIntegerTlv(FACE_PERSISTENCY)];
+ status.linkType = LinkType.values()[(int) decoder.readNonNegativeIntegerTlv(LINK_TYPE)];
+ status.inInterests = (int) decoder.readNonNegativeIntegerTlv(N_IN_INTERESTS);
+ status.inDatas = (int) decoder.readNonNegativeIntegerTlv(N_IN_DATAS);
+ status.outInterests = (int) decoder.readNonNegativeIntegerTlv(N_OUT_INTERESTS);
+ status.outDatas = (int) decoder.readNonNegativeIntegerTlv(N_OUT_DATAS);
+ status.inBytes = (int) decoder.readNonNegativeIntegerTlv(N_IN_BYTES);
+ status.outBytes = (int) decoder.readNonNegativeIntegerTlv(N_OUT_BYTES);
+
+ return status;
+ }
+
+}
diff --git a/src/main/java/com/intel/jndn/management/LinkType.java b/src/main/java/com/intel/jndn/management/LinkType.java
new file mode 100644
index 0000000..e69513e
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/LinkType.java
@@ -0,0 +1,31 @@
+/*
+ * File name: LinkType.java
+ *
+ * Purpose: Indicate the type of communication link; used by FaceStatus
+ * See http://redmine.named-data.net/projects/nfd/widi/FaceMgmt
+ *
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management;
+
+/**
+ * Indicate the type of communication link; used by FaceStatus
+ * See http://redmine.named-data.net/projects/nfd/widi/FaceMgmt
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public enum LinkType {
+
+ POINT_TO_POINT(0),
+ MULTI_ACCESS(1);
+
+ LinkType(int value) {
+ value_ = value;
+ }
+
+ public final int getNumericValue() {
+ return value_;
+ }
+ private final int value_;
+}
diff --git a/src/main/java/com/intel/jndn/management/NFD.java b/src/main/java/com/intel/jndn/management/NFD.java
new file mode 100644
index 0000000..e19f517
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/NFD.java
@@ -0,0 +1,303 @@
+/*
+ * File name: NFD.java
+ *
+ * Purpose: Helper class for interacting with an NDN forwarder daemon;
+ * see http://redmine.named-data.net/projects/nfd/wiki/Management for
+ * explanations of the various protocols used.
+ *
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management;
+
+import com.intel.jndn.utils.Client;
+import java.io.IOException;
+import java.util.List;
+import net.named_data.jndn.ControlParameters;
+import net.named_data.jndn.Data;
+import net.named_data.jndn.Face;
+import net.named_data.jndn.ForwardingFlags;
+import net.named_data.jndn.Interest;
+import net.named_data.jndn.Name;
+import net.named_data.jndn.encoding.EncodingException;
+import net.named_data.jndn.security.SecurityException;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/**
+ * Helper class for interacting with an NDN forwarder daemon; see
+ * http://redmine.named-data.net/projects/nfd/wiki/Management for explanations
+ * of the various protocols used.
+ *
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class NFD {
+
+ public final static long DEFAULT_TIMEOUT = 2000;
+ private static final Logger logger = LogManager.getLogger();
+
+ /**
+ * Ping a forwarder on an existing face to verify that the forwarder is
+ * working and responding to requests; this version sends a discovery packet
+ * to /localhost/nfd which should always respond if the requestor is on the
+ * same machine as the NDN forwarding daemon.
+ *
+ * @param face
+ * @return true if successful, false otherwise
+ */
+ public static boolean pingLocal(Face face) {
+ return ping(face, new Name("/localhost/nfd"));
+ }
+
+ /**
+ * Request a name on an existing face to verify the forwarder is working and
+ * responding to requests. Note that the name must be served or cached on
+ * the forwarder for this to return true.
+ *
+ * @param face
+ * @param name
+ * @return true if successful, false otherwise
+ */
+ public static boolean ping(Face face, Name name) {
+ // build interest
+ Interest interest = new Interest(name);
+ interest.setInterestLifetimeMilliseconds(DEFAULT_TIMEOUT);
+ interest.setMustBeFresh(true);
+
+ // send packet
+ Data data = Client.getDefault().getSync(face, interest);
+ return data != null;
+ }
+
+ /**
+ * Retrieve a list of faces and their status from the given forwarder; calls
+ * /localhost/nfd/faces/list which requires a local Face (all non-local
+ * packets are dropped)
+ *
+ * @param forwarder Only a localhost Face
+ * @return
+ * @throws Exception
+ */
+ public static List<FaceStatus> getFaceList(Face forwarder) throws Exception {
+ // build management Interest packet; see http://redmine.named-data.net/projects/nfd/wiki/StatusDataset
+ Interest interest = new Interest(new Name("/localhost/nfd/faces/list"));
+ interest.setMustBeFresh(true);
+ interest.setChildSelector(Interest.CHILD_SELECTOR_RIGHT);
+ interest.setInterestLifetimeMilliseconds(DEFAULT_TIMEOUT);
+
+ // TODO verify that all faces are being returned; right now they don't
+ // match up with the results from nfd-status-http-server but no
+ // additional segments are present;
+ // see http://redmine.named-data.net/projects/nfd/wiki/StatusDataset
+ // send packet
+ Data data = Client.getDefault().getSync(forwarder, interest);
+ if (data == null) {
+ throw new Exception("Failed to retrieve list of faces from the forwarder.");
+ }
+
+ // parse packet
+ return FaceStatus.decode(data);
+ }
+
+ /**
+ * Helper method to register a new face on the forwarder; as mentioned at
+ * http://named-data.net/doc/NFD/current/manpages/nfdc.html, this is more
+ * for debugging; use 'register' instead
+ *
+ * @param forwarder Only a localhost Face
+ * @param faceId
+ * @param prefix
+ * @return
+ * @throws Exception
+ */
+ public static boolean addNextHop(Face forwarder, int faceId, Name prefix) throws Exception {
+ // build command name
+ Name command = new Name("/localhost/nfd/fib/add-nexthop");
+ ControlParameters parameters = new ControlParameters();
+ parameters.setName(prefix);
+ parameters.setFaceId(faceId);
+ command.append(parameters.wireEncode());
+
+ // send the interest
+ return sendCommandAndErrorCheck(forwarder, new Interest(command));
+ }
+
+ /**
+ * Create a new face on the given forwarder. Ensure the forwarding face is
+ * on the local machine (management requests are to /localhost/...) and that
+ * command signing has been set up (e.g. forwarder.setCommandSigningInfo()).
+ *
+ * @param forwarder Only a localhost Face
+ * @param uri
+ * @return
+ * @throws java.lang.Exception
+ */
+ public static int createFace(Face forwarder, String uri) throws Exception {
+ Name command = new Name("/localhost/nfd/faces/create");
+ ControlParameters parameters = new ControlParameters();
+ parameters.setUri(uri);
+ command.append(parameters.wireEncode());
+
+ // send the interest
+ ControlResponse response = sendCommand(forwarder, new Interest(command));
+
+ // check for body
+ if (response.Body.isEmpty()) {
+ throw new Exception("Failed to create face: " + uri);
+ }
+
+ // return
+ return response.Body.get(0).getFaceId();
+ }
+
+ /**
+ * Register a route on the forwarder; see
+ * http://named-data.net/doc/NFD/current/manpages/nfdc.html for command-line
+ * usage and http://redmine.named-data.net/projects/nfd/wiki/RibMgmt for
+ * protocol documentation. Ensure the forwarding face is on the local
+ * machine (management requests are to /localhost/...) and that command
+ * signing has been set up (e.g. forwarder.setCommandSigningInfo()).
+ *
+ * @param forwarder Only a localhost Face
+ * @param controlParameters
+ * @return
+ * @throws Exception
+ */
+ public static boolean register(Face forwarder, ControlParameters controlParameters) throws Exception {
+ // build command name
+ Name command = new Name("/localhost/nfd/rib/register");
+ command.append(controlParameters.wireEncode());
+
+ // send the interest
+ return sendCommandAndErrorCheck(forwarder, new Interest(command));
+ }
+
+ /**
+ * Register a route on a forwarder; this will create a new face on the
+ * forwarder to the given URI/route pair. See register(Face,
+ * ControlParameters) for more details documentation.
+ *
+ * @param forwarder Only a localhost Face
+ * @param uri
+ * @param cost
+ * @param route
+ * @return true for successful registration
+ * @throws java.lang.Exception
+ */
+ public static boolean register(Face forwarder, String uri, Name route, int cost) throws Exception {
+ // create the new face
+ int faceId = createFace(forwarder, uri);
+
+ // run base method
+ return register(forwarder, faceId, route, cost);
+ }
+
+ /**
+ * Register a route on a forwarder; this will not create a new face since it
+ * is provided a faceId. See register(Face, ControlParameters) for full
+ * documentation
+ *
+ * @param forwarder Only a localhost Face
+ * @param faceId
+ * @param route
+ * @param cost
+ * @return true for successful registration
+ * @throws java.lang.Exception
+ */
+ public static boolean register(Face forwarder, int faceId, Name route, int cost) throws Exception {
+ // build command name
+ ControlParameters parameters = new ControlParameters();
+ parameters.setName(route);
+ parameters.setFaceId(faceId);
+ parameters.setCost(cost);
+ ForwardingFlags flags = new ForwardingFlags();
+ flags.setCapture(true);
+ flags.setChildInherit(true);
+ parameters.setForwardingFlags(flags);
+
+ // run base method
+ return register(forwarder, parameters);
+ }
+
+ /**
+ * Set a strategy on the forwarder; see
+ * http://named-data.net/doc/NFD/current/manpages/nfdc.html for command-line
+ * usage and http://redmine.named-data.net/projects/nfd/wiki/StrategyChoice
+ * for protocol documentation. Ensure the forwarding face is on the local
+ * machine (management requests are to /localhost/...) and that command
+ * signing has been set up (e.g. forwarder.setCommandSigningInfo()).
+ *
+ * @param forwarder Only a localhost Face
+ * @param prefix
+ * @param strategy
+ * @return true for successful command
+ * @throws Exception
+ */
+ public static boolean setStrategy(Face forwarder, Name prefix, Name strategy) throws Exception {
+ // build command name
+ Name command = new Name("/localhost/nfd/strategy-choice/set");
+ ControlParameters parameters = new ControlParameters();
+ parameters.setName(prefix);
+ parameters.setStrategy(strategy);
+ command.append(parameters.wireEncode());
+
+ // send the interest
+ return sendCommandAndErrorCheck(forwarder, new Interest(command));
+ }
+
+ /**
+ * Send an interest as a command to the forwarder; this method will convert
+ * the interest to a command interest and block until a response is received
+ * from the forwarder. Ensure the forwarding face is on the local machine
+ * (management requests are to /localhost/...) and that command signing has
+ * been set up (e.g. forwarder.setCommandSigningInfo()).
+ *
+ * @param forwarder Only a localhost Face
+ * @param interest As described at
+ * http://redmine.named-data.net/projects/nfd/wiki/ControlCommand, the
+ * requested interest must have encoded ControlParameters appended to the
+ * interest name
+ * @return
+ * @throws net.named_data.jndn.security.SecurityException
+ * @throws java.io.IOException
+ * @throws net.named_data.jndn.encoding.EncodingException
+ */
+ public static ControlResponse sendCommand(Face forwarder, Interest interest) throws SecurityException, IOException, EncodingException {
+ forwarder.makeCommandInterest(interest);
+
+ // send command packet
+ Data data = Client.getDefault().getSync(forwarder, interest);
+ if (data == null) {
+ throw new IOException("Failed to receive command response.");
+ }
+
+ // return response
+ return ControlResponse.decode(data);
+ }
+
+ /**
+ * Send an interest as a command to the forwarder; this method will convert
+ * the interest to a command interest and block until a response is received
+ * from the forwarder.
+ *
+ * @param forwarder Only a localhost Face
+ * @param interest As described at
+ * http://redmine.named-data.net/projects/nfd/wiki/ControlCommand, the
+ * requested interest must have encoded ControlParameters appended to the
+ * interest name
+ * @return
+ * @throws net.named_data.jndn.security.SecurityException
+ * @throws java.io.IOException
+ * @throws net.named_data.jndn.encoding.EncodingException
+ */
+ public static boolean sendCommandAndErrorCheck(Face forwarder, Interest interest) throws SecurityException, IOException, EncodingException {
+ ControlResponse response = sendCommand(forwarder, interest);
+ if (response.StatusCode < 400) {
+ return true;
+ } else {
+ logger.warn("Command sent but failed: " + response.StatusCode + " " + response.StatusText);
+ return false;
+ }
+ }
+}