Skip to content
404 changes: 404 additions & 0 deletions chrome/content/Cbor.js

Large diffs are not rendered by default.

118 changes: 72 additions & 46 deletions chrome/content/Handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,14 @@ Copper.defaultHandler = function(message) {

if (message.getRTT) Copper.updateLabel('info_code', ' (RTT ' + message.getRTT() + ' ms)', true);

if (message.getContentFormat()==Copper.CONTENT_TYPE_APPLICATION_LINK_FORMAT) {
if (message.getContentFormat()==Copper.CONTENT_TYPE_APPLICATION_LINK_FORMAT) {
Copper.updateResourceLinks( Copper.parseLinkFormat( document.getElementById('packet_payload').value ) );
}
} else if (message.getContentFormat()==Copper.CONTENT_TYPE_APPLICATION_CBOR &&
(Copper.WELL_KNOWN_RESOURCES.indexOf(message.getOption(Copper.OPTION_URI_PATH)) > -1)) {
// FIXME: investigate why the code below triggers a parsing error
// Copper.updateResourceLinks( Copper.parseLinkFormat( Copper.parseCBORFormat(document.getElementById('packet_payload').value ) ) );
}

};

//Handle ping responses
Expand Down Expand Up @@ -182,53 +187,74 @@ Copper.observingHandler = function(message) {
};

