Notification Server

Architecture

Revision History
Revision 1.0November 2012FRS
First Edition
Revision 1.1March 2013FRS
Simple API

Table of Contents

1. Introduction
State of the art
Current Internet solutions issues
Service Description
Adventages for developers
2. Mobile network issues with current PUSH platforms
Mobile networks in a Private or Public LAN
Mobile Network. Circuit domain states
Mobile Network. Package domain states
Mobile Network. States relation
Mobile Network. Signalling storms
Mobile Network. Battery comsuption
3. Notification server API
API between WebApp and the User Agent
API between the User Agent and the Notification Server
API between the Application Server and the Notification Server
Generic API
Simple PUSH API
API between the WA and the AS
Tokens
channelID
UAID
endpointURL
WakeUp
status
Wake up method
4. Log traces
I. Command reference
load_mcc_mnc_onmongo.awk — loads a mobile operator list into the central MongoDB
add_wakeupserver_ip — links a wakeup server IP and Port to a MCC-MNC pair
empty_mongo — simple script to clean all MongoDB collections
getloginfo — shows the detailed log trace description

List of Tables

2.1. RCC - GMM relation

List of Examples

3.1. Multiple device messages
3.2. Message broadcast

Today mobile applications retrieve asynchronously information from multiple sites. Developers have two ways to retrieve this information:

  • Polling: Periodically query the information to the server.
  • Push: The server sends the information to the client when the required information is available.

The first method is strongly discouraged due to the large number of connections made to the server needlessly, because information is not available and you lose time and resources.

That is why the PUSH methods are widely used for information retrieval, anyway how PUSH platforms are currently working are misusing mobile radio resources and also consuming lot of battery.

This article aims to explain how to manage this kind of messaging, problems with existing solutions and finally how Telefónica Digital, within the framework of the development of Firefox OS operating system, a new solution designed friendlier to the network and low battery consumption on mobile terminals.

Historically mobile operators offered (and offer) real mechanisms PUSH notifications, also known as WAP PUSH. WAP PUSH can "wake up" applications when any action is required of them by the server side (without interaction from the user). Sending WAP PUSH messages is done in the domain of circuits, the same used for voice and SMS, and that is why the user don't need to establish a data connection. These kind messages work properly out of the box.

WAP PUSH solutions works great when the user is registered in the mobile network, but if you are out of coverage or connected to a WiFi hotspot instead a celular network, you can not receive these messages.

Also, if we add that this messages implies an economic cost (basically it is a short message SMS) the effect is that major smartphone operating systems (Apple iOS and Google Android) have implemented a parallel solution that would work regardless of the mobile network to which the user belongs and it can run smoothly when they are using WiFi networks.

This chapter explains why current solutions are bad for the mobile networks and how we designed this server to solve this issues.

In order to understand the complete problem, we need to introduce you on how the mobile nerworks work at radio level and also how the carriers have their network infrastructure. So, go ahead !

In the 3GPP TS 25.331 specification, we can query all the circuit domain statues of the RRC Layer (Radio Resource Control).

In order to simplify, we only list the third generation (3G) states:

The following scheme represent the different radio states ordered by power comsuption on the device:

In this section we show the relation between RRC and GMM states.

In order to simplify this table, we only consider the handset is only using data channels, so no voice nor SMS (circuit domain) is being used.

Table 2.1. RCC - GMM relation

RCC StateGMM State (2G/3G)Description
RCC StateGMM State (2G/3G)Description
Cell_DCHREADY/PMM_CONNECTED

The handset is transmiting or receiving data information using a dedicated channel or a HSPA shared channel.

Cell_FACHREADY/PMM_CONNECTED

The handset had been transmiting or receiving data some seconds ago and due to inactivity had been moved to the Cell_FACH RCC state.

Also it's possible that the handset is transmiting or receiving small amount of data like pings, keep-alives, cell updates,...

Cell_PCH/URA_PCHREADY/PMM_CONNECTED

The handset had been in Cell_FACH some seconds ago and due to inactivity had been moved to this less resource consume state.

