blob: 2d89f747b6ab7cd493ac52ed7f4be16959c6613a [file] [log] [blame]
Wentao Shangbd63e462012-12-03 16:19:33 -08001/**
Jeff Thompson17a9da82012-11-12 01:11:01 -08002 * @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
Jeff Thompson2b14c7e2013-07-29 15:09:56 -070012/**
13 * @constructor
14 */
Jeff Thompson3b6bf982013-01-13 20:00:03 -080015var XpcomTransport = function XpcomTransport() {
Jeff Thompson714c1c72013-04-01 22:01:44 -070016 this.elementListener = null;
Jeff Thompson3b6bf982013-01-13 20:00:03 -080017 this.socket = null; // nsISocketTransport
18 this.outStream = null;
Jeff Thompsonf668acb2013-01-26 20:29:46 -080019 this.connectedHost = null; // Read by NDN.
20 this.connectedPort = null; // Read by NDN.
Jeff Thompson3b6bf982013-01-13 20:00:03 -080021
Jeff Thompson3fa84152012-12-16 17:11:42 -080022 this.defaultGetHostAndPort = NDN.makeShuffledGetHostAndPort
23 (["A.hub.ndn.ucla.edu", "B.hub.ndn.ucla.edu", "C.hub.ndn.ucla.edu", "D.hub.ndn.ucla.edu",
24 "E.hub.ndn.ucla.edu", "F.hub.ndn.ucla.edu", "G.hub.ndn.ucla.edu", "H.hub.ndn.ucla.edu"],
25 9695);
Jeff Thompson17a9da82012-11-12 01:11:01 -080026};
27
Jeff Thompson2b14c7e2013-07-29 15:09:56 -070028/**
Jeff Thompsonf668acb2013-01-26 20:29:46 -080029 * Connect to the host and port in ndn. This replaces a previous connection and sets connectedHost
30 * and connectedPort. Once connected, call onopenCallback().
Jeff Thompson07f15fb2013-01-20 20:32:29 -080031 * Listen on the port to read an entire binary XML encoded element and call
Jeff Thompson26325842013-01-26 20:03:25 -080032 * ndn.onReceivedElement(element).
Jeff Thompson3b6bf982013-01-13 20:00:03 -080033 */
Jeff Thompsonf668acb2013-01-26 20:29:46 -080034XpcomTransport.prototype.connect = function(ndn, onopenCallback) {
Jeff Thompson714c1c72013-04-01 22:01:44 -070035 this.elementListener = ndn;
36 this.connectHelper(ndn.host, ndn.port, ndn);
37
38 onopenCallback();
39};
40
Jeff Thompson2b14c7e2013-07-29 15:09:56 -070041/**
Jeff Thompson714c1c72013-04-01 22:01:44 -070042 * Do the work to connect to host and port. This replaces a previous connection and sets connectedHost
43 * and connectedPort.
44 * Listen on the port to read an entire binary XML encoded element and call
45 * elementListener.onReceivedElement(element).
46 */
47XpcomTransport.prototype.connectHelper = function(host, port, elementListener) {
Jeff Thompson3b6bf982013-01-13 20:00:03 -080048 if (this.socket != null) {
49 try {
50 this.socket.close(0);
51 } catch (ex) {
52 console.log("XpcomTransport socket.close exception: " + ex);
53 }
54 this.socket = null;
55 }
Jeff Thompson3b6bf982013-01-13 20:00:03 -080056
57 var transportService = Components.classes["@mozilla.org/network/socket-transport-service;1"].getService
58 (Components.interfaces.nsISocketTransportService);
59 var pump = Components.classes["@mozilla.org/network/input-stream-pump;1"].createInstance
60 (Components.interfaces.nsIInputStreamPump);
Jeff Thompson714c1c72013-04-01 22:01:44 -070061 this.socket = transportService.createTransport(null, 0, host, port, null);
62 if (LOG > 0) console.log('XpcomTransport: Connected to ' + host + ":" + port);
63 this.connectedHost = host;
64 this.connectedPort = port;
Jeff Thompson3b6bf982013-01-13 20:00:03 -080065 this.outStream = this.socket.openOutputStream(1, 0, 0);
66
67 var inStream = this.socket.openInputStream(0, 0, 0);
68 var dataListener = {
Jeff Thompson714c1c72013-04-01 22:01:44 -070069 elementReader: new BinaryXmlElementReader(elementListener),
Jeff Thompson3b6bf982013-01-13 20:00:03 -080070
71 onStartRequest: function (request, context) {
72 },
73 onStopRequest: function (request, context, status) {
74 },
75 onDataAvailable: function (request, context, _inputStream, offset, count) {
76 try {
77 // Use readInputStreamToString to handle binary data.
78 // TODO: Can we go directly from the stream to Uint8Array?
Jeff Thompson24189e52013-01-20 23:29:51 -080079 this.elementReader.onReceivedData(DataUtils.toNumbersFromString
80 (NetUtil.readInputStreamToString(inStream, count)));
Jeff Thompson3b6bf982013-01-13 20:00:03 -080081 } catch (ex) {
Jeff Thompson24189e52013-01-20 23:29:51 -080082 console.log("XpcomTransport.onDataAvailable exception: " + ex + "\n" + ex.stack);
Jeff Thompson3b6bf982013-01-13 20:00:03 -080083 }
84 }
85 };
86
87 pump.init(inStream, -1, -1, 0, 0, true);
88 pump.asyncRead(dataListener, null);
89};
90
Jeff Thompson2b14c7e2013-07-29 15:09:56 -070091/**
Jeff Thompson3b6bf982013-01-13 20:00:03 -080092 * Send the data over the connection created by connect.
93 */
94XpcomTransport.prototype.send = function(/* Uint8Array */ data) {
Jeff Thompson714c1c72013-04-01 22:01:44 -070095 if (this.socket == null || this.connectedHost == null || this.connectedPort == null) {
Jeff Thompson3b6bf982013-01-13 20:00:03 -080096 console.log("XpcomTransport connection is not established.");
97 return;
98 }
Jeff Thompson17a9da82012-11-12 01:11:01 -080099
Jeff Thompson3b6bf982013-01-13 20:00:03 -0800100 var rawDataString = DataUtils.toString(data);
Jeff Thompson714c1c72013-04-01 22:01:44 -0700101 try {
102 this.outStream.write(rawDataString, rawDataString.length);
103 this.outStream.flush();
104 } catch (ex) {
105 if (this.socket.isAlive())
106 // The socket is still alive. Assume there could still be incoming data. Just throw the exception.
107 throw ex;
108
109 if (LOG > 0)
110 console.log("XpcomTransport.send: Trying to reconnect to " + this.connectedHost + ":" +
111 this.connectedPort + " and resend after exception: " + ex);
112
113 this.connectHelper(this.connectedHost, this.connectedPort, this.elementListener);
114 this.outStream.write(rawDataString, rawDataString.length);
115 this.outStream.flush();
116 }
Jeff Thompson3b6bf982013-01-13 20:00:03 -0800117};