[SIP Beyond VoIP] New Sylk Pushserver version 1.0.0

Adrian Georgescu ag at ag-projects.com
Wed Jun 17 17:30:01 CEST 2020


# Sylk Pushserver

Sylk Pushserver was designed to act as a central dispatcher for mobile push
notifications inside RTC provider infrastructures.  Both the provider and
the mobile application customer, in the case of a shared infrastructure, can
easily audit problems related to the processing of push notifications.

Author: Bibiana Rivadeneira <bibo at ag-projects.com>

## License

Sylk Pushserver is licensed under GNU General Public License version 3.  
[Copy of the license](http://www.fsf.org/licensing/licenses/gpl-3.0.html)

## Deployment scenarios

Sylk Pushserver can be deployed together with WebRTC server applications or
VoIP servers like SIP Proxies and PBXs.  Its main purpose is to act as a
central entity inside RTC provider infrastructures.  Without such a
component, the same functionality must be built inside multiple servers and
as the number of mobile applications increases, the need for such central
component becomes obvious.

### Integration examples

 * OpenSIPS: **config/opensips.cfg**
 * SylkServer: built-in support

## Design

Sylk Pushserver can handle an arbitrary number of different combinations of
push notification service and mobile applications.  It and can be extended
by using Python programming language to support new push notification
services and applications.  Sample applications are provided to handle Sylk
and Linphone mobile applications for Apple and Firebase push notification
services.

For each configured Apple application, the server maintains a persistent
connection by using HTTP/2 over TLS 1.2 and reuses that connection for
sending notifications related to the application.  Latest voip functionality
for iOS 13 or later is also suported.

Each outgoing connection can use its own set of credentials, X.509
certificates and urls.  The connection failures are properly handled and
incoming requests remained queued for later by using a timer dependent on
the payload type.

### Logging

All incoming and outgoing requests, including HTTP headers and bodies, can
be logged for troubleshooting purposes in the system journal and in a
separate log file.  These logs can easily be correlated with the logs from
the server that generated the request by using the call-id key.

Remote HTTP logging of the results is possible so that one or more
third-parties can receive information about the individual push requests and
responses for each application.

## API

Sylk Pushserver expects a json over HTTP POST requests and translates it
into a correspondent outgoing push notifications request to Apple Push
Notifications or Firebase FCM servers.

Json object structure:

```{
'app-id': 'com.agprojects.sylk-ios', 
'platform': 'apple', 
'token': '6688-71a883fe', 
'device-id': 'accc8375125582aae062353', 
'call-id': '4dbe8-7a53-42bd-95f3-9a7d43938', 
'from': 'alice at example.com', 
'from_display_name': 'Alice',
'to': 'bob at biloxi.com', 
'media-type':'audio', 
'event': 'incoming_session'
'silent': True
}
```

Where:
 
* `app-id: str`,  id provided by the mobile application (e.g. mobile bundle ID) 
* `platform: str`,  'firebase', 'android', 'apple' or 'ios' 
* `token: str`,  destination device token,
    * *iOS device tokens* are strings with 64 hexadecimal symbols
    * *Android device push tokens* can differ in length`.
* `device-id: str`,  the device that generated the token 
* `call-id: str`,  the unique session id for each call 
* `from: str`,  address of the caller 
* `from_display_name`, (mandatory)*, display name of the caller 
* `to`,  address of the callee 
* `media-type: str`:  'audio', 'video', 'chat', 'sms' or 'file-transfer' 
* `silent: bool`: *(optional, default `True`)* True for silent notification 
* `event: str`,  type of event:
    * For *Sylk app*  must be 'incoming_session', 'incoming_conference' or 'cancel'
    * For *Linphone app*  must be 'incoming_session'

The response is a json with the following structure:

```{ 
'code': 'a numeric code equal to the HTTP response code',
'description': 'a detailed text description',
'data' : {}
}
```

*data* contains an arbitrary dictionary with a structure depending on the
request type and the remote server response.

### Sample client code

See *scripts/sylk-pushclient*

### External APIs

For documentation related to the API used by Apple and Firebase push
notifications services you must consult their respective websites.  For
reference, the following APIs were used for developing the server, but these
links may change:

 * [Sending Apple VoIp notifications](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns)
 * [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging)


## Installation

### As a Debian package (Buster 10)

Install the AG Projects debian software signing key:

wget http://download.ag-projects.com/agp-debian-gpg.key 

sudo apt-key add agp-debian-gpg.key

Add these repository matching your distribution to /etc/apt/sources.list:

http://projects.ag-projects.com/projects/documentation/wiki/Repositories

Update the list of available packages:

sudo apt-get update

sudo apt-get install sylk-pushserver

### From source

The source code is managed using darcs version control tool. The darcs
repository can be fetched with:

darcs clone http://devel.ag-projects.com/repositories/sylk-pushserver

Alternatively, one can download a tar archive from:

http://download.ag-projects.com/SylkPushserver/

Install Python dependencies:

`pip3 install -r requirements.txt`

`python3 setup.py install`

### Building Debian package

Install building dependencies:

```
sudo apt install dh-virtualenv debhelper libsystemd-dev dh-python python3-dev python3-setuptools python3-pip
```

Build the package:

```
python setup.py sdist
cd dist
tar zxvf *.tar.gz
cd sylk_pushserver-?.?.?
debuild
```

To install the debian package manually:

```
sudo dpkg -i sylk-pushserver_1.0.0_all.deb
sudo apt --fix-broken install
```

## Configuration

There are two configurations files.

 * general.ini

Contains the general server settings.

 * applications.ini

Contains the settings for each mobile application, *see
config/applications.ini.sample*.  Chages to this file cause the server to
autamtically reload it, there is no need to restart the server.

## Remote logging

Remote logging is done using a POST request over HTTP with a json containg
both the original request and the final response of the push notification.

```{
'request': push_request, 
'response': push_response
}
```

Where :

 * push_request is the original json payload received by this server
 * push_response is a json with the following format:

```{
'code': code,                # http response code from PNS
'description': description,  # detail description of the response from the PNS
'push_url': push_url,        # the final URL of the outgoing push notification
'incoming_body': {...},      # the original request body received by the server
'outgoing_headers': {...}.   # the outgoing request headers sent to the PNS
'outgoing_body': {...}       # the outgoing request body sent to the PNS
}
```

The returned result should be a json with a consistent key.  The key can be
defined in the application.ini for each application.  If the key is set then
its value will be logged which can make troubleshooting easier.

## Custom applications

Custom applications can be written in Python by subclassing existing template classes.

Define the directory for custom applications in `general.ini` file:

 `extra_applications_dir` = `/etc/sylk-pushserver/applications`

Copy config/applications/myapp.py to the extra_applications_dir and
overwrite its functions.

In `applications.ini` file set app_type for the custom applications:

```
`app_type` = *myapp* 
```

## Custom Push services

Custom PNS can be written in Python by subclassing existing template classes.

Define the directory for custom push services in `general.ini` file:

 `extra_pns_dir` = `/etc/sylk-pushserver/pns`

Copy config/pns/mypns.py to the extra_pns dir and overwrite its classes.

In `applications.ini` file set app_type for the custom applications:

```
`app_platform` = *mypns* 
```

## Running the server

### From the source code

`./sylk-pushserver --config_dir <path-to-config-directory>`

If the config_dir directory is not specified, the following paths are searched for:

  * /etc/sylk-pushserver
  *./config

For more command line options use -h.

### Debian package

```
sudo systemctl start sylk-pushserver
```

### Testing

For testing the server scripts/sylk-pushclient can be used.

## Compatibility

The server is developed in Python 3 and was tested on Debian Buster 10.

## Reporting bugs

You may report bugs to [SIP Beyond VoIP mailing list](http://lists.ag-projects.com/pipermail/sipbeyondvoip/)




More information about the SIPBeyondVoIP mailing list