// Handle messages with link format payload
Copper.discoverCache = new String();
Copper.discoverHandler = function(message) {

Copper.logEvent('INFO: discoverHandler()');

if (message.getCode()!=Copper.CODE_2_05_CONTENT) return;

if (message.getContentFormat()==Copper.CONTENT_TYPE_APPLICATION_LINK_FORMAT) {

Copper.updateLabel('info_code', 'Discovering');

if (message.isOption(Copper.OPTION_BLOCK2)) {

if (message.getBlock2More()) {
Copper.discoverCache = {};
Copper.discoverHandler = function(message, stoppedListening) {

// block size negotiation
let size = Copper.negotiateBlockSize(message);
let offset = message.getBlock2Offset();
let num = offset/size;
Copper.discover(num, size);
}

if (message.getBlock2Number()==0) {
Copper.logEvent('INFO: Starting new discover cache');
Copper.discoverCache = new String();
}

Copper.discoverCache += Copper.bytes2str( message.getPayload() );

if (!message.getBlock2More()) {
Copper.logEvent('INFO: Appending discover cache');
// link-format
Copper.resourcesCached = false;
Copper.updateResourceLinks( Copper.parseLinkFormat( Copper.discoverCache ) );
Copper.logEvent('INFO: discoverHandler()');

document.getElementById('toolbar_discover').image = 'chrome://copper/skin/tool_discover.png';
}
} else {
// link-format
Copper.resourcesCached = false;
Copper.updateResourceLinks( Copper.parseLinkFormat( Copper.bytes2str( message.getPayload() ) ) );
if (message.getCode()!=Copper.CODE_2_05_CONTENT) return;

document.getElementById('toolbar_discover').image = 'chrome://copper/skin/tool_discover.png';
}
} else {
Copper.logWarning(new Error("Discovery requires 'application/link-format', but received "+message.getContentFormat()));
}
let domain = "["+message.from.addrress+"]:"+ message.from.port;

Copper.logEvent('INFO: discovery of ' + message.getOption(Copper.OPTION_URI_PATH) );

if (message.getContentFormat()==Copper.CONTENT_TYPE_APPLICATION_LINK_FORMAT
|| (message.getContentFormat()==Copper.CONTENT_TYPE_APPLICATION_CBOR) ) {

Copper.updateLabel('info_code', 'Discovering');

if (message.isOption(Copper.OPTION_BLOCK2)) {

if (message.getBlock2Number()==0) {
Copper.logEvent('INFO: Starting new discover cache');
Copper.discoverCache[domain] = {};
Copper.discoverCache[domain].payloads = message.getPayload();
Copper.discoverCache[domain].from = message.from;
} else {
Copper.logEvent('INFO: Appending '+message.getPayload().length +' to discover cache ' + Copper.discoverCache[domain].payloads.length);
Copper.discoverCache[domain].payloads = Copper.discoverCache[domain].payloads.concat( message.getPayload() );
Copper.logEvent('INFO: discover cache is now ' + Copper.discoverCache[domain].payloads.length);
}

if (message.getBlock2More()) {
// block size negotiation
let size = Copper.negotiateBlockSize(message);
let offset = message.getBlock2Offset();
let num = offset/size;
Copper.startDiscovery(message.from, num, size);
} else {
// got all blocks
Copper.resourcesCached = false;
if (message.getContentFormat()==Copper.CONTENT_TYPE_APPLICATION_LINK_FORMAT) {
// link-format
Copper.discoverCache[domain].payloads = Copper.bytes2str(Copper.discoverCache[domain].payloads);
} else {
// oic link format
Copper.discoverCache[domain].payloads = Copper.parseCBORFormat( Copper.discoverCache[domain].payloads );
}
Copper.updateResourceLinks( Copper.parseLinkFormat( Copper.discoverCache[domain]) );
}
} else {
// link-format
Copper.resourcesCached = false;
Copper.discoverCache[domain] = {};
Copper.discoverCache[domain].from = message.from;
if (message.getContentFormat()==Copper.CONTENT_TYPE_APPLICATION_LINK_FORMAT) {
Copper.discoverCache[domain].payloads = Copper.bytes2str( message.getPayload() );
} else {
Copper.discoverCache[domain].payloads = Copper.parseCBORFormat(message.getPayload());
}
Copper.updateResourceLinks( Copper.parseLinkFormat( Copper.discoverCache[domain] ) );
}
if(stoppedListening) {
document.getElementById('toolbar_discover').image = 'chrome://copper/skin/tool_discover.png';
Copper.displayPayload(message);
}
Copper.displayMessageInfo(message);

} else {
Copper.logWarning(new Error("Discovery requires 'application/link-format', but received "+message.getContentFormat()));
}
};

Copper.errorHandler = function(message) {
Expand Down
106 changes: 99 additions & 7 deletions chrome/content/Helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Copper.getRequestType = function() {
Copper.loadBehavior = function() {
Copper.behavior.requests = Copper.prefManager.getCharPref('extensions.copper.behavior.requests');
Copper.behavior.retransmissions = Copper.prefManager.getBoolPref('extensions.copper.behavior.retransmissions');
Copper.behavior.oic = Copper.prefManager.getBoolPref('extensions.copper.behavior.oic');
Copper.behavior.sendDuplicates = Copper.prefManager.getBoolPref('extensions.copper.behavior.send-duplicates');
Copper.behavior.showUnknown = Copper.prefManager.getBoolPref('extensions.copper.behavior.show-unknown');
Copper.behavior.rejectUnknown = Copper.prefManager.getBoolPref('extensions.copper.behavior.reject-unknown');
Expand All @@ -62,6 +63,7 @@ Copper.loadBehavior = function() {
// sync XUL menu with behavior object
Copper.updateBehavior = function() {
document.getElementById('menu_behavior_requests_' + Copper.behavior.requests).setAttribute('checked', 'true');
document.getElementById('menu_behavior_oic').setAttribute('checked', Copper.behavior.oic);
document.getElementById('menu_behavior_retransmissions').setAttribute('checked', Copper.behavior.retransmissions);
document.getElementById('menu_behavior_send_duplicates').setAttribute('checked', Copper.behavior.sendDuplicates);
document.getElementById('menu_behavior_show_unknown').setAttribute('checked', Copper.behavior.showUnknown);
Expand All @@ -78,6 +80,10 @@ Copper.updateBehavior = function() {
Copper.behaviorUpdate = function(target) {
if (target.id.substr(0,22)=='menu_behavior_requests') {
Copper.behavior.requests = target.value;
} else if (target.id=='menu_behavior_oic') {
Copper.behavior.oic = target.getAttribute('checked')=='true';
Copper.resources = new Object();
Copper.updateResourceLinks();
} else if (target.id=='menu_behavior_retransmissions') {
Copper.behavior.retransmissions = target.getAttribute('checked')=='true';
Copper.endpoint.setRetransmissions(Copper.behavior.retransmissions);
Expand Down Expand Up @@ -113,6 +119,7 @@ Copper.behaviorUpdate = function(target) {
Copper.saveBehavior = function() {
Copper.prefManager.setCharPref('extensions.copper.behavior.requests', Copper.behavior.requests);
Copper.prefManager.setBoolPref('extensions.copper.behavior.retransmissions', Copper.behavior.retransmissions);
Copper.prefManager.setBoolPref('extensions.copper.behavior.oic', Copper.behavior.oic);
Copper.prefManager.setBoolPref('extensions.copper.behavior.send-duplicates', Copper.behavior.sendDuplicates);
Copper.prefManager.setBoolPref('extensions.copper.behavior.show-unknown', Copper.behavior.showUnknown);
Copper.prefManager.setBoolPref('extensions.copper.behavior.reject-unknown', Copper.behavior.rejectUnknown);
Expand Down Expand Up @@ -331,10 +338,69 @@ Copper.checkUri = function(uri, caller) {
}
};

Copper.parseLinkFormat = function(data) {

var links = new Object();
Copper.parseCBORFormat = function(data) {
let abs = data.length;
let ab = new ArrayBuffer(abs);
let abv = new DataView(ab);
for(var i=0; i < abs; i++)
abv.setUint8(i, data[i]);
return Copper.cbor.decode(ab);
};

Copper.createCBORFormat = function (obj) {
let ab = Copper.cbor.encode(obj);
let abv = new DataView(ab);
let abs = abv.byteLength;
let a = new Array(abs);
for(var i=0; i < abs; i++)
a[i] = abv.getUint8(i, abv[i]);
return a;
}

Copper.parseLinkFormat = function(cache) {
// This should really be based on rt=oic.rt.res
// but iotivity doesn't set this yet.
let data = cache.payloads;
let from = cache.from;
if ( data instanceof Array ) {
var baseURL = "coap://"+ from.address + ':' + from.port;
var links = new Object();
for (var i = 0; i < data.length; i++) {
if((data[i].links) instanceof Array)
{
Copper.parseOICLinkFormat(data[i], baseURL, links);
}
}
delete data[0]['links'];
links[baseURL + Copper.WELL_KNOWN_RESOURCES] = data[0];
return links;
}
return Copper.parseRawLinkFormat (data);

};

Copper.parseOICLinkFormat = function(data, baseURL, olinks) {
var elm = data.links;

// add all links
for (var i = 0; i<elm.length; i++)
{
if(-1 === elm[i].href.indexOf('://')) {
let sep = (0 === elm[i].href.indexOf('/')) ? '': '/';
elm[i].href = baseURL + sep + elm[i].href;
}

olinks[elm[i].href] = elm[i];
delete elm[i]['href'];
}
// add oic/res
return olinks;
};

Copper.parseRawLinkFormat = function(data) {

var links = new Object();

// totally complicated but supports ',' and '\n' to separate links and ',' as well as '\"' within quoted strings
var format = data.match(/(<[^>]+>\s*(;\s*\w+\s*(=\s*(\w+|"([^"\\]*(\\.[^"\\]*)*)")\s*)?)*)/g);
Copper.logEvent('-parsing link-format----------------------------');
Expand Down Expand Up @@ -391,6 +457,21 @@ Copper.parseLinkFormat = function(data) {
return links;
};

Copper.stringifyReplacer = function(key, value) {
var ua = this[key];
if(value instanceof Uint8Array) {
// Copper.logEvent('replacestringify ' + (typeof value) + ' ['+key+'] = ' + value);
var h='';
for (var i = 0; i<ua.length; i++) {
h += ua[i].toString(16)
}
return h;
} else {
//Copper.logEvent('stringify ' + (typeof value) + ' key = '+key+'; value = ' + this[key]);
return value;
}
}

Copper.updateResourceLinks = function(add) {

// merge links
Expand All @@ -405,9 +486,15 @@ Copper.updateResourceLinks = function(add) {

// add well-known resource to resource cache
if (!Copper.resources[Copper.WELL_KNOWN_RESOURCES]) {
Copper.resources[Copper.WELL_KNOWN_RESOURCES] = new Object();
Copper.resources[Copper.WELL_KNOWN_RESOURCES]['ct'] = 40;
Copper.resources[Copper.WELL_KNOWN_RESOURCES]['title'] = 'Resource discovery';
if (Copper.behavior.oic) {
// OIC parsing will add the well known already
//Copper.resources[Copper.WELL_KNOWN_RESOURCES] = new Object();
//Copper.resources[Copper.WELL_KNOWN_RESOURCES]['rt'] = 'oic.wk.res';
} else {
Copper.resources[Copper.WELL_KNOWN_RESOURCES] = new Object();
Copper.resources[Copper.WELL_KNOWN_RESOURCES]['ct'] = 40;
Copper.resources[Copper.WELL_KNOWN_RESOURCES]['title'] = 'Resource discovery';
}
}

Copper.clearTree();
Expand All @@ -427,7 +514,7 @@ Copper.updateResourceLinks = function(add) {
}

// save in cache
let saveRes = JSON.stringify(Copper.resources);
let saveRes = JSON.stringify(Copper.resources, Copper.stringifyReplacer);
if (Copper.hostname!='') Copper.prefManager.setCharPref('extensions.copper.resources.'+Copper.hostname+':'+Copper.port, escape(saveRes));
};

Expand Down Expand Up @@ -548,6 +635,11 @@ Copper.displayPayload = function(message) {
Copper.renderText(Copper.displayCache);
Copper.renderLinkFormat(Copper.displayCache);
break;
case Copper.CONTENT_TYPE_APPLICATION_CBOR:
if (!Copper.displayInvalid && !message.getBlock2More()) {
Copper.renderCBORFormat(Copper.displayCache);
};
break;
default:
Copper.renderText(Copper.displayCache);
}
Expand Down
Loading