Skip to content

Peer side API

Thomas Schwotzer edited this page Aug 17, 2024 · 13 revisions

Setup

We want to hide as much complexity as possible from application developers. We make it short. Here is the less complex and best way to work with a hub in your ASAP based application.

We assume, you are already familiar with our ASAPEncounterManager.

Here is the code you should copy into your application.

SharkPeer sharkPeer = ...; // there is a peer
ASAPPeer asapPeer = sharkPeer.getASAPPeer(); // there is always an ASAP peer inside
// we need also the peer in its role of a connection handler
ASAPConnectionHandler asapHandler = (ASAPConnectionHandler) asapPeer();

// setup the system

// create an encounter manager
ASAPEncounterManagerImpl encounterManager = new ASAPEncounterManagerImpl(asapHandler, asapPeer.getPeerID());

// create a hub manager on peer side and link it with encounter manager
HubConnectionManager hubConnectionManager = new HubConnectionManagerImpl(this.encounterManager, asapPeer);

Now we are ready to work with a hub.

Connect and Disconnect

A peer can be connected to a hub by calling a single methode: hubConnectionManager.connectHub. It requires a single parameter, a HubConnectorDescription. It is a simple data structure comprising parameter required to access a hub.

HubConnectorDescription hcd = new TCPHubConnectorDescriptionImpl("localhost", 6666, true);
hubConnectionManager.connectHub(hcd);

This code would try to establish a connection to a hub available on the same machine with an open TCP port on 6666. Nothing more to do for app developers.

A new connection attempt would be redirected to the encouter manager. It would briefly check if a new ASAP session is useful. The actual ASAP session would be performed by its ASAP peer.

hubConnectionManager.disconnectHub(hcd);

This code breaks the connection to the hub.

List<HubConnectorDescription> hcdList  = hubConnectionManager.getConnectedHubs();

You can get a list of hub connections which are actually in place.

Persist Hub Connection Descriptions

Actually, we do not know how you will use hubs in your application. We consider hubs a more fluent entity. It is launched, runs a while(minutes, hours, maybe days) but disappears soon.

The obvious question is a version of the chicken-and-the-egg problem. Where would we get information on a hub in the first place. Once we have it, we can disseminate information on next hubs in our application. But how to find the first.

There are two sub-project in place:

  • We send hub information in social networks steganographic hidden. It is, of course, not a perfect safe solution. But it could be useful in some application classes.
  • We use a P2P system like libp2p / disc to provide hub descriptions. Those information are public.

It always depends on your application requirements. At least, you can chose.

Anyway, we need a way to make hub descriptions persistent on a peer. Good news. A SharkPeer can remember.

Details on Hub Manager Management

You can add and remove HubConnector objects to a ASAPHubManager. This manager performs a simple algorithm: This approach enables you to connect to the Hub using a custom HubConnector object.

  1. Get a fresh list of peers from each connected hub
  2. establish a connection to each peer - peers newer met first
  3. wait a while
  4. Go back to step 1
// create an encounter manager
ASAPPeer peer = ...;
ASAPEncounterManager asapEncounterManager = new ASAPEncounterManagerImpl(peer);
// create hub manager with encounter manager
ASAPHubManagerImpl hubManagerImpl = new ASAPHubManagerImpl(asapEncounterManager);
// start it
hubManagerImpl.start();
// use interface - clean is cleaner
ASAPHubManager asapASAPHubManager = hubManagerImpl;
// see step 3. Overwrite default (default 600 s = 10 minutes) if you like
asapASAPHubManager.setTimeOutInMillis(maxTimeOutMillis);
// create a hub hubConnector
HubConnector hubConnector = SharedTCPChannelConnectorPeerSide.createTCPHubConnector(host, specificPort);
// add a listener - use same encounter manager object!
NewConnectionListener listener = new YourNewConnectionListener(asapEncounterManager);
// add to hub manager
asapASAPHubManager.addHub(hubConnector);

