Compare commits

...
789 Commits
Author SHA1 Message Date
Evgeny Poberezkin f5e666ae4f 6.0.4.0 2024-09-11 18:51:26 +01:00
Evgeny Poberezkin 62133ceb24 Revert "xrcp: use SHA3-256 in hybrid key agreement (#1302)"
This reverts commit 67d38090ed.
2024-09-11 18:45:44 +01:00
Evgeny 3b50e1fb7d ntf server: only use SOCKS proxy for servers without public address (#1314) 2024-09-11 18:41:40 +01:00
Evgeny 7c25b3b1e0 smp protocol: send DELD when subscribed queue is deleted (#1312)
* smp protocol: send DELD when subscribed queue is deleted

* fix, test

* refactor

* send DELD event only if the client supports it (version 10); send END otherwise

* fix test

* notify on notifier rotation

* increase test delays
2024-09-11 13:16:51 +01:00
Evgeny a70bd02c67 xftp server: round down file creation time to 1 hour (#1310) 2024-09-10 08:14:05 +01:00
Evgeny 990dcec348 smp server: add created/updated/used date to queues to manage expiration (#1306)
* smp server: add created/updated/used date to queues to manage expiration, all: make Map updates strict in value

* remove strict

* remove time precision

* diff

* style

* only update when time changed
2024-09-09 14:53:11 +01:00
Evgeny 75712641ee rfc: stabilize iOS notifications (#1221) 2024-09-09 17:07:32 +04:00
spaced4ndy 946e16339e agent: process last notification from list (#1307) 2024-09-09 16:42:14 +04:00
spaced4ndy 092ed088ca ntf: support for multiple messages encoding (#1305) 2024-09-09 16:03:17 +04:00
Evgeny dab1980d79 xftp: report receive file error with redirected file ID, when redirect is present (#1304)
* xftp: report receive file error with redirected file ID, when redirect is present

* fix test
2024-09-09 08:08:16 +01:00
Evgeny 344a295845 agent: error when user record is not in database (#1303) 2024-09-08 16:50:22 +01:00
Evgeny 67d38090ed xrcp: use SHA3-256 in hybrid key agreement (#1302) 2024-09-08 15:45:45 +01:00
Evgeny a9e8d02593 server: bind control port server only to 127.0.0.1 for better security (in case of firewall misconfuguration) (#1280) 2024-09-05 13:48:09 +01:00
Evgeny d859f27999 ntf server: remove debug logging (#1284) 2024-09-05 13:26:34 +01:00
Evgeny e86338d555 smp server: fewer map updates on re-subscriptions (#1297)
* smp server: fewer map updates on re-subscriptions

* temp version

* replace Client with ClientId in queues

* version

* version

* comments

* reduce threads when sending ENDs

* revert version
2024-09-05 13:25:41 +01:00
Evgeny 137ebc1cad servers: reduce memory used for period stats (#1298) 2024-09-02 23:12:08 +01:00
Evgeny d84a49b85a smp server: split and reduce STM transactions (#1294) 2024-09-02 17:06:31 +01:00
Evgeny d5efe3406a agent: fix race when sending a message to the deleted connection (#1296) 2024-09-02 15:07:16 +01:00
Evgeny Poberezkin d559a66145 6.0.3.0 2024-08-30 12:55:17 +01:00
Evgeny ce6777b68d newtype for server entity IDs, fix TRcvQueues (#1290)
* put DRG state to IORef, split STM transaction of sending notification (#1288)

* put DRG state to IORef, split STM transaction of sending notification

* remove comment

* remove comment

* add comment

* revert version

* newtype for server entity IDs, fix TRcvQueues

* Revert "put DRG state to IORef, split STM transaction of sending notification (#1288)"

This reverts commit 517933d189.

* logServer
2024-08-30 12:50:02 +01:00
Evgeny 655e7ad7d5 smp server: get message queue faster, avoiding STM contention if queue exists, split transaction for notification delivery (#1289)
* put DRG state to IORef, split STM transaction of sending notification (#1288)

* put DRG state to IORef, split STM transaction of sending notification

* remove comment

* remove comment

* add comment

* revert version

* smp server: get message queue faster, avoiding STM contention if queue exists

* IORef for counter

* Revert "put DRG state to IORef, split STM transaction of sending notification (#1288)"

This reverts commit 517933d189.

* version

* remove IORef

* split notification delivery transations

* revert version
2024-08-30 11:53:22 +01:00
Evgeny 9596a03139 servers: reduce STM transactions (#1287)
* servers: reduce STM transactions

* switch stats and pending ENDs to IORef

* more IORef, split pending ENDs to use in one thread
2024-08-29 13:18:12 +01:00
Evgeny 2e7e476f81 smp server: remove "expensive" stats (#1285) 2024-08-28 18:20:44 +01:00
Evgeny 2c9ad74599 smp server: batch END responses when subscribed client switches (version 2) (#1283)
* fix incorrect entity ID for notification subscription END when queue is deleted

* throttle sending ENDs

* fix stats

* clean up
2024-08-28 10:14:41 +01:00
Evgeny Poberezkin aa60bd6770 use strict Maps, fix stats for sent END batches 2024-08-26 19:35:57 +01:00
Evgeny 16cf5c8628 smp server: stats for END events and for SUB/DEL event batches (#1281)
* smp server: count queued and sent END events

* fix

* shadowing

* stats for batches

* fix
2024-08-26 14:58:18 +01:00
Evgeny Poberezkin 56986f82c8 6.0.2.0 2024-08-24 14:54:32 +01:00
Evgeny 53e829a21c agent: store query errors, reduce slow query threshold to 1ms (#1277)
* agent: collect query errors stats

* simplify

* test

* use microseconds

* parens

* revert change to track all queries, reduce threshold to 1 ms
2024-08-24 14:51:26 +01:00
Evgeny ab4acadcc1 agent: fix stuck connection commands when server is not responding (#1276)
* agent: fix stuck connection commands when server is not responding

* fix

* rename

* test SKEY retry
2024-08-24 13:54:20 +01:00
Evgeny 325e679bc4 ntf server: reduce PING interval to 1 minute, only mark subscriptions with END if it is received by the currently active client (#1275) 2024-08-24 11:34:59 +01:00
Evgeny Poberezkin d81cae712e Merge branch 'master' into stable 2024-08-23 14:41:15 +01:00
Evgeny Poberezkin 1d22608f86 6.0.1.0 2024-08-20 18:46:42 +01:00
Evgeny 39f3cf3082 agent: only create notification subscriptions to connections without errors or with temporary errors (#1270) 2024-08-20 16:05:50 +01:00
sh 5be81c562f scripts: update install/update (#1271) 2024-08-20 15:57:29 +01:00
Evgeny 2bdda1ff1f servers: safe compacting of store logs (#1269)
* servers: safe compacting of store logs

* fix
2024-08-20 13:36:37 +01:00
Evgeny ac930dff30 smp server: possible race when creating client that might lead to memory leak (#1260) 2024-08-20 12:25:58 +01:00
DiogoandEvgeny Poberezkin 1cbf8c0015 agent: support changing user of the new connection (#1267)
* agent: support new connection user id update

* another way for assertion

* add more tests to setConnUserId

* remove fdescribes

* allow rcv connection to change user id

* add functional test to api

* remove fdescribe

* refactor

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-08-20 10:57:09 +01:00
Evgeny 571d148bdf agent: do not start delivery workers when there are no messages to deliver (#1263)
* agent: use weak ThreadId and forkIO in workers instead of async (reduce memory)

* agent: do not start and exit delivery workers when there are no messages to deliver (#1264)

* agent: exit delivery workers when no messages to deliver

* only start delivery workers when there are pending messages

* fix

* focus test

* enable all tests

* lift

* do not exit workers when there is no work
2024-08-18 21:30:06 +01:00
Evgeny 32a150eb40 agent: enable notifications for all connections (#1262) 2024-08-18 14:07:09 +01:00
EvgenyandAlexander Bondarenko 5ad6e5f2f3 deps: upgrade tls to 1.9 (#1265)
* deps: use tls-2.0

* roll back RCP "cleanup"

* use tls 1.9

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
2024-08-18 13:55:12 +01:00
Evgeny f229e135e3 agent: reduce subscription transactions (#1259)
* agent: reduce subscription transactions

* nub

* remove commented
2024-08-16 10:06:22 +01:00
Evgeny Poberezkin d15d87c111 Merge branch 'master' into stable 2024-08-11 18:06:11 +01:00
Evgeny Poberezkin 0dd52dc69f v6.0.0 (6.0.0.8) 2024-08-09 23:09:09 +01:00
Evgeny 47dd0c4c64 agent: do not send worker crash errors when agent is not active (stopped) (#1256) 2024-08-09 21:10:27 +01:00
Evgeny 7762b4d364 reduce the number of STM transactions (#1255)
* reduce the number of STM transactions

* reduce STM more

* refactor

* remove more
2024-08-09 16:38:46 +01:00
Evgeny Poberezkin 7d8457263b 6.0.0.7 2024-08-08 13:15:01 +01:00
Evgeny fc6b9c0e1b agent: stop statistics and cleanup when chat is stopped (#1251) 2024-08-07 13:14:09 +01:00
Evgeny Poberezkin a76e15fd77 6.0.0.6 2024-08-06 12:39:11 +01:00
Evgeny a017047c52 smp server: fix race when client is marked as subscribed after it is disconnected, preventing its GC (#1250)
* smp server: fix race when client is marked as subscribed after it is disconnected, preventing its GC

* refactor
2024-08-06 08:17:38 +01:00
Evgeny f4d1a33ed8 agent: retry loop that resumes subscriptions as soon as agent is moved to foreground, suspend retry loops while agent is suspended (#1249)
* agent: retry loop that resumes subscriptions as soon as agent is moved to foreground, suspend retry loops while agent is suspended

* reset retry enterval when moving to foreground

* account for network state too

* simplify

* typo

* simplify
2024-08-05 15:09:46 +01:00
Evgeny Poberezkin 03ea151be5 agent: support additional messages for connection in message batches (#1247)
* agent: support additional messages for connection in message batches

* fix, test

* test 2 connections

* use TVar instead of TMVar for GHC 8.10.7
2024-07-30 17:12:29 +01:00
Evgeny Poberezkin 83f8622b23 6.0.0.5 2024-07-29 21:02:22 +01:00
Evgeny Poberezkin 3753379ae4 agent: support dababase access with high priority for more responsive user actions (#1248)
* agent: support dababase access with high priority for more responsive user actions

* rename, export

* fix
2024-07-29 18:57:16 +01:00
Evgeny Poberezkin 2de16cfae8 6.0.0.4 2024-07-28 15:03:32 +01:00
Evgeny Poberezkinandspaced4ndy 5fa3c149e9 smp server: fix server-info, additional stats, allow expiring inactive clients which have prohibit subscriptions only (iOS NSE clients) (#1237)
* smp server: fix server-info

* fix

* faster saving messages

* remove comment

* move ProhibitSub out of TVar

* subscription stats

* stabilize test

* order

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* more notification stats

* count ntf stats

* update server-info

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-07-25 16:06:40 +01:00
Evgeny Poberezkin 9093c7b120 agent, ntf server: only mark subscriptions as pending that were created by the disconnected client (#1242)
* ntf server: only mark subscriptions as pending if the disconnected client is current

* add sessionId to subscribed queue

* add sessionId to subscriptions in ntf server agent

* fix
2024-07-25 13:07:28 +01:00
Evgeny Poberezkin 47ae921b86 use strict Map (#1241) 2024-07-23 08:27:54 +01:00
spaced4ndyandEvgeny Poberezkin c605156302 agent: getAgentSubsTotal api (#1238)
* agent: getAgentSubsTotal api

* move

* export

* count sessions

* simplify

* simplify 2

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-07-22 15:43:38 +01:00
Evgeny Poberezkin 051bf38bc7 agent: remove delays in notification processing, add notification stats (#1235)
* agent: remove delays in notification processing, add notification stats

* do not replace token after failed check

* more stats

* refactor

* fix

* backwards compatible JSON parsing

* retry deleting subscription on temporary error

* remove attempts to get multiple notification messages

* fix JSON decoding to be backwards compatible
2024-07-22 15:42:34 +01:00
Evgeny Poberezkin 8423c636a8 rename queueId to entId (can be message queue, proxied session and data blob ID to be added) (#1240) 2024-07-22 12:01:38 +01:00
Evgeny Poberezkin cc5732f41f smp server: stats for commands retrieving messages when notifications are received (#1236)
* more stats

* fix stats
2024-07-20 14:10:10 +01:00
spaced4ndy 7565ddd91c agent: initialize ratchet on processing confirmation to support decryption of messages received before allowConnection; return SndQueueSecured from joinConnection, acceptContact (#1233) 2024-07-18 19:54:14 +04:00
Evgeny Poberezkin 0de596dbcf 6.0.0.3 2024-07-18 11:05:53 +01:00
Evgeny Poberezkin e59a098e66 smp server: remove subscriptions from the clients when queues are deleted (#1234)
* smp server: remove subscriptions from the clients when queues are deleted

* remove ntf subscriptions, update stats

* add GET stats
2024-07-18 10:59:48 +01:00
Evgeny Poberezkin 8d56b0ba85 agent: allow starting only XFTP sending workers (#1232)
* agent: allow starting only XFTP sending workers

* use Bool param

* flip bool

* update
2024-07-17 13:01:17 +01:00
Evgeny Poberezkin b40d55c358 6.0.0.2 2024-07-15 20:30:39 +01:00
Evgeny Poberezkin 784d36d691 socks mode encoding (#1231)
* socks mode encoding

* test delays

* test delay

* unused import
2024-07-15 20:28:24 +01:00
Evgeny Poberezkin 1bdfc8ae00 6.0.0.1 2024-07-14 23:21:14 +01:00
Evgeny Poberezkin 291039159f ntf server: use SOCKS proxy to connect to onion-only SMP servers (#1229)
* ntf server: use SOCKS proxy to connect to onion-only SMP servers

* fix test
2024-07-14 23:19:02 +01:00
Evgeny Poberezkin d4fa0af350 ntf: additional tests for token registration when server and device are restarted (#1230)
* ntf: additional tests for token registration when server and device are restarted

* test response timeouts
2024-07-14 17:57:34 +01:00
Evgeny Poberezkin 492d2f86bc smp server: additional control port commands to monitor server state (#1228)
* smp server: additional control port commands to monitor server state

* fix

* space
2024-07-13 22:34:10 +01:00
Evgeny Poberezkin 8dd54ced0e agent: retry proxied command on NO_SESSION error, to prevent failure of proxied interactive commands (like joining connection) (#1227) 2024-07-13 10:06:48 +01:00
Evgeny Poberezkin e56bd0b47b agent: add known servers (#1225)
* agent: add known servers

* test delays

* ServerCfg

* json encoding

* enabledServerCfg

* checkUserServers
2024-07-12 12:41:55 +01:00
spaced4ndy ff2b00a029 agent: change ProxyClientError json encoding (#1226) 2024-07-11 19:27:04 +04:00
Evgeny Poberezkin 017469b2de 6.0.0.0 2024-07-09 13:56:02 +01:00
Evgeny Poberezkin 26979ff6b5 smp server: simplify client subscriptions (#1223) 2024-07-09 08:36:03 +01:00
Evgeny Poberezkin 21abc5cabe smp server: reduce the number of threads by delivering message to subscription when it is sent (#1222)
* smp server: reduce the number of threads by delivering message to subscription when it is sent

* test delay

* test delay
2024-07-08 23:12:01 +01:00
Evgeny Poberezkin 6e76221e07 agent: fix possible dead lock between sending and receiving messages, stress test for message delivery (#1224)
* agent: fix possible dead lock between sending and receiving messages, stress test for message delivery

* deliver events after the lock is released

* delayed delivery in command processing too

* tests: increase message expiration time
2024-07-08 21:47:42 +01:00
Evgeny Poberezkin 743676421d ntf server: simplify and optimize subscriptions in server agent (#1219)
* increase queue size

* simplify

* refactor to optimize memory usage and performance

* comment

* refactor

* test delays
2024-07-07 21:17:12 +01:00
Evgeny Poberezkin 9d0774a58e agent: add queue information (#1217)
* agent: add queue information to "debug delivery" response

* fix test

* rename

* encodings
2024-07-03 19:32:27 +01:00
Evgeny Poberezkin ce732c0efb agent: enable fast handshake (revert #1215) (#1216)
* Revert "agent: disable fast handshake (#1215)"

This reverts commit aa1d8d6c8b.

* remove import

* test delays
2024-07-03 18:05:27 +01:00
Evgeny Poberezkin 1ac0068d22 Merge commit 'f392ce0a9355cd3883400906ae6c361b77ca46ea' into stable 2024-07-03 14:09:54 +01:00
spaced4ndyandEvgeny Poberezkin ae8e1c5e9a agent: servers stats improvements, fixes (#1208)
* agent: reset stats startedAt time in memory

* getAgentSubsSummary

* change sub counting

* ack statistics

* add import

* instance

* Revert "instance"

This reverts commit 1f63740d56.

* Revert "add import"

This reverts commit ef72df8014.

* modify sub counting

* modify conn creation counting

* use int64

* file size stats

* remove import

* ack err counting

* conn del stats

* format

* new data

* add data

* toKB

* restore connCompleted

* use Int for counts

* use rq from scope

* remove getAgentSubsSummary

* fix connCompleted

* fix

* revert disabling stats

* use srv from scope

* combine ack stats

* modify

* comment

* count subs

* refactor

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-07-03 12:36:15 +01:00
Evgeny Poberezkin f392ce0a93 5.8.2.0 2024-07-02 13:55:28 +01:00
Evgeny Poberezkin aa1d8d6c8b agent: disable fast handshake (#1215) 2024-07-02 13:40:37 +01:00
Evgeny Poberezkin ae4325d0e7 Merge pull request #1209 from simplex-chat/fast-connection
fast handshake protocol
2024-07-02 08:13:37 +01:00
Evgeny Poberezkin da5f669133 remove diagram 2024-07-01 23:34:31 +01:00
Evgeny Poberezkin 5c839b40c9 Merge branch 'master' into fast-connection 2024-07-01 21:14:32 +01:00
spaced4ndy a50e2e74a5 agent: disable saving stats (#1214)
* agent: disable stat saving

* disable migration

* schema

* disable restore
2024-07-01 21:06:38 +01:00
Evgeny Poberezkin 26cfad5e88 do not use sndSecure when rotating queue (#1213) 2024-07-01 13:42:46 +01:00
Evgeny Poberezkin a99ce6122c secure queue by sender via proxy (proxy SKEY command) (#1210)
* client: secure queue by sender via proxy (proxy SKEY command)

* agent and server: proxy SKEY command
2024-06-30 16:20:54 +01:00
Evgeny Poberezkin a6b542b301 Merge branch 'master' into fast-connection 2024-06-30 15:00:28 +01:00
Evgeny Poberezkin 6a54a58a0d agent: remove legacy statistics (#1211)
* agent: remove legacy statistics

* delays after disposeAgent

* delays

* enable all tests

* more delays
2024-06-30 12:50:42 +01:00
Evgeny Poberezkin 9ee684b0f4 rfc: faster handshake protocol (#1203)
* rfc: faster handshake protocol

* update

* 1 message

* SKEY

* use SKEY for both parties

* test

* update doc

* NEW command parameter

* add k=s param to queue URI

* fix

* add sndSecure field to queues

* make sender key non-optional in SndQueue (WIP, tests fail)

* fast handshake sometimes works (many tests fail)

* correctly handle SKEY retries, avoiding to re-generate the keys

* handle SKEY retries during async connection

* fix most tests (1 test fails)

* remove do

* fix contact requests encoding/tests

* export

* fix: ignore duplicate confirmations, fixes testBatchedPendingMessages

* do not store sndSecure in store log if it is false to allow server downgrade

* add connection invitation encoding tests
2024-06-30 08:36:24 +01:00
spaced4ndyandEvgeny Poberezkin c788692687 agent: servers summary types, api (#1202)
* agent: servers summary types, api [wip]

* encoding

* export

* Revert "export"

This reverts commit cd9f315fe8.

* comment

* rename

* simplify types

* uncomment

* comment

* rework

* comment, exports

* save, restore stats wip

* remove

* rename

* save stats periodically

* sigint, sigterm experiments

* corrections

* remove some proxy stats

* increase stat

* proposed stats

* fields

* Revert "sigint, sigterm experiments"

This reverts commit f876fbd418.

* wip

* retries -> attempts

* errs

* fix

* other errs

* more stat tracking

* sub stats

* remove xftp successes stats

* xftp stats tracking

* revert

* revert

* refactor

* remove imports

* comment

* Revert "refactor"

This reverts commit 26c368d82a.

* Revert "revert"

This reverts commit 4c9e3753b5.

* Revert "revert"

This reverts commit 6f65644053.

* todos

* persistence

* rename, fix

* config

* comment

* add started at to summary

* delete stats on user deletion

* reset api

* move

* getAgentServersSummary collect state logic

* corrections

* corrections

* remove

* rework

* decrease contention

* update

* more stats

* count sentProxied

* count subs

* remove unused

* comment

* remove comment

* comment

* export

* refactor

* cleanup

* intervals

* refactor

* refactor2

* refactor3

* refactor4

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2024-06-25 09:42:59 +04:00
Alexander BondarenkoandEvgeny Poberezkin 9e7e0d102d smp-server: conserve resources (#1194)
* transport: force auth params, remove async wrapper

* stricter new messages

* bang more thunks

* style

* don't produce msgQuota unless requested

* strict

* refactor

* remove bangs

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2024-06-24 13:15:08 +01:00
d47c099ac9 docs: update protocol specifications (#1204)
* docs: update protocol specifications

* update SMP protocol (WIP)

* add proxy protocol commands and responses, amend envelope sizes in SMP protocol

* docs: update XFTP protocol (#1205)

* docs: update XFTP protocol

* commands

* fix table of contents, move sections

* add about ids

* download encryption

* qualities

* diagram

* crypto

* sending file diagram

* fix svg

* receiving file diagram

* update commands

* update handshake

* Add updated XRCP (#1207)

* add XRCP protocol

* add ToC

* update

* update

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>

* add XFTP handshake description

* update agent protocol

* fast duplex connection in agent protocol

* update agent protocol

* update overview

* typos

* queue rotation, agent API, updates

* push notifications specification

* add XRCP threat model

* XFTP threat model

* update PQDR

* agent protocol end-to-end encryption

* versions

* remove TOC details

* update

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
2024-06-23 22:53:45 +01:00
Evgeny Poberezkin e371a4a62d Merge branch 'master' into stable 2024-06-16 07:58:05 -07:00
sh 8a3b72458f readme: update compiling from source instructions (#1190) 2024-06-16 07:43:22 -07:00
Evgeny Poberezkin f616cb7b3e 5.8.1.0 2024-06-16 07:36:38 -07:00
spaced4ndyandEvgeny Poberezkin 4bbadffa37 agent: api to reconnect single server (#1198)
* agent: api to reconnect single server

* refactor

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2024-06-16 06:27:25 -07:00
Evgeny PoberezkinandAlexander Bondarenko 388d77b61a ntf stats on SMP server (#1197)
* log undelivered notifications

* type

* add counters and encoding

* rename

* diff

* style

* style2

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
2024-06-15 20:05:45 -07:00
Alexander Bondarenko 6597f6f0ed tests: add proxy connection refused test (#1200) 2024-06-15 19:27:58 -07:00
M. Sarmad QadeerandEvgeny Poberezkin 7008b08031 smp-server: fix layout (#1196)
* smp-server: fix layout

* ws

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2024-06-15 12:52:41 -07:00
spaced4ndyandEvgeny Poberezkin bb1d31e459 remote ctrl: differentiate RCP error when trying to connect to unknown host identity (#1195)
* remote ctrl: differentiate RCP error when trying to connect to unknown host identity

* rename

* refactor

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2024-06-10 17:42:51 +04:00
sh 369efc24c2 scripts: update install/update scripts (#1192) 2024-06-08 08:12:16 +01:00
spaced4ndy da620c388a xftp: start chunk upload after all chunks are prepared (#1191) 2024-06-06 15:50:15 +04:00
spaced4ndy 3c0cd7efcc agent: separate type for agent file errors (#1185) 2024-06-05 18:44:32 +04:00
Evgeny Poberezkin 3d605310ed agent: remove protocol encodings and agent TCP server (#1189)
* rfc: remove agent protocol encodings

* agent: remove protocol encodings and agent TCP server

* update

* remove unused code

* remove

* move tests

* add delay to tests

* stabilize test

* test

* more delays

* reduce delays

* enable all tests

* delays

* style
2024-06-05 14:34:40 +01:00
Evgeny Poberezkin 3dab330480 use throwE instead of throwError (#1187)
* use throwE instead of throwError

* test delay
2024-06-05 11:20:50 +01:00
Evgeny Poberezkin 44b8f265ae 5.8.0: changelog 2024-06-03 10:01:59 +01:00
Evgeny Poberezkin 2e4f507919 5.8.0.10 2024-05-31 22:20:30 +01:00
Evgeny Poberezkin d28b17e787 xftp server: send HTTP2 error as timeout error to the client so it is treated as temporary (#1186)
* xftp server: log file reception error

* report HTTP2 error as timeout error

* reduce timeout to 5 min

* process timeout error in protocol response

* log warning on timeout/HTTP2 error
2024-05-31 22:18:28 +01:00
Evgeny Poberezkin e1017e2a7f 5.8.0.9 2024-05-31 14:25:57 +01:00
Evgeny Poberezkin 1ff91d888f Merge branch 'stable' 2024-05-31 14:25:19 +01:00
Evgeny Poberezkin 0b5ab3a374 5.7.6.0 2024-05-31 14:23:21 +01:00
Evgeny Poberezkin 8ed54b33e0 agent: report correct errors from xftp handshake so they are treated as temporary (#1184)
* agent: report correct errors from xftp handshake so they are treated as temporary

* disable slow servers test

* remove comments

* all tests

* remove duplicate functions
2024-05-31 13:01:13 +01:00
Evgeny Poberezkin 3a3a84c58c server: log proxy connection errors 2024-05-31 12:20:29 +01:00
Evgeny Poberezkin d12ea92055 agent: report correct errors from xftp handshake so they are treated as temporary (#1184)
* agent: report correct errors from xftp handshake so they are treated as temporary

* disable slow servers test

* remove comments

* all tests

* remove duplicate functions
2024-05-31 09:47:47 +01:00
Evgeny Poberezkin 6e4067dc0c add string encodings for SMPProxyMode and SMPProxyFallback 2024-05-31 09:16:00 +01:00
Evgeny Poberezkinandspaced4ndy 88f1b727e0 SMP protocol extension to debug subscribed SMP queues (#1181)
* SMP protocol extension to debug subscribed SMP queues

* fix, test

* corrections

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* increase delays

* increase timeout

* delay

* delay

* enable all tests

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-05-30 18:49:43 +01:00
spaced4ndy 97a953550f agent: getAgentQueuesInfo (#1180) 2024-05-30 14:21:29 +04:00
Evgeny Poberezkin 39b3b5a25e 5.8.0.8 2024-05-29 13:19:10 +01:00
Alexander BondarenkoandEvgeny Poberezkin 15f0bb9e79 tcp-server: recover from accept errors (#1179)
* tcp-server: recover from accept errors

* log

* warn

* where

* retry

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-05-29 13:18:00 +01:00
5c2c88315a SMP server information (#1072)
* SMP server information

* fix tests

* country codes

* smp-server: serve contact and link pages from static files (#1084)

* smp-server: serve contact and link pages from static files

* generate index

* use params from ini

* render using ServerInformation

* tweak templates

* update

* fix some html

* smp-server: fix layout (#1097)

* smp-server: fix layout

* port fixes to link page

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>

* update server information page

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
Co-authored-by: M. Sarmad Qadeer <MSarmadQadeer@gmail.com>

* update server info

* web: improve server info page design (#1166)

* web: improve server info page design

* web: fix font errors & some tags

* web: improve contact & invitation page layout and header

* update

* remove unused files/css

* cleanup

* fix link page

* remove unused font links

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>

* show contact address as is

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
Co-authored-by: M. Sarmad Qadeer <MSarmadQadeer@gmail.com>
2024-05-29 11:30:42 +01:00
Evgeny Poberezkin 0f663bd569 5.8.0.7 2024-05-29 08:09:27 +01:00
Evgeny Poberezkin 63f5e76f9c agent: treat absent proxy session as a temporary error to retry sending (#1178)
* agent: treat absent proxy session as a temporary error to retry sending

* enable all tests
2024-05-29 08:06:01 +01:00
Evgeny Poberezkin ee052a454e 5.8.0.6 2024-05-28 15:33:55 +01:00
Evgeny Poberezkin e55ec07fe2 server: log stats for QUOTA and other errors (#1177)
* server: log stats for QUOTA errors

* fix test

* more stats

* remove duplicate column
2024-05-28 15:32:41 +01:00
Evgeny Poberezkin 199f85ec62 agent: send MWARN on QUOTA errors (#1176)
* agent: send MWARN on QUOTA errors

* fix tests
2024-05-28 11:56:57 +01:00
Evgeny Poberezkin 4a96dbf871 server: preprocess proxy commands that will not be connecting to network to reduce concurrency, do not wait for destination relay responses before processing the next command (#1174)
* server: preprocess proxy commands that will not be connecting to network to reduce concurrency

* implementation

* tests

* increase proxy client concurrency

* simplify

* refactor

* refactor2

* rename

* refactor3

* fix 8.10.7
2024-05-28 09:38:47 +01:00
Evgeny Poberezkin c8b2bb2ae1 agent: process message sent in expired response to ACK (it will increase duplicates count) (#1175) 2024-05-28 08:35:43 +01:00
Evgeny Poberezkin ab7b350521 agent: prevent sending not-batched client commands once requests time out (#1173) 2024-05-27 14:55:04 +01:00
Evgeny Poberezkin df35c50b99 5.7.5.0 2024-05-25 11:10:14 +01:00
Evgeny Poberezkin bd67844169 5.8.0.5 2024-05-24 14:26:02 +01:00
Evgeny Poberezkin 470dc74391 ntf server: do not persist server connection errors 2024-05-24 14:25:05 +01:00
Evgeny Poberezkin 2ff5f5a832 agent: add context to CMD error (#1167)
* agent: add context to CMD error

* tests, more warnings

* fix tests

* log TBQueue sizes

* log locks

* more logs

* log sendMessagesB

* fix test

* log length

* refactor

* remove logging

* revert lock scope change

* cleanup

* add string error to A_PROHIBITED

* remove

* remove test limitations

* language
2024-05-24 14:13:01 +01:00
Evgeny Poberezkin e7a73a4c89 Merge branch 'stable' 2024-05-23 22:04:06 +01:00
Evgeny Poberezkin 6309f92c68 agent: fail if non-unique connection IDs are passed to sendMessages (#1170) 2024-05-23 22:01:57 +01:00
Evgeny Poberezkin 875a56b75a Merge branch 'stable' 2024-05-23 16:48:11 +01:00
Alexander Bondarenko 984394d906 core: remove MonadUnliftIO ExceptT orphans (#1169) 2024-05-23 16:44:00 +01:00
Alexander Bondarenko 5d38ad03af tests: add proxy stress tests (#1163)
* tests: add proxy stress tests

* organize benches

* add agent tests

* move prints to logNote

* fix stuck agent tests
2024-05-23 15:34:25 +01:00
Alexander Bondarenko f6bb105536 utils: remove MonadError usage (#1168) 2024-05-23 12:47:30 +01:00
Evgeny Poberezkin 6c86aa302f 5.8.0.4 2024-05-22 16:13:26 +01:00
Evgeny Poberezkin 2b09ada392 agent: reduce interval for storing server connection errors to 3 seconds 2024-05-22 14:36:54 +01:00
Evgeny Poberezkin 8097df5540 agent: persist server connection error (#1165)
* agent: persist server connection

* comment, refactor

* fix tests, reduce interval for ntf server

* cleanup

* 0
2024-05-22 13:25:49 +01:00
Evgeny Poberezkin 5bff2f5537 Merge branch 'stable' 2024-05-21 23:42:49 +01:00
Evgeny Poberezkin 769e54db76 5.7.4.1 2024-05-21 22:58:58 +01:00
Evgeny Poberezkin f50589b31a agent: remove external timeout to resubscribe (#1164)
* agent: remove external timeout to resubscribe

* liftIO

* fix tests
2024-05-21 22:52:22 +01:00
Evgeny Poberezkin 2f2a3acdc0 5.8.0.3 2024-05-21 14:51:11 +01:00
Alexander BondarenkoandEvgeny Poberezkin f50fa5c60b smp-server: limit concurrency in proxy command processing (#1162)
* smp: put client proxy command processing threads under a shared semaphore

* add LIMITS.max_proc_threads to server config

* rename to PROXY.client_concurrency

* retry on strictly greater than max concurrency

* set default to 16

* rename

* fix limit

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-05-21 12:53:33 +01:00
Evgeny Poberezkin e3f5d244c1 5.8.0.2 2024-05-20 17:31:08 +01:00
Alexander BondarenkoandEvgeny Poberezkin f89d715a99 smp server: add proxy stats (#1157)
* smp-server: add proxy counters

* count simplex.im messages

* update

* fix

* get own servers from INI

* remove export

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-05-20 17:07:33 +01:00
Alexander BondarenkoandEvgeny Poberezkin 8fe18c4f6d core: use catMaybes to collect optional replies (#1161)
* core: use catMaybes to collect optional replies

* style

* rollback agent changes and add a note

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-05-20 15:48:21 +01:00
spaced4ndy 2e5433676e xftp: check proxy before downloading from unknown server (#1102)
* xftp: check proxy before downloading from unknown server

* corrections

* remove import

* tests

* comment

* tests

* don't wrap into internal error

* fix tests
2024-05-20 14:14:04 +01:00
Evgeny Poberezkin 8b21f7ef2a agent: aggregate multiple expired subscription responses into a single UP event (#1160)
* agent: aggregate multiple expired subscription responses into a single UP event

* clean up

* refactor processing of expired responses

* refactor

* refactor 2

* refactor unexpectedResponse
2024-05-20 07:56:51 +01:00
Evgeny Poberezkin 7a15ea59c9 Merge branch 'stable' 2024-05-19 07:58:00 +01:00
Evgeny Poberezkin 1bb6a5c43b agent: do not increase network activity interval while offline (#1159)
* agent: do not increase network activity interval while offline

* test
2024-05-19 07:50:47 +01:00
Evgeny Poberezkin 1116aeeea1 5.8.0.1 2024-05-17 15:39:20 +01:00
Evgeny Poberezkin 077ca9c046 Merge branch 'stable' 2024-05-17 15:38:06 +01:00
Evgeny Poberezkin 33f6d2f1da agent: optimize waiting for user network to avoid contention for state updates from multiple threads (#1155)
* haskell magic

* update

* agent: optimize waiting for user network with TChan

* clean up

* Int64

* use TVar

* cleanup

* fix

* testing

* update
2024-05-17 15:12:05 +01:00
spaced4ndy b33e8f4370 agent: reconnect xftp clients (#1156) 2024-05-17 14:23:59 +01:00
Alexander Bondarenko 426f47c805 smp: use session vars for reconnecting small agent (#1152)
* smp: use session vars for reconnecting small agent

* process errors

* split session and protocol functions

* add active flag to agent

* actually invoke agent shutdown

* close proxy agent too

* restore stopping ntf subscribers
2024-05-16 19:06:27 +01:00
Evgeny Poberezkin 9af3297997 Merge pull request #1151 from simplex-chat/ep/remember-error
proxy: remember server connection error for some time
2024-05-15 21:12:52 +01:00
Evgeny Poberezkin 16d79da73e config 2024-05-15 15:15:59 +01:00
Evgeny Poberezkin 6d19033375 proxy: remember server connection error for some time 2024-05-15 12:06:42 +01:00
Evgeny Poberezkin 2d2cc86bd8 Merge pull request #1095 from simplex-chat/proxy
SMP proxy feature branch
2024-05-14 21:35:51 +01:00
Evgeny Poberezkin f51cf1deac agent: use MVar for DB connection for more fair connection distribution between threads (#1147) 2024-05-14 20:04:51 +01:00
spaced4ndy 00a2dde727 Merge branch 'master' into proxy 2024-05-14 10:41:06 +04:00
Evgeny Poberezkin 762909ce33 5.8.0.0 2024-05-13 20:35:46 +01:00
Evgeny Poberezkin 512afa1e2b agent: count received duplicate messages (#1148)
* agent: count received duplicate messages

* count total too

* names

* fix

* tuple
2024-05-13 15:16:20 +01:00
Evgeny Poberezkin c4c983348f Merge branch 'master' into proxy 2024-05-13 14:13:52 +01:00
sh 969951d963 actions: ignore uploading GHC 8.10.7 binaries (#1064)
In other words, finally upload 22.04 binaries.
2024-05-13 10:46:37 +01:00
Evgeny Poberezkin 4455b8bd0e agent: do not throw exception when command is created for deleted connection (#1150)
* agent: do not throw exception when command is created for deleted connection

* convert database busy/locked to critical alert
2024-05-13 08:10:40 +01:00
Evgeny Poberezkin 66c916dbb3 proxy: increase client timeout for proxied commands (#1145) 2024-05-12 21:12:01 +01:00
Evgeny PoberezkinandAlexander Bondarenko 91cc48aabe agent: do not mark subscriptions on expired sessions as active, mark delayed subscriptions as active on the same session, do not cancel sending expired commands (#1127)
* agent: do not mark subscriptions on expired sessions as active, do mark delayed subscriptions as active on the same session, SUBOK response in the next SMP protocol version

* client: prevent sub actions from zombie sessions (#1122)

* client: prevent sub actions from zombie sessions

* error handling

* add AERR to pass background errors to client

* switch to activeClientSession

* put closeClient under activeClientSession

* rename

* remove AERR, do not skip processing

* move check and state update to one transaction

* catch extra UPs

* fix

* check queue is still pending before making it active

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>

* do not forward agent error

* revert not expiring sending subs

* fixes

* track subscription responses better

* add pending connection

* Revert "revert not expiring sending subs"

This reverts commit 4310a69391.

* do not expire sending commands

* rename

* fix race

* function

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
2024-05-12 17:47:08 +01:00
Evgeny Poberezkin 1339a8da11 5.7.4.0 2024-05-11 23:39:28 +01:00
Evgeny Poberezkin 103ae06d55 agent: remove critical error on subscription timeout (#1146) 2024-05-11 23:38:27 +01:00
Evgeny Poberezkin 8516b0dd5b proxy: negotiate client-relay version, include it in PFWD commands and in encrypted forwarded transmissions (#1144)
* proxy: negotiate client-relay version, include it in PFWD commands and in encrypted forwarded transmissions

* rename

* inline

* comment

* use correct server version when encoding forwarded commands
2024-05-11 17:11:28 +01:00
Evgeny Poberezkin 9f72b249b4 Merge branch 'master' into proxy 2024-05-11 10:25:35 +01:00
Evgeny Poberezkin acc7faea11 5.7.3.1 2024-05-10 22:24:00 +01:00
Evgeny PoberezkinandAlexander Bondarenko 727fd8b8f5 server: more efficient response to batched subscriptions (#1141)
* server: more efficient response to batched subscriptions

* add sndMsgQ for interleaving messages with replies

* remove redundant liftIO

* refactor

* refactor2

* rename

* fix

* diff

* remove comment

* remove comment

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
2024-05-10 22:19:11 +01:00
Evgeny Poberezkin dc111437fd 5.7.3.0 2024-05-10 15:15:43 +01:00
Evgeny Poberezkin b7afb725fd proxy: send MWARN event to user on server version or host more errors (#1140)
* proxy: include delivery path in SENT event

* send MWARN event to user on server version or host more errors

* Revert "proxy: include delivery path in SENT event"

This reverts commit 5c476718ec.
2024-05-10 10:55:19 +01:00
Evgeny Poberezkin b48215d341 proxy: additional configuration for SOCKS proxy usage in SMP proxy client (#1138)
* proxy: additional configuration for SOCKS proxy usage in SMP proxy client

* update
2024-05-09 15:36:02 +01:00
Evgeny Poberezkin 5cafd9d5c4 server: more efficient responses to batch subscriptions (#1137)
* server: more efficient responses to batch subscriptions

* comments

* comment

* enable tests

* LogError
2024-05-09 09:20:57 +01:00
Evgeny Poberezkin 817fd77332 Merge branch 'master' into proxy 2024-05-08 23:00:53 +01:00
Evgeny Poberezkin b27f126bab include server version range in transport handle (#1135)
* include server version range in transport handle

* xftp handshake

* remove coment

* simplify

* comments
2024-05-08 23:00:00 +01:00
Evgeny Poberezkin ea21b296fd agent: reset error count and do not report errors when consequitive timeouts happen while offline (#1136)
* agent: reset error count and do not report errors when consequitive timeouts happen while offline

* refactor

* comment
2024-05-08 15:33:51 +01:00
spaced4ndy 3f57d54832 xftp: catch exceptions in chunk download (#1133) 2024-05-08 16:57:04 +04:00
Evgeny Poberezkin b40654c95d update agent to v7/v2 SMP/NTF protocol versions (#997)
* update agent to v7/v2 SMP/NTF protocol versions
2024-05-08 13:05:06 +01:00
Evgeny Poberezkin 6d471b8be2 Merge branch 'master' into proxy 2024-05-08 00:14:06 +01:00
Alexander BondarenkoandEvgeny Poberezkin 7a07076277 transport: require ALPN for extended handshakes (#1134)
* transport: require ALPN for extended handshakes

* fix 8.10 build

* rename

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-05-08 00:06:09 +01:00
Evgeny Poberezkin a70f492f4d proxy: fallback to direct connection if destination relay does not support proxy protocol (#1132)
* proxy: fallback to direct connection if destination relay does not support proxy protocol

* move version to TransportError, refactor
2024-05-07 13:37:40 +01:00
Alexander BondarenkoandEvgeny Poberezkin c85f6a2f0e proxy: reporting errors (#1108)
* smp-proxy: iron out errors

* treat proxy timeouts as temporary

* update errors

* proxy errors (missing encoding)

* update

* enable tests

* update

* update

* fix

* fix

* simplify

* test

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-05-06 22:00:42 +01:00
Evgeny Poberezkin f22daf5cb6 Merge branch 'master' into proxy 2024-05-06 15:26:11 +01:00
Evgeny Poberezkin 93fd424f86 5.7.2.0 2024-05-05 17:13:26 +01:00
Evgeny Poberezkin e13b0df539 client: remove TLS handshake timeout (#1129)
* client: remove TLS handshake timeout

* remove comment
2024-05-05 17:05:51 +01:00
Evgeny Poberezkin ee8e4067b0 agent: prepare connection record before joining to prevent race conditions (#1128)
* agent: prepare connection record before joining to prevent race conditions

* prepare connection for contact address as well

* clean up
2024-05-05 12:12:19 +01:00
Alexander BondarenkoandEvgeny Poberezkin 0e205e70ad add TRcvQueues tests (#1117)
Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-05-03 23:39:00 +01:00
Evgeny Poberezkin b586a6e90a client: removed concurrency limit when waiting for subscription results (#1126) 2024-05-03 22:16:52 +01:00
Evgeny Poberezkin 259f6fcc3b Merge branch 'stable' 2024-05-02 16:24:32 +01:00
Evgeny Poberezkin 8d8010a62a 5.7.1.0 2024-05-02 16:22:55 +01:00
Evgeny Poberezkin c5941b790b client: increase timeout for SOCKS connection, increase timeout for direct connection (#1123) 2024-05-02 16:00:58 +01:00
Evgeny Poberezkin 60403955c0 5.7.0.4 2024-05-02 16:00:35 +01:00
Evgeny Poberezkinandspaced4ndy 9e49c289b4 upgrade SMP/NTF servers to v7/v2 protocol versions (#996)
* upgrade SMP/NTF servers to v7/v2 protocol versions

* 5.6.0.0

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-05-02 16:00:03 +01:00
Evgeny Poberezkin 6f83273318 client: increase timeout for SOCKS connection, increase timeout for direct connection (#1123) 2024-05-02 15:14:01 +01:00
Evgeny Poberezkin fb5d54e0a2 Merge branch 'master' into proxy 2024-05-01 12:52:04 +01:00
Alexander BondarenkoandEvgeny Poberezkin 0d2c1d3c01 transport: reduce ping traffic (#1118)
* transport: reduce ping traffic

* make pings opt-in, enable automatically with SUB commands

* fix reduced delays

* enable pings on MSG too

* rename pingErrorCount

* check timeout counter even when not sending pings

* clean up

* reset timeout error count on any event

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-05-01 10:38:33 +01:00
Evgeny PoberezkinandAlexander Bondarenko 6d60de2429 proxy: agent implementation (#1106)
* proxy: agent implementation

* revert change

* update rfc

* test stuck subscription mock

* store proxy sessions inside SMP client var

* rename

* create and use proxy session

* tests

* return proxy in SENT event

* rename, more tests

* rename

* more tests

* remove comment

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
2024-05-01 08:48:33 +01:00
Evgeny Poberezkin 323cdc412e 5.7.0.4 2024-05-01 00:56:33 +01:00
Evgeny Poberezkinandspaced4ndy 66eccbecb3 upgrade SMP/NTF servers to v7/v2 protocol versions (#996)
* upgrade SMP/NTF servers to v7/v2 protocol versions

* 5.6.0.0

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-05-01 00:51:08 +01:00
Evgeny Poberezkin 935d2e25df 5.7.0.3 2024-04-25 10:22:18 +01:00
Alexander Bondarenko b931c1be37 utils: remove zstd contexts (#1116) 2024-04-25 09:33:22 +01:00
Evgeny Poberezkin daa866f333 5.7.0.2 2024-04-22 18:59:33 +01:00
Evgeny Poberezkin fe28e02be7 agent: make version independent of PQ enqryption support (#1114)
* agent: make version independent of PQ enqryption support

* remove comment
2024-04-22 13:40:24 +01:00
Evgeny Poberezkin 1612a7e2c7 agent: reduce sizes for per-queue e2e encryption (#1113) 2024-04-22 09:25:03 +01:00
Evgeny Poberezkin b08314722d 5.7.0.1 2024-04-21 22:58:15 +01:00
Evgeny Poberezkin 2347b82b47 adjust timeouts and delayed response errors (#1112) 2024-04-21 22:57:07 +01:00
Evgeny Poberezkin 3d40393ae8 5.7.0.0 2024-04-20 18:20:18 +01:00
Alexander BondarenkoandEvgeny Poberezkin b98fdb672d transport: increase client timeouts, don't send command after timeout (#1110)
* transport: fix client handshake timeouts

* fix handshake timeout

* skip sending requests for timed out responses

* expose batch concurrency as PClient field

* move to NetworkConfig

* remove Request on timeout

* use record

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-04-20 18:17:48 +01:00
Evgeny Poberezkin 3ba3172aaf xftp: enable ALPN in XFTP server (#1109) 2024-04-20 09:15:33 +01:00
Evgeny Poberezkin 2d1609f222 update envelope sizes for proxied messages, remove unnecessary proxy-relay encryption padding (#1107)
* update envelope sizes for proxied messages

* remove unnecessary padding from proxy-relay encryption
2024-04-19 20:24:25 +01:00
Alexander BondarenkoandEvgeny Poberezkin 58ede38bf4 put smp errors into proxy wrappers (#1103)
* put smp errors into proxy wrappers

* use substring in PROXY UNEXPECTED error

* fix encoding

* revert String encoding, discard invalid errors in QC

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-04-19 14:58:15 +01:00
Evgeny Poberezkin 7712070cb3 Merge branch 'master' into proxy 2024-04-18 23:33:06 +01:00
Evgeny Poberezkin c00c223f3b remove (or make optional) client key from handshakes (#1104)
* remove (or make optional) client key from handshakes

* remove comment
2024-04-18 22:43:49 +01:00
a3b229f668 SMP proxy: low level client and server implementation (#1096)
* SMP proxy: low level client and server implementation

* SMP proxy: server implementation (#1098)

* wip

* PRXY command

* progress

* SMP Proxy: client-level implementation (#1101)

* buildable

* encode messages

* update pkey

* fix queue types

* wrap SEND in proxy lookup

* WIP proxy client

* WIP

* post-rebase fixes

* encode something with something

* cleanup

* update

* fix nonce/corrId in batchingTests

* WIP: dig into createSMPProxySession

* agent

* test progress

* pass the test

* parameterize transport handle with transport peer to include server certificate (#1100)

* parameterize transport handle with transport peer to include server certificate

* include server certificate into THandle

* load server chain and sign key

* fix key type

* fix for 8.10

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
Co-authored-by: IC Rainbow <aenor.realm@gmail.com>

* cleanup

* add 2-server test

* remove subsumed test

* checkCredentials for BrokerMsg

* skip batching tests

* remove userId param

* remove agent changes

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>

* remove unused type

* icrease test timeout

* reduce transport block

* envelope sizes

* don't fork unless have proxied commands to process

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
Co-authored-by: IC Rainbow <aenor.realm@gmail.com>
2024-04-18 22:35:17 +01:00
Evgeny Poberezkin 8d7e0b1d09 Merge branch 'master' into proxy 2024-04-17 17:46:39 +01:00
2f43b43225 parameterize transport handle with transport peer to include server certificate (#1100)
* parameterize transport handle with transport peer to include server certificate

* include server certificate into THandle

* load server chain and sign key

* fix key type

* fix for 8.10

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
Co-authored-by: IC Rainbow <aenor.realm@gmail.com>
2024-04-17 17:46:22 +01:00
ad4b5b6b71 parameterize transport handle with transport peer to include server certificate (#1100)
* parameterize transport handle with transport peer to include server certificate

* include server certificate into THandle

* load server chain and sign key

* fix key type

* fix for 8.10

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
Co-authored-by: IC Rainbow <aenor.realm@gmail.com>
2024-04-15 13:47:48 +01:00
Evgeny Poberezkin 98eb2742bc Merge branch 'master' into proxy 2024-04-13 18:51:17 +01:00
Evgeny Poberezkin ebb75ced12 extract SessionVar from AgentClient to reuse (#1099) 2024-04-13 18:33:12 +01:00
Evgeny Poberezkin 5e783396e0 5.6.2.2: v5.6.2 2024-04-12 23:14:20 +01:00
Evgeny Poberezkin b741b65700 use online status in network information (#1094)
* use online status in network information

* test

* refactor

* flip condition

* fix
2024-04-12 22:22:24 +01:00
Alexander BondarenkoandEvgeny Poberezkin 875ddd80d6 SMP proxy: protocol (#954)
* WIP: proxy-related types

* test plan

* buildable with stubs

* add auth test

* update protocol

* fix

* update rfc

* update protocol/types

* disable test

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-04-12 18:04:29 +01:00
Alexander BondarenkoandEvgeny Poberezkin 036b7523a5 xftp: matrix test for new versions (#1093)
* xftp: matrix test for new versions

* manual matrix

* more, faster

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-04-12 13:28:16 +01:00
spaced4ndyandEvgeny Poberezkin 3b1dd6dff9 agent: notify about available quota (#1087)
* agent: notify about available quota

* rename

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-04-11 09:38:12 +01:00
Evgeny Poberezkin 2e44ec5083 fix message expiration test (#1092) 2024-04-11 08:52:15 +01:00
Evgeny Poberezkin fbc25b171e xftp: reply ERR AUTH when file is removed from server storage (#1091) 2024-04-10 23:02:48 +01:00
Evgeny Poberezkinandspaced4ndy 8fa9ed6317 wait for user network availability (#1085)
* ghc-options

* wait for user network availability

* test

* update

* comment

* refactor

* slow config

* line

* waitForUserNetwork in xftp and ntf workers

* refactor

* refactor with registerDelay

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-04-10 21:50:05 +01:00
Alexander Bondarenko 91cf6841e0 http2: fix client setup (#1090)
* http2: cancel client action on setup timeout

* ignore incompatible server keys
2024-04-10 21:00:39 +01:00
Evgeny PoberezkinandAlexander Bondarenko 1219446996 dispose agent instances, fix tests, (#1089)
* dispose agent instances in tests

* fix quota test

* tests: fix tests with -threaded (#1088)

* fix some tests

* match RTS opts with apps

* less verbose rts stats

* enable sqlite extended error codes

* clean up

* unfocus

* remove extendedErrorCode

It's actually setExtendedResultCodes, which isn't yet available.

* diff

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>

* fix switch test

* fix

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
2024-04-10 19:34:02 +01:00
Evgeny Poberezkin b994fd9f0f use sendRequest for HTTP2 2024-04-09 21:14:10 +01:00
Alexander BondarenkoandEvgeny Poberezkin 4c20ff6d00 xftp: negotiate protocol with ALPN (#1047)
* xftp: negotiate protocol with ALPN

* add RFC

* add handshake implementation

* implement extended handshake

* enable authentication

* update rfc

* Apply suggestions from code review

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>

* cleanup

* discard trailing data

* cleanup diff

* use find

* rename

* refactor

* add x509 tests

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-04-09 15:03:40 +01:00
spaced4ndyandEvgeny Poberezkin 791368c7be export lock function (#1073)
* export lock functions

* rename with tick

* simplify

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-04-04 15:37:31 +01:00
Alexander Bondarenko a4cfcfcc85 ntf-server: fix test token handling (#1083)
* use formatted logger

* fix DeviceToken parser for apns_null

* exclude PPNull from token stats
2024-04-04 14:46:40 +01:00
Evgeny Poberezkin 6bc4f6c94e 5.6.2.1 2024-04-03 10:04:41 +01:00
Evgeny Poberezkin 84b8c8417b revert base64 change (#1081) 2024-04-03 09:27:36 +01:00
Alexander Bondarenko be9a84905f servers: read stores by chunks (#1080) 2024-04-01 19:42:30 +01:00
Evgeny Poberezkin bfd532e833 5.6.2.0 2024-04-01 11:33:22 +01:00
Alexander BondarenkoandEvgeny Poberezkin a698f9a0c4 xftp-server: run expiration checks on start (#1042)
* xftp-server: run expiration checks on start

* rename

* refactor

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-04-01 11:29:19 +01:00
39bb804fab xftp: fix repeated replica creation if it was in uploaded status (#1079)
* test with failing files (in progress)

* print

* add replica uploading state

* Revert "add replica uploading state"

This reverts commit 7068213aa6.

* <=

* fix

* prints

* test no redundancy

* all tests no redundancy

* revert delay

* refactor

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-04-01 13:37:35 +04:00
Evgeny PoberezkinandAlexander Bondarenko 6ded721daa remove monad typeclasses to reduce overhead (#1077)
* remove monad typeclasses to reduce overhead

* remove unliftIO

* StrictData

* inline

* optional agent port

* avoid MonadUnliftIO instance (#1078)

* avoid MonadUnliftIO instance

* simpler liftError'

* rename

* narrow down instance

* revert

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>

* logServer

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
2024-03-31 20:50:35 +01:00
Evgeny Poberezkin 6c48092f5e 5.6.1.0 2024-03-28 18:23:19 +00:00
Evgeny Poberezkin 44410535fd do not pass key to control port of xftp server (#1074) 2024-03-28 18:16:36 +00:00
Alexander BondarenkoandEvgeny Poberezkin bbc9eccf4d xftp: prevent overwriting completed upload (#1063)
* xftp: prevent overwriting completed upload

* add size check for skipCommitted

* fix import

* fail on incorrect size

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-03-28 18:12:48 +00:00
Alexander BondarenkoandEvgeny Poberezkin ee90ea6a69 replace base64-bytestring with base64 (#1065)
* replace base64-bytestring with base64

* minify

* use bytestring-0.10 compatible fork

PR pending...

* bump base64 fork with text compat

* move compat details to modules

* switch repo

* add back module

* cleanup

* minify

* clean imports

* rename

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-03-27 23:35:09 +00:00
Alexander BondarenkoandEvgeny Poberezkin 5e0123313c log control port commands, authentication for control port (#1071)
* log control port commands

* auth

* add auth to xftp, config and commands

* log missing auth

* put smp save under auth

* corrections

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-03-26 18:04:28 +00:00
Evgeny Poberezkin 2712fbc711 add key to XFTP server control port command (#1070)
* add key to XFTP server control port command

* name
2024-03-26 09:38:28 +00:00
Evgeny Poberezkin dbaef5a0f8 fix SMP server msgCount stat (#1069) 2024-03-25 16:26:40 +00:00
Alexander BondarenkoandEvgeny Poberezkin ff1d7f2fac ntf-server: break processing transaction (#1067)
* ntf-server: break processing transaction

* make resubscribe sync

* diff

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-03-25 15:35:33 +00:00
Evgeny Poberezkin c5a5edadf5 rfc: relay metadata and network decentralization (#1056) 2024-03-24 08:51:35 +00:00
Evgeny Poberezkin 8496884b42 5.6.0.4 2024-03-21 15:18:11 +00:00
Evgeny Poberezkin b32259d048 notify about critical error on agent crash (#1062)
* notify about critical error on agent crash

* waitUntilActive

* disposeAgent

* fix
2024-03-21 14:54:57 +00:00
Alexander Bondarenko a48c22ea36 core: fix leak in serverDown handler (#1061) 2024-03-21 12:03:19 +00:00
Alexander Bondarenko 9eacae5492 xftp: remove duplicate check in receiveServerFile (#1057) 2024-03-20 15:50:38 +00:00
Evgeny Poberezkin 7b6b80cea2 v5.6.0-beta.3 2024-03-19 15:00:42 +00:00
Alexander Bondarenko d68ff7e22f xftp-server: set initial usedStorage from actual file records (#1045) 2024-03-19 13:53:02 +00:00
Evgeny Poberezkin 46e49fa823 xftp: return OK on duplicate upload attempt 2024-03-19 13:52:07 +00:00
Alexander BondarenkoandEvgeny Poberezkin db3bddecca xftp-server: fix receiveServerFile (#1048)
* xftp-server: fix receiveServerFile

* refactor

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-03-19 13:34:21 +00:00
Alexander Bondarenko 097cec1c35 utils: add stateless compress1 (#1053) 2024-03-19 12:13:42 +00:00
Alexander Bondarenko ca68eca86e agent: fix leak in getChunkDigest (#1051) 2024-03-15 12:18:15 +04:00
Alexander Bondarenkoandspaced4ndy ace09cc07d xftp: force single chunk for redirect descriptions (#1050)
* xftp: force single chunk for redirect descriptions

* Update src/Simplex/FileTransfer/Client/Main.hs

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-03-15 12:08:52 +04:00
spaced4ndy 293a2ca3f1 agent: remove withStoreCtx (#1044) 2024-03-13 13:33:59 +04:00
spaced4ndy e93ea6df71 xftp: fix sending large files (#1043) 2024-03-13 13:33:43 +04:00
Evgeny Poberezkin 0aa4ae7228 v5.6.0-beta.2 2024-03-12 14:31:30 +00:00
Alexander BondarenkoandEvgeny Poberezkin 2cad0cb201 core: check ACK handling with return type (#1041)
* core: check ACK handling with return type

* fix ratchet sync

* add SQL Locked to dbBusyLoop

* rename

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-03-11 19:06:53 +00:00
Evgeny Poberezkin 78eb4f764f v5.6.0-beta.1 2024-03-10 19:41:06 +00:00
Evgeny Poberezkin 819ae7040d Merge pull request #1024 from simplex-chat/pq
agent: quantum-resistant double ratchet encryption
2024-03-10 19:38:44 +00:00
Evgeny Poberezkin b4c90781bb pqdr: update envelope sizes 2024-03-10 17:53:57 +00:00
Evgeny Poberezkin 851ed2d02e pqdr: more tests, pass e2e version to rcEncrypt from config (#1040)
* pqdr: more tests, pass e2e version to rcEncrypt from config

* fix
2024-03-10 13:29:03 +00:00
Evgeny Poberezkin 054b6edb14 pqdr: clean up (#1039) 2024-03-10 11:27:31 +00:00
Evgeny Poberezkin dab55e0a9b pqdr: return agent version from connection request version & PQ support check api 2024-03-08 23:13:21 +00:00
Alexander Bondarenko 8cdd49b912 core: restore Eq instances (#1038)
* core: restore Eq instances

* remove duplicates from tests
2024-03-08 13:43:33 +00:00
Alexander Bondarenko b4e55146b8 core: fix VersionRange JSON instances (#1037) 2024-03-08 10:58:45 +00:00
Evgeny Poberezkin 03d73f442f JSON instance for VersionRange (#1036) 2024-03-08 10:01:58 +00:00
Evgeny Poberezkin 8ff4c628b5 pqdr: make envelope sizes dependent on version, test enabling PQ (#1035) 2024-03-08 08:28:15 +00:00
spaced4ndy 5e23fa6cfc agent pq: connRequestPQSupport api (#1034) 2024-03-07 19:44:48 +04:00
Alexander BondarenkoandEvgeny Poberezkin dd22b5c823 core: tweak compress api (#1029)
* convert compress to a wrapper with passthrough fallback

* add compress1 for non-batched compression

* use original size as upper bound for scratch

* refactor

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-03-07 14:17:32 +00:00
Evgeny Poberezkin 11288866f9 pqdr: refactor 2024-03-07 12:41:10 +00:00
Evgeny Poberezkin 07fa75ec49 pqdr: agent api to confirm PQ encryption support during connection handshake, fix incorrect PQ support (#1032)
* pqdr: agent api to confirm PQ encryption support during connection handshake

* fix CONF, tests

* fix REQ, tests

* remove unused
2024-03-07 08:35:40 +00:00
Evgeny Poberezkin 4ffb6a348a pqdr: use different newtypes for supporting and enabling PQ encryption in connections (#1031)
* pqdr: use different newtypes for supporting and enabling PQ encryption in connections

* rename field, fix test

* refactor
2024-03-06 21:28:03 +00:00
Evgeny Poberezkin b435a4dacb envelope sizes dependent on PQ encryption (#1028)
* envelope sizes dependent on PQ encryption (WIP)

* add "supported" flag to ratchets, update this flag on ratchet resync

* change connection PQ status on sendMessage

* comment, fix

* refactor
2024-03-06 16:38:30 +00:00
Alexander BondarenkoandEvgeny Poberezkin e04705d9c5 utils: add generic batching and compression (#1018)
* extract batchTransmissions_

* add Simplex.Messaging.Compression

* add combined compression/batching

* force NonEmpty for batching

* hide FFI and allocation related IO

* split packing

* remove batch compression, tweak API

* OCD over API

* remove Empty, extract passthrough const

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-03-06 09:10:49 +00:00
Evgeny Poberezkin b050cf5027 double ratchet versioning for post-quantum encryption (#1025)
* correctly parse new Ratchet fields when omitted

* rfc: migrating connection versions to pqdr

* update rfc

* WIP (dont commit)

* rename versions

* update ratchet version based on PQ encryption feature flag

* remove duplicate function

* synchronize ratchet, fix tests, refactor

* comments

* test

* pattern
2024-03-05 17:07:15 +00:00
Evgeny Poberezkin 52a67daea6 agent: pass PQ encryption flag separately for each message in batch APIs (#1027) 2024-03-05 11:09:07 +00:00
Evgeny Poberezkin ba1bfaa5aa Merge branch 'master' into pq 2024-03-04 20:13:01 +00:00
Evgeny Poberezkin dd2bd11584 parameterize version scopes with phantom types (#1026)
* parameterize version scopes with phantom types

* move Version to another module

* parens
2024-03-04 19:06:51 +00:00
Evgeny Poberezkinandspaced4ndy e06e22328f agent: quantum-resistant double ratchet encryption (#939)
* doc

* diff

* ratchet header

* types

* ratchet step with PQ KEM, message header with KEM

* comment

* update types, remove Eq instances, store KEM keys to database

* pqx3dh

* PQ double ratchet test

* pqdr tests pass

* fix most tests

* refactor

* allow KEM proposals from both sides

* test names

* agent API parameters to use PQ KEM

* initialize ratchet state for enabling KEM

* fix/test KEM state machine to support disabling/enabling via messages

* more tests

* diff

* diff2

* refactor

* refactor

* refactor

* refactor

* remove Maybe

* rename

* add PQ encryption status to CON, MID and MSG events and sendMessage API results

* different PQ parameter when creating connection

* rename/reorganize types for PQ encryption modes

* rename

* fix testWaitDeliveryTimeout

* rename

* rename2

* ghc8107

* rename

* increase timeouts for concurrent send/receive test

* enable all tests

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-03-03 19:40:49 +00:00
spaced4ndy 30fd4065d9 rename delete waiting delivery tests (#1022) 2024-03-03 12:56:54 +04:00
Alexander Bondarenko 246a0d10c2 xftp: raise internal upload limit to 5gb (#1020)
* xftp: raise internal upload limit to 5gb

* extract hard limit from agent
2024-03-02 18:46:05 +00:00
Evgeny Poberezkin ce78646c7f refactor creating connection record (#1021) 2024-03-02 18:27:51 +00:00
spaced4ndyandEvgeny Poberezkin 294d7ec8dd agent: delay connection deletion to finish delivery of pending messages (#1015)
* agent: delay connection deletion to finish delivery of pending messages (wip)

* fixes, test

* notify, test

* add tests

* comment

* add test

* timeout

* test timeout

* up

* more tests

* rename

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-02-29 18:08:58 +00:00
Evgeny Poberezkin c9ec7ea274 Merge branch 'stable' 2024-02-27 18:07:30 +00:00
Evgeny Poberezkin 5011ac2e7c Merge branch 'v5522' into stable 2024-02-27 17:58:08 +00:00
Evgeny Poberezkin 0987895926 5.5.2.2 2024-02-27 00:00:29 +00:00
2e3c961dab agent: optimize execution performance of slow memory operations during (re)subscriptions (#1013)
* agent: remove redundant set building

* tests: add tRcvQueuesTests (#1016)

* double accounting

* unit tests for invariants

* batch add queues

* ghc8107 compatibility

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2024-02-27 00:00:29 +00:00
spaced4ndyandEvgeny Poberezkin 050a921fbb agent: batch db operations for deleting connections and xftp files (#1009)
* agent: batch db operations for deleting connections

* batch delete rcv files

* snd files

* refactor

* refactor2

* lines

* refactor

* fix prefix path

* refactor

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-02-26 10:28:50 +00:00
Evgeny Poberezkin e2ec737c68 stop using public keys from table (#1014)
* stop using public keys from table

* comment
2024-02-25 16:19:04 +00:00
Alexander Bondarenko 95c0914809 agent: speed up SMP clientDisconnected (#1011) 2024-02-24 14:59:14 +00:00
Alexander BondarenkoandEvgeny Poberezkin 385463192b agent: extend worker summary (#1007)
* agent: extend worker summary with active/idle split

* simplify

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-02-24 13:29:36 +00:00
Evgeny Poberezkin d7394aa762 fix ntf server version range in the client 2024-02-22 19:33:14 +00:00
Evgeny Poberezkin 0d843ea4ce Merge branch 'stable' 2024-02-21 20:33:06 +00:00
Evgeny Poberezkin 04cd2aa4ad Merge pull request #1006 from simplex-chat/v5521
5.5.2.1
2024-02-21 20:07:34 +00:00
Evgeny Poberezkin a34da38966 Merge branch 'stable' into v5521 2024-02-21 19:28:30 +00:00
Evgeny Poberezkin 32c94df040 5.5.2.1 2024-02-21 14:13:07 +00:00
Evgeny Poberezkin 5c1519df7f optimize: use IntMap (#1005) 2024-02-21 11:52:24 +00:00
Evgeny PoberezkinandAlexander Bondarenko 03c24c3ada agent: fix performance leak, smp server: optimize and fix potential memory leak (#1004)
* fix agent performance leak when re-connecting clients, optimize SMP server

* let the clients remove themselves from their clientvars

* fix another test

* do not call removeSubs when AgentClient is not active

* revert some changes

* revert more, refactor

* comment

* rename

* refactor

* refactor

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
2024-02-21 11:45:34 +00:00
Evgeny Poberezkin 12dac60397 v5.6.0-beta.0 2024-02-18 16:31:48 +00:00
Evgeny Poberezkin 9b38f69e7e smp server: add stats for queues deleted before and after they were secured (#1002) 2024-02-18 16:25:32 +00:00
Evgeny Poberezkin 155831ae36 tests: test notification decryption 2024-02-18 09:30:21 +00:00
Evgeny Poberezkin 89140e0ff0 use package version for all servers (#1001) 2024-02-18 08:56:35 +00:00
Evgeny Poberezkin caeeb2df9c fix protocol in NTF server error 2024-02-17 15:32:44 +00:00
Evgeny Poberezkin 51be2fea20 agent: test NTF server (#1000) 2024-02-17 14:55:40 +00:00
Evgeny Poberezkin f6acc5c240 remove test chunk after XFTP server test (#999) 2024-02-16 23:24:57 +00:00
Evgeny Poberezkin abf956d425 fix tests for new protocol versions (#998)
* fix basic auth tests

* fix batching and syntax tests

* fix test matrix
2024-02-16 20:21:15 +00:00
Alexander Bondarenko 194a7bb58e agent: remove redirect entries when deleting rcv files (#995)
* agent: remove redirect entries when deleting rcv files

* update schema dump

* use rcv_file primary key for redirect lookup

* allow multiple redirects
2024-02-16 19:49:50 +04:00
Evgeny Poberezkin c179073260 remove support for old versions (#990)
* remove support for old versions (WIP)

* fix

* updates

* use version var
2024-02-16 13:28:50 +00:00
416f1b1721 smp: command authorization (#982)
* smp: command authorization

* fix encoding, most tests

* remove old tests

* authorize via crypto_box

* extract authenticator to Crypto module

* make TransmissionAuth Maybe

* rfc

* support authenticators in NTF protocol, test matrix (no backwards compatibility yet from new clients to old servers)

* fix/add tests, add version config to "small" agent

* separate client and server versions for SMP protocol

* test batching SMP v7

* do not send session ID in each transmission

* refactor auth verification in the server, split tests

* server "warm up" fixes timing test

* uncomment SUB timing test

* comments, disable two timing tests

* rename version

* increase auth timing test failure threshold

* use different algorithms to authorize snd/rcv commands, use random correlation ID

* transport: fetch and store server certificate (#985)

* THandleParams (WIP, does not compile)

* transport: fetch and store server certificate

* smp: add getOnlinePubKey example to smpClientHandshake

* add server certs and sign authPub

* cleanup

* update

* style

* load server certs from test fixtures

* sign ntf authPubKey

* fix onServerCertificate

* increase delay before sending messages

* require certificate with key in SMP server handshake

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>

* remove dhSecret from THandle

* remove v8, merge all changes to one version

* parameterize THandle

* rfc: transmission ecnryption

* Revert "parameterize THandle"

This reverts commit 75adfc94fb.

* use batch syntax for ntf server commands

* separate encodeTransmission when there is no key

* typo

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* rename

* diff

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-02-16 11:45:54 +00:00
Evgeny Poberezkin 9254d8dac5 v5.5.3 2024-02-16 11:33:56 +00:00
Alexander BondarenkoandEvgeny Poberezkin 9ab34bca7d cli: add cert command to xftp and ntf servers (#991)
Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-02-16 10:56:54 +00:00
spaced4ndy 6f62d7ff05 agent: add numRecipients parameter to send description (#993) 2024-02-15 13:24:46 +04:00
Alexander Bondarenko 7275714b8e cli: configure server paths from env (#992) 2024-02-14 20:31:06 +00:00
spaced4ndy 004597c764 agent: add index to file redirect migration (#988) 2024-02-14 18:47:39 +04:00
Alexander BondarenkoandEvgeny Poberezkin 2f7a288280 xftp: add sending and receiving via URI-encoded redirects (#968)
* xftp: add URI encoding for FileDescription

* tweak URI

* allow smaller blocks

* draft xftpReceiveFileFollow' and xftpSendFilePublic'

* add sending with redirect

* allow 64k chunks

* add migrations with redirect fields

* add test case

* fix deadlock

* revert CLI code

* WIP: working send/receive via URI

* fix field ambiguity

* cleanup

* update agent db schema

* update minimal chunk size

* add rfc

* apply suggestions from code review

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>

* add createRcvFileRedirect

* extract Simplex.Messaging.ServiceScheme and reuse for files

* update db schema

* check size/digest on receive complete

* cleanup

* use SIZE/DIGEST errors for redirects too

* split digest/size errors from redirect checks

* fix redirect error encoding

* rename RedirectMeta to RedirectFileInfo

* use query encoding for file URI

* group maybe fields under RcvFileRedirect

* add extras field

* update rfc

* add extras encoding and no-redirect tests

* fix toStrict for old ghc

* extra client data in file descr URI

* remove decoded yaml file

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-02-13 14:08:49 +00:00
Alexander BondarenkoandEvgeny Poberezkin 57e7c8ef6b smp-server: add cert CLI command to rotate online certificate (#984)
* smp-server: add gen-online CLI command

* use CN and algo from old certificate

* add cert checks to test

* rename command

* fix test

* cert

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-02-12 20:17:08 +00:00
spaced4ndy 8de23c15ad agent: return ntf server in getNtfToken (#986) 2024-02-12 16:51:37 +04:00
Evgeny Poberezkin e64b6cba4b 5.5.2.0 2024-02-10 22:07:02 +00:00
Evgeny Poberezkin 189885c50d protocol: ignore tail bytes in handshake blocks to allow future extension (#983)
* protocol: ignore tail bytes in handshake blocks to allow future extension

* cleanup
2024-02-05 21:01:20 +00:00
Evgeny Poberezkin a516c2f72c 5.5.1.2 2024-02-02 08:19:02 +00:00
Evgeny Poberezkin 2ae1c9f79d agent: only retry connecting SMP clients when there are pending subscriptions (#981)
* agent: only retry connecting SMP clients when there are pending subscriptions

* fix

* remove retry on creating clients

* simplify
2024-02-01 16:17:37 +00:00
Alexander BondarenkoandEvgeny Poberezkin 24b84106a6 core: add activity tests to workers details (#980)
* core: add activity tests to workers details

* remove names

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-02-01 11:02:31 +00:00
Alexander BondarenkoandEvgeny Poberezkin 15bc027f23 core: fix reconnection bugs (#979)
* core: fix reconnection bugs

* untangle newProtocolClient

* refactor

* report busy clientVar error

* log error

* comments

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-02-01 10:55:50 +00:00
Alexander Bondarenko cb64dabf75 tests: fix sporadic failures from reading stats (#975) 2024-01-30 11:36:07 +00:00
Evgeny Poberezkin 7a0cd8041b 5.5.1.1 2024-01-22 14:06:52 +00:00
Evgeny Poberezkinandspaced4ndy fd4eeb36db agent: optimize expired messages query (#976)
* agent: optimize expired messages query

* schema

* fix query

* fix

* typo

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* fix

* refactor

* comment

* refactor2

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-01-22 14:04:57 +00:00
Evgeny Poberezkin 1e49f1c92d 5.5.1.0 2024-01-19 19:47:39 +00:00
f7cdec2f08 fix: support multiple notification servers in configuration (#971)
* tests: add trpl-keeps-server check

* add smp server switch check

* add connection test and fix withNtfServer

* Update src/Simplex/Messaging/Agent/NtfSubSupervisor.hs

Co-authored-by: Evgeny Poberezkin <e.poberezkin@me.com>

* use ntfServer from token

* rename

---------

Co-authored-by: Evgeny Poberezkin <e.poberezkin@me.com>
Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-01-19 19:42:28 +00:00
Evgeny Poberezkin 8ff89c19dc servers: do not keep stats file open during delays (#974) 2024-01-19 17:47:47 +00:00
Evgeny Poberezkin baf2c47065 agent: expire messages failed after quota exceeded after 7 days, and expire multiple messages at once (#973)
* agent: expire messages failed after quota exceeded after 7 days, and expire multiple messages at once

* fix, test

* refactor

* catch in loop
2024-01-19 17:21:25 +00:00
Alexander Bondarenko 40fa34c2d5 tests: test multiple Ntf servers (#966)
* tests: add ntf case with multiple Ntf servers

* simplify test

* fix for master

* add server switch test

* add server switch test

* add message test for ntf server switch
2024-01-17 19:47:47 +00:00
Alexander Bondarenko eb41abfb8f tests: fix random order in async commands case (#969) 2024-01-17 11:48:41 +00:00
Evgeny Poberezkin b547f34cc0 Revert "Revert "agent: do not create user record in new databases (#957)" (#963)" (#964)
* Revert "Revert "agent: do not create user record in new databases (#957)" (#963)"

This reverts commit aee9088417.

* tests

* remove logging
2024-01-17 11:01:04 +00:00
Evgeny Poberezkin f6ed4640d4 5.5.0.6 2024-01-16 17:07:15 +00:00
Evgeny Poberezkin a0b35cec4f agent: fix potential race when good client can be removed instead of bad for the same transport session (#967)
* agent: fix potential race when good client can be removed instead of bad for the same transport session

* tryAgentError

* case
2024-01-16 13:45:51 +00:00
Evgeny Poberezkin 00c4ff4a21 agent: fix race condition in subscription worker (results in stuck delivery), better error handling in batch operations (#962)
* debugging test: join connection when reply queue creation fails

* more logs

* more logs

* more logs, fixed bug

* cleanup

* catch all errors

* simplify

* comment

* remove client ID counter
2024-01-16 10:29:35 +00:00
Evgeny Poberezkin aee9088417 Revert "agent: do not create user record in new databases (#957)" (#963)
This reverts commit 9b9a0bd0df.
2024-01-14 22:28:28 +00:00
Evgeny Poberezkin 7f7a77c4eb SMP protocol: optimize batching transactions, remove Builder (#961)
* remove Builder

* fewer chunks

* remove lazy bytestrings

* optimize

* pad
2024-01-14 20:42:47 +00:00
Alexander Bondarenko cd4329f2de agent: collect worker stats (#959)
* agent: collect worker stats

* add more workers

* process asyncCmdWorkers as a Map
2024-01-12 23:38:35 +00:00
Alexander BondarenkoandEvgeny Poberezkin 68f5e189a6 smp: check for progress when resubscribing (#956)
* smp: check for progress when resubscribing

* add allowClose to reconnectServer to distinguish entry points

* resolve error todo

* make reconnect async per-session

* remove allowClose

* deregister reconnecter when it finishes

* signal/react more work explicitly

* fix restart condition

* wait for reconnecter to finish

* remove redundant reconnect locks

* rename getClientVar for expanded scope

* formatting

* remove withPending

* move pending check to tryReconnectSMPClient loop

* combine pending check and slot release transactions

* actually reserve the slot for async

* simplify

* refactor

* refactor

* use removeClientVar

* rename

* refactor

* test

* reduce MonadError scope

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2024-01-12 19:29:18 +00:00
Evgeny Poberezkin 17f64e1565 docs: URI schemes (#958) 2024-01-12 17:21:57 +00:00
Evgeny Poberezkin 9b9a0bd0df agent: do not create user record in new databases (#957)
* agent: do not create user record in new databases

* update
2024-01-12 16:57:57 +00:00
Evgeny Poberezkin ad8cd1d515 5.5.0.5 2024-01-09 19:44:15 +00:00
Evgeny Poberezkin ca527b4d6c use Builder for batching commands (#953)
* use Builder for batching commands

* refactor

* refactor

* increase timeout in test

* do not materialize builder

* use concat

* debug test

* debug2

* delays

* more delay, less worker delay

* remove logs

* reduce delay

* tests

* sized builder

* builder

* comment

* remove unsafe

* style

* remove fromIntegral
2024-01-08 22:54:27 +00:00
Evgeny Poberezkin 55808b0c82 5.5.0.4 2024-01-06 11:40:15 +00:00
Evgeny Poberezkin fa794d7878 agent: send errors on subscription timeouts (#937)
* agent: debug server reconnections

* update lock only if it has the same name already

* report subscription timeouts

* clean up
2024-01-05 17:36:57 +00:00
Alexander BondarenkoandEvgeny Poberezkin 34056b9d7b xftp-server: add control port (#951)
Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2024-01-05 17:36:19 +00:00
Alexander Bondarenko 87cec9ad16 control: try deleting from senders first (#950) 2024-01-05 17:07:29 +00:00
Evgeny Poberezkin 2488cf1e3a agent: restart worker when it terminated (#948)
* agent: restart worker when it terminated

* comment

* remove writeTMVar

* remove writeTMVar 2

* remove writeTMVar 3
2024-01-05 14:22:26 +00:00
Alexander BondarenkoandEvgeny Poberezkin b4495bb4f0 xftp-server: fix stats (#944)
* xftp-server: fix stats

* count file expirations

* rename

* simplify

* check files size

* store and fix fileSize check

* do

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2024-01-05 11:30:27 +00:00
Alexander Bondarenko 6d4834f306 core: publish sendMessagesB (#949) 2024-01-04 15:37:13 +00:00
Evgeny Poberezkin 37d30240fd 5.5.0.3 2024-01-03 20:36:54 +00:00
Alexander BondarenkoandEvgeny Poberezkin 8fd5e9f25a servers: make writeStoreLogRecord atomic (#946)
* servers: make writeStoreLogRecord atomic

* comment

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2024-01-03 20:29:09 +00:00
Alexander Bondarenko 36298f2cea smp-server: update stats (#943)
* smp-server: check queue balance in stats vs store

* smp-server: add msgExpired stats

* add msgExpired stats

* split expire/stats transactions

* count and pass msgExpired explicitly

* save/load qCount and use it for checking store
2024-01-02 21:24:17 +00:00
Evgeny Poberezkin f954c2cd17 rfc: SMP proxies key scope and other considerations (#927)
* rfc: SMP proxies key scope and other considerations

* split line
2023-12-28 23:29:51 +00:00
Evgeny Poberezkin d0588bd0ac 5.5.0.2 2023-12-27 20:35:56 +00:00
Alexander BondarenkoandEvgeny Poberezkin 7eb7bd5e81 xftp-server: add inactiveClientExpiration (#936)
* xftp-server: add inactiveClientExpiration

* fix test config

* add test

* add xftpPing

* switch to PCEUnexpectedResponse

* remove watchdog when server quits

* rename, loop

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-12-27 20:31:19 +00:00
Alexander Bondarenko bb4de2e63c ci: limit releases to GHC-9.6.3 (#938) 2023-12-27 15:55:42 +00:00
spaced4ndyandEvgeny Poberezkin 22e1932372 xftp, ntf: refactor, reuse workers abstractions (#935)
* xftp: refactor, reuse workers abstractions (wip, test fails)

* rename

* refactor (tests pass)

* refactor2

* linebreaks

* do

* reuse worker abstractions for notifications

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-12-27 13:02:08 +04:00
spaced4ndyandEvgeny Poberezkin e43e4860b9 xftp: file workers cycle through pending files based on retries count (limit number of iterations per work item to prevent stuck delivery) (#930)
* xftp: test file reception - shouldn't get stuck if file is deleted on server

* comment

* expiration test

* approach

* wip

* sort by retries in other works, revert some diff

* revert diff

* modify tests

* refactor

* refactor

* remove prints

* apply to other workers

* remove import

* comment

* refactor

* revert queue size

* fix test

* rename

* comment, correct number of retries

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-12-26 22:20:25 +00:00
Alexander BondarenkoandEvgeny Poberezkin efe7ce27e7 control: add delete command (#933)
* control: add delete command

* logDeleteQueue only when found

* use default StrEncoding for CPDelete arg

* move stats update from main transaction

* use size

* stabilize AUTH timing tests

* more iterations

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-12-26 20:20:12 +00:00
Evgeny Poberezkin 577e3cf14d agent: add server msg IDs to agent logs, disable 2 tests (#934)
* agent: race when using agent via TCP

* remove logs

* enable tests

* comments

* use different databases for different clients

* enable all tests
2023-12-26 17:50:39 +00:00
Evgeny Poberezkinandspaced4ndy 7ddeca50e4 agent: mark work items failed (#931)
* agent: mark work items failed (WIP)

* add tests, created_at

* getWorkItem for snd and rcv files

* fix

* tests

* fix

* tests

* test

* tests

* rename

* fix,refactor

* add indexes

* update schema

* do not try to get more work when resuming an existing worker

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-12-26 17:00:42 +04:00
Evgeny Poberezkin 1e15d56e92 5.5.0.1: fix migration 2023-12-23 16:06:11 +00:00
Evgeny Poberezkin 46056557f8 5.5.0.1: update .cabal 2023-12-23 14:12:20 +00:00
Evgeny Poberezkin a57066a826 5.5.0.1 2023-12-23 13:42:22 +00:00
Evgeny Poberezkin 2489333c87 agent: use DB to queue async commands and messages (#929)
* agent: use DB to queue async commands and messages

* fix message delivery, async commands dont work

* fix async commands

* remove comment

* rename

* comment

* balance agent operation

* empty lines

* balance another agent operation

* diff

* worker

* qAddress

* fix incorrect queue ID in v1

* types for queues

* fix test

* update index
2023-12-23 12:59:53 +00:00
Evgeny Poberezkin fa457d1c25 agent: avoid race condition between worker and supervisor when getting work (#928) 2023-12-22 11:12:36 +00:00
Evgeny Poberezkin 1c2604f6a3 agent: background mode for agent NSE (#924) 2023-12-22 08:59:07 +00:00
Evgeny Poberezkin 13a60d1d39 use ChaChaDRG as the source of randomness (#920)
* use ChaChaDRG as the source of randomness

* remove functions using entropy directly

* comment
2023-12-21 00:12:08 +00:00
8c250ebe19 agent: batch sending messages (#922)
* agent: batch sending messages (attempt 4)

* handle errors in batch sending

* batch attempt 5 (#923)

* attempt 5

* remove IORefs

* add liftA2 for 8.10 compat

* remove db-related zipping

* traversable

---------

Co-authored-by: IC Rainbow <aenor.realm@gmail.com>

* s/mapE/bindRight/

* name

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* comment

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* remove unused funcs

---------

Co-authored-by: IC Rainbow <aenor.realm@gmail.com>
Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-12-19 23:01:34 +00:00
Evgeny Poberezkin 7627ce6b69 5.5.0-beta.0: SMP server/agent 5.5, XFTP server 1.2, NTF server 1.7 2023-12-19 16:07:11 +00:00
Alexander BondarenkoandEvgeny Poberezkin 7c27357eb2 server: stop inactive clients without subscriptions, additional monitoring via control port (#901)
* fix thread labelling points

* add subscription thread labels

* add explicit sections for sockets/sessions/disconnects

* adjust label threads wrt. next blocking op

* WIP: emit event on server finish

So the event log wouldn't be cut short giving
false impression of unterminated sessions.

* add handshake timeout

* hack server socket stats

* trace closeTLS exceptions

* fix build

* clean up disconnectTransport

* make disconnectTransport terminating

Thus, participating in racyAny_ around it.

* trach snd/rcv time separately, log clients as CSV

* add direct client counting/stats

* add csv dump for socket threads

* guard socket threads dump from older GHC

* cut socket thread listing into socket-threads command

* store client creation time for stats

* wrap tls setup in timeout and labels

* server: expire clients without subscriptions

* fix check for subscriptions

* remove excess tracing

* move hardcoded timeouts to configs

* cleanup

* fix tests

* wrap direct queue waits in timeout

* rewrite old TCP wrappers with their SocketState variants

* add testInactiveWithSubs

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-12-19 15:50:45 +00:00
Evgeny Poberezkin 18be2709f5 use crypton instead of cryptonite (#919) 2023-12-13 09:32:44 +00:00
Evgeny Poberezkin fb113ff008 agent: include queries longer than 5ms into slow queries (was 50ms) 2023-12-12 15:34:49 +00:00
Evgeny Poberezkin f576260594 client: increase default network timeouts (#918) 2023-12-12 12:01:38 +00:00
Evgeny Poberezkin 560dc55312 agent: notify about polled message processing (for iOS notifications) (#908)
* agent: notify about polled message processing (for iOS notifications)

* optionally keep key and support re-opening database

* exports

* test that cannot reopen when created with keepKey: false

* set max number of messages to receive for a notification to 3
2023-12-11 13:03:53 +00:00
Evgeny Poberezkin a860936072 agent: do not account for delivery of stored messages for agent suspension (#916) 2023-12-05 23:14:33 +00:00
sh e7b6b5facd docker: add missing dependency (#915) 2023-12-05 11:03:03 +00:00
Evgeny Poberezkin eaf5317834 compatibility with GHC 8.10.7, narrow dependency ranges (#914)
* Revert "raise mtl version to 2.3.1 (#912)"

This reverts commit 117168ccce.

* Revert "expand dependency ranges (#911)"

This reverts commit 90a8fc91d3.

* fix test

* remove unnecessary forks

* make text version dependent on GHC version

* text

* remove stack.yaml

* bytestring

* bytestring

* hpack 0.35

* mtl
2023-12-04 00:00:50 +00:00
Alexander Bondarenko 117168ccce raise mtl version to 2.3.1 (#912)
* raise mtl version to 2.3.1

* fix test on 8.10
2023-12-02 11:43:36 +00:00
Evgeny Poberezkin 76af9ed242 remove ghc 9.6.3 from cabal.project 2023-12-01 17:51:33 +00:00
Alexander Bondarenko 90a8fc91d3 expand dependency ranges (#911) 2023-12-01 13:08:26 +00:00
Alexander BondarenkoandEvgeny Poberezkin 6bffcc8503 compatibility with GHC 8.10.7 (#906)
* build with ghc-8.10

* add 8.10 to matrix

* cleanup

* stats

* remove getField

* agent

* server

* remote

* space

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-11-29 12:53:06 +00:00
Evgeny Poberezkin 3f2e50eebd 5.4.0 2023-11-28 22:36:32 +00:00
Evgeny Poberezkin cc8b8cd10d agent: fix hanging test (#907) 2023-11-28 22:25:58 +00:00
Alexander BondarenkoandEvgeny Poberezkin febf9019e2 remote: add controller address preferences (#905)
* remote: add controller address preferences

* suppress localhost from breaking multicast discovery w/o prefs

* rewrite findCtrlAddress

* refactor

* refactor2

* add tests

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-11-28 14:12:29 +00:00
sh 2a6be894e1 docker: bump ghc version (#904) 2023-11-27 23:41:52 +00:00
Evgeny Poberezkin 8fa369f9d3 5.4.0: xftp 1.1.3, ntf 1.6.4 (#903)
* 5.4.0: xftp 1.2.0, ntf 1.7.0

* upgrade ghc in github job

* change xftp, ntf versions

* shorter predicate for exception in test
2023-11-26 22:20:42 +00:00
Evgeny Poberezkin 31f520af05 rfc: message delivery problems (#743)
* rfc: message delivery problems

* update
2023-11-26 12:02:08 +00:00
Evgeny Poberezkin 7c29e2a189 rfc: delivery proxy (#760) 2023-11-26 11:59:57 +00:00
Evgeny Poberezkin f49607e522 rfc: SMP/XFTP proxies (#844)
* rfc: SMP/XFTP proxies

* update

* update

* update

* add threat model

* correction to encryption layer

* corrections
2023-11-26 11:57:56 +00:00
Evgeny Poberezkin 757b7eec81 5.4.0.6 2023-11-21 20:50:10 +00:00
Evgeny Poberezkin 88a4cf7d90 Merge pull request #898 from simplex-chat/ab/fix-agent-leak
agent: fix leak in AgentOpState counters
2023-11-21 20:43:32 +00:00
IC Rainbow 8ac97ed700 add retry around removing tmp dir 2023-11-21 21:30:53 +02:00
IC Rainbow 79d9f41fd8 add delay to testDuplicateMessage 2023-11-21 20:10:14 +02:00
IC Rainbow 2fe408666e fix testAsyncCommandsRestore test 2023-11-21 19:54:10 +02:00
IC Rainbow 317c68a860 agent: fix leak in AgentOpState counters 2023-11-21 14:53:53 +02:00
Evgeny Poberezkin c7a7323f54 list imports 2023-11-20 12:15:09 +00:00
spaced4ndy 044eca5ac4 5.4.0.5 2023-11-20 15:55:09 +04:00
Evgeny Poberezkin 0841067132 Merge pull request #880 from simplex-chat/xrcp
xrcp: SimpleX Remote Control protocol
2023-11-18 15:32:58 +00:00
Alexander BondarenkoandEvgeny Poberezkin 40ba94ce72 remote: add multicast discovery w/ encrypted announce (#895)
* Implement multicast discovery

* replace rcConnectMulticast with explicit discoverRCCtrl

* add multicast source/invitation host check

* remove JSON encoding for multicast invitations

* add specific error for announcing "new" controllers

* rename

* set size, rename

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-11-17 17:56:14 +00:00
Alexander Bondarenko c501f4f9cc remote: fix deadlocked client when server rejects its cert (#897)
* remote: detect tls errors sooner to prevent deadlocks

* remove redundant error checking

* cleanup
2023-11-17 10:37:32 +00:00
Evgeny Poberezkin 3b348a463c Merge branch 'master' into xrcp 2023-11-14 14:36:21 +00:00
spaced4ndy 7aae6f3cbe agent: fix case of ratchet synchronization getting stuck in endless loop (#892) 2023-11-14 17:55:20 +04:00
Evgeny Poberezkin d60911c780 xftp: refactor receiving encrypted file (#896) 2023-11-14 13:51:23 +00:00
Evgeny Poberezkin e0b7942e45 remote: return tls with remote host before host confirmation (#894) 2023-11-13 19:25:53 +00:00
Alexander Bondarenko 4f5d52ada4 Do not allow rejected client certificate (#893) 2023-11-13 17:57:26 +00:00
Evgeny Poberezkin c051ebab74 Merge branch 'master' into xrcp 2023-11-11 09:37:15 +00:00
Evgeny Poberezkin 9460551a04 5.4.0.4: xftp 1.1.2, ntf 1.6.3 2023-11-11 09:16:40 +00:00
Evgeny Poberezkin 6a2e6b040e additional lazy crypto for XRCP (#890) 2023-11-10 11:16:43 +00:00
Evgeny Poberezkin bd06b47a9d return TLS session on remote connection step (#891) 2023-11-09 22:27:30 +00:00
Evgeny Poberezkin 102487bc4f xrcp: error handling (#889)
* xrcp: error handling

* rename

* dont lock on STM

* move catch

* controller error handling

* fail sooner on incorrect CA in host HELLO

* remove TODO lock session

* refactor
2023-11-08 16:34:56 +00:00
Evgeny Poberezkin 248144f3de do not use previous KEM shared secret in multicast packets and in host HELLO (#888)
* do not use previous KEM shared secret in multicast packets and in host HELLO

* simplify
2023-11-08 12:06:10 +00:00
Alexander Bondarenko ecb23c66e0 Extract public RC types (#887) 2023-11-07 20:30:28 +00:00
Alexander Bondarenko c0566d37a0 add To/FromField instance to KEMShardKey (#886) 2023-11-07 17:09:38 +00:00
Alexander BondarenkoandEvgeny Poberezkin 1a8dfb4cbe agent: xrcp implementation for connection via link (no multicast) (#884)
* WIP: start working on connection invites

startSession/OOB is broken now - the port isn't coming from the actualy assigned one.

* Add invite types

* clean old invite-related types

* apply renames

* Move SessionKeys from Invitation

* Stub host-side keys and handle

* move keys and handles to Types

* add Simplex.RemoteControl.Client

* more keys

* progress

* crypto for sessions

* progress to multicast

* multicast crypto

* add RC TLS server

* agent api for remote control

* WIP: tls client

* fix test

* update encoding to include nonce

* add TODO

* update

* Use network-info to find TransportHost

* request and submit tls client certificate

* WIP: add missing bits for testing RC client

* RCEncryptedHello encoding

* add block encoding

* refactor

* validate known host certificate

* remove some spaghetti

* functional API to host/ctrl clients

* refactor connectRCCtrl_

* refactor connectRCHost

* question

* add type

* fix RC session

* update doc

* update doc 2

* add block on confirmation

* remove unused parameter

* export CtrlSessKeys

* export

* fix parsing

* move test of xrcp handshake

* move KEM to HELLO step

* fix JSON

* type

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-11-07 13:05:18 +00:00
Evgeny Poberezkin 1a0c4b73de Merge branch 'master' into xrcp 2023-11-04 18:26:01 +00:00
Evgeny Poberezkin e9b5a849ab update http2 to 4.2.2 (#879) 2023-11-01 10:57:19 +00:00
Evgeny Poberezkin a5fed340e2 hybrid shared secret X25519 + sntrup761 (#881)
* hybrid shared secret X25519 + sntrup761

* use IORef

* enable all tests

* update

* update

* use newtype

* move withDRG
2023-11-01 10:33:15 +00:00
Evgeny Poberezkin ce796ec225 Merge branch 'master' into xrcp 2023-11-01 09:24:06 +00:00
Evgeny Poberezkin 4660ee9cff agent: revert to TVar (#883) 2023-11-01 09:15:51 +00:00
Evgeny Poberezkin 70bf665938 Merge branch 'master' into xrcp 2023-10-31 23:52:45 +00:00
Evgeny Poberezkin b5f733d2db agent: use IORef for DRG (#882) 2023-10-31 23:52:13 +00:00
Evgeny PoberezkinandIC Rainbow c22c15a2e8 sntrup761 (#865)
* add sntrup761 source

* it compiles

* Wrap bindings in non-FFI types

Test passes with a dummy RNG.

* pass ChaChaDRG via FunPtr

* Add iOS smoke test at createAgentStore

* style

* add "ssl" library dep

Attempt to fix missing _SHA512 symbol on macos.

* remove sha512 wrapper and use openssl directly

* restore names, remove dummy RNG

* Revert "remove sha512 wrapper and use openssl directly"

This reverts commit f9f7781f09.

* restore code from RFC

* shorter names

* enable all tests

* remove run test

---------

Co-authored-by: IC Rainbow <aenor.realm@gmail.com>
2023-10-31 22:44:46 +00:00
Evgeny PoberezkinandAlexander Bondarenko db1b2f77cd rfc: SimpleX Remote Control protocol v2 (#874)
* rfc: SimpleX Remote Control protocol

* tweak rfc sections

* rfc: SimpleX Remote Control protocol v2

* add session verification

* add alternative design

* add KEM to rfc

* key agreement

* add pad

* pad

* padding

* remove marker from multicast packet

* update

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
2023-10-31 19:39:42 +00:00
Alexander BondarenkoandEvgeny Poberezkin 8e2ffcb297 extract xrcp protocol (#878)
* xrcp: files and folders

* extract remote up to rev-http

* Remove unused files

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-10-31 19:31:53 +00:00
Alexander BondarenkoandEvgeny Poberezkin 0410948b56 add runTransportWith (#875)
* Cut transport server to allow custom tcp servers

Allows socket inspection before wrapping up in a transport/prototocol.

* rename

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-10-27 14:40:53 +01:00
Evgeny Poberezkin 511d793b92 derive JSON instances with TH (#869)
* derive JSON instances with TH

* defaultJSON

* remove ToJSON
2023-10-26 09:20:30 +01:00
Evgeny Poberezkin 5f750a6783 docs: amend SMP protocol transmission encoding (#843)
* docs: amend SMP protocol transmission encoding

* base64 encoding

* remove "optional"
2023-10-25 17:52:02 +01:00
spaced4ndy d920a2504b agent: check confirmed snd queue doesn't exist before replacing (#871) 2023-10-25 09:48:54 +04:00
spaced4ndy 55a6157880 agent: change invLocks key type to ByteString 2023-10-24 17:20:39 +04:00
spaced4ndy 73d7f84ee3 agent: take invitation lock on join (#870) 2023-10-24 16:55:57 +04:00
Evgeny Poberezkin cf8b9c12ff remove test dependencies (#861)
* remove test dependencies

* .hlint.yaml
2023-10-22 10:50:36 +01:00
sh 9994375c16 docker: workaround for xftp quota format (#862) 2023-10-22 09:26:36 +01:00
Evgeny Poberezkin 9d12d76078 add fourmolu (#868)
* add fourmolu

* linebreak

* simplify

* comment
2023-10-22 09:20:14 +01:00
spaced4ndy deb3fc7359 agent: order by internal id when retrieving pending messages (#867) 2023-10-19 20:17:12 +04:00
spaced4ndy 80905c0822 test concurrent send and receipts (#866) 2023-10-19 20:08:58 +04:00
Evgeny Poberezkin decf25d7dc refactor http2 file (#864)
* refactor http2 file

* move fileBlockSize to HTTP2.File
2023-10-19 10:25:21 +01:00
Evgeny Poberezkin 5e047f3199 update http2 to 4.1.4 2023-10-18 13:26:38 +01:00
spaced4ndy 1ad69cf74f agent: always parse connection request uri as simplex:/ (#863) 2023-10-16 18:25:56 +04:00
Evgeny Poberezkin 696fa652a5 agent: always return simplex:/ links in invitations 2023-10-12 14:54:37 +01:00
Evgeny Poberezkin 6b0da8ac50 export JSON tags as patterns 2023-10-07 14:21:15 +01:00
Evgeny Poberezkin 9195509485 update aeson to add tag to platform-specific single field JSON encoding (#859)
* update aeson to add tag to platform-specific single field JSON encoding

* refactor
2023-10-07 12:30:26 +01:00
Alexander BondarenkoandEvgeny Poberezkin 96a38505d6 add FromJSON instances (#856)
* Add FromJSON instances

* add missing FromJSON instances

* more JSON instances

* update comments

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-10-05 15:57:53 +01:00
Alexander BondarenkoandEvgeny Poberezkin 753a6c7542 add X509 cert and TLS credentials generator (#857)
* Add X509 cert and TLS credentials generator

* Expand Crypto toolkit and rewrite tls credentials with it

* Exclude X keys from SignatureAlgorithmX509 and TLS.PrivKey

* Add helpers for DB marshalling and fingerprints

* Derive public key from private

* remove module name from selectors

* Remove StrEncoding (PrivateKey Ed25519)

* remove comment

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-10-03 13:43:21 +01:00
Alexander Bondarenko ec1b72cb80 Run HTTP2 sessions over existing TLS transport (#852)
* Split HTTP2 server and client setup

For attaching to an existing TLS session.

* Add genTlsCredentials

* Allow chain construction from separate credentials

So the CA may be stored and leaf ephemeral.

* Rewrap X509 fingerprint into simplex KeyHash used in transport

* Fix docstring

* Remove TLS.Credentials generator
2023-09-27 17:29:39 +01:00
Evgeny Poberezkin fda1284ae4 agent: support closing and re-opening store (#855)
* agent: support closing and re-opening store

* add closed flag, tests
2023-09-27 12:50:24 +01:00
Evgeny Poberezkin 8d47f69083 agent: fix creating empty file for XFTP to close file (#851) 2023-09-21 11:57:00 +01:00
Evgeny Poberezkin 3828a9591c unpin unix package (#850) 2023-09-20 18:32:03 +01:00
Evgeny Poberezkin 81385e39bf Merge branch 'master-ghc9' 2023-09-18 21:18:45 +01:00
Evgeny Poberezkin fee897f367 fix unix to 2.8.1.1 2023-09-18 20:59:02 +01:00
sh f2d832fe20 Dockerfile: update cabal and ghc versions (#848) 2023-09-18 13:27:18 +03:00
Evgeny Poberezkin 57d08c0e36 Merge branch 'master' into master-ghc9 2023-09-17 22:30:46 +01:00
Evgeny Poberezkin 00b48babf3 5.4.0.3: ntf 1.6.2 2023-09-17 22:23:00 +01:00
Evgeny Poberezkin 0b488ceb66 ntf server: faster restoring from store log (#846)
* ntf server: faster restoring from store log

* only log sub status when changed
2023-09-17 15:16:24 +01:00
Evgeny Poberezkin 887ccbcf6c Merge branch 'master' into master-ghc9 2023-09-10 18:00:33 +01:00
Evgeny Poberezkin 0cabe0690b 5.4.0.2: xftp 1.1.1, ntf 1.6.1 2023-09-10 17:44:37 +01:00
84ce037867 extend SMP protocol to allow creating new queues without subscriptions (#839)
* Trace auto-subs flag

* Replace Bools with SubscriptionMode

* Handle SMOnlyCreate

* Wire remaining todos

* Update tests and fix

* Bump protocol level

* Apply suggestions from code review

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>

* Scrub needs_sub from agent DB

* Scrub a few more needSubs from the agent api

* change API, fix test

* agent: do not subscribe to queue when creating reply queue

* fix encoding

* WIP: SMOnlyCreate test

* Add SM guard for confirmQueue

Allows the test case to pump the allowConnection
reply without getting PROHIBITED.

* Remove tracing

* add noMessages, remove unnecessary getConnectionMessage from test

* add sending messages to the test

---------

Co-authored-by: IC Rainbow <aenor.realm@gmail.com>
Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
2023-09-10 17:07:19 +01:00
Evgeny Poberezkin 504465f8e2 xftp: add 64kb file chunk (#842)
* xftp: add 64kb file chunk

* disable chunk size 64kb in the agent

* revert rename
2023-09-08 13:31:11 +01:00
spaced4ndy 351f42650c export isCompatibleRange function (#841) 2023-09-06 15:42:47 +04:00
Evgeny Poberezkin 980e5c4d1e agent: add debugging info (#840) 2023-09-04 22:02:12 +01:00
Evgeny Poberezkin 17a1a911d8 import stateTVar 2023-09-01 22:24:53 +01:00
Evgeny Poberezkin 5dc3d739b2 agent: support encrypted local files (#837)
* agent: support encrypted local files

* migration, update store, api

* tests, fix

* use CF.plain
2023-08-31 22:43:58 +01:00
Evgeny Poberezkin dc65197cfd Merge branch 'master' into master-ghc9 2023-08-26 16:54:09 +01:00
Evgeny Poberezkin 4c0b8a31d2 agent: create parent folders when creating the database 2023-08-26 16:53:31 +01:00
Evgeny Poberezkin cffbd39f4e 5.4.0.1 2023-08-26 16:04:40 +01:00
Evgeny Poberezkin a67669287a Merge branch 'master' into master-ghc9 2023-08-26 16:03:10 +01:00
Evgeny PoberezkinandAlexander Bondarenko 7bdae793cb server: add control port commands for clients and ghc threads (#836)
* server: add control port commands for clients and ghc threads (#835)

* Add stats-rts control query

With supporting ghc-options that would provide the data.

* Add CPSkip command

Allows spamming empty lines a few times to clean up the view.

* server: Add CP commands to enumerate clients and threads

* style

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>

* use base64 encoding for session ID

* fromMaybe

* whitespace

---------

Co-authored-by: Alexander Bondarenko <486682+dpwiz@users.noreply.github.com>
2023-08-26 16:02:18 +01:00
Alexander BondarenkoandEvgeny Poberezkin 4eb3b8e113 server: add env lookups for smp server paths (#817)
* Add env lookups for smp server paths

Allows running smp-server without touching system paths.
Can be helpful for running multiple instances.

* allow empty env var values

* diff

* fix

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-08-26 15:54:26 +01:00
Evgeny Poberezkin ed05428227 Merge branch 'master' into master-ghc9 2023-08-25 14:11:51 +01:00
Evgeny Poberezkin 066d91b0f5 agent: export SubInfo 2023-08-25 09:20:12 +01:00
Evgeny Poberezkin 414b019ad4 agent: function to debug agent subscriptions (#834)
* agent: function to debug agent subscriptions

* add Show instances
2023-08-24 23:19:48 +01:00
Moritz AngermannandEvgeny Poberezkin 002f36dde0 5.4.0.0: use ghc 9.6.2 (#791)
* Add 9.6 compat

* compile with GHC9.6.2: dependencies, imports, code

* refactor typeclasses

* refactor record dot

* update cabal version

* update github actions

* update direct-sqlcipher

* 5.4.0.0

* update cabal.project

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-08-24 20:22:02 +01:00
Evgeny Poberezkin b001b748db agent: rename functions, remove unused code, stabilize tests (#830)
* agent: rename functions, stabilize tests

* test pattern match
2023-08-24 19:52:58 +01:00
Evgeny Poberezkin ec268e2006 agent: wait while agent is in foreground to continue xftp operation (#831) 2023-08-24 19:11:44 +01:00
Evgeny Poberezkin a97c7da48a changelog 2023-08-23 12:06:39 +01:00
Alexander Bondarenko fcce544488 Pin GHC version in cabal.project (#815)
Allows building without switching user-preferred version.
2023-08-23 11:59:25 +01:00
Evgeny Poberezkin a302b601ea docs: comment in the protocol doc 2023-08-21 17:41:30 +01:00
Evgeny Poberezkin 44abb90c63 agent: fix async join to avoid sending HELLO again after restart (#829)
* agent: fix async join to avoid sending HELLO again after restart

* update test

* add callstack to test

* improve test
2023-08-21 14:35:46 +01:00
Evgeny Poberezkin d09adb5cd6 agent: wait for db (Revert Revert db error busy treatments (#796) (#808)) (#828)
* Revert "Revert "db error busy treatments (#796)" (#808)"

This reverts commit 82aec2cd8f.

* update test

* combine pragmas
2023-08-21 09:06:51 +01:00
Evgeny Poberezkin b329eb9a86 agent: fix async JOIN (#827)
* agent: fix async JOIN

* refactor
2023-08-20 18:45:16 +01:00
Evgeny Poberezkin 40e6d16e48 client: streaming batched commands, refactor (#826) 2023-08-19 16:11:05 +01:00
Evgeny Poberezkin f3111f4559 client: batch while sending commands - wait for responses before sending the next batch (#825)
* client: batch while sending commands - wait for responses before sending the next batch

* fix comments

* fix tests
2023-08-18 21:02:47 +01:00
spaced4ndy cf2a17b80c agent: track count and average time for slow queries (#824) 2023-08-16 20:14:27 +04:00
spaced4ndy e586bef57a agent: add indexes to improve slow queries performance (#823) 2023-08-16 10:29:09 +04:00
Evgeny Poberezkin e2065ab352 agent: track slow SQL queries (#822)
* agent: track slow SQL queries

* add executeMany

* reduce threshold for slow queries to 50ms
2023-08-12 18:18:10 +01:00
Evgeny Poberezkin 43f283471c Merge branch 'stable' 2023-08-12 08:20:50 +01:00
Evgeny Poberezkin a1e56979b7 Merge commit 'fdbfe0e8d159f394f6eb0f5168620da8694033cd' into stable 2023-08-12 08:20:03 +01:00
Evgeny Poberezkin 6446edd1a6 Merge branch 'stable' 2023-08-12 08:19:25 +01:00
Evgeny Poberezkin 82aec2cd8f Revert "db error busy treatments (#796)" (#808)
This reverts commit 1afcefa5e7.
2023-08-09 12:24:03 +01:00
Evgeny Poberezkin fdbfe0e8d1 5.3.0.1 2023-07-22 13:21:53 +01:00
spaced4ndy e81f3b5529 add indexes (#809) 2023-07-22 13:20:49 +01:00
Evgeny Poberezkin 6314bb1706 agent: partially fix message queries, debug message times (#810)
* agent: partially fix message queries, debug message times

* fix more joins
2023-07-22 13:00:25 +01:00
Evgeny Poberezkin c54be32135 Revert "agent: expire messages on quota errors (#801)" (#807)
This reverts commit 3fee468051.
2023-07-22 09:16:06 +01:00
spaced4ndy 7e2b309450 migration to delete expired messages (#801 is suspected to have caused temporary traffic increase due to flood of non expired messages) (#806) 2023-07-20 16:15:33 +04:00
spaced4ndy 4ed40fa5d5 enable a test in CI ("should resume sending file after restart") (#800) 2023-07-17 20:33:25 +04:00
Evgeny Poberezkin de95119ca6 5.3.0.0 2023-07-15 13:35:09 +01:00
Evgeny Poberezkin 4fae7dcaee server: control port (#804)
* server: control port

* do not remove messages when saving via control port

* remove unused record fields

* fix tests
2023-07-15 13:33:00 +01:00
Evgeny Poberezkin d989d11478 server: refactor restoring store log (#803) 2023-07-15 10:37:08 +01:00
Evgeny Poberezkin 1901e96ecc server: make main SMP server queues unbounded (#802) 2023-07-14 21:07:45 +01:00
Evgeny Poberezkin 3fee468051 agent: expire messages on quota errors (#801) 2023-07-14 18:13:54 +01:00
Evgeny Poberezkinandspaced4ndy 58cb2855d2 agent: delivery receipts (#752)
* rfc: delivery receipts

* update doc

* update rfc

* implementation plan, types, schema

* migration, update types

* update types

* rename migration

* export MsgReceiptStatus, JSON encoding

* update rfc, schema

* correction

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* skeleton of the implementation

* more implementation (some tests fail)

* more code, 1 test fails

* fix encoding

* refactor

* refactor

* test, fix

* only send receipts in v3+, test

* flip condition

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* flip condition

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* agent version 4 required to send receipts

* fix test

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-07-13 22:33:48 +01:00
Evgeny Poberezkin 745a144e0c 5.2.1 (ntf 1.5.1, xftp 1.0.1) (#799) 2023-07-13 19:23:06 +01:00
Evgeny Poberezkin 4c6c436e7f resubscribe in batches in Client.Agent (#798)
* resubscribe in batches in Client.Agent

* fix test
2023-07-12 07:35:38 +01:00
Evgeny Poberezkin b61e3b5f95 server: disable transport timeout (#793) 2023-07-11 19:43:31 +01:00
Evgeny Poberezkin 58dbc197ce increase TCP timeout for clients (#797) 2023-07-11 18:54:14 +01:00
spaced4ndy 1afcefa5e7 db error busy treatments (#796) 2023-07-11 20:19:20 +04:00
Evgeny Poberezkin 532cd2f39c fix allFinally 2023-07-09 21:36:23 +01:00
Evgeny Poberezkin 2f5c646e55 test with catchError/tryError 2023-07-09 18:38:44 +01:00
Evgeny Poberezkin f76a5ca5b6 agent: catch IO errors correctly in MonadError (#795)
* agent: catch IO errors correctly in MonadError

* correction

* correction

* utils

* agentFinally to catch IO exceptions in ExceptT

* rename

* remove, inline

* rename utils

* utils unit test

* test to show catch and finally problems

* tryAllErrors

* enable all tests
2023-07-09 18:04:45 +01:00
spaced4ndy f2657f9c0b add crypto error to RSYNC event (#794) 2023-07-05 18:14:51 +04:00
Evgeny Poberezkin fe22d9b299 agent api to reconnect all servers (#792) 2023-07-04 22:54:45 +01:00
Evgeny Poberezkin 75fe28a8a6 lint 2023-07-03 17:43:56 +01:00
Evgeny Poberezkin 54dc8d42e7 5.2.0, ntf server 1.5.0 (#790) 2023-07-03 13:32:58 +01:00
spaced4ndy 0e1562deae increase connection agent version according to received messages; add version and flags to connection stats, bump currentSMPAgentVersion (#789) 2023-06-30 20:19:10 +04:00
Evgeny Poberezkin 94540a2c71 servers: add TCP timeouts to avoid memory leaks (#776)
* servers: add TCP timeouts to avoid memory leaks

* fix tests

* only use RecvTimeOut

* servers: simple timeout for TCP transport

* revert dependency change

* simplify

* simplify

* simplify 2
2023-06-30 16:22:01 +01:00
Evgeny Poberezkin 16367fcb3b make timeouts for batched functions dependent on the number of batches (#786)
* make timeouts for batched functions dependent on the number of batches

* fix

* refactor

* refactor

* change import

* refactor

* rename function

* rename

* refactor

* remove space
2023-06-30 12:26:09 +01:00
spaced4ndyandEvgeny Poberezkin 8be2505fa0 ratchet re-synchronization (#774)
* ratchet re-synchronization rfc wip

* additions

* additions, types

* fix tests

* re-sync implementation wip

* re-sync implementation 1st rev.

* test wip

* test passes

* doc

* wording

* improve doc schema

* single agreed state

* refactor (1 state variable)

* allowed -> required

* prohibit enqueue

* enqueue

* send via multiple queues

* test with server offline

* clarify errors

* rename

* more tests

* refactor

* rename AgentRKey

* rename AM_CONN_RATCHET_KEY

* more tests

* rename

* write encoded AgentRatchetInfo to AgentRatchetKey info

* move withConnLock

* refactor qDuplex

* re-create ratchet on receiving second key

* invert condition

* refactor

* simplify

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-06-30 14:17:08 +04:00
spaced4ndy a000419bd7 restore confirmation after client restart (#783) 2023-06-29 10:10:34 +04:00
spaced4ndy c8a8e2c297 differentiate agent INACTIVE error, treat as temporary (#784) 2023-06-29 10:00:53 +04:00
Evgeny Poberezkin f7d038ef20 agent: more batched commands (#782)
* agent: more batched commands

* layout
2023-06-28 19:50:11 +01:00
Evgeny Poberezkin 4a927d1ae2 ntf server: better batching and logging (#780)
* ntf server: better batching and logging

* reduce batch delay for ntf server

* comments

* 5.1.3, ntf 1.4.2

* more logging

* more logging

* split large batches, more logging

* remove some logs
2023-06-26 20:14:35 +01:00
spaced4ndy 3a74558e84 fix connection switch status db encoding (#781) 2023-06-26 21:03:46 +04:00
Evgeny Poberezkin e3fff98b1b 5.1.2, ntf server 1.4.1 2023-06-25 09:31:55 +01:00
Evgeny Poberezkinandspaced4ndy acea477aab batch subscriptions for ntf server (#778)
* return updated ConnectionStats from switchConnectionAsync (#777)

* batch ntf server subscriptions to SMP servers

* refactor

* fix filtering queues in reconnect

* test, remove repeated grouping

* enable all tests

* reduce subscriptions count

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-06-25 08:27:50 +01:00
spaced4ndy c31668ce28 return updated ConnectionStats from switchConnectionAsync (#777) 2023-06-19 14:51:14 +04:00
spaced4ndy 2efe1496d2 rename "stop switch" -> "abort switch", add canAbortSwitch to rcv queue info (#775) 2023-06-16 13:41:01 +04:00
spaced4ndyandEvgeny Poberezkin 011e1109e9 connection switch - track status, stop switch command (#764)
* connection switch improvements

* stop in transaction

* refactor

* checks in transaction

* withSwitchingRQ in transaction

* withSwitchedSQ in transaction

* refactor

* refactor

* inverse some cases

* reset snd switch progress on repeat qadd

* remove unused functions

* connection info type

* correction

* SPFinalizing phase, correctly update connection in event

* refactor

* tests

* refactor switch conn lock taking, take lock in switch stop, remove ineligible test

* comment

* corrections

* corrections

* corrections

* refactor

* remove checks in transactions, remove some statuses

* remove diff

* refactor

* refactor tests

* update connection in memory

* revert diff

* corrections

* more tests

* remove statuses, change switching queue lookup

* async queue deletion

* refactor

* lock, phases

* test status

* refactor

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-06-15 11:15:46 +04:00
spaced4ndy fbf1afc9f5 run a single batch test to avoid hanging on server disconnect (#773) 2023-06-13 19:36:47 +04:00
sh 20dc00d96d install: simplify systemd service and add new helper stopscript (#771)
* install: simplify systemd service and add new helper stopscript

* README: update hash
2023-06-05 13:13:20 +04:00
sh 862aa29a6f install: some more fixes (#770) 2023-06-05 13:13:20 +04:00
sh ec6e44f034 install.sh: fixes (#765)
* install.sh: fixes

* change back to stable
2023-06-05 13:13:20 +04:00
sh 76e3863cbb install: simplify systemd service and add new helper stopscript (#771)
* install: simplify systemd service and add new helper stopscript

* README: update hash
2023-06-05 13:01:16 +04:00
sh 1c2fbdb2c5 install: some more fixes (#770) 2023-06-05 11:12:09 +04:00
sh 1822296481 install.sh: fixes (#765)
* install.sh: fixes

* change back to stable
2023-06-05 10:27:02 +04:00
spaced4ndy b747080db3 add more message delivery tests (#763) 2023-06-02 18:00:24 +04:00
tcely 20f7b538e5 Docker entrypoint fixes (#753)
* docker entrypoint: DRY store log backup

Don't Repeat Yourself

Set a variable for the full path to the source file.

Create the backup path by appending an extension from `date` output.

Also fixed quoting and switched to an `if` block.

Clean up block level variables.

* docker entrypoint: use ISO 8601 format

The previous format discards information about the local time zone.

* docker entrypoint: always use UTC

Now the format always ends in +00:00, and we can ignore that part again.

* docker entrypoint: provide the date format again

* docker entrypoint: remove time zone from the date format

* docker entrypoint: use an unambiguous date format

Present a leading zero before the month:
YYYY-0MM-DD

Both YYYY-MM-DD and YYYY-DD-MM are used by people and can be confusing in the beginning of the month.

* docker entrypoint: use appropriate quoting

Without avoiding field splitting a password containing a space changes the number of arguments being set.

* docker entrypoint: use explicit braces for custom variables

Make the intentions clear and don't assume the user knows the special cases for when variables won't be extended.

Example:
word=animal
words=mistake
echo "$words vs $word vs ${word}s"

* docker entrypoint-xftp-server: braces and quoting

* docker entrypoint-xftp-server: backup block

* docker entrypoints: explain date format in a comment

* switched from long to short option to date for POSIX

* docker entrypoint-smp-server: explain date format

* docker entrypoint-xftp-server: explain date format

* docker entrypoints: further explain format

I fixed the case to match the date format letters.

Also, use words to explain since I don't want everyone to need to read about date formats to understand.

* docker entrypoints: only quote letters

I was either going to quote the dashes too or stop quoting the colons.

Having less quotes was more readable.

* Revert "docker entrypoint: use an unambiguous date format"

This reverts commit ba2a93bad9.

* docker entrypoints: remove %F

* docker entrypoint-smp-server: remove %F

Used part of the explicit ISO 8601 format,
provided by the coreutils date invocation guide.

* docker entrypoint-xftp-server: remove %F

Used part of the explicit ISO 8601 format,
provided by the coreutils date invocation guide.
2023-05-29 14:12:23 +03:00
Evgeny Poberezkin 89caf55729 agent: ack message in case of decryption error (#759) 2023-05-27 18:28:14 +01:00
Evgeny Poberezkin c08cfb460b 5.1.1 2023-05-27 15:54:40 +01:00
Evgeny Poberezkinandspaced4ndy 03eca19d38 server: expire messages when restoring them (#758)
* server: expire messages when restoring them

* add test

* specify constructor

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* improve test

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-05-27 15:52:49 +01:00
Evgeny Poberezkin a5a3a2cbad server: increase server main queue size 2023-05-27 15:18:53 +01:00
spaced4ndy 4a3c5abf32 add with withTransaction version with logging (#757) 2023-05-26 20:33:48 +04:00
spaced4ndy 6c6f22051d check previous encrypted message hashes for duplicates on decryption errors (#756) 2023-05-17 15:42:57 +04:00
spaced4ndy d693868bc0 change implementation of time diff calculation (#754) 2023-05-15 20:26:18 +04:00
spaced4ndy 32a64b994e remove agentOperationBracket from file transfer (#755) 2023-05-15 20:23:18 +04:00
Evgeny Poberezkin a83f85dc58 5.1.0: smp 1.4.0, xftp 1.0.0 2023-05-12 22:01:32 +01:00
sh 0f7ede5eed docker+scripts: XFTP servers installation, update docs, install scripts (#750)
* docker: major overhaul with xftp support

* github: update docker actions

* install: add installation scripts

* readme: update readme to reflect latest changes
2023-05-12 10:45:04 +01:00
spaced4ndy ce64c91d5a add indexes for reading pending files (#751) 2023-05-10 15:17:26 +04:00
66177fd550 Add shumvgolove to CODEOWNERS (#747)
* CODEOWNERS: add shumvgolove for docker scripts

* CODEOWNERS: add shumvgolove for Dockerfiles

* CODEOWNERS: add shumvgolove for main scripts

* update

---------

Co-authored-by: shum <shum@liber.li>
Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-05-09 20:08:17 +01:00
Evgeny Poberezkinandspaced4ndy 9d83a9c017 configure message/file expiration time in INI file (#749)
* configure message/file expiration time in INI file

* correct comment

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-05-09 20:07:42 +01:00
tcely 019db0ab91 DRY build.Dockerfile (#748)
In addition to Don't Repeat Yourself, using ENV shows the versions used in the image history.
2023-05-09 20:06:12 +01:00
spaced4ndyandEvgeny Poberezkin 8954f39425 agent: vacuum on migrations (#745)
* agent: vacuum on migrations

* vacuum after all migrations

* style

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-05-04 17:26:05 +04:00
Sam A 4d96e3700c Add GH Actions workflow to build and push Docker image (#734)
* Add GH Actions workflow to build and push Docker image on release

* Use a matrix to support building other applications

* Rename application from simplexmq to smp-server

* Remove linux/386 platform

* Remove linux/arm64 platform
2023-04-26 08:53:34 +01:00
sh eaa8221b95 docker: adjusments (#737)
* docker: workaround for cabal

* docker: use llvm-12

See: https://gitlab.haskell.org/ghc/ghc/-/issues/21936

* docker: switch to jammy
2023-04-25 11:31:15 +01:00
spaced4ndy af3f70829d xftp: remove user id from internal deletion apis (#739) 2023-04-25 12:48:10 +04:00
spaced4ndy ff8197b87b xftp: check encrypted file exists when uploading (#738) 2023-04-24 19:45:30 +04:00
sh fd96ee2840 docker: revert buildplatform (#736)
* docker: revert buildplatform

* docker: only build smp-server
2023-04-24 13:34:26 +01:00
sh 605970f6b6 docker: refactoring (#735)
* build: switch ubuntu image to lunar

* dcoker: support multi-platform builds

* docker: strip binary

* docker: multicore execution

* readme: change docker hub to smp-server
2023-04-24 11:10:05 +01:00
sh dc40c3461a docker: fix docker logs and add build arg (#733) 2023-04-23 15:29:19 +01:00
Evgeny Poberezkin 4da637a565 5.0.0 (#728)
* 5.0.0

* correction

* update
2023-04-20 13:53:09 +01:00
spaced4ndy 23cecc7b68 xftp: test file deletion restores after restart (#727) 2023-04-17 13:34:58 +04:00
Evgeny Poberezkin 9692e636ac support ipv6 (#715)
* support ipv6

* fix

* refactor

* only listen to ipv6

* refactor

* refactor 2

* 3

* fix build?

* fix release
2023-04-15 21:40:02 +01:00
Evgeny Poberezkin 2b93e0b17d report ratchet decryption errors from agent (#720)
* report ratchet decryption errors from agent

* agent crypto errors
2023-04-14 20:05:29 +01:00
spaced4ndy 9f0b9a83d6 xftp: use chunk digest as entity id for transport session (#725) 2023-04-14 13:01:14 +04:00
Evgeny Poberezkin 27cfc4c62b move assertForeground (#724) 2023-04-14 12:52:18 +04:00
spaced4ndy 5e39c47975 Merge pull request #709 from simplex-chat/xftp-send
xftp: recoverable send
2023-04-13 20:13:04 +04:00
Evgeny Poberezkinandspaced4ndy ed0f8c79a2 xftp: wait for agent in foreground in XFTP workers without delaying suspension (#721)
Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-04-13 20:04:38 +04:00
spaced4ndy 29eb9e4e27 xftp: test additional recipient IDs are requested when number of recipients exceeds maximum per request (#723) 2023-04-13 20:04:23 +04:00
spaced4ndy e346a81e46 xftp: delete snd files on servers (#722) 2023-04-13 17:46:43 +04:00
spaced4ndy e6e17ec637 xftp: api to delete snd files internally, cleanup snd files, tests (#719) 2023-04-12 14:50:40 +04:00
spaced4ndy d35bd8a954 xftp: restore snd files, expire snd files in agent (#718) 2023-04-11 22:00:09 +04:00
spaced4ndy d1774e5b56 xftp: send progress events (#717) 2023-04-11 19:36:51 +04:00
spaced4ndy 9c460966b2 xftp: use recoverable send implementation instead of experimental, fix query, tests (#716) 2023-04-11 11:10:57 +04:00
spaced4ndy d0cd34989d xftp: choose server when creating chunk, retrying with different servers (#714) 2023-04-10 19:13:03 +04:00
Evgeny Poberezkin d838be773b xftp: agent client functions to upload file and add recipients (#713)
* xftp: agent client functions to upload file and add recipients

* re-read replicas
2023-04-07 19:34:51 +04:00
Evgeny Poberezkin 2edc7529f9 xftp: client function to create new chunk (#712)
* xftp: client function to create new chunk

* remove chunk digest update

* rename
2023-04-07 14:50:38 +01:00
spaced4ndy 6d9af2ec17 xftp: use fs path when encrypting file and uploading chunks (#711) 2023-04-07 16:08:31 +04:00
spaced4ndy 3533929905 xftp: transform SndFile to recipient descriptions; non optional chunk digest (#710) 2023-04-07 14:29:07 +04:00
spaced4ndy d8e60ecfdb xftp: recoverable send - spike (#707) 2023-04-07 11:19:50 +04:00
Evgeny Poberezkin 215d2414b7 update preset xftp servers 2023-04-06 23:12:52 +01:00
Evgeny Poberezkin b1489138ea xftp: fix file reception on 32 bit platforms (#708) 2023-04-06 20:40:52 +01:00
Evgeny Poberezkin 9f8db13553 xftp: agent API to set and test servers (#704)
* xftp: agent API to set and test servers

* ProtocolTestStep

* update agent API for XFTP servers

* ci: update ubuntu versions

* disable test hanging on ubuntu
2023-04-05 20:37:03 +01:00
Evgeny Poberezkin 511a97c5d0 update http2 2023-04-05 09:41:13 +01:00
Evgeny Poberezkin 44f0dd39f3 ci: disable 2 tests on linux only, switch to ubuntu 20 and 22 (#705)
* ci: disable 2 tests on linux only, switch to ubuntu 20 and 22

* fix platform name

* keep ubuntu 22 binaries

* Revert "keep ubuntu 22 binaries"

This reverts commit a1bbb12870.

* skip 1 more test

* skip 1 more test

* log os

* log os

* unconditionally skip test

* skip 1 more test in CI

* fix tests
2023-04-04 12:19:38 +01:00
spaced4ndy bdff274f56 use Int64 for time calculations (#706) 2023-04-04 14:51:13 +04:00
Evgeny Poberezkin 83364052b1 xftp: implement server command to add file recipients (#702) 2023-04-03 09:33:12 +01:00
Evgeny Poberezkin c6033e51a0 update http2 2023-04-01 16:43:41 +01:00
spaced4ndy 0f23b4ab5c xftp: re-create output file if decryption restarts (#701) 2023-03-30 16:27:47 +04:00
spaced4ndy e27c4f7b81 xftp: notify about errors on rcv files retry; process snd files errors (#700) 2023-03-30 16:26:33 +04:00
spaced4ndy b5869cf169 xftp: agent to expire rcv files older than 2 days (#699) 2023-03-28 15:23:08 +04:00
spaced4ndy 6b03876ef1 catch errors in cleanup manager (#698) 2023-03-27 18:55:20 +04:00
Evgeny Poberezkinandspaced4ndy 6a665a0833 support down migrations (#696)
* support down migrations

* test

* update

* add down migrations and tests

* get current migrations

* corrections

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* update tests

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-03-27 12:44:53 +01:00
Evgeny Poberezkin c5eb65fec8 xftp: send events for file sending/receiving progress (#697) 2023-03-27 11:44:15 +01:00
Tristan de Cacqueray 5743069021 Remove duplicated serverIdentity field (#491) 2023-03-26 12:37:31 +01:00
spaced4ndy 0df7733125 xftp: relative file paths, worker management (#694) 2023-03-22 15:34:25 +04:00
Evgeny Poberezkin d41c2bec2a store retry intervals to resume from the same interval on restart (#693)
* store retry intervals to resume from the same interval on restart

* add migration

* updates
2023-03-22 08:42:56 +00:00
spaced4ndy 7e265e5c59 Merge pull request #584 from simplex-chat/xftp
XFTP
2023-03-20 20:33:01 +04:00
spaced4ndy 2bec353eae xftp: add command to delete rcv file; agent manages save path (#692) 2023-03-20 20:08:38 +04:00
Evgeny Poberezkin 40da7e76dd import stateTVar 2023-03-18 13:57:17 +00:00
Evgeny Poberezkin 2e02ba86fd add stateTVar import 2023-03-18 13:38:20 +00:00
Evgeny Poberezkin 02eb1e9822 add stateTVar imports for compatibility with older hackage index in nix builds 2023-03-18 07:57:25 +00:00
Evgeny Poberezkin cd48c33c0d Merge branch 'master' into xftp 2023-03-17 13:30:52 +00:00
Evgeny Poberezkin 5258fe9b7e add sha512 (#691)
* add sha512

* update export title
2023-03-17 13:01:49 +00:00
Evgeny Poberezkin e33d5b5184 use different constraint for non-error functions (#690) 2023-03-17 16:01:24 +04:00
spaced4ndyandEvgeny Poberezkin 2b1a02d7d4 xftp: reconnect XFTP client on replica retry (#689)
* xftp: re-create XFTP client on replica retry

* closeXFTPSessionClient

* refactor

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-03-17 09:50:49 +00:00
spaced4ndy 9255d48b69 xftp: move delay to replica (#688) 2023-03-16 18:12:38 +04:00
Evgeny Poberezkin bab689099f xftp: streaming file encryption/decryption to avoid memory spikes (#687)
* xftp: streaming file decryption to avoid memory spikes

* refactor, enable tests

* streaming encryption

* refactor
2023-03-16 13:57:21 +00:00
Evgeny Poberezkin a0eb53b891 xftp: use agent servers in experimental send, refactor decryption (#686)
* xftp: use agent servers in experimental send, refactor decryption

* fix/enable xftp send test test

* allow any order
2023-03-14 22:56:19 +00:00
spaced4ndy db120b6d2e xftp: pass save path to agent (#685) 2023-03-14 19:16:25 +04:00
+shyfire131and+shyfire131 64f5d63d2e Support for building ARM docker images (#679)
* add llvm to build stage

running docker build on Apple Sillicon would result in this error:

#14 49.39 <no location info>: error:
#14 49.39     Warning: Couldn't figure out LLVM version!
#14 49.39              Make sure you have installed LLVM between [9 and 13)

I assume it can’t find llvm/clang?

* install using unattended helper script

the current haskell is hardcoded to x86, so switch to using haskell’s official helper script which supports arm

also need to bump up setting the path, since ghcup is no longer in /usr/bin

reference: https://www.haskell.org/ghcup/guide/#continuous-integration

* add numa headers/libs

docker build (specifically haskell install step) would fail with :

#7 107.2 utils/ghc-cabal/dist-install/build/tmp/ghc-cabal: error while loading shared libraries: libnuma.so.1: cannot open shared object file: No such file or directory

I think this is because numa isn’t installed on arm instances of focal by default, but it is in later versions

anyway this fixes that

* also add numa to final

The image builds at this point! But it fails to boot on arm - again with a numa error.

This fixes that.

* don’t specify llvm version

---------

Co-authored-by: +shyfire131 <shyfire131@shyfire131.net>
2023-03-13 20:00:34 +00:00
Evgeny Poberezkinandspacedandy ddc2da8fe4 xftp: agent API for xftp commands and events (#684)
* xftp: agent API for xftp commands and events

* fix tests

* fix tests 2

* xftp: update agent send api

* update API to make temp path optional

* revert tmp path changes (fixes send)

---------

Co-authored-by: spacedandy <8711996+spaced4ndy@users.noreply.github.com>
2023-03-13 09:04:23 +00:00
Evgeny Poberezkin 3fe1f3c822 rename FileParty constructors 2023-03-11 10:05:07 +00:00
Evgeny Poberezkin 448b674fb1 5.0.0-beta.5 2023-03-10 17:37:38 +00:00
spaced4ndy cf1cd75a15 xftp: fix experimental send api description paths (#683) 2023-03-10 21:06:09 +04:00
Evgeny Poberezkin 40164ff21f update http2 to 4.1 (#680) 2023-03-10 16:59:26 +00:00
spaced4ndy c1266d55a4 xftp: experimental send api wip (#682) 2023-03-10 20:43:10 +04:00
spaced4ndy cf8f78f518 xftp: add random bytestring entity id for rcv files (#681) 2023-03-10 20:32:37 +04:00
Evgeny Poberezkin accfee5a52 5.0.0-beta.4 2023-03-10 10:32:05 +00:00
spaced4ndy cc2066473c xftp: cleanup complete & error files tmp paths; remove save path before decrypting if exists (#677) 2023-03-10 14:26:34 +04:00
Evgeny Poberezkin 8fde8e1344 xftp: agent command entities (#676)
* xftp: agent command entities

* progress event

* parameterize agent command by entity

* refactor

* Eq instance for APartyCmdTag
2023-03-10 09:10:52 +00:00
spaced4ndy deec963de8 xftp: agent error handling (#675)
- chunk download doesn't loop on permanent errors
- decryption errors are considered permanent - local worker doesn't retry
- update replica retries; to do - consider use for this field, or remove it
- rcv file Error status - to prevent repeat reads of chunks for download, files for decryption; also plan to use it for filtering on cleanup
- error string saved in separate field for debugging (not part of status type)
- agent event for rcv file errors
2023-03-09 15:32:17 +04:00
Evgeny Poberezkin 552759018e xftp: server types for any protocol (#672) 2023-03-09 09:54:31 +00:00
spaced4ndy 6d52150672 xftp: agent send file design wip (#674) 2023-03-08 14:30:37 +04:00
spaced4ndy e9f949f117 xftp: resume file reception and decryption on agent restart (#673) 2023-03-07 13:29:28 +04:00
spaced4ndy a0c86158d9 xftp agent: update chunk delay (#671) 2023-03-03 20:39:15 +04:00
spacedandy cc38deb65d Merge branch 'master' into xftp 2023-03-03 19:16:12 +04:00
spaced4ndyandEvgeny Poberezkin cf147397a4 xftp: agent receive file (#637)
* xftp: agent receive file draft

* receiveFile more stubs, changes to types, schema

* cabal file

* comments

* xftp_server_id

* schema changes, get client, local worker/action

* agent env, save file description, adjust schema

* client stubs

* download chunk wip, store, schema, types

* remove commented code

* read file description, schema, types

* check received, decrypt

* remove pure

* todo

* add XFTP to agent client

* add user id

* agent test

* tests

* rename supervisor into agent

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-03-03 18:50:16 +04:00
Evgeny Poberezkin 2f7c115207 retryInterval functions pass current interval to the action, to resume with the same interval on restart (improve battery consumption) (#670) 2023-03-03 14:12:36 +00:00
Evgeny Poberezkin 6ed4dd1515 update http2 library 2023-03-03 11:00:10 +00:00
Evgeny Poberezkin 914240108d xftp: update http2 to remove workarounds with padding and delay (#667) 2023-03-02 16:00:46 +00:00
Evgeny Poberezkin e764a51fc0 v5.0.0-beta.3 2023-03-01 14:37:59 +00:00
Evgeny Poberezkin 94de01a06f xftp: use SHA256 digest for file chunks to reduce file description size (#666)
* xftp: use SHA256 digest for file chunks to reduce file description size

* enable all tests
2023-03-01 14:36:55 +00:00
Evgeny Poberezkin faec32dc5e xftp: constrain supported file size to 1gb 2023-03-01 13:50:08 +00:00
Evgeny Poberezkinandspaced4ndy 6227215c3f xftp: remove file description that cannot be used (#665)
* xftp: remove file description that cannot be used

* show sender file description first

* change order

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-03-01 13:08:59 +00:00
Evgeny Poberezkinandspaced4ndy 3d3eb335e8 xftp: download timeout, reconnect CLI on timeouts, verbose logging (#664)
* xftp: download timeout, reconnect CLI on timeouts, verbose logging

* typo

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-03-01 07:47:27 +00:00
Seth For Privacy 453e18c4ad Correct minor Docker syntax error (#662)
Noticed that the environment variables for SMP server when using Docker were improperly quoted, so I corrected them.

This will fix an issue with server address being displayed incorrectly in the CLI when viewing init logs.

I also explicitly added the `:latest` tag for the Docker image in the Running example to make it more clear which tag is being run (no tag defaults to `latest`.)
2023-03-01 07:45:18 +00:00
Evgeny Poberezkin 249bcc7bb3 update cGet to not throw exception if returned string is shorter (trying to fix HTTP2), fix test (#663) 2023-02-28 19:16:35 +00:00
Evgeny Poberezkin 4afb72070a v5.0.0-beta.2 2023-02-28 09:02:05 +00:00
Evgeny Poberezkin 524c1de4de xftp: server stats (#661) 2023-02-28 08:59:28 +00:00
Evgeny Poberezkin 875a4bac5e xftp cli: use 3 chunk sizes (256kb, 1mb, 4mb) (#660)
* xftp cli: use 3 chunk sizes (256kb, 1mb, 4mb)

* hardcode default servers

* disable rand command

* hide rand command instead of removing
2023-02-27 21:15:22 +00:00
Evgeny Poberezkin f02cb2da4c 5.0.0-beta.1 2023-02-27 18:04:00 +00:00
Evgeny Poberezkin 2f15ce2662 xftp: add quota param to server CLI, restrict chunk sizes (#659)
* xftp: add quota param to server CLI

* only allow certain file sizes, fix tests
2023-02-27 18:01:18 +00:00
Evgeny Poberezkinandspaced4ndy 781f8e0000 xftp: increase timeouts for file uploads, show progress (#658)
* xftp: increase timeouts for file uploads, show progress

* refactor

* use default port 443

* typo

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* upload/download to/from chosen servers concurrently

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-02-27 13:42:15 +00:00
Evgeny Poberezkin c3872f0a55 5.0.0-beta.0 2023-02-25 19:52:33 +00:00
Evgeny Poberezkin 3e9e144145 ci: add xftp server (#657)
* ci: add xftp server

* add xftp
2023-02-25 19:51:33 +00:00
Evgeny Poberezkin 50c9c95287 Merge branch 'master' into xftp 2023-02-25 18:36:48 +00:00
spaced4ndyandEvgeny Poberezkin 1b4b184517 xftp: server - retry on duplicate ids (#655)
* xftp: server - retry on duplicate ids (with commented monad code)

* remove commented code, refactor

* replace traverse with mapM

* refactor

* refactor

* refactor

* refactor

* refactor

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-02-25 17:55:58 +00:00
Evgeny Poberezkin e4aad7583f unpadded AES-GCM encryption now requires 12 bytes IV (#656)
* unpadded AES-GCM encryption now requires 12 bytes IV

* update

* simplify AuthTag encoding
2023-02-25 16:22:10 +00:00
spaced4ndy f20a996797 xftp: more store log tests (#654) 2023-02-24 18:34:01 +04:00
Evgeny Poberezkin 8c8a984c1c xftp: add basic auth (#653) 2023-02-24 17:40:26 +04:00
spaced4ndy 202922bceb xftp: server store log (#652) 2023-02-24 15:21:07 +04:00
Evgeny Poberezkinandspaced4ndy 3ab5e9d110 xftp: expire files on the server, track/limit used storage (#651)
* xftp: expire files on the server

* track/limit used storage

* support storage quota and disabling queue creation in CLI parameters

* fix ini file

* correction

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-02-24 11:09:51 +04:00
Evgeny Poberezkin 4ce4fa3423 xftp: write secret_box auth tag to the end of the file, for efficiency of ecryption/decryption (#650)
* xftp: write secret_box auth tag to the end of the file, for efficiency of ecryption/decryption

* comments
2023-02-23 18:28:20 +00:00
spaced4ndy fbf0b8b175 xftp: cli - delete file command, acknowledge received chunks (#649) 2023-02-23 16:54:50 +04:00
spaced4ndyandEvgeny Poberezkin 1f394b76a6 xftp: sender file description (#647)
* xftp: sender file description

* tests

* check, info, tests

* test

* refactor

* refactor, rename sender file

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-02-22 17:16:49 +04:00
Evgeny Poberezkinandspaced4ndy 97b8b37325 xftp: FDEL and FACK commands (#648)
* xftp: FDEL and FACK commands

* correction

* more tests

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-02-22 12:32:30 +00:00
Evgeny Poberezkin bbf9e28696 xftp: add server to client encryption layer with cryptobox (#646)
* xftp: add server to client encryption layer with cryptobox

* workarounds for http2

* update http2 commit

* remove TODOs
2023-02-22 09:03:18 +00:00
Evgeny Poberezkin 50664930cc xftp: tests with 2 servers and 2 clients 2023-02-20 12:41:15 +00:00
Evgeny Poberezkin cd1adc8307 Merge branch 'master' into xftp 2023-02-20 09:37:25 +00:00
spaced4ndy 733c9374bf fix comment (#645) 2023-02-20 11:35:01 +04:00
Evgeny Poberezkin a8121fc8ad add unpadded AES encryption 2023-02-19 12:14:48 +00:00
Evgeny Poberezkin c970674452 faster lazy secret_box 2023-02-19 10:54:54 +00:00
Evgeny Poberezkin 4a9b5412db xftp: refactor 2023-02-18 23:21:59 +00:00
Evgeny Poberezkin 1ecef81b4d xftp: validate digests of file chunks in client and server 2023-02-18 22:44:44 +00:00
Evgeny Poberezkin 2bf8cba4fd xftp: download chunks to separate files 2023-02-18 20:56:46 +00:00
Evgeny Poberezkin 628169adb4 xftp: only receive correct number of bytes 2023-02-18 19:47:17 +00:00
Evgeny Poberezkin fcef7deec0 Merge branch 'master' into xftp 2023-02-18 18:46:28 +00:00
Evgeny Poberezkin 44535628a5 4.4.1 2023-02-18 18:28:57 +00:00
Evgeny Poberezkin 6a48b735d1 increase timeout for QUOTA errors 2023-02-18 18:09:58 +00:00
Evgeny Poberezkin bd0cc25083 XFTP error type 2023-02-17 22:27:36 +00:00
Evgeny Poberezkin 15637e545b Merge branch 'master' into xftp 2023-02-17 21:40:35 +00:00
spaced4ndyandEvgeny Poberezkin c0dcf283eb server_key_hash fields (#643)
* server_key_hash fields

* test

* refactor

* fix

* order

* use sync command in test

* refactor

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-02-17 21:24:32 +00:00
Evgeny Poberezkin 2ddfb044fc parameterize protocol by error type (#644) 2023-02-17 20:46:01 +00:00
Evgeny Poberezkin acdf4f41c5 XFTP: CLI tests, output command results, info command (#642)
* XFTP: CLI tests, output command results

* info command, test

* fix test
2023-02-17 11:38:43 +00:00
spaced4ndy a3d9ee213d xftp: cli - option to pass servers, choose servers randomly (#641) 2023-02-16 21:06:23 +04:00
spaced4ndy cf7346d48b xftp: cli - verify file digest (#640) 2023-02-16 21:01:41 +04:00
spaced4ndyandEvgeny Poberezkin 4e8657097c xftp: cli client draft (#635)
* xftp: cli client draft

* more stubs

* compiles

* hash, app

* options parsers, random

* tmp

* xftp CLI client agent, simplify CLI command syntax

* only allow argument as a second parameter

* pivot signature draft

* receive file

* pivot sent chunks to recipients

* encryptFile - temp, chunks, specs

* send (upload) file and save file descriptions

* refactor, remove encrypted file

* save file size in description as string

* include filename inside padded encrypted file

* call chunk uploads concurrently, using queueing in HTTP2 as library client does not support concurrent streaming uploads

* download file (does not work yet)

* add digests to sent chunks

* fix recv - save file using AppendMode

* encrypt/decrypt sent file with secretbox

* remove print

* fix file description parsing in tests

* fix test

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-02-16 14:06:03 +04:00
Evgeny Poberezkin d8f81b5cdb Merge branch 'master' into xftp 2023-02-15 22:02:19 +00:00
Evgeny Poberezkin 2ae3100bed lazy pad/unpad, secretbox encrypt/decrypt (#639) 2023-02-15 22:01:33 +00:00
Evgeny Poberezkin 88c6b0d663 Merge branch 'master' into xftp 2023-02-15 12:51:34 +00:00
Evgeny Poberezkin 8659d4de05 NaCL secretbox based on cryptonite (#636) 2023-02-15 12:51:08 +00:00
bccef0ba47 files: server and client spike - basic upload/download (#591)
* Files: main, env, stats, storeLog

* Better + transport

* Executable

* Env

* Update Client.hs, Server.hs, and 4 more files...

* Answer on request

* Delay

* Temp file

* Bypass cert check

* update package.yml, rename

* update store log

* extend HTTP2 transport

* refactor caStore

* HTTP2 body

* update server stats

* file server/client framework

* verify server commands

* process FNEW command, CLI test works

* simple XFTP server test (fails)

* fix test, refactor

* upload chunk works

* receive file chunk in the client

* remove transport handshake

* typo

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* fix names

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-02-13 13:36:02 +00:00
Evgeny Poberezkin d7a008985b Merge branch 'xftp' of github.com:simplex-chat/simplexmq into xftp 2023-02-12 15:53:48 +00:00
9775861b6f files: file description parsing & serialization, tests (#633)
* files: file description parsing & serialization, tests

* chunk list

* processFileDescription

* name

* different values

* undo chunk objects to strings

* parser, serializer

* use Either as monad

* refactor

* remove comments

* fix 2 tests

* fix test

* enable all tests

* remove comment

* move

---------

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>
Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-02-12 15:53:37 +00:00
Evgeny Poberezkin 4d333a90fa Merge branch 'master' into xftp 2023-02-10 19:07:12 +00:00
Evgeny Poberezkin eb1723acce refactor transport encoding, make client IO error "temporary" (#634)
* file server/client framework

* refactor

* make IOError temporary

* fix test
2023-02-10 19:06:28 +00:00
Evgeny Poberezkin eff501ddcc Merge branch 'master' into xftp 2023-02-09 23:10:46 +00:00
Evgeny Poberezkin b342b1dc59 extend HTTP2 transport (#632)
* extend HTTP2 transport

* refactor caStore

* HTTP2 body

* enable test

* remove maxBodySize
2023-02-09 23:09:24 +00:00
JRoberts 1523c00bcc files: file description types (#631) 2023-02-09 21:22:58 +04:00
Evgeny Poberezkin 3637d0c610 update protocol/store to include file digest 2023-02-09 09:03:34 +00:00
Evgeny Poberezkin 360e55a48f Merge branch 'master' into xftp 2023-02-08 20:57:24 +00:00
Evgeny Poberezkin ee2a764f93 agent: more strict parsing of TransportHost, tests (#629) 2023-02-04 22:59:28 +00:00
Evgeny Poberezkin cfe995325a agent: prevent batch deletions from failing on one connection sql error (#628)
* agent: prevent error reading one connection failing batched subscription

* prevent batch deletions from failing on one connection sql error

* rename
2023-02-04 20:46:45 +00:00
Evgeny Poberezkin 3be0008c5a 4.4.0 (#624)
* 4.4.0

* changelog
2023-02-03 11:29:15 +00:00
Evgeny Poberezkin 5d8febc353 avoid possible race conditions when cancelled clients/asyncs can be removed after the new ones are added (so that the new are removed as well) (#627) 2023-01-30 17:46:06 +00:00
Evgeny Poberezkin c77e7f7e43 remove tests/tmp folder after every test (#625) 2023-01-29 22:10:07 +00:00
Evgeny Poberezkin 6858f74897 Merge branch 'master' into xftp 2023-01-27 18:00:11 +00:00
Evgeny Poberezkin d1b4fa8911 Merge pull request #599 from simplex-chat/users
support multiple user profiles
2023-01-26 10:15:35 +00:00
Evgeny Poberezkin 7fb48930f6 increase database transaction timeout, add test for user deletion (#622)
* increase database transaction timeout, add test for user deletion

* more test logs
2023-01-25 20:58:03 +00:00
JRoberts ff038b492c fix DEL_RCVQ queue parameter type (#621) 2023-01-24 15:59:32 +00:00
Evgeny Poberezkin b59669a65e refactor functions operating on single connections using batch functions (#620)
* refactor functions operating on single connections using batch functions

* update tests
2023-01-24 13:14:13 +00:00
Evgeny PoberezkinandJRoberts 2ccef1690b events sent by the agent when queue, connection and user are deleted asynchronously (#619)
* events sent by the agent when queue, connection and user are deleted asynchronously

* update test

* more tests

* add user tests

* queries

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>
2023-01-24 11:12:07 +00:00
Evgeny Poberezkin d4fc638478 async batch connection deletion (#617)
* async batch connection deletion

* delete user record with connections, async connection deletion

* updates

* update query
2023-01-21 13:41:16 +00:00
Evgeny Poberezkin f66e8239f4 Merge branch 'master' into users 2023-01-19 17:45:31 +00:00
Evgeny Poberezkin 56eea29ec3 end SMP client connection after configured number of PING errors, reset PING error count on any success (#615)
* end SMP client connection after configured number of PING errors, reset PING error count on any success

* only terminate client on PING timeout

* refactor

* comment
2023-01-19 17:45:06 +00:00
Evgeny PoberezkinandJRoberts a854b5f2b2 batched queue deletion (#611)
* batched queue deletion

* only re-connect client on subscribe errors, not in all batch commands

* add test, fix

* correction

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>

* refactor

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>
2023-01-19 16:53:28 +00:00
Evgeny Poberezkin 63b7956083 Merge branch 'master' into users 2023-01-18 22:20:29 +00:00
Evgeny Poberezkin 4f4b4f7eee only reconnect client on temporary errors in single subscription too (not currently used) (#616)
* only reconnect client on temporary errors in single subscription too (not currently used)

* refactor
2023-01-18 22:03:43 +00:00
Evgeny Poberezkin f9c613ffb8 Merge branch 'master' into users 2023-01-18 21:18:42 +00:00
Evgeny PoberezkinandJRoberts 14cb88e725 remove completed async action handles from memory (#614)
* remove completed async action handles from memory

* name

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>
2023-01-18 18:22:17 +00:00
Evgeny Poberezkin 6ccbe5e66e retry unsuccessful subscriptions in case of temporary errors (#613)
* retry unsuccessful subscriptions in case of temporary errors

* do not send DOWN if connection has any active queues
2023-01-18 14:30:25 +00:00
Evgeny Poberezkin f921dc3adb 4.3.1 2023-01-18 11:21:45 +00:00
Evgeny Poberezkin c4f377a85b fix SMP server stats (#612)
* fix SMP server stats

* add server stats test

* fix test
2023-01-18 11:07:25 +00:00
Evgeny Poberezkin ca5c4b75eb Merge branch 'master' into users 2023-01-17 20:32:23 +00:00
Evgeny Poberezkin 0af6533510 rfc: update xftp doc (#609) 2023-01-17 12:24:05 +00:00
JRoberts 42df6a421d add missing fkey indexes (#610) 2023-01-17 16:07:13 +04:00
Evgeny Poberezkin bc8acf2abf Merge branch 'master' into xftp 2023-01-16 19:29:55 +00:00
Evgeny Poberezkin 19feee881b 4.3.0 2023-01-16 12:00:37 +00:00
Evgeny Poberezkin 324e01300d execute asynchronous commands for correct users, include session in messages from SMP clients to agent (#608)
* execute asynchronous commands for correct users

* pass transport session to message processing to avoid race condition

* account for server changes when determining unused servers

* enable one test

* enable all tests, remove log
2023-01-16 11:06:19 +00:00
Evgeny Poberezkin b549910c17 support switching session mode, transport session now uses connection ID (#607)
* support switching session mode, transport session now uses connection ID

* refactor
2023-01-16 08:51:41 +00:00
Evgeny Poberezkin a1eda12475 increase sending retries on ERR QUOTA 2023-01-15 18:14:20 +00:00
Evgeny Poberezkin abee1fa70b Merge branch 'master' into users 2023-01-14 18:43:09 +00:00
Evgeny Poberezkin 701d06ba01 refactor tests to improve errors (#606)
* refactor tests to improve errors

* fix test descriptions

* fix test
2023-01-14 18:28:37 +00:00
Evgeny Poberezkin cac3432b03 Merge branch 'master' into users 2023-01-14 15:34:18 +00:00
Evgeny Poberezkin 56cc2bc71f additional SMP server stats (#605)
* additional SMP server stats

* refactor
2023-01-14 13:23:37 +00:00
Evgeny Poberezkin 9c9ba8c25c subscribe users in different sessions (#602)
* subscribe users in different sessions

* remove comments

* include userId to rcv queue map key

* use hash of userId[:entityId] as SOCKS proxy username
2023-01-13 09:58:39 +00:00
JRoberts 8e024590bc fix createUserRecord query (#604) 2023-01-13 11:31:35 +04:00
Evgeny Poberezkin f47e7bf3c5 4.2.3 2023-01-12 23:27:35 +00:00
Evgeny Poberezkin 5e31c60c35 do not show warning on server restart when restoring "quota" message and quota is exceeded (#603)
* do not show warning on server restart when restoring "quota" message and quota is exceeded

* complete case

* line break
2023-01-12 23:26:21 +00:00
Evgeny Poberezkin a0a092747a Merge branch 'master' into users 2023-01-12 16:37:59 +00:00
Evgeny Poberezkin 36bf92e54f 4.2.2 (#601) 2023-01-12 16:01:50 +00:00
Evgeny Poberezkin 1f12697279 strict writes to STM, remove type class (#600) 2023-01-12 14:59:46 +00:00
Evgeny Poberezkin 92a379e75c 4.2.1 2023-01-11 22:24:38 +00:00
Evgeny Poberezkin 0dddd59b36 increase server internal queue sizes (#595) 2023-01-11 16:14:33 +00:00
Evgeny PoberezkinandJRoberts f4ad3a983e support users in agent to isolate traffic of different users (#598)
* users table, isolate traffic sessions by users or by queues

* remove extra indices

* corrections

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>
2023-01-11 17:47:20 +04:00
Evgeny Poberezkin b328492dc9 4.2.0 (#597) 2023-01-09 11:16:25 +00:00
JRoberts 698b5c4146 set correct snd queue as primary on QTEST (#596) 2023-01-09 10:37:57 +00:00
Evgeny Poberezkin acfa65200a deduplicate connections in connect/disconnect responses, log errors in tPut (#593)
* remove TODO for old handshake version (this HELLO is not sent now)

* deduplicate connections in responses and verify server in the list of subscribed queues

* log transport and LargeMsg in tPut (the results it returns are only used in the tests)

* refactor

* refactor
2023-01-06 17:14:49 +00:00
Evgeny PoberezkinandJRoberts 61e0c346df simplify C.sign, Crypto tests, triage TODOs (#592)
* simplify C.sign, Crypto tests, triage TODOs

* update condition

* remove todos

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>
2023-01-06 15:34:05 +00:00
JRoberts 11c235a8a3 check token status when sending verification notification (#594) 2023-01-06 19:16:55 +04:00
Evgeny Poberezkin 058e3ac55e send/process "quota exceeded" message from SMP server when sender gets ERR QUOTA (#585)
* send "quota exceeded" message from SMP server when sender gets ERR QUOTA (ignored in the agent for now)

* send msg quota to the recipient to indicate that sender got ERR QUOTA, test

* switch between slow/fast retry intervals (tests do not pass yet)

* send QCONT message, refactor RetryInterval, test

* refactor

* remove comment

* remove space

* unit test for withRetryLock2

* refactor
2023-01-04 14:10:13 +00:00
Evgeny Poberezkin 470b512a88 fix CLI tests (#590) 2023-01-02 16:14:12 +00:00
Evgeny Poberezkin 8dd728e834 add XFTP to ProtocolType 2022-12-30 22:22:07 +00:00
Stanislav DmitrenkoandEvgeny Poberezkin 7adcbf839f FileStore (#589)
* FileStore

* Set instead of List

* update

* refactor

* refactor

* sort imports

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2022-12-30 21:07:35 +00:00
Evgeny Poberezkin 69a5896dac 4.1.0 (#588) 2022-12-29 21:33:55 +00:00
Evgeny PoberezkinandAvently 4b29855430 core: SimpleX File Transfer protocol type (#587)
* core: File transfer protocol

* Optimization

* Renaming and interfaces

* update response type

* eol

* update type

Co-authored-by: Avently <7953703+avently@users.noreply.github.com>
2022-12-29 18:12:41 +00:00
Evgeny Poberezkin 1d78e35688 XFTP modules structure 2022-12-27 21:54:02 +00:00
Evgeny Poberezkin af903bd405 rfc: managing exceeded queue quotas (#583)
* rfc: managing exceeded queue quotas

* update
2022-12-27 16:29:07 +00:00
Evgeny Poberezkin 51b0833f98 rfc: SimpleX File Transfer protocol (#582)
* rfc: SimpleX File Transfer protocol

* update

* update

* remove space

* update transport protocol notes

* spellcheck
2022-12-27 12:42:53 +00:00
Evgeny Poberezkin 874f9f5cd6 option to enable/disable TLS handshake error logs (disable by default) (#581)
* option to enable/disable TLS handshake error logs (disable by default)

* refactor
2022-12-27 10:13:51 +00:00
Evgeny Poberezkin 66d3465c19 Merge branch 'stable' 2022-12-26 22:28:42 +00:00
sh d5bf99c32c docker: update (#578)
* readme: update for recent docker changes

* docker: update entrypoint logic

* readme: clarify
2022-12-26 22:27:56 +00:00
Evgeny Poberezkin 1d3a604988 refactor SMP client, NTF server store (#580)
* refactor SMP client, NTF server store

* remove undefined
2022-12-26 18:54:28 +00:00
Evgeny Poberezkin 267236a4f8 remove unnecessary exception handler, error format in stats 2022-12-26 13:00:41 +00:00
Evgeny Poberezkin aa17cc55c1 collect agent stats (#579)
* collect agent stats

* remove comment
2022-12-26 12:02:20 +00:00
Evgeny PoberezkinandJRoberts fb21d9836e agent: api to get hash of ratchet associated data for connection verification (#577)
* agent: api to get hash of ratchet associated data for connection verification

* enable all tests

* correction

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>
2022-12-09 09:41:12 +00:00
Evgeny PoberezkinandJRoberts e4842f4f47 agent: include server address string into BROKER errors (#575)
* agent: include server address string into BROKER errors

* eol

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>
2022-11-30 08:25:07 +00:00
Evgeny Poberezkin dc920d90d9 v4.0.0 (#573)
* v4.0.0

* update
2022-11-28 19:59:04 +00:00
Evgeny Poberezkin f53c1f5559 server: clear folders during initialization instead of deleting them (#572) 2022-11-28 07:40:59 +00:00
sh 0942bf9f1e readme: correction (#571) 2022-11-26 20:10:46 +00:00
shandEvgeny Poberezkin 57fc190a91 readme: fix install steps (#570)
* readme: fix install steps

* correction

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2022-11-26 14:29:59 +00:00
Evgeny PoberezkinandJRoberts 43fb513ef7 initialize SMP server interactively, CLI options (#566)
* initialize SMP server interactively, CLI options

* correction

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>

* corrections

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>
2022-11-18 19:07:41 +00:00
Evgeny Poberezkin fbccca9947 refactor server CLIs (#565)
* refactor server CLIs

* refactor
2022-11-18 08:37:03 +00:00
Evgeny Poberezkin 40000047af server: refactor CLIs, tests (#564)
* server: refactor CLIs, tests

* add files, test

* rename Executable -> Main
2022-11-17 19:43:01 +00:00
Evgeny Poberezkin c2342cba05 FromJSON instance for ProtoServerWithAuth 2022-11-15 22:42:01 +00:00
Evgeny Poberezkin f3b6ed4db0 agent API for SMP server test (#563)
* agent API for SMP server test

* add JSON encoding
2022-11-15 07:50:46 +00:00
Evgeny Poberezkin 95db734b2d export BasicAuth constructor 2022-11-13 08:29:54 +00:00
Evgeny PoberezkinandJRoberts e281efdcb8 server: SMP basic auth (#561)
* server: SMP basic auth

* update ini default

* rfc, types

* tests

* update INI file

* typo

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>

* refactor

* update INI options, log new queue creation mode on start (on/off/requires auth)

Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>
2022-11-12 22:29:36 +00:00
292 changed files with 48208 additions and 9364 deletions
+4 -1
View File
@@ -1 +1,4 @@
* @epoberezkin @efim-poberezkin
* @epoberezkin @spaced4ndy
/Dockerfile @shumvgolove
/scripts/docker/ @shumvgolove
/scripts/main/ @shumvgolove
+25 -15
View File
@@ -11,23 +11,30 @@ on:
jobs:
build:
name: build-${{ matrix.os }}
name: build-${{ matrix.os }}-${{ matrix.ghc }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-18.04
- os: ubuntu-20.04
platform_name: 20_04-x86-64
ghc: "8.10.7"
- os: ubuntu-20.04
platform_name: 20_04-x86-64
ghc: "9.6.3"
- os: ubuntu-22.04
platform_name: 22_04-x86-64
ghc: "9.6.3"
steps:
- name: Clone project
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Setup Haskell
uses: haskell/actions/setup@v1
uses: haskell-actions/setup@v2
with:
ghc-version: "8.10.7"
cabal-version: "latest"
ghc-version: ${{ matrix.ghc }}
cabal-version: "3.10.1.0"
- name: Cache dependencies
uses: actions/cache@v2
@@ -42,20 +49,21 @@ jobs:
run: cabal build --enable-tests
- name: Test
if: matrix.os == 'ubuntu-18.04'
timeout-minutes: 30
timeout-minutes: 40
shell: bash
run: cabal test --test-show-details=direct
- name: Prepare binaries
if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'ubuntu-20.04'
if: startsWith(github.ref, 'refs/tags/v')
shell: bash
run: |
mv $(cabal list-bin smp-server) smp-server-ubuntu-20_04-x86-64
mv $(cabal list-bin ntf-server) ntf-server-ubuntu-20_04-x86-64
mv $(cabal list-bin smp-server) smp-server-ubuntu-${{ matrix.platform_name}}
mv $(cabal list-bin ntf-server) ntf-server-ubuntu-${{ matrix.platform_name}}
mv $(cabal list-bin xftp-server) xftp-server-ubuntu-${{ matrix.platform_name}}
mv $(cabal list-bin xftp) xftp-ubuntu-${{ matrix.platform_name}}
- name: Build changelog
if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'ubuntu-20.04'
if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'ubuntu-22.04'
id: build_changelog
uses: mikepenz/release-changelog-builder-action@v1
with:
@@ -67,7 +75,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create release
if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'ubuntu-20.04'
if: startsWith(github.ref, 'refs/tags/v') && matrix.ghc != '8.10.7'
uses: softprops/action-gh-release@v1
with:
body: |
@@ -78,8 +86,10 @@ jobs:
prerelease: true
files: |
LICENSE
smp-server-ubuntu-20_04-x86-64
ntf-server-ubuntu-20_04-x86-64
smp-server-ubuntu-${{ matrix.platform_name}}
ntf-server-ubuntu-${{ matrix.platform_name}}
xftp-server-ubuntu-${{ matrix.platform_name}}
xftp-ubuntu-${{ matrix.platform_name}}
fail_on_unmatched_files: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+50
View File
@@ -0,0 +1,50 @@
name: Build and push Docker image to Docker Hub
on:
push:
tags:
- "v*"
jobs:
build-and-push:
name: Build and push Docker image
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- app: smp-server
app_port: 5223
- app: xftp-server
app_port: 443
steps:
- name: Clone project
uses: actions/checkout@v3
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Extract metadata for Docker image
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.app }}
flavor: |
latest=auto
tags: |
type=semver,pattern=v{{version}}
type=semver,pattern=v{{major}}.{{minor}}
type=semver,pattern=v{{major}}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
push: true
build-args: |
APP=${{ matrix.app }}
APP_PORT=${{ matrix.app_port }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+4
View File
@@ -7,3 +7,7 @@ dist-newstyle/
cabal.project.local
cabal.project.local~
.hpc/
*.tix
.coverage
+1
View File
@@ -0,0 +1 @@
- ignore: {name: "Use underscore"}
+467 -3
View File
@@ -1,3 +1,467 @@
# 6.0.4
SMP server:
- better performance/memory: fewer map updates on re-subscriptions (#1297), split and reduce STM transactions (#1294)
- send DELD when subscribed queue is deleted (#1312)
- add created/updated/used date to queues to manage expiration (#1306)
XFTP server: truncate file creation time to 1 hour (#1310)
Servers:
- bind control port only to 127.0.0.1 for better security in case of firewall misconfiguration (#1280)
- reduce memory used for period stats (#1298)
Agent: process last notification from list (#1307)
- report receive file error with redirected file ID, when redirect is present (#1304)
- special error when deleted user record is not in database (#1303)
- fix race when sending a message to the deleted connection (#1296)
- support for multiple messages in a single notification
Ntf server:
- only use SOCKS proxy for servers without public address (#1314)
# 6.0.3
Agent:
- fix possible stuck queue rotation (#1290).
SMP server:
- batch END responses when subscribed client switches to reduce server and client traffic.
- reduce STM transactions for better performance.
- add stats for END events and for SUB/DEL event batches.
- remove "expensive" stats to save memory.
# 6.0.2
SMP agent:
- fix stuck connection commands when a server is not responding.
- store query errors, reduce slow query threshold to 1ms.
Notification server:
- reduce PING interval to 1 minute.
- fix subscriptions disabled on race condition (only mark subscriptions with END status when received via the active connection).
# 6.0.1
SMP agent:
- support changing user of the new connection.
- do not start delivery workers when there are no messages to deliver.
- enable notifications for all connections.
- combine database transactions when subscribing.
SMP server:
- safe compacting of store log.
- fix possible race when creating client that might lead to memory leak.
Dependencies: upgrade tls to 1.9
# 6.0.0
Version 6.0.0.8
Agent:
- enabled fast handshake support.
- batch-send multiple messages in each connection.
- resume subscriptions as soon as agent moves to foreground or as network connection resumes.
- "known" servers to determine whether to use SMP proxy.
- retry on SMP proxy NO_SESSION error.
- fixes to notification subscriptions.
- persistent server statistics.
- better concurrency.
SMP server:
- reduce threads usage.
- additional statistics.
- improve disabling inactive clients.
- additional control port commands for monitoring.
Notification server:
- support onion-only SMP servers.
# 5.8.2
Agent:
- fast handshake support (disabled).
- new statistics api.
SMP server:
- fast handshake support (SKEY command).
- minor changes to reduce memory usage.
# 5.8.1
Agent:
- API to reconnect one server.
- Better error handling of file errors and remote control connection errors.
- Only start uploading file once all chunks were registered on the servers.
SMP server:
- additional stats for sent message notifications.
- fix server page layout.
# 5.8.0
Version 5.8.0.10
SMP server and client:
- protocol extension to forward messages to the destination servers, to protect sending client IP address and transport session.
Agent:
- process timed out subscription responses to reduce the number of resubscriptions.
- avoid sending messages and commands when waiting for response timed out (except batched SUB and DEL commands).
- fix issue with stuck message reception on slow connection (when response to ACK timed out, and the new message was not processed until resubscribed).
- fix issue when temporary file sending or receiving error was treated as permanent.
SMP server:
- include OK responses to all batched SUB requests to reduce subscription timeouts.
XFTP server:
- report file upload timeout as TIMEOUT, to avoid delivery failure.
# 5.7.6
XFTP agent:
- treat XFTP handshake timeouts and network errors as temporary, to retry file operations.
# 5.7.5
SMP agent:
- fail if non-unique connection IDs are passed to sendMessages (to prevent client errors and deadlocks).
# 5.7.4
SMP agent:
- remove re-subscription timeouts (as they are tracked per operation, and could cause failed subscriptions).
- reconnect XFTP clients when network settings changes.
- fix lock contention resulting in stuck subscriptions on network change.
# 5.7.3
SMP/NTF protocol:
- add ALPN for handshake version negotiation, similar to XFTP (to preserve backwards compatibility with the old clients).
- upgrade clients to versions v7/v2 of the protocols.
SMP server:
- faster responses to subscription requests.
XFTP client:
- fix network exception during file download treated as permanent file error.
SMP agent:
- do not report subscription timeouts while client is offline.
# 5.7.2
SMP agent:
- fix connections failing when connecting via link due to race condition on slow network.
- remove concurrency limit when waiting for connection subscription.
- remove TLS timeout.
# 5.7.1
SMP agent:
- increase timeout for TLS connection via SOCKS
# 5.7.0
Version 5.7.0.4
_Please note_: the earliest SimpleX Chat clients supported by this version of the servers is 5.5.3 (released on February 11, 2024).
SMP server:
- increase max SMP protocol version to 7 (support for deniable authenticators).
NTF server:
- increase max NTF protocol version to 2 (support for deniable authenticators).
XFTP server:
- version handshake using ALPN.
SMP agent:
- increase timeouts for XFTP files.
- don't send commands after timeout.
- PQ encryption support.
# 5.6.2
Version 5.6.2.2.
SMP agent:
- Lower memory consumption (~20-25%).
- More stable XFTP file uploads and downloads.
- API to receive network connectivity changes from the apps.
- to reduce battery consumption: connection attempts interval growing to every 2 hours when app reports as offline.
- to reduce retries and traffic: 50% increased timeouts when on mobile network.
XFTP server:
- expire files on start.
- version negotiation based on TLS ALPN and handshake.
NTF server:
- reduced downtime by ~100x faster start time.
- exclude test tokens from statistics.
# 5.6.1
Version 5.6.1.0.
- Much faster iOS notification server start time (fewer skipped notifications).
- Fix SMP server stored message stats.
- Prevent overwriting uploaded XFTP files with subsequent upload attempts.
- Faster base64 encoding/parsing.
- Control port audit log and authentication.
# 5.6.0
Version 5.6.0.4.
SMP protocol/client/server:
- support deniable sender command authorization (to be enabled in the next version).
- remove support for SMP protocol versions (prior to v4, 07/2022).
Agent:
- optional post-quantum key agreement using sntrup761 in double ratchet protocol.
- improve performance of deleting multiple connections and files by batching database operations.
- delay connection deletion to deliver pending messages.
- API to test for notifications server.
- remove support for client protocols versions (prior to 10/2022).
XFTP server:
- restore storage quota in case of failed uploads.
Performance and stability improvements.
# 5.5.3
Agent:
- notification token API also returns active notifications server.
- support file descriptions with redirection and file URIs.
Servers:
- CLI commands for online key and certificate rotation.
- Configure config and log paths via environment variables.
# 5.5.2
Extensible handshake for clients and SMP/NTF servers (ignore extra data).
# 5.5.1
SMP servers:
- do not keep stats file open
- additional stats about currently stored messages
Agent:
- support multiple notification servers (only one can be used at a time).
- expire messages after "quota exceeded" error after 7 days (instead of 21 days previously).
- stabilize message delivery, remove unnecessary subscription retries and traffic.
- improve database performance for message delivery.
- fix sockets/memory leak - a very old bug "activated" by improvements in v5.5.0.
# 5.5.0
Code:
- compatible with GHC 8.10.7 to support compilation for armv7a.
- migrate to `crypton` from deprecated `cryptonite` (the seed for DRG is now sha512-hashed).
- use ChaChaDRG for all random IDs, keys and nonces, only using hashed entropy as seed.
- more efficient transaction batching in SMP protocol client and server.
Agent:
- stabilize message reception and delivery, migrate message delivery to database queue.
- additional event MSGNTF confirming that message received via notification is processed.
- efficient processing of messages sent to multiple recipients with batched database transactions.
- new worker abstraction for all queued tasks resilient to race conditions and some database errors.
- many fixed race conditions.
- background mode for iOS NSE.
- additional error reporting to client on critical errors (to be show as alert in the clients).
- functional api to get worker statistics.
SMP/XFTP servers:
- fix socket and memory leak on servers with high load (inactive clients without subscriptions are disconnected after set time of inactivity).
- control port improvements.
- fix statistics for stored queues, messages and files.
- make writing to store log atomic (fixes a rare bug in XFTP server).
# 5.4.0
Migrate to GHC 9.6.3
Agent:
- database improvements:
- track slow queries.
- better performance.
- "busy" error handling.
- create parent folder when needed.
- support closing and re-opening database.
- SMP agent improvements
- streaming for batched SMP commands.
- fix asynchronous JOINing connection.
- handle repeating JOINs without failure.
- api to get subscribed connections.
- return simplex:/ links as invitations.
- fix memory leak.
- XFTP improvements:
- suspend when agent is suspended.
- support locally encrypted files.
- fixes - create empty file, prevent permanent error treated as temporary.
- upgrade HTTP2 library (fixes error handling and flow control).
- Remote control protocol (XRCP)
SMP server:
- control port commands for GHC threads introspection.
- allow creating new queues without subscriptions (required for iOS).
XFTP server:
- allow 64kb file chunks.
NTF server:
- faster startup.
# 5.3.0
Agent:
- improve performance, track slow database queries.
- support delivery receipts.
SMP server:
- control port
# 5.2.0 (NTF server 1.5.0)
Agent:
- treat agent INACTIVE error as temporary - fixes failed message delivery in some race conditions.
- restore connection confirmations after client restart - fixes failed connections.
- ratchet resynchronization protocol and API.
- increase connection version to mutually supported by both peers on each received message.
Client:
- make timeout for batched functions dependent on the number of batches - fixes expiry on large batches.
Servers:
- add timeout in case of sending TCP traffic and in case of partial delivery of requested blocks to avoid resource leaks.
# 5.1.2, 5.1.3 (NTF server 1.4.1, 1.4.2)
Agent:
- ACK message on decryption error (fixes stuck message delivery bug)
- more robust connection switching logic, API to abort switching the address
Notification server:
- batch subscriptions to SMP servers
# 5.1.1 (NTF server 1.4.0)
Agent:
- store and check hashes of previous encrypted messages to differentiate between duplicates and decryption errors
Server:
- larger processing queues
- expire messages when restoring them
# 5.1.0
XFTP client:
- check encrypted file exists when uploading
- remove user ID from deletion API
Agent:
- vacuum database on migrations
SMP server:
- configure message expiration time in INI file
# 5.0.0
SimpleX File Transfer Protocol (XFTP):
- XFTP server
- XFTP CLI
- support XFTP in the agent
Other changes:
- preserve retry interval for sending messages on agent restarts
- support IPv6 in the servers and in the agent
- support for 32-bit platforms
Read more about XFTP in this post: https://simplex.chat/blog/20230301-simplex-file-transfer-protocol.html
# 4.4.1
SMP agent:
- fix handling of server addresses.
- prevent message delivery getting stuck on IO error in SMP client.
# 4.4.0
SMP agent:
- support multiple user profiles with transport session isolation.
- support optional transport isolation per connection.
- batch connection deletion
- improve asynchronous connection deletion it may now be completed after the client is restarted as well.
- improve subscription logic to retry if initial attempt fails.
- end SMP client connection after a number of failed PINGs (default is 3).
# 4.3.0
SMP server:
- additional server usage statistics.
SMP agent:
- increase retry interval when sending messages after ERR QUOTA.
# 4.2.0
SMP agent and server:
- reduce sender traffic in cases when queue quota is exceeded:
- server sends quota exceeded message to the recipient when sender receives ERR QUOTA.
- recipient sends QCONT message to the send once the queue is drained (via reply queue).
- sender retry delays are increased, reducing traffic, but sender instantly resumes delivery where QCONT is received.
SMP server:
- increase internal queue sizes.
SMP agent:
- deduplicate connection IDs in connect/disconnect responses.
- unit tests for Crypto.hs.
- fix connection switch to another queue: correctly set primary send queue.
Notification server (v1.3.0):
- check token status when sending verification notification.
# 4.1.0
SMP agent and server:
- option to toggle TLS handshake error logs (disabled by default).
SMP agent:
- include server address in BROKER error.
- api to get hash of double ratchet associated data (for connection verification).
- api to get agent statistics.
# 4.0.0
SMP server:
- Basic authentication. The server address can now include an optional password that is required to create messaging queues, so the contacts who message you will not be able to receive messages via your server, unless you share with them the address with the password. It is recommended to enable basic authentication on all private servers by adding `create_password` parameter into AUTH section of server INI file (the previously deployed servers do not have this section, you need to add it).
- Disable creating new queues completely with `new_queues: off` parameter in AUTH section of INI file - it can be used to simplify migrating the existing connections to another server.
- Updated server CLI with changed defaults:
- interactive server initialization, use -y flag to initialize the server non-interactively.
- store log is now enabled by default, so messaging queues and messages are restored when the server is restarted (to restore undelivered messages the server needs to be stopped with SIGINT signal).
- a random password is now generated by default during the server initialization.
SMP agent:
- API to test SMP servers. It connects to the server, creates and deletes a messaging queue. The new SimpleX Chat client uses this API to allow you to test that you have the correct server address, with the valid certificate fingerprint and password, before enabling the new server.
# 3.4.0
SMP agent:
@@ -42,9 +506,9 @@ SMP server and agent:
SMP server:
- restore undeliverd messages when the server is restarted.
- restore undelivered messages when the server is restarted.
- SMP protocol v3 to support push notification:
- updated SEND and MSG to add message flags (for notification flag that contros whether the notification is sent and for any future extensions) and to move message meta-data sent to the recipient into the encrypted envelope.
- updated SEND and MSG to add message flags (for notification flag that confirm whether the notification is sent and for any future extensions) and to move message meta-data sent to the recipient into the encrypted envelope.
- update NKEY and NID to add e2e encryption keys (for the notification meta-data encryption between SMP server and the client), and update NMSG to include this meta-data.
- update ACK command to include message ID (to avoid acknowledging unprocessed message).
- add NDEL commands to remove notification subscription credentials from SMP queue.
@@ -55,7 +519,7 @@ SMP agent:
- new protocol for duplex connection handshake reducing traffic and connection time.
- support for SMP notifications server and managing device token.
- remove redundant FQDN validation from TLS handshake to prepare for access via Tor.
- support for fully stopping agent and for termporary suspending agent operations.
- support for fully stopping agent and for temporary suspending agent operations.
- improve management of duplicate message delivery.
SMP notifications server v1.0:
+62
View File
@@ -0,0 +1,62 @@
ARG TAG=22.04
FROM ubuntu:${TAG} AS build
### Build stage
# Install curl and git and simplexmq dependencies
RUN apt-get update && apt-get install -y curl git build-essential libgmp3-dev zlib1g-dev llvm-12 llvm-12-dev libnuma-dev libssl-dev
# Specify bootstrap Haskell versions
ENV BOOTSTRAP_HASKELL_GHC_VERSION=9.6.3
ENV BOOTSTRAP_HASKELL_CABAL_VERSION=3.10.1.0
# Install ghcup
RUN curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 sh
# Adjust PATH
ENV PATH="/root/.cabal/bin:/root/.ghcup/bin:$PATH"
# Set both as default
RUN ghcup set ghc "${BOOTSTRAP_HASKELL_GHC_VERSION}" && \
ghcup set cabal "${BOOTSTRAP_HASKELL_CABAL_VERSION}"
COPY . /project
WORKDIR /project
ARG APP
ARG APP_PORT
RUN if [ -z "$APP" ] || [ -z "$APP_PORT" ]; then printf "Please spcify \$APP and \$APP_PORT build-arg.\n"; exit 1; fi
# Compile app
RUN cabal update
RUN cabal build exe:$APP
# Create new path containing all files needed
RUN mkdir /final
WORKDIR /final
# Strip the binary from debug symbols to reduce size
RUN bin=$(find /project/dist-newstyle -name "$APP" -type f -executable) && \
mv "$bin" ./ && \
strip ./"$APP" &&\
mv /project/scripts/docker/entrypoint-"$APP" ./entrypoint
### Final stage
FROM ubuntu:${TAG}
# Install OpenSSL dependency
RUN apt-get update && apt-get install -y openssl libnuma-dev
# Copy compiled app from build stage
COPY --from=build /final /usr/local/bin/
# Open app listening port
ARG APP_PORT
EXPOSE $APP_PORT
# simplexmq requires using SIGINT to correctly preserve undelivered messages and restore them on restart
STOPSIGNAL SIGINT
# Finally, execute helper script
ENTRYPOINT [ "/usr/local/bin/entrypoint" ]
+148 -17
View File
@@ -90,19 +90,158 @@ You can either run your own SMP server locally or deploy using [Linode StackScri
It's the easiest to try SMP agent via a prototype [simplex-chat](https://github.com/simplex-chat/simplex-chat) terminal UI.
## Deploy SMP server on Linux
## Deploy SMP/XFTP servers on Linux
You can run your SMP server as a Linux process, optionally using a service manager for booting and restarts.
You can run your SMP/XFTP server as a Linux process, optionally using a service manager for booting and restarts.
- For Ubuntu you can download a binary from [the latest release](https://github.com/simplex-chat/simplexmq/releases).
Notice that `smp-server` and `xftp-server` requires `openssl` as run-time dependency (it is used to generate server certificates during initialization). Install it with your packet manager:
If you're using other Linux distribution and the binary is incompatible with it, you can build from source using [Haskell stack](https://docs.haskellstack.org/en/stable/README/):
```sh
# For Ubuntu
apt update && apt install openssl
```
```shell
curl -sSL https://get.haskellstack.org/ | sh
...
stack install
```
### Install binaries
#### Using Docker
On Linux, you can deploy smp and xftp server using Docker. This will download image from [Docker Hub](https://hub.docker.com/r/simplexchat).
1. Create directories for persistent Docker configuration:
```sh
mkdir -p $HOME/simplex/{xftp,smp}/{config,logs} && mkdir -p $HOME/simplex/xftp/files
```
2. Run your Docker container.
- `smp-server`
You must change **your_ip_or_domain**. `-e "pass=password"` is optional variable to password-protect your `smp` server:
```sh
docker run -d \
-e "ADDR=your_ip_or_domain" \
-e "PASS=password" \
-p 5223:5223 \
-v $HOME/simplex/smp/config:/etc/opt/simplex:z \
-v $HOME/simplex/smp/logs:/var/opt/simplex:z \
simplexchat/smp-server:latest
```
- `xftp-server`
You must change **your_ip_or_domain** and **maximum_storage**.
```sh
docker run -d \
-e "ADDR=your_ip_or_domain" \
-e "QUOTA=maximum_storage" \
-p 443:443 \
-v $HOME/simplex/xftp/config:/etc/opt/simplex-xftp:z \
-v $HOME/simplex/xftp/logs:/var/opt/simplex-xftp:z \
-v $HOME/simplex/xftp/files:/srv/xftp:z \
simplexchat/xftp-server:latest
```
#### Using installation script
**Please note** that currently, only Ubuntu distribution is supported.
You can install and setup servers automatically using our script:
```sh
curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/simplex-chat/simplexmq/stable/install.sh -o simplex-server-install.sh \
&& if echo 'c90886104cd640b2ed64921dba80e90691db36788e8d6dcc13d8f33f92f0ea54 simplex-server-install.sh' | sha256sum -c; then chmod +x ./simplex-server-install.sh && ./simplex-server-install.sh; rm ./simplex-server-install.sh; else echo "SHA-256 checksum is incorrect!" && rm ./simplex-server-install.sh; fi
```
### Build from source
#### Using Docker
> **Please note:** to build the app use source code from [stable branch](https://github.com/simplex-chat/simplexmq/tree/stable).
On Linux, you can build smp server using Docker.
1. Build your images:
```sh
git clone https://github.com/simplex-chat/simplexmq
cd simplexmq
git checkout stable
DOCKER_BUILDKIT=1 docker build -t local/smp-server --build-arg APP="smp-server" --build-arg APP_PORT="5223" . # For xmp-server
DOCKER_BUILDKIT=1 docker build -t local/xftp-server --build-arg APP="xftp-server" --build-arg APP_PORT="443" . # For xftp-server
```
2. Create directories for persistent Docker configuration:
```sh
mkdir -p $HOME/simplex/{xftp,smp}/{config,logs} && mkdir -p $HOME/simplex/xftp/files
```
3. Run your Docker container.
- `smp-server`
You must change **your_ip_or_domain**. `-e "pass=password"` is optional variable to password-protect your `smp` server:
```sh
docker run -d \
-e "ADDR=your_ip_or_domain" \
-e "PASS=password" \
-p 5223:5223 \
-v $HOME/simplex/smp/config:/etc/opt/simplex:z \
-v $HOME/simplex/smp/logs:/var/opt/simplex:z \
simplexchat/smp-server:latest
```
- `xftp-server`
You must change **your_ip_or_domain** and **maximum_storage**.
```sh
docker run -d \
-e "ADDR=your_ip_or_domain" \
-e "QUOTA=maximum_storage" \
-p 443:443 \
-v $HOME/simplex/xftp/config:/etc/opt/simplex-xftp:z \
-v $HOME/simplex/xftp/logs:/var/opt/simplex-xftp:z \
-v $HOME/simplex/xftp/files:/srv/xftp:z \
simplexchat/xftp-server:latest
```
#### Using your distribution
1. Install dependencies and build tools (`GHC`, `cabal` and dev libs):
```sh
# On Ubuntu. Depending on your distribution, use your package manager to determine package names.
sudo apt-get update && apt-get install -y build-essential curl libffi-dev libffi7 libgmp3-dev libgmp10 libncurses-dev libncurses5 libtinfo5 pkg-config zlib1g-dev libnuma-dev libssl-dev
export BOOTSTRAP_HASKELL_GHC_VERSION=9.6.3
export BOOTSTRAP_HASKELL_CABAL_VERSION=3.10.3.0
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 sh
ghcup set ghc "${BOOTSTRAP_HASKELL_GHC_VERSION}"
ghcup set cabal "${BOOTSTRAP_HASKELL_CABAL_VERSION}"
source ~/.ghcup/env
```
2. Build the project:
```sh
git clone https://github.com/simplex-chat/simplexmq
cd simplexmq
git checkout stable
cabal update
cabal build exe:smp-server exe:xftp-server
```
3. List compiled binaries:
`smp-server`
```sh
cabal list-bin exe:smp-server
```
`xftp-server`
```sh
cabal list-bin exe:xftp-server
```
- Initialize SMP server with `smp-server init [-l] -n <fqdn>` or `smp-server init [-l] --ip <ip>` - depending on how you initialize it, either FQDN or IP will be used for server's address.
@@ -112,14 +251,6 @@ You can run your SMP server as a Linux process, optionally using a service manag
See [this section](#smp-server) for more information. Run `smp-server -h` and `smp-server init -h` for explanation of commands and options.
<img alt="Docker" src="./img/docker.svg" align="right" width="200">
## Deploy SMP server with Docker
SMP server could also be deployed using `Docker`.
See: [`scripts/docker`](./scripts/docker/)
[<img alt="Linode" src="./img/linode.svg" align="right" width="200">](https://cloud.linode.com/stackscripts/748014)
## Deploy SMP server on Linode
+10 -77
View File
@@ -1,88 +1,21 @@
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Logger.Simple
import Data.Functor (($>))
import Data.Ini (lookupValue)
import Simplex.Messaging.Client.Agent (defaultSMPClientAgentConfig)
import Simplex.Messaging.Notifications.Server (runNtfServer)
import Simplex.Messaging.Notifications.Server.Env (NtfServerConfig (..))
import Simplex.Messaging.Notifications.Server.Push.APNS (defaultAPNSPushClientConfig)
import Simplex.Messaging.Server.CLI (ServerCLIConfig (..), protocolServerCLI)
import System.FilePath (combine)
import Simplex.Messaging.Server.CLI (getEnvPath)
import Simplex.Messaging.Notifications.Server.Main
cfgPath :: FilePath
cfgPath = "/etc/opt/simplex-notifications"
defaultCfgPath :: FilePath
defaultCfgPath = "/etc/opt/simplex-notifications"
logPath :: FilePath
logPath = "/var/opt/simplex-notifications"
defaultLogPath :: FilePath
defaultLogPath = "/var/opt/simplex-notifications"
logCfg :: LogConfig
logCfg = LogConfig {lc_file = Nothing, lc_stderr = True}
main :: IO ()
main = do
setLogLevel LogDebug -- change to LogError in production
withGlobalLogging logCfg $ protocolServerCLI ntfServerCLIConfig runNtfServer
ntfServerCLIConfig :: ServerCLIConfig NtfServerConfig
ntfServerCLIConfig =
let caCrtFile = combine cfgPath "ca.crt"
serverKeyFile = combine cfgPath "server.key"
serverCrtFile = combine cfgPath "server.crt"
in ServerCLIConfig
{ cfgDir = cfgPath,
logDir = logPath,
iniFile = combine cfgPath "ntf-server.ini",
storeLogFile = combine logPath "ntf-server-store.log",
caKeyFile = combine cfgPath "ca.key",
caCrtFile,
serverKeyFile,
serverCrtFile,
fingerprintFile = combine cfgPath "fingerprint",
defaultServerPort = "443",
executableName = "ntf-server",
serverVersion = "SMP notifications server v1.2.0",
mkIniFile = \enableStoreLog defaultServerPort ->
"[STORE_LOG]\n\
\# The server uses STM memory for persistence,\n\
\# that will be lost on restart (e.g., as with redis).\n\
\# This option enables saving memory to append only log,\n\
\# and restoring it when the server is started.\n\
\# Log is compacted on start (deleted objects are removed).\n\
\enable: "
<> (if enableStoreLog then "on" else "off")
<> "\n\
\log_stats: off\n\n\
\[TRANSPORT]\n\
\port: "
<> defaultServerPort
<> "\n\
\websockets: off\n",
mkServerConfig = \storeLogFile transports ini ->
let settingIsOn section name = if lookupValue section name ini == Right "on" then Just () else Nothing
logStats = settingIsOn "STORE_LOG" "log_stats"
in NtfServerConfig
{ transports,
subIdBytes = 24,
regCodeBytes = 32,
clientQSize = 16,
subQSize = 64,
pushQSize = 128,
smpAgentCfg = defaultSMPClientAgentConfig,
apnsConfig = defaultAPNSPushClientConfig,
inactiveClientExpiration = Nothing,
storeLogFile,
resubscribeDelay = 50000, -- 50ms
caCertificateFile = caCrtFile,
privateKeyFile = serverKeyFile,
certificateFile = serverCrtFile,
logStatsInterval = logStats $> 86400, -- seconds
logStatsStartTime = 0, -- seconds from 00:00 UTC
serverStatsLogFile = combine logPath "ntf-server-stats.daily.log",
serverStatsBackupFile = logStats $> combine logPath "ntf-server-stats.log"
}
}
setLogLevel LogInfo
cfgPath <- getEnvPath "NTF_SERVER_CFG_PATH" defaultCfgPath
logPath <- getEnvPath "NTF_SERVER_LOG_PATH" defaultLogPath
withGlobalLogging logCfg $ ntfServerCLI cfgPath logPath
+17 -4
View File
@@ -1,33 +1,46 @@
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
module Main where
import Control.Logger.Simple
import Data.ByteArray (ScrubbedBytes)
import qualified Data.List.NonEmpty as L
import qualified Data.Map.Strict as M
import Simplex.Messaging.Agent.Env.SQLite
import Simplex.Messaging.Agent.Server (runSMPAgent)
import Simplex.Messaging.Agent.Store.SQLite (MigrationConfirmation (..))
import Simplex.Messaging.Client (defaultNetworkConfig)
import Simplex.Messaging.Transport (TLS, Transport (..))
cfg :: AgentConfig
cfg = defaultAgentConfig
agentDbFile :: String
agentDbFile = "smp-agent.db"
agentDbKey :: ScrubbedBytes
agentDbKey = ""
servers :: InitialAgentServers
servers =
InitialAgentServers
{ smp = L.fromList ["smp://bU0K-bRg24xWW__lS0umO1Zdw_SXqpJNtm1_RrPLViE=@localhost:5223"],
{ smp = M.fromList [(1, L.fromList ["smp://bU0K-bRg24xWW__lS0umO1Zdw_SXqpJNtm1_RrPLViE=@localhost:5223"])],
ntf = [],
xftp = M.empty,
netCfg = defaultNetworkConfig
}
logCfg :: LogConfig
logCfg = LogConfig {lc_file = Nothing, lc_stderr = True}
-- Warning: this SMP agent server is experimental - it does not work correctly with multiple connected TCP clients in some cases.
main :: IO ()
main = do
putStrLn $ "SMP agent listening on port " ++ tcpPort (cfg :: AgentConfig)
let AgentConfig {tcpPort} = cfg
putStrLn $ maybe (error "no agent port") (\port -> "SMP agent listening on port " ++ port) tcpPort
setLogLevel LogInfo -- LogError
withGlobalLogging logCfg $ runSMPAgent (transport @TLS) cfg servers
Right st <- createAgentStore agentDbFile agentDbKey False MCConsole
withGlobalLogging logCfg $ runSMPAgent (transport @TLS) cfg servers st
+10 -97
View File
@@ -1,25 +1,15 @@
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Logger.Simple
import Data.Functor (($>))
import Data.Ini (lookupValue)
import Simplex.Messaging.Server (runSMPServer)
import Simplex.Messaging.Server.CLI (ServerCLIConfig (..), protocolServerCLI, readStrictIni)
import Simplex.Messaging.Server.Env.STM (ServerConfig (..), defaultInactiveClientExpiration, defaultMessageExpiration)
import Simplex.Messaging.Server.Expiration
import Simplex.Messaging.Transport (simplexMQVersion, supportedSMPServerVRange)
import System.FilePath (combine)
import Simplex.Messaging.Server.CLI (getEnvPath)
import Simplex.Messaging.Server.Main
import qualified Static
cfgPath :: FilePath
cfgPath = "/etc/opt/simplex"
defaultCfgPath :: FilePath
defaultCfgPath = "/etc/opt/simplex"
logPath :: FilePath
logPath = "/var/opt/simplex"
defaultLogPath :: FilePath
defaultLogPath = "/var/opt/simplex"
logCfg :: LogConfig
logCfg = LogConfig {lc_file = Nothing, lc_stderr = True}
@@ -27,83 +17,6 @@ logCfg = LogConfig {lc_file = Nothing, lc_stderr = True}
main :: IO ()
main = do
setLogLevel LogDebug
withGlobalLogging logCfg . protocolServerCLI smpServerCLIConfig $ \cfg@ServerConfig {inactiveClientExpiration} -> do
putStrLn $ case inactiveClientExpiration of
Just ExpirationConfig {ttl, checkInterval} -> "expiring clients inactive for " <> show ttl <> " seconds every " <> show checkInterval <> " seconds"
_ -> "not expiring inactive clients"
runSMPServer cfg
smpServerCLIConfig :: ServerCLIConfig ServerConfig
smpServerCLIConfig =
let caCrtFile = combine cfgPath "ca.crt"
serverKeyFile = combine cfgPath "server.key"
serverCrtFile = combine cfgPath "server.crt"
in ServerCLIConfig
{ cfgDir = cfgPath,
logDir = logPath,
iniFile = combine cfgPath "smp-server.ini",
storeLogFile = combine logPath "smp-server-store.log",
caKeyFile = combine cfgPath "ca.key",
caCrtFile,
serverKeyFile,
serverCrtFile,
fingerprintFile = combine cfgPath "fingerprint",
defaultServerPort = "5223",
executableName = "smp-server",
serverVersion = "SMP server v" <> simplexMQVersion,
mkIniFile = \enableStoreLog defaultServerPort ->
"[STORE_LOG]\n\
\# The server uses STM memory for persistence,\n\
\# that will be lost on restart (e.g., as with redis).\n\
\# This option enables saving memory to append only log,\n\
\# and restoring it when the server is started.\n\
\# Log is compacted on start (deleted objects are removed).\n"
<> ("enable: " <> (if enableStoreLog then "on" else "off") <> "\n")
<> "# Undelivered messages are optionally saved and restored when the server restarts,\n\
\# they are preserved in the .bak file until the next restart.\n"
<> ("restore_messages: " <> (if enableStoreLog then "on" else "off") <> "\n")
<> ("log_stats: off\n\n")
<> "[TRANSPORT]\n"
<> ("port: " <> defaultServerPort <> "\n")
<> "websockets: off\n\n"
<> "[INACTIVE_CLIENTS]\n\
\# TTL and interval to check inactive clients\n\
\disconnect: off\n"
<> ("# ttl: " <> show (ttl defaultInactiveClientExpiration) <> "\n")
<> ("# check_interval: " <> show (checkInterval defaultInactiveClientExpiration) <> "\n"),
mkServerConfig = \storeLogFile transports ini ->
let settingIsOn section name = if lookupValue section name ini == Right "on" then Just () else Nothing
logStats = settingIsOn "STORE_LOG" "log_stats"
in ServerConfig
{ transports,
tbqSize = 16,
serverTbqSize = 64,
msgQueueQuota = 128,
queueIdBytes = 24,
msgIdBytes = 24, -- must be at least 24 bytes, it is used as 192-bit nonce for XSalsa20
caCertificateFile = caCrtFile,
privateKeyFile = serverKeyFile,
certificateFile = serverCrtFile,
storeLogFile,
storeMsgsFile =
let messagesPath = combine logPath "smp-server-messages.log"
in case lookupValue "STORE_LOG" "restore_messages" ini of
Right "on" -> Just messagesPath
Right _ -> Nothing
-- if the setting is not set, it is enabled when store log is enabled
_ -> storeLogFile $> messagesPath,
allowNewQueues = True,
messageExpiration = Just defaultMessageExpiration,
inactiveClientExpiration =
settingIsOn "INACTIVE_CLIENTS" "disconnect"
$> ExpirationConfig
{ ttl = readStrictIni "INACTIVE_CLIENTS" "ttl" ini,
checkInterval = readStrictIni "INACTIVE_CLIENTS" "check_interval" ini
},
logStatsInterval = logStats $> 86400, -- seconds
logStatsStartTime = 0, -- seconds from 00:00 UTC
serverStatsLogFile = combine logPath "smp-server-stats.daily.log",
serverStatsBackupFile = logStats $> combine logPath "smp-server-stats.log",
smpServerVRange = supportedSMPServerVRange
}
}
cfgPath <- getEnvPath "SMP_SERVER_CFG_PATH" defaultCfgPath
logPath <- getEnvPath "SMP_SERVER_LOG_PATH" defaultLogPath
withGlobalLogging logCfg $ smpServerCLI_ Static.generateSite Static.serveStaticFiles cfgPath logPath
+1
View File
@@ -0,0 +1 @@
../link.html
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
../link.html
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

@@ -0,0 +1,26 @@
<svg width="119" height="40" viewBox="0 0 119 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.44484 39.125C8.14016 39.125 7.84284 39.1211 7.54055 39.1143C6.91433 39.1061 6.28957 39.0516 5.67141 38.9512C5.095 38.8519 4.53661 38.6673 4.01467 38.4033C3.49751 38.1415 3.02582 37.7983 2.61767 37.3867C2.20361 36.98 1.85888 36.5082 1.59716 35.9902C1.33255 35.4688 1.14942 34.9099 1.05416 34.333C0.951281 33.7131 0.895621 33.0863 0.887656 32.458C0.881316 32.2471 0.873016 31.5449 0.873016 31.5449V8.44434C0.873016 8.44434 0.881856 7.75293 0.887706 7.5498C0.895332 6.92248 0.950669 6.29665 1.05324 5.67773C1.14868 5.09925 1.33194 4.53875 1.5967 4.01563C1.85746 3.49794 2.20027 3.02586 2.61184 2.61768C3.02294 2.20562 3.49614 1.8606 4.01418 1.59521C4.53492 1.33209 5.09225 1.14873 5.6675 1.05127C6.28769 0.949836 6.91462 0.894996 7.54301 0.88721L8.44533 0.875H111.214L112.127 0.8877C112.75 0.895099 113.371 0.94945 113.985 1.05029C114.566 1.14898 115.13 1.33362 115.656 1.59814C116.694 2.13299 117.539 2.97916 118.071 4.01807C118.332 4.53758 118.512 5.09351 118.606 5.66699C118.71 6.29099 118.768 6.92174 118.78 7.5542C118.783 7.8374 118.783 8.1416 118.783 8.44434C118.791 8.81934 118.791 9.17627 118.791 9.53613V30.4648C118.791 30.8281 118.791 31.1826 118.783 31.54C118.783 31.8652 118.783 32.1631 118.779 32.4697C118.768 33.0909 118.71 33.7104 118.608 34.3232C118.515 34.9043 118.333 35.4675 118.068 35.9932C117.805 36.5056 117.462 36.9733 117.053 37.3789C116.644 37.7927 116.172 38.1379 115.653 38.4014C115.128 38.6674 114.566 38.8527 113.985 38.9512C113.367 39.0522 112.742 39.1067 112.116 39.1143C111.823 39.1211 111.517 39.125 111.219 39.125L110.135 39.127L8.44484 39.125Z" fill="black"/>
<path d="M24.7689 20.3007C24.7796 19.466 25.0013 18.6477 25.4134 17.9217C25.8254 17.1957 26.4144 16.5858 27.1254 16.1486C26.6737 15.5035 26.0778 14.9725 25.3849 14.598C24.6921 14.2234 23.9215 14.0156 23.1343 13.991C21.455 13.8147 19.8271 14.9958 18.9714 14.9958C18.0991 14.9958 16.7816 14.0085 15.3629 14.0376C14.4452 14.0673 13.5509 14.3341 12.767 14.8122C11.9831 15.2903 11.3364 15.9632 10.89 16.7655C8.95597 20.1139 10.3986 25.035 12.2512 27.7416C13.1781 29.0669 14.2613 30.5474 15.6788 30.4949C17.0659 30.4374 17.5839 29.6104 19.2582 29.6104C20.917 29.6104 21.403 30.4949 22.8492 30.4615C24.3376 30.4374 25.2753 29.1303 26.1697 27.7924C26.8357 26.848 27.3481 25.8043 27.6881 24.6999C26.8234 24.3341 26.0855 23.722 25.5664 22.9397C25.0473 22.1574 24.7699 21.2396 24.7689 20.3007V20.3007Z" fill="white"/>
<path d="M22.0373 12.2109C22.8488 11.2367 23.2486 9.98451 23.1518 8.72028C21.9119 8.8505 20.7667 9.44306 19.9442 10.3799C19.5421 10.8376 19.2341 11.37 19.0378 11.9468C18.8416 12.5235 18.7609 13.1333 18.8005 13.7413C19.4206 13.7477 20.0341 13.6132 20.5948 13.3482C21.1555 13.0831 21.6487 12.6942 22.0373 12.2109Z" fill="white"/>
<path d="M42.3023 27.1396H37.5689L36.4322 30.4961H34.4273L38.9107 18.0781H40.9937L45.4771 30.4961H43.438L42.3023 27.1396ZM38.0591 25.5908H41.8111L39.9615 20.1435H39.9097L38.0591 25.5908Z" fill="white"/>
<path d="M55.1597 25.9697C55.1597 28.7832 53.6538 30.5908 51.3814 30.5908C50.8057 30.6209 50.2332 30.4883 49.7294 30.2082C49.2256 29.928 48.8109 29.5117 48.5327 29.0068H48.4897V33.4912H46.6313V21.4424H48.4302V22.9482H48.4644C48.7553 22.4458 49.1771 22.0316 49.6847 21.7497C50.1923 21.4679 50.7669 21.3289 51.3472 21.3476C53.645 21.3477 55.1597 23.1641 55.1597 25.9697ZM53.2495 25.9697C53.2495 24.1367 52.3023 22.9316 50.857 22.9316C49.437 22.9316 48.482 24.1621 48.482 25.9697C48.482 27.7939 49.437 29.0156 50.857 29.0156C52.3023 29.0156 53.2495 27.8193 53.2495 25.9697Z" fill="white"/>
<path d="M65.1245 25.9697C65.1245 28.7832 63.6187 30.5908 61.3462 30.5908C60.7706 30.6209 60.1981 30.4883 59.6943 30.2082C59.1905 29.928 58.7758 29.5117 58.4976 29.0068H58.4546V33.4912H56.5962V21.4424H58.395V22.9482H58.4292C58.7201 22.4458 59.1419 22.0316 59.6495 21.7497C60.1571 21.4679 60.7317 21.3289 61.312 21.3476C63.6099 21.3476 65.1245 23.164 65.1245 25.9697ZM63.2144 25.9697C63.2144 24.1367 62.2671 22.9316 60.8218 22.9316C59.4019 22.9316 58.4468 24.1621 58.4468 25.9697C58.4468 27.7939 59.4019 29.0156 60.8218 29.0156C62.2671 29.0156 63.2144 27.8193 63.2144 25.9697H63.2144Z" fill="white"/>
<path d="M71.7105 27.0361C71.8482 28.2676 73.0445 29.0761 74.6792 29.0761C76.2456 29.0761 77.3726 28.2675 77.3726 27.1572C77.3726 26.1933 76.6929 25.6162 75.0835 25.2207L73.4742 24.833C71.1939 24.2822 70.1353 23.2158 70.1353 21.4853C70.1353 19.3427 72.0025 17.871 74.6538 17.871C77.2778 17.871 79.0767 19.3427 79.1372 21.4853H77.2612C77.1489 20.246 76.1245 19.498 74.6274 19.498C73.1304 19.498 72.106 20.2548 72.106 21.3564C72.106 22.2343 72.7603 22.7509 74.3608 23.1464L75.729 23.4823C78.2769 24.0849 79.3355 25.1083 79.3355 26.9247C79.3355 29.248 77.4849 30.703 74.5415 30.703C71.7876 30.703 69.9282 29.2821 69.8081 27.036L71.7105 27.0361Z" fill="white"/>
<path d="M83.3462 19.2998V21.4424H85.0679V22.9141H83.3462V27.9053C83.3462 28.6807 83.6909 29.042 84.4478 29.042C84.6522 29.0384 84.8562 29.0241 85.0591 28.999V30.4619C84.7188 30.5255 84.373 30.5543 84.0269 30.5478C82.1939 30.5478 81.479 29.8593 81.479 28.1035V22.9141H80.1626V21.4424H81.479V19.2998H83.3462Z" fill="white"/>
<path d="M86.065 25.9697C86.065 23.1211 87.7427 21.3311 90.3589 21.3311C92.9839 21.3311 94.6539 23.1211 94.6539 25.9697C94.6539 28.8262 92.9927 30.6084 90.3589 30.6084C87.7261 30.6084 86.065 28.8262 86.065 25.9697ZM92.7603 25.9697C92.7603 24.0156 91.8648 22.8623 90.3589 22.8623C88.8531 22.8623 87.9585 24.0244 87.9585 25.9697C87.9585 27.9316 88.8531 29.0762 90.3589 29.0762C91.8648 29.0762 92.7603 27.9316 92.7603 25.9697H92.7603Z" fill="white"/>
<path d="M96.1861 21.4424H97.9585V22.9834H98.0015C98.1215 22.5021 98.4034 22.0768 98.8 21.7789C99.1966 21.481 99.6836 21.3287 100.179 21.3476C100.393 21.3469 100.607 21.3702 100.816 21.417V23.1553C100.546 23.0726 100.264 23.0347 99.981 23.043C99.711 23.032 99.4419 23.0796 99.192 23.1825C98.9422 23.2854 98.7176 23.4411 98.5336 23.639C98.3496 23.8369 98.2106 24.0723 98.1262 24.3289C98.0418 24.5856 98.0139 24.8575 98.0445 25.126V30.4961H96.1861L96.1861 21.4424Z" fill="white"/>
<path d="M109.384 27.8369C109.134 29.4805 107.534 30.6084 105.486 30.6084C102.852 30.6084 101.217 28.8437 101.217 26.0127C101.217 23.1729 102.861 21.3311 105.408 21.3311C107.913 21.3311 109.488 23.0518 109.488 25.7969V26.4336H103.093V26.5459C103.064 26.8791 103.105 27.2148 103.216 27.5306C103.326 27.8464 103.502 28.1352 103.732 28.3778C103.963 28.6203 104.242 28.8111 104.552 28.9374C104.861 29.0637 105.195 29.1226 105.529 29.1103C105.968 29.1515 106.409 29.0498 106.785 28.8203C107.162 28.5909 107.455 28.246 107.62 27.8369L109.384 27.8369ZM103.102 25.1348H107.628C107.645 24.8352 107.6 24.5354 107.495 24.2541C107.39 23.9729 107.229 23.7164 107.02 23.5006C106.812 23.2849 106.561 23.1145 106.283 23.0003C106.006 22.8861 105.708 22.8305 105.408 22.8369C105.105 22.8351 104.805 22.8933 104.525 23.008C104.245 23.1227 103.99 23.2918 103.776 23.5054C103.562 23.7191 103.392 23.973 103.276 24.2527C103.16 24.5323 103.101 24.8321 103.102 25.1348V25.1348Z" fill="white"/>
<path d="M37.8262 8.73101C38.2158 8.70305 38.6068 8.76191 38.9709 8.90335C39.335 9.04478 39.6632 9.26526 39.9318 9.54889C40.2004 9.83251 40.4026 10.1722 40.524 10.5435C40.6455 10.9148 40.6829 11.3083 40.6338 11.6959C40.6338 13.6021 39.6035 14.6979 37.8262 14.6979H35.6709V8.73101H37.8262ZM36.5977 13.854H37.7227C38.0011 13.8707 38.2797 13.825 38.5382 13.7204C38.7968 13.6158 39.0287 13.4548 39.2172 13.2493C39.4057 13.0437 39.546 12.7987 39.6279 12.5321C39.7097 12.2655 39.7311 11.9839 39.6904 11.708C39.7282 11.4332 39.7046 11.1534 39.6215 10.8887C39.5384 10.6241 39.3977 10.3811 39.2097 10.1771C39.0216 9.97322 38.7908 9.81341 38.5337 9.70917C38.2766 9.60494 37.9997 9.55885 37.7227 9.57422H36.5977V13.854Z" fill="white"/>
<path d="M41.6807 12.4443C41.6524 12.1484 41.6862 11.8499 41.7801 11.5678C41.8739 11.2857 42.0257 11.0264 42.2256 10.8064C42.4255 10.5864 42.6693 10.4107 42.9411 10.2904C43.213 10.1701 43.507 10.108 43.8042 10.108C44.1015 10.108 44.3955 10.1701 44.6673 10.2904C44.9392 10.4107 45.1829 10.5864 45.3828 10.8064C45.5828 11.0264 45.7345 11.2857 45.8284 11.5678C45.9222 11.8499 45.9561 12.1484 45.9278 12.4443C45.9566 12.7406 45.9232 13.0396 45.8296 13.3221C45.736 13.6046 45.5843 13.8644 45.3843 14.0848C45.1843 14.3052 44.9404 14.4814 44.6683 14.6019C44.3962 14.7225 44.1018 14.7847 43.8042 14.7847C43.5066 14.7847 43.2123 14.7225 42.9401 14.6019C42.668 14.4814 42.4241 14.3052 42.2241 14.0848C42.0241 13.8644 41.8725 13.6046 41.7789 13.3221C41.6853 13.0396 41.6518 12.7406 41.6807 12.4443V12.4443ZM45.0137 12.4443C45.0137 11.4683 44.5752 10.8975 43.8057 10.8975C43.0332 10.8975 42.5987 11.4683 42.5987 12.4444C42.5987 13.4282 43.0333 13.9946 43.8057 13.9946C44.5752 13.9946 45.0137 13.4243 45.0137 12.4443H45.0137Z" fill="white"/>
<path d="M51.5733 14.6978H50.6514L49.7207 11.3813H49.6504L48.7237 14.6978H47.8106L46.5694 10.1948H47.4707L48.2774 13.6308H48.3438L49.2696 10.1948H50.1221L51.0479 13.6308H51.1182L51.9209 10.1948H52.8096L51.5733 14.6978Z" fill="white"/>
<path d="M53.8536 10.1948H54.709V10.9102H54.7754C54.8881 10.6532 55.0781 10.4379 55.319 10.2941C55.5598 10.1503 55.8396 10.0852 56.1192 10.1079C56.3383 10.0914 56.5583 10.1245 56.7629 10.2046C56.9675 10.2847 57.1514 10.4098 57.3011 10.5706C57.4508 10.7315 57.5624 10.9239 57.6276 11.1337C57.6928 11.3436 57.7099 11.5654 57.6778 11.7827V14.6977H56.7891V12.0059C56.7891 11.2822 56.4746 10.9224 55.8174 10.9224C55.6687 10.9154 55.5202 10.9408 55.3821 10.9966C55.244 11.0524 55.1197 11.1375 55.0176 11.2458C54.9154 11.3542 54.838 11.4834 54.7904 11.6245C54.7429 11.7657 54.7265 11.9154 54.7422 12.0635V14.6978H53.8535L53.8536 10.1948Z" fill="white"/>
<path d="M59.0938 8.43701H59.9825V14.6978H59.0938V8.43701Z" fill="white"/>
<path d="M61.2178 12.4443C61.1895 12.1484 61.2234 11.8498 61.3172 11.5677C61.4111 11.2857 61.5629 11.0263 61.7629 10.8063C61.9628 10.5863 62.2065 10.4106 62.4784 10.2903C62.7503 10.17 63.0443 10.1079 63.3416 10.1079C63.6389 10.1079 63.9329 10.17 64.2047 10.2903C64.4766 10.4106 64.7203 10.5863 64.9203 10.8063C65.1203 11.0263 65.272 11.2857 65.3659 11.5677C65.4598 11.8498 65.4936 12.1484 65.4654 12.4443C65.4942 12.7406 65.4607 13.0396 65.3671 13.3221C65.2734 13.6046 65.1218 13.8644 64.9217 14.0848C64.7217 14.3052 64.4778 14.4814 64.2057 14.6019C63.9335 14.7224 63.6392 14.7847 63.3416 14.7847C63.044 14.7847 62.7496 14.7224 62.4775 14.6019C62.2053 14.4814 61.9614 14.3052 61.7614 14.0848C61.5614 13.8644 61.4097 13.6046 61.3161 13.3221C61.2225 13.0396 61.189 12.7406 61.2178 12.4443V12.4443ZM64.5508 12.4443C64.5508 11.4683 64.1123 10.8975 63.3428 10.8975C62.5703 10.8975 62.1358 11.4683 62.1358 12.4444C62.1358 13.4282 62.5704 13.9946 63.3428 13.9946C64.1123 13.9946 64.5508 13.4243 64.5508 12.4443H64.5508Z" fill="white"/>
<path d="M66.4009 13.4243C66.4009 12.6138 67.0044 12.1465 68.0757 12.0801L69.2954 12.0098V11.6211C69.2954 11.1455 68.981 10.877 68.3736 10.877C67.8775 10.877 67.5337 11.0591 67.4351 11.3775H66.5747C66.6656 10.604 67.3931 10.1079 68.4146 10.1079C69.5435 10.1079 70.1802 10.6699 70.1802 11.6211V14.6978H69.3247V14.065H69.2544C69.1117 14.292 68.9113 14.477 68.6737 14.6012C68.4361 14.7254 68.1697 14.7844 67.9019 14.772C67.7129 14.7916 67.5218 14.7715 67.341 14.7128C67.1603 14.6541 66.9938 14.5581 66.8524 14.4312C66.711 14.3042 66.5977 14.149 66.52 13.9756C66.4422 13.8022 66.4017 13.6144 66.4009 13.4243V13.4243ZM69.2954 13.0396V12.6631L68.1958 12.7334C67.5757 12.7749 67.2945 12.9859 67.2945 13.3828C67.2945 13.7881 67.646 14.0239 68.1295 14.0239C68.2711 14.0383 68.4142 14.024 68.5502 13.9819C68.6862 13.9398 68.8123 13.8708 68.9211 13.7789C69.0299 13.6871 69.1191 13.5743 69.1834 13.4473C69.2477 13.3203 69.2858 13.1816 69.2954 13.0396V13.0396Z" fill="white"/>
<path d="M71.3482 12.4444C71.3482 11.0215 72.0796 10.1201 73.2173 10.1201C73.4987 10.1072 73.778 10.1746 74.0226 10.3145C74.2671 10.4544 74.4667 10.661 74.5982 10.9101H74.6646V8.43701H75.5533V14.6978H74.7017V13.9863H74.6314C74.4898 14.2338 74.2832 14.4378 74.0339 14.5763C73.7847 14.7148 73.5023 14.7825 73.2173 14.772C72.0718 14.772 71.3482 13.8706 71.3482 12.4444ZM72.2662 12.4444C72.2662 13.3994 72.7164 13.9741 73.4693 13.9741C74.2183 13.9741 74.6812 13.3911 74.6812 12.4483C74.6812 11.5098 74.2134 10.9185 73.4693 10.9185C72.7212 10.9185 72.2661 11.4971 72.2661 12.4444H72.2662Z" fill="white"/>
<path d="M79.23 12.4443C79.2017 12.1484 79.2356 11.8499 79.3294 11.5678C79.4232 11.2857 79.575 11.0264 79.7749 10.8064C79.9749 10.5864 80.2186 10.4107 80.4904 10.2904C80.7623 10.1701 81.0563 10.108 81.3536 10.108C81.6508 10.108 81.9448 10.1701 82.2167 10.2904C82.4885 10.4107 82.7322 10.5864 82.9322 10.8064C83.1321 11.0264 83.2839 11.2857 83.3777 11.5678C83.4715 11.8499 83.5054 12.1484 83.4771 12.4443C83.5059 12.7406 83.4725 13.0396 83.3789 13.3221C83.2853 13.6046 83.1336 13.8644 82.9336 14.0848C82.7336 14.3052 82.4897 14.4814 82.2176 14.6019C81.9455 14.7225 81.6512 14.7847 81.3536 14.7847C81.0559 14.7847 80.7616 14.7225 80.4895 14.6019C80.2173 14.4814 79.9735 14.3052 79.7735 14.0848C79.5735 13.8644 79.4218 13.6046 79.3282 13.3221C79.2346 13.0396 79.2012 12.7406 79.23 12.4443V12.4443ZM82.563 12.4443C82.563 11.4683 82.1245 10.8975 81.355 10.8975C80.5826 10.8975 80.148 11.4683 80.148 12.4444C80.148 13.4282 80.5826 13.9946 81.355 13.9946C82.1245 13.9946 82.563 13.4243 82.563 12.4443Z" fill="white"/>
<path d="M84.6695 10.1948H85.5249V10.9102H85.5913C85.704 10.6532 85.894 10.4379 86.1349 10.2941C86.3757 10.1503 86.6555 10.0852 86.9351 10.1079C87.1542 10.0914 87.3742 10.1245 87.5788 10.2046C87.7834 10.2847 87.9673 10.4098 88.117 10.5706C88.2667 10.7315 88.3783 10.9239 88.4435 11.1337C88.5087 11.3436 88.5258 11.5654 88.4937 11.7827V14.6977H87.605V12.0059C87.605 11.2822 87.2906 10.9224 86.6333 10.9224C86.4846 10.9154 86.3361 10.9408 86.198 10.9966C86.06 11.0524 85.9356 11.1375 85.8335 11.2458C85.7314 11.3542 85.6539 11.4834 85.6064 11.6245C85.5588 11.7657 85.5424 11.9154 85.5581 12.0635V14.6978H84.6695V10.1948Z" fill="white"/>
<path d="M93.5152 9.07373V10.2153H94.4908V10.9639H93.5152V13.2793C93.5152 13.751 93.7095 13.9575 94.1519 13.9575C94.2651 13.9572 94.3783 13.9503 94.4908 13.937V14.6772C94.3312 14.7058 94.1695 14.721 94.0074 14.7226C93.0191 14.7226 92.6255 14.375 92.6255 13.5068V10.9638H91.9107V10.2153H92.6255V9.07373H93.5152Z" fill="white"/>
<path d="M95.7046 8.43701H96.5855V10.9185H96.6558C96.7739 10.6591 96.9691 10.4425 97.2148 10.2982C97.4605 10.1539 97.7448 10.0888 98.0288 10.1118C98.2467 10.1 98.4646 10.1364 98.6669 10.2184C98.8692 10.3004 99.0509 10.4261 99.199 10.5864C99.3471 10.7468 99.458 10.9378 99.5238 11.146C99.5896 11.3541 99.6086 11.5742 99.5796 11.7905V14.6978H98.69V12.0098C98.69 11.2905 98.355 10.9263 97.7271 10.9263C97.5744 10.9137 97.4207 10.9347 97.277 10.9878C97.1332 11.0408 97.0027 11.1247 96.8948 11.2334C96.7868 11.3421 96.7038 11.4732 96.6518 11.6173C96.5997 11.7614 96.5798 11.9152 96.5933 12.0679V14.6977H95.7047L95.7046 8.43701Z" fill="white"/>
<path d="M104.761 13.4819C104.641 13.8935 104.379 14.2495 104.022 14.4876C103.666 14.7258 103.236 14.8309 102.81 14.7847C102.513 14.7925 102.219 14.7357 101.946 14.6182C101.674 14.5006 101.43 14.3252 101.232 14.1041C101.034 13.8829 100.887 13.6214 100.8 13.3376C100.713 13.0537 100.689 12.7544 100.73 12.4605C100.691 12.1656 100.715 11.8656 100.801 11.581C100.888 11.2963 101.034 11.0335 101.231 10.8105C101.428 10.5874 101.671 10.4092 101.942 10.288C102.214 10.1668 102.509 10.1054 102.806 10.1079C104.059 10.1079 104.815 10.9639 104.815 12.3779V12.688H101.635V12.7378C101.621 12.9031 101.642 13.0694 101.696 13.2261C101.75 13.3829 101.837 13.5266 101.95 13.6481C102.062 13.7695 102.2 13.866 102.352 13.9314C102.504 13.9968 102.669 14.0297 102.835 14.0278C103.047 14.0533 103.262 14.0151 103.453 13.9178C103.644 13.8206 103.802 13.6689 103.906 13.4819L104.761 13.4819ZM101.635 12.0308H103.91C103.921 11.8796 103.9 11.7278 103.849 11.5851C103.798 11.4424 103.718 11.3119 103.614 11.2021C103.509 11.0922 103.383 11.0054 103.243 10.9472C103.103 10.8891 102.953 10.8608 102.801 10.8643C102.648 10.8623 102.495 10.8912 102.353 10.9491C102.21 11.0071 102.081 11.0929 101.972 11.2017C101.864 11.3104 101.778 11.4397 101.72 11.5821C101.662 11.7245 101.633 11.8771 101.635 12.0308H101.635Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

+66
View File
@@ -0,0 +1,66 @@
(function () {
let complete = false
run()
window.onload = run
async function run() {
const connURIel = document.getElementById("conn_req_uri_text");
const mobileConnURIanchor = document.getElementById("mobile_conn_req_uri");
const connQRCodes = document.getElementsByClassName("conn_req_uri_qrcode");
console.log(connQRCodes);
if (complete || !connURIel || !mobileConnURIanchor || connQRCodes < 2) return
complete = true
let connURI = document.location.toString()
const parsedURI = new URL(connURI)
const path = parsedURI.pathname.split("/")
const len = path.length
const action = path[len - (path[len - 1] == "" ? 2 : 1)]
parsedURI.protocol = "https"
parsedURI.pathname = "/" + action
connURI = parsedURI.toString()
console.log("connection URI: ", connURI)
mobileConnURIanchor.href = "simplex:" + parsedURI.pathname + parsedURI.hash
connURIel.innerText = "/c " + connURI
for (const connQRCode of connQRCodes) {
try {
await QRCode.toCanvas(connQRCode, connURI, {
errorCorrectionLevel: "M",
color: {dark: "#062D56"}
});
connQRCode.style.width = "320px";
connQRCode.style.height = "320px";
} catch (err) {
console.error(err);
}
}
function contentCopyWithTooltip(parent) {
const content = parent.querySelector(".content");
const tooltip = parent.querySelector(".tooltiptext");
console.log(parent.querySelector(".content_copy"), 111)
console.log(parent)
const copyButton = parent.querySelector(".content_copy");
copyButton.addEventListener("click", copyAddress)
copyButton.addEventListener("mouseout", resetTooltip)
function copyAddress() {
navigator.clipboard.writeText(content.innerText || content.value);
tooltip.innerHTML = "Copied!";
}
function resetTooltip() {
tooltip.innerHTML = "Copy to clipboard";
}
}
function copyAddress() {
navigator.clipboard.writeText(connURI);
tooltipEl.innerHTML = "Copied!";
}
function resetTooltip() {
tooltipEl.innerHTML = "Copy to clipboard";
}
}
})();
Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

+372
View File
@@ -0,0 +1,372 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="560"
height="164"
version="1.1"
id="svg1048"
sodipodi:docname="f_droid.svg"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1050"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
showgrid="false"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-intersection-paths="true"
inkscape:object-paths="true"
inkscape:snap-smooth-nodes="true"
inkscape:snap-midpoints="true"
inkscape:snap-object-midpoints="true"
inkscape:snap-center="true"
inkscape:snap-text-baseline="true"
inkscape:snap-page="true"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="1.1996734"
inkscape:cx="186.71748"
inkscape:cy="100.02722"
inkscape:window-width="1920"
inkscape:window-height="1007"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg1048" />
<defs
id="defs974">
<linearGradient
id="a">
<stop
offset="0"
stop-color="#fff"
stop-opacity=".098"
id="stop968" />
<stop
offset="1"
stop-color="#fff"
stop-opacity="0"
id="stop970" />
</linearGradient>
<radialGradient
xlink:href="#a"
id="b"
cx="113"
cy="-12.89"
fx="113"
fy="-12.89"
r="59.661999"
gradientTransform="matrix(0,1.96105,-1.97781,0,254.507,78.763)"
gradientUnits="userSpaceOnUse" />
</defs>
<g
transform="translate(-332,-355.362)"
id="g1046">
<rect
style="stroke:none;marker:none"
width="560"
height="164"
x="332"
y="355.362"
rx="20"
ry="20"
color="#000000"
overflow="visible"
stroke="#a6a6a6"
stroke-width="4"
id="rect976" />
<text
y="402.367"
x="508.95099"
style="line-height:100%;-inkscape-font-specification:'DejaVu Sans';marker:none"
color="#000000"
font-weight="400"
font-size="12.395px"
font-family="'DejaVu Sans'"
letter-spacing="0"
word-spacing="0"
overflow="visible"
fill="#ffffff"
id="text980"><tspan
y="402.367"
x="508.95099"
style="-inkscape-font-specification:'DejaVu Sans'"
font-size="34.125px"
id="tspan978">GET IT ON</tspan></text>
<text
style="line-height:100%;-inkscape-font-specification:'Rokkitt Bold';text-align:start;marker:none"
x="508.21301"
y="489.36099"
color="#000000"
font-weight="700"
font-size="29.709px"
font-family="Rokkitt"
letter-spacing="0"
word-spacing="0"
overflow="visible"
fill="#ffffff"
id="text984"><tspan
x="508.21301"
y="489.36099"
style="line-height:100%;-inkscape-font-specification:'Roboto Slab Bold';text-align:start"
font-size="95px"
font-family="'Roboto Slab'"
id="tspan982">F-Droid</tspan></text>
<g
fill-rule="evenodd"
id="g994">
<path
d="m 2.589,1006.862 4.25,5.5"
fill="#8ab000"
stroke="#769616"
stroke-width="2.5"
stroke-linecap="round"
transform="matrix(-2.63159,0,0,2.63157,483.158,-2270.475)"
id="path986" />
<path
style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;isolation:auto;mix-blend-mode:normal"
d="m 476.286,375.862 c 1.193,0.031 2.004,0.497 2.58,1.18 -5.333,6.34 -6.232,7.347 -13.514,16.372 -2.683,3.472 -5.478,1.678 -2.795,-1.793 l 11.185,-14.474 c 0.602,-0.804 1.54,-1.258 2.544,-1.285 z"
color="#000000"
font-weight="400"
font-family="sans-serif"
white-space="normal"
overflow="visible"
fill="#ffffff"
fill-opacity="0.298"
id="path988" />
<path
style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;isolation:auto;mix-blend-mode:normal"
d="m 478.89,377.075 c 0.325,0.39 1.476,2.118 0.058,4.096 l -11.184,14.473 c -2.683,3.471 -3.026,-1.611 -3.026,-1.611 0,0 9.828,-11.869 14.151,-16.958 z"
color="#000000"
font-weight="400"
font-family="sans-serif"
white-space="normal"
overflow="visible"
fill="#263238"
fill-opacity="0.2"
id="path990" />
<path
style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;isolation:auto;mix-blend-mode:normal"
d="m 477.006,376.48 c 1.153,0 2.525,0.373 2.169,2.102 -0.273,1.32 -12.266,15.985 -12.266,15.985 -2.683,3.47 -6.562,1.78 -3.879,-1.691 l 11.143,-14.402 c 0.685,-0.763 1.602,-1.957 2.833,-1.994 z"
color="#000000"
font-weight="400"
font-family="sans-serif"
white-space="normal"
overflow="visible"
fill="#8ab000"
id="path992" />
</g>
<g
fill-rule="evenodd"
id="g1004">
<path
d="m 2.589,1006.862 4.25,5.5"
fill="#8ab000"
stroke="#769616"
stroke-width="2.5"
stroke-linecap="round"
transform="matrix(2.63159,0,0,2.63157,356.842,-2270.475)"
id="path996" />
<path
d="m 363.714,375.862 c -1.193,0.031 -2.004,0.497 -2.58,1.18 5.333,6.34 6.232,7.347 13.514,16.372 2.683,3.472 5.478,1.678 2.795,-1.793 l -11.185,-14.474 c -0.602,-0.804 -1.54,-1.258 -2.544,-1.285 z"
style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;isolation:auto;mix-blend-mode:normal"
color="#000000"
font-weight="400"
font-family="sans-serif"
white-space="normal"
overflow="visible"
fill="#ffffff"
fill-opacity="0.298"
id="path998" />
<path
d="m 361.11,377.075 c -0.325,0.39 -1.476,2.118 -0.058,4.096 l 11.184,14.473 c 2.683,3.471 3.026,-1.611 3.026,-1.611 0,0 -9.828,-11.869 -14.151,-16.958 z"
style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;isolation:auto;mix-blend-mode:normal"
color="#000000"
font-weight="400"
font-family="sans-serif"
white-space="normal"
overflow="visible"
fill="#263238"
fill-opacity="0.2"
id="path1000" />
<path
d="m 362.995,376.48 c -1.153,0 -2.526,0.373 -2.17,2.102 0.273,1.32 12.266,15.985 12.266,15.985 2.683,3.47 6.562,1.78 3.879,-1.691 l -11.143,-14.402 c -0.685,-0.763 -1.602,-1.957 -2.832,-1.994 z"
style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;isolation:auto;mix-blend-mode:normal"
color="#000000"
font-weight="400"
font-family="sans-serif"
white-space="normal"
overflow="visible"
fill="#8ab000"
id="path1002" />
</g>
<g
transform="matrix(2.63159,0,0,2.63157,467.369,-2270.475)"
id="g1014">
<rect
ry="3"
rx="3"
y="1010.36"
x="-37"
height="12.92"
width="38"
fill="#aeea00"
id="rect1006" />
<rect
width="38"
height="10"
x="-37"
y="1013.279"
rx="3"
ry="3"
fill="#263238"
fill-opacity="0.2"
id="rect1008" />
<rect
width="38"
height="10"
x="-37"
y="1010.362"
rx="3"
ry="3"
fill="#ffffff"
fill-opacity="0.298"
id="rect1010" />
<rect
width="38"
height="10.641"
x="-37"
y="1011.5"
rx="3"
ry="2.4560001"
fill="#aeea00"
id="rect1012" />
</g>
<g
transform="matrix(2.63159,0,0,2.63157,356.842,-2270.745)"
id="g1024">
<rect
ry="3"
rx="3"
y="1024.522"
x="5"
height="25.84"
width="38"
fill="#1976d2"
id="rect1016" />
<rect
width="38"
height="13"
x="5"
y="1037.3621"
rx="3"
ry="3"
fill="#263238"
fill-opacity="0.2"
id="rect1018" />
<rect
width="38"
height="13"
x="5"
y="1024.442"
rx="3"
ry="3"
fill="#ffffff"
fill-opacity="0.2"
id="rect1020" />
<rect
width="38"
height="23.559999"
x="5"
y="1025.662"
rx="3"
ry="2.7179999"
fill="#1976d2"
id="rect1022" />
</g>
<g
transform="matrix(2.63159,0,0,2.63157,356.842,396.264)"
id="g1030">
<path
d="m 24,17.75 c -2.88,0 -5.32,1.985 -6.033,4.65 H 21.18 A 3.215,3.215 0 0 1 24,20.75 3.228,3.228 0 0 1 27.25,24 3.228,3.228 0 0 1 24,27.25 3.219,3.219 0 0 1 21.07,25.4 h -3.154 c 0.642,2.766 3.132,4.85 6.084,4.85 3.434,0 6.25,-2.816 6.25,-6.25 0,-3.434 -2.816,-6.25 -6.25,-6.25 z"
style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;isolation:auto;mix-blend-mode:normal"
color="#000000"
font-weight="400"
font-family="sans-serif"
white-space="normal"
overflow="visible"
fill="#0d47a1"
id="path1026" />
<circle
r="9.5500002"
cy="24"
cx="24"
fill="none"
stroke="#0d47a1"
stroke-width="1.9"
stroke-linecap="round"
id="circle1028" />
</g>
<g
transform="matrix(2.63159,0,0,2.63157,356.842,-2269.159)"
id="g1036">
<ellipse
ry="3.875"
rx="3.375"
cx="14.375"
cy="1016.487"
fill="#263238"
fill-opacity="0.2"
id="ellipse1032" />
<circle
r="3.375"
cy="1016.987"
cx="14.375"
fill="#ffffff"
id="circle1034" />
</g>
<g
transform="matrix(2.63159,0,0,2.63157,408.158,-2269.159)"
id="g1042">
<ellipse
cy="1016.487"
cx="14.375"
rx="3.375"
ry="3.875"
fill="#263238"
fill-opacity="0.2"
id="ellipse1038" />
<circle
cx="14.375"
cy="1016.987"
r="3.375"
fill="#ffffff"
id="circle1040" />
</g>
<path
d="m 282.715,299.835 a 3.29,3.29 0 0 0 -2.662,5.336 l 9.474,12.261 A 7.894,7.894 0 0 0 289,320.257 v 18.21 a 7.877,7.877 0 0 0 7.895,7.895 h 84.21 A 7.877,7.877 0 0 0 389,338.468 v -18.211 c 0,-0.999 -0.19,-1.949 -0.525,-2.826 l 9.472,-12.26 a 3.29,3.29 0 0 0 -2.433,-5.334 3.29,3.29 0 0 0 -2.772,1.31 l -9.013,11.666 a 7.91,7.91 0 0 0 -2.624,-0.45 h -84.21 c -0.922,0 -1.8,0.163 -2.622,0.45 l -9.015,-11.666 a 3.29,3.29 0 0 0 -2.543,-1.312 z m 14.18,49.527 A 7.877,7.877 0 0 0 289,357.257 v 52.21 a 7.877,7.877 0 0 0 7.895,7.895 h 84.21 A 7.877,7.877 0 0 0 389,409.468 v -52.211 a 7.877,7.877 0 0 0 -7.895,-7.895 z"
style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;isolation:auto;mix-blend-mode:normal;fill:url(#b)"
color="#000000"
font-weight="400"
font-family="sans-serif"
white-space="normal"
overflow="visible"
fill="url(#b)"
fill-rule="evenodd"
transform="translate(81,76)"
id="path1044" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,39 @@
<svg width="135" height="41" viewBox="0 0 135 41" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M130 40.5H5C2.2 40.5 0 38.3 0 35.5V5.5C0 2.7 2.2 0.5 5 0.5H130C132.8 0.5 135 2.7 135 5.5V35.5C135 38.3 132.8 40.5 130 40.5Z" fill="black"/>
<path d="M47.4 10.7C47.4 11.5 47.2 12.2 46.7 12.7C46.1 13.3 45.4 13.6 44.5 13.6C43.6 13.6 42.9 13.3 42.3 12.7C41.7 12.1 41.4 11.4 41.4 10.5C41.4 9.60002 41.7 8.90002 42.3 8.30002C42.9 7.70002 43.6 7.40002 44.5 7.40002C44.9 7.40002 45.3 7.50002 45.7 7.70002C46.1 7.90002 46.4 8.10002 46.6 8.40002L46.1 8.90002C45.7 8.40002 45.2 8.20002 44.5 8.20002C43.9 8.20002 43.3 8.40002 42.9 8.90002C42.4 9.30002 42.2 9.90002 42.2 10.6C42.2 11.3 42.4 11.9 42.9 12.3C43.4 12.7 43.9 13 44.5 13C45.2 13 45.7 12.8 46.2 12.3C46.5 12 46.7 11.6 46.7 11.1H44.5V10.3H47.4V10.7V10.7ZM52 8.20002H49.3V10.1H51.8V10.8H49.3V12.7H52V13.5H48.5V7.50002H52V8.20002ZM55.3 13.5H54.5V8.20002H52.8V7.50002H57V8.20002H55.3V13.5ZM59.9 13.5V7.50002H60.7V13.5H59.9ZM64.1 13.5H63.3V8.20002H61.6V7.50002H65.7V8.20002H64V13.5H64.1ZM73.6 12.7C73 13.3 72.3 13.6 71.4 13.6C70.5 13.6 69.8 13.3 69.2 12.7C68.6 12.1 68.3 11.4 68.3 10.5C68.3 9.60002 68.6 8.90002 69.2 8.30002C69.8 7.70002 70.5 7.40002 71.4 7.40002C72.3 7.40002 73 7.70002 73.6 8.30002C74.2 8.90002 74.5 9.60002 74.5 10.5C74.5 11.4 74.2 12.1 73.6 12.7ZM69.8 12.2C70.2 12.6 70.8 12.9 71.4 12.9C72 12.9 72.6 12.7 73 12.2C73.4 11.8 73.7 11.2 73.7 10.5C73.7 9.80002 73.5 9.20002 73 8.80002C72.6 8.40002 72 8.10002 71.4 8.10002C70.8 8.10002 70.2 8.30002 69.8 8.80002C69.4 9.20002 69.1 9.80002 69.1 10.5C69.1 11.2 69.3 11.8 69.8 12.2ZM75.6 13.5V7.50002H76.5L79.4 12.2V7.50002H80.2V13.5H79.4L76.3 8.60002V13.5H75.6V13.5Z" fill="white" stroke="white" stroke-width="0.2" stroke-miterlimit="10"/>
<path d="M68.1 22.3C65.7 22.3 63.8 24.1 63.8 26.6C63.8 29 65.7 30.9 68.1 30.9C70.5 30.9 72.4 29.1 72.4 26.6C72.4 24 70.5 22.3 68.1 22.3ZM68.1 29.1C66.8 29.1 65.7 28 65.7 26.5C65.7 25 66.8 23.9 68.1 23.9C69.4 23.9 70.5 24.9 70.5 26.5C70.5 28 69.4 29.1 68.1 29.1ZM58.8 22.3C56.4 22.3 54.5 24.1 54.5 26.6C54.5 29 56.4 30.9 58.8 30.9C61.2 30.9 63.1 29.1 63.1 26.6C63.1 24 61.2 22.3 58.8 22.3ZM58.8 29.1C57.5 29.1 56.4 28 56.4 26.5C56.4 25 57.5 23.9 58.8 23.9C60.1 23.9 61.2 24.9 61.2 26.5C61.2 28 60.1 29.1 58.8 29.1ZM47.7 23.6V25.4H52C51.9 26.4 51.5 27.2 51 27.7C50.4 28.3 49.4 29 47.7 29C45 29 43 26.9 43 24.2C43 21.5 45.1 19.4 47.7 19.4C49.1 19.4 50.2 20 51 20.7L52.3 19.4C51.2 18.4 49.8 17.6 47.8 17.6C44.2 17.6 41.1 20.6 41.1 24.2C41.1 27.8 44.2 30.8 47.8 30.8C49.8 30.8 51.2 30.2 52.4 28.9C53.6 27.7 54 26 54 24.7C54 24.3 54 23.9 53.9 23.6H47.7V23.6ZM93.1 25C92.7 24 91.7 22.3 89.5 22.3C87.3 22.3 85.5 24 85.5 26.6C85.5 29 87.3 30.9 89.7 30.9C91.6 30.9 92.8 29.7 93.2 29L91.8 28C91.3 28.7 90.7 29.2 89.7 29.2C88.7 29.2 88.1 28.8 87.6 27.9L93.3 25.5L93.1 25V25ZM87.3 26.4C87.3 24.8 88.6 23.9 89.5 23.9C90.2 23.9 90.9 24.3 91.1 24.8L87.3 26.4ZM82.6 30.5H84.5V18H82.6V30.5ZM79.6 23.2C79.1 22.7 78.3 22.2 77.3 22.2C75.2 22.2 73.2 24.1 73.2 26.5C73.2 28.9 75.1 30.7 77.3 30.7C78.3 30.7 79.1 30.2 79.5 29.7H79.6V30.3C79.6 31.9 78.7 32.8 77.3 32.8C76.2 32.8 75.4 32 75.2 31.3L73.6 32C74.1 33.1 75.3 34.5 77.4 34.5C79.6 34.5 81.4 33.2 81.4 30.1V22.5H79.6V23.2V23.2ZM77.4 29.1C76.1 29.1 75 28 75 26.5C75 25 76.1 23.9 77.4 23.9C78.7 23.9 79.7 25 79.7 26.5C79.7 28 78.7 29.1 77.4 29.1ZM101.8 18H97.3V30.5H99.2V25.8H101.8C103.9 25.8 105.9 24.3 105.9 21.9C105.9 19.5 103.9 18 101.8 18V18ZM101.9 24H99.2V19.7H101.9C103.3 19.7 104.1 20.9 104.1 21.8C104 22.9 103.2 24 101.9 24ZM113.4 22.2C112 22.2 110.6 22.8 110.1 24.1L111.8 24.8C112.2 24.1 112.8 23.9 113.5 23.9C114.5 23.9 115.4 24.5 115.5 25.5V25.6C115.2 25.4 114.4 25.1 113.6 25.1C111.8 25.1 110 26.1 110 27.9C110 29.6 111.5 30.7 113.1 30.7C114.4 30.7 115 30.1 115.5 29.5H115.6V30.5H117.4V25.7C117.2 23.5 115.5 22.2 113.4 22.2V22.2ZM113.2 29.1C112.6 29.1 111.7 28.8 111.7 28C111.7 27 112.8 26.7 113.7 26.7C114.5 26.7 114.9 26.9 115.4 27.1C115.2 28.3 114.2 29.1 113.2 29.1V29.1ZM123.7 22.5L121.6 27.9H121.5L119.3 22.5H117.3L120.6 30.1L118.7 34.3H120.6L125.7 22.5H123.7V22.5ZM106.9 30.5H108.8V18H106.9V30.5Z" fill="white"/>
<path d="M10.4 8C10.1 8.3 10 8.8 10 9.4V31.5C10 32.1 10.2 32.6 10.5 32.9L10.6 33L23 20.6V20.4L10.4 8Z" fill="url(#paint0_linear_7_408)"/>
<path d="M27 24.8L22.9 20.7V20.4L27 16.3L27.1 16.4L32 19.2C33.4 20 33.4 21.3 32 22.1L27 24.8V24.8Z" fill="url(#paint1_linear_7_408)"/>
<path d="M27.1 24.7L22.9 20.5L10.4 33C10.9 33.5 11.6 33.5 12.5 33.1L27.1 24.7" fill="url(#paint2_linear_7_408)"/>
<path d="M27.1 16.3001L12.5 8.00005C11.6 7.50005 10.9 7.60005 10.4 8.10005L22.9 20.5001L27.1 16.3001V16.3001Z" fill="url(#paint3_linear_7_408)"/>
<path opacity="0.2" d="M27 24.6L12.5 32.8C11.7 33.3 11 33.2 10.5 32.8L10.4 32.9L10.5 33C11 33.4 11.7 33.5 12.5 33L27 24.6Z" fill="black"/>
<path opacity="0.12" d="M10.4 32.8C10.1 32.5 10 32 10 31.4V31.5C10 32.1 10.2 32.6 10.5 32.9V32.8H10.4ZM32 21.8L27 24.6L27.1 24.7L32 21.9C32.7 21.5 33 21 33 20.5C33 21 32.6 21.4 32 21.8V21.8Z" fill="black"/>
<path opacity="0.25" d="M12.5 8.10003L32 19.2C32.6 19.6 33 20 33 20.5C33 20 32.7 19.5 32 19.1L12.5 8.00003C11.1 7.20003 10 7.80003 10 9.40003V9.50003C10 8.00003 11.1 7.30003 12.5 8.10003Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear_7_408" x1="21.8" y1="9.21" x2="5.017" y2="25.992" gradientUnits="userSpaceOnUse">
<stop stop-color="#00A0FF"/>
<stop offset="0.007" stop-color="#00A1FF"/>
<stop offset="0.26" stop-color="#00BEFF"/>
<stop offset="0.512" stop-color="#00D2FF"/>
<stop offset="0.76" stop-color="#00DFFF"/>
<stop offset="1" stop-color="#00E3FF"/>
</linearGradient>
<linearGradient id="paint1_linear_7_408" x1="33.834" y1="20.501" x2="9.63699" y2="20.501" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFE000"/>
<stop offset="0.409" stop-color="#FFBD00"/>
<stop offset="0.775" stop-color="#FFA500"/>
<stop offset="1" stop-color="#FF9C00"/>
</linearGradient>
<linearGradient id="paint2_linear_7_408" x1="24.827" y1="22.796" x2="2.069" y2="45.554" gradientUnits="userSpaceOnUse">
<stop stop-color="#FF3A44"/>
<stop offset="1" stop-color="#C31162"/>
</linearGradient>
<linearGradient id="paint3_linear_7_408" x1="7.29699" y1="0.676051" x2="17.46" y2="10.8391" gradientUnits="userSpaceOnUse">
<stop stop-color="#32A071"/>
<stop offset="0.069" stop-color="#2DA771"/>
<stop offset="0.476" stop-color="#15CF74"/>
<stop offset="0.801" stop-color="#06E775"/>
<stop offset="1" stop-color="#00F076"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

@@ -0,0 +1,10 @@
<svg width="34" height="35" viewBox="0 0 34 35" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.02958 8.60922L8.622 14.2013L14.3705 8.45375L17.1669 11.2498L11.4183 16.9972L17.0114 22.5895L14.1373 25.4633L8.54422 19.871L2.79636 25.6187L0 22.8227L5.74794 17.075L0.155484 11.483L3.02958 8.60922Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.0923 25.5156L16.944 22.6642L16.9429 22.6634L22.6467 16.9612L17.0513 11.3675L17.0523 11.367L14.2548 8.56979L8.65972 2.97535L11.5114 0.123963L17.1061 5.71849L22.8099 0.015625L25.6074 2.81285L19.9035 8.51562L25.4984 14.1099L31.2025 8.40729L34 11.2045L28.2958 16.907L33.8917 22.5017L31.0399 25.3531L25.4442 19.7584L19.7409 25.4611L25.3365 31.0559L22.4848 33.9073L16.8892 28.3124L11.1864 34.0156L8.38885 31.2184L14.0923 25.5156Z" fill="url(#paint0_linear_656_10815)"/>
<defs>
<linearGradient id="paint0_linear_656_10815" x1="12.8381" y1="-0.678252" x2="9.54355" y2="31.4493" gradientUnits="userSpaceOnUse">
<stop stop-color="#01F1FF"/>
<stop offset="1" stop-color="#0197FF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,15 @@
<svg width="34" height="34" viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_14_10)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.02972 8.59396L8.62219 14.186L14.3703 8.43848L17.1668 11.2346L11.4182 16.982L17.0112 22.5742L14.1371 25.448L8.5441 19.8557L2.79651 25.6035L0 22.8074L5.74813 17.0597L0.155656 11.4678L3.02972 8.59396Z" fill="#023789"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.0922 25.5L16.9434 22.6486L16.9423 22.6478L22.6464 16.9456L17.0512 11.3519L17.0518 11.3514L14.2542 8.55418L8.65961 2.95973L11.5114 0.108337L17.106 5.70288L22.8095 0L25.607 2.79722L19.903 8.5L25.4981 14.0943L31.2022 8.39169L33.9997 11.1889L28.2957 16.8914L33.8914 22.4861L31.0396 25.3375L25.4439 19.7428L19.7404 25.4454L25.3361 31.0403L22.4843 33.8917L16.8887 28.2968L11.1862 34L8.38867 31.2028L14.0922 25.5Z" fill="url(#paint0_linear_14_10)"/>
</g>
<defs>
<linearGradient id="paint0_linear_14_10" x1="12.8379" y1="-0.693875" x2="9.54344" y2="31.4337" gradientUnits="userSpaceOnUse">
<stop stop-color="#01F1FF"/>
<stop offset="1" stop-color="#0197FF"/>
</linearGradient>
<clipPath id="clip0_14_10">
<rect width="34" height="34" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.92814 12.6789C6.17655 15.9347 11.7044 15.6463 14.5425 12.0117C14.6636 11.8566 14.6825 11.6448 14.5907 11.4708C14.4989 11.2967 14.3136 11.1926 14.1172 11.2049C11.5269 11.3673 8.97627 10.4315 7.0743 8.52765C5.17264 6.62414 4.23958 4.06868 4.40169 1.47281C4.41397 1.2762 4.30965 1.09069 4.13526 0.999048C3.96088 0.907402 3.74893 0.926696 3.59396 1.04833C3.36099 1.23117 3.13828 1.42685 2.92823 1.63726C-0.111372 4.68223 -0.111585 9.63533 2.92814 12.6789Z" stroke="black" stroke-miterlimit="10" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 632 B

File diff suppressed because one or more lines are too long
+39
View File
@@ -0,0 +1,39 @@
const isMobile = {
Android: () => navigator.userAgent.match(/Android/i),
iOS: () => navigator.userAgent.match(/iPhone|iPad|iPod/i)
};
window.addEventListener('click', clickHandler)
if (isMobile.iOS) {
for (const btn of document.getElementsByClassName("close-overlay-btn")) {
btn.addEventListener("touchend", (e) => setTimeout(() => closeOverlay(e), 100))
}
}
function clickHandler(e) {
if (e.target.closest('.contact-tab-btn')) {
e.target.closest('.contact-tab').classList.toggle('active')
}
}
window.addEventListener('load', () => {
const googlePlayBtn = document.querySelector('.google-play-btn');
const appleStoreBtn = document.querySelector('.apple-store-btn');
const fDroidBtn = document.querySelector('.f-droid-btn');
if (!googlePlayBtn || !appleStoreBtn || !fDroidBtn) return;
if (isMobile.Android()) {
googlePlayBtn.classList.remove('hidden');
fDroidBtn.classList.remove('hidden');
}
else if (isMobile.iOS()) {
appleStoreBtn.classList.remove('hidden');
}
else {
appleStoreBtn.classList.remove('hidden');
googlePlayBtn.classList.remove('hidden');
fDroidBtn.classList.remove('hidden');
}
})
+414
View File
@@ -0,0 +1,414 @@
@font-face {
font-family: Gilroy;
src: url("GilroyRegular.woff2") format("woff2");
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: Gilroy;
src: url("GilroyLight.woff2") format("woff2");
font-weight: 300;
font-style: normal;
}
@font-face {
font-family: Gilroy;
src: url("GilroyMedium.woff2") format("woff2");
font-weight: 500;
font-style: normal;
}
@font-face {
font-family: Gilroy;
src: url("GilroyBold.woff2") format("woff2");
font-weight: 700;
font-style: normal;
}
@font-face {
font-family: Gilroy;
src: url("GilroyRegularItalic.woff2") format("woff2");
font-weight: 400;
font-style: italic;
}
html {
scroll-behavior: smooth;
font-family: Gilroy, Helvetica, sans-serif;
;
letter-spacing: 0.003em;
}
img {
user-select: none;
-webkit-user-select: none;
/* For Safari and older Chrome versions */
-moz-user-select: none;
/* For Firefox */
-ms-user-select: none;
/* For Internet Explorer and Edge */
}
a{
word-wrap: break-word;
}
/* NEW SITE */
.container,
.container-fluid,
.container-xxl,
.container-xl,
.container-lg,
.container-md,
.container-sm {
width: 100%;
/* padding: 0 20px; */
margin-right: auto;
margin-left: auto;
}
@media (min-width: 576px) {
.container-sm,
.container {
max-width: 540px;
}
}
@media (min-width: 768px) {
.container-md,
.container-sm,
.container {
max-width: 720px;
}
}
@media (min-width: 992px) {
.container-lg,
.container-md,
.container-sm,
.container {
max-width: 960px;
}
}
@media (min-width: 1200px) {
.container-xl,
.container-lg,
.container-md,
.container-sm,
.container {
max-width: 1140px;
}
}
@media (min-width: 1400px) {
.container-xxl,
.container-xl,
.container-lg,
.container-md,
.container-sm,
.container {
max-width: 1320px;
}
}
.gradient-text {
background: -webkit-linear-gradient(to bottom, #53C1FF -50%, #0053D0 160%);
background: linear-gradient(to bottom, #53C1FF -50%, #0053D0 160%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-fill-color: transparent;
}
.dark .border-gradient {
background:
linear-gradient(#11182F, #11182F) padding-box,
linear-gradient(to bottom, transparent, #01F1FF 58%) border-box;
border: 1px solid transparent;
}
.dark .only-light {
display: none;
}
.only-dark {
display: none;
}
.dark .only-dark {
display: inherit;
}
.menu-link {
font-size: 16px;
line-height: 33.42px;
color: #0D0E12;
}
.dark .menu-link {
color: #fff;
}
.nav-link ul li a.active {
color: #0053D0;
}
.dark .nav-link ul li a.active {
color: #66D9E2;
}
@media (min-width:1024px) {
.nav-link-text,
.menu-link {
display: inline-block;
position: relative;
color: #0D0E12;
}
.nav-link-text::before,
.active .nav-link-text::before,
.menu-link::before {
content: "";
position: absolute;
width: 0;
height: 1px;
bottom: 0;
right: 0;
/* background-color: initial; */
transition: width 0.25s ease-out;
}
.menu-link::before {
background-color: #0D0E12;
}
.dark .menu-link::before {
background-color: #fff;
}
.active .nav-link-text::before {
width: 100%;
}
.nav-link:hover .nav-link-text::before,
.menu-link:hover::before {
width: 100%;
left: 0;
right: auto;
}
}
.sub-menu {
visibility: hidden;
opacity: 0;
color: #505158;
}
.sub-menu .no-hover {
color: #505158 !important;
}
.dark .sub-menu,
.dark .sub-menu .no-hover {
color: #fff !important;
}
.dark .sub-menu li:hover {
color: #66D9E2;
}
.sub-menu li:hover {
color: #0053D0;
}
.sub-menu {
transition: all .3s ease !important;
}
.nav-link span svg,
header nav {
transition: all 0.5s ease;
}
.nav-link:hover span svg {
transform: rotate(180deg);
}
@media (min-width:1024px) {
.nav-link:hover .sub-menu,
.nav-link:focus-within .sub-menu {
visibility: visible;
opacity: 1;
margin-top: 0;
}
}
@media (max-width: 1024px) {
.sub-menu {
max-height: 0;
transform: translateY(-10px);
transition: all .7s ease !important;
}
.active .sub-menu {
max-height: 600px;
transform: translateY(0px);
opacity: 1;
visibility: visible;
margin-top: 0;
}
header nav {
visibility: hidden;
opacity: 0;
transform: translateX(100%);
}
header nav.open {
visibility: visible;
opacity: 1;
transform: translateX(0);
}
}
.lock-scroll {
overflow: hidden;
}
/* hero */
header {
transition: all .7s ease;
}
.primary-header {
background: linear-gradient(270deg, #0053D0 35.85%, #0197FF 94.78%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-shadow: 0px 4px 74px #e9e7e2;
}
.dark .primary-header {
background: linear-gradient(270deg, #70F0F9 100%, #70F0F9 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-shadow: none;
}
.secondary-header {
color: #606c71;
text-shadow: 0px 4px 74px #e9e7e2;
}
.dark .secondary-header {
color: #fff;
text-shadow: none;
}
.description {
width: 31rem;
}
p a {
color: #0053D0;
text-decoration: underline;
text-underline-offset: 2px;
}
.dark p a {
color: #70F0F9;
}
/* For Contact & Invitation Page */
.primary-header-contact {
background: linear-gradient(251.16deg, #53c1ff 1.1%, #0053d0 100.82%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-shadow: 0px 4px 74px #e9e7e2;
}
.dark .primary-header-contact {
background: linear-gradient(270deg, #70F0F9 100%, #70F0F9 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-shadow: none;
}
.secondary-header-contact {
text-shadow: 0px 4px 74px #e9e7e2;
}
.dark .secondary-header-contact {
text-shadow: none;
}
.content_copy_with_tooltip {
background-color: #f8f8f6;
border-radius: 50px;
padding-bottom: 4px;
padding-top: 8px;
margin-top: 16px;
margin-bottom: 16px;
}
.content_copy_with_tooltip .tooltip {
vertical-align: -6px;
}
.content_copy_with_tooltip .content {
font-size: 15px;
}
.contact-tab>.contact-tab-content,
.job-tab>.job-tab-content {
opacity: 0;
max-height: 0;
transition: all 0.5s ease;
visibility: hidden;
transform: translateY(10px);
overflow: hidden;
}
.contact-tab svg,
.job-tab svg {
transform: rotate(-180deg);
transition: all .5s ease;
}
.contact-tab.active>.contact-tab-content,
.job-tab.active>.job-tab-content {
opacity: 1;
max-height: 300px;
visibility: visible;
transform: translateY(0px);
}
.for-tablet .contact-tab.active>.contact-tab-content,
.for-tablet .job-tab.active>.job-tab-content {
min-height: 450px;
}
.contact-tab.active svg,
.contact-tab:hover svg,
.job-tab.active svg,
.job-tab:hover svg {
transform: rotate(0deg);
}
.d-none-if-js-disabled {
display: none !important;
}
+11
View File
@@ -0,0 +1,11 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M23.9958 12.2815C23.9363 12.3954 23.8849 12.5146 23.8158 12.6224C23.5945 12.9674 23.2766 13.1624 22.8654 13.1685C22.2182 13.1782 21.5707 13.1764 20.9234 13.17C20.2781 13.1636 19.7772 12.6464 19.7773 11.9999C19.7774 11.3535 20.2754 10.8389 20.9237 10.8303C21.532 10.8221 22.1405 10.8258 22.7488 10.8278C23.3522 10.8298 23.7281 11.0908 23.9462 11.6508C23.956 11.6761 23.9789 11.6964 23.9958 11.719C23.9958 11.9064 23.9958 12.094 23.9958 12.2815Z" fill="white"/>
<path d="M11.7154 24.0003C11.6217 23.9526 11.5256 23.9088 11.4345 23.8564C11.0545 23.6377 10.836 23.3104 10.8286 22.87C10.8175 22.2149 10.8179 21.5593 10.828 20.9042C10.8378 20.2738 11.3597 19.7812 11.9967 19.7812C12.6336 19.7812 13.155 20.2739 13.1654 20.9042C13.1757 21.5359 13.1717 22.168 13.1682 22.7998C13.1652 23.3392 12.8885 23.7369 12.3906 23.937C12.3509 23.9529 12.3153 23.979 12.2779 24.0003C12.0904 24.0003 11.9029 24.0003 11.7154 24.0003Z" fill="white"/>
<path d="M17.2592 11.9958C17.2733 14.8825 14.9232 17.2468 12.0032 17.2612C9.11732 17.2754 6.75397 14.9264 6.73836 12.0041C6.72295 9.12027 9.07502 6.75326 11.9946 6.73835C14.8788 6.72363 17.2449 9.07587 17.2592 11.9958Z" stroke="white" stroke-width="1.5"/>
<path d="M13.1693 2.11324C13.1692 2.43329 13.1744 2.75345 13.1682 3.07341C13.1555 3.7216 12.6425 4.21934 11.995 4.21864C11.3493 4.21789 10.8358 3.71808 10.828 3.06768C10.8204 2.42766 10.8201 1.78736 10.8283 1.14738C10.8365 0.500704 11.3562 -0.000843934 12.0007 1.06615e-06C12.6437 0.000846066 13.1564 0.504314 13.1684 1.15307C13.1743 1.47303 13.1694 1.79318 13.1693 2.11324Z" fill="white"/>
<path d="M2.10878 13.1714C1.78877 13.1714 1.46872 13.1754 1.14885 13.1705C0.504832 13.1605 -0.000422735 12.6426 2.65407e-07 11.9987C0.000423265 11.3553 0.503376 10.838 1.15138 10.8301C1.79126 10.8223 2.43138 10.8222 3.07126 10.8303C3.72034 10.8385 4.21822 11.3541 4.21794 12.0012C4.21766 12.6477 3.71555 13.1609 3.06872 13.1706C2.7488 13.1753 2.42875 13.1714 2.10878 13.1714Z" fill="white"/>
<path d="M6.85268 5.524C6.82732 6.152 6.60944 6.52005 6.16969 6.72981C5.73844 6.93552 5.29738 6.90378 4.94534 6.58208C4.41604 6.09838 3.90431 5.59148 3.42451 5.05894C3.02923 4.62023 3.09727 3.9209 3.51626 3.50792C3.9361 3.09409 4.63284 3.03567 5.06893 3.43194C5.59381 3.90888 6.09569 4.41446 6.57188 4.93996C6.73726 5.12252 6.79642 5.4014 6.85268 5.524Z" fill="white"/>
<path d="M17.1426 18.4446C17.1749 17.8424 17.389 17.4819 17.8198 17.2738C18.2418 17.07 18.6812 17.0888 19.0265 17.3998C19.5706 17.8899 20.0919 18.4099 20.5814 18.9544C20.9675 19.384 20.895 20.0764 20.485 20.4873C20.0824 20.8907 19.3961 20.9756 18.9718 20.5988C18.4129 20.1026 17.89 19.5625 17.3864 19.0096C17.2323 18.8405 17.1926 18.5671 17.1426 18.4446Z" fill="white"/>
<path d="M18.2026 6.84235C17.8449 6.82333 17.4821 6.61377 17.2723 6.18256C17.0626 5.7515 17.0878 5.30837 17.4061 4.95629C17.8919 4.41887 18.4055 3.90234 18.945 3.41897C19.3826 3.02693 20.0905 3.1037 20.4947 3.52429C20.9057 3.95198 20.9561 4.64003 20.5568 5.07805C20.0843 5.59645 19.576 6.08306 19.071 6.5708C18.8688 6.76619 18.6057 6.84832 18.2026 6.84235Z" fill="white"/>
<path d="M5.54205 17.1445C6.14812 17.1747 6.51058 17.385 6.72137 17.8153C6.9323 18.2459 6.90765 18.6892 6.58942 19.0415C6.1037 19.5791 5.58933 20.0948 5.05088 20.5795C4.62165 20.9659 3.93035 20.8989 3.51681 20.4933C3.09875 20.0833 3.02864 19.3789 3.4227 18.942C3.908 18.404 4.42706 17.8934 4.96382 17.4066C5.13982 17.247 5.41663 17.1985 5.54205 17.1445Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

+176
View File
@@ -0,0 +1,176 @@
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
module Static where
import Control.Logger.Simple
import Control.Monad
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Data.Maybe (fromMaybe)
import Data.String (fromString)
import Data.Text.Encoding (encodeUtf8)
import Network.Wai.Application.Static as S
import Network.Wai.Handler.Warp as W
import qualified Network.Wai.Handler.WarpTLS as W
import Simplex.Messaging.Encoding.String (strEncode)
import Simplex.Messaging.Server.Information
import Simplex.Messaging.Server.Main (EmbeddedWebParams (..), WebHttpsParams (..))
import Simplex.Messaging.Transport.Client (TransportHost (..))
import Simplex.Messaging.Util (tshow)
import Static.Embedded as E
import System.Directory (createDirectoryIfMissing)
import System.FilePath
import UnliftIO.Concurrent (forkFinally)
serveStaticFiles :: EmbeddedWebParams -> IO ()
serveStaticFiles EmbeddedWebParams {webStaticPath, webHttpPort, webHttpsParams} = do
forM_ webHttpPort $ \port -> flip forkFinally (\e -> logError $ "HTTP server crashed: " <> tshow e) $ do
logInfo $ "Serving static site on port " <> tshow port
W.runSettings (mkSettings port) (S.staticApp $ S.defaultFileServerSettings webStaticPath)
forM_ webHttpsParams $ \WebHttpsParams {port, cert, key} -> flip forkFinally (\e -> logError $ "HTTPS server crashed: " <> tshow e) $ do
logInfo $ "Serving static site on port " <> tshow port <> " (TLS)"
W.runTLS (W.tlsSettings cert key) (mkSettings port) (S.staticApp $ S.defaultFileServerSettings webStaticPath)
where
mkSettings port = setPort port defaultSettings
generateSite :: ServerInformation -> Maybe TransportHost -> FilePath -> IO ()
generateSite si onionHost sitePath = do
createDirectoryIfMissing True sitePath
B.writeFile (sitePath </> "index.html") $ serverInformation si onionHost
createDirectoryIfMissing True $ sitePath </> "media"
forM_ E.mediaContent $ \(path, bs) -> B.writeFile (sitePath </> "media" </> path) bs
createDirectoryIfMissing True $ sitePath </> "contact"
B.writeFile (sitePath </> "contact" </> "index.html") E.linkHtml
createDirectoryIfMissing True $ sitePath </> "invitation"
B.writeFile (sitePath </> "invitation" </> "index.html") E.linkHtml
logInfo $ "Generated static site contents at " <> tshow sitePath
serverInformation :: ServerInformation -> Maybe TransportHost -> ByteString
serverInformation ServerInformation {config, information} onionHost = render E.indexHtml substs
where
substs = substConfig <> maybe [] substInfo information <> [("onionHost", strEncode <$> onionHost)]
substConfig =
[ ( "persistence",
Just $ case persistence config of
SPMMemoryOnly -> "In-memory only"
SPMQueues -> "Queues"
SPMMessages -> "Queues and messages"
),
("messageExpiration", Just $ maybe "Never" (fromString . timedTTLText) $ messageExpiration config),
("statsEnabled", Just . yesNo $ statsEnabled config),
("newQueuesAllowed", Just . yesNo $ newQueuesAllowed config),
("basicAuthEnabled", Just . yesNo $ basicAuthEnabled config)
]
yesNo True = "Yes"
yesNo False = "No"
substInfo spi =
concat
[ basic,
maybe [("usageConditions", Nothing), ("usageAmendments", Nothing)] conds (usageConditions spi),
maybe [("operator", Nothing)] operatorE (operator spi),
maybe [("admin", Nothing)] admin (adminContacts spi),
maybe [("complaints", Nothing)] complaints (complaintsContacts spi),
maybe [("hosting", Nothing)] hostingE (hosting spi),
server
]
where
basic =
[ ("sourceCode", Just . encodeUtf8 $ sourceCode spi),
("website", encodeUtf8 <$> website spi)
]
conds ServerConditions {conditions, amendments} =
[ ("usageConditions", Just $ encodeUtf8 conditions),
("usageAmendments", encodeUtf8 <$> amendments)
]
operatorE Entity {name, country} =
[ ("operator", Just ""),
("operatorEntity", Just $ encodeUtf8 name),
("operatorCountry", encodeUtf8 <$> country)
]
admin ServerContactAddress {simplex, email, pgp} =
[ ("admin", Just ""),
("adminSimplex", strEncode <$> simplex),
("adminEmail", encodeUtf8 <$> email),
("adminPGP", encodeUtf8 . pkURI <$> pgp),
("adminPGPFingerprint", encodeUtf8 . pkFingerprint <$> pgp)
]
complaints ServerContactAddress {simplex, email, pgp} =
[ ("complaints", Just ""),
("complaintsSimplex", strEncode <$> simplex),
("complaintsEmail", encodeUtf8 <$> email),
("complaintsPGP", encodeUtf8 . pkURI <$> pgp),
("complaintsPGPFingerprint", encodeUtf8 . pkFingerprint <$> pgp)
]
hostingE Entity {name, country} =
[ ("hosting", Just ""),
("hostingEntity", Just $ encodeUtf8 name),
("hostingCountry", encodeUtf8 <$> country)
]
server =
[ ("serverCountry", fmap encodeUtf8 $ serverCountry =<< information)
]
-- Copy-pasted from simplex-chat Simplex.Chat.Types.Preferences
{-# INLINE timedTTLText #-}
timedTTLText :: (Integral i, Show i) => i -> String
timedTTLText 0 = "0 sec"
timedTTLText ttl = do
let (m', s) = ttl `quotRem` 60
(h', m) = m' `quotRem` 60
(d', h) = h' `quotRem` 24
(mm, d) = d' `quotRem` 30
unwords $
[mms mm | mm /= 0]
<> [ds d | d /= 0]
<> [hs h | h /= 0]
<> [ms m | m /= 0]
<> [ss s | s /= 0]
where
ss s = show s <> " sec"
ms m = show m <> " min"
hs 1 = "1 hour"
hs h = show h <> " hours"
ds 1 = "1 day"
ds 7 = "1 week"
ds 14 = "2 weeks"
ds d = show d <> " days"
mms 1 = "1 month"
mms mm = show mm <> " months"
-- | Rewrite source with provided substitutions
render :: ByteString -> [(ByteString, Maybe ByteString)] -> ByteString
render src = \case
[] -> src
(label, content') : rest -> render (section_ label content' src) rest
-- | Rewrite section content inside @<x-label>...</x-label>@ markers.
-- Markers are always removed when found. Closing marker is mandatory.
-- If content is absent, whole section is removed.
-- Section content is delegated to `item_`. If no sections found, the whole source is delegated.
section_ :: ByteString -> Maybe ByteString -> ByteString -> ByteString
section_ label content' src =
case B.breakSubstring startMarker src of
(_, "") -> item_ label (fromMaybe "" content') src -- no section, just replace items
(before, afterStart') ->
-- found section start, search for end too
case B.breakSubstring endMarker $ B.drop (B.length startMarker) afterStart' of
(_, "") -> error $ "missing section end: " <> show endMarker
(inside, next') ->
let next = B.drop (B.length endMarker) next'
in case content' of
Nothing -> before <> next -- collapse section
Just content -> before <> item_ label content inside <> section_ label content' next
where
startMarker = "<x-" <> label <> ">"
endMarker = "</x-" <> label <> ">"
-- | Replace all occurences of @${label}@ with provided content.
item_ :: ByteString -> ByteString -> ByteString -> ByteString
item_ label content' src =
case B.breakSubstring marker src of
(done, "") -> done
(before, after') -> before <> content' <> item_ label content' (B.drop (B.length marker) after')
where
marker = "${" <> label <> "}"
+15
View File
@@ -0,0 +1,15 @@
{-# LANGUAGE TemplateHaskell #-}
module Static.Embedded where
import Data.FileEmbed (embedDir, embedFile)
import Data.ByteString (ByteString)
indexHtml :: ByteString
indexHtml = $(embedFile "apps/smp-server/static/index.html")
linkHtml :: ByteString
linkHtml = $(embedFile "apps/smp-server/static/link.html")
mediaContent :: [(FilePath, ByteString)]
mediaContent = $(embedDir "apps/smp-server/static/media/")
+21
View File
@@ -0,0 +1,21 @@
module Main where
import Control.Logger.Simple
import Simplex.Messaging.Server.CLI (getEnvPath)
import Simplex.FileTransfer.Server.Main
defaultCfgPath :: FilePath
defaultCfgPath = "/etc/opt/simplex-xftp"
defaultLogPath :: FilePath
defaultLogPath = "/var/opt/simplex-xftp"
logCfg :: LogConfig
logCfg = LogConfig {lc_file = Nothing, lc_stderr = True}
main :: IO ()
main = do
setLogLevel LogDebug -- change to LogError in production
cfgPath <- getEnvPath "XFTP_SERVER_CFG_PATH" defaultCfgPath
logPath <- getEnvPath "XFTP_SERVER_LOG_PATH" defaultLogPath
withGlobalLogging logCfg $ xftpServerCLI cfgPath logPath
+6
View File
@@ -0,0 +1,6 @@
module Main where
import Simplex.FileTransfer.Client.Main
main :: IO ()
main = xftpClientCLI
+16 -3
View File
@@ -1,17 +1,30 @@
packages: .
-- packages: . ../direct-sqlcipher ../sqlcipher-simple
-- packages: . ../hs-socks
-- packages: . ../http2
-- packages: . ../network-transport
index-state: 2023-12-12T00:00:00Z
package cryptostore
flags: +use_crypton
source-repository-package
type: git
location: https://github.com/simplex-chat/aeson.git
tag: 3eb66f9a68f103b5f1489382aad89f5712a64db7
tag: aab7b5a14d6c5ea64c64dcaee418de1bb00dcc2b
source-repository-package
type: git
location: https://github.com/simplex-chat/hs-socks.git
tag: a30cc7a79a08d8108316094f8f2f82a0c5e1ac51
source-repository-package
type: git
location: https://github.com/simplex-chat/direct-sqlcipher.git
tag: 34309410eb2069b029b8fc1872deb1e0db123294
tag: f814ee68b16a9447fbb467ccc8f29bdd3546bfd9
source-repository-package
type: git
location: https://github.com/simplex-chat/sqlcipher-simple.git
tag: 5e154a2aeccc33ead6c243ec07195ab673137221
tag: a46bd361a19376c5211f1058908fc0ae6bf42446
+3
View File
@@ -0,0 +1,3 @@
# Streamlined NTRU Prime: sntrup761
The implementation of sntrup761 is the _exact_ copy from this [Internet draft](https://www.ietf.org/archive/id/draft-josefsson-ntruprime-streamlined-00.html).
+9
View File
@@ -0,0 +1,9 @@
#include <openssl/sha.h>
#include "sha512.h"
void crypto_hash_sha512 (unsigned char *out,
const unsigned char *in,
unsigned long long inlen)
{
SHA512(in, inlen, out);
}
+3
View File
@@ -0,0 +1,3 @@
void crypto_hash_sha512 (unsigned char *out,
const unsigned char *in,
unsigned long long inlen);
+1035
View File
File diff suppressed because it is too large Load Diff
+33
View File
@@ -0,0 +1,33 @@
/*
* Derived from public domain source, written by (in alphabetical order):
* - Daniel J. Bernstein
* - Chitchanok Chuengsatiansup
* - Tanja Lange
* - Christine van Vredendaal
*/
#ifndef SNTRUP761_H
#define SNTRUP761_H
#include <string.h>
#include <stdint.h>
#define SNTRUP761_SECRETKEY_SIZE 1763
#define SNTRUP761_PUBLICKEY_SIZE 1158
#define SNTRUP761_CIPHERTEXT_SIZE 1039
#define SNTRUP761_SIZE 32
typedef void sntrup761_random_func (void *ctx, size_t length, uint8_t *dst);
void
sntrup761_keypair (uint8_t *pk, uint8_t *sk,
void *random_ctx, sntrup761_random_func *random);
void
sntrup761_enc (uint8_t *c, uint8_t *k, const uint8_t *pk,
void *random_ctx, sntrup761_random_func *random);
void
sntrup761_dec (uint8_t *k, const uint8_t *c, const uint8_t *sk);
#endif /* SNTRUP761_H */
+30
View File
@@ -0,0 +1,30 @@
indentation: 2
column-limit: none
function-arrows: trailing
comma-style: trailing
import-export-style: trailing
indent-wheres: true
record-brace-space: true
newlines-between-decls: 1
haddock-style: single-line
haddock-style-module: null
let-style: inline
in-style: right-align
single-constraint-parens: never
unicode: never
respectful: true
fixities:
- infixr 9 .
- infixr 8 .:, .:., .=
- infixr 6 <>
- infixr 5 ++
- infixl 4 <$>, <$, $>, <$$>, <$?>
- infixl 4 <*>, <*, *>, <**>
- infix 4 ==, /=
- infixr 3 &&
- infixl 3 <|>
- infixr 2 ||
- infixl 1 >>, >>=
- infixr 1 =<<, >=>, <=<
- infixr 0 $, $!
reexports: []
-1
View File
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.1 KiB

Executable
+218
View File
@@ -0,0 +1,218 @@
#!/usr/bin/env sh
set -eu
# Links to scripts/configs
bin="https://github.com/simplex-chat/simplexmq/releases/latest/download"
remote_version="$(curl --proto '=https' --tlsv1.2 -sSf -L https://api.github.com/repos/simplex-chat/simplexmq/releases/latest | grep -i "tag_name" | awk -F \" '{print $4}')"
scripts="https://raw.githubusercontent.com/simplex-chat/simplexmq/stable/scripts/main"
scripts_systemd_smp="$scripts/smp-server.service"
scripts_systemd_xftp="$scripts/xftp-server.service"
scripts_update="$scripts/simplex-servers-update"
scripts_uninstall="$scripts/simplex-servers-uninstall"
scripts_stopscript="$scripts/simplex-servers-stopscript"
# Default installation paths
path_bin="/usr/local/bin"
path_bin_smp="$path_bin/smp-server"
path_bin_xftp="$path_bin/xftp-server"
path_bin_update="$path_bin/simplex-servers-update"
path_bin_uninstall="$path_bin/simplex-servers-uninstall"
path_bin_stopscript="$path_bin/simplex-servers-stopscript"
path_conf_etc="/etc/opt"
path_conf_var="/var/opt"
path_conf_smp="$path_conf_etc/simplex $path_conf_var/simplex"
path_conf_xftp="$path_conf_etc/simplex-xftp $path_conf_var/simplex-xftp /srv/xftp"
path_conf_info="$path_conf_etc/simplex-info"
path_systemd="/etc/systemd/system"
path_systemd_smp="$path_systemd/smp-server.service"
path_systemd_xftp="$path_systemd/xftp-server.service"
# Defaut users
user_smp="smp"
user_xftp="xftp"
GRN='\033[0;32m'
BLU='\033[1;34m'
YLW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
logo='
____ _ _ __ __
/ ___|(_)_ __ ___ _ __ | | ___\ \/ /
\___ \| | '"'"'_ ` _ \| '"'"'_ \| |/ _ \\ /
___) | | | | | | | |_) | | __// \
|____/|_|_| |_| |_| .__/|_|\___/_/\_\
|_|
'
welcome="Welcome to SMP/XFTP installation script! Here's what we're going to do:
${GRN}1.${NC} Install latest binaries from GitHub releases:
- smp: ${YLW}${path_bin_smp}${NC}
- xftp: ${YLW}${path_bin_xftp}${NC}
${GRN}2.${NC} Create server directories:
- smp: ${YLW}${path_conf_smp}${NC}
- xftp: ${YLW}${path_conf_xftp}${NC}
${GRN}3.${NC} Setup user for each server:
- xmp: ${YLW}${user_smp}${NC}
- xftp: ${YLW}${user_xftp}${NC}
${GRN}4.${NC} Create systemd services:
- smp: ${YLW}${path_systemd_smp}${NC}
- xftp: ${YLW}${path_systemd_xftp}${NC}
${GRN}5.${NC} Install stopscript (systemd), update and uninstallation script:
- all: ${YLW}${path_bin_update}${NC}, ${YLW}${path_bin_uninstall}${NC}, ${YLW}${path_bin_stopscript}${NC}
Press:
- ${GRN}ENTER${NC} to continue installing both xftp and smp servers
- ${GRN}1${NC} to install only smp server
- ${GRN}2${NC} to install only xftp server
- ${RED}Ctrl+C${NC} to cancel installation
Selection: "
end="Installtion is complete!
Please checkout our server guides:
- smp: ${GRN}https://simplex.chat/docs/server.html${NC}
- xftp: ${GRN}https://simplex.chat/docs/xftp-server.html${NC}
To uninstall with full clean-up, simply run: ${YLW}sudo /usr/local/bin/simplex-servers-uninstall${NC}
"
os_test() {
. /etc/os-release
case "$VERSION_ID" in
20.04|22.04) : ;;
24.04) VERSION_ID='22.04' ;;
*) printf "${RED}Unsupported Ubuntu version!${NC}\nPlease file Github issue with request to support Ubuntu %s: https://github.com/simplex-chat/simplexmq/issues/new\n" "$VERSION_ID" && exit 1 ;;
esac
version="$(printf '%s' "$VERSION_ID" | tr '.' '_')"
arch="$(uname -p)"
case "$arch" in
x86_64) arch="$(printf '%s' "$arch" | tr '_' '-')" ;;
*) printf "${RED}Unsupported architecture!${NC}\nPlease file Github issue with request to support %s architecture: https://github.com/simplex-chat/simplexmq/issues/new" "$arch" && exit 1 ;;
esac
bin_smp="$bin/smp-server-ubuntu-${version}-${arch}"
bin_xftp="$bin/xftp-server-ubuntu-${version}-${arch}"
}
setup_bins() {
eval "bin=\$bin_${1}"
eval "path=\$path_bin_${1}"
curl --proto '=https' --tlsv1.2 -sSf -L "$bin" -o "$path" && chmod +x "$path"
unset bin path
}
setup_users() {
eval "user=\$user_${1}"
useradd -M "$user" 2> /dev/null || true
unset user
}
setup_dirs() {
# Unquoted varibles, so field splitting can occur
eval "path_conf=\$path_conf_${1}"
eval "user=\$user_${1}"
mkdir -p $path_conf
mkdir -p $path_conf_info
printf "local_version_%s='%s'\n" "$1" "$remote_version" >> "$path_conf_info/release"
chown -R "$user":"$user" $path_conf
unset path_conf user
}
setup_systemd() {
eval "scripts_systemd=\$scripts_systemd_${1}"
eval "path_systemd=\$path_systemd_${1}"
curl --proto '=https' --tlsv1.2 -sSf -L "$scripts_systemd" -o "$path_systemd"
unset scripts_systemd path_systemd
}
setup_scripts() {
curl --proto '=https' --tlsv1.2 -sSf -L "$scripts_update" -o "$path_bin_update" && chmod +x "$path_bin_update"
curl --proto '=https' --tlsv1.2 -sSf -L "$scripts_uninstall" -o "$path_bin_uninstall" && chmod +x "$path_bin_uninstall"
curl --proto '=https' --tlsv1.2 -sSf -L "$scripts_stopscript" -o "$path_bin_stopscript" && chmod +x "$path_bin_stopscript"
}
checks() {
if [ "$(id -u)" -ne 0 ]; then
printf "This script is intended to be run with root privileges. Please re-run script using sudo."
exit 1
fi
os_test
mkdir -p $path_conf_info
}
main() {
checks
printf "%b\n%b" "${BLU}$logo${NC}" "$welcome"
read ans
if [ "$ans" = '1' ]; then
setup='smp'
elif [ "$ans" = '2' ]; then
setup='xftp'
else
setup='smp xftp'
fi
printf "Installing binaries..."
for i in $setup; do
setup_bins "$i"
done
printf "${GRN} Done!${NC}\n"
printf "Creating users..."
for i in $setup; do
setup_users "$i"
done
printf "${GRN} Done!${NC}\n"
printf "Creating directories..."
for i in $setup; do
setup_dirs "$i"
done
printf "${GRN} Done!${NC}\n"
printf "Creating systemd services..."
for i in $setup; do
setup_systemd "$i"
done
printf "${GRN} Done!${NC}\n"
printf "Installing stopscript, update and uninstallation script..."
setup_scripts
printf "${GRN} Done!${NC}\n"
printf "%b" "$end"
}
main
+23
View File
@@ -0,0 +1,23 @@
common:
corrId - random BS, used as CbNonce
entityId - p2r tlsUniq
# setup
s->p: "proxy", uri, auth?
# unless connected
p->r: "p_handshake"
p<-r: "r_key", tls-signed dh pub
s<-r: "r_key", tls-signed dh pub # reply entityId contains tlsUniq
# working
s ; generate random dh priv, make shared secret
s->p: s2r("forward", random dh pub, SEND command blob)
p->r: p2r("forward", random dh pub, s2r("forward", ...)))
r->c@ "msg", ...
p<-r: p2r("r_res", s2r("ok" / "error", error))
s<-p@ s2r("ok" / "error", error)
# expired
p<-r@ p2r("error", "key expired")
s<-p@ "error", "key expired"
s ; reconnect
+106 -28
View File
@@ -1,5 +1,5 @@
name: simplexmq
version: 3.4.0
version: 6.0.4.0
synopsis: SimpleXMQ message broker
description: |
This package includes <./docs/Simplex-Messaging-Server.html server>,
@@ -20,9 +20,13 @@ category: Chat, Network, Web, System, Cryptography
extra-source-files:
- README.md
- CHANGELOG.md
- cbits/sha512.h
- cbits/sntrup761.h
- apps/smp-server/static/*.html
- apps/smp-server/static/media/*
dependencies:
- aeson == 2.0.*
- aeson == 2.2.*
- ansi-terminal >= 0.10 && < 0.12
- asn1-encoding == 0.9.*
- asn1-types == 0.3.*
@@ -30,70 +34,101 @@ dependencies:
- attoparsec == 0.14.*
- base >= 4.14 && < 5
- base64-bytestring >= 1.0 && < 1.3
- bytestring == 0.10.*
- case-insensitive == 1.2.*
- composition == 1.0.*
- constraints >= 0.12 && < 0.14
- containers == 0.6.*
- cryptonite >= 0.27 && < 0.30
- cryptostore == 0.2.*
- crypton == 0.34.*
- crypton-x509 == 1.7.*
- crypton-x509-store == 1.6.*
- crypton-x509-validation == 1.6.*
- cryptostore == 0.3.*
- data-default == 0.7.*
- direct-sqlcipher == 2.3.*
- directory == 1.3.*
- filepath == 1.4.*
- hashable == 1.4.*
- hourglass == 0.2.*
- http-types == 0.12.*
- http2 == 3.0.*
- generic-random >= 1.3 && < 1.5
- http2 >= 4.2.2 && < 4.3
- ini == 0.4.1
- iproute == 1.7.*
- iso8601-time == 0.1.*
- memory == 0.15.*
- mtl == 2.2.*
- memory == 0.18.*
- mtl >= 2.3.1 && < 3.0
- network >= 3.1.2.7 && < 3.2
- network-transport == 0.5.4
- network-info >= 0.2 && < 0.3
- network-transport == 0.5.6
- network-udp >= 0.0 && < 0.1
- optparse-applicative >= 0.15 && < 0.17
- QuickCheck == 2.14.*
- process == 1.6.*
- random >= 1.1 && < 1.3
- simple-logger == 0.1.*
- socks == 0.6.*
- sqlcipher-simple == 0.4.*
- stm == 2.5.*
- template-haskell == 2.16.*
- text == 1.2.*
- time == 1.9.*
- time-compat == 1.9.*
- temporary == 1.3.*
- time == 1.12.*
- time-manager == 0.0.*
- tls >= 1.6.0 && < 1.7
- transformers == 0.5.*
- tls >= 1.9.0 && < 1.10
- transformers == 0.6.*
- unliftio == 0.2.*
- unliftio-core == 0.2.*
- websockets == 0.12.*
- x509 == 1.7.*
- x509-store == 1.6.*
- x509-validation == 1.6.*
- yaml == 0.11.*
- zstd == 0.1.3.*
flags:
swift:
description: Enable swift JSON format
manual: True
default: False
use_crypton:
description: Use crypton etc. in cryptostore
manual: True
default: True
# cpp-options:
# - -Dslow_servers
when:
- condition: flag(swift)
cpp-options:
- -DswiftJSON
- condition: impl(ghc >= 9.6.2)
dependencies:
- bytestring == 0.11.*
- template-haskell == 2.20.*
- text >= 2.0.1 && < 2.2
- condition: impl(ghc < 9.6.2)
dependencies:
- bytestring == 0.10.*
- template-haskell == 2.16.*
- text >= 1.2.3.0 && < 1.3
library:
source-dirs: src
c-sources:
- cbits/sha512.c
- cbits/sntrup761.c
include-dirs: cbits
extra-libraries: crypto
executables:
smp-server:
source-dirs: apps/smp-server
source-dirs:
- apps/smp-server
- apps/smp-server/web
main: Main.hs
dependencies:
- file-embed
- simplexmq
- wai-app-static
- warp
- warp-tls
ghc-options:
- -threaded
- -rtsopts
ntf-server:
source-dirs: apps/ntf-server
@@ -102,33 +137,76 @@ executables:
- simplexmq
ghc-options:
- -threaded
- -rtsopts
smp-agent:
source-dirs: apps/smp-agent
xftp-server:
source-dirs: apps/xftp-server
main: Main.hs
dependencies:
- simplexmq
ghc-options:
- -threaded
- -rtsopts
xftp:
source-dirs: apps/xftp
main: Main.hs
dependencies:
- simplexmq
ghc-options:
- -threaded
- -rtsopts
tests:
smp-server-test:
simplexmq-test:
source-dirs: tests
main: Test.hs
dependencies:
- simplexmq
- hspec == 2.7.*
- hspec-core == 2.7.*
- deepseq == 1.4.*
- generic-random == 1.5.*
- hspec == 2.11.*
- hspec-core == 2.11.*
- HUnit == 1.6.*
- QuickCheck == 2.14.*
- silently == 1.2.*
- main-tester == 0.2.*
- timeit == 2.0.*
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-A64M
- -with-rtsopts=-N1
ghc-options:
# - -haddock
- -Wall
- -Weverything
- -Wno-missing-exported-signatures
- -Wno-missing-import-lists
- -Wno-missed-specialisations
- -Wno-all-missed-specialisations
- -Wno-unsafe
- -Wno-safe
- -Wno-missing-local-signatures
- -Wno-missing-kind-signatures
- -Wno-missing-deriving-strategies
- -Wno-monomorphism-restriction
- -Wno-prepositive-qualified-module
- -Wno-unused-packages
- -Wno-implicit-prelude
- -Wno-missing-safe-haskell-mode
- -Wno-missing-export-lists
- -Wno-partial-fields
- -Wcompat
- -Werror=incomplete-record-updates
- -Werror=incomplete-patterns
- -Werror=incomplete-uni-patterns
- -Werror=missing-methods
- -Werror=tabs
- -Wredundant-constraints
- -Wincomplete-record-updates
- -Wincomplete-uni-patterns
- -Wunused-type-patterns
- -O2
default-extensions:
- StrictData
+341 -284
View File
@@ -1,3 +1,5 @@
Version 5, 2024-06-22
# SMP agent protocol - duplex communication over SMP protocol
## Table of contents
@@ -5,69 +7,61 @@
- [Abstract](#abstract)
- [SMP agent](#smp-agent)
- [SMP servers management](#smp-servers-management)
- [SMP agent protocol components](#smp-agent-protocol-components)
- [SMP agent protocol scope](#smp-agent-protocol-scope)
- [Duplex connection procedure](#duplex-connection-procedure)
- [Contact addresses](#contact-addresses)
- [Communication between SMP agents](#communication-between-smp-agents)
- [Message syntax](#messages-between-smp-agents)
- [HELLO message](#hello-message)
- [REPLY message](#reply-message)
- [MSG message](#msg-message)
- [INV message](#inv-message)
- [ACK message](#ack-message)
- [NEW message](#new-message)
- [DEL message](#del-message)
- [SMP agent commands](#smp-agent-commands)
- [Client commands and server responses](#client-commands-and-server-responses)
- [NEW command and INV response](#new-command-and-inv-response)
- [JOIN command](#join-command)
- [CONF notification and LET command](#conf-notification-and-let-command)
- [REQ notification and ACPT command](#req-notification-and-acpt-command)
- [INFO and CON notifications](#info-and-con-notifications)
- [SUB command](#sub-command)
- [SEND command and MID, SENT and MERR responses](#send-command-and-mid-sent-and-merr-responses)
- [MSG notification](#msg-notification)
- [END notification](#end-notification)
- [OFF command](#off-command)
- [DEL command](#del-command)
- [Connection request](#connection-request)
- [A_MSG message](#a_msg-message)
- [A_RCVD message](#a_rcvd-message)
- [EREADY message](#eready-message)
- [A_QCONT message](#a_qcont-message)
- [Rotating messaging queue](#rotating-messaging-queue)
- [End-to-end encryption](#end-to-end-encryption)
- [Connection link: 1-time invitation and contact address](#connection-link-1-time-invitation-and-contact-address)
- [Appendix A: SMP agent API](#smp-agent-api)
- [API functions](#api-functions)
- [API events](#api-events)
## Abstract
The purpose of SMP agent protocol is to define the syntax and the semantics of communications between the client and the agent that connects to [SMP](./simplex-messaging.md) servers.
It provides:
- protocol to create and manage bi-directional (duplex) connections between the users of SMP agents consisting of two (or more) separate unidirectional (simplex) SMP queues, abstracting away multiple steps required to establish bi-directional connections and any information about the servers location from the users of the agent protocol.
- API to create and manage bi-directional (duplex) connections between the users of SMP agents consisting of two (or more) separate unidirectional (simplex) SMP queues, abstracting away multiple steps required to establish bi-directional connections and any information about the servers location from the users of the agent protocol.
- management of E2E encryption between SMP agents, generating ephemeral asymmetric keys for each connection.
- SMP command authentication on SMP servers, generating ephemeral keys for each SMP queue.
- TCP/TLS transport handshake with SMP servers.
- validation of message integrity.
SMP agent protocol provides no encryption or security on the client side - it is assumed that the agent is executed in the trusted and secure environment, in one of three ways:
- via TCP network using secure connection.
- via local port (when the agent runs on the same device as a separate process).
- via agent library, when the agent logic is included directly into the client application - [SimpleX Chat for terminal](https://github.com/simplex-chat/simplex-chat) uses this approach.
SMP agent API provides no security between the agent and the client - it is assumed that the agent is executed in the trusted and secure environment, via the agent library, when the agent logic is included directly into the client application - [SimpleX Chat for terminal](https://github.com/simplex-chat/simplex-chat) uses this approach.
## SMP agent
SMP agents communicate with each other via SMP servers using [simplex messaging protocol (SMP)](./simplex-messaging.md) according to the commands received from its users. This protocol is a middle layer in SimpleX protocols (above SMP protocol but below any application level protocol) - it is intended to be used by client-side applications that need secure asynchronous bi-directional communication channels ("connections").
SMP agents communicate with each other via SMP servers using [simplex messaging protocol (SMP)](./simplex-messaging.md) according to the API calls used by the client applications. This protocol is a middle layer in SimpleX protocols (above SMP protocol but below any application level protocol) - it is intended to be used by client-side applications that need secure asynchronous bi-directional communication channels ("connections").
The agent must have a persistent storage to manage the states of known connections and of the client-side information of SMP queues that each connection consists of, and also the buffer of the most recent sent and received messages. The number of the messages that should be stored is implementation specific, depending on the error management approach that the agent implements; at the very least the agent must store the hashes and IDs of the last received and sent messages.
## SMP servers management
SMP agent protocol commands do not contain the addresses of the SMP servers that the agent will use to create and use the connections (excluding the server address in queue URIs used in JOIN command). The list of the servers is a part of the agent configuration and can be dynamically changed by the agent implementation:
SMP agent API does not use the addresses of the SMP servers that the agent will use to create and use the connections (excluding the server address in queue URIs used in JOIN command). The list of the servers is a part of the agent configuration and can be dynamically changed by the agent implementation:
- by the client applications via any API that is outside of scope of this protocol.
- by the agents themselves based on availability and latency of the configured servers.
## SMP agent protocol components
## SMP agent protocol scope
SMP agent protocol has 3 main parts:
SMP agent protocol has 2 main parts:
- the syntax and semantics of the messages that SMP agents exchange with each other in order to:
- the messages that SMP agents exchange with each other in order to:
- negotiate establishing unidirectional (simplex) encrypted queues on SMP servers.
- exchange client messages and delivery notifications, providing sequential message IDs and message integrity (by including the hash of the previous message).
- the syntax and semantics of the commands that are sent by the agent clients to the agents. This protocol allows to create and manage multiple connections, each consisting of two or more SMP queues.
- the syntax and semantics of the message that the clients of SMP agents should send out-of-band (as pre-shared "invitation" including queue URIs) to protect [E2E encryption][1] from active attacks ([MITM attacks][2]).
- re-negotiate messaging queues to use and connection e2e encryption.
- the messages that the clients of SMP agents should send out-of-band (as pre-shared "invitation" including queue URIs) to protect [E2E encryption][1] from active attacks ([MITM attacks][2]).
[Appendix A](#appendix-a-smp-agent-api) of this document describes:
- the functional API used by the client application with the agent. This API allows to create and manage multiple connections, each consisting of two or more SMP queues.
- events that the agent passes to the clients.
## Duplex connection procedure
@@ -75,54 +69,126 @@ SMP agent protocol has 3 main parts:
The procedure of establishing a duplex connection is explained on the example of Alice and Bob creating a bi-directional connection consisting of two unidirectional (simplex) queues, using SMP agents (A and B) to facilitate it, and two different SMP servers (which could be the same server). It is shown on the diagram above and has these steps:
1. Alice requests the new connection from the SMP agent A using SMP NEW command.
2. Agent A creates an SMP connection on the server (using [SMP protocol](./simplex-messaging.md)) and responds to Alice with the invitation that contains queue information and the encryption key Bob's agent B should use. The invitation format is described in [Connection request](#connection-request).
3. Alice sends the [connection request](#connection-request) to Bob via any secure channel (out-of-band message).
4. Bob sends `JOIN` command with the connection request as a parameter to agent B to accept the connection.
5. Establishing Alice's SMP queue (with SMP protocol commands):
- Agent B sends an "SMP confirmation" with SMP SEND command to the SMP queue specified in the connection request - SMP confirmation is an unauthenticated message with an ephemeral key that will be used to authenticate Bob's commands to the queue, as described in SMP protocol, and Bob's info (profile, public key for E2E encryption, etc.). This message is encrypted using key passed in the connection request (or with the derived key, in which case public key for key derivation should be sent in clear text).
- Agent A receives the SMP confirmation containing Bob's key and info as SMP MSG.
- Agent A notifies Alice sending REQ notification with Bob's info.
- Alice accepts connection request with ACPT command.
- Agent A secures the queue with SMP KEY command.
- Agent B tries sending authenticated SMP SEND command with agent `HELLO` message until it succeeds. Once it succeeds, Bob's agent "knows" the queue is secured.
6. Agent B creates a new SMP queue on the server.
7. Establish Bob's SMP queue:
- Agent B sends `REPLY` message (SMP SEND command) with the connection request to this 2nd queue to Alice's agent (via the 1st queue) - this connection request SHOULD use "simplex" URI scheme.
- Agent A, having received `REPLY` message, sends unauthenticated message (SMP SEND) to SMP queue with Alice agent's ephemeral key that will be used to authenticate Alice's commands to the queue, as described in SMP protocol, and Alice's info.
- Bob's agent receives the key and Alice's information and secures the queue (SMP KEY).
- Bob's agent sends the notification `INFO` with Alice's information to Bob.
- Alice's agent keeps sending `HELLO` message until it succeeds.
8. Agents A and B notify Alice and Bob that connection is established.
- Once sending `HELLO` succeeds, Alice's agent sends to Alice `CON` notification that confirms that now both parties can communicate.
- Once Bob's agent receives `HELLO` from Alice's agent, it sends to Bob `CON` notification as well.
1. Alice requests the new connection from the SMP agent A using agent `createConnection` api function.
2. Agent A creates an SMP queue on the server (using [SMP protocol](./simplex-messaging.md) `NEW` command) and responds to Alice with the invitation that contains queue information and the encryption keys Bob's agent B should use. The invitation format is described in [Connection link](connection-link-1-time-invitation-and-contact-address).
3. Alice sends the [connection link](#connection-link-1-time-invitation-and-contact-address) to Bob via any secure channel (out-of-band message) - as a link or as a QR code.
4. Bob uses agent `joinConnection` api function with the connection link as a parameter to agent B to accept the connection.
5. Agent B creates Bob's SMP reply queue with SMP server `NEW` command.
6. Agent B confirms the connection: sends an "SMP confirmation" with SMP server `SEND` command to the SMP queue specified in the connection link - SMP confirmation is an unauthenticated message with an ephemeral key that will be used to authenticate Bob's commands to the queue, as described in SMP protocol, and Bob's info (profile, public key for E2E encryption, and the connection link to this 2nd queue to Agent A - this connection link SHOULD use "simplex" URI scheme). This message is encrypted using key passed in the connection link (or with the derived shared secret, in which case public key for key derivation should be sent in clear text).
6. Alice confirms and continues the connection:
- Agent A receives the SMP confirmation containing Bob's key, reply queue and info as SMP server `MSG`.
- Agent A notifies Alice sending `CONF` notification with Bob's info.
- Alice allows connection to continue with agent `allowConnection` api function.
- Agent A secures the queue with SMP server `KEY` command.
- Agent A sends SMP confirmation with ephemeral sender key, ephemeral public encryption key and profile (but without reply queue).
7. Agent B confirms the connection:
- receives the confirmation.
- sends the notification `INFO` with Alice's information to Bob.
- secures SMP queue that it sent to Alice in the first confirmation with SMP `KEY` command .
- sends `HELLO` message via SMP `SEND` command. This confirms that the reply queue is secured and also validates that Agent A secured the first SMP queue
8. Agent A notifies Alice.
- receives `HELLO` message from Agent B.
- sends `HELLO` message to Agent B via SMP `SEND` command.
- sends `CON` notification to Alice, confirming that the connection is established.
9. Agent B notifies Bob.
- Once Agent B receives `HELLO` from Agent A, it sends to Bob `CON` notification as well.
At this point the duplex connection between Alice and Bob is established, they can use `SEND` command to send messages. The diagram also shows how the connection status changes for both parties, where the first part is the status of the SMP queue to receive messages, and the second part - the status of the queue to send messages.
The most communication happens between the agents and servers, from the point of view of Alice and Bob there are 4 steps (not including notifications):
1. Alice requests a new connection with `NEW` command and receives the invitation.
2. Alice passes connection request out-of-band to Bob.
3. Bob accepts the connection with `JOIN` command with the connection request to his agent.
4. Alice accepts the connection with `ACPT` command.
1. Alice requests a new connection with `createConnection` agent API function and receives the connection link.
2. Alice passes connection link out-of-band to Bob.
3. Bob accepts the connection with `joinConnection` agent API function with the connection link to his agent.
4. Alice accepts the connection with `ACPT` agent API function.
5. Both parties receive `CON` notification once duplex connection is established.
Clients SHOULD support establishing duplex connection asynchronously (when parties are intermittently offline) by persisting intermediate states and resuming SMP queue subscriptions.
## Fast duplex connection procedure
Previously described duplex connection procedure requires sending 4 messages creating a bad UX for the users - it requires waiting until each party in online before the messages can be sent.
It allows users validating connecting party profile before proceeding with the connection, but it turned out to be unnecessary UX step and is not used in the client applications.
It also protects against an attacker who compromised TLS and uses the sender queue ID sent to the recipient to secure the queue before the sender can. This attack is very hard, and this accepting its risk is better than worse UX. Future protocol versions could mitigate this attack by encrypting entity IDs.
Faster duplex connection process is possible with the `SKEY` command added in v9 of SMP protocol.
![Fast duplex connection procedure](./diagrams/duplex-messaging/duplex-creating-fast.svg)
1. Alice requests the new connection from the SMP agent A using agent `createConnection` api function
2. Agent A creates an SMP queue on the server (using [SMP protocol](./simplex-messaging.md) `NEW` command with the flag allowing the sender to secure the queue) and responds to Alice with the invitation that contains queue information and the encryption keys Bob's agent B should use. The invitation format is described in [Connection link](connection-link-1-time-invitation-and-contact-address).
3. Alice sends the [connection link](connection-link-1-time-invitation-and-contact-address) to Bob via any secure channel (out-of-band message) - as a link or as a QR code. This link contains the flag that the queue can be secured by the sender.
4. Bob uses agent `joinConnection` api function with the connection link as a parameter to agent B to accept the connection.
5. Agent B secures Alice's queue with SMP command `SKEY` - this command can be proxied.
6. Agent B creates Bob's SMP reply queue with SMP server `NEW` command (with the flag allowing the sender to secure the queue).
7. Agent B confirms the connection: sends an "SMP confirmation" with SMP server `SEND` command to the SMP queue specified in the connection link - SMP confirmation is an unauthenticated message with an ephemeral key that will be used to authenticate Bob's commands to the queue, as described in SMP protocol, and Bob's info (profile, public key for E2E encryption, and the connection link to this 2nd queue to Agent A - this connection link SHOULD use "simplex" URI scheme). This message is encrypted using key passed in the connection link (or with the derived shared secret, in which case public key for key derivation should be sent in clear text).
8. Alice confirms the connection:
- Agent A receives the SMP confirmation containing Bob's key, reply queue and info as SMP server `MSG`.
- Agent A notifies Alice sending `CONF` notification with Bob's info (that indicates that Agent B already secured the queue).
- Alice allows connection to continue with agent `allowConnection` api function.
- Agent A secures Bob's queue with SMP command `SKEY`.
- Agent A sends SMP confirmation with ephemeral public encryption key and profile (but without reply queue, and without sender key).
9. Agent A notifies Alice with `CON` notification.
10. Agent B notifies Bob about connection success:
- receives confirmation message from Alice.
- sends the notification `INFO` with Alice's information to Bob.
- sends `CON` notification to Bob.
## Contact addresses
SMP agents support creating a special type of connection - a contact address - that allows to connect to multiple network users who can send connection requests by sending 1-time connection links to the message queue.
This connection address uses a messaging queue on SMP server to receive invitations to connect - see `agentInvitation` message below. Once connection request is accepted, a new connection is created and the address itself is no longer used to send the messages - deleting this address does not disrupt the connections that were created via it.
## Communication between SMP agents
To establish duplex connections and to send messages on behalf of their clients, SMP agents communicate via SMP servers.
Agents use SMP message client body (the part of the SMP message after header - see [SMP protocol](./simplex-messaging.md)) to transmit agent client messages and exchange messages between each other.
Each SMP message client body, once decrypted, contains 3 parts (one of them may include binary message body), as defined by `decryptedSmpMessageBody` syntax:
These messages are encrypted with per-queue shared secret using NaCL crypto_box and can be of 4 types, as defined by `decryptedSMPClientMessage`:
- `agentConfirmation` - used when confirming SMP queues, contains connection information encrypted with double ratchet. This envelope can only contain `agentConnInfo` or `agentConnInfoReply` encrypted with double ratchet.
- `agentMsgEnvelope` - contains different agent messages encrypted with double ratchet, as defined in `agentMessage`.
- `agentInvitation` - sent to SMP queue that is used as contact address, does not use double ratchet.
- `agentRatchetKey` - used to re-negotiate double ratchet encryption - can contain additional information in `agentRatchetKey`.
```abnf
decryptedSMPClientMessage = agentConfirmation / agentMsgEnvelope / agentInvitation / agentRatchetKey
agentConfirmation = agentVersion %s"C" ("0" / "1" sndE2EEncryptionParams) encConnInfo
agentVersion = 2*2 OCTET
sndE2EEncryptionParams = TODO
encConnInfo = doubleRatchetEncryptedMessage
agentMsgEnvelope = agentVersion %s"M" encAgentMessage
encAgentMessage = doubleRatchetEncryptedMessage
agentInvitation = agentVersion %s"I" connReqLength connReq connInfo
connReqLength = 2*2 OCTET ; Word16
agentRatchetKey = agentVersion %s"R" rcvE2EEncryptionParams agentRatchetInfo
rcvE2EEncryptionParams = TODO
doubleRatchetEncryptedMessage = TODO
```
This syntax of decrypted SMP client message body is defined by `decryptedAgentMessage` below.
Decrypted SMP message client body can be one of 4 types:
- `agentConnInfo` - used by the initiating party when confirming reply queue - sent in `agentConfirmation` envelope.
- `agentConnInfoReply` - used by accepting party, includes reply queue(s) in the initial confirmation - sent in `agentConfirmation` envelope.
- `agentRatchetInfo` - used to pass additional information when renegotiating double ratchet encryption - sent in `agentRatchetKey` envelope.
- `agentMessage` - all other agent messages.
`agentMessage` contains these parts:
- `agentMsgHeader` - agent message header that contains sequential agent message ID for a particular SMP queue, agent timestamp (ISO8601) and the hash of the previous message.
- `agentMessage` - a command/message to the other SMP agent:
- to establish the connection with two SMP queues (`helloMsg`, `replyQueueMsg`)
- to send and to acknowledge user messages (`clientMsg`, `acknowledgeMsg`)
- to manage SMP queue rotation (`newQueueMessage`, `deleteQueueMsg`)
- to manage encryption key rotation (TODO)
- `aMessage` - a command/message to the other SMP agent:
- to confirm the connection (`HELLO`).
- to send and to confirm reception of user messages (`A_MSG`, `A_RCVD`).
- to confirm that the new double ratchet encryption is agreed (`EREADY`).
- to notify another party that it can continue sending messages after queue capacity was exceeded (`A_QCONT`).
- to manage SMP queue rotation (`QADD`, `QKEY`, `QUSE`, `QTEST`).
- `msgPadding` - an optional message padding to make all SMP messages have constant size, to prevent servers from observing the actual message size. The only case the message padding can be absent is when the message has exactly the maximum size, in all other cases the message MUST be padded to a fixed size.
### Messages between SMP agents
@@ -130,269 +196,160 @@ Each SMP message client body, once decrypted, contains 3 parts (one of them may
Message syntax below uses [ABNF][3] with [case-sensitive strings extension][4].
```abnf
decryptedSmpMessageBody = agentMsgHeader CRLF agentMessage CRLF msgPadding
agentMsgHeader = agentMsgId SP previousMsgHash ; here `agentMsgId` is sequential ID set by the sending agent
agentMsgId = 1*DIGIT
previousMsgHash = encoded
encoded = <base64 encoded>
decryptedAgentMessage = agentConnInfo / agentConnInfoReply / agentRatchetInfo / agentMessage
agentConnInfo = %s"I" connInfo
connInfo = *OCTET
agentConnInfoReply = %s"D" smpQueues connInfo
agentRatchetInfo = %s"R" ratchetInfo
agentMessage = helloMsg / replyQueueMsg /
clientMsg / invitationMsg /
newQueueMessage / deleteQueueMsg
agentMessage = %s"M" agentMsgHeader aMessage msgPadding
agentMsgHeader = agentMsgId prevMsgHash
agentMsgId = 8*8 OCTET ; Int64
prevMsgHash = shortString
msgPadding = *OCTET ; optional random bytes to get messages to the same size (as defined in SMP message size)
aMessage = HELLO / A_MSG / A_RCVD / EREADY / A_QCONT /
QADD / QKEY / QUSE / QTEST
helloMsg = %s"H"
HELLO = %s"H"
replyQueueMsg = %s"R" connectionRequest ; `connectionRequest` is defined below
; this message can only be sent by the second connection party
A_MSG = %s"M" userMsgBody
userMsgBody = *OCTET
clientMsg = %s"M" clientMsgBody
clientMsgBody = *OCTET
A_RCVD = %s"V" msgReceipt
msgReceipt = agentMsgId msgHash rcptLength rcptInfo
; TODO remove and move to "public" header
invitationMsg = %s"INV" SP connReqInvitation SP connInfo
; `connReqInvitation` and `connInfo` are defined below
EREADY = %s"E" agentMsgId
newQueueMsg = %s"N" queueURI
; this message can be sent by any party to add SMP queue to the connection.
; NOT SUPPORTED in the current implementation
A_QCONT = %s"QC" sndQueueAddr
deleteQueueMsg = %s"D" queueURI
; notification that the queue with passed URI will be deleted
; no need to notify the other party about suspending queue separately, as suspended and deleted queues are indistinguishable to the sender
; NOT SUPPORTED in the current implementation
QADD = %s"QA" sndQueues
sndQueues = length 1*(newQueueUri replacedSndQueue)
newQueueUri = clientVRange smpServer senderId dhPublicKey [sndSecure]
dhPublicKey = length x509encoded
sndSecure = "T"
replacedSndQueue = "0" / "1" sndQueueAddr
QKEY = %s"QK" sndQueueKeys
sndQueueKeys = length 1*(newQueueInfo senderKey)
newQueueInfo = version smpServer senderId dhPublicKey [sndSecure]
senderKey = length x509encoded
QUSE = %s"QU" sndQueuesReady
sndQueuesReady = length 1*(sndQueueAddr primary)
primary = %s"T" / %s"F"
QTEST = %s"QT" sndQueueAddrs
sndQueueAddrs = length 1*sndQueueAddr
sndQueueAddr = smpServer senderId
smpServer = hosts port keyHash
hosts = length 1*host
host = shortString
port = shortString
keyHash = shortString
senderId = shortString
clientVRange = version version
version = 2*2 OCTET
msgPadding = *OCTET
rcptLength = 2*2 OCTET
shortString = length *OCTET
length = 1*1 OCTET
```
#### HELLO message
This is the first message that both agents send after the respective SMP queue is secured by the receiving agent (see diagram). It MAY contain the public key that the recipient would use to verify messages signed by the sender.
This is the first message that both agents send after the respective SMP queue is secured by the receiving agent (see diagram).
Sending agent might need to retry sending HELLO message, as it would not have any other confirmation that the queue is secured other than the success of sending this message with the signed SMP SEND command.
This message is not used with [fast duplex connection](#fast-duplex-connection-procedure).
#### REPLY message
#### A_MSG message
This is the message that is sent by the agent that received an out-of-band connection request to pass the connection request for the reply SMP queues to the agent that originated the connection (see diagram).
This is the agent envelope used to send client messages once the connection is established. This is different from the MSG sent by SMP server to the agent and MSG event from SMP agent to the client that are sent in different contexts.
#### MSG message
#### A_RCVD message
This is the agent envelope used to send client messages once the connection is established. Do not confuse it with the MSG response from SMP server to the agent and MSG response from SMP agent to the client that are sent in different contexts.
This message is sent to confirm the client message reception. It includes received message number and message hash.
#### INV message
#### EREADY message
This message is sent to the SMP queue(s) in `connReqContact`, to establish a new connection via existing unsecured queue, that acts as a permanent connection link of a user.
This message is sent after re-negotiating a new double ratchet encryption with `agentRatchetKey`.
#### ACK message
#### A_QCONT message
This message is sent to confirm the client message reception. It includes received message number, message hash and the reception status.
This message is sent to notify the sender client that it can continue sending the messages after queue capacity was exhausted.
#### NEW message
### Rotating messaging queue
This message is sent to add an additional SMP queue to the connection. Unlike REPLY message it can be sent at any time.
SMP agents SHOULD support 4 messages to rotate message reception to another messaging server:
`QADD`: add the new queue address(es) to the connection - sent by the client that initiates rotation.
`QKEY`: pass sender's key via existing connection (SMP confirmation message will not be used, to avoid the same "race" of the initial key exchange that would create the risk of intercepting the queue for the attacker) - sent by the client accepting the rotation
`QUSE`: instruct the sender to use the new queue with sender's queue ID as parameter. From this point some messages can be sent to both the new queue and the old queue.
`QTEST`: send test message to the new connection. Any other message can be sent if available to continue rotation, the absence of this message is not an error. Once this message is successfully sent the sender will stop using the old queue. Once this message (or any other message in the new queue) is received, the recipient will stop using the old queue and delete it.
#### DEL message
**Queue rotation procedure**
This message is sent to notify that the queue with passed URI will be deleted - having received this message, the receiving agent should no longer send messages to this queue. In case it was the last remaining send queue in the duplex connection, the agent MAY also delete the reply queue(s) in the connection.
![Queue rotation procedure](./diagrams/duplex-messaging/queue-rotation.svg)
## SMP agent commands
`SKEY` command added in v9 of SMP protocol allows for faster queue rotation procedure.
This part describes the transmissions between users and client-side SMP agents: commands that the users send to create and operate duplex connections and SMP agent responses and messages they deliver.
**Fast queue rotation procedure**
Commands syntax below is provided using [ABNF][3] with [case-sensitive strings extension][4].
![Fast queue rotation procedure](./diagrams/duplex-messaging/queue-rotation-fast.svg)
Each transmission between the user and SMP agent must have this format/syntax:
## End-to-end encryption
```abnf
agentTransmission = [corrId] CRLF [connId] CRLF agentCommand
Messages between SMP agents have two layers of e2e encryption:
- simple encryption agreed in SMP protocol with a fixed key agreed when the messaging queue is agreed by parties.
- post-quantum resistant augmented double ratchet algorithm (PQDR) specified in [this document](./pqdr.md).
corrId = 1*(%x21-7F) ; any characters other than control/whitespace
The protocol supports adding and removing post-quantum KEM primitive to the key agreement in double ratchet:
- to support migration of pre-existing connections to PQDR.
- to be able to disable PQ key agreement.
- to be able to use invitation links and contact addresses without large PQ keys.
connId = encoded
Possible scenarios below show the possible states of PQ key agreement, assuming that both clients support it.
agentCommand = (userCmd / agentMsg) CRLF
userCmd = newCmd / joinCmd / letCmd / acceptCmd / subscribeCmd / sendCmd / acknowledgeCmd / suspendCmd / deleteCmd
agentMsg = invitation / confMsg / connReqMsg / connInfo / connected / unsubscribed / connDown / connUp / messageId / sent / messageError / message / received / ok / error
Possible options for each stage are:
- no KEM encapsulation key was sent (No PQ key),
- only KEM encapsulation key was sent, but not ciphertext yet (PQ key sent),
- both KEM encapsulation key from one KEM agreement and ciphertext from the previous agreement were sent (PQ key + PQ ct sent).
newCmd = %s"NEW" SP connectionMode [SP %s"NO_ACK"] ; response is `invitation` or `error`
; NO_ACK parameter currently not supported
`+` in the table means that this scenario is possible, and `-` - that it is not possible.
connectionMode = %s"INV" / %s"CON"
| Connection stage | No PQ key | PQ key sent | PQ key + PQ ct sent |
|:------------------------------------------------------:|:----------------:|:----------------:|:-------------------:|
| invitation | + | + | - |
| confirmation, in reply to: <br>no-pq inv <br>pq inv | &nbsp;<br>+<br>+ | &nbsp;<br>+<br>- | &nbsp;<br>-<br>+ |
| 1st msg, in reply to: <br>no-pq conf <br>pq/pq+ct conf | &nbsp;<br>+<br>+ | &nbsp;<br>+<br>- | &nbsp;<br>-<br>+ |
| Nth msg, in reply to: <br>no-pq msg <br>pq/pq+ct msg | &nbsp;<br>+<br>+ | &nbsp;<br>+<br>- | &nbsp;<br>-<br>+ |
invitation = %s"INV" SP connectionRequest ; `connectionRequest` is defined below
These scenarios can be reduced to:
1. initial invitation optionally has PQ key, but must not have ciphertext.
2. all subsequent messages should be allowed without PQ key/ciphertext, but:
- if the previous message had PQ key or PQ key with ciphertext, they must either have no PQ key, or have PQ key with ciphertext (PQ key without ciphertext is an error).
- if the previous message had no PQ key, they must either have no PQ key, or have PQ key without ciphertext (PQ key with ciphertext is an error).
confMsg = %s"CONF" SP confirmationId SP msgBody
; msgBody here is any binary information identifying connection request
The rules for calculating the shared secret for received/sent messages are (assuming received message is valid according to the above rules):
letCmd = %s"LET" SP confirmationId SP msgBody
; msgBody here is any binary information identifying connecting party
| sent msg > <br>V received msg | no-pq | pq | pq+ct |
|:------------------------------:|:-----------:|:-------:|:---------------:|
| no-pq | DH / DH | DH / DH | err |
| pq (sent msg was NOT pq) | DH / DH | err | DH / DH+KEM |
| pq+ct (sent msg was NOT no-pq) | DH+KEM / DH | err | DH+KEM / DH+KEM |
confirmationId = 1*DIGIT
To summarize, the upgrade to DH+KEM secret happens in a sent message that has PQ key with ciphertext sent in reply to message with PQ key only (without ciphertext), and the downgrade to DH secret happens in the message that has no PQ key.
connReqMsg = %s"REQ" SP invitationId SP msgBody
; msgBody here is any binary information identifying connection request
## Connection link: 1-time invitation and contact address
acceptCmd = %s"ACPT" SP invitationId SP msgBody
; msgBody here is any binary information identifying connecting party
Connection links are generated by SMP agent in response to `createConnection` api call, used by another party user with `joinConnection` api, and then another connection link is sent by the agent in `agentConnInfoReply` and used by the first party agent to connect to the reply queue (the second part of the process is invisible to the users).
invitationId = 1*DIGIT
connInfo = %s"INFO" SP msgBody
; msgBody here is any binary information identifying connecting party
connected = %s"CON"
subscribeCmd = %s"SUB" ; response is `ok` or `error`
unsubscribed = %s"END"
; when another agent (or another client of the same agent)
; subscribes to the same SMP queue on the server
connDown = %s"DOWN"
; lost connection (e.g. because of Internet connectivity or server is down)
connUp = %s"UP"
; restored connection
joinCmd = %s"JOIN" SP connectionRequest SP connInfo [SP %s"NO_REPLY"] [SP %s"NO_ACK"]
; `connectionRequest` and `connInfo` are defined below
; response is `connected` or `error`
; parameters NO_REPLY and NO_ACK are currently not supported
suspendCmd = %s"OFF" ; can be sent by either party, response `ok` or `error`
deleteCmd = %s"DEL" ; can be sent by either party, response `ok` or `error`
sendCmd = %s"SEND" SP msgBody
; send syntax is similar to that of SMP protocol, but it is wrapped in SMP message
msgBody = stringMsg | binaryMsg
stringMsg = ":" string ; until CRLF in the transmission
string = *(%x01-09 / %x0B-0C / %x0E-FF %) ; any characters other than NUL, CR and LF
binaryMsg = size CRLF msgBody CRLF ; the last CRLF is in addition to CRLF in the transmission
size = 1*DIGIT ; size in bytes
msgBody = *OCTET ; any content of specified size - safe for binary
messageId = %s"MID" SP agentMsgId
sent = %s"SENT" SP agentMsgId
messageError = %s"MERR" SP agentMsgId SP <errorType>
message = %s"MSG" SP msgIntegrity SP recipientMeta SP brokerMeta SP senderMeta SP binaryMsg
recipientMeta = %s"R=" agentMsgId "," agentTimestamp ; receiving agent message metadata
brokerMeta = %s"B=" brokerMsgId "," brokerTimestamp ; broker (server) message metadata
senderMeta = %s"S=" agentMsgId ; sending agent message ID
brokerMsgId = encoded
brokerTimestamp = <date-time>
msgIntegrity = ok / msgIntegrityError
msgIntegrityError = %s"ERR" SP msgIntegrityErrorType
msgIntegrityErrorType = skippedMsgErr / badMsgIdErr / badHashErr
skippedMsgErr = %s"NO_ID" SP missingFromMsgId SP missingToMsgId
badMsgIdErr = %s"ID" SP previousMsgId ; ID is lower than the previous
badHashErr = %s"HASH"
missingFromMsgId = agentMsgId
missingToMsgId = agentMsgId
previousMsgId = agentMsgId
acknowledgeCmd = %s"ACK" SP agentMsgId ; ID assigned by receiving agent (in MSG "R")
received = %s"RCVD" SP agentMsgId SP msgIntegrity
; ID assigned by sending agent (in SENT response)
; currently not implemented
msgStatus = ok | error
ok = %s"OK"
error = %s"ERR" SP <errorType>
```
### Client commands and server responses
#### NEW command and INV response
`NEW` command is used to create a connection and a connection request to be sent out-of-band to another protocol user (the joining party). It should be used by the client of the agent that initiates creating a duplex connection (the initiating party).
`INV` response is sent by the agent to the client of the initiating party.
`NEW` command has `connectionMode` parameter to define the connection mode - to be used to communicate with a single contact (invitation mode, `connectionMode` is `INV`) or to accept connection requests from anybody (contact mode, `connectionMode` is `CON`). The type of connection request is determined by `connectionMode` parameter.
#### JOIN command
It is used to create a connection and accept the connection request received out-of-band. It should be used by the client of the agent that accepts the connection (the joining party).
#### CONF notification and LET command
When the joining party uses `JOIN` command to accept connection invitation created with `NEW INV` command, the initiating party will receive `CONF` notification with some numeric identifier and an additional binary information, that can be used to identify the joining party or for any other purpose.
To continue with the connection the initiating party should use `LET` command.
#### REQ notification and ACPT command
When the joining party uses `JOIN` command to connect to the contact created with `NEW CON` command, the initiating party will receive `REQ` notification with some numeric identifier and an additional binary information, that can be used to identify the joining party or for any other purpose.
To continue with the connection the party that created the contact should use `ACPT` command.
#### INFO and CON notifications
After the initiating party proceeds with the connection using `ACPT` command, the joining party will receive `INFO` notification that can be used to identify the initiating party or for any other purpose.
Once the connection is established and ready to accept client messages, both agents will send `CON` notification to their clients.
#### SUB command
This command can be used by the client to resume receiving messages from the connection that was created in another TCP/client session. Agent response to this command can be `OK` or `ERR` in case connection does not exist (or can only be used to send connections - e.g. when the reply queue was not created).
#### SEND command and MID, SENT, RCVD and MERR responses
`SEND` command is used by the client to send messages.
`MID` response with the message ID (the sequential message number that includes both sent and received messages in the connection) is sent to the client to confirm that the message is accepted by the agent, before it is sent to the SMP server.
`SENT` notification is sent by the agent to confirm that the message was delivered to at least one of SMP servers. This notification contains the same message ID as `MID` notification. `SENT` notification, depending on network availability, can be sent at any time later, potentially in the next client session.
`RCVD` notification is sent by the agent when it receives `ACK` message from the receiving agent. This notification contains reception status, only one successful notification will be sent, and multiple error notifications will be sent in case `ACK` had error status.
In case of the failure to send the message for any other reason than network connection or message queue quota - e.g. authentication error (`ERR AUTH`) or syntax error (`ERR CMD error`), the agent will send to the client `MERR` notification with the message ID, and this message delivery will no longer be attempted to this SMP queue.
#### MSG notification
It is sent by the agent to the client when agent receives the message from the SMP server. It has message ID and timestamp from both the receiving and sending agents and from SMP server:
- recipient agent ID is intended to be used to refer to the message in the future.
- sender agent ID is intended to be used to identify any missed / skipped message(s)
- broker ID should be used to detect duplicate deliveries (it would happen if TCP connection is lost before the message is acknowledged by the agent - see [SMP protocol](./simplex-messaging.md))
#### END notification
It is sent by the agent to the client when agent receives SMP protocol `END` notification from SMP server. It indicates that another agent has subscribed to the same SMP queue on the server and the server terminated the subscription of the current agent.
#### DOWN and UP notifications
These notifications are sent when server or network connection is, respectively, `DOWN` or back `UP`.
All the subscriptions made in the current client session will be automatically resumed when `UP` notification is received.
#### OFF command
It is used to suspend the receiving SMP queue - sender will no longer be able to send the messages to the connection, but the recipient can retrieve the remaining messages. Agent response to this command can be `OK` or `ERR`. This command is irreversible.
#### DEL command
It is used to delete the connection and all messages in it, as well as the receiving SMP queue and all messages in it that were remaining on the server. Agent response to this command can be `OK` or `ERR`. This command is irreversible.
## Connection request
Connection request `connectionRequest` is generated by SMP agent in response to `newCmd` command (`"NEW"`), used by another party user with `joinCmd` command (`"JOIN"`), and then another connection request is sent by the agent in `replyQueueMsg` and used by the first party agent to connect to the reply queue (the second part of the process is invisible to the users).
Connection request syntax:
Connection link syntax:
```
connectionRequest = connectionScheme "/" connReqType "#/?smp=" smpQueues "&e2e=" e2eEncryption
connReqType = %s"invitation" / %s"contact"
; this parameter has the same meaning as connectionMode in agent commands
; `NEW INV` creates `invitation` connection request, `NEW CON` - `contact`
connectionLink = connectionScheme "/" connLinkType "#/?smp=" smpQueues "&e2e=" e2eEncryption
connLinkType = %s"invitation" / %s"contact"
connectionScheme = (%s"https://" clientAppServer) | %s"simplex:"
clientAppServer = hostname [ ":" port ]
; client app server, e.g. simplex.chat
@@ -407,12 +364,112 @@ smpQueue = <URL-encoded queueURI defined in SMP protocol>
All parameters are passed via URI hash to avoid sending them to the server (in case "https" scheme is used) - they can be used by the client-side code and processed by the client application. Parameters `smp` and `e2e` can be present in any order, any unknown additional parameters SHOULD be ignored.
`clientAppServer` is not an SMP server - it is a server that shows the instruction on how to download the client app that will connect using this connection request. This server can also host a mobile or desktop app manifest so that this link is opened directly in the app if it is installed on the device.
`clientAppServer` is not an SMP server - it is a server that shows the instruction on how to download the client app that will connect using this connection link. This server can also host a mobile or desktop app manifest so that this link is opened directly in the app if it is installed on the device.
"simplex" URI scheme in `connectionProtocol` can be used instead of client app server, to connect without creating any web traffic. Client apps MUST support this URI scheme.
See SMP protocol [out-of-band messages](./simplex-messaging.md#out-of-band-messages) for syntax of `queueURI`.
## Appendix A: SMP agent API
The exact specification of agent library API and of the events that the agent sends to the client application is out of scope of the protocol specification.
The list of some of the API functions and events below is supported by the reference implementation, and they are likely to be required by the client applications.
### API functions
The list of APIs below is not exhaustive and provided for information only. Please consult the source code for more information.
#### Create conection
`createConnection` api is used to create a connection - it returns the connection link that should be sent out-of-band to another protocol user (the joining party). It should be used by the client of the agent that initiates creating a duplex connection (the initiating party).
This api is also used to create a contact address - a special connection that can be used by multiple people to connect to the user.
Some communication scenarios may require fault-tolerant mechanism of creating connections that retries on network failures and continue retrying after the client is restarted. Such asynchronous API would return its result via `INV` event once it succeeds.
#### Join connection
`joinConnection` is used to create a connection record and accept the connection invitation received out-of-band. It should be used by the client of the agent that accepts the connection (the joining party).
This api can also be required as asynchronous, in which case `OK` event will be dispatched to the client to indicate the success or `ERR` in case it permanently failed (e.g., in case connection was deleted by another party).
#### Allow connection
Once the client receives `CONF` event, it should use synchronous `allowConnection` api to proceed with the connection (both for the [standard](#duplex-connection-procedure) and for the [fast duplex procedure](#fast-duplex-connection-procedure)).
In case this API is used as asynchronous it will return its result via `OK` or `ERR` event.
#### Accept and reject connection requests
Connection requests are delivered to the client application via `REQ` event.
Client can `acceptContact` and `rejectContact`, with `OK` and `ERR` events in case of asynchronous calls.
#### Send message
`sendMessage` api is always asynchronous. The api call returns message ID, `SENT` event once the message is sent to the server, `MWARN` event in case of temporary delivery failure that can be resolved by the user (e.g., by connecting via Tor or by upgrading the client) and `MERR` in case of permanent delivery failure.
#### Acknowledge received message
Messages are delivered to the client application via `MSG` event.
Client application must always `ackMessage` to receive the next one - failure to call it in reference implementation will prevent the delivery of subsequent messages until the client reconnects to the server.
This api is also used to acknowledge message delivery to the sending party - that party client application will receive `RCVD` event.
#### Subscribe connection
`subscribeConnection` api is used by the client to resume receiving messages from the connection that was created in another TCP/client session.
#### Get notification message
`getNotificationMessage` is used by push notification subsystem of the client application to receive the message from a specific messaging queue mentioned in the notification. The client application would receive `MSG` and any other events from the agent, and then `MSGNTF` event once the message related to this notification is received.
#### Rotate message queue to another server
`switchConnection` api is used to rotate connection queues to another messaging server.
#### Renegotiate e2e encryption
`synchronizeRatchet` api is used to re-negotiate double ratchet encryption for the connection.
#### Delete connection
`deleteConnection` api is used to delete connection. In case of asynchronous call, the connection deletion will be confirmed with `DEL_RCVQ` and `DEL_CONN` events.
#### Suspend connection
`suspendConnection` api is used to prevent any further messages delivered to the connection without deleting it.
### API events
Agent API uses these events dispatch to notify client application about events related to the connections:
- `INV` - connection invitation or connection address URI after connection is created.
- `CONF` - confirmation that connection is accepted by another party. When the accepting party uses `joinConnection` api to accept connection invitation, the initiating party will receive `CONF` notification with some identifier and additional information from the accepting party (e.g., profile). To continue the connection the initiating party client should use `allowConnection` api.
- `REQ` - connection request is sent when another party uses `joinConnection` api with contact address. The client application can use `acceptContact` or `rejectContact` api.
- `INFO` - information from the party that initiated the connection with `createConnection` sent to the party accepting the connection with `joinConnection`.
- `CON` - notification that connection is established sent to both parties of the connection.
- `END` - notification that connection subscription is terminated when another client subscribed to the same messaging queue.
- `DOWN` - notification that connection server is temporarily unavailable.
- `UP` - notification that the subscriptions made in the current client session are resumed after the server became available.
- `SWITCH` - notification about queue rotation process.
- `RSYNC` - notification about e2e encryption re-negotiation process.
- `SENT` - notification to confirm that the message was delivered to at least one of SMP servers. This notification contains the same message ID as returned to `sendMessage` api. `SENT` notification, depending on network availability, can be sent at any time later, potentially in the next client session.
- `MWARN` - temporary delivery failure that can be resolved by the user (e.g., by connecting via Tor or by upgrading the client).
- `MERR` - notification about permanent message delivery failure.
- `MERRS` - notification about permanent message delivery failure for multiple messages (e.g., when multiple messages expire).
- `MSG` - sent when agent receives the message from the SMP server.
- `MSGNTF` - sent after agent received and processed the message referenced in the push notification.
- `RCVD` - notification confirming message receipt by another party.
- `QCONT` - notification that the agent continued sending messages after queue capacity was exceeded and recipient received all messages.
- `DEL_RCVQ` - confirmation that message queue was deleted.
- `DEL_CONN` - confirmation that connection was deleted.
- `OK` - confirmation that asynchronous api call was successful.
- `ERR` - error of asynchronous api call or some other error event.
This list of events is not exhaustive and provided for information only. Please consult the source code for more information.
[1]: https://en.wikipedia.org/wiki/End-to-end_encryption
[2]: https://en.wikipedia.org/wiki/Man-in-the-middle_attack
[3]: https://tools.ietf.org/html/rfc5234
@@ -0,0 +1,65 @@
sequenceDiagram
participant A as Alice
participant AA as Alice's<br>agent
participant AS as Alice's<br>server
participant BS as Bob's<br>server
participant BA as Bob's<br>agent
participant B as Bob
note over AA, BA: status (receive/send): NONE/NONE
note over A, AA: 1. request connection<br>from agent
A ->> AA: createConnection
note over AA, AS: 2. create Alice's SMP queue
AA ->> AS: NEW: create SMP queue<br>allow sender to secure
AS ->> AA: IDS: SMP queue IDs
note over AA: status: NEW/NONE
AA ->> A: INV: invitation<br>to connect
note over A, B: 3. out-of-band invitation
A ->> B: OOB: invitation to connect
note over BA, B: 4. accept connection
B ->> BA: joinConnection:<br>via invitation info
note over BA: status: NONE/NEW
note over BA, AS: 5. secure Alice's SMP queue
BA ->> AS: SKEY: secure queue (this command needs to be proxied)
note over BA: status: NONE/SECURED
note over BA, BS: 6. create Bob's SMP queue
BA ->> BS: NEW: create SMP queue<br>allow sender to secure
BS ->> BA: IDS: SMP queue IDs
note over BA: status: NEW/SECURED
note over BA, AA: 7. confirm Alice's SMP queue
BA ->> AS: SEND: Bob's info without sender's key (SMP confirmation with reply queues)
note over BA: status: NEW/CONFIRMED
AS ->> AA: MSG: Bob's info without<br>sender server key
note over AA: status: CONFIRMED/NEW
AA ->> AS: ACK: confirm message
AA ->> A: CONF: connection request ID<br>and Bob's info
A -> AA: allowConnection: accept connection request,<br>send Alice's info
note over AA, BS: 8. secure Bob's SMP queue
AA ->> BS: SKEY: secure queue (this command needs to be proxied)
note over BA: status: CONFIRMED/SECURED
AA ->> BS: SEND: Alice's info without sender's server key (SMP confirmation without reply queues)
note over AA: status: CONFIRMED/CONFIRMED
note over AA, A: 9. notify Alice<br>about connection success<br>(no HELLO needed in v6)
AA ->> A: CON: connected
note over AA: status: ACTIVE/ACTIVE
note over BA, B: 10. notify Bob<br>about connection success
BS ->> BA: MSG: Alice's info without<br>sender's server key
note over BA: status: CONFIRMED/CONFIRMED
BA ->> B: INFO: Alice's info
BA ->> BS: ACK: confirm message
BA ->> B: CON: connected
note over BA: status: ACTIVE/ACTIVE
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 40 KiB

@@ -1,71 +0,0 @@
sequenceDiagram
participant A as Alice
participant AA as Alice's<br>agent
participant AS as Alice's<br>server
participant BS as Bob's<br>server
participant BA as Bob's<br>agent
participant B as Bob
note over AA, BA: status (receive/send): NONE/NONE
note over A, AA: 1. request connection<br>from agent
A ->> AA: NEW: create<br>duplex connection
note over AA, AS: 2. create Alice's SMP queue
AA ->> AS: NEW: create SMP queue
AS ->> AA: IDS: SMP queue IDs
note over AA: status: NEW/NONE
AA ->> A: INV: invitation<br>to connect
note over A, B: 3. out-of-band invitation
A ->> B: OOB: invitation to connect
note over BA, B: 4. accept connection
B ->> BA: JOIN:<br>via invitation info
note over BA: status: NONE/NEW
note over BA, BS: 5. create Bob's SMP queue
BA ->> BS: NEW: create SMP queue
BS ->> BA: IDS: SMP queue IDs
note over BA: status: NEW/NEW
note over BA, AA: 6. establish Alice's SMP queue
BA ->> AS: SEND: Bob's info and sender server key (SMP confirmation with reply queues)
note over BA: status: NEW/CONFIRMED
AS ->> AA: MSG: Bob's info and<br>sender server key
note over AA: status: CONFIRMED/NONE
AA ->> AS: ACK: confirm message
AA ->> A: CONF: connection request ID<br>and Bob's info
A ->> AA: LET: accept connection request,<br>send Alice's info
AA ->> AS: KEY: secure queue
note over AA: status: SECURED/NONE
AA ->> BS: SEND: Alice's info and sender's server key (SMP confirmation without reply queues)
note over AA: status: SECURED/CONFIRMED
BS ->> BA: MSG: Alice's info and<br>sender's server key
note over BA: status: CONFIRMED/CONFIRMED
BA ->> B: INFO: Alice's info
BA ->> BS: ACK: confirm message
BA ->> BS: KEY: secure queue
note over BA: status: SECURED/CONFIRMED
BA ->> AS: SEND: HELLO: only needs to be sent once in v2
note over BA: status: SECURED/ACTIVE
note over BA, B: 7a. notify Bob<br>about connection success
BA ->> B: CON: connected
AS ->> AA: MSG: HELLO: Alice's agent<br>knows Bob can send
note over AA: status: SECURED/ACTIVE
AA ->> AS: ACK: confirm message
note over A, AA: 7a. notify Alice<br>about connection success
AA ->> A: CON: connected
AA ->> BS: SEND: HELLO: only needs to be sent once in v2
note over AA: status: ACTIVE/ACTIVE
BS ->> BA: MSG: HELLO: Bob's agent<br>knows Alice can send
note over BA: status: ACTIVE/ACTIVE
BA ->> BS: ACK: confirm message
@@ -8,8 +8,8 @@ sequenceDiagram
note over AA, BA: status (receive/send): NONE/NONE
note over A, AA: 1. request connection from agent
A ->> AA: NEW: create<br>duplex connection
note over A, AA: 1. request connection<br>from agent
A ->> AA: createConnection
note over AA, AS: 2. create Alice's SMP queue
AA ->> AS: NEW: create SMP queue
@@ -17,63 +17,58 @@ sequenceDiagram
note over AA: status: NEW/NONE
AA ->> A: INV: invitation<br>to connect
note over AA: status: PENDING/NONE
note over A, B: 3. out-of-band invitation
A ->> B: OOB: invitation to connect
note over BA, B: 4. accept connection
B ->> BA: JOIN:<br>via invitation info
B ->> BA: joinConnection:<br>via invitation info
note over BA: status: NONE/NEW
note over BA, AA: 5. establish Alice's SMP queue
BA ->> AS: SEND: Bob's info and sender server key (SMP confirmation)
note over BA: status: NONE/CONFIRMED
activate BA
note over BA, BS: 5. create Bob's SMP queue
BA ->> BS: NEW: create SMP queue
BS ->> BA: IDS: SMP queue IDs
note over BA: status: NEW/NEW
note over BA, AA: 6. confirm Alice's SMP queue
BA ->> AS: SEND: Bob's info and sender server key (SMP confirmation with reply queues)
note over BA: status: NEW/CONFIRMED
AS ->> AA: MSG: Bob's info and<br>sender server key
note over AA: status: CONFIRMED/NONE
AA ->> AS: ACK: confirm message
AA ->> A: CONF: connection request ID<br>and Bob's info
A ->> AA: LET: accept connection request,<br>send Alice's info
A ->> AA: allowConnection: accept connection request,<br>send Alice's info
AA ->> AS: KEY: secure queue
note over AA: status: SECURED/NONE
BA ->> AS: SEND: HELLO: try sending until successful
deactivate BA
note over BA: status: NONE/ACTIVE
AS ->> AA: MSG: HELLO: Alice's agent<br>knows Bob can send
note over AA: status: ACTIVE/NONE
AA ->> AS: ACK: confirm message
AA ->> BS: SEND: Alice's info and sender's server key (SMP confirmation without reply queues)
note over AA: status: SECURED/CONFIRMED
note over BA, BS: 6. create Bob's SMP queue
BA ->> BS: NEW: create SMP queue
BS ->> BA: IDS: SMP queue IDs
note over BA: status: NEW/ACTIVE
note over AA, BA: 7. establish Bob's SMP queue
BA ->> AS: SEND: REPLY: invitation to the connect
note over BA: status: PENDING/ACTIVE
AS ->> AA: MSG: REPLY: invitation<br>to connect
note over AA: status: ACTIVE/NEW
AA ->> AS: ACK: confirm message
AA ->> BS: SEND: Alice's info and sender's server key
note over AA: status: ACTIVE/CONFIRMED
activate AA
note over BA, AA: 7. confirm Bob's SMP queue
BS ->> BA: MSG: Alice's info and<br>sender's server key
note over BA: status: CONFIRMED/ACTIVE
note over BA: status: CONFIRMED/CONFIRMED
BA ->> B: INFO: Alice's info
BA ->> BS: ACK: confirm message
BA ->> BS: KEY: secure queue
note over BA: status: SECURED/CONFIRMED
BA ->> AS: SEND: HELLO message
note over BA: status: SECURED/ACTIVE
AA ->> BS: SEND: HELLO: try sending until successful
deactivate AA
AS ->> AA: MSG: HELLO: Alice's agent<br>knows Bob can send
note over AA: status: SECURED/ACTIVE
AA ->> AS: ACK: confirm message
AA ->> BS: SEND: HELLO
note over A, AA: 8. notify Alice<br>about connection success
AA ->> A: CON: connected
note over AA: status: ACTIVE/ACTIVE
BS ->> BA: MSG: HELLO: Bob's agent<br>knows Alice can send
note over BA: status: ACTIVE/ACTIVE
BA ->> BS: ACK: confirm message
note over A, B: 8. notify users about connection success
AA ->> A: CON: connected
note over BA, B: 9. notify Bob<br>about connection success
BA ->> B: CON: connected
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 40 KiB

@@ -0,0 +1,17 @@
sequenceDiagram
participant A as Alice
participant R as Current server<br>that has A's<br>receive queue
participant R' as New server<br>that has the new A's<br>receive queue
participant S as Server<br>that has A's send queue<br>(B's receive queue)
participant B as Bob
A ->> R': NEW: create new queue<br>(allow SKEY)
A ->> S: SEND: QADD (R'): send address<br>of the new queue(s)
S ->> B: MSG: QADD (R')
B ->> R': SKEY: secure new queue
B ->> R': SEND: QTEST
R' ->> A: MSG: QTEST
A ->> R: DEL: delete the old queue
B ->> R': SEND: send messages to the new queue
R' ->> A: MSG: receive messages from the new queue
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 27 KiB

@@ -0,0 +1,21 @@
sequenceDiagram
participant A as Alice
participant R as Current server<br>that has A's<br>receive queue
participant R' as New server<br>that has the new A's<br>receive queue
participant S as Server<br>that has A's send queue<br>(B's receive queue)
participant B as Bob
A ->> R': NEW: create new queue
A ->> S: SEND: QADD (R'): send address<br>of the new queue(s)
S ->> B: MSG: QADD (R')
B ->> R: SEND: QKEY (R'): sender's key<br>for the new queue(s)
R ->> A: MSG: QKEY(R')
A ->> R': KEY: secure new queue
A ->> S: SEND: QUSE (R'): instruction to use new queue(s)
S ->> B: MSG: QUSE (R')
B ->> R': SEND: QTEST
R' ->> A: MSG: QTEST
A ->> R: DEL: delete the old queue
B ->> R': SEND: send messages to the new queue
R' ->> A: MSG: receive messages from the new queue
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 28 KiB

@@ -0,0 +1,30 @@
sequenceDiagram
participant M as mobile app
participant C as chat core
participant A as agent
participant P as push server
participant APN as APN
note over M, APN: get device token
M ->> APN: registerForRemoteNotifications()
APN ->> M: device token
note over M, P: register device token with push server
M ->> C: /_ntf register <token>
C ->> A: registerNtfToken(<token>)
A ->> P: TNEW
P ->> A: ID (tokenId)
A ->> C: registered
C ->> M: registered
note over M, APN: verify device token
P ->> APN: E2E encrypted code<br>in background<br>notification
APN ->> M: deliver background notification with e2ee verification token
M ->> C: /_ntf verify <e2ee code>
C ->> A: verifyNtfToken(<e2ee code>)
A ->> P: TVFY code
P ->> A: OK / ERR
A ->> C: verified
C ->> M: verified
note over M, APN: now token ID can be used
@@ -1,30 +1,26 @@
sequenceDiagram
participant M as mobile app
participant C as chat core
participant C as client app
participant A as agent
participant P as push server
participant APN as APN
participant P as SimpleX<br>Notification<br>Server
participant APN as Apple<br>Push Notifications<br>Server
note over M, APN: get device token
M ->> APN: registerForRemoteNotifications()
APN ->> M: device token
note over C, APN: get device token
C ->> APN: registerForRemoteNotifications()
APN ->> C: device token
note over M, P: register device token with push server
M ->> C: /_ntf register <token>
C ->> A: registerNtfToken(<token>)
note over C, P: register device token with push server
C ->> A: registerToken
A ->> P: TNEW
P ->> A: ID (tokenId)
A ->> C: registered
C ->> M: registered
note over M, APN: verify device token
note over C, APN: verify device token
P ->> APN: E2E encrypted code<br>in background<br>notification
APN ->> M: deliver background notification with e2ee verification token
M ->> C: /_ntf verify <e2ee code>
C ->> A: verifyNtfToken(<e2ee code>)
APN ->> C: deliver background notification with e2ee verification token
C ->> A: verifyToken<br>(<e2ee code>)
A ->> P: TVFY code
P ->> A: OK / ERR
A ->> C: verified
C ->> M: verified
note over M, APN: now token ID can be used
note over C, APN: now token ID can be used
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 28 KiB

@@ -0,0 +1,40 @@
sequenceDiagram
participant M as mobile app
participant C as chat core
participant A as agent
participant S as SMP server
participant N as NTF server
participant APN as APN
note over M, APN: register subscription
alt register existing
M -->> A: on /_ntf register, for subscribed queues
else create new connection
A -->> S: NEW / JOIN
note over A, S: ...<br>Connection handshake<br>...
S -->> A: CON
end
A ->> S: NKEY nKey
S ->> A: NID nId
A ->> N: SNEW tknId dhKey (smpServer, nId, nKey)
N ->> A: ID subId dhKey
N ->> S: NSUB nId
S ->> N: OK [/ NMSG]
note over M, APN: notify about message
S ->> N: NMSG
N ->> APN: APNSMutableContent<br>ntfQueue, nonce
APN ->> M: UNMutableNotificationContent
note over M, S: ...<br>Client awaken, message is received<br>...
S ->> M: message
note over M: mutate notification
note over M, APN: change APN token
APN ->> M: new device token
M -->> C: /_ntf_sub update tkn
C -->> A: updateNtfToken()
A -->> N: TUPD tknId newDeviceToken
note over M, N: ...<br>Verify token<br>...
@@ -1,17 +1,16 @@
sequenceDiagram
participant M as mobile app
participant C as chat core
participant C as client app
participant A as agent
participant S as SMP server
participant N as NTF server
participant APN as APN
note over M, APN: register subscription
note over C, APN: register subscription
alt register existing
M -->> A: on /_ntf register, for subscribed queues
C -->> A: registerToken
else create new connection
A -->> S: NEW / JOIN
A -->> S: create/joinConnection
note over A, S: ...<br>Connection handshake<br>...
S -->> A: CON
end
@@ -20,21 +19,20 @@ sequenceDiagram
A ->> N: SNEW tknId dhKey (smpServer, nId, nKey)
N ->> A: ID subId dhKey
N ->> S: NSUB nId
S ->> N: OK [/ NMSG]
S ->> N: OK / NMSG:<br>confirm subscription
note over M, APN: notify about message
note over C, APN: notify about message
S ->> N: NMSG
N ->> APN: APNSMutableContent<br>ntfQueue, nonce
APN ->> M: UNMutableNotificationContent
note over M, S: ...<br>Client awaken, message is received<br>...
S ->> M: message
note over M: mutate notification
APN ->> C: UNMutableNotificationContent
note over C, S: ...<br>Client awaken, message is received<br>...
S ->> C: message
note over C: show notification
note over M, APN: change APN token
note over C, APN: change APN token
APN ->> M: new device token
M -->> C: /_ntf_sub update tkn
C -->> A: updateNtfToken()
APN ->> C: new device token
C -->> A: updateToken()
A -->> N: TUPD tknId newDeviceToken
note over M, N: ...<br>Verify token<br>...
note over C, N: ...<br>Verify token<br>...
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 31 KiB

@@ -0,0 +1,23 @@
sequenceDiagram
participant B as Bob (sender)
participant S as server (queue RID)
participant A as Alice (recipient)
note over A: creating queue<br>("public" key RK<br>for msg retrieval)
A ->> S: 1. create queue ("NEW")
S ->> A: respond with queue RID and SID ("IDS")
note over A: out-of-band msg<br>(sender's queue SID<br>and "public" key EK<br>to encrypt msgs)
A -->> B: 2. send out-of-band message
note over B: secure queue<br>(with "public" key SK for<br>sending messages)
B ->> S: 3. confirm queue ("SKEY" command authorized with SK)
note over B: confirm queue<br>(public key<br>for e2e encryption<br>and any optional<br>encrypted info.)
B ->> S: 4. confirm queue ("SEND" command authorized with SK)
S ->> A: 5. deliver Bob's message (MSG)
note over A: decrypt message<br>("private" key EK)
A ->> S: acknowledge message (ACK)
note over S: 6. simplex<br>queue RID<br>is ready to use!
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 27 KiB

@@ -10,11 +10,13 @@ sequenceDiagram
note over A: out-of-band msg<br>(sender's queue SID<br>and "public" key EK<br>to encrypt msgs)
A -->> B: 2. send out-of-band message
note over B: confirm queue<br>("public" key SK for<br>sending messages<br>and any optional<br>info encrypted with<br>"public" key EK)
note over B: confirm queue<br>("public" key SK for<br>sending messages,<br>public key for<br>e2e encryption<br>and any optional<br>encrypted info)
B ->> S: 3. confirm queue ("SEND" command not signed)
S ->> A: 4. deliver Bob's message
S ->> A: 4. deliver Bob's message (MSG)
note over A: decrypt message<br>("private" key EK)
A ->> S: acknowledge message (ACK)
A ->> S: 5. secure queue ("KEY", RK-signed)
note over S: 6. simplex<br>queue RID<br>is ready to use!
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 26 KiB

@@ -0,0 +1,18 @@
sequenceDiagram
participant B as Bob (recipient)
participant S as XFTP server(s)
note over B: having received file description<br>from sender
loop for each chunk
B ->> S: 1a. download chunk ("FGET")
S ->> B: send chunk body ("FILE")
opt
B ->> S: 1b. acknowledge chunk reception ("FACK")
note over S: delete recipient ID
S ->> B: respond with ok ("OK")
end
end
note over B: 2. combine chunks into a file<br>3. decrypt file using key from file description<br>4. extract file name and unpad the file<br>5. validate file digest with the file description
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

@@ -0,0 +1,23 @@
sequenceDiagram
participant A as Alice (sender)
participant S as XFTP server(s)
participant B as recipient(s)
note over A: 1. prepare file:<br>encrypt,<br>split into chunks,<br>generate recipient<br>keys, etc.
loop for each chunk
A ->> S: 2a. register chunk ("FNEW")
S ->> A: respond with sender's and recipients' chunk IDs ("SIDS")
opt
A ->> S: 2b. request additional recipient IDs ("FADD")
S ->> A: respond with added recipients' chunk IDs ("RIDS")
end
A ->> S: 2c. upload chunk to chosen server ("FPUT")
S ->> A: respond with ok ("OK")
end
note over A: 3. prepare file description(s)
A -->> B: 4. send file description(s) out-of-band
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 25 KiB

+44
View File
@@ -0,0 +1,44 @@
sequenceDiagram
participant CI as Controller UI
participant CC as Controller Core
participant HC as Host Core
participant HI as Host UI
note over CI, HI: 1. Session invitation
CI->>CC: "Link a mobile"
CC-->>CI: Session invitation URI
note over CC: Listen for TCP connection
activate CC
HI->>HC: Session invitation URI
note over CI, HI: 2. Establishing TLS connection
HC-->>CC: TCP connect
note over CC, HC: TLS handshake
par
note over CC: validate client X509 credentials
CC->>CI: session code from tlsUnique
CI-->>CC: user confirmation
and
note over HC: validate server X509 credentials
HC->>HI: session code from tlsUnique
HI-->>HC: user confirmation
end
note over CI, HI: 3. Session verification and protocol negotiation
HC->>CC: host HELLO
note over CC: validate version, CA fingerprint
alt
CC-->>HC: controller ERROR
else
CC-->>HC: controller HELLO
note over CC, HC: update stored keys
end
deactivate CC
note over CI, HI: 4. Session operation
loop
CI->>CC: command
CC->>HC: XRCP command
HC-->>CC: XRCP response
CC-->>CI: response
end
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 31 KiB

+127 -56
View File
@@ -1,4 +1,4 @@
Revision 1, 2022-01-01
Revision 2, 2024-06-22
Evgeny Poberezkin
@@ -13,19 +13,23 @@ Evgeny Poberezkin
- [Technical Details](#technical-details)
- [Trust in Servers](#trust-in-servers)
- [Client -> Server Communication](#client---server-communication)
- [2-hop Onion Message Routing](#2-hop-onion-message-routing)
- [SimpleX Messaging Protocol](#simplex-messaging-protocol)
- [SimpleX Agents](#simplex-agents)
- [Encryption Primitives Used](#encryption-primitives-used)
- [Threat model](#threat-model)
- [Acknowledgements](#acknowledgements)
## Introduction
#### What is SimpleX
SimpleX as a whole is a platform upon which applications can be built. [SimpleX Chat](https://github.com/simplex-chat/simplex-chat) is one such application that also serves as an example and reference application.
- [SimpleX Messaging Protocol](https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md) (SMP) is a protocol to send messages in one direction to a recipient, relying on a server in-between. The messages are delivered via uni-directional queues created by recipients.
- [SimpleX Messaging Protocol](./simplex-messaging.md) (SMP) is a protocol to send messages in one direction to a recipient, relying on a server in-between. The messages are delivered via uni-directional queues created by recipients.
- SMP protocol allows to send message via a SMP server playing proxy role using 2-hop onion routing (referred to as "private routing" in messaging clients) to protect transport information of the sender (IP address and session) from the server chosen (and possibly controlled) by the recipient.
- SMP runs over a transport protocol (shown below as TLS) that provides integrity, server authentication, confidentiality, and transport channel binding.
@@ -35,7 +39,9 @@ SimpleX as a whole is a platform upon which applications can be built. [SimpleX
- SimpleX Client libraries speak SMP to SimpleX Servers and provide a low-level API not generally intended to be used by applications.
- SimpleX Agents interface with SimpleX Clients to provide a more high-level API intended to be used by applications. Typically they are embedded as libraries, but are designed so they can also be abstracted into local services.
- SimpleX Agents interface with SimpleX Clients to provide a more high-level API intended to be used by applications. Typically they are embedded as libraries, but can also be abstracted into local services.
- SimpleX Agents communicate with other agents inside e2e encrypted envelopes provided by SMP protocol - the syntax and semantics of the messages exchanged by the agent are defined by [SMP agent protocol](./agent-protocol.md)
*Diagram showing the SimpleX Chat app, with logical layers of the chat application interfacing with a SimpleX Agent library, which in turn interfaces with a SimpleX Client library. The Client library in turn speaks the Messaging Protocol to a SimpleX Server.*
@@ -72,10 +78,11 @@ SimpleX as a whole is a platform upon which applications can be built. [SimpleX
- Low latency: the delay introduced by the network should not be higher than 100ms-1s in addition to the underlying TCP network latency.
2. Provide better communication security and privacy than the alternative instant messaging solutions. In particular SimpleX provides better privacy of metadata (who talks to whom and when) and better security against active network attackers and malicious servers.
2. Provide better communication security and privacy than the alternative instant messaging solutions. In particular SimpleX provides better privacy of metadata (who talks to whom and when) and better security against active network attackers and malicious servers.
3. Balance user experience with privacy requirements, prioritizing experience of mobile device users.
#### In Comparison
SimpleX network has a design similar to P2P networks, but unlike most P2P networks it consists of clients and servers without depending on any centralized component.
@@ -91,53 +98,73 @@ In comparison to more traditional messaging applications (e.g. WhatsApp, Signal,
- users can change servers with minimal disruption - even after an in-use server disappears, simply by changing the configuration on which servers the new queues are created.
## Technical Details
#### Trust in Servers
Clients communicate directly with servers (but not with other clients) using SimpleX Messaging Protocol (SMP) running over some transport protocol that provides integrity, server authentication, confidentiality, and transport channel binding. By default, we assume this transport protocol is TLS.
Users use multiple servers, and choose where to receive their messages. Accordingly, they send messages to their communication partners' chosen servers.
Users use multiple servers, and choose where to receive their messages. Accordingly, they send messages to their communication partners' chosen servers either directly, if this is a known/trusted server, or via another SMP server providing proxy functionality to protect IP address and session of the sender.
Although end-to-end encryption is always present, users place a degree of trust in servers. This trust decision is very similar to a user's choice of email provider; however the trust placed in a SimpleX server is significantly less. Notably, there is no re-used identifier or credential between queues on the same (or different) servers. While a user *may* re-use a connection to fetch from multiple queues, or connect to a server from the same IP address, both are choices a user may opt into to break the promise of un-correlatable queues.
Although end-to-end encryption is always present, users place a degree of trust in servers they connect to. This trust decision is very similar to a user's choice of email provider; however the trust placed in a SimpleX server is significantly less. Notably, there is no re-used identifier or credential between queues on the same (or different) servers. While a user *may* re-use a transport connection to fetch messages from multiple queues, or connect to a server from the same IP address, both are choices a user may opt into to break the promise of un-correlatable queues.
Users may trust a server because:
- They deploy and control the servers themselves from the available open-source code. This has the trade-offs of strong trust in the server but limited metadata obfuscation to a passive network observer. Techniques such as noise traffic, traffic mixing (incurring latency), and using an onion routing transport protocol can mitigate that latter.
- They deploy and control the servers themselves from the available open-source code. This has the trade-offs of strong trust in the server but limited metadata obfuscation to a passive network observer. Techniques such as noise traffic, traffic mixing (incurring latency), and using an onion routing transport protocol can mitigate that.
- They use servers from a trusted commercial provider. The more clients the provider has, the less metadata about the communication times is leaked to the network observers.
- Users trust their contacts and the servers they chose.
By default, servers do not retain access logs, and permanently delete messages and queues when requested. Messages persist only in memory until they cross a threshold of time, typically on the order of days.[0] There is still a risk that a server maliciously records all queues and messages (even though encrypted) sent via the same transport connection to gain a partial knowledge of the users communications graph and other meta-data.
By default, servers do not retain access logs, and permanently delete messages and queues when requested. Messages persist only in memory until they cross a threshold of time, typically on the order of days.[0] There is still a risk that a server maliciously records all queues and messages (even though encrypted) sent via the same transport connection to gain a partial knowledge of the users communications graph and other meta-data.
SimpleX supports measures (managed transparently to the user at the agent level) to mitigate the trust placed in servers. These include rotating the queues in use between users, noise traffic, supporting overlay networks such as Tor, and isolating traffic to different queues to different transport connections (and Tor circuits, if Tor is used).
SimpleX supports measures (managed transparently to the user at the agent level) to mitigate the trust placed in servers. These include rotating the queues in use between users, noise traffic, and supporting overlay networks such as Tor.
[0] While configurable by servers, a minimum value is enforced by the default software. SimpleX Agents provide redundant routing over queues to mitigate against message loss.
[0] While configurable by servers, a minimum value is enforced by the default software. SimpleX Agents can provide redundant routing over queues to mitigate against message loss.
#### Client -> Server Communication
Utilizing TLS grants the SimpleX Messaging Protocol (SMP) server authentication and metadata protection to a passive network observer. But SMP does not rely on the transport protocol for message confidentiality or client authentication. The SMP protocol itself provides end-to-end confidentiality, authentication, and integrity of messages between communicating parties.
Servers have long-lived, self-signed, offline certificates whose hash is pre-shared with clients over secure channels - either provided with the client library or provided in the secure introduction between clients. The offline certificate signs an online certificate used in the transport protocol handshake. [0]
Servers have long-lived, self-signed, offline certificates whose hash is pre-shared with clients over secure channels - either provided with the client library or provided in the secure introduction between clients, as part of the server address. The offline certificate signs an online certificate used in the transport protocol handshake. [0]
If the transport protocol's confidentiality is broken, incoming and outgoing messages to the server cannot be correlated by message contents. Additionally, because of encryption at the SMP layer, impersonating the server is not sufficient to pass (and therefore correlate) a message from a sender to recipient - the only attack possible is to drop the messages. Only by additionally *compromising* the server can one pass and correlate messages.
It's important to note that the SMP protocol does not do server authentication. Instead we rely upon the fact that an attacker who tricks the transport protocol into authenticating the server incorrectly cannot do anything with the SMP messages except drop them.
After the connection is established, the client sends blocks of a fixed size 16Kb, and the server replies with the blocks of the same size to reduce metadata observable to a network adversary. The protocol has been designed to make traffic correlation attacks difficult, adapting ideas from Tor, remailers, and more general onion and mix networks. It does not try to replace Tor though - SimpleX servers can be deployed as onion services and SimpleX clients can communicate with servers over Tor to further improve participants privacy.
After the connection is established, the client sends blocks of a fixed size 16KB, and the server replies with the blocks of the same size to reduce metadata observable to a network adversary. The protocol has been designed to make traffic correlation attacks difficult, adapting ideas from Tor, remailers, and more general onion and mix networks. It does not try to replace Tor though - SimpleX servers can be deployed as onion services and SimpleX clients can communicate with servers over Tor to further improve participants privacy.
By using fixed-size blocks, oversized for the expected content, the vast majority of traffic is uniform in nature. When enough traffic is transiting a server simultaneously, the server acts as a (very) low-latency mix node. We can't rely on this behavior to make a security claim, but we have engineered to take advantage of it when we can. As mentioned, this holds true even if the transport connection is compromised.
By using fixed-size blocks, oversized for the expected content, the vast majority of traffic is uniform in nature. When enough traffic is transiting a server simultaneously, the server acts as a low-latency mix node. We can't rely on this behavior to make a security claim, but we have engineered to take advantage of it when we can. As mentioned, this holds true even if the transport connection is compromised.
The protocol does not protect against attacks targeted at particular users with known identities - e.g., if the attacker wants to prove that two known users are communicating, they can achieve it. At the same time, it substantially complicates large-scale traffic correlation, making determining the real user identities much less effective.
The protocol does not protect against attacks targeted at particular users with known identities - e.g., if the attacker wants to prove that two known users are communicating, they can achieve it by observing their local traffic. At the same time, it substantially complicates large-scale traffic correlation, making determining the real user identities much less effective.
[0] Future versions of SMP may add support for revocation lists of certificates, presently this risk is mitigated by the SMP protocol itself.
#### 2-hop Onion Message Routing
As SimpleX Messaging Protocol servers providing messaging queues are chosen by the recipients, in case senders connect to these servers directly the server owners (who potentially can be the recipients themselves) can learn senders' IP addresses (if Tor is not used) and which other queues on the same server are accessed by the user in the same transport connection (even if Tor is used).
While the clients support isolating the messages sent to different queues into different transport connections (and Tor circuits), this is not practical, as it consumes additional traffic and system resources.
To mitigate this problem SimpleX Messaging Protocol servers support 2-hop onion message routing when the SMP server chosen by the sender forwards the messages to the servers chosen by the recipients, thus protecting both the senders IP addresses and sessions, even if connection isolation and Tor are not used.
The design of 2-hop onion message routing prevents these potential attacks:
- MITM by proxy (SMP server that forwards the messages).
- Identification by the proxy which and how many queues the sender sends messages to (as messages are additionally e2e encrypted between the sender and the destination SMP server).
- Correlation of messages sent to different queues via the same user session (as random correlation IDs and keys are used for each message).
See more details about 2-hop onion message routing design in [SimpleX Messaging Protocol](./simplex-messaging.md#proxying-sender-commands)
Also see [Threat model](#threat-model)
#### SimpleX Messaging Protocol
SMP is initialized with an in-person or out-of-band introduction message, where Alice provides Bob with details of a server (including IP, port, and hash of the long-lived offline certificate), a queue ID, and Alice's public key for her receiving queue. These introductions are similar to the PANDA key-exchange, in that if observed, the adversary can race to establish the communication channel instead of the intended participant. [0]
SMP is initialized with an in-person or out-of-band introduction message, where Alice provides Bob with details of a server (including IP address or host name, port, and hash of the long-lived offline certificate), a queue ID, and Alice's public keys to agree e2e encryption. These introductions are similar to the PANDA key-exchange, in that if observed, the adversary can race to establish the communication channel instead of the intended participant. [0]
Because queues are uni-directional, Bob provides an identically-formatted introduction message to Alice over Alice's now-established receiving queue.
@@ -145,6 +172,7 @@ When setting up a queue, the server will create separate sender and recipient qu
[0] Users can additionally create public 'contact queues' that are only used to receive connection requests.
#### SimpleX Agents
SimpleX agents provide higher-level operations compared to SimpleX Clients, who are primarily concerned with creating queues and communicating with servers using SMP. Agent operations include:
@@ -157,9 +185,10 @@ SimpleX agents provide higher-level operations compared to SimpleX Clients, who
- Noise traffic
#### Encryption Primitives Used
- Ed448 to sign/verify commands to SMP servers (Ed25519 is also supported via client/server configuration).
- Ed25519 or Curve25519 to authorize/verify commands to SMP servers (authorization algorithm is set via client/server configuration).
- Curve25519 for DH exchange to agree:
- the shared secret between server and recipient (to encrypt message bodies - it avoids shared cipher-text in sender and recipient traffic)
- the shared secret between sender and recipient (to encrypt messages end-to-end in each queue - it avoids shared cipher-text in redundant queues).
@@ -170,42 +199,44 @@ SimpleX agents provide higher-level operations compared to SimpleX Clients, who
- AES-GCM AEAD cipher,
- SHA512-based HKDF for key derivation.
## Threat Model
#### Global Assumptions
- A user protects their local database and key material
- The user's application is authentic, and no local malware is running
- The cryptographic primitives in use are not broken
- A user protects their local database and key material.
- The user's application is authentic, and no local malware is running.
- The cryptographic primitives in use are not broken.
- A user's choice of servers is not directly tied to their identity or otherwise represents distinguishing information about the user.
- The user's client uses 2-hop onion message routing.
#### A passive adversary able to monitor the traffic of one user
*can:*
- identify that and when a user is using SimpleX
- identify that and when a user is using SimpleX.
- block SimpleX traffic
- determine which servers the user communicates with
- determine which servers the user receives the messages from.
- observe how much traffic is being sent, and make guesses as to its purpose.
*cannot:*
- see who sends messages to the user and who the user sends the messages to
- see who sends messages to the user and who the user sends the messages to.
- determine the servers used by users' contacts.
#### A passive adversary able to monitor a set of senders and recipients
*can:*
- identify who and when is using SimpleX
- identify who and when is using SimpleX.
- learn which SimpleX Messaging Protocol servers are used as receive queues for which users
- learn which SimpleX Messaging Protocol servers are used as receive queues for which users.
- learn when messages are sent and received
- learn when messages are sent and received.
- perform traffic correlation attacks against senders and recipients and correlate senders and recipients within the monitored set, frustrated by the number of users on the servers
- perform traffic correlation attacks against senders and recipients and correlate senders and recipients within the monitored set, frustrated by the number of users on the servers.
- observe how much traffic is being sent, and make guesses as to its purpose
@@ -217,43 +248,83 @@ SimpleX agents provide higher-level operations compared to SimpleX Clients, who
*can:*
- learn when a queue recipient or sender is online
- learn when a queue recipient is online
- know how many messages are sent via the queue (although some may be noise)
- know how many messages are sent via the queue (although some may be noise or not content messages).
- perform queue correlation (matching multiple queues to a single user) via either a re-used transport connection, user's IP Address, or connection timing regularities
- learn which messages would trigger notifications even if a user does not use [push notifications](./push-notifications.md).
- learn a user's IP address, track them through other IP addresses they use to access the same queue, and infer information (e.g. employer) based on the IP addresses, as long as Tor is not used.
- perform the correlation of the queue used to receive messages (matching multiple queues to a single user) via either a re-used transport connection, user's IP Address, or connection timing regularities.
- drop all future messages inserted into a queue, detectable only over other, redundant queues
- learn a recipient's IP address, track them through other IP addresses they use to access the same queue, and infer information (e.g. employer) based on the IP addresses, as long as Tor is not used.
- drop all future messages inserted into a queue, detectable only over other, redundant queues.
- lie about the state of a queue to the recipient and/or to the sender (e.g. suspended or deleted when it is not).
- spam a user with invalid messages
- spam a user with invalid messages.
*cannot:*
- undetectably add, duplicate, or corrupt individual messages
- undetectably add, duplicate, or corrupt individual messages.
- undetectably drop individual messages, so long as a subsequent message is delivered
- undetectably drop individual messages, so long as a subsequent message is delivered.
- learn the contents of messages
- learn the contents or type of messages.
- distinguish noise messages from regular messages except via timing regularities
- distinguish noise messages from regular messages except via timing regularities.
- compromise the user's end-to-end encryption with an active attack
- compromise the users' end-to-end encryption with an active attack.
- learn a sender's IP address, track them through other IP addresses they use to access the same queue, and infer information (e.g. employer) based on the IP addresses, even if Tor is not used (provided messages are sent via proxy SMP server).
- perform senders' queue correlation (matching multiple queues to a single sender) via either a re-used transport connection, user's IP Address, or connection timing regularities, unless it has additional information from the proxy SMP server (provided messages are sent via proxy SMP server).
#### SimpleX Messaging Protocol server that proxies the messages to another SMP server
*can:*
- learn a sender's IP address, as long as Tor is not used.
- learn when a sender with a given IP address is online.
- know how many messages are sent from a given IP address and to a given destination SMP server.
- drop all messages from a given IP address or to a given destination server.
- unless destination SMP server detects repeated public DH keys of senders, replay messages to a destination server within a single session, causing either duplicate message delivery (which will be detected and ignored by the receiving clients), or, when receiving client is not connected to SMP server, exhausting capacity of destination queues used within the session.
*cannot:*
- perform queue correlation (matching multiple queues to a single user), unless it has additional information from the destination SMP server.
- undetectably add, duplicate, or corrupt individual messages.
- undetectably drop individual messages, so long as a subsequent message is delivered.
- learn the contents or type of messages.
- learn which messages would trigger notifications.
- learn the destination queues of messages.
- distinguish noise messages from regular messages except via timing regularities.
- compromise the user's end-to-end encryption with another user via an active attack.
- compromise the user's end-to-end encryption with the destination SMP servers via an active attack.
#### An attacker who obtained Alice's (decrypted) chat database
*can:*
- see the history of all messages exchanged by Alice with her communication partners
- see the history of all messages exchanged by Alice with her communication partners.
- see shared profiles of contacts and groups
- see shared profiles of contacts and groups.
- surreptitiously receive new messages sent to Alice via existing queues; until communication queues are rotated or the Double-Ratchet advances forward
- surreptitiously receive new messages sent to Alice via existing queues; until communication queues are rotated or the Double-Ratchet advances forward.
- prevent Alice from receiving all new messages sent to her - either surreptitiously by emptying the queues regularly or overtly by deleting them
- prevent Alice from receiving all new messages sent to her - either surreptitiously by emptying the queues regularly or overtly by deleting them.
- send messages from the user to their contacts; recipients will detect it as soon as the user sends the next message, because the previous message hash wont match (and potentially wont be able to decrypt them in case they dont keep the previous ratchet keys).
@@ -269,41 +340,41 @@ SimpleX agents provide higher-level operations compared to SimpleX Clients, who
*can:*
- spam the user with messages
- spam the user with messages.
- forever retain messages from the user
- forever retain messages from the user.
*cannot:*
- cryptographically prove to a third-party that a message came from a user (assuming the users device is not seized)
- cryptographically prove to a third-party that a message came from a user (assuming the users device is not seized).
- prove that two contacts they have is the same user
- prove that two contacts they have is the same user.
- cannot collaborate with another of the user's contacts to confirm they are communicating with the same user
- cannot collaborate with another of the user's contacts to confirm they are communicating with the same user.
#### An attacker who observes Alice showing an introduction message to Bob
*can:*
- Impersonate Bob to Alice
- Impersonate Bob to Alice.
*cannot:*
- Impersonate Alice to Bob
- Impersonate Alice to Bob.
#### An attacker with Internet access
*can:*
- Denial of Service SimpleX messaging servers
- Denial of Service SimpleX messaging servers.
- spam a user's public “contact queue” with connection requests
- spam a user's public “contact queue” with connection requests.
*cannot:*
- send messages to a user who they are not connected with
- send messages to a user who they are not connected with.
- enumerate queues on a SimpleX server
- enumerate queues on a SimpleX server.
## Acknowledgements
+222
View File
@@ -0,0 +1,222 @@
Version 1, 2024-06-22
# Post-quantum resistant augmented double ratchet algorithm (PQDR)
## Table of contents
- [Overview](#overview)
- [Comparison with the other approaches](#comparison-with-the-other-approaches)
- [PQXDH for post-quantum key agreement](#pqxdh-for-post-quantum-key-agreement) (Signal)
- [Hybrid Signal protocol for post-quantum encryption](#hybrid-signal-protocol-for-post-quantum-encryption) (Tutanota)
- [Augmented double ratchet algorithm](#augmented-double-ratchet-algorithm)
- [Double ratchet with encrypted headers augmented with double PQ KEM](#double-ratchet-with-encrypted-headers-augmented-with-double-pq-kem)
- [Initialization](#initialization)
- [Encrypting messages](#encrypting-messages)
- [Decrypting messages](#decrypting-messages)
- [Implementation considerations](#implementation-considerations)
- [Chosen KEM algorithm](#chosen-kem-algorithm)
- [Summary](#summary)
## Overview
It is a reasonable assumption that "record-now-decrypt-later" attacks are ongoing, so the users want to use cryptographic schemes for end-to-end encryption that are augmented with some post-quantum algorithm that is believed to be resistant to quantum computers.
SimpleX Chat uses [double-ratchet with header encryption](https://signal.org/docs/specifications/doubleratchet/#double-ratchet-with-header-encryption) to provide end-to-end encryption to messages and files. This document describes augmented algorithm with post-quantum key encapsulation mechanism (KEM) making it resistant to quantum computers.
Double-ratchet algorithm is a state of the art solution for end to end encryption offering a set of qualities that is not present in any other algorithm:
- perfect forward secrecy, i.e. compromise of session or long term keys does not lead to the ability to decrypt any of the past messages.
- deniability (also known as repudiation), i.e. the fact that the recipient of the message while having the proof of message authenticity, cannot prove to a third party that the sender actually sent this message.
- break-in recovery (also know as post-compromise security or future secrecy), i.e. the ability of the end-to-end encryption security to recover from the compromise of the long term keys. This is achieved by generating a new random key pair whenever a new DH key is received (DH ratchet step).
It is desirable to preserve all these qualities when augmenting the algorithm with a post-quantum algorithm, and having these qualities resistant to both conventional and quantum computers.
## Comparison with the other approaches
### PQXDH for post-quantum key agreement
[The solution](https://signal.org/docs/specifications/pqxdh/) recently [introduced by Signal](https://signal.org/blog/pqxdh/) augments the initial key agreement ([X3DH](https://signal.org/docs/specifications/x3dh/)) that is made prior to double ratchet algorithm. This is believed to provide protection from "record-now-decrypt-later" attack, but if the attacker at any point obtains long term keys from any of the devices, the break-in recovery will not be post-quantum resistant, and the attacker with quantum computer will be able to decrypt all the subsequent messages.
### Hybrid Signal protocol for post-quantum encryption
[The solution](https://eprint.iacr.org/2021/875.pdf) [proposed by Tutanota](https://tutanota.com/blog/posts/pqmail-update/) aims to preserve the break-in recovery property of double ratchet, but in doing so it:
- replaces rather than augments DH key agreement with post-quantum KEM mechanism, making it potentially vulnerable to conventional computers.
- adds signature to the DH ratchet step, to compensate for not keeping DH key agreement, but losing the deniability property for some of the messages.
## Augmented double ratchet algorithm
The double ratchet algorithm is augmented with post-quantum KEM mechanism, preserving all properties of the double ratchet algorithm.
It is possible, because although double ratchet uses DH (which is a non-interactive key exchanges), it uses it "interactively", when the new DH keys are generated by both parties in turns. Parties of double-ratchet encrypted communication can run two post-quantum key encapsulation mechanisms in parallel with both DH and KEM key agreements in each DH ratchet step, making break-in recovery of double ratchet algorithm post-quantum resistant, without losing deniability or resistance to conventional computers.
Specifically, [double ratchet with encrypted headers](https://signal.org/docs/specifications/doubleratchet/#double-ratchet-with-header-encryption) is augmented with some post-quantum key encapsulation mechanism (KEM) as described below. A possible algorithm for PQ KEM is [NTRU-prime](https://ntruprime.cr.yp.to), that is currently adopted in SSH and has available implementations. It is important though that the proposed scheme can be used with any PQ KEM algorithm.
The downside of the scheme is its substantial size overhead, as the encapsulation key and encapsulated shared secret are added to the header of each message. For the algorithm described below NTRU-prime adds ~2-4kb to each message (depending on the key size and the chosen variant). See [this table](https://ntruprime.cr.yp.to/security.html) for key and ciphertext sizes and the assessment of the security level for various key sizes.
It is possible to reduce size overhead by using only one KEM agreement and making only one of two ratchet steps providing post-quantum resistant break-in recovery.
## Double ratchet with encrypted headers augmented with double PQ KEM
Algorithm below assumes that in addition to shared secret from the initial key agreement, there will be an encapsulation key available from the party that published its keys (Bob).
### Initialization
The double ratchet initialization is defined in pseudo-code. This pseudo-code is identical to Signal algorithm specification except for that parts that add post-quantum key agreement.
```
// Alice obtained Bob's keys and initializes ratchet first
def RatchetInitAlicePQ2HE(state, SK, bob_dh_public_key, shared_hka, shared_nhkb, bob_pq_kem_encapsulation_key):
state.DHRs = GENERATE_DH()
state.DHRr = bob_dh_public_key
// below added for post-quantum KEM
state.PQRs = GENERATE_PQKEM()
state.PQRr = bob_pq_kem_encapsulation_key
state.PQRss = random // shared secret for KEM
state.PQRct = PQKEM-ENC(state.PQRr, state.PQRss) // encapsulated additional shared secret
// above added for KEM
// the next line augments DH key agreement with PQ shared secret
state.RK, state.CKs, state.NHKs = KDF_RK_HE(SK, DH(state.DHRs, state.DHRr) || state.PQRss)
state.CKr = None
state.Ns = 0
state.Nr = 0
state.PN = 0
state.MKSKIPPED = {}
state.HKs = shared_hka
state.HKr = None
state.NHKr = shared_nhkb
// Bob initializes ratchet second, having received Alice's connection request
def RatchetInitBobPQ2HE(state, SK, bob_dh_key_pair, shared_hka, shared_nhkb, bob_pq_kem_key_pair):
state.DHRs = bob_dh_key_pair
state.DHRr = None
// below added for KEM
state.PQRs = bob_pq_kem_key_pair
state.PQRr = None
state.PQRss = None
state.PQRct = None
// above added for KEM
state.RK = SK
state.CKs = None
state.CKr = None
state.Ns = 0
state.Nr = 0
state.PN = 0
state.MKSKIPPED = {}
state.HKs = None
state.NHKs = shared_nhkb
state.HKr = None
state.NHKr = shared_hka
```
`GENERATE_PQKEM` generates decapsulation/encapsulation key pair.
`PQKEM-ENC` is key encapsulation algorithm.
Other than commented lines, the above adds parameters `bob_pq_kem_encapsulation_key` and `bob_pq_kem_key_pair` to the ratchet initialization. Otherwise it is identical to the original double ratchet initialization.
### Encrypting messages
```
def RatchetEncryptPQ2HE(state, plaintext, AD):
state.CKs, mk = KDF_CK(state.CKs)
// encapsulation key from PQRs and encapsulated shared secret is added to header
header = HEADER_PQ2(
dh = state.DHRs.public,
kem = state.PQRs.public, // added for KEM #2
ct = state.PQRct // added for KEM #1
pn = state.PN,
n = state.Ns,
)
enc_header = HENCRYPT(state.HKs, header)
state.Ns += 1
return enc_header, ENCRYPT(mk, plaintext, CONCAT(AD, enc_header))
```
Other than adding encapsulation key and encapsulated shared secret into the header, the above is identical to the original double ratchet message encryption step.
### Decrypting messages
```
def RatchetDecryptPQ2HE(state, enc_header, ciphertext, AD):
plaintext = TrySkippedMessageKeysHE(state, enc_header, ciphertext, AD)
if plaintext != None:
return plaintext
header, dh_ratchet = DecryptHeader(state, enc_header) // DecryptHeader is the same as in double ratchet specification
if dh_ratchet:
SkipMessageKeysHE(state, header.pn) // SkipMessageKeysHE is the same as in double ratchet specification
DHRatchetPQ2HE(state, header)
SkipMessageKeysHE(state, header.n)
state.CKr, mk = KDF_CK(state.CKr)
state.Nr += 1
return DECRYPT(mk, ciphertext, CONCAT(AD, enc_header))
// DecryptHeader is the same as in double ratchet specification
def DecryptHeader(state, enc_header):
header = HDECRYPT(state.HKr, enc_header)
if header != None:
return header, False
header = HDECRYPT(state.NHKr, enc_header)
if header != None:
return header, True
raise Error()
def DHRatchetPQ2HE(state, header):
state.PN = state.Ns
state.Ns = 0
state.Nr = 0
state.HKs = state.NHKs
state.HKr = state.NHKr
state.DHRr = header.dh
// save new encapsulation key from header
state.PQRr = header.kem
// decapsulate shared secret from header - KEM #2
ss = PQKEM-DEC(state.PQRs.private, header.ct)
// use decapsulated shared secret with receiving ratchet
state.RK, state.CKr, state.NHKr = KDF_RK_HE(state.RK, DH(state.DHRs, state.DHRr) || ss)
state.DHRs = GENERATE_DH()
// below is added for KEM
state.PQRs = GENERATE_PQKEM() // generate new PQ key pair
state.PQRss = random // shared secret for KEM
state.PQRct = PQKEM-ENC(state.PQRr, state.PQRss) // encapsulated additional shared secret KEM #1
// above is added for KEM
// use new shared secret with sending ratchet
state.RK, state.CKs, state.NHKs = KDF_RK_HE(state.RK, DH(state.DHRs, state.DHRr) || state.PQRss)
```
`PQKEM-DEC` is key decapsulation algorithm.
`DHRatchetPQ2HE` augments both DH agreements with decapsulated shared secret from the received header and with the new shared secret, respectively. The new shared secret together with the new encapsulation key are saved in the state and will be added to the header in the next sent message.
Other than augmenting DH key agreements with the shared secrets from KEM, the above is identical to the original double ratchet DH ratchet step.
It is worth noting that while DH agreements work as ping-pong, when the new received DH key is used for both DH agreements (and only the sent DH key is updated for the second DH key agreement), PQ KEM agreements in the proposed scheme work as a "parallel ping-pong", with two balls in play all the time (two KEM agreements run in parallel).
## Implementation considerations for SimpleX Messaging Protocol
As SimpleX Messaging Protocol pads messages to a fixed size, using 16kb transport blocks, the size increase introduced by this scheme can be compensated for by using ZSTD encryption of JSON bodies and image previews encoded as base64. While there may be some rare cases of random texts that would fail to compress, in all real scenarios it would not cause the message size reduction.
Sharing the initial keys in case of SimpleX Chat it is equivalent to sharing the invitation link. As encapsulation key is large, it may be inconvenient to share it in the link in some contexts, e.g. when QR codes are used.
It is possible to postpone sharing the encapsulation key until the first message from Alice (confirmation message in SMP protocol), the party sending connection request. The upside here is that the invitation link size would not increase. The downside is that the user profile shared in this confirmation will not be encrypted with PQ-resistant algorithm.
Another consideration is pairwise ratchets in groups. Key generation in sntrup761 is quite slow - on slow devices it can be as slow as 10-20 keys per second, so using this primitive in groups larger than 10-20 members would result in slow performance.
For backward compatibility the implementation must support adding PQ-resistant key agreement to the existing connections.
It is also beneficial to support removing PQ-resistant key agreement from the connections that have them, e.g. as the group size grows.
### Chosen KEM algorithm
The implementation uses Streamlined NTRU-Prime 761 (sntrup761) that was also used for OpenSSH for a long time.
It was chosen over ML-KEM (Kyber) standardized by NIST for several reasons:
- sntrup761 was used in OpenSSH for a long period of time.
- ML-KEM standardization process raised [concerns](https://groups.google.com/a/list.nist.gov/g/pqc-forum/c/WFRDl8DqYQ4) [amongst](https://blog.cr.yp.to/20231003-countcorrectly.html) the experts.
- ML-KEM (if modified) is likely to have conflicts with the existing patents, unlike sntrup761.
It was chosen over non-interactive CTIDH due to its slower implementation, and lack of optimized code for aarch64 CPUs used in mobile devices.
## Summary
If chosen PQ KEM proves secure against quantum computer attacks, then the proposed augmented double ratchet will also be secure against quantum computer attack, including break-in recovery property, while keeping deniability and forward secrecy, because the [same proof](https://eprint.iacr.org/2016/1013.pdf) as for double ratchet algorithm would hold here, provided chosen KEM is secure.
+398
View File
@@ -0,0 +1,398 @@
Version 2, 2024-06-22
# Overview of push notifications for SimpleX Messaging Servers
## Table of contents
- [Introduction](#introduction)
- [Participating servers](#participating-servers)
- [Register device token to receive push notifications](#register-device-token-to-receive-push-notifications)
- [Subscribe to connection notifications](#subscribe-to-connection-notifications)
- [SimpleX Notification Server protocol](#simplex-notification-server-protocol)
- [Register new notification token](#register-new-notification-token)
- [Verify notification token](#verify-notification-token)
- [Check notification token status](#check-notification-token-status)
- [Replace notification token](#replace-notification-token)
- [Delete notification token](#delete-notification-token)
- [Subscribe to periodic notifications](#subscribe-to-periodic-notifications)
- [Create SMP message notification subscription](#create-smp-message-notification-subscription)
- [Check notification subscription status](#check-notification-subscription-status)
- [Delete notification subscription](#delete-notification-subscription)
- [Error responses](#error-responses)
- [Threat model](#threat-model)
## Introduction
SimpleX Messaging servers already operate as push servers and deliver the messages to subscribed clients as soon as they are sent to the servers.
The reason for push notifications is to support instant message notifications on iOS that does not allow background services.
## Participating servers
The diagram below shows which servers participate in message notification delivery.
While push provider (e.g., APN) can learn how many notifications are delivered to the user, it cannot access message content, even encrypted, or any message metadata - the notifications are e2e encrypted between SimpleX Notification Server and the user's device.
```
User's iOS device Internet Servers
--------------------- . ------------------------ . -----------------------------
. .
. . can be self-hosted now
+--------------+ . . +----------------+
| SimpleX Chat | -------------- TLS --------------- | SimpleX |
| client |------> SimpleX Messaging Protocol (SMP) ------> | Messaging |
+--------------+ ---------------------------------- | Server |
^ | . . +----------------+
| | . . . . . | . . .
| | . . | V |
| | . . |SMP| TLS
| | . . | | | SimpleX
| | . . . . . V . . . NTF Server
| | . . +----------------------------------+
| | . . | +---------------+ |
| | -------------- TLS --------------- | | SimpleX | can be |
| |-----------> Notification Server Protocol -----> | | Notifications | self-hosted |
| ---------------------------------- | | Subscriber | in the future |
| . . | +---------------+ |
| . . | | |
| . . | V |
| . . | +---------------+ |
| . . | | SimpleX | |
| . . | | Push | |
| . . | | Server | |
| . . | +---------------+ |
| . . +----------------------------------+
| . . . . . | . . .
| . . | V |
| . . |SMP| TLS
| . . | | |
| . . . . . V . . .
| -------------- TLS --------------- +-----------------+
|----------------- Notification delivery <-------| Apple PN server |
---------------------------------- +-----------------+
. .
```
## Register device token to receive push notifications
This diagram shows the process of registering a device to receive PUSH notifications via Apple Push Notification (APN) servers.
![Register device notification token](./diagrams/notifications/register-token.svg)
## Subscribe to connection notifications
This diagram shows the process of subscription to notifications, notification delivery and device token update.
![Subscribe to notifications](./diagrams/notifications/subscription.svg)
## SimpleX Notification Server protocol
To manage notification subscriptions to SMP servers, SimpleX Notification Server provides an RPC protocol with a similar design to SimpleX Messaging Protocol server.
This protocol sends requests and responses in a fixed size blocks of 512 bytes over TLS, uses the same [syntax of protocol transmissions](./simplex-messaging.md#smp-transmission-and-transport-block-structure) as SMP protocol, and has the same transport [handshake syntax](./simplex-messaging.md#transport-handshake) (except the server certificate is not included in the handshake).
Protocol commands have this syntax:
```
ntfServerTransmission =
ntfServerCmd = newTokenCmd / verifyTokenCmd / checkTokenCmd /
replaceTokenCmd / deleteTokenCmd / cronCmd /
newSubCmd / checkSubCmd / deleteSubCmd
```
### Register new notification token
This command should be used after the client app obtains a token from push notifications provider to register the token with the server.
Having received this command the server will deliver a test notification via the push provider to validate that the client has this token.
The command syntax:
```abnf
newTokenCmd = %s"TNEW" SP newToken
newToken = %s"T" deviceToken authPubKey clientDhPubKey
deviceToken = pushProvider tokenString
pushProvider = apnsDev / apnsProd / apnsNull
apnsDev = "AD" ; APNS token for development environment
apnsProd = "AP" ; APNS token for production environment
apnsNull = "AN" ; token that does not trigger any notification delivery - used for server testing
tokenString = shortString
authPubKey = length x509encoded ; Ed25519 key used to verify clients commands
clientDhPubKey = length x509encoded ; X25519 key to agree e2e encryption between the server and client
shortString = length *OCTET
length = 1*1 OCTET
```
The server response syntax:
```abnf
tokenIdResp = %s"IDTKN" SP entityId serverDhPubKey
entityId = shortString
serverDhPubKey = length x509encoded ; X25519 key to agree e2e encryption between the server and client
```
### Verify notification token
This command is used to verify the token after the device receives the test notification from the push provider.
The command syntax:
```abnf
verifyTokenCmd = %s"TVFY" SP regCode
regCode = shortString
```
The response to this command is `okResp` or `errorResp`
```abnf
okResp = %s"OK"
```
### Check notification token status
This command is used to check the token status:
```abnf
checkTokenCmd = %s"TCHK"
```
The response to this command:
```abnf
tokenStatusResp = %s"TKN" SP tokenStatus
tokenStatus = %s"NEW" / %s"REGISTERED" / %s"INVALID" / %s"CONFIRMED" / %s"ACTIVE" / %s"EXPIRED"
```
### Replace notification token
This command should be used when push provider issues a new notification token.
It happens when:
- the app data is migrated to another device.
- the app is re-installed on the same device.
- can happen periodically, at push provider discretion.
This command allows to replace the token without re-registering and re-subscribing all notification subscriptions.
Using this command triggers the same verification flow as registering a new token.
The command syntax:
```abnf
replaceTokenCmd = %s"TRPL" SP deviceToken
```
The response to this command is `okResp` or `errorResp`.
### Delete notification token
The command syntax:
```abnf
deleteTokenCmd = %s"TDEL"
```
The response to this command is `okResp` or `errorResp`.
After this command all message notification subscriptions will be removed and no more notifications will be sent.
### Subscribe to periodic notifications
This command enables or disables periodic notifications sent to the client device irrespective of message notifications.
This is useful for two reasons:
- it provides better privacy from notification server, as while the server learns the device token, it doesn't learn anything else about user communications.
- it allows to receive messages when notifications were dropped by push provider, e.g. while the device was offline, or lost by notification server, e.g. while it was restarting.
The command syntax:
```abnf
cronCmd = %s"TCRN" SP interval
interval = 2*2 OCTET ; Word16, minutes
```
The interval for periodic notifications is set in minutes, with the minimum of 20 minutes. The client should pass `0` to disable periodic notifications.
### Create SMP message notification subscription
This command makes notification server subscribe to message notifications from SMP server and to deliver them to push provider:
```abnf
newSubCmd = %s"SNEW" newSub
newSub = %s "S" tokenId smpServer notifierId notifierKey
tokenId = shortString ; returned in response to `TNEW` command
smpServer = smpServer = hosts port fingerprint
hosts = length 1*host
host = shortString
port = shortString
fingerprint = shortString
notifierId = shortString ; returned by SMP server in response to `NKEY` SMP command
notifierKey = length x509encoded ; private key used to authorize requests to subscribe to message notifications
```
The response syntax:
```abnf
subIdResp = %s"IDSUB" SP entityId
```
### Check notification subscription status
This command syntax:
```abnf
checkSubCmd = %s"SCHK"
```
The response:
```abnf
subStatusResp = %s"SUB" SP subStatus
subStatus = %s"NEW" / %s"PENDING" / ; e.g., after SMP server disconnect/timeout while ntf server is retrying to connect
%s"ACTIVE" / %s"INACTIVE" / %s"END" / ; if another server subscribed to notifications
%s"AUTH" / subErrStatus
subErrStatus = %s"ERR" SP shortString
```
### Delete notification subscription
The command syntax:
```abnf
deleteSubCmd = %s"SDEL"
```
The response to this command is `okResp` or `errorResp`.
After this command no more message notifications will be sent from this queue.
### Error responses
All commands can return error response:
```abnf
errorResp = %s"ERR" SP errorType
```
Where `errorType` has the same syntax as in [SimpleX Messaging Protocol](./simplex-messaging.md#error-responses)
## Threat Model
This threat model compliments SimpleX Messaging Protocol [threat model](./overview-tjr.md#threat-model)
#### A passive adversary able to monitor the traffic of one user
*can:*
- identify that and a user is using SimpleX push notifications.
*cannot:*
- determine which servers a user subscribed to the notifications from.
#### A passive adversary able to monitor a set of senders and recipients
*can:*
- perform more efficient traffic correlation attacks against senders and recipients and correlate senders and recipients within the monitored set, frustrated by the number of users on the servers.
#### SimpleX Messaging Protocol server
*can:*
- learn which messages trigger push notifications.
- learn IP address of SimpleX notification servers used by the user.
- drop message notifications.
- spam a user with invalid notifications.
*cannot:*
- learn user device token for push notifications.
- learn which queues belong to the same users with any additional efficiency compared with not using push notifications.
#### SimpleX Notification Server subscribed to message notifications
*can:*
- learn a user device token.
- learn how many messaging queues and servers a user receives messages from.
- learn how many message notifications are delivered to the user from each queue.
- undetectably drop notifications.
- spam a user with background notifications.
*cannot:*
- learn queue addresses for receiving or sending messages.
- learn the contents or type of messages (not even encrypted).
- learn anything about messages sent without notification flag.
- spam a user with visible notifications (provided the client app can filter push notifications).
- add, duplicate, or corrupt individual messages that will be shown to the user.
#### SimpleX Notification Server subscribed ONLY to periodic notifications
*can:*
- learn a user device token.
- drop periodic notifications.
- spam a user with background notifications.
*cannot:*
- learn how many messaging queues and servers a user receives messages from.
- learn how many message notifications are delivered to the user from each queue.
- learn queue addresses for receiving or sending messages.
- learn the contents or type of messages (not even encrypted).
- learn anything about messages sent without notification flag.
- spam a user with visible notifications (provided the client app can filter push notifications).
- add, duplicate, or corrupt individual messages that will be shown to the user.
#### A users contact
*cannot:*
- determine if a user uses push notifications or not.
#### Push notification provider (e.g., APN)
*can:*
- learn that a user uses SimpleX app.
- learn how many notifications are delivered to user's device.
- drop notifications (in fact, APN coalesces notifications delivered while user's device is offline, delivering only the last one).
*cannot:*
- learn which SimpleX Messaging Protocol servers are used by a user (notifications are e2e encrypted).
- learn which or how many messaging queues a user receives notifications from.
- learn the contents or type of messages (not even encrypted, notifications only contain encrypted metadata).
#### An attacker with Internet access
*cannot:*
- register notification token not present on attacker's device.
- enumerate tokens or subscriptions on a SimpleX Notification Server.
File diff suppressed because it is too large Load Diff
+16
View File
@@ -0,0 +1,16 @@
Scheme name: xftp
Status: Provisional
Applications/protocols that use this scheme name:
This scheme is used for URIs of XFTP (SimpleX File Transfer Protocol) servers,
a client-server protocol for asynchronous file transfer via relays,
preserving file meta-data (including size and name) and content privacy.
Contact: Evgeny Poberezkin <ep@simplex.chat>
Change controller: Evgeny Poberezkin <ep@simplex.chat>
References:
The syntax for server URIs in the provisional specification for SimpleX File Transfer Protocol:
https://github.com/simplex-chat/simplexmq/blob/master/rfcs/2022-12-26-simplex-file-transfer.md#server-address-syntax
+632
View File
@@ -0,0 +1,632 @@
Version 2, 2024-06-22
# SimpleX File Transfer Protocol
## Table of contents
- [Abstract](#abstract)
- [Introduction](#introduction)
- [XFTP Model](#xftp-model)
- [Persistence model](#persistence-model)
- [XFTP procedure](#xftp-procedure)
- [File description](#file-description)
- [URIs syntax](#uris-syntax)
- [XFTP server URI](#xftp-server-uri)
- [File description URI](#file-description-URI)
- [XFTP qualities and features](#xftp-qualities-and-features)
- [Cryptographic algorithms](#cryptographic-algorithms)
- [File chunk IDs](#file-chunk-ids)
- [Server security requirements](#server-security-requirements)
- [Transport protocol](#transport-protocol)
- [TLS ALPN](#tls-alpn)
- [Connection handshake](#connection-handshake)
- [Requests and responses](#requests-and-responses)
- [XFTP commands](#xftp-commands)
- [Correlating responses with commands](#correlating-responses-with-commands)
- [Command authentication](#command-authentication)
- [Keep-alive command](#keep-alive-command)
- [File sender commands](#file-sender-commands)
- [Register new file chunk](#register-new-file-chunk)
- [Add file chunk recipients](#add-file-chunk-recipients)
- [Upload file chunk](#upload-file-chunk)
- [Delete file chunk](#delete-file-chunk)
- [File recipient commands](#file-recipient-commands)
- [Download file chunk](#download-file-chunk)
- [Acknowledge file chunk download](#acknowledge-file-chunk-download)
- [Threat model](#threat-model)
## Abstract
SimpleX File Transfer Protocol is a client-server protocol for asynchronous unidirectional file transmission.
It's designed with the focus on communication security, integrity and meta-data privacy, under the assumption that any part of the message transmission network can be compromised.
It is designed as a application level protocol to solve the problem of secure and private file transmission, making [MITM attacks][1] very difficult at any part of the file transmission system, and preserving meta-data privacy of the sent files.
## Introduction
The objective of SimpleX File Transfer Protocol (XFTP) is to facilitate the secure and private unidirectional transfer of files from senders to recipients via persistent file chunks stored by the xftp server.
XFTP is implemented as an application level protocol on top of HTTP2 and TLS.
The protocol describes the set of commands that senders and recipients can send to XFTP servers to create, upload, download and delete file chunks of several pre-defined sizes. XFTP servers SHOULD support chunks of 4 sizes: 64KB, 256KB, 1MB and 4MB (1KB = 1024 bytes, 1MB = 1024KB).
The protocol is designed with the focus on meta-data privacy and security. While using TLS, the protocol does not rely on TLS security by using additional encryption to achieve that there are no identifiers or ciphertext in common in received and sent server traffic, frustrating traffic correlation even if TLS is compromised.
XFTP does not use any form of participants' identities. It relies on out-of-band passing of "file description" - a human-readable YAML document with the list of file chunk locations, hashes and necessary cryptographic keys.
## XFTP Model
The XFTP model has three communication participants: the recipient, the file server (XFTP server) that is chosen and, possibly, controlled by the sender, and the sender.
XFTP server allows uploading fixed size file chunks, with or without basic authentication. The same party that can be the sender of one file chunk can be the recipient of another, without exposing it to the server.
Each file chunk allows multiple recipients, each recipient can download the same chunk multiple times. It allows depending on the threat model use the same recipient credentials for multiple parties, thus reducing server ability to understand the number of intended recipients (but server can still track IP addresses to determine it), or use one unique set of credentials for each recipient, frustrating traffic correlation on the assumption of compromised TLS. In the latter case, senders can create a larger number of recipient credentials to hide the actual number of intended recipients from the servers (which is what SimpleX clients do).
```
Sender Internet XFTP relays Internet Recipient
---------------------------- | ----------------- | ------------------- | ------------ | ----------
| | | |
| | (can be self-hosted) | |
| | +---------+ | |
chunk 1 ----- HTTP2 over TLS ------ | XFTP | ---- HTTP2 / TLS ----- chunk 1
|---> SimpleX File Transfer Protocol (XFTP) --> | Relay | ---> XFTP ------------->|
| --------------------------- +---------+ ---------------------- |
| | | | | |
| | | | | v
+----------+ | | +---------+ | | +-------------+
| Sending | ch. 2 ------- HTTP2 / TLS ------- | XFTP | ---- HTTP2 / TLS ---- ch. 2 | Receiving |
file ---> | XFTP | ------> XFTP ----> | Relay | ---> XFTP ------> | XFTP | ---> file
| Client | --------------------------- +---------+ ---------------------- | Client |
+----------+ | | | | +-------------+
| | | | | ^
| | | +---------+ | | |
| ------- HTTP2 / TLS ------- | XFTP | ---- HTTP2 / TLS ---- |
|-------------> XFTP ----> | Relay | ---> XFTP ------------->|
chunk N --------------------------- +---------+ --------------------- chunk N
| | (store file chunks) | |
| | | |
| | | |
```
When sender client uploads a file chunk, it has to register it first with one sender ID and multiple recipient IDs, and one random unique key per ID to authenticate sender and recipients, and also provide its size and hash that will be validated when chunk is uploaded.
To send the actual file, the sender client MUST pad it and encrypt it with a random symmetric key and distribute chunks of fixed sized across multiple XFTP servers. Information about chunk locations, keys, hashes and required keys is passed to the recipients as "[file description](#file-description)" out-of-band.
Creating, uploading, downloading and deleting file chunks requires sending commands to the XFTP server - they are described in detail in [XFTP commands](#xftp-commands) section.
## Persistence model
Server stores file chunk records in memory, with optional adding to append-only log, to allow restoring them on server restart. File chunk bodies can be stored as files or as objects in any object store (e.g. S3).
## XFTP procedure
1. Sending the file.
To send the file, the sender will:
1) Prepare file
- compute its SHA512 digest.
- prepend header with the name and pad the file to match the whole number of chunks in size. It is RECOMMENDED to use 2 of 4 allowed chunk sizes, to balance upload size and metadata privacy.
- encrypt it with a randomly chosen symmetric key and IV (e.g., using NaCL secret_box).
- split into allowed size chunks.
- generate per-recipient keys. It is recommended that the sending client generates more per-recipient keys than the actual number of recipients, rounding up to a power of 2, to conceal the actual number of intended recipients.
2) Upload file chunks
- register each chunk record with randomly chosen one or more (for redundancy) XFTP server(s).
- optionally request additional recipient IDs, if required number of recipient keys didn't fit into register request.
- upload each chunk to chosen server(s).
3) Prepare file descriptions, one per recipient.
The sending client combines addresses of all chunks and other information into "file description", different for each file recipient, that will include:
- an encryption key used to encrypt/decrypt the full file (the same for all recipients).
- file SHA512 digest to validate download.
- list of chunk descriptions; information for each chunk:
- private Ed25519 key to sign commands for file transfer server.
- chunk address (server host and chunk ID).
- chunk sha512 digest.
To reduce the size of file description, chunks are grouped by the server host.
4) Send file description(s) to the recipient(s) out-of-band, via pre-existing secure and authenticated channel. E.g., SimpleX clients send it as messages via SMP protocol, but it can be done via any other channel.
![Sending file](./diagrams/xftp/xftp-sending-file.svg)
2. Receiving the file.
Having received the description, the recipient will:
1) Download all chunks.
The receiving client can fall back to secondary servers, if necessary:
- if the server is not available.
- if the chunk is not present on the server (ERR AUTH response).
- if the hash of the downloaded file chunk does not match the description.
Optionally recipient can acknowledge file chunk reception to delete file ID from server for this recipient.
2) Combine the chunks into a file.
3) Decrypt the file using the key in file description.
4) Extract file name and unpad the file.
5) Validate file digest with the file description.
![Receiving file](./diagrams/xftp/xftp-receiving-file.svg)
## File description
"File description" is a human-readable YAML document that is sent via secure and authenticated channel.
It includes these fields:
- `party` - "sender" or "recipient". Sender's file description is required to delete the file.
- `size` - padded file size equal to total size of all chunks, see `fileSize` syntax below.
- `digest` - SHA512 hash of encrypted file, base64url encoded string.
- `key` - symmetric encryption key to decrypt the file, base64url encoded string.
- `nonce` - nonce to decrypt the file, base64url encoded string.
- `chunkSize` - default chunk size, see `fileSize` syntax below.
- `replicas` - the array of file chunk replicas descriptions.
- `redirect` - optional property for redirect information indicating that the file is itself a description to another file, allowing to use file description as a short URI.
Each replica description is an object with 2 fields:
- `chunks` - and array of chunk replica descriptions stored on one server.
- `server` - [server address](#xftp-server-uri) where the chunks can be downloaded from.
Each server replica description is a string with this syntax:
```abnf
chunkReplica = chunkNo ":" replicaId ":" replicaKey [":" chunkDigest [":" chunkSize]]
chunkNo = 1*DIGIT
; a sequential 1-based chunk number in the original file.
replicaId = base64url
; server-assigned random chunk replica ID.
replicaKey = base64url
; sender-generated random key to receive (or to delete, in case of sender's file description) the chunk replica.
chunkDigest = base64url
; chunk digest that MUST be specified for the first replica of each chunk,
; and SHOULD be omitted (or be the same) on the subsequent replicas
chunkSize = fileSize
fileSize = sizeInBytes / sizeInUnits
; chunk size SHOULD only be specified on the first replica and only if it is different from default chunk size
sizeInBytes = 1*DIGIT
sizeInUnits = 1*DIGIT sizeUnit
sizeUnit = %s"kb" / %s"mb" / %s"gb"
base64url = <base64url encoded binary> ; RFC4648, section 5
```
Optional redirect information has two fields:
- `size` - the size of the original encrypted file to which file description downloaded via the current file description will lead to, see `fileSize` syntax below.
- `digest` - SHA512 hash of the original file, base64url encoded string.
## URIs syntax
### XFTP server URI
The XFTP server address is a URI with the following syntax:
```abnf
xftpServerURI = %s"xftp://" xftpServer
xftpServer = serverIdentity [":" basicAuth] "@" srvHost [":" port]
srvHost = <hostname> ; RFC1123, RFC5891
port = 1*DIGIT
serverIdentity = base64url
basicAuth = base64url
```
### File description URI
This file description URI can be generated by the client application to share a small file description as a QR code or as a link. Practically, to be able to scan a QR code it should be under 1000 characters, so only file descriptions with 1-2 chunks can be used in this case. This is supported with `redirect` property when file description leads to a file which in itself is a larger file description to another file - akin to URL shortener.
File description URI syntax:
```abnf
fileDescriptionURI = serviceScheme "/file" "#/?desc=" description [ "&data=" userData ]
serviceScheme = (%s"https://" clientAppServer) | %s"simplex:"
clientAppServer = hostname [ ":" port ]
; client app server, e.g. simplex.chat
description = <URI-escaped YAML file description>
userData = <any URI-compatible string>
```
clientAppServer is not a server the client connects to - it is a server that shows the instruction on how to download the client app that will connect using this connection request. This server can also host a mobile or desktop app manifest so that this link is opened directly in the app if it is installed on the device.
"simplex" URI scheme in serviceScheme can be used instead of client app server. Client apps MUST support this URI scheme.
## XFTP qualities and features
XFTP stands for SimpleX File Transfer Protocol. Its design is based on the same ideas and has some of the qualities of SimpleX Messaging Protocol:
- recipient cannot see sender's IP address, as the file fragments (chunks) are temporarily stored on multiple XFTP relays.
- file can be sent asynchronously, without requiring the sender to be online for file to be received.
- there is no network of peers that can observe this transfer - sender chooses which XFTP relays to use, and can self-host their own.
- XFTP relays do not have any file metadata - they only see individual chunks, with access to each chunk authorized with anonymous credentials (using Edwards curve cryptographic signature) that are random per chunk.
- chunks have one of the sizes allowed by the servers - 64KB, 256KB, 1MB and 4MB chunks, so sending a large file looks indistinguishable from sending many small files to XFTP server. If the same transport connection is reused, server would only know that chunks are sent by the same user.
- each chunk can be downloaded by multiple recipients, but each recipient uses their own key and chunk ID to authorize access, and the chunk is encrypted by a different key agreed via ephemeral DH keys (NaCl crypto_box (SalsaX20Poly1305 authenticated encryption scheme ) with shared secret derived from Curve25519 key exchange) on the way from the server to each recipient. XFTP protocol as a result has the same quality as SMP protocol - there are no identifiers and ciphertext in common between sent and received traffic inside TLS connection, so even if TLS is compromised, it complicates traffic correlation attacks.
- XFTP protocol supports redundancy - each file chunk can be sent via multiple relays, and the recipient can choose the one that is available. Current implementation of XFTP protocol in SimpleX Chat does not support redundancy though.
- the file as a whole is encrypted with a random symmetric key using NaCl secret_box.
## Cryptographic algorithms
Clients must cryptographically authorize XFTP commands, see [Command authentication](#command-authentication).
To authorize/verify transmissions clients and servers MUST use either signature algorithm Ed25519 algorithm defined in RFC8709 or using deniable authentication scheme based on NaCL crypto_box (see Simplex Messaging Protocol).
To encrypt/decrypt file chunk bodies delivered to the recipients, servers/clients MUST use NaCL crypto_box.
Clients MUST encrypt file chunk bodies sent via XFTP servers using use NaCL crypto_box.
## File chunk IDs
XFTP servers MUST generate a separate new set of IDs for each new chunk - for the sender (that uploads the chunk) and for each intended recipient. It is REQUIRED that:
- These IDs are different and unique within the server.
- Based on random bytes generated with cryptographically strong pseudo-random number generator.
## Server security requirements
XFTP server implementations MUST NOT create, store or send to any other servers:
- Logs of the client commands and transport connections in the production environment.
- History of retrieved files.
- Snapshots of the database they use to store file chunks (instead clients can manage redundancy by creating chunk replicas using more than one XFTP server). In-memory persistence is recommended for file chunks records.
- Any other information that may compromise privacy or [forward secrecy][4] of communication between clients using XFTP servers.
## Transport protocol
- binary-encoded commands sent as fixed-size padded block in the body of HTTP2 POST request, similar to SMP and notifications server protocol transmission encodings.
- HTTP2 POST with a fixed size padded block body for file upload and download.
Block size - 4096 bytes (it would fit ~120 Ed25519 recipient keys).
The reasons to use HTTP2:
- avoid the need to have two hostnames (or two different ports) for commands and file uploads.
- compatibility with the existing HTTP2 client libraries.
The reason not to use JSON bodies:
- bigger request size, so fewer recipient keys would fit in a single request
- signature over command has to be outside of JSON anyway.
The reason not to use URI segments / HTTP verbs / REST semantics is to have consistent request size.
### ALPN to agree handshake version
Client and server use [ALPN extension][18] of TLS to agree handshake version.
Server SHOULD send `xftp/1` protocol name and the client should confirm this name in order to use the current protocol version. This is added to allow support of older clients without breaking backward compatibility and to extend or modify handshake syntax.
If the client does not confirm this protocol name, the server would fall back to v1 of XFTP protocol.
### Transport handshake
When a client and a server agree on handshake version using ALPN extension, they should proceed with XFTP handshake.
As with SMP, a client doesn't reveal its version range to avoid version fingerprinting. Unlike SMP, XFTP runs a HTTP2 protocol over TLS and the server can't just send its handshake right away. So a session handshake is driven by client-sent requests:
1. To pass initiative to the server, the client sends a request with empty body.
2. Server responds with its `paddedServerHello` block.
3. Clients sends a request containing `paddedClientHello` block,
4. Server sends an empty response, finalizing the handshake.
Once TLS handshake is complete, client and server will exchange blocks of fixed size (16384 bytes).
```abnf
paddedServerHello = <padded(serverHello, 16384)>
serverHello = xftpVersionRange sessionIdentifier serverCert signedServerKey ignoredPart
xftpVersionRange = minXftpVersion maxXftpVersion
minXftpVersion = xftpVersion
maxXftpVersion = xftpVersion
sessionIdentifier = shortString
; unique session identifier derived from transport connection handshake
serverCert = originalLength <x509encoded>
signedServerKey = originalLength <x509encoded> ; signed by server certificate
paddedClientHello = <padded(clientHello, 16384)>
clientHello = xftpVersion keyHash ignoredPart
; chosen XFTP protocol version - must be the maximum supported version
; within the range offered by the server
xftpVersion = 2*2OCTET ; Word16 version number
keyHash = shortString
shortString = length length*OCTET
length = 1*1OCTET
originalLength = 2*2OCTET
ignoredPart = *OCTET
```
In XFTP v2 the handshake is only used for version negotiation, but `serverCert` and `signedServerKey` must be validated by the client.
`keyHash` is the CA fingerprint used by client to validate TLS certificate chain and is checked by a server against its own key.
`ignoredPart` in handshake allows to add additional parameters in handshake without changing protocol version - the client and servers must ignore any extra bytes within the original block length.
For TLS transport client should assert that `sessionIdentifier` is equal to `tls-unique` channel binding defined in [RFC 5929][14] (TLS Finished message struct); we pass it in `serverHello` block to allow communication over some other transport protocol (possibly, with another channel binding).
### Requests and responses
- File sender:
- create file chunk record.
- Parameters:
- Ed25519 key for subsequent sender commands and Ed25519 keys for commands of each recipient.
- chunk size.
- Response:
- chunk ID for the sender and different IDs for all recipients.
- add recipients to file chunk
- Parameters:
- sender's chunk ID
- Ed25519 keys for commands of each recipient.
- Response:
- chunk IDs for new recipients.
- upload file chunk.
- delete file chunk (invalidates all recipient IDs).
- File recipient:
- download file chunk:
- chunk ID
- DH key for additional encryption of the chunk.
- command should be signed with the key passed by the sender when creating chunk record.
- delete file chunk ID (only for one recipient): signed with the same key.
## XFTP commands
Commands syntax below is provided using ABNF with case-sensitive strings extension.
```abnf
xftpCommand = ping / senderCommand / recipientCmd / serverMsg
senderCommand = register / add / put / delete
recipientCmd = get / ack
serverMsg = pong / sndIds / rcvIds / ok / file
```
The syntax of specific commands and responses is defined below.
### Correlating responses with commands
Commands are made via HTTP2 requests, responses to commands are correlated as HTTP2 responses.
### Command authentication
XFTP servers must authenticate all transmissions (excluding `ping`) by verifying the client signatures. Command signature should be generated by applying the algorithm specified for the file to the `signed` block of the transmission, using the key associated with the file chunk ID (recipient's or sender's depending on which file chunk ID is used).
### Keep-alive command
To keep the transport connection alive and to generate noise traffic the clients should use `ping` command to which the server responds with `pong` response. This command should be sent unsigned and without file chunk ID.
```abnf
ping = %s"PING"
```
This command is always sent unsigned.
data FileResponse = ... | FRPong | ...
```abnf
pong = %s"PONG"
```
### File sender commands
Sending any of the commands in this section (other than `register`, that is sent without file chunk ID) is only allowed with sender's ID.
#### Register new file chunk
This command is sent by the sender to the XFTP server to register a new file chunk.
Servers SHOULD support basic auth with this command, to allow only server owners and trusted users to create file chunks on the servers.
The syntax is:
```abnf
register = %s"FNEW " fileInfo rcvPublicAuthKeys basicAuth
fileInfo = sndKey size digest
sndKey = length x509encoded
size = 1*DIGIT
digest = length *OCTET
rcvPublicAuthKeys = length 1*rcvPublicAuthKey
rcvPublicAuthKey = length x509encoded
basicAuth = "0" / "1" length *OCTET
x509encoded = <binary X509 key encoding>
length = 1*1 OCTET
```
If the file chunk is registered successfully, the server must send `sndIds` response with the sender's and recipients' file chunk IDs:
```abnf
sndIds = %s"SIDS " senderId recipientIds
senderId = length *OCTET
recipientIds = length 1*recipientId
recipientId = length *OCTET
```
#### Add file chunk recipients
This command is sent by the sender to the XFTP server to add additional recipient keys to the file chunk record, in case number of keys requested by client didn't fit into `register` command. The syntax is:
```abnf
add = %s"FADD " rcvPublicAuthKeys
rcvPublicAuthKeys = length 1*rcvPublicAuthKey
rcvPublicAuthKey = length x509encoded
```
If additional keys were added successfully, the server must send `rcvIds` response with the added recipients' file chunk IDs:
```abnf
rcvIds = %s"RIDS " recipientIds
recipientIds = length 1*recipientId
recipientId = length *OCTET
```
#### Upload file chunk
This command is sent by the sender to the XFTP server to upload file chunk body to server. The syntax is:
```abnf
put = %s"FPUT"
```
Chunk body is streamed via HTTP2 request.
If file chunk body was successfully received, the server must send `ok` response.
```abnf
ok = %s"OK"
```
#### Delete file chunk
This command is sent by the sender to the XFTP server to delete file chunk from the server. The syntax is:
```abnf
delete = %s"FDEL"
```
Server should delete file chunk record, invalidating all recipient IDs, and delete file body from file storage. If file chunk was successfully deleted, the server must send `ok` response.
### File recipient commands
Sending any of the commands in this section is only allowed with recipient's ID.
#### Download file chunk
This command is sent by the recipient to the XFTP server to download file chunk body from the server. The syntax is:
```abnf
get = %s"FGET " rDhKey
rDhKey = length x509encoded
```
If requested file is successfully located, the server must send `file` response. File chunk body is sent as HTTP2 response body.
```abnf
file = %s"FILE " sDhKey cbNonce
sDhKey = length x509encoded
cbNonce = <nonce used in NaCl crypto_box encryption scheme>
```
Chunk is additionally encrypted on the way from the server to the recipient using a key agreed via ephemeral DH keys `rDhKey` and `sDhKey`, so there is no ciphertext in common between sent and received traffic inside TLS connection, in order to complicate traffic correlation attacks, if TLS is compromised.
#### Acknowledge file chunk download
This command is sent by the recipient to the XFTP server to acknowledge file reception, deleting file ID from server for this recipient. The syntax is:
```abnf
ack = %s"FACK"
```
If file recipient ID is successfully deleted, the server must send `ok` response.
In current implementation of XFTP protocol in SimpleX Chat clients don't use FACK command. Files are automatically expired on servers after configured time interval.
## Threat model
#### Global Assumptions
- A user protects their local database and key material.
- The user's application is authentic, and no local malware is running.
- The cryptographic primitives in use are not broken.
- A user's choice of servers is not directly tied to their identity or otherwise represents distinguishing information about the user.
#### A passive adversary able to monitor the traffic of one user
*can:*
- identify that and when a user is sending files over XFTP protocol.
- determine which servers the user sends/receives files to/from.
- observe how much traffic is being sent, and make guesses as to its purpose.
*cannot:*
- see who sends files to the user and who the user sends the files to.
#### A passive adversary able to monitor a set of file senders and recipients
*can:*
- learn which XFTP servers are used to send and receive files for which users.
- learn when files are sent and received.
- perform traffic correlation attacks against senders and recipients and correlate senders and recipients within the monitored set, frustrated by the number of users on the servers.
- observe how much traffic is being sent, and make guesses as to its purpose
*cannot, even in case of a compromised transport protocol:*
- perform traffic correlation attacks with any increase in efficiency over a non-compromised transport protocol
#### XFTP server
*can:*
- learn when file senders and recipients are online.
- know how many file chunks and chunk sizes are sent via the server.
- perform the correlation of the file chunks as belonging to one file via either a re-used transport connection, user's IP address, or connection timing regularities.
- learn file senders' and recipients' IP addresses, and infer information (e.g. employer) based on the IP addresses, as long as Tor is not used.
- delete file chunks, preventing file delivery, as long as redundant delivery is not used.
- lie about the state of a file chunk to the recipient and/or to the sender (e.g. deleted when it is not).
- refuse deleting the file when instructed by the sender.
*cannot:*
- undetectably corrupt file chunks.
- learn the contents, name or the exact size of sent files.
- learn approximate size of sent files, as long as more than one server is used to send file chunks.
- compromise the users' end-to-end encryption of files with an active attack.
#### An attacker who obtained Alice's (decrypted) chat database
*can:*
- see the history of all files exchanged by Alice with her communication partners, as long as files were not deleted from the database.
- receive all files sent and received by Alice that did not expire yet, as long as information about these files was not removed from the database.
- prevent Alice's contacts from receiving the files she sent by deleting all or some of the file chunks from XFTP servers.
#### A user's contact
*can:*
- spam the user with files.
- forever retain files from the user.
*cannot:*
- cryptographically prove to a third-party that a file came from a user (assuming the user's device is not seized).
- prove that two contacts they have is the same user.
- cannot collaborate with another of the user's contacts to confirm they are communicating with the same user, even if they receive the same file.
#### An attacker with Internet access
*can:*
- Denial of Service XFTP servers.
*cannot:*
- send files to a user who they are not connected with.
- enumerate file chunks on an XFTP server.
+15
View File
@@ -0,0 +1,15 @@
Scheme name: xrcp
Status: Provisional
Applications/protocols that use this scheme name:
This scheme is used for URIs of controller sessions via SimpleX Remote Control protocol (XRCP),
a protocol for remote access and management of hosts via insecure network.
Contact: Evgeny Poberezkin <ep@simplex.chat>
Change controller: Evgeny Poberezkin <ep@simplex.chat>
References:
The syntax for server URIs in the provisional specification for SimpleX File Transfer Protocol:
https://github.com/simplex-chat/simplexmq/blob/master/rfcs/2023-10-25-remote-control.md#session-invitation
+330
View File
@@ -0,0 +1,330 @@
Version 1, 2024-06-22
# SimpleX Remote Control Protocol
## Table of contents
- [Abstract](#abstract)
- [XRCP model](#xrcp-model)
- [Transport protocol](#transport-protocol)
- [Session invitation](#session-invitation)
- [Establishing TLS connection](#establishing-tls-connection)
- [Session verification and protocol negotiation](#session-verification-and-protocol-negotiation)
- [Controller/host session operation](#сontrollerhost-session-operation)
- [Key agreement for announcement packet and for session](#key-agreement-for-announcement-packet-and-for-session)
- [Threat model](#threat-model)
## Abstract
The SimpleX Remote Control Protocol is a client-server protocol designed to transform application UIs into thin clients, enabling remote control from another device. This approach allows users to remotely access and utilize chat profiles without the complexities of master-master replication for end-to-end encryption states.
Like SMP and XFTP, XRCP leverages out-of-band invitations to mitigate MITM attacks and employs multiple cryptographic layers to safeguard application data.
## XRCP model
XRCP assumes two application roles: host (that contain the application data) and controller that gains limited access to host data.
Applications are also split into two components: UI and core.
When an XRCP session is established a host UI is locked out and a controller UI uses its core to proxy commands to the host core, getting back responses and events.
```
+------+ +------+ xrcp +------+ +------+
| Ctrl | commands | Ctrl | commands | Host | | Host |
user ---> | UI | -----------> | Core | -----------> | Core | | UI |
+------+ +------+ +------+ +------+
^ responses | ^ xrcp responses | ^
|<------------------| |<-----------------| | +-------------+
| events | | | Application |-+
|<------------------| |----> | protocol | |
| servers | |
+-------------+ |
+--------------+
```
## Transport protocol
Protocol consists of four phases:
- controller session invitation
- establishing session TLS connection
- session verification and protocol negotiation
- session operation
![Session sequence](./diagrams/xrcp/session.svg)
### Session invitation
The invitation to the first session between host and controller pair MUST be shared out-of-band, to establish a long term identity keys/certificates of the controller to host device.
The subsequent sessions can be announced via an application-defined site-local multicast group, e.g. `224.0.0.251` (also used in mDNS/bonjour) and an application-defined port (SimpleX Chat uses 5227).
The session invitation contains this data:
- supported version range for remote control protocol.
- application-specific information, e.g. device name, application name and supported version range, settings, etc.
- session start time in seconds since epoch.
- if multicast is used, counter of announce packets sent by controller.
- network address (ipv4 address and port) of the controller.
- CA TLS certificate fingerprint of the controller - this is part of long term identity of the controller established during the first session, and repeated in the subsequent session announcements.
- Session Ed25519 public key used to verify the announcement and commands - this mitigates the compromise of the long term signature key, as the controller will have to sign each command with this key first.
- Long-term Ed25519 public key used to verify the announcement and commands - this is part of the long term controller identity.
- Session X25519 DH key and SNTRUP761 KEM encapsulation key to agree session encryption (both for multicast announcement and for commands and responses in TLS), as described in https://datatracker.ietf.org/doc/draft-josefsson-ntruprime-hybrid/. The new keys are used for each session, and if client key is already available (from the previous session), the computed shared secret will be used to encrypt the announcement multicast packet. The out-of-band invitation is unencrypted. DH public key and KEM encapsulation key are sent unencrypted. NaCL crypto_box is used for encryption.
Host application decrypts (except the first session) and validates the invitation:
- Session signature is valid.
- Timestamp is within some window from the current time.
- Long-term key signature is valid.
- Long-term CA and signature key are the same as in the first session.
- Some version in the offered range is supported.
OOB session invitation is a URI with this syntax:
```abnf
sessionAddressUri = "xrcp:/" encodedCAFingerprint "@" host ":" port "#/?" qsParams
encodedCAFingerprint = base64url
host = <ipv4 or ipv6 address> ; in textual form, RFC4001
port = 1*DIGIT ; uint16
qsParams = param *("&" param)
param = versionRangeParam / appInfoParam / sessionTsParam /
sessPubKeyParam / idPubKeyParam / dhPubKeyParam /
sessSignatureParam / idSignatureParam
versionRangeParam = "v=" (versionParam / (versionParam "-" versionParam))
versionParam = 1*DIGIT
appInfoParam = "app=" escapedJSON
sessionTsParam = "ts=" 1*DIGIT
sessPubKeyParam = "skey=" base64url
idPubKeyParam = "idkey=" base64url
dhPubKeyParam = "dh=" base64url
sessSignatureParam = "ssig=" base64url ; signs the URI with this and idSignatureParam param removed
idSignatureParam = "idsig=" base64url ; signs the URI with this param removed
base64url = <base64url encoded binary> ; RFC4648, section 5
```
Multicast session announcement is a binary encoded packet with this syntax:
```abnf
sessionAddressPacket = dhPubKey nonce encrypted(unpaddedSize sessionAddress packetPad)
dhPubKey = length x509encoded ; same as announced
nonce = length *OCTET
sessionAddress = largeLength sessionAddressUri ; as above
length = 1*1 OCTET ; for binary data up to 255 bytes
largeLength = 2*2 OCTET ; for binary data up to 65535 bytes
packetPad = <pad packet size to 1450 bytes> ; possibly, we may need to move KEM agreement one step later,
; with encapsulation key in HELLO block and KEM ciphertext in reply to HELLO.
```
### Establishing TLS connection
Both controller and host use 2-element certificate chains with unique self-signed CA root representing long-term identities. Leaf certificates aren't stored and instead generated on each session start.
A controller runs a TCP server to avoid opening listening socket on a host, which might create an attack vector. A controller keeps no sensitive data to be exposed this way.
During TLS handshake, parties validate certificate chains against previously known (from invitation or storage) CA fingerprints. The fingerprints MUST be the same as in the invitation and in the subsequent connections.
### Session verification and protocol negotiation
Once TLS session is established, both the host and controller devices present a "session security code" to the user who must match them (e.g., visually or via QR code scan) and confirm on the host device. The session security code must be a digest of tlsunique channel binding. As it is computed as a digest of the TLS handshake for both the controller and the host, it will validate that the same TLS certificates are used on both sides, and that the same TLS session is established, mitigating the possibility of MITM attack in the connection.
Once the session is confirmed by the user, the host sends HELLO block to the controller.
XRCP blocks inside TLS are padded to 16384 bytes.
Host HELLO block must contain:
- new session DH key - used to compute new shared secret with the controller keys from the announcement.
- encrypted part of HELLO block (JSON object), containing:
- chosen protocol version.
- host CA TLS certificate fingerprint - part of host long term identity - must match the one presented in TLS handshake and the previous sessions, otherwise the connection is terminated.
- KEM encapsulation key - used to compute new shared secret for the session.
- additional application specific parameters, e.g host device name, application version, host settings or JSON encoding format.
Host HELLO block syntax:
```abnf
hostHello = %s"HELLO " dhPubKey nonce encrypted(unpaddedSize hostHelloJSON helloPad) pad
unpaddedSize = largeLength
dhPubKey = length x509encoded
pad = <pad block size to 16384 bytes>
helloPad = <pad hello size to 12888 bytes>
largeLength = 2*2 OCTET
```
The controller decrypts (including the first session) and validates the received HELLO block:
- Chosen versions are supported (must be within offered ranges).
- CA fingerprint matches the one presented in TLS handshake and the previous sessions - in subsequent sessions TLS connection should be rejected if the fingerprint is different.
[JTD schema](https://www.rfc-editor.org/rfc/rfc8927) for the encrypted part of host HELLO block `hostHelloJSON`:
```json
{
"definitions": {
"version": {
"type": "string",
"metadata": {
"format": "[0-9]+"
}
},
"base64url": {
"type": "string",
"metadata": {
"format": "base64url"
}
}
},
"properties": {
"v": {"ref": "version"},
"ca": {"ref": "base64url"},
"kem": {"ref": "base64url"}
},
"optionalProperties": {
"app": {"properties": {}, "additionalProperties": true}
},
"additionalProperties": true
}
```
The controller should reply with with `ctrlHello` or `ctrlError` response:
```abnf
ctrlHello = %s"HELLO " kemCiphertext nonce encrypted(unpaddedSize ctrlHelloJSON helloPad) pad
; ctrlHelloJSON is encrypted with the hybrid secret,
; including both previously agreed DH secret and KEM secret from kemCiphertext
unpaddedSize = largeLength
kemCiphertext = largeLength *OCTET
pad = <pad block size to 16384 bytes>
helloPad = <pad hello size to 12888 bytes>
largeLength = 2*2 OCTET
ctrlError = %s"ERROR " nonce encrypted(unpaddedSize ctrlErrorMessage helloPad) pad
ctrlErrorMessage = <utf-8 encoded text>; encrypted using previously agreed DH secret.
```
JTD schema for the encrypted part of controller HELLO block `ctrlHelloJSON`:
```json
{
"properties": {},
"additionalProperties": true
}
```
Once the controller replies HELLO to the valid host HELLO block, it should stop accepting new TCP connections.
### Controller/host session operation
The protocol for communication during the session is out of scope of this protocol.
SimpleX Chat uses HTTP2 encoding, where host device acts as a server and controller acts as a client (these roles are reversed compared with TLS connection, restoring client-server semantics in HTTP).
Payloads in the protocol must be encrypted using NaCL secret_box using the hybrid shared secret agreed during session establishment.
Commands of the controller must be signed after the encryption using the controller's session and long term Ed25519 keys.
tlsunique channel binding from TLS session MUST be included in commands (included in the signed body).
The syntax for encrypted command and response body encoding:
```abnf
commandBody = encBody sessSignature idSignature [attachment]
responseBody = encBody [attachment] ; counter must match command
encBody = nonce encLength32 encrypted(tlsunique counter body)
attachment = %x01 nonce encLength32 encrypted(attachment)
noAttachment = %x00
tlsunique = length 1*OCTET
counter = 8*8 OCTET ; int64
encLength32 = 4*4 OCTET ; uint32, includes authTag
```
If the command or response includes attachment, its hash must be included in command/response and validated.
## Key agreement for announcement packet and for session
Initial announcement is shared out-of-band (URI with xrcp scheme), and it is not encrypted.
This announcement contains only DH keys, as KEM key is too large to include in QR code, which are used to agree encryption key for host HELLO block. The host HELLO block will contain DH key in plaintext part and KEM encapsulation (public) key in encrypted part, that will be used to determine the shared secret (using SHA256 over concatenated DH shared secret and KEM encapsulated secret) both for controller HELLO response (that contains KEM ciphertext in plaintext part) and subsequent session commands and responses.
During the next session the announcement is sent via encrypted multicast block. The shared key for this announcement and for host HELLO block is determined using the KEM shared secret from the previous session and DH shared secret computed using the host DH key from the previous session and the new controller DH key from the announcement.
For the session, the shared secret is computed again using the KEM shared secret encapsulated by the controller using the new KEM key from the host HELLO block and DH shared secret computed using the host DH key from HELLO block and the new controller DH key from the announcement.
In pseudo-code:
```
// session 1
hostHelloSecret(1) = dhSecret(1)
sessionSecret(1) = sha256(dhSecret(1) || kemSecret(1)) // to encrypt session 1 data, incl. controller hello
dhSecret(1) = dh(hostHelloDhKey(1), controllerInvitationDhKey(1))
kemCiphertext(1) = enc(kemSecret(1), kemEncKey(1))
// kemEncKey is included in host HELLO, kemCiphertext - in controller HELLO
kemSecret(1) = dec(kemCiphertext(1), kemDecKey(1))
// multicast announcement for session n
announcementSecret(n) = sha256(dhSecret(n'))
dhSecret(n') = dh(hostHelloDhKey(n - 1), controllerDhKey(n))
// session n
hostHelloSecret(n) = dhSecret(n)
sessionSecret(n) = sha256(dhSecret(n) || kemSecret(n)) // to encrypt session n data, incl. controller hello
dhSecret(n) = dh(hostHelloDhKey(n), controllerDhKey(n))
// controllerDhKey(n) is either from invitation or from multicast announcement
kemCiphertext(n) = enc(kemSecret(n), kemEncKey(n))
kemSecret(n) = dec(kemCiphertext(n), kemDecKey(n))
```
If controller fails to store the new host DH key after receiving HELLO block, the encryption will become out of sync and the host won't be able to decrypt the next announcement. To mitigate it, the host should keep the last session DH key and also previous session DH key to try to decrypt the next announcement computing shared secret using both keys (first the new one, and in case it fails - the previous).
To decrypt a multicast announcement, the host should try to decrypt it using the keys of all known (paired) remote controllers.
## Threat model
#### A passive network adversary able to monitor the site-local traffic:
*can:*
- observe session times, duration and volume of the transmitted data between host and controller.
*cannot:*
- observe the content of the transmitted data.
- substitute the transmitted commands or responses.
- replay transmitted commands or events from the hosts.
#### An active network adversary able to intercept and substitute the site-local traffic:
*can:*
- prevent host and controller devices from establishing the session
*cannot:*
- same as passive adversary, provided that user visually verified session code out-of-band.
#### An active adversary with the access to the network:
*can:*
- spam controller device.
*cannot:*
- compromise host or controller devices.
#### An active adversary with the access to the network who also observed OOB announcement:
*can:*
- connect to controller instead of the host.
- present incorrect data to the controller.
*cannot:*
- connect to the host or make host connect to itself.
#### Compromised controller device:
*can:*
- observe the content of the transmitted data.
- access any data of the controlled host application, within the capabilities of the provided API.
*cannot:*
- access other data on the host device.
- compromise host device.
#### Compromised host device:
*can:*
- present incorrect data to the controller.
- incorrectly interpret controller commands.
*cannot:*
- access controller data, even related to this host device.
+33
View File
@@ -0,0 +1,33 @@
# Transmission encryption
## Problems
### Protection of meta-data from sending proxy
The SEND commands and message queue IDs need to be encrypted so that sending proxy cannot see how many queues exist on each server.
Correlation IDs need to be random and can be re-used as nonces so that the destination relay cannot use the increasing correlation IDs that are sent in v6 of the protocol to track the sender.
### Protection of the traffic from the attacker who compromised TLS
Currently, even though different sending and receiving queue IDs are used, the attacker who compromised TLS could do statistical analysis and in this way correlate queue IDs of senders and recipients, and therefore correlate the senders and recipients.
## Possible solutions
1. Encrypt sent messages, other commands and their responses in the additional envelope, irrespective of whether proxy is used or not. In this case the requestion transmission could have this syntax:
```abnf
encReqTransmission = pubKey nonce encrypted(reqTransmission)
reqTransmission = respNonce entityId command
encRespTransmission = replyNonce encrypted(respTransmission)
respTransmission = entityId command
```
The keys to encrypt and decrypt both the command and responses would be computed as curve25519 from the key sent together with command and server session key. For the requests, the nonce has to be random and sent outside of the encrypted envelopt, but for the response respNonce would be taken from inside of the encrypted envelope and it would also be used for correlating commands and responses. This way the attacker who could compromise TLS would not be able to correlate the commands and responses, and also observe entity IDs.
2. The remaining question is to how encrypt and decrypt messages delivered not in response to the commands.
The possible options are:
- restore client session key only for that purpose, but do not forward this key to the destination proxy for sent messages. Then the messages can be sent with a random replyNonce and the key would be computed from session keys. The advantage here is that we won't need to parameterize handles as both client and server would have session keys. The downside that we would have to either somehow differentiate messages and responses, either by some flag that would allow some correlation or just by the absense of replyNonce in the lookup map - that is if the client can find replyNonce, it would use the associated key to decrypt, and if not it would use session key.
- use the same key that was sent with SUB or ACK command. This is much more complex, and would only have some upside if we were to introduce receiving proxies (to conceal transport sessions from the receiving relays for the recipients).
+130
View File
@@ -0,0 +1,130 @@
# Relay metadata and SimpleX network decentralization
## Problem
Currently, the clients configure/choose which servers to use, but they cannot see who operates them, in which geography and hosting provider, what is the server source code (in case it was modified from the reference implementation we provide) and also any administrative and feedback contacts.
Further, we currently use simplex.chat domain to host group links, and as diversity of the groups grows it is beginning to require managing feedback from the users about groups. It is important that this feedback is directed to relay owners and not to us, in case they are not our relays, as we are simply providing software here.
We also need to make it much easier to access administrative actions - e.g., if the relay owner wants to block some address based on the feedback, they should be able to do so effectively. While freedom of speech of users is important the autonomy and sovereignty of relay operators allowing them to decide what they want or don't want to host, irrespective of the reasons, is as important - public relays constitute a public space rather than a service, and while there is no authentication or authorization required to use them, the relay owners should be able to decide their conditions and limitations of use, as is the case for any public space.
## Why it is important
1. We are building network and not a service, so contrary to the traditional approach when service collects users metadata and conceals its own, it appears important to do the opposite - expose all relay metadata that may have any effect on users privacy and security and provide access to this metadata with the minimal friction, via the app UI.
2. We need to remove the only remaining bit of centralization - using simplex.chat website to show the QR code and help new users onboarding - this role can be delegated to the relays.
3. We need to make it easy for the users to submit feedback and to the relay operators to manage that feedback. That includes ourselves, as relay operators, and also any other person or organization that operates public relays.
4. It is important to stress the requirement of AGPLv3 license to provide access to the source code to the relay users, as any code modifications might undermine user privacy and security and must be made transparent to the relay users.
While this document is not the end of the journey to decentralize the network, it's an important first step.
## Proposed solution
The proposed solution consists of two parts:
- communicate server metadata via protocol, so it can be observed by the clients.
- create home page for the relays, with all the same metadata.
- create invitation and address links in the same domain name as the relay.
The latter point is important so it is clear to the users who operates and owns the relay and where the access point to the content or group is hosted. Even though simplex.chat domain is never accessed by the app, and the meaningful part of the address is never sent to the page hosting server, it creates an impression of centralization, and some dependency on simplex.chat domain for anything other that showing the link QR code.
Moving invitation links to the domain of the relay (primary relay, in case the link has redundancy) will both clarify relay ownership, solve the incorrect mis-perception of centralization, remove the dependency on simplex-chat domain without any user effort, and provides the means to submit content complaints to the relay operators (should they wish to receive them, which seems reasonable for large public relays, but may be unnecessary for private relays where unidentified parties cannot create links).
## Solution details
Extend server INI file with information section:
```
[INFORMATION]
# Please note that under AGPLv3 license conditions you MUST make
# any source code modifications available to the end users of the server.
# LICENSE: https://github.com/simplex-chat/simplexmq/blob/stable/LICENSE
# Not doing so would constitute a license violation.
# Declaring an incorrect information here amounts to a fraud.
# The license holders reserve the right to prosecute missing or incorrect
# information about the server source code to the fullest extent permitted by the law.
# The server will show warning on start if this field is absent
# and will not launch from v6.0 until this field is added.
# If any other information field is present, source code property also MUST be present.
source_code: https://github.com/simplex-chat/simplexmq
# Declaring all below information is optional, any of these fields can be omitted.
# Declaring an incorrect information here would amount to a fraud.
# We should split this document to the model one, where specific parameters will be external to the document,
# and specific to us, so that relay operators can adopt our recommended policy and publish any amendments separately.
usage_conditions: https://github.com/simplex-chat/simplex-chat/blob/_archived-ep/ios-file-provider/PRIVACY.md
# condition_amendments: link
server_country: SE
operator: SimpleX Chat Ltd.
operator_country: GB # operator country
website: https://simplex.chat
admin_simplex: administrative SimpleX address
admin_email: chat@simplex.chat
admin_pgp: PGP key
complaints_simplex: SimpleX address for feedback, comments and complaints
complaints_email: complaints@simplex.chat
complaints_pgp: PGP key
hosting: Linode / Akamai Inc.
hosting_country: US
```
Server home page would show whether queue creation is allowed and/or password protected, server retention policy (e.g., preserve messages on restart or not, and persist connections or not).
Server queue address/contact pages will optionally, provide the UI to submit feedback, comments and complaints directly from the web page (not an MVP, initially we would simply show addresses for feedback, and, probably, create link that opens in the app with pre-populated message, and we could also use this addresses defined in server meta-data to submit feedback from inside of the app - it's also out of MVP scope).
If server is available on .onion address, the web pages would show "open via .onion" in Tor browser.
Extend server handshake header with these information fields:
```haskell
data ServerHandshake = ServerHandshake
{ smpVersionRange :: VersionRangeSMP,
sessionId :: SessionId,
-- pub key to agree shared secrets for command authorization and entity ID encryption.
authPubKey :: Maybe (X.CertificateChain, X.SignedExact X.PubKey),
-- ^^ existing fields
-- vv new field that will be sent as length-prefixed JSON in the handshake
information :: Maybe ServerInformation
}
data ServerInformation = ServerInformation
{ config :: ServerPublicConfig,
info :: ServerPublicInfo
}
-- based on server configuration
data ServerPublicConfig = ServerPublicConfig
{ persistence :: SMPServerPersistenceMode,
messageExpiration :: Int,
statsEnabled :: Bool,
newQueuesAllowed :: Bool,
basicAuthEnabled :: Bool -- server is private if enabled
}
-- based on INFORMATION section of INI file
data ServerPublicInfo = ServerPublicInfo
{ sourceCode :: Text, -- note that this property is not optional, in line with AGPLv3 license
conditions :: Maybe ServerConditions,
operator :: Maybe Entity,
website :: Maybe Text,
adminContacts :: Maybe ServerContactAddress,
complaintsContacts :: Maybe ServerContactAddress,
hosting :: Maybe Entity,
serverCountry :: Maybe Text
}
data ServerPersistenceMode = SMPMemoryOnly | SPMQueues | SPMQueuesMessages
data ServerConditions = ServerConditions {conditions :: Text, amendments :: Maybe Text}
data Entity = Entity {name :: Text, country :: Maybe Text}
data ServerContactAddress = ServerContactAddress
{ simplex :: Maybe Text,
email :: Maybe Text, -- it is recommended that it matches DNS email address, if either is present
pgp :: Maybe Text
}
```
This extended server information will be stored in the chat database every time it changes and shown in the UI of the server configuration.
+19
View File
@@ -0,0 +1,19 @@
# Evolving agent API
## Problem
Historically, agent API started as a TCP protocol with encoding. We do not use the actual protocol and maintaining the encoding complicates the evolution of the API.
Currently, I was trying to add ERRS event to combine multiple subscription errors into one to prevent overloading the UI with processing multiple subscription errors (e.g.):
```haskell
ERRS :: (ConnId, AgentErrorType) -> ACommand Agent AEConn
```
This constructor is not possible to encode/parse in a sensible way other than including lengths of errors.
## Proposal
Remove commands type and encodings for commands and events.
Only keep encodings for the commands that are saved to the database: NEW, JOIN, LET, ACK, SWCH, DEL (this one is no longer used but needs to be supported for backwards compatibility).
+18
View File
@@ -0,0 +1,18 @@
# iOS notifications stability
## Problem
iOS notifications may fail to deliver for several reasons, but there are two important reasons that we could address:
- when notification server is not subscribed to SMP server(s), the notifications can be dropped - it can happen because either notification server restarts or becuase SMP server restarted and some messages are received before notification server resubscribed. We lose approximately 3% of notifications because of this reason.
- when user device is offline or has low power condition, Apple does not deliver notification, but puts them to storage. If while the notification is in storage a new one arrives it would overwrite the previous notification. If it was the message to the same message queue, the client will download messages anyway, up to a limit, but if the message was to another queue, it will not be delivered until the app is opened. Apple delivers about 88% of notifications that should be delivered (not accounting for uninstalled apps), the rest is replaced with the newer notifications.
## Solution
The first problem can be solved by preserving notifications for a limited time (say 1 hour) in case there is no subscription to notification from notification server. At the very least, they can be preserved in SMP server memory but can also be stored to a file on restart, similar to messages, and be delivered when notification server resubscribes. It is sufficient to store one notification per messaging queue.
The second problem is both more damaging and more complex to solve. The solution could be to always deliver several last notifications to different queues in one packet (Apple allows up to ~4-5kb notification size, and we are sending packets of fixed size 512 bytes, so we could fit up to 8-10 of them in each notification).
Every time a client receives such batch of notifications if can:
- check if that notification was already received in the previous batch.
- if it was received, it would be ignored, otherwise it would be processed.
- process them one by one, started from the most recent one while the time allows.
+27
View File
@@ -0,0 +1,27 @@
# SMP Basic Auth
## Problem
Users who host their own servers do not want unknown people to be able to create messaging queues on their servers after discovering server address in groups or after making a connection. As the number of self-hosted servers is growing it became more important than it was when we excluded it from the original design.
## Solution
Single access password that can be optionally included in server address that is passed to app configuration. It will not be allowed in the existing contexts (and parsing will fail), to avoid accidentally leaking it. Server address with password will look this way: `smp://fingerprint:password@hosts`
## Implementation plan
1. A separate type to include server and password, so it can only be used where allowed.
2. Server password to create queues will be configured in TRANSPORT section of INI file, as `create_password` parameter.
3. The password will only be required in server configuration/address to create queues only, it won't be required for other receiving queue operations on already existing queues.
4. If new command is attempted in the session that does not allow creating queues, the server will send `ERR AUTH` response
5. Passing password to the server can be done in one of the several ways, we need to decide:
- as a parameter of NEW command. Pros: a local change, that only needs checking when queue is created. Cons: protocol version change.
- as a separate command AUTH. Pros: allows to include additional parameters and potentially be extended beyond basic auth. Cons: more complex to manage server state, can be more difficult syntax in the future, if extended.
- as part of handshake (we currently ignore the unparsed part of handshake block, so it can be extended). Pros: probably, the simplest, and independent of the commands protocol establishes create permission for the current session. Cons: the client won't know about whether it is able to create the queue until it tries (same as in case 1).
My preference is the last option. As a variant of the last option, we can add a server response/message that includes permission to create queues - it will only be sent to the clients who pass credential in handshake - that might simplify testing server connection (we currently do not do it). It might be unnecessary, as we could simply create and delete queue in case credential is passed as part of testing connection (and even sending a message to it).
@@ -0,0 +1,173 @@
# SimpleX File Transfer protocol
## Problem
Sending files as currently implemented in SimpleX Chat is inefficient for these reasons:
1. Slow: message delivery requires acknowledgement for each message before the server sends the next message.
2. Not fully asynchronous:
a. SMP queue size is limited, so the whole file cannot be sent/stored in server memory.
b. Recipient needs to accept the file before it is sent.
3. No broadcast: sending the same file to multiple recipients requires sending it multiple times.
## Possible solutions
These problems could be solved within SMP protocol:
- streaming messages without waiting for acknowledgements.
- bigger queue sizes stored on hard drive and accepting large files without waiting for the recipient confirmation.
- adding broadcast to SMP servers.
These solution are complex and they do not scale well.
Another approach would be adopting some open-source file storage, possibly S3-compatible, to host files while "in transit". The downsides are:
1. Missing features. S3-compatible file servers require a service layer that we would need to develop to manage user accounts and permissions. There are solutions that allow self-registering users and uploading files without service layer, but they are not flexible enough in managing policies for these files.
2. Limited meta-data protection, both on the application and on transport layer: same address for sending and receiving a file, file size is known to the server, etc.
3. More difficult to self-host for the users when the server has 2 components (a 3rd party solution with our service component).
We are not considering P2P solutions because of their bad meta-data privacy and requirement of having a single network - the same reason why P2P design is not used for SimpleX messaging network.
A proposed solution is to develop a file hosting service (SimpleX File Transfer service) that would have better meta-data protection and functionality than the alternatives, using the ideas from SMP protocol design.
The parameters of the solution would be:
1. The server does not have knowledge of the users and actual files only anonymously uploaded fixed-size chunks (considered 8Mb, maybe we should allow 2 sizes, e.g. 1Mb and 8Mb).
2. The server should allow broadcast, so that a chunk can be downloaded by multiple recipients.
3. There should be no identifiers and ciphertext in common inside TLS between sender and recipient traffic, and between the traffic of different recipients of the same file. This approach can be extended to support public chunks that have persistent identifiers.
4. The server should prevent multiple uploads of the same chunk. This can be extended to allow multiple downloads from the same persistent address.
5. Clients can send the chunks from the same file via multiple servers, both by splitting chunks between them and for redundancy.
## Design approach
File transfer servers will be chosen by file senders. The servers will allow senders to anonymously upload fixed-size file chunks.
### Transport protocol
- binary-encoded commands sent as fixed-size padded block in the body of HTTP2 POST request, similar to SMP and notifications server protocol transmission encodings.
- HTTP2 POST with a fixed size padded block body for file upload and download.
Block size - 4096 bytes (it would fit ~120 Ed25519 recipient keys).
The reasons to use HTTP2:
- avoid the need to have two hostnames (or two different ports) for commands and file uploads.
- compatibility with the existing HTTP2 client libraries.
The reason not to use JSON bodies:
- bigger request size, so fewer recipient keys would fit in a single request
- signature over command has to be outside of JSON anyway.
The reason not to use URI segments / HTTP verbs / REST semantics is to have consistent request size.
### Required server commands:
- File sender:
- create file chunk record.
- Parameters:
- Ed25519 key for subsequent sender commands and Ed25519 keys for commands of each recipient.
- chunk size.
- Response:
- chunk ID for the sender and different IDs for all recipients.
- add recipients to file chunk
- Parameters:
- sender's chunk ID
- Ed25519 keys for commands of each recipient.
- Response:
- chunk IDs for new recipients.
- upload file chunk.
- delete file chunk (invalidates all recipient IDs).
- File recipient:
- download file chunk:
- chunk ID
- DH key for additional encryption of the chunk.
- command should be signed with the key passed by the sender when creating chunk record.
- delete file chunk ID (only for one recipient): signed with the same key.
### Storage model
Same as for SMP and notifications server - in-memory storage of the records, with adding to append-only log, restored and compacted on server restart.
### Sending file
To send the file, the sender will:
- compute SHA512 digest
- pad the file to match the whole number of chunks in size,
- encrypt it with a randomly chosen symmetric key and IV (e.g., using NaCL crypto_secretbox),
- split into fixed size chunks
- upload each chunk to a randomly chosen server.
The sending client should generate more per-recipient keys than the actual number of recipients, possibly rounding up to a power of 2, to conceal the actual number of intended recipients.
Then the sending client will combine addresses of all chunks and other information into "file description", different for each file recipient, that will include:
- an encryption key that was used to encrypt the file (the same for all recipients).
- file SHA512 digest
- list of chunk descriptions; information for each chunk:
- private Ed25519 key to sign commands for file transfer server.
- chunk address (server host and chunk ID).
- chunk sha512 digest
To reduce the size, chunk descriptions will be grouped by the server host.
This "file description" itself will be sent as a small file over an authenticated channel, to prevent file description modification. To estimate its size:
- each chunk \* redundancy per chunk, assuming chunks are grouped per server:
- 1-based chunk number in the file - 8 bytes (including any overhead)
- Ed25519 key (different for each recipient / chunk combination) - 32 bytes \* 4/3 (base64, assuming text encoding)
- chunk ID (different for each recipient) - 64 bytes \* 4/3
- optional (only in the first chunk occurence) chunk sha512 digests - 64 bytes \* 4/3
- server addresses - say, 128 bytes per server
- sha512 digest - 64 bytes \* 4/3
- encryption key - 32 bytes \* 4/3
- IV - 32 bytes \* 4/3
- encoding overhead - say, 256 bytes
For 1gb file, sent via 4 different servers, in 8Mb chunks, with redundancy 2, the size of "file description", assuming text encoding, will be ~45kb (`128 * (8 + 32 + 64) * 2 * 4/3 + 128 * 64 * 4/3 + 128 * 4 + (64 + 32 + 32) * 4/3 + 256`).
File description format (yml):
```
name: file.ext
size: 33200000
chunk: 8mb
hash: abc=
key: abc=
iv: abc=
parts:
- server: xftp://abc=@example1.com
chunks: [1:abc=:def=:ghi=, 3:abc=:def=:ghi=]
- server: xftp://abc=@example2.com
chunks: [2:abc=:def=:ghi=, 4:abc=:def=:ghi=:2mb]
- server: xftp://abc=@example3.com
chunks: [1:abc=:def=, 4:abc=:def=]
- server: xftp://abc=@example4.com
chunks: [2:abc=:def=, 3:abc=:def=]
```
This file description is sent to all recipients via normal messages, split to 15780 byte chunks if needed.
### Server address syntax
The server address is a URI with the following format:
```abnf
xftpServerURI = %s"xftp://" xftpServer
xftpServer = serverIdentity "@" srvHost [":" port]
srvHost = <hostname> ; RFC1123, RFC5891
port = 1*DIGIT
serverIdentity = base64url
base64url = <base64url encoded binary> ; RFC4648, section 5
```
### Receiving file
Having received the description, the recipient will:
- download all chunks falling back to secondary servers, if needed
- combine the chunks into a file
- decrypt the file
- un-pad it
- validate file digest
+20
View File
@@ -0,0 +1,20 @@
# SMP and SMP agent protocol extensions to manage queue quotas
## Problem
SMP servers define a limit on the number of messages that can be stored on the server. When the sender reaches this limit, they continue trying to send the message with exponential back off, until the server allows it. To reduce the traffic we added expiration on unsent messages of 2 days that:
- adds its own set of problems because of expired control messages - e.g., group fragmentation.
- doesn't solve problem of traffic in active groups with many inactive members - there are still too many retries in queues that reached capacity.
## Solution
Sending agent permanently stops trying to send messages having received `ERR QUOTA` (or, for the period of clients migration, increases TTL much more than in cases of network errors).
Add SMP server event that means "quota reached" (e.g. `QTA` or `MSG QUOTA`) - it will be delivered to the recipient once all messages are retrieved at the same point in message stream where the sender received `ERR QUOTA`. Alternatively, it could be a message flag that is set on the last message in the queue at a point the sender received `ERR QUOTA`.
Add SMP agent message that means "quota available, resume sending" (e.g. `A_QTA` or `A_RESUME`) the receiving agent will send it via the reply queue to the sending agent that will resume sending messages at this point.
Possibly, increase TTL for local messages to 30 days. That might require separately addressing the problem of permanently failing servers.
We discussed a possible solution of merging all messages to one server into one delivery queue, so that having multiple failing queues on this server will not result in multiple connection attempts, and this proposal also answers the question what to do with the messages when quota is exceeded - the whole queue can be marked as suspended, and processed separately from others - TBD.
+58
View File
@@ -0,0 +1,58 @@
# Re-sync encryption ratchets, queue rotation, message delivery receipts
This is very unfocussed doc outlining several problems that seem somewhat related, and some possible solution approaches.
## Problems
When old database backup is used, the sending client encrypts the messages in a way that the receiving client cannot decrypt them, because it does not store the old keys, and does not try to decrypt ratchet headers using the old keys. When receiving the messages, the client that uses the old database is unable to decrypt them, either the header or the message itself (if more than 500 messages are skipped, or if root ratchet step happened).
The same symptoms happen during the queue rotation, unfortunately, as we do not keep the history of received messages once they are acknowledged, so the client reports these error to the users.
While these are two different problems, to the users they manifest in the same way, so it is difficult to differentiate.
Another ratchet problem that should be solved as well is not deleting unused skipped keys after some time or some number of events, possibly it should be considered at the same time.
While it is tempting to consider delivery receipts as an isolated problem, it is somewhat coupled, as the requests to re-sync ratchets and to re-deliver skipped messages are effectively delivery receipts.
A naive solution to delivery receipts when each message is responded to with a confirmation has two downsides:
- it doubles the traffic.
- in the absense of delays, it also leaks some information about the network latency, that can be used to track user's location.
Both problems can be mitigated by sending delivery receipts with a random delay, to confirm all messages sent, not each one. But this would only reduce the traffic when the sender sends many messages. Alternatively, we could think how to reduce the block size for SMP commands. The challenge is profile pictures and image previews, so to reduce traffic we need to start sending them as XFTP files, potentially with a smaller 64kb chunks (that would also increase preview quality).
## Solution for queue rotation
We need to:
- store and show the rotation status in the UI to prevent attempts to rotate the queue multiple times.
- process multiple message delivery events while there is a redundancy, to avoid errors in terminal.
- differentiate between decryption errors during queue rotation - that would require keeping the messages for some time, at least keeping their IDs and hashes together with some additional status. In this case when duplicate or old message arrives, we can check whether this message was already processed, and do not show error if it was.
## Solution to re-sync ratchets
When we establish that the receiving client is indeed unable to decrypt messages, we should:
- notify the user - it is already happening, but it happens in case of rotation as well.
- optionally, notify another client that message was not decrypted - this effectively becomes a delivery receipt. That could be a separate command triggered by the user in the UI.
- clients can get into this state at the same time, how do we handle concurrent requests? Possibly, we could design these messages so this is irrelevant whether the message is sent in response or not, and calculate the new ratchet keys once the clients have both the sent and received messages. After that both clients can send "ratchet reset" message:
- EKEY - message containing a new set of keys to initialize the ratchets
- EREADY - message confirming that the ratchet is ready, already e2e encrypted
The downside of this approach, is that unlike the initial handshake, where the second ratchet key is sent in e2e encrypted response, this message will be sent only encrypted with queue key. We could change this protocol by adding EREPLY message, and the clients would know to ingnore EKEY with bigger hash of the keys, so that the client who sent keys with smaller hash would be processing response from another client (that is if EKEY is received after EKEY is sent).
```
A B
EKEY 1 -> <- EKEY 2 (e2e encrypted with per-queue key only)
EKEY 2 <- -> EKEY 1
1 < 2, wait 2 > 1, reply EREPLY 3 (e2e encrypted with ratchets)
ratchet: 1, 3 ratchet: 3, 1
```
Once ratchets are re-synched the clients could additionally request delivery of skipped messages. As ratchets being out of sync is not the only problem when messages can be lost, it may be managed independently from the ratchet re-sync. This problem seems tied with delivery receipts too, as requesting to re-deliver some messages automatically confirms that some other messages were delivered.
Alternatively, the request for ratchet sync can already contain the ID of the first failed message - that would allow the agent:
- stop sending messages until ratchets are in sync.
- re-deliver failed messages first.
- only then deliver any pending messages.
This approach would probably result in a better UX (no out of order delivery), but requires tracking pending messages that are not attempted to deliver and to also insert old messages in the delivery queue with the old IDs.
+170
View File
@@ -0,0 +1,170 @@
# Delivery receipts
## Problems
User experience - users need to know that the messages are delivered to the recipient, as this confirms that the system is functioning.
The downside of communicating message delivery as it confirms that the recipient was online, and, unless there is a delay in confirming, can be used to track the location via the variation in network latency. So delivery receipts should be delayed with a randomized interval and should be opt in or opt out.
Another problem of message receipts is that they increase network traffic and server load. This could be avoided if delivery receipts are communicated as part of normal message delivery flow.
Some other existing and planned features implicitely confirm message delivery and, possibly, should depend on message delivery being enabled:
- agent message to resume delivery when quota was exceeded (implemented, [rfc](./2022-12-27-queue-quota.md))
- agent message to re-deliver skipped messages or to re-negotiate double ratchet.
## Solution
There are three layers where delivery receipts can be implemented:
- chat protocol. Pro: logic of when to deliver it is decoupled from the message flow, Con: extra traffic, can only work in duplex connections.
- agent client protocol. Pro: can be automated and combined with the protocol to re-deliver skipped messages. Con: extra traffic.
- SMP protocol. Pro: minimal extra traffic, Con: complicates server design as it would require pushing receipts when there is no next message.
The last approach seems the most promising for avoiding additional traffic:
- modify client ACK command to include whether delivery receipt should be provided to sender, and, possibly, any e2e encrypted data that should be included in the receipt (e.g., that the receiving client already saw this message in case we use "feedback" variant of roumor-mongering protocol for groups).
- server would manage delaying of the receipts, by randomizing the time after which the receipt will be available to the sender, and by combining the receipts when possible.
- modify response to SEND command to include any available delivery receipts.
- add a separate delivery receipt that will be pushed to the sender in the connection where the message was received by the server.
## SMP protocol changes
```haskell
data Command (p :: Party) where
-- ...
ACK :: MsgId -> Maybe ByteString -> Command Recipient
-- the presense of ByteString in ACK indicates that the delivery needs to be confirmed.
-- the protocol does not define the format of this confirmation, it is application specific, and can be -- an empty string.
-- And open question is how to e2e encrypt information in this string - this probably can be handled on Agent client protocol level, and could be the same ratchet key that was used to encrypt and decrypt the message. The downside of this approach is that this key currently is not stored, and storing it requires additional logic to clear these keys if unused after some time.
-- TODO consider what could be a better approach.
SENT :: MsgId -> [(MsgId, UTCTime, ByteString)] -> Command Sender
-- or
-- SENT :: MsgId -> Command Sender
-- in case we just batch
-- this response will be sent to SEND command and will include a sender's message ID generated by the server (currently it does not exist), and posibly an empty list of delivery receipts with the same message IDs as in responses to SEND, timestamps when these receipts became available, and e2e encrypted ByteString passed in ACK command.
-- The ID in this response should be different from the ID used in MSG, to keep the promise of not having shared identifiers in sent/received traffic even inside TLS tunnel.
-- Keeping the quality of shared ciphertext also requires adding additional encryption layer between the server and the sender, this can be achieved in one of two ways:
-- 1) passing a separate DH key in each SEND command, and server including additional DH key in each SENT response, with computed DH secret per message later used to encrypt and decrypt the delivery receipt payloads. This is probably a bad idea as it would increase a cryptographic load on both the server and the client.
-- 2) agree a key per queue, in the same way it is done for the recipient. Possibly, it requires additional DH key in confirmation message that the recipient then uses to secure the queue, and passing this key in KEY (secure queue) command. The response to this secure command would the include server's DH key returned to the recipient that would be passed to the sender in HELLO message. Even though recipient could observe both public DH keys, they won't know the computed shared secret. Recipient that controls the server could perform MITM attack on this key exchange, but it doesn't give any benefit over what recipient can do when they have access to the server - the threat model remains the same. The downside of this approach is that it also requires additional changes in client protocol level (confirmation message format and HELLO message).
-- 3) also agree on a key per queue, but via separate commands between the sender and the server, once the sender was notified that the queue is secured. This approach is probably better, and the server would simply delay the delivery of delivery receipts until the shared secret is agreed.
SKEY :: C.PublicKeyX25519 -> Command Sender
SBKEY :: C.PublicKeyX25519 -> BrokerMsg
-- these are the command and response to agree secret to encrypt delivery receipt payloads for option 3
SSUB :: Command Sender
-- subscribe to receive delivery receipts for a given queue - will be sent when the conversation is opened (unless there is an active subscription already), not all queues at once, and won't be re-subscribed on losing the server connection (TBC).
RCVD :: MsgId -> UTCTime -> ByteString -> Command Recipient
-- delivery receipt. UTCTime is the time when it became available, not the time when ACK was sent by the recipient, to avoid leaking location via network latency.
```
Possibly, there is no need to include delivery receipts into SENT response and instead just use batching of responses that is already supported. As server responses are not signed, there is no per-response overhead that is substantial, and a lot of receipts that are available can be packed into one block (depending on the size of payload that has to be fixed not to leak metadata).
This all seems rather complicated for SMP protocol, and the approach of doing it on a higher level seems more attractive than initially. Possibly we should reconsider, and reduce traffic by reducing block sizes... Reducing block sizes unfortunately requires supporting variable block sizes, and would leak some metadata during the transition period.
## Another approach
Above represents substantial complexity, and at least doubles server code complexity for the feature that is definitely not doubling the value of server software. Moving to variable block size is simpler, but also has a lot of complexity, reduces metadata privacy (at least for the duration of migration period), reduces image preview quality, and requires postponing this feature for multiple releases, until all clients migrate.
Given that the main traffic is generated by the groups, and direct messages do not create a lot of traffic, a much simpler and better solution is to simply send delivery receipts as the message, in direct conversations only, either as chat protocol message or as agent client protocol message (either on the message or on the envelope layer).
### Comparison of these two approaches:
**Chat protocol message**
Pros:
- simpler, more contained change - SMP layer is not aware of this feature
- easier to extend protocol with additional application specific payload, e.g. references to group DAG
Cons:
- ?
```json
// ...
"x.msg.delivered": {
"properties": {
"msgId": {"ref": "base64url"},
"params": {
"properties": {
"msgId": {"ref": "base64url"},
},
"optionalProperties": {
"data": {} // possibly the initial protocol does not need it, with JSON can be added later
}
}
}
},
// ...
```
**Agent client protocol envelope**
Pros:
- possibility of using it in a wider range of the applications
- possibility to include received message hash to increase communication integrity - the sending client would be then notified, and it can be exposed in the UI, that the received message is not the same as sent.
Cons:
- additional implementation complexity - requires additional events to communicate between chat and agent.
```haskell
data AMessage =
-- ...
| A_RCVD AgentMsgId MsgHash ByteString -- references to the received message
-- ...
```
The weirdness of the above design is that it refers to the data present in the header of another message, the alternative would be to have a separate envelope for delivery receipt:
```haskell
data AgentMessage =
-- ...
AgentMessageRcvd APrivHeader AgentMsgId MsgHash ByteString -- references to the received message
-- ...
```
But probably the first one is a bit better, TBC.
In any case there should be an additional event to notify chat client:
```haskell
data ACommand (p :: AParty) (e :: AEntity) where
-- ...
RCVD AgentMsgId MsgMeta ByteString -> ACommand Agent AEConn
-- ...
```
On the balance of things, implementing on the level of Agent Client protocol seems better, as the additional complexity is marginal, but it allows for wider range of applications, and also allows for additional delivery integrity validation. The format for payload still requires chat protocol message encoding once we want to add it, but initially it could be just an empty string.
## Implementation plan
Currently, we delete sent messages once delivered to the server. It would be helpful if we could keep the records in snd_messages table, and then use them to process delivery receipts, although it may be insufficient (we could add fields). Probably it is not possible to keep them as there is a foreign key constraint with `on delete cascade`.
The new table will be used to track sent message hashes to correlate their IDs with delivery receipts (that will also be stored in messages/rcv_messages). Receipts need to be processed in chat in the same way as normal messages, so they would be sent to chat with MsgMeta, and the chat will need to ack them once processed.
Agent ackMessage function will be also used to automatically schedule sending delivery receipts if they are enabled for connection, only for normal messages - no sending receipts to receipts.
There can be receipt re-delivery to the chat in the same cases as when normal message can be re-delivered (in case of AGENT A_DUPLICATE when it was not ack'd by the user).
## Other considerations
### How clients decide whether to send delivery receipts
Two options are possible - local settings per conversation or chat preferences framework, that allows to have mutual on/off. The latter seems preferable as without knowing whether the other party is sending receipts, it is not possible to uderstand what the absense of the receipt means - network malfunction or receipts disabled.
Groups are a special case, as while some groups may enable sending the delivery receipts, the group members should be able to disable it locally. This should probably be done via a separate conversation setting in the same way as enabling notifications or favourites. In this case the receipt would only be sent to the group if it is enabled in the group and not disabled by the member. The toggle may be located in the same page as chat preferences, but it should be a separate setting. We might want though to communicate somehow whether a given member sends delivery receipts so that other members know whether to expect them or not.
### How this functionality is released
5.2:
- support for sending and receiving delivery receipts preference, both in direct messages and in groups (for forward compatibility).
- support for sending and receiving delivery receipts in direct chats only, but disable sending them
5.3:
- show receipt preferences in the UI
- enable sending receipts in direct chats where they are enabled
A separate question is how to enable this functionality for the existing contacts. Possible options are:
1. Enable (as per default) for all contacts, show notification to the user when they open the app for update that delivery notifications are now sent by default to all contacts. Pro: no extra logic to implement. Con: may be perceived as a privacy violation, as to some contacts the delivery receipts will be sent before the user had chance to disable them.
2. Ask the user when the new version first runs whether they want to use delivery receipts and offer these options:
1) keep enabled for all profiles (and for all contacts)
2) enable for all profiles in ~12 or in ~24 hours giving users the chance to review all contacts / profiles and disable some of them. The problem here is also in possibility of the correlation in case they all start sending receipts at the same time. Possibly the option could be to set a random time in 12-15 or 24-30 hours range to avoid the possibility of such correlation.
3) disable for all profiles it will require sending profile updates to all contacts, so the delivery receipts should be kept disabled and profile updates should be sent after random intervals, one by one (not scheduled all at once, as the time may pass while the app is off).
3. Offer an option to enable globally later - we could keep it as a one-off option, available only to existing users, and visible on the top level of the Settings - once enabled, the option will disappear and it won't be possible to disable again. The downside here is that the new contacts would be receiving the profile with enabled notifications but they still won't be delivered...
4. Another option is to have all new contacts decided based on a global user default (that can be set in the settings and in the dialog on first start), but for the existing contacts keep in unset state that is not interpreted as either on or off, but interpreted as unknown until the user makes a choice... That might be an optimal solution for the users but it would probably require changing the preferences framework or some ad-hoc hacks. That still keeps the question open how to avoid correlation between profiles.
5. That might be the case for version agreement too - the availability of the option per contact will depend on the version. It doesn't answer the question what to do with global defaults though...

Some files were not shown because too many files have changed in this diff Show More