Class: ThaliNotificationClient

thaliNotificationClient~ThaliNotificationClient

new ThaliNotificationClient(thaliPeerPool, ecdhForLocalDevice, addressBookCallback)

Creates a class that can register to receive the module:thaliMobile.event:peerAvailabilityChanged event. It will listen for the event and upon receiving it, will enqueue an action with the submitted thaliPeerPool. Once called back by the pool then the callback will issue a HTTP GET request to retrieve the notification beacons for the peer, parse them, see if one matches and if so then fire a module:thaliNotificationClient.event:peerAdvertisesDataForUs. Callers can listen for the event by using the emitter member.

Parameters:
Name Type Description
thaliPeerPool module:thaliPeerPoolInterface~ThaliPeerPoolInterface

Requests to retrieve notification beacons are enqueued on this object in order to make sure we don't overwhelm our bandwidth or native communication capabilities.

ecdhForLocalDevice Crypto.ECDH

A Crypto.ECDH object initialized with the local device's public and private keys.

addressBookCallback addressBookCallback

An object used to validate which peers we are interested in talking to.

Source:
Fires:

Members

(static, readonly) ACTION_TYPE :string

This is the action type that will be used by instances of this class when registering with module:thaliPeerPoolInterface~ThaliPeerPoolInterface.

Type:
  • string
Source:

peerDictionary :ThaliNotificationClient.PeerDictionary

A dictionary used to track the state of peers we have received notifications about from module:thaliMobile.

Type:
  • ThaliNotificationClient.PeerDictionary
Source:

Methods

start()

This method will cause a listener to be registered on the global singleton module:thaliMobile object for the module:thaliMobile.event:peerAvailabilityChanged event.

This method MUST be idempotent so calling it twice in a row MUST NOT cause multiple listeners to be registered with thaliMobile.

Handling peerAvailabilityChanged Events

The notification code is triggered via peerAvailabilityChanged events. In handling these events remember that our goal is to find the notification beacons associated with each peerIdentifier. Once we have retrieved the beacons for a specific peerIdentifier we don't ever need to deal with that specific peerIdentifier again. If the peer behind the identifier changes their beacons then we will get a new peerIdentifier.

  • If hostAddress != null
    • If this peer is not in the dictionary
    • If this peer is in the table
      • If this peer has been marked as RESOLVED
        • Ignore the event
      • If this peer has been marked as CONTROLLED_BY_POOL and the action's state is QUEUED or if the peer's state is WAITING
        • First update the connection dictionary for the peer's entry with the new data. Then if the connectionType of the new event is TCP_NATIVE and if the connectionType of the existing action isn't that then kill the existing action using module:thaliPeerPoolInterface~ThaliPeerPoolInterface#kill and create a new action and enqueue it and update the entry. The point of this exercise is that we prefer native TCP transport to other options.
      • If this peer has been marked as CONTROLLED_BY_POOL and the action's state is STARTED
        • If the connectionType of the event is different than the connectionType of the action then just update the peerConnectionDictionary and move on. If the connectionTypes are identical then kill the existing action as above. If the peerConnectionDictionary contains a TCP_NATIVE entry then create and enqueue an action for that. Otherwise take the entry that was just updated and create and enqueue that as an action.
  • If hostAddress == null
    • If this peer is not in the table
      • This is technically possible in a number of cases. If this happens then just ignore the event.
    • If this peer is in the table
      • If this peer has been marked as resolved
        • Ignore the event.
      • If this peer has been marked as CONTROLLED_BY_POOL and the action's state is QUEUED or if the peer's state is WAITING or if this peer has been marked as CONTROLLED_BY_POOL and the action's state is STARTED
        • Call kill on the action via module:thaliPeerPoolInterface~ThaliPeerPoolInterface#kill and remove the associated entry in peerConnectionDictionary. If this leaves no entries in peerConnectionDictionary then remove this table entry in total from the dictionary. If there is still an entry left then create a notificationAction for it and enqueue it.

Handling Resolved events from notificationActions

When creating a notificationAction a listener MUST be placed on that action to listen for the module:thaliNotificationAction~NotificationAction.event:Resolved event.

  • BEACONS_RETRIEVED_AND_PARSED
  • BEACONS_RETRIEVED_BUT_BAD
    • This indicates a malfunctioning peer. We need to assume they are bad all up and mark their entry as RESOLVED without taking any further action. This means we will ignore this peerIdentifier in the future.
  • HTTP_BAD_RESPONSE
    • This tells us that the peer is there but not in good shape. But we will give them the benefit of the doubt. We will wait 100 ms if we are in the foreground and 500 ms if we are in the background (the later only applies to Android) and then create a new action (remember, prefer TCP_NATIVE) and then enqueue it. Make sure to set the dictionary entry's state to WAITING and when the timer is up and we enqueue to CONTROLLED_BY_POOL.
  • NETWORK_problem
    • Treat the same as HTTP_BAD_RESPONSE
  • KILLED
    • We MUST check the value of the notificationAction on the associated dictionary entry with the notificationAction that this handler was created on. If they are different then this means that this class was the one who called kill and so we can ignore this event. If they are the same then it means that the ThaliPeerPoolInterface called kill (due to resource exhaustion). Having the pool kill us is a pretty extreme event, it means we have so many peerIdentifiers that we blew up the pool. So at that point the best thing for us to do is to just delete the entire entry for this peerIdentifier and move on.
Source:

stop()

Will remove the listener registered on the global thaliMobile object, if any. This method MUST be idempotent so calling it multiple times MUST only cause a single call to removeListener on thaliMobile and only then if there already was a call to addListener on this object.

Removing the listener MUST not just stop listening for the event but MUST also cause all non-resolved entries in the dictionary to either stop waiting or if under control of the pool to be killed and then their entries MUST be removed from the peer dictionary.

Source: