blob: 973ed77dd3c36639989d0b47b8612efb4bb76618 [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 Thompson3b6bf982013-01-13 20:00:03 -080012var XpcomTransport = function XpcomTransport() {
Jeff Thompson714c1c72013-04-01 22:01:44 -070013 this.elementListener = null;
Jeff Thompson3b6bf982013-01-13 20:00:03 -080014 this.socket = null; // nsISocketTransport
15 this.outStream = null;
Jeff Thompsonf668acb2013-01-26 20:29:46 -080016 this.connectedHost = null; // Read by NDN.
17 this.connectedPort = null; // Read by NDN.
Jeff Thompson3b6bf982013-01-13 20:00:03 -080018
Jeff Thompson3fa84152012-12-16 17:11:42 -080019 this.defaultGetHostAndPort = NDN.makeShuffledGetHostAndPort
20 (["A.hub.ndn.ucla.edu", "B.hub.ndn.ucla.edu", "C.hub.ndn.ucla.edu", "D.hub.ndn.ucla.edu",
21 "E.hub.ndn.ucla.edu", "F.hub.ndn.ucla.edu", "G.hub.ndn.ucla.edu", "H.hub.ndn.ucla.edu"],
22 9695);
Jeff Thompson17a9da82012-11-12 01:11:01 -080023};
24
Jeff Thompson3b6bf982013-01-13 20:00:03 -080025/*
Jeff Thompsonf668acb2013-01-26 20:29:46 -080026 * Connect to the host and port in ndn. This replaces a previous connection and sets connectedHost
27 * and connectedPort. Once connected, call onopenCallback().
Jeff Thompson07f15fb2013-01-20 20:32:29 -080028 * Listen on the port to read an entire binary XML encoded element and call
Jeff Thompson26325842013-01-26 20:03:25 -080029 * ndn.onReceivedElement(element).
Jeff Thompson3b6bf982013-01-13 20:00:03 -080030 */
Jeff Thompsonf668acb2013-01-26 20:29:46 -080031XpcomTransport.prototype.connect = function(ndn, onopenCallback) {
Jeff Thompson714c1c72013-04-01 22:01:44 -070032 this.elementListener = ndn;
33 this.connectHelper(ndn.host, ndn.port, ndn);
34
35 onopenCallback();
36};
37
38/*
39 * Do the work to connect to host and port. This replaces a previous connection and sets connectedHost
40 * and connectedPort.
41 * Listen on the port to read an entire binary XML encoded element and call
42 * elementListener.onReceivedElement(element).
43 */
44XpcomTransport.prototype.connectHelper = function(host, port, elementListener) {
Jeff Thompson3b6bf982013-01-13 20:00:03 -080045 if (this.socket != null) {
46 try {
47 this.socket.close(0);
48 } catch (ex) {
49 console.log("XpcomTransport socket.close exception: " + ex);
50 }
51 this.socket = null;
52 }
Jeff Thompson3b6bf982013-01-13 20:00:03 -080053
54 var transportService = Components.classes["@mozilla.org/network/socket-transport-service;1"].getService
55 (Components.interfaces.nsISocketTransportService);
56 var pump = Components.classes["@mozilla.org/network/input-stream-pump;1"].createInstance
57 (Components.interfaces.nsIInputStreamPump);
Jeff Thompson714c1c72013-04-01 22:01:44 -070058 this.socket = transportService.createTransport(null, 0, host, port, null);
59 if (LOG > 0) console.log('XpcomTransport: Connected to ' + host + ":" + port);
60 this.connectedHost = host;
61 this.connectedPort = port;
Jeff Thompson3b6bf982013-01-13 20:00:03 -080062 this.outStream = this.socket.openOutputStream(1, 0, 0);
63
64 var inStream = this.socket.openInputStream(0, 0, 0);
65 var dataListener = {
Jeff Thompson714c1c72013-04-01 22:01:44 -070066 elementReader: new BinaryXmlElementReader(elementListener),
Jeff Thompson3b6bf982013-01-13 20:00:03 -080067
68 onStartRequest: function (request, context) {
69 },
70 onStopRequest: function (request, context, status) {
71 },
72 onDataAvailable: function (request, context, _inputStream, offset, count) {
73 try {
74 // Use readInputStreamToString to handle binary data.
75 // TODO: Can we go directly from the stream to Uint8Array?
Jeff Thompson24189e52013-01-20 23:29:51 -080076 this.elementReader.onReceivedData(DataUtils.toNumbersFromString
77 (NetUtil.readInputStreamToString(inStream, count)));
Jeff Thompson3b6bf982013-01-13 20:00:03 -080078 } catch (ex) {
Jeff Thompson24189e52013-01-20 23:29:51 -080079 console.log("XpcomTransport.onDataAvailable exception: " + ex + "\n" + ex.stack);
Jeff Thompson3b6bf982013-01-13 20:00:03 -080080 }
81 }
82 };
83
84 pump.init(inStream, -1, -1, 0, 0, true);
85 pump.asyncRead(dataListener, null);
86};
87
88/*
89 * Send the data over the connection created by connect.
90 */
91XpcomTransport.prototype.send = function(/* Uint8Array */ data) {
Jeff Thompson714c1c72013-04-01 22:01:44 -070092 if (this.socket == null || this.connectedHost == null || this.connectedPort == null) {
Jeff Thompson3b6bf982013-01-13 20:00:03 -080093 console.log("XpcomTransport connection is not established.");
94 return;
95 }
Jeff Thompson17a9da82012-11-12 01:11:01 -080096
Jeff Thompson3b6bf982013-01-13 20:00:03 -080097 var rawDataString = DataUtils.toString(data);
Jeff Thompson714c1c72013-04-01 22:01:44 -070098 try {
99 this.outStream.write(rawDataString, rawDataString.length);
100 this.outStream.flush();
101 } catch (ex) {
102 if (this.socket.isAlive())
103 // The socket is still alive. Assume there could still be incoming data. Just throw the exception.
104 throw ex;
105
106 if (LOG > 0)
107 console.log("XpcomTransport.send: Trying to reconnect to " + this.connectedHost + ":" +
108 this.connectedPort + " and resend after exception: " + ex);
109
110 this.connectHelper(this.connectedHost, this.connectedPort, this.elementListener);
111 this.outStream.write(rawDataString, rawDataString.length);
112 this.outStream.flush();
113 }
Jeff Thompson3b6bf982013-01-13 20:00:03 -0800114};