blob: 49c09a47425a31d4765713e0446947021290d5f9 [file] [log] [blame]
Jeff Thompson5b265a72012-11-12 01:13:08 -08001/*
2 * @author: Wentao Shang
3 * See COPYING for copyright and distribution information.
4 * Implement getAsync and putAsync used by NDN using nsISocketTransportService.
5 * This is used inside Firefox XPCOM modules.
6 */
7
8var WebSocketTransport = function WebSocketTransport() {
9 this.ws = null;
10 this.ccndid = null;
11 this.maxBufferSize = 10000; // Currently support 10000 bytes data input, consistent with BinaryXMLEncoder
12 this.buffer = new Uint8Array(this.maxBufferSize);
13 this.structureDecoder = new BinaryXMLStructureDecoder();
14};
15
16WebSocketTransport.prototype.expressInterest = function(ndn, interest, closure) {
17 if (this.ws != null) {
18 //TODO: check local content store first
19
20 var binaryInterest = encodeToBinaryInterest(interest);
21 var bytearray = new Uint8Array(binaryInterest.length);
22 bytearray.set(binaryInterest);
23
24 var pitEntry = new PITEntry(interest.name.getName(), closure);
25 PITTable.push(pitEntry);
26
27 this.ws.send(bytearray.buffer);
28 console.log('ws.send() returned.');
29 }
30 else{
31 console.log('WebSocket connection is not established.');
32 return null;
33 }
34};
35
36
37var ccndIdFetcher = '/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY';
38
39WebSocketTransport.prototype.connectWebSocket = function(ndn) {
40 if (this.ws != null)
41 delete this.ws;
42
43 this.ws = new WebSocket('ws://' + ndn.host + ':' + ndn.port);
44 console.log('ws connection created.');
45
46 this.ws.binaryType = "arraybuffer";
47
48 var self = this;
49 this.ws.onmessage = function(ev) {
50 var result = ev.data;
51 //console.log('RecvHandle called.');
52
53 if(result == null || result == undefined || result == "" ) {
54 console.log('INVALID ANSWER');
55 } else if (result instanceof ArrayBuffer) {
56 var bytearray = new Uint8Array(result);
57
58 if (LOG>3) console.log('BINARY RESPONSE IS ' + bytearray);
59
60 try {
61 if (bytearray.length + self.buffer.byteOffset >= self.buffer.byteLength) {
62 console.log("NDN.ws.onmessage: buffer overflow. Accumulate received length: " + self.buffer.byteOffset
63 + ". Current packet length: " + bytearray.length + ".");
64 // Purge and quit.
65 delete self.structureDecoder;
66 delete self.buffer;
67 self.structureDecoder = new BinaryXMLStructureDecoder();
68 self.buffer = new Uint8Array(self.maxBufferSize);
69 return;
70 }
71
72 /*for (var i = 0; i < bytearray.length; i++) {
73 self.buffer.push(bytearray[i]);
74 }*/
75 self.buffer.set(bytearray, self.buffer.byteOffset);
76
77 if (!self.structureDecoder.findElementEnd(self.buffer)) {
78 // Need more data to decode
79 console.log('Incomplete packet received. Length ' + bytearray.length + '. Wait for more input.');
80 console.log('self.buffer length: ' + self.buffer.length);
81 return;
82 }
83 } catch (ex) {
84 console.log("NDN.ws.onmessage exception: " + ex);
85 return;
86 }
87
88 var decoder = new BinaryXMLDecoder(self.buffer);
89 // Dispatch according to packet type
90 if (decoder.peekStartElement(CCNProtocolDTags.Interest)) { // Interest packet
91 console.log('Interest packet received.');
92
93 var interest = new Interest();
94 interest.from_ccnb(decoder);
95 if (LOG>3) console.log(interest);
96 var nameStr = escape(interest.name.getName());
97 console.log(nameStr);
98
99 var entry = getEntryForRegisteredPrefix(nameStr);
100 if (entry != null) {
101 //console.log(entry);
102 entry.closure.upcall(Closure.UPCALL_INTEREST, new UpcallInfo(ndn, interest, 0, null));
103 }
104
105 } else if (decoder.peekStartElement(CCNProtocolDTags.ContentObject)) { // Content packet
106 console.log('ContentObject packet received.');
107
108 var co = new ContentObject();
109 co.from_ccnb(decoder);
110 if (LOG>3) console.log(co);
111 nameStr = co.name.getName();
112 console.log(nameStr);
113
114 if (self.ccndid == null && nameStr.match(ccndIdFetcher) != null) {
115 // We are in starting phase, record publisherPublicKeyDigest in self.ccndid
116 if(!co.signedInfo || !co.signedInfo.publisher
117 || !co.signedInfo.publisher.publisherPublicKeyDigest) {
118 console.log("Cannot contact router");
119 } else {
120 console.log('Connected to ccnd.');
121 self.ccndid = co.signedInfo.publisher.publisherPublicKeyDigest;
122 if (LOG>3) console.log(self.ccndid);
123 }
124 } else {
125 var pitEntry = getEntryForExpressedInterest(nameStr);
126 if (pitEntry != null) {
127 //console.log(pitEntry);
128 pitEntry.closure.upcall(Closure.UPCALL_CONTENT, new UpcallInfo(ndn, null, 0, co));
129 }
130 }
131 } else {
132 console.log('Incoming packet is not Interest or ContentObject. Discard now.');
133 }
134
135 delete decoder;
136
137 // Renew StrcutureDecoder and buffer after we process a full packet
138 delete self.structureDecoder;
139 delete self.buffer;
140 self.structureDecoder = new BinaryXMLStructureDecoder();
141 self.buffer = new Uint8Array(self.maxBufferSize);
142 }
143 }
144
145 this.ws.onopen = function(ev) {
146 console.log(ev);
147 console.log('ws.onopen: WebSocket connection opened.');
148 console.log('ws.onopen: ReadyState: ' + this.readyState);
149
150 // Fetch ccndid now
151 interest = new Interest(new Name(ccndIdFetcher));
152 interest.InterestLifetime = 4200;
153 //var hex = encodeToHexInterest(interest);
154 var hex = encodeToBinaryInterest(interest);
155
156 /*var bytes = new Uint8Array(hex.length / 2);
157 for (var i = 0; i < hex.length; i = i + 2) {
158 bytes[i / 2] = '0x' + hex.substr(i, 2);
159 }*/
160 var bytes = new Uint8Array(hex.length);
161 bytes.set(hex);
162
163 self.ws.send(bytes.buffer);
164 console.log('ws.onopen: ws.send() returned.');
165 }
166
167 this.ws.onerror = function(ev) {
168 console.log('ws.onerror: ReadyState: ' + this.readyState);
169 console.log(ev);
170 console.log('ws.onerror: WebSocket error: ' + ev.data);
171 }
172
173 this.ws.onclose = function(ev) {
174 console.log('ws.onclose: WebSocket connection closed.');
175 self.ws = null;
176 }
177}
178
179
180// For fetching data
181var PITTable = new Array();
182
183var PITEntry = function PITEntry(interest, closure) {
184 this.interest = interest; // String
185 this.closure = closure; // Closure
186}
187
188function getEntryForExpressedInterest(name) {
189 for (var i = 0; i < PITTable.length; i++) {
190 if (name.match(PITTable[i].interest) != null)
191 return PITTable[i];
192 // TODO: handle multiple matching prefixes
193 }
194 return null;
195}
196
197
198// For publishing data
199var CSTable = new Array();
200
201var CSEntry = function CSEntry(name, closure) {
202 this.name = name; // String
203 this.closure = closure; // Closure
204}
205
206function getEntryForRegisteredPrefix(name) {
207 for (var i = 0; i < CSTable.length; i++) {
208 if (CSTable[i].name.match(name) != null)
209 return CSTable[i];
210 }
211 return null;
212}
213
214WebSocketTransport.prototype.registerPrefix = function(ndn, name, closure, flag) {
215 if (this.ws != null) {
216 if (this.ccndid == null) {
217 console.log('ccnd node ID unkonwn. Cannot register prefix.');
218 return;
219 }
220
Jeff Thompson48ba4ff2012-11-12 01:23:13 -0800221 var fe = new ForwardingEntry('selfreg', name, null, null, 3, 2147483647);
Jeff Thompson5b265a72012-11-12 01:13:08 -0800222 var bytes = encodeForwardingEntry(fe);
223
224 var si = new SignedInfo();
225 si.setFields();
226
227 var co = new ContentObject(new Name(), si, bytes, new Signature());
228 co.sign();
229 var coBinary = encodeToBinaryContentObject(co);
230
231 //var ccnxnodename = 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');
232 var ccnxnodename = this.ccndid;
233 var interestName = new Name(['ccnx', ccnxnodename, 'selfreg', coBinary]);
234
235 var interest = new Interest(interestName);
236 interest.scope = 1;
237 //var hex = encodeToHexInterest(int);
238 var binaryInterest = encodeToBinaryInterest(interest);
239 var bytearray = new Uint8Array(binaryInterest.length);
240 bytearray.set(binaryInterest);
241 console.log('Send Interest registration packet.');
242
Jeff Thompson48ba4ff2012-11-12 01:23:13 -0800243 var csEntry = new CSEntry(name.getName(), closure);
Jeff Thompson5b265a72012-11-12 01:13:08 -0800244 CSTable.push(csEntry);
245
246 this.ws.send(bytearray.buffer);
247 console.log('ws.send() returned.');
248
249 return 0;
250 } else {
251 console.log('WebSocket connection is not established.');
252 return -1;
253 }
254}
255