UNPKG

thali

Version:
891 lines (330 loc) 25.2 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Home</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Home</h1> <h3> </h3> <section> <header> <h2> <span class="ancestors"><a href="module-TCPServersManager.html">TCPServersManager</a>~</span>NextGeneration/TCPServersManager.js</h2> </header> <article> <div class="container-overview"> <div class="description"><p>This is where we manage creating multiplex objects. For all intents and purposes this file should be treated as part of <a href="module-thaliMobileNative.html">module:thaliMobileNative</a>. We have broken this functionality out here in order to make the code more maintainable and easier to follow.</p> <p>When dealing with incoming connections this code creates a multiplex object to handle de-multiplexing the incoming connections and in the iOS case to also send TCP/IP connections down the incoming connection (reverse the polarity as it were).</p> <p>When dealing with discovered peers we like to advertise a port that the Thali Application can connect to in order to talk to that peer. But for perf reasons that port is typically not connected to anything at the native layer (with the exception of a lexically smaller peer) until someone connects to the port. The reason for this design (thanks Ville!) is to make non-TCP and TCP peers look the same. There is an address (in this case 127.0.0.1) and a port and you connect and there you go. This file defines all the magic needed to create the illusion that a non-TCP peer is actually available over TCP.</p> <p>There are three different scenarios where multiplex objects can get created:</p> <p>Android</p> <ul> <li>We get an incoming connection from the native layer to the portNumber we submitted to startUpdateAdvertisingAndListening<ul> <li>We create a mux that pipes to the incoming TCP/IP connection.</li> </ul> </li> <li>We get a peerAvailabilityChanged Event<ul> <li>We create a local listener and advertise nonTCPPeerAvailabilityChanged. When we get a connection to that listener then we call native connect, create a connection to the native connect port, hook the mux to that connection on one end and the incoming listener to the mux on the other end.</li> </ul> </li> </ul> <p>iOS - Lexically Smaller Peer</p> <ul> <li>We get an incoming connection from the native layer to the portNumber we submitted to startUpdateAdvertisingAndListening<ul> <li>We create a mux that pipes to the incoming TCP/IP connection. We keep track of this mux because we might need it in the next entry. Remember, we don't know which peer made the incoming connection.</li> </ul> </li> <li>We get a peerAvailabilityChanged Event<ul> <li>Because we are lexically smaller this event will have pleaseConnect set to false. So we create a port and advertise it on nonTCPPeerAvailabilityChanged. When we get a connection we call connect. If there is already an incoming connection then the connect will return with the clientPort/serverPort and we will re-use the existing mux If there is no existing incoming connection then the system will wait to trigger the lexically larger peer to create it and once it is created and properly terminated (per the previous section) then we will find the mux via clientPort/ServerPort.</li> </ul> </li> </ul> <p>iOS - Lexically Larger Peer</p> <ul> <li>We get an incoming connection from the native layer to the portNumber we submitted to startUpdateAdvertisingAndListening<ul> <li>It isn't possible.</li> </ul> </li> <li><p>We get a peerAvailabilityChanged Event</p> <ul> <li>If the peerAvailabilityChanged Event has pleaseConnect set to true then baring any limitation on available resources we should immediately issue a connect and hook in the mux to it configured to handling incoming connections and then create a TCP listener and have it use createStream with the mux for any incoming connections. Obviously if we already have a connection to the identified peer then we can ignore the pleaseConnect value.</li> <li>If the peerAvailabilityChanged Event has pleaseConnect set to false then we will set up a TCP listener and advertise the port but we won't create the mux or call connect until the first connection to the TCP listener comes in.</li> </ul> <p>We have two basic kinds of listeners. One type is for incoming connections from remote peers. In that case we will have a TCP connection from the native layer connecting to us which we will then connect to a multiplex object. The other listener is for connections from a Thali App to a remote peer. In that case we will create a TCP connection to a native listener and hook our TCP connection into a multiplex object. And of course with the iOS situation sometimes it all gets mixed up.</p> <p>But the point is that each listener has at its root a TCP connection either going out to or coming in from the native layer. Because keeping native connections open eats battery (although this is probably a much less significant issue with iOS due to its UDP based design) we don't want to let connections hang open unused. This is why we put a timeout on the TCP connection under the multiplex. That connection sees all traffic in both directions (e.g. even in the iOS case where we mux connections both ways) and so it knows if anything is happening. If all is quiet then it knows it can kill the connection.</p> <p>We also need to deal with cleaning things up when they go wrong. Typically we will focus the cleanup code on the multiplex object. It will first close the TCP connections with the Thali app then the multiplex streams connected to those TCP connections then it will close the listener and any native connections before closing itself.</p> <p>Separately it is possible for individual multiplexed TCP connections to die or the individual streams they are connected to can die. This only requires local clean up. We just have to be smart so we don't try to close things that are already closed. So when a TCP connection gets a closed event it has to detect if it was closed by the underlying multiplex stream or by a TCP level error. If it was closed by the multiplex stream then it shouldn't call close on the multiplex stream it is paired with otherwise it should. The same logic applies when an individual stream belonging to multiplex object gets closed. Was it closed by its paired TCP connection? If so, then it's done. Otherwise it needs to close that connection.</p> </li> </ul></div> <dl class="details"> <dt class="tag-source">Source:</dt> <dd class="tag-source"><ul class="dummy"><li> <a href="NextGeneration_TCPServersManager.js.html">NextGeneration/TCPServersManager.js</a>, <a href="NextGeneration_TCPServersManager.js.html#line7">line 7</a> </li></ul></dd> </dl> </div> </article> </section> <section> <header> <h2> <span class="ancestors"><a href="module-thaliMobile.html">thaliMobile</a>~</span>NextGeneration/thaliMobile.js</h2> </header> <article> <div class="container-overview"> <div class="description"><p>This is a convenience class to wrap together <a href="module-thaliMobileNativeWrapper.html">module:thaliMobileNativeWrapper</a> and <a href="module-ThaliWifiInfrastructure.html">module:ThaliWifiInfrastructure</a> in order to create a unified interface and set of events. This object assumes that if it is being used then it has exclusive rights to call <a href="module-thaliMobileNativeWrapper.html">module:thaliMobileNativeWrapper</a>, <a href="module-thaliMobileNative.html">module:thaliMobileNative</a> and <a href="module-ThaliWifiInfrastructure.html">module:ThaliWifiInfrastructure</a>.</p></div> <dl class="details"> <dt class="tag-source">Source:</dt> <dd class="tag-source"><ul class="dummy"><li> <a href="NextGeneration_thaliMobile.js.html">NextGeneration/thaliMobile.js</a>, <a href="NextGeneration_thaliMobile.js.html#line10">line 10</a> </li></ul></dd> </dl> </div> </article> </section> <section> <header> <h2> <span class="ancestors"><a href="module-thaliMobileNative.html">thaliMobileNative</a>~</span>NextGeneration/thaliMobileNative.js</h2> </header> <article> <div class="container-overview"> <div class="description"><p>This file defines the contract for the Mobile bindings that Thali provides for JXcore's native call interface. The actual API calls will &quot;just be there&quot; since they are added to the global environment via JXcore's native binding mechanism. It is expected that these methods will not be called directly but rather will be called via the <a href="module-thaliMobileNativeWrapper.html">module:thaliMobileNativeWrapper</a> wrappers.</p> <p>The primary use of these apis is to enable us to leverage non-TCP/IP capabilities on various devices we run on. In the case of Android this is a combination of BLE (for discovery) and Bluetooth (for high bandwidth data transfer). In the case of iOS this is multi-peer connectivity framework which runs on a mix of Bluetooth, an Apple proprietary variant of Wi-Fi Direct and normal Wi-Fi (if connected to an access point that supports local multi-cast and connectivity between devices on the same AP or network of local APs). Note that Apple's multi-peer connectivity framework actually appears to use a combination of TCP and UDP in some cases but it does not expose a TCP level socket. So although TCP/IP is involved nevertheless that use of TCP is hidden from programs using the multi-peer connectivity framework and so for all intents and purposes it is a non-TCP/IP transport.</p> <p>This library also provides information from the native platform such as information about network connectivity.</p> <p>Note that callbacks rather than promises are specified below because that is required by the JXcore native API.</p> <h2>Request processing model</h2><p>With the exception of <code>connect</code> the <code>callNative</code> methods defined in this file MUST only be called serially. That is, once a <code>callNative</code> method other than <code>connect</code> is called no other <code>callNative</code> methods but <code>connect</code> can be called until the first <code>callNative</code>'s callback has been called. If this prohibition is violated then the system will enter an undefined state.</p> <h2>Idempotent calls</h2><p>All stop methods are idempotent. So multiple calls will not result in a state change.</p> <p>All stop methods are always safe to call even if their start paired method has not yet been called. The default start state is &quot;stop&quot; so calling a stop method before calling its start method pair just means to stay in the stop state.</p> <h2>Initial system state When a Thali app starts up and before any of the</h2><p>APIs defined here are called the initial state of the system MUST be:</p> <ul> <li>No listening for discovery announcements using the native facilities</li> <li>No listening for incoming connections using the native facilities</li> <li>No advertising information using the native facilities</li> </ul></div> <dl class="details"> <dt class="tag-source">Source:</dt> <dd class="tag-source"><ul class="dummy"><li> <a href="NextGeneration_thaliMobileNative.js.html">NextGeneration/thaliMobileNative.js</a>, <a href="NextGeneration_thaliMobileNative.js.html#line5">line 5</a> </li></ul></dd> </dl> </div> </article> </section> <section> <header> <h2> <span class="ancestors"><a href="module-thaliMobileNativeWrapper.html">thaliMobileNativeWrapper</a>~</span>NextGeneration/thaliMobileNativeWrapper.js</h2> </header> <article> <div class="container-overview"> <div class="description"><p>This is the primary interface for those wishing to talk directly to the native layer. All the methods defined in this file are asynchronous. However, with the exception of <a href="module-thaliMobileNativeWrapper.html#.emitter">module:thaliMobileNativeWrapper.emitter</a> and module:thaliMobileNativeWrapper.connect, any time a method is called the invocation will immediately return but the request will actually be put on a queue and all incoming requests will be run out of that queue. This means that if one calls two start methods on say advertising or discovery then the first start method will execute, call back its promise and only then will the second start method start running. This restriction is in place to simplify the state model and reduce testing.</p> <h2>Why not just call <a href="module-thaliMobileNative.html">module:thaliMobileNative</a> directly?</h2><p>Our contract in <a href="module-thaliMobileNative.html">module:thaliMobileNative</a> stipulates some behaviors that have to be enforced at the node.js layer. For example, we can only issue a single outstanding non-connect Mobile().callNative command at a time. We also want to change the callbacks from callbacks to promises as well as change registerToNative calls into Node.js events. All of that is handled here. So as a general rule nobody but this module should ever call <a href="module-thaliMobileNative.html">module:thaliMobileNative</a>. Anyone who wants to use the <a href="module-thaliMobileNative.html">module:thaliMobileNative</a> functionality should be calling this module.</p></div> <dl class="details"> <dt class="tag-source">Source:</dt> <dd class="tag-source"><ul class="dummy"><li> <a href="NextGeneration_thaliMobileNativeWrapper.js.html">NextGeneration/thaliMobileNativeWrapper.js</a>, <a href="NextGeneration_thaliMobileNativeWrapper.js.html#line8">line 8</a> </li></ul></dd> </dl> </div> </article> </section> <section> <header> <h2> <span class="ancestors"><a href="module-thaliPeerDictionary.html">thaliPeerDictionary</a>~</span>NextGeneration/thaliPeerDictionary.js</h2> </header> <article> <div class="container-overview"> <div class="description"><p>Defines a dictionary for use by <a href="module-thaliNotificationClient.html">module:thaliNotificationClient</a> that makes sure we only track a fixed number of peers and will forget peers in a defined order if we get too many of them.</p></div> <dl class="details"> <dt class="tag-source">Source:</dt> <dd class="tag-source"><ul class="dummy"><li> <a href="NextGeneration_thaliPeerDictionary.js.html">NextGeneration/thaliPeerDictionary.js</a>, <a href="NextGeneration_thaliPeerDictionary.js.html#line5">line 5</a> </li></ul></dd> </dl> </div> </article> </section> <section> <header> <h2> <span class="ancestors"><a href="module-ThaliWifiInfrastructure.html">ThaliWifiInfrastructure</a>~</span>NextGeneration/thaliWifiInfrastructure.js</h2> </header> <article> <div class="container-overview"> <div class="description"><p>This is the interface used to manage local discover of peers over a Wi-Fi Infrastructure mode access point.</p> <p>All the methods defined in this file are asynchronous. However any time a method is called the invocation will immediately return but the request will actually be put on a queue and all incoming requests will be run out of that queue. This means that if one calls two start methods on say advertising or discovery then the first start method will execute, call back its promise and only then will the second start method start running. This restriction is in place to simplify the state model and reduce testing.</p> <p>All stop methods in this file are idempotent so they can be called multiple times in a row without causing a state change.</p></div> <dl class="details"> <dt class="tag-source">Source:</dt> <dd class="tag-source"><ul class="dummy"><li> <a href="NextGeneration_thaliWifiInfrastructure.js.html">NextGeneration/thaliWifiInfrastructure.js</a>, <a href="NextGeneration_thaliWifiInfrastructure.js.html#line7">line 7</a> </li></ul></dd> </dl> </div> </article> </section> <section> <header> <h2> <span class="ancestors"><a href="module-WifiBasedNativeMock.html">WifiBasedNativeMock</a>~</span>NextGeneration/wifiBasedNativeMock.js</h2> </header> <article> <div class="container-overview"> <div class="description"><p>This is a mock of <a href="module-thaliMobileNative.html">module:thaliMobileNative</a>. It is intended to replicate all the capabilities of <a href="module-thaliMobileNative.html">module:thaliMobileNative</a> so that we can build and test code intended to use <a href="module-thaliMobileNative.html">module:thaliMobileNative</a> but on the desktop.</p> <p>We are intentionally replicating the lowest layer of the stack in order to to be able to test on the desktop all the layers on top of it. This includes emulating behaviors unique to iOS and Android.</p> <p>For testing purposes if callNative or registerToNative do not get all the parameters they were expecting then a &quot;Bad Arguments&quot; exception MUST be thrown.</p></div> <dl class="details"> <dt class="tag-source">Source:</dt> <dd class="tag-source"><ul class="dummy"><li> <a href="NextGeneration_wifiBasedNativeMock.js.html">NextGeneration/wifiBasedNativeMock.js</a>, <a href="NextGeneration_wifiBasedNativeMock.js.html#line9">line 9</a> </li></ul></dd> </dl> </div> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-TCPServersManager.html">TCPServersManager</a></li><li><a href="module-thaliMobile.html">thaliMobile</a></li><li><a href="module-thaliMobileNative.html">thaliMobileNative</a></li><li><a href="module-thaliMobileNativeWrapper.html">thaliMobileNativeWrapper</a></li><li><a href="module-thaliNotificationAction.html">thaliNotificationAction</a></li><li><a href="module-thaliNotificationBeacons.html">thaliNotificationBeacons</a></li><li><a href="module-thaliNotificationClient.html">thaliNotificationClient</a></li><li><a href="module-thaliNotificationServer.html">thaliNotificationServer</a></li><li><a href="module-thaliPeerAction.html">thaliPeerAction</a></li><li><a href="module-thaliPeerDictionary.html">thaliPeerDictionary</a></li><li><a href="module-thaliPeerPoolInterface.html">thaliPeerPoolInterface</a></li><li><a href="module-ThaliWifiInfrastructure.html">ThaliWifiInfrastructure</a></li><li><a href="module-WifiBasedNativeMock.html">WifiBasedNativeMock</a></li></ul><h3>Externals</h3><ul><li><a href="external-_Mobile(_connect_)_.html">Mobile('connect')</a></li><li><a href="external-_Mobile(_discoveryAdvertisingStateUpdateNonTCP_)_.html">Mobile('discoveryAdvertisingStateUpdateNonTCP')</a></li><li><a href="external-_Mobile(_incomingConnectionToPortNumberFailed_)_.html">Mobile('incomingConnectionToPortNumberFailed')</a></li><li><a href="external-_Mobile(_killConnections_)_.html">Mobile('killConnections')</a></li><li><a href="external-_Mobile(_networkChanged_)_.html">Mobile('networkChanged')</a></li><li><a href="external-_Mobile(_peerAvailabilityChanged_)_.html">Mobile('peerAvailabilityChanged')</a></li><li><a href="external-_Mobile(_startListeningForAdvertisements_)_.html">Mobile('startListeningForAdvertisements')</a></li><li><a href="external-_Mobile(_startUpdateAdvertisingAndListening_)_.html">Mobile('startUpdateAdvertisingAndListening')</a></li><li><a href="external-_Mobile(_stopAdvertisingAndListening_)_.html">Mobile('stopAdvertisingAndListening')</a></li><li><a href="external-_Mobile(_stopListeningForAdvertisements_)_.html">Mobile('stopListeningForAdvertisements')</a></li></ul><h3>Classes</h3><ul><li><a href="ConnectionTable.html">ConnectionTable</a></li><li><a href="module-TCPServersManager-TCPServersManager.html">TCPServersManager</a></li><li><a href="module-thaliNotificationAction-NotificationAction.html">NotificationAction</a></li><li><a href="module-thaliNotificationBeacons-ParseBeaconsResponse.html">ParseBeaconsResponse</a></li><li><a href="module-thaliNotificationClient-ThaliNotificationClient.html">ThaliNotificationClient</a></li><li><a href="module-thaliNotificationServer-ThaliNotificationServer.html">ThaliNotificationServer</a></li><li><a href="module-thaliPeerAction-PeerAction.html">PeerAction</a></li><li><a href="module-thaliPeerDictionary-NotificationPeerDictionaryEntry.html">NotificationPeerDictionaryEntry</a></li><li><a href="module-thaliPeerDictionary-PeerConnectionInformation.html">PeerConnectionInformation</a></li><li><a href="module-thaliPeerDictionary-PeerDictionary.html">PeerDictionary</a></li><li><a href="module-thaliPeerPoolInterface-ThaliPeerPoolInterface.html">ThaliPeerPoolInterface</a></li><li><a href="module-ThaliWifiInfrastructure-ThaliWifiInfrastructure.html">ThaliWifiInfrastructure</a></li><li><a href="module-WifiBasedNativeMock-MobileCallInstance.html">MobileCallInstance</a></li><li><a href="module-WifiBasedNativeMock-WifiBasedNativeMock.html">WifiBasedNativeMock</a></li></ul><h3>Events</h3><ul><li><a href="module-thaliMobileNativeWrapper.html#~event:discoveryAdvertisingStateUpdateNonTCPEvent">discoveryAdvertisingStateUpdateNonTCPEvent</a></li><li><a href="module-ThaliWifiInfrastructure.html#~event:discoveryAdvertisingStateUpdateWifiEvent">discoveryAdvertisingStateUpdateWifiEvent</a></li><li><a href="module-TCPServersManager.html#~event:failedConnection">failedConnection</a></li><li><a href="module-thaliMobileNativeWrapper.html#~event:incomingConnectionToPortNumberFailed">incomingConnectionToPortNumberFailed</a></li><li><a href="module-thaliMobileNativeWrapper.html#~event:networkChangedNonTCP">networkChangedNonTCP</a></li><li><a href="module-ThaliWifiInfrastructure.html#~event:networkChangedWifi">networkChangedWifi</a></li><li><a href="module-thaliMobileNativeWrapper.html#~event:nonTCPPeerAvailabilityChangedEvent">nonTCPPeerAvailabilityChangedEvent</a></li><li><a href="module-TCPServersManager.html#~event:routerPortConnectionFailed">routerPortConnectionFailed</a></li><li><a href="module-ThaliWifiInfrastructure.html#~event:wifiPeerAvailabilityChanged">wifiPeerAvailabilityChanged</a></li><li><a href="module-thaliMobile.html#.event:event:discoveryAdvertisingStateUpdate">discoveryAdvertisingStateUpdate</a></li><li><a href="module-thaliMobile.html#.event:event:networkChanged">networkChanged</a></li><li><a href="module-thaliMobile.html#.event:event:peerAvailabilityChanged">peerAvailabilityChanged</a></li><li><a href="module-thaliNotificationAction-NotificationAction.html#.event:event:Resolved">Resolved</a></li><li><a href="module-thaliNotificationClient.html#.event:event:peerAdvertisesDataForUs">peerAdvertisesDataForUs</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getPKCS12Content">getPKCS12Content</a></li><li><a href="global.html#getPublicKeyHash">getPublicKeyHash</a></li><li><a href="global.html#stopThaliReplicationManager">stopThaliReplicationManager</a></li><li><a href="global.html#ThaliEmitter">ThaliEmitter</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Mon Jan 18 2016 11:19:31 GMT+0200 (EET) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>