| src | Fix keeping status items | |
| .gitignore | Initial commit | |
| Dockerfile | Initial commit | |
| package-lock.json | Update dependencies | |
| package.json | Update dependencies | |
| Readme.md | Fix link to socket.io | |
| tsconfig.json | Initial commit | |
| tslint.json | Initial commit | |
Communication Server
A silly backend which saves and delivers messages
Device IDs
Every device can generate a id by itself and use it.
A device id must match the pattern ^[a-zA-Z0-9+/=]{24}$.
Device authentication
Every device can chose an authentication token by itself and use it. The token is a string which muste have at least 32 chars.
The authentication token is set when a device connects the first time. Due to the automated deletion of old data, a new device can take an existing device id and set a new token when the old device has not connected for 4 weeks.
Messages
A message is a piece of data which can be sent from one device to an other device. It has the following fields at the database:
- senderDeviceId
- messageId
- receiverDeviceId
- sequenceId
- content
- time
As soon as the receiver confirms the delivery by adding the message id to
receivedMessageIds in a sync request, the message is removed from the server.
Message Content
The message content must match the pattern /^[a-zA-Z0-9+/=]*$/.
Sequence IDs
To prevent duplicate messages, every message gets a number. The sequence id can be any number starting 0.
If a device sends a message whose sequence id is smaller or equal to a previous message sent by this device, than the new message will be ignored.
The sender device can see which messages are not yet delivered in the
pendingSentMessageSequenceIds response field.
Messages are deleted if they were not delivered within one week.
The deletion without delivery removes the sequence id from the
pendingSentMessageSequenceIds response field too.
Statuses
A status is a piece of data which can be sent from one device. One status can be sent to multiple devices. A status must be sent to at least one device.
A status has got the following fields at the database:
- senderDeviceId
- statusId
- content
- time
- receiverDeviceIds
Status ID
The status id must match the pattern /^[a-zA-Z0-9]{10}$/.
Status Content
The status content must match the pattern /^[a-zA-Z0-9+/=]*$/.
Sending
To send/ keep a status, it must be added to the
putStatus request field.
If a status is not in the putStatus anymore, then it's considered old and is deleted.
If newContent is not set for a status, then it's assumed that the content is equal to the previous content of this status. If newContent is not set and there is no previous content,
then the status id is added to missingStatusContent .
Receiving
Status changes are reported using the response field statusUpdates.
For caching, the client can set the receivedStatus field to specify the statuses he received.
Then only updates are reported using the response field statusUpdates.
if the content of a status update is not set, then the status
which is contained in receivedStatus does not exist anymore.
Privacy
- anyone can take any unused device id
- the sender of a message knows when the message was delivered
- anyone can send messages to anyone
- messages and status updates contain timestamps
Resulting recommendations:
- input validation
- input validation
- input validation
- encrypting and signing the data
- generating device ids randomly
- keeping device ids private
Scaling
Using multiple instances of this server application with the same database breaks the change notifications.
API
There is exactly one endpoint: /sync.
The requests and responses use JSON.
They are described here and here.
Notifications/ Push
To allow a fast message delivery, it's possible to suscribe for changes using socket.io. To use that:
- connect to the server with a socket.io client
- after connecting, emit ('subscribe', deviceId, authToken, confirmationListener) where confirmationListener is a function
- wait for the event 'changes'
- the change event has got one parameter of the type object with these properties:
- messages (boolean, true if and only if there is a new message for this device)
- status (boolean, true if and only if the status messages sent to this device were changed)
- deliveredMessages (boolean, true if and only if messages sent from this device were delivered)
The notifications are not triggered when deleting old data.
Deletion of old data
- device registrations (last activity timestamp, auth token) are deleted after 4 weeks without activity
- messages are deleted after 1 week if they were not delivered
- statuses are deleted if the sender didn't do any sync for 1 week
Usage
- install the dependencies with
npm install - build it with
npm run build - eventually set environment variables
- PORT (the listening port for the http server)
- DATABASE_URL (the url of the database which should be used)
- start it with
npm start
License
Copyright (C) 2019 Jonas Lochmann
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.