Added if (LOG>3) messages for receiving data.
diff --git a/js/tools/build/ndn-js-uncomp.js b/js/tools/build/ndn-js-uncomp.js
index 6f1bc95..781fb39 100644
--- a/js/tools/build/ndn-js-uncomp.js
+++ b/js/tools/build/ndn-js-uncomp.js
@@ -19,7 +19,6 @@
this.ndn_data = null; // this holds the ndn_closure
this.ndn_data_dirty = false;
- //this.timerID = -1; // Store the interest timer; used to cancel the timer upon receiving interest
};
// Upcall result
@@ -71,11 +70,7 @@
var WebSocketTransport = function WebSocketTransport() {
this.ws = null;
- this.ccndid = null;
- this.maxBufferSize = 10000; // Currently support 10000 bytes data input, consistent with BinaryXMLEncoder
- this.buffer = new Uint8Array(this.maxBufferSize);
- this.bufferOffset = 0;
- this.structureDecoder = new BinaryXMLStructureDecoder();
+ this.elementReader = null;
this.defaultGetHostAndPort = NDN.makeShuffledGetHostAndPort
(["A.ws.ndn.ucla.edu", "B.ws.ndn.ucla.edu", "C.ws.ndn.ucla.edu", "D.ws.ndn.ucla.edu",
"E.ws.ndn.ucla.edu"],
@@ -91,6 +86,7 @@
this.ws.binaryType = "arraybuffer";
+ this.elementReader = new BinaryXmlElementReader(ndn);
var self = this;
this.ws.onmessage = function(ev) {
var result = ev.data;
@@ -104,237 +100,12 @@
if (LOG>3) console.log('BINARY RESPONSE IS ' + DataUtils.toHex(bytearray));
try {
- if (bytearray.length + self.bufferOffset >= self.buffer.byteLength) {
- if (LOG>3) {
- console.log("NDN.ws.onmessage: buffer overflow. Accumulate received length: " + self.bufferOffset
- + ". Current packet length: " + bytearray.length + ".");
- }
-
- // Purge and quit.
- delete self.structureDecoder;
- delete self.buffer;
- self.structureDecoder = new BinaryXMLStructureDecoder();
- self.buffer = new Uint8Array(self.maxBufferSize);
- self.bufferOffset = 0;
- return;
- }
-
- /*for (var i = 0; i < bytearray.length; i++) {
- self.buffer.push(bytearray[i]);
- }*/
- self.buffer.set(bytearray, self.bufferOffset);
- self.bufferOffset += bytearray.length;
-
- if (!self.structureDecoder.findElementEnd(self.buffer.subarray(0, self.bufferOffset))) {
- // Need more data to decode
- if (LOG>3) console.log('Incomplete packet received. Length ' + bytearray.length + '. Wait for more input.');
- return;
- }
- if (LOG>3) console.log('Complete packet received. Length ' + bytearray.length + '. Start decoding.');
+ // Find the end of the binary XML element and call ndn.onReceivedElement.
+ self.elementReader.onReceivedData(bytearray);
} catch (ex) {
console.log("NDN.ws.onmessage exception: " + ex);
return;
}
-
- var decoder = new BinaryXMLDecoder(self.buffer);
- // Dispatch according to packet type
- if (decoder.peekStartElement(CCNProtocolDTags.Interest)) { // Interest packet
- if (LOG > 3) console.log('Interest packet received.');
-
- var interest = new Interest();
- interest.from_ccnb(decoder);
- if (LOG > 3) console.log(interest);
- var nameStr = escape(interest.name.getName());
- if (LOG > 3) console.log(nameStr);
-
- var entry = getEntryForRegisteredPrefix(nameStr);
- if (entry != null) {
- //console.log(entry);
- var info = new UpcallInfo(ndn, interest, 0, null);
- var ret = entry.closure.upcall(Closure.UPCALL_INTEREST, info);
- if (ret == Closure.RESULT_INTEREST_CONSUMED && info.contentObject != null) {
- var coBinary = encodeToBinaryContentObject(info.contentObject);
- // If we directly use coBinary.buffer to feed ws.send(), WebSocket
- // will end up sending a packet with 10000 bytes of data. That
- // is, WebSocket will flush the entire buffer in BinaryXMLEncoder
- // regardless of the offset of the Uint8Array. So we have to
- // create a new Uint8Array buffer with just the right size and
- // copy the content from coBinary to the new buffer.
- // ---Wentao
- var bytearray = new Uint8Array(coBinary.length);
- bytearray.set(coBinary);
-
- self.ws.send(bytearray.buffer);
- }
- }
-
- } else if (decoder.peekStartElement(CCNProtocolDTags.ContentObject)) { // Content packet
- if (LOG > 3) console.log('ContentObject packet received.');
-
- var co = new ContentObject();
- co.from_ccnb(decoder);
- //console.log(co);
- //var nameStr = co.name.getName();
- //console.log(nameStr);
-
- if (self.ccndid == null && NDN.ccndIdFetcher.match(co.name)) {
- // We are in starting phase, record publisherPublicKeyDigest in self.ccndid
- if(!co.signedInfo || !co.signedInfo.publisher
- || !co.signedInfo.publisher.publisherPublicKeyDigest) {
- console.log("Cannot contact router, close NDN now.");
-
- // Close NDN if we fail to connect to a ccn router
- ndn.readyStatus = NDN.CLOSED;
- ndn.onclose();
- //console.log("NDN.onclose event fired.");
- } else {
- //console.log('Connected to ccnd.');
- self.ccndid = co.signedInfo.publisher.publisherPublicKeyDigest;
- if (LOG>3) console.log(self.ccndid);
-
- // Call NDN.onopen after success
- ndn.readyStatus = NDN.OPENED;
- ndn.onopen();
- //console.log("NDN.onopen event fired.");
- }
- } else {
- var pitEntry = NDN.getEntryForExpressedInterest(co.name);
- if (pitEntry != null) {
- //console.log(pitEntry);
- // Remove PIT entry from NDN.PITTable
- var index = NDN.PITTable.indexOf(pitEntry);
- if (index >= 0)
- NDN.PITTable.splice(index, 1);
-
- var currentClosure = pitEntry.closure;
-
- // Cancel interest timer
- clearTimeout(pitEntry.timerID);
- //console.log("Clear interest timer");
- //console.log(currentClosure.timerID);
-
- // Key verification
-
- // Recursive key fetching & verification closure
- var KeyFetchClosure = function KeyFetchClosure(content, closure, key, sig, wit) {
- this.contentObject = content; // unverified content object
- this.closure = closure; // closure corresponding to the contentObject
- this.keyName = key; // name of current key to be fetched
- this.sigHex = sig; // hex signature string to be verified
- this.witness = wit;
-
- Closure.call(this);
- };
-
- KeyFetchClosure.prototype.upcall = function(kind, upcallInfo) {
- if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
- console.log("In KeyFetchClosure.upcall: interest time out.");
- console.log(this.keyName.contentName.getName());
- } else if (kind == Closure.UPCALL_CONTENT) {
- //console.log("In KeyFetchClosure.upcall: signature verification passed");
-
- var rsakey = decodeSubjectPublicKeyInfo(upcallInfo.contentObject.content);
- var verified = rsakey.verifyByteArray(this.contentObject.rawSignatureData, this.witness, this.sigHex);
-
- var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
- //console.log("raise encapsulated closure");
- this.closure.upcall(flag, new UpcallInfo(ndn, null, 0, this.contentObject));
-
- // Store key in cache
- var keyEntry = new KeyStoreEntry(keylocator.keyName, rsakey, new Date().getTime());
- NDN.addKeyEntry(keyEntry);
- //console.log(NDN.KeyStore);
- } else if (kind == Closure.UPCALL_CONTENT_BAD) {
- console.log("In KeyFetchClosure.upcall: signature verification failed");
- }
- };
-
- if (co.signedInfo && co.signedInfo.locator && co.signature) {
- if (LOG > 3) console.log("Key verification...");
- var sigHex = DataUtils.toHex(co.signature.signature).toLowerCase();
-
- var wit = null;
- if (co.signature.Witness != null) {
- wit = new Witness();
- wit.decode(co.signature.Witness);
- }
-
- var keylocator = co.signedInfo.locator;
- if (keylocator.type == KeyLocatorType.KEYNAME) {
- if (LOG > 3) console.log("KeyLocator contains KEYNAME");
- //var keyname = keylocator.keyName.contentName.getName();
- //console.log(nameStr);
- //console.log(keyname);
-
- if (keylocator.keyName.contentName.match(co.name)) {
- if (LOG > 3) console.log("Content is key itself");
-
- var rsakey = decodeSubjectPublicKeyInfo(co.content);
- var verified = rsakey.verifyByteArray(co.rawSignatureData, wit, sigHex);
- var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
-
- currentClosure.upcall(flag, new UpcallInfo(ndn, null, 0, co));
-
- // SWT: We don't need to store key here since the same key will be
- // stored again in the closure.
- //var keyEntry = new KeyStoreEntry(keylocator.keyName, rsakey, new Date().getTime());
- //NDN.addKeyEntry(keyEntry);
- //console.log(NDN.KeyStore);
- } else {
- // Check local key store
- var keyEntry = NDN.getKeyByName(keylocator.keyName);
- if (keyEntry) {
- // Key found, verify now
- if (LOG > 3) console.log("Local key cache hit");
- var rsakey = keyEntry.rsaKey;
- var verified = rsakey.verifyByteArray(co.rawSignatureData, wit, sigHex);
- var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
-
- // Raise callback
- currentClosure.upcall(flag, new UpcallInfo(ndn, null, 0, co));
- } else {
- // Not found, fetch now
- if (LOG > 3) console.log("Fetch key according to keylocator");
- var nextClosure = new KeyFetchClosure(co, currentClosure, keylocator.keyName, sigHex, wit);
- var interest = new Interest(keylocator.keyName.contentName.getPrefix(4));
- interest.interestLifetime = 4000; // milliseconds
- self.expressInterest(ndn, interest, nextClosure);
- }
- }
- } else if (keylocator.type == KeyLocatorType.KEY) {
- if (LOG > 3) console.log("Keylocator contains KEY");
-
- var rsakey = decodeSubjectPublicKeyInfo(co.signedInfo.locator.publicKey);
- var verified = rsakey.verifyByteArray(co.rawSignatureData, wit, sigHex);
-
- var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
- // Raise callback
- currentClosure.upcall(Closure.UPCALL_CONTENT, new UpcallInfo(ndn, null, 0, co));
-
- // Since KeyLocator does not contain key name for this key,
- // we have no way to store it as a key entry in KeyStore.
- } else {
- var cert = keylocator.certificate;
- console.log("KeyLocator contains CERT");
- console.log(cert);
-
- // TODO: verify certificate
- }
- }
- }
- }
- } else {
- console.log('Incoming packet is not Interest or ContentObject. Discard now.');
- }
-
- delete decoder;
-
- // Renew StrcutureDecoder and buffer after we process a full packet
- delete self.structureDecoder;
- delete self.buffer;
- self.structureDecoder = new BinaryXMLStructureDecoder();
- self.buffer = new Uint8Array(self.maxBufferSize);
- self.bufferOffset = 0;
}
}
@@ -346,12 +117,7 @@
// Fetch ccndid now
var interest = new Interest(NDN.ccndIdFetcher);
interest.interestLifetime = 4000; // milliseconds
- var subarray = encodeToBinaryInterest(interest);
-
- var bytes = new Uint8Array(subarray.length);
- bytes.set(subarray);
-
- self.ws.send(bytes.buffer);
+ this.send(encodeToBinaryInterest(interest));
}
this.ws.onerror = function(ev) {
@@ -371,108 +137,62 @@
}
};
-WebSocketTransport.prototype.expressInterest = function(ndn, interest, closure) {
+/*
+ * Send the Uint8Array data.
+ */
+WebSocketTransport.prototype.send = function(data) {
if (this.ws != null) {
- //TODO: check local content store first
-
- var binaryInterest = encodeToBinaryInterest(interest);
- var bytearray = new Uint8Array(binaryInterest.length);
- bytearray.set(binaryInterest);
-
- if (closure != null) {
- var pitEntry = new PITEntry(interest, closure);
- NDN.PITTable.push(pitEntry);
- closure.pitEntry = pitEntry;
- }
-
- this.ws.send(bytearray.buffer);
+ // If we directly use data.buffer to feed ws.send(),
+ // WebSocket may end up sending a packet with 10000 bytes of data.
+ // That is, WebSocket will flush the entire buffer
+ // regardless of the offset of the Uint8Array. So we have to create
+ // a new Uint8Array buffer with just the right size and copy the
+ // content from binaryInterest to the new buffer.
+ // ---Wentao
+ var bytearray = new Uint8Array(data.length);
+ bytearray.set(data);
+ this.ws.send(bytearray.buffer);
if (LOG > 3) console.log('ws.send() returned.');
-
- // Set interest timer
- if (closure != null) {
- pitEntry.timerID = setTimeout(function() {
- if (LOG > 3) console.log("Interest time out.");
-
- // Remove PIT entry from NDN.PITTable
- var index = NDN.PITTable.indexOf(pitEntry);
- //console.log(NDN.PITTable);
- if (index >= 0)
- NDN.PITTable.splice(index, 1);
- //console.log(NDN.PITTable);
- //console.log(pitEntry.interest.name.getName());
-
- // Raise closure callback
- closure.upcall(Closure.UPCALL_INTEREST_TIMED_OUT, new UpcallInfo(ndn, interest, 0, null));
- }, interest.interestLifetime); // interestLifetime is in milliseconds.
- //console.log(closure.timerID);
- }
}
else
console.log('WebSocket connection is not established.');
-};
-
-
-// For publishing data
-var CSTable = new Array();
-
-var CSEntry = function CSEntry(name, closure) {
- this.name = name; // String
- this.closure = closure; // Closure
-};
-
-function getEntryForRegisteredPrefix(name) {
- for (var i = 0; i < CSTable.length; i++) {
- if (CSTable[i].name.match(name) != null)
- return CSTable[i];
- }
- return null;
}
-WebSocketTransport.prototype.registerPrefix = function(ndn, name, closure, flag) {
- if (this.ws != null) {
- if (this.ccndid == null) {
- console.log('ccnd node ID unkonwn. Cannot register prefix.');
- return -1;
- }
-
- var fe = new ForwardingEntry('selfreg', name, null, null, 3, 2147483647);
- var bytes = encodeForwardingEntry(fe);
-
- var si = new SignedInfo();
- si.setFields();
-
- var co = new ContentObject(new Name(), si, bytes, new Signature());
- co.sign();
- var coBinary = encodeToBinaryContentObject(co);
-
- //var nodename = unescape('%00%88%E2%F4%9C%91%16%16%D6%21%8E%A0c%95%A5%A6r%11%E0%A0%82%89%A6%A9%85%AB%D6%E2%065%DB%AF');
- var nodename = this.ccndid;
- var interestName = new Name(['ccnx', nodename, 'selfreg', coBinary]);
-
- var interest = new Interest(interestName);
- interest.scope = 1;
- var binaryInterest = encodeToBinaryInterest(interest);
- // If we directly use binaryInterest.buffer to feed ws.send(),
- // WebSocket will end up sending a packet with 10000 bytes of data.
- // That is, WebSocket will flush the entire buffer in BinaryXMLEncoder
- // regardless of the offset of the Uint8Array. So we have to create
- // a new Uint8Array buffer with just the right size and copy the
- // content from binaryInterest to the new buffer.
- // ---Wentao
- var bytearray = new Uint8Array(binaryInterest.length);
- bytearray.set(binaryInterest);
- if (LOG > 3) console.log('Send Interest registration packet.');
-
- var csEntry = new CSEntry(name.getName(), closure);
- CSTable.push(csEntry);
-
- this.ws.send(bytearray.buffer);
-
- return 0;
- } else {
- console.log('WebSocket connection is not established.');
- return -1;
+WebSocketTransport.prototype.expressInterest = function(ndn, interest, closure) {
+ if (ndn.readyStatus != NDN.OPENED) {
+ console.log('Connection is not established.');
+ return;
+ }
+
+ //TODO: check local content store first
+ if (closure != null) {
+ var pitEntry = new PITEntry(interest, closure);
+ // TODO: This needs to be a single thread-safe transaction on a global object.
+ NDN.PITTable.push(pitEntry);
+ closure.pitEntry = pitEntry;
}
+
+ // Set interest timer
+ if (closure != null) {
+ pitEntry.timerID = setTimeout(function() {
+ if (LOG > 3) console.log("Interest time out.");
+
+ // Remove PIT entry from NDN.PITTable.
+ // TODO: Make this a thread-safe operation on the global PITTable.
+ var index = NDN.PITTable.indexOf(pitEntry);
+ //console.log(NDN.PITTable);
+ if (index >= 0)
+ NDN.PITTable.splice(index, 1);
+ //console.log(NDN.PITTable);
+ //console.log(pitEntry.interest.name.getName());
+
+ // Raise closure callback
+ closure.upcall(Closure.UPCALL_INTEREST_TIMED_OUT, new UpcallInfo(ndn, interest, 0, null));
+ }, interest.interestLifetime); // interestLifetime is in milliseconds.
+ //console.log(closure.timerID);
+ }
+
+ this.send(encodeToBinaryInterest(interest));
};
/**
@@ -7809,6 +7529,7 @@
// Event handler
this.onopen = (settings.onopen || function() { if (LOG > 3) console.log("NDN connection established."); });
this.onclose = (settings.onclose || function() { if (LOG > 3) console.log("NDN connection closed."); });
+ this.ccndid = null;
};
NDN.UNOPEN = 0; // created but not opened yet
@@ -7879,6 +7600,22 @@
return result;
};
+// For publishing data
+NDN.CSTable = new Array();
+
+var CSEntry = function CSEntry(name, closure) {
+ this.name = name; // String
+ this.closure = closure; // Closure
+};
+
+function getEntryForRegisteredPrefix(name) {
+ for (var i = 0; i < NDN.CSTable.length; i++) {
+ if (NDN.CSTable[i].name.match(name) != null)
+ return NDN.CSTable[i];
+ }
+ return null;
+}
+
/*
* Return a function that selects a host at random from hostList and returns { host: host, port: port }.
* If no more hosts remain, return null.
@@ -7933,7 +7670,220 @@
};
NDN.prototype.registerPrefix = function(name, closure, flag) {
- return this.transport.registerPrefix(this, name, closure, flag);
+ if (this.readyStatus != NDN.OPENED) {
+ console.log('Connection is not established.');
+ return -1;
+ }
+
+ if (this.ccndid == null) {
+ console.log('ccnd node ID unkonwn. Cannot register prefix.');
+ return -1;
+ }
+
+ var fe = new ForwardingEntry('selfreg', name, null, null, 3, 2147483647);
+ var bytes = encodeForwardingEntry(fe);
+
+ var si = new SignedInfo();
+ si.setFields();
+
+ var co = new ContentObject(new Name(), si, bytes, new Signature());
+ co.sign();
+ var coBinary = encodeToBinaryContentObject(co);
+
+ //var nodename = unescape('%00%88%E2%F4%9C%91%16%16%D6%21%8E%A0c%95%A5%A6r%11%E0%A0%82%89%A6%A9%85%AB%D6%E2%065%DB%AF');
+ var nodename = this.ccndid;
+ var interestName = new Name(['ccnx', nodename, 'selfreg', coBinary]);
+
+ var interest = new Interest(interestName);
+ interest.scope = 1;
+ if (LOG > 3) console.log('Send Interest registration packet.');
+
+ var csEntry = new CSEntry(name.getName(), closure);
+ NDN.CSTable.push(csEntry);
+
+ this.transport.send(encodeToBinaryInterest(interest));
+
+ return 0;
+};
+
+/*
+ * This is called when an entire binary XML element is received, such as a ContentObject or Interest.
+ * Look up in the PITTable and call the closure callback.
+ */
+NDN.prototype.onReceivedElement = function(element) {
+ if (LOG>3) console.log('Complete element received. Length ' + element.length + '. Start decoding.');
+ var decoder = new BinaryXMLDecoder(element);
+ // Dispatch according to packet type
+ if (decoder.peekStartElement(CCNProtocolDTags.Interest)) { // Interest packet
+ if (LOG > 3) console.log('Interest packet received.');
+
+ var interest = new Interest();
+ interest.from_ccnb(decoder);
+ if (LOG > 3) console.log(interest);
+ var nameStr = escape(interest.name.getName());
+ if (LOG > 3) console.log(nameStr);
+
+ var entry = getEntryForRegisteredPrefix(nameStr);
+ if (entry != null) {
+ //console.log(entry);
+ var info = new UpcallInfo(this, interest, 0, null);
+ var ret = entry.closure.upcall(Closure.UPCALL_INTEREST, info);
+ if (ret == Closure.RESULT_INTEREST_CONSUMED && info.contentObject != null)
+ this.transport.send(encodeToBinaryContentObject(info.contentObject));
+ }
+ } else if (decoder.peekStartElement(CCNProtocolDTags.ContentObject)) { // Content packet
+ if (LOG > 3) console.log('ContentObject packet received.');
+
+ var co = new ContentObject();
+ co.from_ccnb(decoder);
+
+ if (this.ccndid == null && NDN.ccndIdFetcher.match(co.name)) {
+ // We are in starting phase, record publisherPublicKeyDigest in ccndid
+ if(!co.signedInfo || !co.signedInfo.publisher
+ || !co.signedInfo.publisher.publisherPublicKeyDigest) {
+ console.log("Cannot contact router, close NDN now.");
+
+ // Close NDN if we fail to connect to a ccn router
+ this.readyStatus = NDN.CLOSED;
+ this.onclose();
+ //console.log("NDN.onclose event fired.");
+ } else {
+ //console.log('Connected to ccnd.');
+ this.ccndid = co.signedInfo.publisher.publisherPublicKeyDigest;
+ if (LOG>3) console.log(ndn.ccndid);
+
+ // Call NDN.onopen after success
+ this.readyStatus = NDN.OPENED;
+ this.onopen();
+ //console.log("NDN.onopen event fired.");
+ }
+ } else {
+ var pitEntry = NDN.getEntryForExpressedInterest(co.name);
+ if (pitEntry != null) {
+ //console.log(pitEntry);
+ // Remove PIT entry from NDN.PITTable
+ var index = NDN.PITTable.indexOf(pitEntry);
+ if (index >= 0)
+ NDN.PITTable.splice(index, 1);
+
+ var currentClosure = pitEntry.closure;
+
+ // Cancel interest timer
+ clearTimeout(pitEntry.timerID);
+ //console.log("Clear interest timer");
+ //console.log(currentClosure.timerID);
+
+ // Key verification
+
+ // Recursive key fetching & verification closure
+ var KeyFetchClosure = function KeyFetchClosure(content, closure, key, sig, wit) {
+ this.contentObject = content; // unverified content object
+ this.closure = closure; // closure corresponding to the contentObject
+ this.keyName = key; // name of current key to be fetched
+ this.sigHex = sig; // hex signature string to be verified
+ this.witness = wit;
+
+ Closure.call(this);
+ };
+
+ var thisNdn = this;
+ KeyFetchClosure.prototype.upcall = function(kind, upcallInfo) {
+ if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
+ console.log("In KeyFetchClosure.upcall: interest time out.");
+ console.log(this.keyName.contentName.getName());
+ } else if (kind == Closure.UPCALL_CONTENT) {
+ //console.log("In KeyFetchClosure.upcall: signature verification passed");
+
+ var rsakey = decodeSubjectPublicKeyInfo(upcallInfo.contentObject.content);
+ var verified = rsakey.verifyByteArray(this.contentObject.rawSignatureData, this.witness, this.sigHex);
+
+ var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
+ //console.log("raise encapsulated closure");
+ this.closure.upcall(flag, new UpcallInfo(thisNdn, null, 0, this.contentObject));
+
+ // Store key in cache
+ var keyEntry = new KeyStoreEntry(keylocator.keyName, rsakey, new Date().getTime());
+ NDN.addKeyEntry(keyEntry);
+ //console.log(NDN.KeyStore);
+ } else if (kind == Closure.UPCALL_CONTENT_BAD) {
+ console.log("In KeyFetchClosure.upcall: signature verification failed");
+ }
+ };
+
+ if (co.signedInfo && co.signedInfo.locator && co.signature) {
+ if (LOG > 3) console.log("Key verification...");
+ var sigHex = DataUtils.toHex(co.signature.signature).toLowerCase();
+
+ var wit = null;
+ if (co.signature.Witness != null) {
+ wit = new Witness();
+ wit.decode(co.signature.Witness);
+ }
+
+ var keylocator = co.signedInfo.locator;
+ if (keylocator.type == KeyLocatorType.KEYNAME) {
+ if (LOG > 3) console.log("KeyLocator contains KEYNAME");
+ //var keyname = keylocator.keyName.contentName.getName();
+ //console.log(nameStr);
+ //console.log(keyname);
+
+ if (keylocator.keyName.contentName.match(co.name)) {
+ if (LOG > 3) console.log("Content is key itself");
+
+ var rsakey = decodeSubjectPublicKeyInfo(co.content);
+ var verified = rsakey.verifyByteArray(co.rawSignatureData, wit, sigHex);
+ var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
+
+ currentClosure.upcall(flag, new UpcallInfo(this, null, 0, co));
+
+ // SWT: We don't need to store key here since the same key will be
+ // stored again in the closure.
+ //var keyEntry = new KeyStoreEntry(keylocator.keyName, rsakey, new Date().getTime());
+ //NDN.addKeyEntry(keyEntry);
+ //console.log(NDN.KeyStore);
+ } else {
+ // Check local key store
+ var keyEntry = NDN.getKeyByName(keylocator.keyName);
+ if (keyEntry) {
+ // Key found, verify now
+ if (LOG > 3) console.log("Local key cache hit");
+ var rsakey = keyEntry.rsaKey;
+ var verified = rsakey.verifyByteArray(co.rawSignatureData, wit, sigHex);
+ var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
+
+ // Raise callback
+ currentClosure.upcall(flag, new UpcallInfo(this, null, 0, co));
+ } else {
+ // Not found, fetch now
+ if (LOG > 3) console.log("Fetch key according to keylocator");
+ var nextClosure = new KeyFetchClosure(co, currentClosure, keylocator.keyName, sigHex, wit);
+ this.expressInterest(keylocator.keyName.contentName.getPrefix(4), nextClosure);
+ }
+ }
+ } else if (keylocator.type == KeyLocatorType.KEY) {
+ if (LOG > 3) console.log("Keylocator contains KEY");
+
+ var rsakey = decodeSubjectPublicKeyInfo(co.signedInfo.locator.publicKey);
+ var verified = rsakey.verifyByteArray(co.rawSignatureData, wit, sigHex);
+
+ var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
+ // Raise callback
+ currentClosure.upcall(Closure.UPCALL_CONTENT, new UpcallInfo(this, null, 0, co));
+
+ // Since KeyLocator does not contain key name for this key,
+ // we have no way to store it as a key entry in KeyStore.
+ } else {
+ var cert = keylocator.certificate;
+ console.log("KeyLocator contains CERT");
+ console.log(cert);
+
+ // TODO: verify certificate
+ }
+ }
+ }
+ }
+ } else
+ console.log('Incoming packet is not Interest or ContentObject. Discard now.');
};
/*
@@ -7958,8 +7908,8 @@
this.port = hostAndPort.port;
console.log("Trying host from getHostAndPort: " + this.host);
- // Fetch the ccndId.
- var interest = new Interest(NDN.ccndIdFetcher);
+ // Fetch any content.
+ var interest = new Interest(new Name("/"));
interest.interestLifetime = 4000; // milliseconds
var thisNDN = this;
@@ -7985,8 +7935,7 @@
NDN.ConnectClosure.prototype.upcall = function(kind, upcallInfo) {
if (!(kind == Closure.UPCALL_CONTENT ||
- kind == Closure.UPCALL_CONTENT_UNVERIFIED ||
- kind == Closure.UPCALL_INTEREST))
+ kind == Closure.UPCALL_CONTENT_UNVERIFIED))
// The upcall is not for us.
return Closure.RESULT_ERR;
@@ -7998,3 +7947,43 @@
return Closure.RESULT_OK;
};
+/*
+ * A BinaryXmlElementReader lets you call onReceivedData multiple times which uses a
+ * BinaryXMLStructureDecoder to detect the end of a binary XML element and calls
+ * elementListener.onReceivedElement(element) with the element.
+ * This handles the case where a single call to onReceivedData may contain multiple elements.
+ */
+var BinaryXmlElementReader = function BinaryXmlElementReader(elementListener) {
+ this.elementListener = elementListener;
+ this.dataParts = [];
+ this.structureDecoder = new BinaryXMLStructureDecoder();
+};
+
+BinaryXmlElementReader.prototype.onReceivedData = function(/* Uint8Array */ rawData) {
+ // Process multiple objects in the data.
+ while(true) {
+ // Scan the input to check if a whole ccnb object has been read.
+ this.structureDecoder.seek(0);
+ if (this.structureDecoder.findElementEnd(rawData)) {
+ // Got the remainder of an object. Report to the caller.
+ this.dataParts.push(rawData.subarray(0, this.structureDecoder.offset));
+ this.elementListener.onReceivedElement(DataUtils.concatArrays(this.dataParts));
+
+ // Need to read a new object.
+ rawData = rawData.subarray(this.structureDecoder.offset, rawData.length);
+ this.dataParts = [];
+ this.structureDecoder = new BinaryXMLStructureDecoder();
+ if (rawData.length == 0)
+ // No more data in the packet.
+ return;
+
+ // else loop back to decode.
+ }
+ else {
+ // Save for a later call to concatArrays so that we only copy data once.
+ this.dataParts.push(rawData);
+ if (LOG>3) console.log('Incomplete packet received. Length ' + rawData.length + '. Wait for more input.');
+ return;
+ }
+ }
+}
\ No newline at end of file