// connectors to other hubs can be added as well
...
// can be removed
asapASAPHubManager.removeHub(hubConnector);

2. HubConnector with EncounterManager

It's also possible to connect to the hub without using a ASAPHubManager. You can use this approach if you want to connect to a single hub.

Class names in that project had the tendency to become quite lengthy.

HubConnector hubConnector = SharedTCPChannelConnectorPeerSide.createTCPHubConnector(host, specificPort);
NewConnectionListener listener = ...; // you have to implement this listener
hubConnector.addListener(listener);

// tell hub who you are - other peers will find you
hubConnector.connectHub(PEER_ID);
// get list of peer connected to this hub
hubConnector.getPeerIDs();
// get fresh status information from hub, especially peer ids
hubConnector.syncHubInformation();

This code creates HubConnector object and adds a listener. The listener is called when a point-to-point connection to another peer is established. An ASAP encounter should be initiated. We strongly suggest using our EncounterManager. A working implementation of a listener would be very simple:

class YourNewConnectionListener implements NewConnectionListener {
    private final EncounterManager em;
    YourNewConnectionListener(EncounterManager em) { this.em = em; }
    public void notifyPeerConnected(CharSequence targetPeerID, StreamPair streamPair) {
        try {
            this.em.handleEncounter(streamPair, EncounterConnectionType.INTERNET);
        }
        catch(IOException e) { /* write a log */ }
    }
}

Peers connect and disconnect from hub. It would be useful to get a fresh peer list from time to time, create a new connection to peers etc. Good news: You do not have to implement this algorithm but to use ASAPHubManager

3. using a HubConnector with a custom NewConnectionListener

This approach for handling an encounter between peers connected to the hub should only be used if you are using the hub for non-ASAP applications or for testing/debugging purposes. If the notifyPeerConnected method of NewConnectionListener is called a StreamPair object and the peer-id of the target peer is passed to it. The StreamPair provides an InputStream and an OutputStream which can be used for data transfer with the target peer.

Thus, the ASAPHub could be used as a TCP relay server for a wide range of Java applications. The use of a TCP relay server enables peers to establish a connection to each other even if they are behind a NAT, do not have a public IP address or don't want to expose a public TCP-IP port.

This example shows how to use the ASAPHub as a TCP relay server. We are implementing a custom NewConnectionListener class named CustomConnectionListener. This listener is added to our HubConnector.

public class MyApp{
    
    public static void main(String[] args) throws ASAPException, IOException, InterruptedException {
        // initialize HubConnector
        HubConnector hubConnector = SharedTCPChannelConnectorPeerSide.createTCPHubConnector("127.0.0.1", 6000);
        
        // add our custom NewConnectionListener to the HubConnector
        NewConnectionListener connectionListener = new CustomConnectionListener();
        hubConnector.addListener(connectionListener);
        
        // register on relay server with peer-id "alice"
        // if you want to use the hub as a relay server you should set the 'canCreateTCPConnections' parameter to false
         hubConnector.connectHub("alice", false);
        
        // get all peers which are already registered to the Hub
        Collection<CharSequence> peers = hubConnector.getPeerIDs();
        
        // exchange data with target peer bob
        hubConnector.connectPeer("bob");
        /*
        after the connection request was answered by bob the 'notifyPeerConnected' of our 'CustomConnectionListener'
        will be called   
         */
    }

    class CustomConnectionListener implements NewConnectionListener {

        private InputStream is;
        private OutputStream os;
        private String targetPeerId;

        public CustomConnectionListener(...) {
        ...
        }

        @Override
        public void notifyPeerConnected(CharSequence targetPeerID, StreamPair streamPair) {
            os = streamPair.getOutputStream();
            is = streamPair.getInputStream();
            targetPeerId = targetPeerID;
        
        ...
        }

        public InputStream getInputStream(){
            return is;
        }

        public OutputStream getInputStream(){
            return is;
        }

        public String getTargetPeerId(){
            return targetPeerId;
        }
    }
}

Have a look in our test package for further examples.

Clone this wiki locally