Wentao Shang | bd63e46 | 2012-12-03 16:19:33 -0800 | [diff] [blame] | 1 | /** |
Jeff Thompson | 17a9da8 | 2012-11-12 01:11:01 -0800 | [diff] [blame] | 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 | |
Jeff Thompson | 3b6bf98 | 2013-01-13 20:00:03 -0800 | [diff] [blame] | 12 | var XpcomTransport = function XpcomTransport() { |
Jeff Thompson | 714c1c7 | 2013-04-01 22:01:44 -0700 | [diff] [blame^] | 13 | this.elementListener = null; |
Jeff Thompson | 3b6bf98 | 2013-01-13 20:00:03 -0800 | [diff] [blame] | 14 | this.socket = null; // nsISocketTransport |
| 15 | this.outStream = null; |
Jeff Thompson | f668acb | 2013-01-26 20:29:46 -0800 | [diff] [blame] | 16 | this.connectedHost = null; // Read by NDN. |
| 17 | this.connectedPort = null; // Read by NDN. |
Jeff Thompson | 3b6bf98 | 2013-01-13 20:00:03 -0800 | [diff] [blame] | 18 | |
Jeff Thompson | 3fa8415 | 2012-12-16 17:11:42 -0800 | [diff] [blame] | 19 | 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 Thompson | 17a9da8 | 2012-11-12 01:11:01 -0800 | [diff] [blame] | 23 | }; |
| 24 | |
Jeff Thompson | 3b6bf98 | 2013-01-13 20:00:03 -0800 | [diff] [blame] | 25 | /* |
Jeff Thompson | f668acb | 2013-01-26 20:29:46 -0800 | [diff] [blame] | 26 | * Connect to the host and port in ndn. This replaces a previous connection and sets connectedHost |
| 27 | * and connectedPort. Once connected, call onopenCallback(). |
Jeff Thompson | 07f15fb | 2013-01-20 20:32:29 -0800 | [diff] [blame] | 28 | * Listen on the port to read an entire binary XML encoded element and call |
Jeff Thompson | 2632584 | 2013-01-26 20:03:25 -0800 | [diff] [blame] | 29 | * ndn.onReceivedElement(element). |
Jeff Thompson | 3b6bf98 | 2013-01-13 20:00:03 -0800 | [diff] [blame] | 30 | */ |
Jeff Thompson | f668acb | 2013-01-26 20:29:46 -0800 | [diff] [blame] | 31 | XpcomTransport.prototype.connect = function(ndn, onopenCallback) { |
Jeff Thompson | 714c1c7 | 2013-04-01 22:01:44 -0700 | [diff] [blame^] | 32 | 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 | */ |
| 44 | XpcomTransport.prototype.connectHelper = function(host, port, elementListener) { |
Jeff Thompson | 3b6bf98 | 2013-01-13 20:00:03 -0800 | [diff] [blame] | 45 | 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 Thompson | 3b6bf98 | 2013-01-13 20:00:03 -0800 | [diff] [blame] | 53 | |
| 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 Thompson | 714c1c7 | 2013-04-01 22:01:44 -0700 | [diff] [blame^] | 58 | 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 Thompson | 3b6bf98 | 2013-01-13 20:00:03 -0800 | [diff] [blame] | 62 | this.outStream = this.socket.openOutputStream(1, 0, 0); |
| 63 | |
| 64 | var inStream = this.socket.openInputStream(0, 0, 0); |
| 65 | var dataListener = { |
Jeff Thompson | 714c1c7 | 2013-04-01 22:01:44 -0700 | [diff] [blame^] | 66 | elementReader: new BinaryXmlElementReader(elementListener), |
Jeff Thompson | 3b6bf98 | 2013-01-13 20:00:03 -0800 | [diff] [blame] | 67 | |
| 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 Thompson | 24189e5 | 2013-01-20 23:29:51 -0800 | [diff] [blame] | 76 | this.elementReader.onReceivedData(DataUtils.toNumbersFromString |
| 77 | (NetUtil.readInputStreamToString(inStream, count))); |
Jeff Thompson | 3b6bf98 | 2013-01-13 20:00:03 -0800 | [diff] [blame] | 78 | } catch (ex) { |
Jeff Thompson | 24189e5 | 2013-01-20 23:29:51 -0800 | [diff] [blame] | 79 | console.log("XpcomTransport.onDataAvailable exception: " + ex + "\n" + ex.stack); |
Jeff Thompson | 3b6bf98 | 2013-01-13 20:00:03 -0800 | [diff] [blame] | 80 | } |
| 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 | */ |
| 91 | XpcomTransport.prototype.send = function(/* Uint8Array */ data) { |
Jeff Thompson | 714c1c7 | 2013-04-01 22:01:44 -0700 | [diff] [blame^] | 92 | if (this.socket == null || this.connectedHost == null || this.connectedPort == null) { |
Jeff Thompson | 3b6bf98 | 2013-01-13 20:00:03 -0800 | [diff] [blame] | 93 | console.log("XpcomTransport connection is not established."); |
| 94 | return; |
| 95 | } |
Jeff Thompson | 17a9da8 | 2012-11-12 01:11:01 -0800 | [diff] [blame] | 96 | |
Jeff Thompson | 3b6bf98 | 2013-01-13 20:00:03 -0800 | [diff] [blame] | 97 | var rawDataString = DataUtils.toString(data); |
Jeff Thompson | 714c1c7 | 2013-04-01 22:01:44 -0700 | [diff] [blame^] | 98 | 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 Thompson | 3b6bf98 | 2013-01-13 20:00:03 -0800 | [diff] [blame] | 114 | }; |