Skip to content

EncounterManager

Thomas Schwotzer edited this page Sep 14, 2023 · 27 revisions

Connection Creation

ASAP peers run an ASAP session over an existing connection. That connection is not created by peers but other parts of an ASAP application. Those parts needs to provide Input- and Outputstream.

ASAP can use any networks that provides those streams - which are all known protocols, like Bluetooth, TCP, LoRa just to name a few. Multiple protocols can and should be used in parallel. That's the very idea of ASAP - build most resilient applications using as much communication protocols as possible.

It makes no sense to connect to peers at the same time over more than one protocol, though. It would a wast of rescource since an ASAP session is rather quick. A peer would not even recognize that is has multiple connection to the same other peer. They would have the same ASAP session over two protocols. Wast of resources.

We decided not to make a peer more complex than it already is but to introduce a EncounterManager. It wraps a peer. It keeps track of running ASAP sessions and can decide if a new connection should be established or not.

The following code is taken from unit test connectAliceAndBobWithEncounterManager_Preferred in ConnectPeers.

// peer alice in its role as connection handler
ASAPConnectionHandler alice = new ASAPPeerFS(TestConstants.ALICE_ID, aliceFolder, formats);

// create an encounter manager for peer alice with cool down period 100ms
ASAPEncounterManager aliceEncounterManager = new ASAPEncounterManagerImpl(alice, 100);

Scenario

Let's discuss usage of our encounter manager in an example. Figure: EncounterManagerWrapsASAPPeer

There are two peers (Alice and Bob) including their encounter manager. Another entity BTConnectionProducer symbolises a part in an application that can produce Bluetooth connections.

  1. Bluetooth adapter on both sides would recognize another device in communication range. Adapters would see at least a device name or even a service description if service discovery is used. (Such details are out of the scope here, though).

  2. Both adapter should ask their local encounter manager if they should create an connection.

  3. Both would agree since there is no other connection to Alice or Bob. Encounter manager remember recent connections over a cool down period. That period is defined by developers. It avoid that flickering effect we already discussed.

  4. Their is usually a race condition in ASAP based applications using ad-hoc protocols like Bluetooth: Both sides would offer an open port for other (ASAP) applications to connect to. Both sides would see each other. Both would realize they are not connected yet and would establish a connection. Both sides would do exactly the same simultaneously. Accepting a connection request on an open port is a bit fasten than establishing a new connection. So, on both sides, a connection requested is accepted and is immediatelly followed by a successful new connection establishment to same device which connections request was granted a view moments earlier. This (nearly) always leads to two new connections. (We tested it on several devices and took a few nerving hours to answer the question. Why are there two ASAP session running between both devices?). You will face exactly the same situation if you work with ad-hoc networks. No way arround in a P2P system. Both sides do the same: Offer connections and connect. Our encounter manager solves the problem by waiting a view milliseconds to let the second connection be established. A little protocol based on random numbers runs between both encounter mangager instances. It is like flipping a coin to decide what connection is to be closed. That's it. Good news: ASAP app developers are not bothered with those details. You should have it in mind when you deal with ad-hoc protocols.

  5. Encounter manager on both side would ask their peers to run an ASAP session on the (remaining) connection.

Code

Good news: The code is much shorter than this explanation.

InputStream is; 
OutputStream os;
if(aliceEncounterManager.shouldCreateConnectionToPeer​(
    "Bob", EncounterConnectionType.AD_HOC_LAYER_2_NETWORK)) {
        // connect and remember is and os
} else { // leave }

// connection established - create stream pair object
StreamPair newStreamPair = StreamPairImpl.getStreamPair(is, os);

// optional - close connection if - in this case - idle for 200ms
IdleStreamPairCloser.getIdleStreamsCloser(newStreamPair, 200).start();

// ask manager to handle new encouter
aliceEncounterManager.handleEncounter(newStreamPair, EncounterConnectionType.AD_HOC_LAYER_2_NETWORK);