blob: dbda8b7c48c300c2e5148f2893362b18e8f66672 [file] [log] [blame]
Wentao Shangc0311e52012-12-03 10:38:23 -08001/**
Jeff Thompson5b265a72012-11-12 01:13:08 -08002 * @author: Wentao Shang
3 * See COPYING for copyright and distribution information.
Jeff Thompson5b265a72012-11-12 01:13:08 -08004 */
5
6var WebSocketTransport = function WebSocketTransport() {
7 this.ws = null;
Jeff Thompson5b265a72012-11-12 01:13:08 -08008 this.maxBufferSize = 10000; // Currently support 10000 bytes data input, consistent with BinaryXMLEncoder
9 this.buffer = new Uint8Array(this.maxBufferSize);
Wentao Shang2b740e62012-12-07 00:02:53 -080010 this.bufferOffset = 0;
Jeff Thompson5b265a72012-11-12 01:13:08 -080011 this.structureDecoder = new BinaryXMLStructureDecoder();
Jeff Thompsonc881b552012-12-14 01:29:12 -080012 this.defaultGetHostAndPort = NDN.makeShuffledGetHostAndPort
13 (["A.ws.ndn.ucla.edu", "B.ws.ndn.ucla.edu", "C.ws.ndn.ucla.edu", "D.ws.ndn.ucla.edu",
14 "E.ws.ndn.ucla.edu"],
15 9696);
Jeff Thompson5b265a72012-11-12 01:13:08 -080016};
17
Jeff Thompson5b265a72012-11-12 01:13:08 -080018WebSocketTransport.prototype.connectWebSocket = function(ndn) {
19 if (this.ws != null)
20 delete this.ws;
21
22 this.ws = new WebSocket('ws://' + ndn.host + ':' + ndn.port);
Jeff Thompson3c263812012-12-01 17:20:28 -080023 if (LOG > 0) console.log('ws connection created.');
Jeff Thompson5b265a72012-11-12 01:13:08 -080024
25 this.ws.binaryType = "arraybuffer";
26
27 var self = this;
28 this.ws.onmessage = function(ev) {
29 var result = ev.data;
30 //console.log('RecvHandle called.');
31
32 if(result == null || result == undefined || result == "" ) {
33 console.log('INVALID ANSWER');
34 } else if (result instanceof ArrayBuffer) {
35 var bytearray = new Uint8Array(result);
36
Jeff Thompson13c2e7b2012-12-01 17:33:30 -080037 if (LOG>3) console.log('BINARY RESPONSE IS ' + DataUtils.toHex(bytearray));
Jeff Thompson5b265a72012-11-12 01:13:08 -080038
39 try {
Wentao Shang2b740e62012-12-07 00:02:53 -080040 if (bytearray.length + self.bufferOffset >= self.buffer.byteLength) {
41 if (LOG>3) {
42 console.log("NDN.ws.onmessage: buffer overflow. Accumulate received length: " + self.bufferOffset
43 + ". Current packet length: " + bytearray.length + ".");
44 }
45
Jeff Thompson5b265a72012-11-12 01:13:08 -080046 // Purge and quit.
47 delete self.structureDecoder;
48 delete self.buffer;
49 self.structureDecoder = new BinaryXMLStructureDecoder();
50 self.buffer = new Uint8Array(self.maxBufferSize);
Wentao Shang2b740e62012-12-07 00:02:53 -080051 self.bufferOffset = 0;
Jeff Thompson5b265a72012-11-12 01:13:08 -080052 return;
53 }
54
55 /*for (var i = 0; i < bytearray.length; i++) {
56 self.buffer.push(bytearray[i]);
57 }*/
Wentao Shang2b740e62012-12-07 00:02:53 -080058 self.buffer.set(bytearray, self.bufferOffset);
59 self.bufferOffset += bytearray.length;
Jeff Thompson5b265a72012-11-12 01:13:08 -080060
Wentao Shang2b740e62012-12-07 00:02:53 -080061 if (!self.structureDecoder.findElementEnd(self.buffer.subarray(0, self.bufferOffset))) {
Jeff Thompson5b265a72012-11-12 01:13:08 -080062 // Need more data to decode
Wentao Shang2b740e62012-12-07 00:02:53 -080063 if (LOG>3) console.log('Incomplete packet received. Length ' + bytearray.length + '. Wait for more input.');
Jeff Thompson5b265a72012-11-12 01:13:08 -080064 return;
65 }
Wentao Shang2b740e62012-12-07 00:02:53 -080066 if (LOG>3) console.log('Complete packet received. Length ' + bytearray.length + '. Start decoding.');
Jeff Thompson5b265a72012-11-12 01:13:08 -080067 } catch (ex) {
68 console.log("NDN.ws.onmessage exception: " + ex);
69 return;
70 }
71
Jeff Thompson75771cb2013-01-20 23:27:38 -080072 ndn.onReceivedElement(self.buffer);
73
Jeff Thompson5b265a72012-11-12 01:13:08 -080074 // Renew StrcutureDecoder and buffer after we process a full packet
75 delete self.structureDecoder;
76 delete self.buffer;
77 self.structureDecoder = new BinaryXMLStructureDecoder();
78 self.buffer = new Uint8Array(self.maxBufferSize);
Wentao Shang2b740e62012-12-07 00:02:53 -080079 self.bufferOffset = 0;
Jeff Thompson5b265a72012-11-12 01:13:08 -080080 }
81 }
82
83 this.ws.onopen = function(ev) {
Jeff Thompson3c263812012-12-01 17:20:28 -080084 if (LOG > 3) console.log(ev);
85 if (LOG > 3) console.log('ws.onopen: WebSocket connection opened.');
86 if (LOG > 3) console.log('ws.onopen: ReadyState: ' + this.readyState);
Jeff Thompson5b265a72012-11-12 01:13:08 -080087
88 // Fetch ccndid now
Wentao Shange0d7f052013-01-05 16:37:02 -080089 var interest = new Interest(NDN.ccndIdFetcher);
Jeff Thompson42806a12012-12-29 18:19:39 -080090 interest.interestLifetime = 4000; // milliseconds
Jeff Thompson75771cb2013-01-20 23:27:38 -080091 this.send(encodeToBinaryInterest(interest));
Jeff Thompson5b265a72012-11-12 01:13:08 -080092 }
93
94 this.ws.onerror = function(ev) {
95 console.log('ws.onerror: ReadyState: ' + this.readyState);
96 console.log(ev);
97 console.log('ws.onerror: WebSocket error: ' + ev.data);
98 }
99
100 this.ws.onclose = function(ev) {
101 console.log('ws.onclose: WebSocket connection closed.');
102 self.ws = null;
Wentao Shang0e291c82012-12-02 23:36:29 -0800103
104 // Close NDN when WebSocket is closed
105 ndn.readyStatus = NDN.CLOSED;
106 ndn.onclose();
Wentao Shangaf25c6b2012-12-03 00:09:30 -0800107 //console.log("NDN.onclose event fired.");
Jeff Thompson5b265a72012-11-12 01:13:08 -0800108 }
Jeff Thompsonbe85be62012-12-13 22:32:01 -0800109};
Jeff Thompson5b265a72012-11-12 01:13:08 -0800110
Jeff Thompson75771cb2013-01-20 23:27:38 -0800111/*
112 * Send the Uint8Array data.
113 */
114WebSocketTransport.prototype.send = function(data) {
Wentao Shangc0311e52012-12-03 10:38:23 -0800115 if (this.ws != null) {
Jeff Thompson75771cb2013-01-20 23:27:38 -0800116 // If we directly use data.buffer to feed ws.send(),
117 // WebSocket may end up sending a packet with 10000 bytes of data.
118 // That is, WebSocket will flush the entire buffer
119 // regardless of the offset of the Uint8Array. So we have to create
120 // a new Uint8Array buffer with just the right size and copy the
121 // content from binaryInterest to the new buffer.
122 // ---Wentao
123 var bytearray = new Uint8Array(data.length);
124 bytearray.set(data);
125 this.ws.send(bytearray.buffer);
Wentao Shangc0311e52012-12-03 10:38:23 -0800126 if (LOG > 3) console.log('ws.send() returned.');
Wentao Shangc0311e52012-12-03 10:38:23 -0800127 }
128 else
129 console.log('WebSocket connection is not established.');
Jeff Thompson5b265a72012-11-12 01:13:08 -0800130}
131
Jeff Thompson75771cb2013-01-20 23:27:38 -0800132WebSocketTransport.prototype.expressInterest = function(ndn, interest, closure) {
133 if (ndn.readyStatus != NDN.OPENED) {
134 console.log('Connection is not established.');
135 return;
136 }
137
138 //TODO: check local content store first
139 if (closure != null) {
140 var pitEntry = new PITEntry(interest, closure);
141 // TODO: This needs to be a single thread-safe transaction on a global object.
142 NDN.PITTable.push(pitEntry);
143 closure.pitEntry = pitEntry;
Jeff Thompson5b265a72012-11-12 01:13:08 -0800144 }
Jeff Thompson75771cb2013-01-20 23:27:38 -0800145
146 // Set interest timer
147 if (closure != null) {
148 pitEntry.timerID = setTimeout(function() {
149 if (LOG > 3) console.log("Interest time out.");
150
151 // Remove PIT entry from NDN.PITTable.
152 // TODO: Make this a thread-safe operation on the global PITTable.
153 var index = NDN.PITTable.indexOf(pitEntry);
154 //console.log(NDN.PITTable);
155 if (index >= 0)
156 NDN.PITTable.splice(index, 1);
157 //console.log(NDN.PITTable);
158 //console.log(pitEntry.interest.name.getName());
159
160 // Raise closure callback
161 closure.upcall(Closure.UPCALL_INTEREST_TIMED_OUT, new UpcallInfo(ndn, interest, 0, null));
162 }, interest.interestLifetime); // interestLifetime is in milliseconds.
163 //console.log(closure.timerID);
164 }
165
166 this.send(encodeToBinaryInterest(interest));
Jeff Thompsonbe85be62012-12-13 22:32:01 -0800167};
Jeff Thompson5b265a72012-11-12 01:13:08 -0800168