Skip to content
This repository was archived by the owner on Jan 18, 2021. It is now read-only.

Commit c779d2e

Browse files
committed
config; manager webapp
1 parent e595cdc commit c779d2e

14 files changed

+234
-31
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
node_modules
2+
config

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ NDNSF is compatible with [NDNx](https://github.com/named-data/ndnx) and [CCNx](h
1515

1616
## Usage
1717

18-
* A TCP connection to e.hub.ndn.ucla.edu is made automatically, and a WebSocket connection to ws://a.ws.ndn.ucla.edu:9696/ is made automatically. FIB entry ndn:/ is added towards these faces. There's currently no way to make a new outgoing connection.
18+
* Rename config-sample directory to config, and modify configuration files.
1919
* Ask local apps to use TCP transport instead of UNIX sockets:
2020
* NDN-On-Node apps can be used directly.
2121
* NDNx apps need `NDN_LOCAL_TRANSPORT=tcp` environment variable.
@@ -34,12 +34,12 @@ NDNSF supports the following features:
3434
* smart forwarding strategy
3535
* TCP transport
3636
* WebSocket transport
37+
* [status web page](http://localhost:9696) with operator key authentication
3738

3839
NDNSF does not yet support:
3940

4041
* CS - Content Store
4142
* ForwardingFlags
4243
* UDP transport
4344
* Face Management Protocol
44-
* status web page
4545

config-sample/README.md

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# NDNSF Configuration Files
2+
3+
This directory contains NDNSF configuration files. This directory must be renamed as `config` to take effect.
4+
5+
## main.json - Main Configuration
6+
7+
"listen_tcp": { // listen for TCP connections
8+
"port": 9695 // local port number
9+
}
10+
// -- or --
11+
"listen_tcp": false // don't listen for TCP connections
12+
13+
"listen_web": { // listen for HTTP requests
14+
"port": 9696 // local port number
15+
16+
"ws": "/" // listen for WebSockets connections on path
17+
// -- or --
18+
"ws": false // don't listen for WebSockets connections
19+
}
20+
// -- or --
21+
"listen_web": false // don't listen for HTTP requests
22+
23+
"mgr_base": "http://yoursunny.com/p/NDNSF/" // base URL of NDNSF manager webapp
24+
25+
"strategy_type": "SmartStrategy" // forwarding strategy
26+
27+
## faces.json - Outgoing Faces
28+
29+
{
30+
"type": "tcp" // connect to TCP peer
31+
"host": "e.hub.ndn.ucla.edu" // remote hostname or IP address
32+
"port": 9695 // remote port number
33+
"fib": [ // FIB entries for this face
34+
{
35+
"prefix": "/" // prefix as URI
36+
}
37+
]
38+
}
39+
40+
{
41+
"type": "ws" // connect to WebSocket address
42+
"address": "ws://a.ws.ndn.ucla.edu:9696/" // remote WebSocket address
43+
"fib": [ // FIB entries for this face
44+
]
45+
}
46+
47+
## keypair.json - Router Key
48+
49+
Generate one on <http://yoursunny.com/p/NDNSF/?p=keypair>
50+
51+
## operators.txt - Trusted Operator Keys
52+
53+
Each line is a trusted operator key digest in HEX format.
54+
NDNSF manager webapp will prompt you to add a digest into this file.
55+

config-sample/faces.json

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[
2+
{
3+
"type": "tcp", "host": "e.hub.ndn.ucla.edu", "port": 9695,
4+
"fib": [
5+
{ "prefix": "/" }
6+
]
7+
},
8+
{
9+
"type": "ws", "address": "ws://a.ws.ndn.ucla.edu:9696/",
10+
"fib": [
11+
{ "prefix": "/" },
12+
{ "prefix": "/ndn/ucla.edu" }
13+
]
14+
}
15+
]

config-sample/keypair.json

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"pvtkey":"-----BEGIN RSA PRIVATE KEY-----\nMIICXQIBAAKBgQD3jAz+tlGESPISzn5zkPY6ueIiztOQLJheHf2TaqJ0HdHLW9PS\nFB2bduiDw5T78mREZRJ0H0yoy73L+O7+LNuwVuYKOHbli7OaXKywKay1k58JzfBL\nzsAtmWAVjBC+Ii2HAlzuve4B650fAOe3hbgbGAVjlUVTw8U7zPU2phozewIDAQAB\nAoGAbansg9Zu7GSIYQ57dGTuv\/tjE7p+fOtUoLU2hd0ClOA09Zr7jqB8sUePH\/hA\nAxFRm\/8OmsTW6BxCO59O+OkUdP4nszmxT1g0gEjTtmq5Iy0EHcway+YP2akdPP6g\ncmRlCqKyL\/4jzFcB8ia7DvaGiTS1a6QVIv9CEklc1LBmHVECQQD\/w2xwkbRTNF\/E\nMemf7LVcvcsuFZ9w\/LBncIqzD6M\/MCsLQt\/PzSWe0zsZfXV3yhU+9Neqjsmxqexh\nkl2koQNpAkEA98auYX4JD57D1ED5bd0wFWEgkn\/Kb3QvuW+ZRj23ep8OJNKGNg4T\nLp8LW0aexA1K0Q\/EfF9FdTciNUNQzsz3QwJAaUGosA8WsiNcwiZ0ai+FV\/x30Khv\nbJVhl8BWJGjsGwYcwM6twxw\/PkTaDpx2Km1NHxKuau\/Gi8pNkL4msajd+QJBAMsR\nurmMYkC7DiRXXBX+wfnDsL5gnbjasIJ6RFSdIFMPKLhlEjobLv12vAgCyPxFKJxP\nH+oO6w42MYMVuJTEx6ECQQC77WqTyp4SHRJjl258jFABovknc+K8yYKA7zNKTDEi\njV3Rs15dcJqaV5iwHPyVy\/AP63uc7KPcUADGuUM+bYM4\n-----END RSA PRIVATE KEY-----\n","pubkey":"-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD3jAz+tlGESPISzn5zkPY6ueIi\nztOQLJheHf2TaqJ0HdHLW9PSFB2bduiDw5T78mREZRJ0H0yoy73L+O7+LNuwVuYK\nOHbli7OaXKywKay1k58JzfBLzsAtmWAVjBC+Ii2HAlzuve4B650fAOe3hbgbGAVj\nlUVTw8U7zPU2phozewIDAQAB\n-----END PUBLIC KEY-----\n"}

config-sample/main.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"listen_tcp": { "port": 9695 },
3+
"listen_web": { "port": 9696, "ws": "/" },
4+
5+
"mgr_base": "http://yoursunny.com/p/NDNSF/",
6+
7+
"strategy_type": "SmartStrategy"
8+
}