However, the signalling channel is available and is able to change to a data transmission state like FACH or DCH with a little amount of signalling.

Cell_PCH/URA_PCHSTANDBY/PMM_IDLE

The handset is not transmiting nor receiving any amount of data and also the signalling connection is closed.

However the IP address is maintained by the network and associated to this handset.

This is one of the most interesting states since the PDP context is not closed, the IP address is still valid and the handset is not consuming baterry, network traffic,...

As soon as the handset needs to restablish the data channel the radio state will be changed to FACH or DCH.

RRC_IDLESTANDBY/PMM_IDLE

This state is the same as the previous one since the radio state is IDLE.

RRC_IDLEIDLE/PMM_DETACHED

The handset is not transmitting nor receiving anything and also it hasn't any PDP context established, so no IP address is available for this handset.

Normally this state is after 24h of innactivity in the package domain.


The Notification Server API is based on the W3C draft: [http://dvcs.w3.org/hg/push/raw-file/default/index.html]

In order to understand this chapter, we'll present the different actors:

  • WebApp (WA):

    The user's applications which is normally executed on the user device.

  • User Agent (UA):

    Since this protocol born under the Firefox OS umbrella the "operating system" layer is known as the User Agent layer, in our case is the Gecko engine.

  • Notification Server (NS):

    Centralized infrastructure of the notification server platform. This one can be freely deployed by anyone since it's open source: [https://github.com/telefonicaid/notification_server] . The protocol also allows to use any server infrastructure the user wants

  • Application server (AS):

    The WA server side. Normally the applications that runs on a mobile device use one or more Internet servers.

    Some of them will be deployed by the same developer as the client application.

    In our case, this server will be the one which send the notification to his clients/users.

The following sequence diagram shows a tipical message flow between actors:

This API is mainly based on the W3C draft as specified in [http://dvcs.w3.org/hg/push/raw-file/default/index.html]

Also there is more information about Simple PUSH API here: [https://wiki.mozilla.org/WebAPI/SimplePush]

With this API the application is able to register notification channels itself into the Notification Server and recover the public URL to be used as the notification endpointURL by his Application Server (AS).

This API (under the navigator.push object) defines these methods:

  • register
  • unregister
  • registrations

After register the application into the Notification Server, all received notification through the given URL will be delivered to the WA registered channel.

Since the notifications will be received by the UA it's needed a way to notify each application. The current specification is using the new System Messages infrastructure defined in FirefoxOS.

In this case, the application shall register to the "push-notification" event handler:

    
    navigator.mozSetMessageHandler("push", function(msg) {
      alert("New Message with body: " + JSON.stringify(msg));
    });
    
    

Inside the msg you'll receive the pushEndpoint URL so an app can register as many channels as it wants and with this attribute has a chance to differenciate one from another.

The complete example:

      
        var emailEndpoint, imEndpoint;

        // The user has logged in, now's a good time to register the channels
        MyAppFramework.addEventListener('user-login', function() {
          setupAppRegistrations();
        });

        function setupAppRegistrations() {
         // Issue a register() call
         // to register to listen for a notification,
         // you simply call push.register
         // Here, we'll register a channel for "email" updates.
         // Channels can be for anything the app would like to get notifications for.
         var reqEmail = navigator.push.register();
         reqEmail.onsuccess = function(e) {
           emailEndpoint = e.target.result.pushEndpoint;
           storeOnAppServer("email", emailEndpoint); // This is the "Hand wavey" way that the App 
                                                     // sends the endPoint back to the AppServer
         }

         // We'll also register a second channel for "im", because we're social and all about the socialists. Or something.
         var reqIm = navigator.push.register();
         reqIm.onsuccess = function(e) {
           imEndpoint = e.target.result.pushEndpoint;
           storeOnAppServer("im", imEndpoint);
         }
        }

        // Once we've registered, the AppServer can send version pings to the EndPoint.
        // This will trigger a 'push' message to be sent to this handler.
        navigator.mozSetMessageHandler('push', function handlePushMessage(message) {
          if (message.pushEndpoint == emailEndpoint)   // Yay! New Email! Steve and blue can dance!
            getNewEmailMessagesFromAppServer(message.version);
          else if (message.pushEndpoint == imEndpoint) // Yay! An IM awaits. I wonder if it's Sam's IM?
            getNewChatMessagesFromAppServer();
        });

        // to unregister, you simply call..
        AppFramework.addEventListener('user-logout', function() {
          navigator.push.unregister(emailEndpoint);
          navigator.push.unregister(imEndpoint);
        });
      
    

With this API the client device is able to register his applications and itself into the selected notification server.

This API isn't yet standarised, anyway the one explained here is an on working proposal.

The UA-NS API is divided in two transport protocols:

Through this channel the device will register itself, his applications, and also will be used to deliver PUSH notifications

The websocket API supports multiple subprotocols identified each one with it's name:

Also know as "Simple push protocol" and defined by Mozilla and Telefonica.

This protocol is based in the Thialfi protocol . described by Google.

Also you can read more about this protocol in the Mozilla Wiki: [https://wiki.mozilla.org/WebAPI/SimplePush/Protocol] .

In order to use this subprotocol, the "push-notification" string shall be sent into the websocket handsake headers.

All methods sent through this channel will have the same JSON structure:

  
  {
    messageType: "<type of message>",
    ... other data ...
  }
  
  

In which messageType defines one of these commands:

With this method the device is able to register itself.

The device is responsible to give the server a valid UAID. If the provided UAID is not valid or is "null", the server will respond with a valid one.

In next connections the UAID given by the server SHALL be used.

When a device is registering to a notification server, it SHALL send his own valid UAID and also the device can send additional information that can be used to optimize the way the messages will be delivered to this device.

If it's not the first connection, the device can send a list of registered channels in order to syncronize client and server data. This mechanism allows a way to recover channels after a server crash.

    
    {
      messageType: "hello",
      uaid: "<a valid UAToken>",
      channelIDs: [<a list of channels to sync [OPTIONAL]>],
      wakeup_hostport: {
        ip: "<current device IP address>",
        port: "<TCP or UDP port in which the device is waiting for wake up notifications>"
      },
      mobilenetwork: {
        mcc: "<Mobile Country Code>",
        mnc: "<Mobile Network Code>"
      }
    }
    
    

The wakeup_hostport and mobilenetwork optional data will be used by the server to identify if it has the required infrastructure into the user's mobile network in order to send wakeup messages to the IP and port indicated in the wakeup_hostport data so it's able to close the WebSocket channel to reduce signalling and battery consume.

The channelIDs array is sent by the client in order to synchronize server and client.

When the server receives a new hello message and the UAID provided by the client is a valid one (in other words, is the same returned to the client) the channelIDs list will be used to syncronize the server information with the client one.

For example, after a server crash, all client channels will be recovered with this simple method.

Another example, if the client uninstalled an app when the handset was offline, next time it connects will send tne channel list with one less, so the server will unregister this channel.

The server response can be one of these:

      
      {
        messageType: "hello",
        uaid: "<a valid UAID>",
        status: 200
      }
      
      

if it's connected through a permanent websocket, or:

      
      {
        messageType: "hello",
        uaid: "<a valid UAID>",
        status: 201
      }
      
      

if it's connected to a wakeup channel (UDP).

      
      {
        messageType: "hello",
        status: 4xx,
        reason: "<any reason>"
      }
      
      

on any error case, like:

  • 460: Error registering UAID

This method is also used to anounce a new IP address or a network change.

The tokens are an important part of this API since it identifies each (user) actor (device and applications) in a unique or shared way.

This chapter describes each log message, his ID and how to interpret it.

It covers NOTIFY, ERROR and CRITICAL traces. DEBUG and INFO traces are not documented.

Next sections describes each log level:

<xi:include></xi:include><xi:include></xi:include><xi:include></xi:include>

Table of Contents

load_mcc_mnc_onmongo.awk — loads a mobile operator list into the central MongoDB
add_wakeupserver_ip — links a wakeup server IP and Port to a MCC-MNC pair
empty_mongo — simple script to clean all MongoDB collections
getloginfo — shows the detailed log trace description