blob: c0178487b0a16533ca4fc360b600a446baa69e1b [file] [log] [blame]
Jeff Thompson17a9da82012-11-12 01:11:01 -08001/*
2 * @author: Jeff Thompson
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
8// Assume already imported the following:
9// Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
10// Components.utils.import("resource://gre/modules/NetUtil.jsm");
11
12var XpcomTransport = function XpcomTransport() {
13};
14
15XpcomTransport.prototype.expressInterest = function(ndn, interest, closure) {
16 var binaryInterest = encodeToBinaryInterest(interest);
17
18 var dataListener = {
19 onReceivedData : function(data) {
20 if (data == null || data == undefined || data.length == 0)
21 dump("NDN.expressInterest: received empty data from socket.\n");
22 else {
23 var decoder = new BinaryXMLDecoder(data);
24 var co = new ContentObject();
25 co.from_ccnb(decoder);
26
Jeff Thompson17a9da82012-11-12 01:11:01 -080027 // TODO: verify the content object and set kind to UPCALL_CONTENT.
28 var result = closure.upcall(Closure.UPCALL_CONTENT_UNVERIFIED,
29 new UpcallInfo(ndn, interest, 0, co));
30 if (result == Closure.RESULT_OK) {
31 // success
32 }
33 else if (result == Closure.RESULT_ERR)
34 dump("NDN.expressInterest: upcall returned RESULT_ERR.\n");
35 else if (result == Closure.RESULT_REEXPRESS)
36 XpcomTransport.readAllFromSocket(ndn.host, ndn.port, binaryInterest, dataListener);
37 else if (result == Closure.RESULT_VERIFY) {
38 // TODO: force verification of content.
39 }
40 else if (result == Closure.RESULT_FETCHKEY) {
41 // TODO: get the key in the key locator and re-call the interest
42 // with the key available in the local storage.
43 }
44 }
45 }
46 }
47
48 XpcomTransport.readAllFromSocket(ndn.host, ndn.port, binaryInterest, dataListener);
49};
50
51/** Send outputData (Uint8Array) to host:port, read the entire response and call
52 * listener.onReceivedData(data) where data is Uint8Array.
53 * Code derived from http://stackoverflow.com/questions/7816386/why-nsiscriptableinputstream-is-not-working .
54 */
55XpcomTransport.readAllFromSocket = function(host, port, outputData, listener) {
56 var transportService = Components.classes["@mozilla.org/network/socket-transport-service;1"].getService
57 (Components.interfaces.nsISocketTransportService);
58 var pump = Components.classes["@mozilla.org/network/input-stream-pump;1"].createInstance
59 (Components.interfaces.nsIInputStreamPump);
60 var transport = transportService.createTransport(null, 0, host, port, null);
61 var outStream = transport.openOutputStream(1, 0, 0);
62 var rawDataString = DataUtils.toString(outputData);
63 outStream.write(rawDataString, rawDataString.length);
64 outStream.flush();
65 var inStream = transport.openInputStream(0, 0, 0);
66 var dataListener = {
Jeff Thompsonfab4a7d2012-11-28 21:24:26 -080067 dataParts: [],
Jeff Thompson17a9da82012-11-12 01:11:01 -080068 structureDecoder: new BinaryXMLStructureDecoder(),
69 calledOnReceivedData: false,
70
71 onStartRequest: function (request, context) {
72 },
73 onStopRequest: function (request, context, status) {
74 inStream.close();
75 outStream.close();
76 if (!this.calledOnReceivedData) {
77 this.calledOnReceivedData = true;
Jeff Thompsonfab4a7d2012-11-28 21:24:26 -080078 listener.onReceivedData(DataUtils.concatArrays(this.dataParts));
Jeff Thompson17a9da82012-11-12 01:11:01 -080079 }
80 },
81 onDataAvailable: function (request, context, _inputStream, offset, count) {
82 if (this.calledOnReceivedData)
83 // Already finished. Ignore extra data.
84 return;
85
86 try {
87 // Ignore _inputStream and use inStream.
88 // Use readInputStreamToString to handle binary data.
Jeff Thompsonfab4a7d2012-11-28 21:24:26 -080089 // TODO: Can we go directly from the stream to Uint8Array?
90 var rawData = DataUtils.toNumbersFromString
91 (NetUtil.readInputStreamToString(inStream, count));
92 // Save for later call to concatArrays so that we only reallocate a buffer once.
93 this.dataParts.push(rawData);
Jeff Thompson17a9da82012-11-12 01:11:01 -080094
95 // Scan the input to check if a whole ccnb object has been read.
Jeff Thompsonfab4a7d2012-11-28 21:24:26 -080096 this.structureDecoder.seek(0);
97 if (this.structureDecoder.findElementEnd(rawData))
Jeff Thompson17a9da82012-11-12 01:11:01 -080098 // Finish.
99 this.onStopRequest();
100 } catch (ex) {
101 dump("readAllFromSocket.onDataAvailable exception: " + ex + "\n");
102 }
103 }
104 };
105
106 pump.init(inStream, -1, -1, 0, 0, true);
107 pump.asyncRead(dataListener, null);
108}
109