thali
Version:
920 lines (354 loc) • 26.1 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Class: TCPServersManager</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">Class: TCPServersManager</h1>
<section>
<header>
<h2>
<span class="ancestors"><a href="module-TCPServersManager.html">TCPServersManager</a>~</span>TCPServersManager</h2>
</header>
<article>
<div class="container-overview">
<h4 class="name" id="TCPServersManager"><span class="type-signature"></span>new TCPServersManager<span class="signature">(routerPort)</span><span class="type-signature"></span></h4>
<div class="description">
<p>An instance of this class is used by <a href="module-thaliMobileNativeWrapper.html">module:thaliMobileNativeWrapper</a>
to create the TCP servers needed to handle non-TCP incoming and outgoing
connections.</p>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>routerPort</code></td>
<td class="type">
<span class="param-type">number</span>
</td>
<td class="description last"><p>The port that the system is hosting the local
router instance for the Thali Application.</p></td>
</tr>
</tbody>
</table>
<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#line497">line 497</a>
</li></ul></dd>
</dl>
<h5>Fires:</h5>
<ul>
<li><a href="module-TCPServersManager.html#~event:routerPortConnectionFailed">event:routerPortConnectionFailed</a></li>
<li><a href="module-TCPServersManager.html#~event:failedConnection">event:failedConnection</a></li>
</ul>
</div>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="createNativeListener"><span class="type-signature">(private) </span>createNativeListener<span class="signature">(routerPort)</span><span class="type-signature"> → {Promise.<(number|Error)>}</span></h4>
<div class="description">
<p>This method creates a TCP listener to handle requests from the native layer
and to then pass them through a multiplex object who will route all the
multiplexed connections to routerPort, the port the system has hosted the
submitted router object on. The TCP listener will be started on port 0 and
the port it is hosted on will be returned in the promise. This is the port
that MUST be submitted to the native layer's llNative command.</p>
<p>If this method is called when we are not in the start state then an exception
MUST be thrown because this is a private method and something very bad just
happened.</p>
<p>If this method is called twice an exception MUST be thrown because this
should only be called once from the constructor.</p>
<h2>TCP Listener</h2><h3>Connect Event</h3><p>A multiplex object MUST be created and MUST be directly piped in both
directions with the TCP socket returned by the listener. We MUST set a
timeout on the incoming TCP socket to a reasonable value for the platform.
The created multiplex object MUST be recorded with an index of the client
port used by the incoming TCP socket.</p>
<h3>Error Event</h3><p>The error MUST be logged.</p>
<h3>Close Event</h3><p>We MUST call destroy on all multiplex objects spawned by this TCP listener.</p>
<h2>Incoming TCP socket returned by the server's connect event</h2><h3>Error Event</h3><p>The error MUST be logged.</p>
<h3>Timeout Event</h3><p>Destroy MUST be called on the piped multiplex object. This will trigger a
total cleanup.</p>
<h3>Close Event</h3><p>If this close is not the result of a destroy on the multiplex object then
destroy MUST be called on the multiplex object.</p>
<h2>Multiplex Object</h2><h3>onStream Callback</h3><p>The incoming stream MUST cause us to create a net.createConnection to
routerPort and to then take the new TCP socket and pipe it in both directions
with the newly created stream. We MUST track the TCP socket so we can clean
it up later. Note that the TCP socket will track its associated stream and
handle cleaning it up. If the TCP socket cannot be connected to routerPort
then a routerPortConnectionFailed event MUST be fired and destroy MUST be
called on the stream provided in the callback.</p>
<h3>Error Event</h3><p>The error MUST be logged.</p>
<h3>Close Event</h3><p>Destroy MUST first be called on all the TCP sockets we created to routerPort
(the TCP sockets will then close their associated multiplex streams). Then we
MUST call Destroy on the incoming TCP socket from the native layer. Note that
in some cases one or more of these objects could already be closed before we
call destroy so we MUST be prepared to catch any exceptions. Finally we MUST
remove the multiplex object from the list of multiplex objects we are
maintaining.</p>
<h2>TCP client socket created by net.createConnection call from multiplex</h2><p>object</p>
<h3>Error Event</h3><p>The error MUST be logged.</p>
<h3>Close Event</h3><p>Destroy MUST be called on the stream this TCP socket is piped to assuming
that it wasn't that stream that called destroy on the TCP client socket.</p>
<h2>multiplex onStream stream</h2><h3>Error Event</h3><p>The error MUST be logged.</p>
<h3>Close Event</h3><p>If the close did not come from the TCP socket this stream is piped to then
close MUST be called on the associated TCP socket.</p>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>routerPort</code></td>
<td class="type">
<span class="param-type">number</span>
</td>
<td class="description last"><p>Port that the router object submitted to
module:ThaliMobileNativeWrapper.startUpdateAdvertisingAndListening is hosted on. This value was passed into this object's constructor.</p></td>
</tr>
</tbody>
</table>
<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#line269">line 269</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
<p>The port that the mux is listening on for
connections from the native layer or an Error object.</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Promise.<(number|Error)></span>
</dd>
</dl>
<h4 class="name" id="createPeerListener"><span class="type-signature"></span>createPeerListener<span class="signature">(peerIdentifier, pleaseConnect<span class="signature-attributes">opt</span>)</span><span class="type-signature"> → {Promise.<(number|Error)>}</span></h4>
<div class="description">
<p>This creates a local TCP server to accept incoming connections from the Thali
app that will be sent to the identified peer.</p>
<p>If this method is called before start is called then a "Start First!" error
MUST be thrown. If this method is called after stop is called then a "We are
stopped!" error MUST be thrown.</p>
<p>If there is already a TCP server listening for connections to the submitted
peerIdentifier then the port for the TCP server MUST be returned.</p>
<p>If there is no existing TCP server for the specified peer then we MUST
examine how many peers we are advertising 127.0.0.1 ports for. If that number
is equal to maxPeersToAdvertise then we MUST call destroy on one of those TCP
listeners before continuing with this method. That way we will never offer
connections to more than maxPeersToAdvertise peers at a time. We should
exclude all TCP servers that have active multiplex objects and pick a TCP
server to close based on FIFO. Once we have closed the TCP server, if
necessary, then a new TCP server MUST be created on port 0 (e.g. any
available port) and configured as follows:</p>
<h2>TCP server</h2><p>If pleaseConnect is true then an immediate call MUST be made to external:"Mobile('connect')".callNative to connect to the specified peer. If
that call fails then the error MUST be returned. Otherwise a new multiplex
object MUST be created and a new TCP connection via net.createConnection
pointed at the port returned by the connect call. The multiplex object MUST
be piped in both directions with the new TCP connection. The TCP connection
MUST have setTimeout called on it and set to a reasonable value for the
platform.</p>
<h3>Connection Event</h3><h4>First call to connection event when pleaseConnect is false</h4><p>If pleaseConnect is false then when the first connection event occurs we MUST
issue a external:"Mobile('connect')".callNative for the requested
peer and handle the response as given in the following sections.</p>
<h5>Error</h5><p>If we get an error then we MUST close the TCP connection and fire a <a href="module-TCPServersManager.html#~event:failedConnection">event:failedConnection</a> event with the returned error.</p>
<h5>listenerPort</h5><p>If the response is listenerPort then we MUST perform the actions specified
above for pleaseConnect is true with the exception that if the connect fails
then we MUST call close on the TCP server since the peer is not available and
fire a <a href="module-TCPServersManager.html#~event:failedConnection">event:failedConnection</a> event with the error set to "Cannot
Connect To Peer".</p>
<h5>clientPort/serverPort</h5><p>If clientPort/serverPort are not null then we MUST confirm that the
serverPort matches the port that the server created in module:TCPServersManager.createNativeListener is listening on and if not
then we MUST call destroy on the incoming TCP connection, fire a <a href="module-TCPServersManager.html#~event:failedConnection">event:failedConnection</a> event with the error set to "Mismatched serverPort",
and act as if connection had not been called (e.g. the next connection will
be treated as the first).</p>
<p>Otherwise we must then lookup the multiplex object via the clientPort. If
there is no multiplex object associated with that clientPort then we have a
race condition where the incoming connection died between when the connect
response was sent and now. In that case we MUST call destroy on the incoming
TCP connection, first a <a href="module-TCPServersManager.html#~event:failedConnection">event:failedConnection</a> event with the error
set to "Incoming connection died" and as previously described treat the next
connection as if it were the first.</p>
<p>Otherwise we MUST configure the multiplex object with the behavior specified
below.</p>
<h4>Standard connection event behavior</h4><p>Each socket returned by the connection event MUST cause a call to
createStream on the multiplex object and the returned stream MUST be piped in
both directions with the connection TCP socket.</p>
<h3>Error Event</h3><p>The error MUST be logged.</p>
<h3>Close Event</h3><p>All the TCP sockets to routerPort MUST first be destroyed. Then all the TCP
sockets from the Thali application MUST be destroyed.</p>
<p>Unless destroy was called on the TCP server by the multiplex object then
destroy MUST be called on the multiplex object.</p>
<h2>Multiplex object</h2><h3>onStream callback</h3><p>If a stream is received a call to net.createConnection MUST be made pointed
at routerPort. If the TCP connection cannot be successfully connected then a
<a href="module-TCPServersManager.html#~event:routerPortConnectionFailed">event:routerPortConnectionFailed</a> MUST be fired and destroy MUST be
called on the stream. Otherwise the TCP connection and the stream MUST be
piped to each other in both directions.</p>
<p>Note that we will support the ability to accept incoming connections over the
multiplex object even for platforms like Android that do not need it. This is
just to keep the code and testing simple and consistent.</p>
<h3>Error Event</h3><p>The error MUST be logged.</p>
<h3>Close Event</h3><p>If the destroy didn't come the TCP server then destroy MUST be called on the
TCP server. If the destroy didn't come from the TCP native socket then
destroy MUST be called on the TCP native socket.</p>
<h2>TCP socket to native layer</h2><h3>Timeout Event</h3><p>Destroy MUST be called on itself.</p>
<h3>Error Event</h3><p>The error MUST be logged.</p>
<h3>Close Event</h3><p>Destroy MUST be called on the multiplex object the stream is piped to.</p>
<h2>TCP socket from Thali Application</h2><h3>Error Event</h3><p>The error MUST be logged.</p>
<h3>Close Event</h3><p>Destroy MUST be called on the stream object the socket is piped to if that
isn't the object that called destroy on the socket.</p>
<h2>createStream Socket</h2><h3>Error Event</h3><p>The error MUST be logged.</p>
<h3>Close Event</h3><p>If destroy wasn't called by the TCP socket from Thali Application the stream
is piped to then destroy MUST be called on that TCP socket.</p>
<h2>TCP socket to routerPort</h2><h3>Error Event</h3><p>The error MUST be logged.</p>
<h3>Close Event</h3><p>Destroy MUST be called on the stream object the socket is piped to if that
isn't the object that called destroy on the socket.</p>
<h2>onStream callback stream</h2><h3>Error Event</h3><p>The error MUST be logged.</p>
<h3>Close Event</h3><p>If destroy wasn't called by the TCP socket to routerPort the stream is piped
to then destroy MUST be called on that TCP socket.</p>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Attributes</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>peerIdentifier</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="attributes">
</td>
<td class="description last"></td>
</tr>
<tr>
<td class="name"><code>pleaseConnect</code></td>
<td class="type">
<span class="param-type">boolean</span>
</td>
<td class="attributes">
<optional><br>
</td>
<td class="description last"><p>If set to true this indicates that a
lexically smaller peer asked for a connection so the lexically larger peer
(the local device) will immediately call external:"Mobile('connect')".callNative to create a connection. If false
(the default value) then the call to external:"Mobile('connect')".callNative will only happen on the first
incoming connection to the TCP server.</p></td>
</tr>
</tbody>
</table>
<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#line458">line 458</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Promise.<(number|Error)></span>
</dd>
</dl>
<h4 class="name" id="start"><span class="type-signature"></span>start<span class="signature">()</span><span class="type-signature"> → {Promise.<(number|Error)>}</span></h4>
<div class="description">
<p>This method will call
<a href="module-TCPServersManager-TCPServersManager.html#createNativeListener">module:TCPServersManager~TCPServersManager#createNativeListener</a>
using the routerPort from the constructor and record the returned port.</p>
<p>This method is idempotent and so MUST be able to be called multiple times
in a row without changing state.</p>
<p>If called successfully then the object is in the start state.</p>
<p>If this method is called after a call to
TCPServersManager~TCPServersManager#stop then a "We are stopped!"
error 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_TCPServersManager.js.html">NextGeneration/TCPServersManager.js</a>, <a href="NextGeneration_TCPServersManager.js.html#line137">line 137</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
<p>Returns the port to be passed to llNative when the system is ready to receive external incoming connections.</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Promise.<(number|Error)></span>
</dd>
</dl>
<h4 class="name" id="stop"><span class="type-signature"></span>stop<span class="signature">()</span><span class="type-signature"> → (nullable) {Error}</span></h4>
<div class="description">
<p>This will cause destroy to be called on the TCP server created by module:TCPServersManager.createNativeListener and then on all the TCP
servers created by module:TCPServersManager.connectToPeerViaNativeLayer.</p>
<p>This method is idempotent and so MUST be able to be called multiple times in
a row without changing state.</p>
<p>If this method is called before calling start then a "Call Start!" Error MUST
be thrown.</p>
<p>Once called the object is in the stop state and cannot leave it. To start
again this object must be disposed and a new one created.</p>
</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#line159">line 159</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</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>