config-sample/operators.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
75892d3caed3c3e6e74cf59abdc91670290b2fcaa5072bdcfb1be1d31cdbea3d

core/fib.js

+17-6
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,15 @@ Fib.prototype.delete_face = function Fib_delete_face(faceid) {
6060
}
6161
};
6262

63-
// public method provide_intclient_commands
64-
Fib.prototype.provide_intclient_commands = function Fib_provide_intclient_commands(intclient) {
63+
// public method provide_intclient
64+
Fib.prototype.provide_intclient = function Fib_provide_intclient_commands(intclient) {
6565
this.intclient = intclient;
66-
intclient.provide_op('selfreg', this.intclient_op.bind(this));
66+
intclient.provide_op('selfreg', this.intclient_command.bind(this));
67+
intclient.provide_op('fib', this.intclient_fib.bind(this));
6768
};
6869

69-
// private method intclient_op
70-
Fib.prototype.intclient_op = function Fib_intclient_op(op, interest, co, send) {
70+
// private method intclient_command
71+
Fib.prototype.intclient_command = function Fib_intclient_op(op, interest, co, send_func) {
7172
var d = new ndn.BinaryXMLDecoder(co.content);
7273
var fe = new ndn.ForwardingEntry();
7374
fe.from_ccnb(d);
@@ -87,7 +88,17 @@ Fib.prototype.intclient_op = function Fib_intclient_op(op, interest, co, send) {
8788
fe.ccndID = this.intclient.ndndid();
8889
fe.lifetime = 3600;
8990

90-
send(new ndn.ContentObject(interest.name, fe.encodeToBinary()));
91+
send_func(new ndn.ContentObject(interest.name, fe.encodeToBinary()));
92+
};
93+
94+
// private method intclient_fib
95+
Fib.prototype.intclient_fib = function Fib_intclient_fib(op, interest, co, send_func) {
96+
var fiblist = [];
97+
for (var uri in this.T) {
98+
var entry = this.T[uri];
99+
fiblist.push({ prefix:uri, faceids:entry.faceids.concat(entry.handler?[0]:[]) });
100+
}
101+
send_func(new ndn.ContentObject(interest.name, JSON.stringify(fiblist)));
91102
};
92103

93104

core/intclient.js

+38-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
var util = require('util');
22
var EventEmitter = require('events').EventEmitter;
3+
var querystring = require('querystring');
34
var ndn = require('ndn-on-node');
45

56

67
// ----------------------------------------------------------------
78
// class InternalClient
8-
var InternalClient = function InternalClient(key) {
9+
var InternalClient = function InternalClient(key, operators) {
910
EventEmitter.call(this);
1011
this.key = key;
12+
this.operators = operators;
1113
};
1214
util.inherits(InternalClient, EventEmitter);
1315

@@ -49,6 +51,12 @@ InternalClient.prototype.command = function InternalClient_command(interest) {
4951
try {
5052
co = ndn.ContentObject.parse(interest.name.getComponent(3));
5153
} catch(ex) { co = false; }
54+
if (co.signedInfo && co.signedInfo.locator && co.signedInfo.locator.type == ndn.KeyLocatorType.KEY) {
55+
var key = co.signedInfo.locator.publicKey;
56+
if (this.operators.indexOf(key.publicKeyDigest.toString('hex'))>=0 && co.verify(key)) {
57+
co.trusted_operator = true;
58+
}
59+
}
5260
}
5361
var f = this['op_'+op];
5462
if (f) {
@@ -70,6 +78,35 @@ InternalClient.prototype.op_ping = function InternalClient_op_ping(op, interest,
7078
send_func(reply);
7179
};
7280

81+
// private method op_verify_operator_key
82+
InternalClient.prototype.op_verify_operator_key = function InternalClient_op_verify_operator_key(op, interest, co, send_func) {
83+
if (co && co.trusted_operator) {
84+
var reply = new ndn.ContentObject(interest.name, 'NDNSF TRUSTED OPERATOR');
85+
send_func(reply);
86+
}
87+
};
88+
89+
// public method provide_web
90+
InternalClient.prototype.provide_web = function InternalClient_provide_web(websvr, mgr_base) {
91+
websvr.provide_op(/^\/$/, this.web_mgr_redirect.bind(this, mgr_base));
92+
};
93+
94+
// private static property web_mgr_base
95+
InternalClient.web_mgr_base = 'http://local.yoursunny.com/p/NDNSF/';
96+
97+
// private method web_mgr_redirect
98+
InternalClient.prototype.web_mgr_redirect = function InternalClient_web_mgr_redirect(mgr_base, req, resp) {
99+
var u = mgr_base + '?' + querystring.stringify({
100+
'mgr': this.ndndid().toString('hex'),
101+
'host': req.headers.host
102+
});
103+
resp.writeHead(303, {
104+
'Location': u
105+
});
106+
resp.end();
107+
};
108+
109+
73110
// ----------------------------------------------------------------
74111
exports.InternalClient = InternalClient;
75112

face/facemgr.js

+16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
var util = require('util');
22
var EventEmitter = require('events').EventEmitter;
3+
var ndn = require('ndn-on-node');
34

45

56
// ----------------------------------------------------------------
@@ -36,6 +37,21 @@ FaceMgr.prototype.get = function FaceMgr_get(id) {
3637
return this.faces[id];
3738
};
3839

40+
// public method provide_intclient
41+
FaceMgr.prototype.provide_intclient = function FaceMgr_provide_intclient(intclient) {
42+
intclient.provide_op('faces', this.intclient_faces.bind(this));
43+
};
44+
45+
// private method intclient_faces
46+
FaceMgr.prototype.intclient_faces = function FaceMgr_intclient_faces(op, interest, co, send_func) {
47+
var facelist = [];
48+
for (var id in this.faces) {
49+
var face = this.faces[id];
50+
facelist.push({ id:parseInt(id), desc:face.desc() });
51+
}
52+
send_func(new ndn.ContentObject(interest.name, JSON.stringify(facelist)));
53+
};
54+
3955

4056
// ----------------------------------------------------------------
4157
exports.FaceMgr = FaceMgr;

face/stream.js

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ var TcpListener = function TcpListener(port) {
5454
EventEmitter.call(this);
5555
this.closed = false;
5656
this.server = net.createServer(this.accept.bind(this)).listen(port);
57+
console.log('TcpListener('+port+')');
5758
};
5859
util.inherits(TcpListener, EventEmitter);
5960

face/ws.js

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ var WebSocketListener = function WebSocketListener(http_server, path) {
5151
this.closed = false;
5252
this.server = new WebSocket.Server({ server:http_server, path:path });
5353
this.server.on('connection', this.accept.bind(this));
54+
console.log('WebSocketListener('+path+')');
5455
};
5556
util.inherits(WebSocketListener, EventEmitter);
5657

index.js

+75-21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
var fs = require('fs');
12
var ndn = require('ndn-on-node');
23
var Face = require('./face').Face;
34
var StreamFace = require('./face').StreamFace;
@@ -9,14 +10,49 @@ var WebServer = require('./web').WebServer;
910
var Fib = require('./core').Fib;
1011
var Pit = require('./core').Pit;
1112
var InternalClient = require('./core').InternalClient;
12-
var Strategy = require('./strategy').Strategy;
13-
var SmartStrategy = require('./strategy').SmartStrategy;
13+
var StrategyModule = require('./strategy');
14+
15+
// ----------------------------------------------------------------
16+
// read config
17+
18+
var config = {
19+
main: {
20+
"listen_tcp": { "port": 9695 },
21+
"listen_web": { "port": 9696, "ws": "/" },
22+
"mgr_base": "http://yoursunny.com/p/NDNSF/",
23+
"strategy_type": "SmartStrategy"
24+
},
25+
faces: [],
26+
operators: []
27+
};
28+
var key;
29+
30+
if (fs.existsSync('config/main.json')) {
31+
var config_main = JSON.parse(fs.readFileSync('config/main.json'));
32+
for (var k in config_main) config.main[k] = config_main[k];
33+
}
34+
if (fs.existsSync('config/keypair.json')) {
35+
var keypair = JSON.parse(fs.readFileSync('config/keypair.json'));
36+
key = new ndn.Key();
37+
key.fromPemString(keypair.pubkey, keypair.pvtkey);
38+
} else {
39+
key = new ndn.NDN().getDefaultKey();
40+
console.log('config/keypair.json is missing, using NDN default keypair');
41+
}
42+
if (fs.existsSync('config/faces.json')) {
43+
config.faces = JSON.parse(fs.readFileSync('config/faces.json'));
44+
}
45+
if (fs.existsSync('config/operators.txt')) {
46+
config.operators = fs.readFileSync('config/operators.txt','utf8').split('\n');
47+
}
48+
49+
// ----------------------------------------------------------------
50+
// create basic components
1451

1552
var facemgr = new FaceMgr();
1653
var fib = new Fib(facemgr);
1754
var pit = new Pit();
18-
//var strategy = new Strategy(fib, pit, facemgr);
19-
var strategy = new SmartStrategy(fib, pit, facemgr);
55+
var strategy = new (StrategyModule[config.main.strategy_type])(fib, pit, facemgr);
2056

2157
function new_face(face) {
2258
face.register(facemgr);
@@ -31,27 +67,45 @@ function process_input(msg) {
3167
}
3268
}
3369

34-
//var key = new ndn.Key(); key.fromPemFile('./non.pub', './non.pem');
35-
var key = new ndn.NDN().getDefaultKey();
36-
var intclient = new InternalClient(key);
70+
var intclient = new InternalClient(key, config.operators);
3771
intclient.register(fib);
3872
intclient.on('send', process_input);
39-
fib.provide_intclient_commands(intclient);
40-
41-
var tcplisten = new TcpListener(9695);
42-
tcplisten.on('accept', new_face);
73+
fib.provide_intclient(intclient);
74+
facemgr.provide_intclient(intclient);
4375

44-
var tcpconn = StreamFace.tcp('e.hub.ndn.ucla.edu',9695);
45-
tcpconn.send(new ndn.Interest(new ndn.Name('/ndn/arizona.edu/ping/1')));
46-
new_face(tcpconn);
47-
fib.add(new ndn.Name('/'), tcpconn.id);
76+
// ----------------------------------------------------------------
77+
// create listeners, faces, and FIB entries
4878

49-
var web = new WebServer(9696);
79+
if (config.main.listen_tcp) {
80+
var tcplisten = new TcpListener(config.main.listen_tcp.port);
81+
tcplisten.on('accept', new_face);
82+
}
5083

51-
var wslisten = web.create_wslistener('/');
52-
wslisten.on('accept', new_face);
84+
if (config.main.listen_web) {
85+
var web = new WebServer(config.main.listen_web.port);
86+
intclient.provide_web(web, config.main.mgr_base);
87+
88+
if (config.main.listen_web.ws) {
89+
var wslisten = web.create_wslistener(config.main.listen_web.ws);
90+
wslisten.on('accept', new_face);
91+
}
92+
}
5393

54-
var wsconn = WebSocketFace.connect('ws://a.ws.ndn.ucla.edu:9696/');
55-
new_face(wsconn);
56-
fib.add(new ndn.Name('/'), wsconn.id);
94+
config.faces.forEach(function(config_face){
95+
var face;
96+
switch (config_face.type) {
97+
case 'tcp': {
98+
face = StreamFace.tcp(config_face.host, config_face.port);
99+
face.send(new ndn.Interest(new ndn.Name([])));//inform peer about our presence
100+
} break;
101+
case 'ws': {
102+
face = WebSocketFace.connect(config_face.address);
103+
} break;
104+
}
105+
if (!face) return;
106+
new_face(face);
107+
config_face.fib.forEach(function(config_fe){
108+
fib.add(new ndn.Name(config_fe.prefix), face.id);
109+
});
110+
});
57111

0 commit comments

Comments
 (0)