thali
Version:
556 lines (509 loc) • 29 kB
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: NextGeneration/thaliMobile.js</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">Source: NextGeneration/thaliMobile.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>'use strict';
var Promise = require('lie');
var thaliMobileNativeWrapper = require('thaliMobileNativeWrapper');
var thaliWifiInfrastructure = require('ThaliWifiInfrastructure')();
var EventEmitter = require('events');
/** @module thaliMobile */
/**
* @file
*
* This is a convenience class to wrap together {@link
* module:thaliMobileNativeWrapper} and {@link module:ThaliWifiInfrastructure}
* 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 {@link
* module:thaliMobileNativeWrapper}, {@link module:thaliMobileNative} and {@link
* module:ThaliWifiInfrastructure}.
*/
/*
METHODS
*/
/**
* This object is our generic status wrapper that lets us return information
* about both WiFi and Native.
*
* @public
* @typedef {Object} combinedResult
* @property {?Error} wifiResult
* @property {?Error} nativeResult
*/
/**
* This method MUST be called before any other method here other than
* registering for events on the emitter. This method will call start on both
* the {@link module:thaliMobileNativeWrapper} singleton and on an instance of
* {@link module:ThaliWifiInfrastructure} class. Note that in the case of wifi
* this call really does nothing but register the router object. In the case of
* native however there is some setup work so an error is more meaningful. If an
* error is received from start on either wifi or native then any subsequent
* method calls below but stop will not attempt to interact with the failed
* type. And yes, if both fail then essentially all the methods but stop turn
* into NOOPs.
*
* This method also instructs the system to pay attention to network events.
* If one or both radio types is not active but a network changed event
* indicates that the relevant radio type is now active and if we are still in
* the start state then this code MUST try to call start on the newly activated
* radio stack. At that point if the object is in the start state for discovery
* or advertising then we MUST also try to call the relevant start methods there
* as well.
*
* This method is not idempotent. If called two times in a row without an
* intervening stop a "Call Stop!" Error MUST be returned.
*
* This method can be called after stop since this is a singleton object.
*
* @public
* @param {Object} router This is an Express Router object (for example,
* express-pouchdb is a router object) that the caller wants non-TCP and WiFi
* connections to be terminated with. This code will put that router at '/' so
* make sure your paths are set up appropriately. If stop is called then the
* system will take down the server so it is no longer available.
* @returns {Promise<module:thaliMobile~combinedResult>}
*/
module.exports.start = function (router) {
return new Promise();
};
/**
* This calls stop on both stacks even if start failed.
*
* Once called the object is in stop state.
*
* This method is idempotent and so MUST be able to be called multiple times
* in a row without changing state.
*
* @public
* @returns {Promise<module:thaliMobile~combinedResult>}
*/
module.exports.stop = function () {
return new Promise();
};
/**
* This method calls the underlying startListeningForAdvertisements on
* whichever radio stack is currently in start state. Note that once this method
* is called it is giving explicit permission to this code to call this method
* on a radio stack that is currently disabled when the method is called but is
* later re-enabled due to a network changed event. In other words if {@link
* module:thaliMobile.start} is called and say WiFi doesn't work. Then this
* method is called and so advertising is only started for the non-TCP
* transport. Then a network changed event happens indicating that WiFi is
* available. Since we are still in start state this code will automatically
* call {@link module:ThaliWifiInfrastructure~ThaliWifiInfrastructure#start} and
* then will call {@link
* module:ThaliWifiInfrastructure.startListeningForAdvertisements} because we
* haven't yet called {@link module:thaliMobile.stopListeningForAdvertisements}.
* If any of the calls triggered by the network event fail then the results MUST
* be logged.
*
* This method is idempotent so multiple consecutive calls without an
* intervening call to stop will not cause a state change.
*
* This method MUST NOT be called if the object is not in start state or a
* "Call Start!" error MUST be returned.
*
* The combinedResult MUST return an error of "Not Active" for any radio type
* that we did not call startListeningForAdvertisements on.
*
* @public
* @returns {Promise<module:thaliMobile~combinedResult>}
*/
module.exports.startListeningForAdvertisements = function () {
return new Promise();
};
/**
* This method calls the underlying stopListeningForAdvertisements on both
* types regardless of which is in start state.
*
* This method is idempotent and MAY be called even if
* startListeningForAdvertisements has not been called.
*
* @public
* @returns {Promise<module:thaliMobile~combinedResult>}
*/
module.exports.stopListeningForAdvertisements = function () {
return new Promise();
};
/**
* This method calls the underlying
* startUpdateAdvertisingAndListening on whichever radio
* stack is currently in start state. This method has the same behavior as
* {@link module:thaliMobile.startListeningForAdvertisements} in that if a radio
* type that was inactive should later become available and we are in start
* state then we will try to call start and if that works and
* stopAdvertisingAndListening has not been called then
* we will try to call startUpdateAdvertisingAndListening on
* the newly started stack. This includes the requirement to log any failed
* attempts to call the various methods triggered by a network status change.
*
* Every call to this method is meant to change the current advertising flag
* to indicate that new data is available.
*
* @public
* @returns {Promise<module:thaliMobile~combinedResult>}
*/
module.exports.startUpdateAdvertisingAndListening =
function () {
return new Promise();
};
/**
* This method calls the underlying
* stopAdvertisingAndListening on both types regardless of
* which is in start state.
*
* This method is idempotent and MAY be called even if
* startUpateAdvertisingAndListenForIncomingConnections has not been called.
*
* @public
* @returns {Promise<module:thaliMobile~combinedResult>}
*/
module.exports.stopAdvertisingAndListening = function () {
return new Promise();
};
/*
EVENTS
*/
/**
* Enum to define the types of connections
*
* @readonly
* @enum {string}
*/
module.exports.connectionTypes = {
MULTI_PEER_CONNECTIVITY_FRAMEWORK: 'MPCF',
BLUE_TOOTH: 'AndroidBlueTooth',
TCP_NATIVE: 'tcp'
};
/**
* It is the job of this module to provide the most reliable guesses (and that
* is what they are) as to when a peer is and is not available. The module MUST
* err on the side of saying that a peer is available over saying they are not
* available.
*
* The module MUST guarantee to its listeners (unlike {@link
* module:thaliMobileNative}) that once it has fired a peerAvailabilityChanged
* event for a specific peerIdentifier + connectionType combination that it will
* not fire another peerAvailabilityChanged event for that peerIdentifier +
* connectionType combination unless the combination has a new hostAddress or
* portNumber.
*
* Note that this code explicitly does not do any kind of duplicate detection
* for the same peerIdentifier across different connectionTypes. This is because
* we want to surface to the caller all the ways a particular peer is available.
*
* This means that if this code receives multiple redundant notifications from
* the various sources it is listening to about the same peerIdentifier and
* connectionType combination then it must silently discard the duplicates.
*
* ## Android + BLE + Bluetooth
*
* When dealing with announcing that a peer has disappeared it is up to this
* code to apply relevant heuristics. For example, in the case of Android it is
* possible for a Thali app to go into the background. When this happens we
* lower the power of the BLE status announcements but we don't change the
* Bluetooth power. This means that a peer can seem to disappear when in fact
* they are still in range of Bluetooth. This behavior is necessary to preserve
* battery. This complicates things because the Android BLE stack never actually
* says a peer is gone. Rather it sends a steady stream of announcements that
* the peer is available and then stops when it doesn't see the peer anymore. So
* this code has to notice those announcements and decide at what point after
* they have stopped to declare the peer gone. In general we should experiment
* with values like 30 seconds before deciding that a peer is gone. But why not
* even longer?
*
* __Open Issue:__ How long should we wait after we don't hear any updates on
* a peer being available over Android before we declare them gone?
*
* __Open Issue:__ A really obvious optimization would be to hook this code
* into the {@link module:TCPServersManager} so it could see if we have a
* Bluetooth or MPCF connection running with a particular peer. If we do then
* obviously we wouldn't want to declare them gone even if we don't see them on
* BLE or if MPCF told us they were gone.
*
* If an attempt to connect to a peer via Bluetooth whose presence we have
* previously advertised via peerAvailabilityChanged should fail then we MUST
* use our own heuristics to decide if we should mark the peer as no longer
* available. Generally speaking if we still see the peer via BLE then we should
* continue to mark them as available. Note that available doesn't mean
* reachable. It is very easy for a peer to get overwhelmed with Bluetooth
* requests and so be near but not able to accept a request.
*
* If we have been notified via a networkChanged event that either BLE or
* Bluetooth is no longer available then we MUST mark all peers discovered via
* BLE as no longer being present and send peerAvailabilityChanged events
* reporting this status change. In theory we could make things more complex by
* specifying that if BLE is turned off and Bluetooth isn't then we could
* continue to say that the Bluetooth peers are there. But in practical terms it
* isn't clear if this situation is possible (e.g. I suspect one can only turn
* off Bluetooth, not sub-select between BLE and Bluetooth) and second it's more
* complexity than we really need at this point.
*
* If we have been notified via a discoveryAdvertisingStatus event that
* discovery is no longer available then we MUST treat existing discovered
* Bluetooth peers as no longer being available and send peerAvailabilityChanged
* events reporting this fact. Eventually we might get more flexible here and
* allow Bluetooth peers to remain "available" and just use the connection
* heuristics described previously to mark them as absent when necessary. But
* for now let's keep things simple.
*
* If we have been notified via a discoveryAdvertisingStatus event that
* advertising is no longer available this should not cause any change in our
* information about peers we have discovered or will yet discover.
*
* ## iOS + MPCF
*
* In the case of the MPCF the native layer has an explicit lostPeer message.
* But we aren't completely sure if it's totally reliable. So we either can
* immediately declare the peer gone when we get lostPeer or we can take note of
* the lostPeer message and then wait a bit before declaring the peer gone. Note
* that we would only see this at the Node.js layer via a {@link
* module:thaliMobileNativeWrapper~nonTCPPeerAvailabilityChanged} event.
*
* __Open Issue:__ How does MPCF deal with peers who have gone out of range?
* Do they regularly send foundPeer messages or do they send one foundPeer
* message and go quiet until they send a lostPeer message after a bit?
*
* __Open Issue:__ How reliable is the lostPeer message from MPCF? I believe
* we have had a suspicion that even if we get a lostPeer we might still be able
* to open a connection to that peer successfully (this would make sense if
* discovery is over Bluetooth and data transfer over Wifi). But we need to now
* make this concrete since we have to decide if we are going to put this
* suspicion into our code.
*
* If an attempt to connect to a peer via MPCF whose presence we have previously
* advertised via peerAvailabilityChanged should fail we MUST use our own
* heuristics to decide if we should mark the peer as no longer available.
* Typically we should allow several failed connection attempts before we decide
* to mark the peer as no longer present.
*
* If we have been notified via a networkChanged event that one of Bluetooth or
* Wifi are no longer available but not both then this should not cause any
* immediate action since MPCF seems able to run exclusively over one transport
* or the other.
*
* If however we have been notified via a networkChanged even that both
* Bluetooth and Wifi are no longer available then we MUST mark all peers that
* we have previously advertised as available as now being unavailable and
* advertise this change via the peerAvailabilityChanged event.
*
* If we have been notified via a discoveryAdvertisingStatus event that
* discovery is no longer available then we MUST change the availability of
* peers discovered via MPCF as not available and advertise this fact via
* peerAvailabilityChanged.
*
* __Open Issue:__ The MPCF explicitly states that one shouldn't keep discovery
* on all the time. One suspects this is because they are using Bluetooth for
* discovery. As such as may need to cycle discovery on and off to save battery.
* In that case we will need to change the logic above so that turning off
* discovery doesn't make the peer appear to be gone.
*
* If we have been notified via a discoveryAdvertisingStatus even that
* advertising is no longer available then this should not cause any change in
* our peer status.
*
* ## Wifi
*
* In the case of Wifi SSDP supports sending both announcements of
* availability as well as announcements that one is going off line. If we
* receive an announcement that a peer is going away then we can trust that
* since it means the peer is deactivating its SSDP stack. But we can't rely on
* receiving such an announcement since obviously if a peer just walks away
* nothing will be said. So we MUST set a timer after receiving a SSDP
* announcement for a peer (we will receive this via a {@link
* module:ThaliWifiInfrastructure~wifiPeerAvailabilityChanged} event) and if we
* don't hear an announcement that they are gone then we MUST automatically
* generate such an announcement ourselves.
*
* Unlike the non-TCP transports, we do not use a proxy architecture with Wifi
* and therefore do not know if an attempted connection succeeded or not. This
* is why there is no equivalent requirement here to the ones above specifying
* that failed connections should cause us to mark a peer as not available.
*
* If we have been notified via a networkChanged event that Wifi is no longer
* available then all peers discovered via Wifi MUST be marked as not present
* and this fact advertised via peerAvailabilityChanged.
*
* If we have been notified via a discoveryAdvertisingStatus event that
* discovery is no longer available then we MUST change the availability of
* peers discovered via Wifi to not available and advertise this fact via
* peerAvailabilityChanged. This is a bit harsh since if Wifi is still working
* we certainly could connect to those peers but once discovery is off we have
* no way of knowing if the peer has disappeared and since we don't have a proxy
* architecture we can't detect failed connections. So it's just easier for now
* to just treat the peers as gone.
*
* If we have been notified via a discoveryAdvertisingStatus event that
* advertising is no longer available then this should not cause any change in
* our peer status.
*
* ## General guidelines on handling nonTCPPeerAvailabilityChanged and
* wifiPeerAvailabilityChanged events
*
* If we receive a {@link
* module:thaliMobileNativeWrapper~nonTCPPeerAvailabilityChanged} event then all
* we have to do is return the arguments below as taken from the event with the
* exception of setting hostAddress to 127.0.0.1 unless the peer is not
* available in which case we should set both hostAddress and portNumber to
* null.
*
* If we receive a {@link
* module:ThaliWifiInfrastructure~wifiPeerAvailabilityChanged} event then all we
* have to do is return the arguments below as taken from the event with the
* exception of setting something reasonable for the suggestedTCPTimeout.
*
* @public
* @event module:thaliMobile.event:peerAvailabilityChanged
* @type {Object}
* @property {string} peerIdentifier This is exclusively used to detect if
* this is a repeat announcement or if a peer has gone to correlate it to the
* announcement of the peer's presence. But this value is not used to establish
* a connection to the peer, the hostAddress and portNumber handle that.
* @property {string} hostAddress The IP/DNS address to connect to or null if
* this is an announcement that the peer is no longer available.
* @property {number} portNumber The port to connect to on the given
* hostAddress or null if this is an announcement that the peer is no longer
* available.
* @property {number} suggestedTCPTimeout Provides a hint to what time out to
* put on the TCP connection. For some transports a handshake can take quite a
* long time.
* @property {connectionTypes} connectionType Defines the kind of connection
* that the request will eventually go over. This information is needed so that
* we can better manage how we use the different transport types available to
* us.
*/
thaliMobileNativeWrapper.on('nonTCPPeerAvailabilityChangedEvent',
function (peer)
{
// Do stuff
});
thaliWifiInfrastructure.on('wifiPeerAvailabilityChanged',
function (hostAddress, portNumber) {
// Do stuff
});
/**
* Fired whenever our state changes.
*
* @public
* @typedef {Object} discoveryAdvertisingStatus
* @property {boolean} discoveryActive If true indicates that our goal is to
* have discovery active on all available radios.
* @property {boolean} advertisingActive If true indicates that our goal is to
* have advertising active on all available radios.
* @property {boolean} nonTCPDiscoveryActive Indicates if discovery is active
* on the non-TCP transport
* @property {boolean} nonTCPAdvertisingActive Indicates if advertising is
* active on the non-TCP transport
* @property {boolean} wifiDiscoveryActive Indicates if discovery is active on
* WiFi
* @property {boolean} wifiAdvertisingActive Indicates if advertising is
* active on WiFi
*/
/**
* If we receive a {@link
* module:thaliMobileNativeWrapper~discoveryAdvertisingStateUpdateNonTCPEvent}
* there are a couple of possibilities:
* - This just confirms whatever command we fired, we started advertising and
* it is confirming that. We should only pass on this event the first time it
* comes through. If we get multiple events with the same state and they all
* match our current state then they should be suppressed.
* - We thought something was started but now we are getting a notice that it
* is stopped. In that case we need to internally record that discovery or
* advertising is no longer started and fire this event to update.
* - We thought something was stopped but now we are getting a notice that
* they are started. This can happen because our network change event code
* detected that a radio that was off is now on and we are trying to start
* things. In that case we should mark the discovery or advertising as started
* and fire this event.
*
* If we receive a {@link
* module:ThaliWifiInfrastructure~discoveryAdvertisingStateUpdateWiFiEvent} then
* the logic is effectively the same as above.
*
* A scary edge case is that we want discovery or advertising off and suddenly
* the spontaneously turn on. This shouldn't happen (famous last words) so we'll
* ignore it for the moment.
*
* @public
* @event module:thaliMobile.event:discoveryAdvertisingStateUpdate
* @type {Object}
* @property {module:thaliMobile~discoveryAdvertisingStatus}
* discoveryAdvertisingStatus
*/
thaliMobileNativeWrapper.on('discoveryAdvertisingStateUpdateNonTCPEvent',
function (discoveryAdvertisingStateUpdateValue) {
// Do stuff
});
thaliWifiInfrastructure.on('discoveryAdvertisingStateUpdateWifiEvent',
function (discoveryAdvertisingStateUpdateValue) {
// Do stuff
});
/**
* Unless something went horribly wrong only one of thaliMobileNativeWrapper
* or ThaliWifiInfrastructure should be enabled for this event at a time. We can
* just pass the event value alone.
*
* @public
* @event module:thaliMobile.event:networkChanged
* @type {Object}
* @property {module:thaliMobileNative~networkChanged} networkChangedValue
*/
thaliMobileNativeWrapper.on('networkChangedNonTCP',
function (networkChangedValue) {
// Do stuff
});
thaliWifiInfrastructure.on('networkChangedWifi',
function (networkChangedValue) {
// Do stuff
});
/**
* If we receive a {@link
* module:thaliMobileNativeWrapper~incomingConnectionToPortNumberFailed} and we
* are in stop state then it means that we had a race condition where someone
* tried to connect to the server just as we were killing it. If we get this in
* the start state after having turned on advertising then it means that our
* server has failed. The best we can do is try to close the server and open it
* again.
*/
thaliMobileNativeWrapper.on('incomingConnectionToPortNumberFailed',
function (portNumber) {
// Do stuff
});
/**
* Use this emitter to subscribe to events
*
* @public
* @fires module:thaliMobile.event:peerAvailabilityChanged
* @fires module:thaliMobile.event:discoveryAdvertisingStateUpdate
* @fires module:thaliMobile.event:networkChanged
*/
module.exports.emitter = new EventEmitter();
</code></pre>
</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>