WebAPI/SimplePush/Protocol: Difference between revisions

Jump to navigation Jump to search
no edit summary
No edit summary
Line 4: Line 4:


'''Everything here applies to Version 1 of the protocol'''.
'''Everything here applies to Version 1 of the protocol'''.
TODO: Possible pain points:
* Versioning
* Sec-WebSocket-Protocol - set to push-notification?


== Purpose ==
== Purpose ==
Line 48: Line 43:
The SimplePush protocol defines how UserAgents and PushServers communicate to ensure reliable delivery of the latest version of a channel from the PushServer to the UserAgent.
The SimplePush protocol defines how UserAgents and PushServers communicate to ensure reliable delivery of the latest version of a channel from the PushServer to the UserAgent.


The SimplePush communication channel is WebSockets, and the wire protocol is JSON, with messages defined below. All messages MUST use TLS (wss:// protocol for WebSockets). In addition, Endpoints generated by PushServer's MUST use HTTPS URLs.
The SimplePush communication channel is WebSockets, and the wire protocol is JSON, with messages defined below.
The WebSocket specific HTTP header <tt>Sec-WebSocket-Protocol</tt> MUST be set to <tt>push-notification</tt> by the UserAgent. The PushServer SHOULD reject the connection if the header is not set. (FIXME: MUST/SHOULD paradox?)
 
All messages MUST use TLS (wss:// protocol for WebSockets). In addition, Endpoints generated by PushServer's MUST use HTTPS URLs.


The PushServer should maintain a mapping of channelIDs and their versions and pushEndpoints.
The PushServer should maintain a mapping of channelIDs and their versions and pushEndpoints.
Line 139: Line 137:


   {
   {
    messageType: “hello”,
  messageType: “hello”,
    uaid: <if not provided by previous call, a new valid one will be generated>
  uaid: <if not provided by previous call, a new valid one will be generated>
   }
   }


Line 163: Line 161:


;channelID string '''REQUIRED'''
;channelID string '''REQUIRED'''
 
:A unique identifier generated by the UserAgent, distinct from any existing channelIDs it has registered. It is RECOMMENDED that this is a UUIDv4 token.


==== PushServer -> UserAgent ====
==== PushServer -> UserAgent ====
Line 174: Line 172:
;status number '''REQUIRED'''
;status number '''REQUIRED'''
: Used to indicate success/failure. MUST be one of:
: Used to indicate success/failure. MUST be one of:
* 200 - OK. Success
* 200 - OK. Success. Idempotent: If the PushServer receives a register for the same channelID from a UserAgent which already has a registration for the channelID, it should still respond with success.
* 409 - Conflict. The chosen ChannelID is already in use and not associated with this UserAgent. UserAgent SHOULD retry with a new ChannelID as soon as possible.
* 409 - Conflict. The chosen ChannelID is already in use and NOT associated with this UserAgent. UserAgent SHOULD retry with a new ChannelID as soon as possible.
* 500 - Internal server error. Database out of space or offline. Disk space full or whatever other reason due to which the PushServer could not grant this registration. UserAgent SHOULD avoid retrying immediately.
* 500 - Internal server error. Database out of space or offline. Disk space full or whatever other reason due to which the PushServer could not grant this registration. UserAgent SHOULD avoid retrying immediately.


Line 182: Line 180:


=== Unregister ===
=== Unregister ===
TODO: Put in stuff about recommendation that client delete its DB entry before
contacting the server.  Unregistration is really a local operation. The
unregister call is only a clean way of notifying the server that a client is no
longer interested in a channelID. Even if the PushServer responds with an error
it makes no difference to the UserAgent, since as long as the app notifies the AppServer,
this channelID won't be used.
==== UserAgent -> PushServer ====


:messageType = "unregister"
:messageType = "unregister"


;channelID string '''REQUIRED'''
;channelID string '''REQUIRED'''
: This is sort of obvious isn't it? :)
==== PushServer -> UserAgent ====
:messageType = "unregister"
;channelID string '''REQUIRED'''
:This MUST be the same as the channelID sent by the UserAgent in the unregister request that this message is a response to.
;status number '''REQUIRED'''
: Used to indicate success/failure. MUST be one of:
* 200 - OK. Success. Idempotent: If the PushServer receives a register for a non-existent channelID it should respond with success. If the channelID is associated with a DIFFERENT UAID, it MUST NOT delete the channelID, but still MUST respond with success to this UserAgent.
* 500 - Internal server error. Database offline or whatever other reason due to which the PushServer could not grant this unregistration. UserAgent SHOULD avoid retrying immediately.


=== Notification ===
=== Notification ===
Line 199: Line 219:
In environments or devices where maintaining an always alive WebSocket is difficult, UserAgents and PushServer's MAY implement alternative means to notify UserAgents about updates. This out of band notification SHOULD be restricted to request the UserAgent to establish the WebSocket. SimplePush state SHOULD NOT be transmitted out of band, since reliable delivery may not be guaranteed.
In environments or devices where maintaining an always alive WebSocket is difficult, UserAgents and PushServer's MAY implement alternative means to notify UserAgents about updates. This out of band notification SHOULD be restricted to request the UserAgent to establish the WebSocket. SimplePush state SHOULD NOT be transmitted out of band, since reliable delivery may not be guaranteed.


API Push Client - Push Server
---
 
This should be considered a translation to WebSockets of the API defined here - https://wiki.mozilla.org/WebAPI/SimplePush/ServerAPI
Status/Error codes documented in that document apply here unless explicitly marked otherwise.
 
Push API endpoint for WebSocket connection is : wss://push.server.com/v1/
 
C->S:
            {
      messageType: "hello",
        uaid: "<a valid UAID>",
channelIDs: [channelID1, channelID2, …],
        interface: {
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>"
},
protocol: <wakeup protocol. OPTIONAL. By default: UDP>
    }
 
uaid can be null, then, a new uaid is created (see next)
S->C:
 
{
messageType: “hello”,
status: xxx, <200, ...>,
uaid: <if not provided by previous call, a new valid one will be generated>
}
 
NOTE: All pending registration/unregistration requests stay on ‘hold’ until the client has transmitted new state and the server has concurred.
 
Recovery protocol
 
 
The client “hello” contains the “uaid” field. If the “uaid” field is known by the server, the server should check that the list of channelIDs sent by the client matches what it has. If there is even a single channelID that the server does not know about, it should generate a new UAID for the client, and drop all state about the current UAID. This will cause the client to generate new channelIDs by waking up all apps and having them register. This way apps get latest state since they contact their server.
 
If the server has ‘extra’ channelIDs associated with the UAID, it can simply delete them.
Channel Registration:
 
A client channel registration request:
  {
      messageType: "register",
channelID: "<ChannelID>
    }
   
The server response can be:
     
{
messageType: “register”,
status: xxx,
pushEndpoint: <pushendpoint>,
channelID: <channelId>
}
 
 
 
Channel Deletion:
 
{
      messageType: "unregister",
      channelID: <channelId>
    }
 
The server response can be:
     
{
      messageType: "unregister",
status: xxx,
      channelID: <channelId>
    }


Channel Update:
Channel Update:
Line 322: Line 268:




https://server:port/notify/<hashed channelID>
[endpoint]


Method PUT
Method PUT
Line 328: Line 274:


body=<any text>[&ttl=<ttl>]
body=<any text>[&ttl=<ttl>]
GROUPS MANAGEMENT [WIP]
https://server:port/groups
CRUD API:
C: POST
https://server:port/groups
Returns URL (pushEndpoint)
R: GET
https://pushEndpoint
Returns:
[endPointURL1, endPointURL2, …]
U: PUT
https://pushEndpoint
url=endPointURLN&op=[ADD|DELETE]
Returns:
200 OK or 404 No group found
D: DELETE
https://pushEndpoint
Removes the group
Returns:
200 OK or 404 No group found
WAKEUP API [WIP]
This (WIP) API will be offered by the carriers in order to be able to wakeup handsets inside their own mobile networks.
Connection to this API will be protected with client certificates signed by the carrier so only trusted 3rd. party notification servers will be able to send datagrams to the handsets.
https://server:port/wakeup
GET
mcc=<mcc>&mnc=<mnc>
RETURNS
200 OK (We’ve a wake up server in that network !)
404 Error (We don’t have a wake up server)
PUT
ip=<ip>&port=<port>&mcc=<mcc>&mnc=<mnc>
RETURNS
200 OK


Channel Update:
Channel Update:
Line 397: Line 287:
updates: [{"channelID": "version", _internal_id: ..., "body": "body"}, ...]
updates: [{"channelID": "version", _internal_id: ..., "body": "body"}, ...]
     }
     }
Return Status codes
WIP: https://github.com/telefonicaid/notification_server/blob/mozAPI/src/common/constants.js
nikhil: I think you’ll just want to use the ones from the mozilla spec that are required, like 404 and so on. Most of the other status codes are not required in my opinion.
Confirmed users
93

edits

Navigation menu