rename remaining occurrences of connection alias into connection id (#265)
This commit is contained in:
parent
d87ff42cf5
commit
5e57c5dfd7
|
@ -6,7 +6,7 @@ CREATE TABLE servers (
|
|||
) WITHOUT ROWID;
|
||||
|
||||
CREATE TABLE connections (
|
||||
conn_alias BLOB NOT NULL PRIMARY KEY,
|
||||
conn_id BLOB NOT NULL PRIMARY KEY,
|
||||
conn_mode TEXT NOT NULL,
|
||||
last_internal_msg_id INTEGER NOT NULL DEFAULT 0,
|
||||
last_internal_rcv_msg_id INTEGER NOT NULL DEFAULT 0,
|
||||
|
@ -22,7 +22,7 @@ CREATE TABLE rcv_queues (
|
|||
host TEXT NOT NULL,
|
||||
port TEXT,
|
||||
rcv_id BLOB NOT NULL,
|
||||
conn_alias BLOB NOT NULL REFERENCES connections ON DELETE CASCADE,
|
||||
conn_id BLOB NOT NULL REFERENCES connections ON DELETE CASCADE,
|
||||
rcv_private_key BLOB NOT NULL,
|
||||
rcv_dh_secret BLOB NOT NULL,
|
||||
e2e_priv_key BLOB NOT NULL,
|
||||
|
@ -42,7 +42,7 @@ CREATE TABLE snd_queues (
|
|||
host TEXT NOT NULL,
|
||||
port TEXT,
|
||||
snd_id BLOB NOT NULL,
|
||||
conn_alias BLOB NOT NULL REFERENCES connections ON DELETE CASCADE,
|
||||
conn_id BLOB NOT NULL REFERENCES connections ON DELETE CASCADE,
|
||||
snd_private_key BLOB NOT NULL,
|
||||
e2e_dh_secret BLOB NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
|
@ -54,7 +54,7 @@ CREATE TABLE snd_queues (
|
|||
) WITHOUT ROWID;
|
||||
|
||||
CREATE TABLE messages (
|
||||
conn_alias BLOB NOT NULL REFERENCES connections (conn_alias)
|
||||
conn_id BLOB NOT NULL REFERENCES connections (conn_id)
|
||||
ON DELETE CASCADE,
|
||||
internal_id INTEGER NOT NULL,
|
||||
internal_ts TEXT NOT NULL,
|
||||
|
@ -62,15 +62,15 @@ CREATE TABLE messages (
|
|||
internal_snd_id INTEGER,
|
||||
msg_type BLOB NOT NULL, -- (H)ELLO, (R)EPLY, (D)ELETE. Should SMP confirmation be saved too?
|
||||
msg_body BLOB NOT NULL DEFAULT x'',
|
||||
PRIMARY KEY (conn_alias, internal_id),
|
||||
FOREIGN KEY (conn_alias, internal_rcv_id) REFERENCES rcv_messages
|
||||
PRIMARY KEY (conn_id, internal_id),
|
||||
FOREIGN KEY (conn_id, internal_rcv_id) REFERENCES rcv_messages
|
||||
ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
|
||||
FOREIGN KEY (conn_alias, internal_snd_id) REFERENCES snd_messages
|
||||
FOREIGN KEY (conn_id, internal_snd_id) REFERENCES snd_messages
|
||||
ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
|
||||
) WITHOUT ROWID;
|
||||
|
||||
CREATE TABLE rcv_messages (
|
||||
conn_alias BLOB NOT NULL,
|
||||
conn_id BLOB NOT NULL,
|
||||
internal_rcv_id INTEGER NOT NULL,
|
||||
internal_id INTEGER NOT NULL,
|
||||
external_snd_id INTEGER NOT NULL,
|
||||
|
@ -79,25 +79,25 @@ CREATE TABLE rcv_messages (
|
|||
internal_hash BLOB NOT NULL,
|
||||
external_prev_snd_hash BLOB NOT NULL,
|
||||
integrity BLOB NOT NULL,
|
||||
PRIMARY KEY (conn_alias, internal_rcv_id),
|
||||
FOREIGN KEY (conn_alias, internal_id) REFERENCES messages
|
||||
PRIMARY KEY (conn_id, internal_rcv_id),
|
||||
FOREIGN KEY (conn_id, internal_id) REFERENCES messages
|
||||
ON DELETE CASCADE
|
||||
) WITHOUT ROWID;
|
||||
|
||||
CREATE TABLE snd_messages (
|
||||
conn_alias BLOB NOT NULL,
|
||||
conn_id BLOB NOT NULL,
|
||||
internal_snd_id INTEGER NOT NULL,
|
||||
internal_id INTEGER NOT NULL,
|
||||
internal_hash BLOB NOT NULL,
|
||||
previous_msg_hash BLOB NOT NULL DEFAULT x'',
|
||||
PRIMARY KEY (conn_alias, internal_snd_id),
|
||||
FOREIGN KEY (conn_alias, internal_id) REFERENCES messages
|
||||
PRIMARY KEY (conn_id, internal_snd_id),
|
||||
FOREIGN KEY (conn_id, internal_id) REFERENCES messages
|
||||
ON DELETE CASCADE
|
||||
) WITHOUT ROWID;
|
||||
|
||||
CREATE TABLE conn_confirmations (
|
||||
confirmation_id BLOB NOT NULL PRIMARY KEY,
|
||||
conn_alias BLOB NOT NULL REFERENCES connections ON DELETE CASCADE,
|
||||
conn_id BLOB NOT NULL REFERENCES connections ON DELETE CASCADE,
|
||||
e2e_snd_pub_key BLOB NOT NULL,
|
||||
sender_key BLOB NOT NULL,
|
||||
sender_conn_info BLOB NOT NULL,
|
||||
|
|
|
@ -203,13 +203,11 @@ Commands syntax below is provided using [ABNF][3] with [case-sensitive strings e
|
|||
Each transmission between the user and SMP agent must have this format/syntax:
|
||||
|
||||
```abnf
|
||||
agentTransmission = [corrId] CRLF [cAlias] CRLF agentCommand
|
||||
agentTransmission = [corrId] CRLF [connId] CRLF agentCommand
|
||||
|
||||
corrId = 1*(%x21-7F) ; any characters other than control/whitespace
|
||||
|
||||
cAlias = cId / cName
|
||||
cId = encoded
|
||||
cName = 1*(ALPHA / DIGIT / "_" / "-")
|
||||
connId = encoded
|
||||
|
||||
agentCommand = (userCmd / agentMsg) CRLF
|
||||
userCmd = newCmd / joinCmd / letCmd / acceptCmd / subscribeCmd / sendCmd / acknowledgeCmd / suspendCmd / deleteCmd
|
||||
|
|
|
@ -26,20 +26,20 @@ Such connections that can be unidirectional or duplex can be managed by agents v
|
|||
|
||||
The protocol to create and manage such stream could be the following:
|
||||
|
||||
1. The sender client notifies the agent about the stream it has to create for a specific duplex connection (the connection must be duplex for it to be possible): `<conn_alias> SNEW <size>` (where `conn_alias` is the existing duplex connection, `size` is the size for the data to be transferred; 0 for unbounded streams), the response is `<conn_alias> STREAM <stream_id> <size>`.
|
||||
1. The sender client notifies the agent about the stream it has to create for a specific duplex connection (the connection must be duplex for it to be possible): `<conn_id> SNEW <size>` (where `conn_id` is the existing duplex connection, `size` is the size for the data to be transferred; 0 for unbounded streams), the response is `<conn_id> STREAM <stream_id> <size>`.
|
||||
2. The sender agent sends to the recipient agent the "envelope" `STREAM <stream_id> <size>`
|
||||
3. The receiving agent would notify the client about availability of the stream by sending `<conn_alias> STREAM <stream_id> <size>` notification.
|
||||
4. Receiving client would send `<conn_alias> SJOIN <stream_id>` command to the receiving agent.
|
||||
3. The receiving agent would notify the client about availability of the stream by sending `<conn_id> STREAM <stream_id> <size>` notification.
|
||||
4. Receiving client would send `<conn_id> SJOIN <stream_id>` command to the receiving agent.
|
||||
5. Receiving agent provisions the SMP queue on the random SMP server (we planned to remove SMP server from NEW command anyway). Possibly, there will be a limited list of servers that support streams (that is un-throttled number of messages), and stream support can be communicated via welcome header and change with AUTH SMP command.
|
||||
6. Receiving agent sends the envelop to sending agent `SJOIN <stream_id> <invitation>` (where invitation has the same format as in out-of-band message, but it has symmetric AES key and IV instead of asymmetric RSA key - the encryption scheme should codified in the invitation to make it generic).
|
||||
7. Sending agent and receiving agent confirm and secure SMP queue as usual. This is still not solving the problem that the sending agent should sign each command. We might extend SMP protocol to create a new queue type that allows authenticating the sender only once per TCP session so that messages can be sent without signing - the server can see that these queues are special anyway, as there will be much faster traffic there.
|
||||
8. Sending agent, once the queue is confirmed notifies the sending client that the stream is ready to accept data by sending notification `<conn_alias> SREADY <stream_id> <max_chunk_size>`.
|
||||
9. Sending agent client can now send packets into the stream up to total `<size>` limit if it was specified by using command `<conn_alias> SPUT <stream_id> <chunk_no> <chunk_size> <binary> ` (the chunk size should not be bigger than `max_chunk_size`, the agent would pad it to this size before sending to the receiving agent)
|
||||
8. Sending agent, once the queue is confirmed notifies the sending client that the stream is ready to accept data by sending notification `<conn_id> SREADY <stream_id> <max_chunk_size>`.
|
||||
9. Sending agent client can now send packets into the stream up to total `<size>` limit if it was specified by using command `<conn_id> SPUT <stream_id> <chunk_no> <chunk_size> <binary> ` (the chunk size should not be bigger than `max_chunk_size`, the agent would pad it to this size before sending to the receiving agent)
|
||||
10. Sending agent would send the chunk to the receiving agent in `CHUNK <chunk_no> <ts> <chunk_size> <binary>` envelope, where the first 4 bytes in decrypted binary is chunk size.
|
||||
11. Receiving agent would send the chunk to the client as `<conn_alias> SDATA <stream_id> <chunk_no> <ts> <status> <chunk_size> <binary>` (possibly, with three IDs and timestamps as with messages).
|
||||
12. Both the receiving and sending clients can terminate the stream with `<conn_alias> SCLOSE <stream_id>` command. The agent would send `SCLOSED <stream_id>` envelope and the opposite client would receive `<conn_alias> SCLOSED <stream_id>` notification - no more data will be accepted into this stream.
|
||||
11. Receiving agent would send the chunk to the client as `<conn_id> SDATA <stream_id> <chunk_no> <ts> <status> <chunk_size> <binary>` (possibly, with three IDs and timestamps as with messages).
|
||||
12. Both the receiving and sending clients can terminate the stream with `<conn_id> SCLOSE <stream_id>` command. The agent would send `SCLOSED <stream_id>` envelope and the opposite client would receive `<conn_id> SCLOSED <stream_id>` notification - no more data will be accepted into this stream.
|
||||
13. If the stream was bounded with some `size` then both the sending and receiving client would receive `SCLOSED` notification after the last chunk of correct size was sent (and the incorrect chunk would be rejected).
|
||||
14. If the stream was interrupted then the recipient client can request resuming this stream using `<conn_alias> SRESUME <stream_id> <from_chunk_no>`, the recipient agent would send "envelope" `SRESUME <stream_id> <from_chunk_no> <invitation>`.
|
||||
14. If the stream was interrupted then the recipient client can request resuming this stream using `<conn_id> SRESUME <stream_id> <from_chunk_no>`, the recipient agent would send "envelope" `SRESUME <stream_id> <from_chunk_no> <invitation>`.
|
||||
|
||||
To be clarified:
|
||||
1. Possibly the internal stream ID used by clients should be different from stream ID communicated between agents, and in any case it should be connection scoped (same as with messages).
|
||||
|
|
|
@ -17,7 +17,7 @@ Additional parameters in commands in SMP agent protocol:
|
|||
|
||||
- `NEW` command will have a parameter `INV` or `CON` to create an invitation or a permanent contact connection.
|
||||
|
||||
`conn_alias? OPEN` (or `PUB`, `NEWPUB`, tbc) - to create an "open"/"public" queue, the response is an invitation in a different format (TBC):
|
||||
`conn_id? OPEN` (or `PUB`, `NEWPUB`, tbc) - to create an "open"/"public" queue, the response is an invitation in a different format (TBC):
|
||||
- should allow multiple servers (probably the original invitation should be extended to support it)
|
||||
- should have a marker to indicate it's an open/public queue (probably the original invitation should be extended to include an invitation type).
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ Agent disconnected from host:port
|
|||
### Received command from the client
|
||||
|
||||
```
|
||||
n --> A : corrId connAlias parsed_command // raw_command
|
||||
n --> A : corrId connId parsed_command // raw_command
|
||||
```
|
||||
|
||||
`raw_command` is added only in case of parsing failure.
|
||||
|
@ -53,13 +53,13 @@ In case the response is a message or notification, corrId should be replaced wit
|
|||
### Interpreted ("unwrapped") SMP message as agent message
|
||||
|
||||
```
|
||||
Agent msg : connAlias parsed_message // raw_message
|
||||
Agent msg : connId parsed_message // raw_message
|
||||
```
|
||||
|
||||
### Sent response / message to the client
|
||||
|
||||
```
|
||||
n <-- A : corrId connAlias parsed_command // raw_command
|
||||
n <-- A : corrId connId parsed_command // raw_command
|
||||
```
|
||||
|
||||
### Database changes
|
||||
|
|
|
@ -516,7 +516,7 @@ connModeT = \case
|
|||
"CON" -> Just CMContact
|
||||
_ -> Nothing
|
||||
|
||||
-- | SMP agent connection alias.
|
||||
-- | SMP agent connection ID.
|
||||
type ConnId = ByteString
|
||||
|
||||
type ConfirmationId = ByteString
|
||||
|
@ -697,9 +697,9 @@ data CommandErrorType
|
|||
|
||||
-- | Connection error.
|
||||
data ConnectionErrorType
|
||||
= -- | connection alias is not in the database
|
||||
= -- | connection is not in the database
|
||||
NOT_FOUND
|
||||
| -- | connection alias already exists
|
||||
| -- | connection already exists
|
||||
DUPLICATE
|
||||
| -- | connection is simplex, but operation requires another queue
|
||||
SIMPLEX
|
||||
|
@ -899,8 +899,8 @@ tGetRaw h = (,,) <$> getLn h <*> getLn h <*> getLn h
|
|||
|
||||
-- | Send SMP agent protocol command (or response) to TCP connection.
|
||||
tPut :: (Transport c, MonadIO m) => c -> ATransmission p -> m ()
|
||||
tPut h (corrId, connAlias, command) =
|
||||
liftIO $ tPutRaw h (corrId, connAlias, serializeCommand command)
|
||||
tPut h (corrId, connId, command) =
|
||||
liftIO $ tPutRaw h (corrId, connId, serializeCommand command)
|
||||
|
||||
-- | Receive client and agent transmissions from TCP connection.
|
||||
tGet :: forall c m p. (Transport c, MonadIO m) => SAParty p -> c -> m (ATransmissionOrError p)
|
||||
|
|
|
@ -248,7 +248,7 @@ newtype InternalSndId = InternalSndId {unSndId :: Int64} deriving (Eq, Show)
|
|||
|
||||
-- | Base message data independent of direction.
|
||||
data MsgBase = MsgBase
|
||||
{ connAlias :: ConnId,
|
||||
{ connId :: ConnId,
|
||||
-- | Monotonically increasing id of a message per connection, internal to the agent.
|
||||
-- Internal Id preserves ordering between both received and sent messages, and is needed
|
||||
-- to track the order of the conversation (which can be different for the sender / receiver)
|
||||
|
@ -272,11 +272,11 @@ type InternalTs = UTCTime
|
|||
data StoreError
|
||||
= -- | IO exceptions in store actions.
|
||||
SEInternal ByteString
|
||||
| -- | failed to generate unique random ID
|
||||
| -- | Failed to generate unique random ID
|
||||
SEUniqueID
|
||||
| -- | Connection alias not found (or both queues absent).
|
||||
| -- | Connection not found (or both queues absent).
|
||||
SEConnNotFound
|
||||
| -- | Connection alias already used.
|
||||
| -- | Connection already used.
|
||||
SEConnDuplicate
|
||||
| -- | Wrong connection type, e.g. "send" connection when "receive" or "duplex" is expected, or vice versa.
|
||||
-- 'upgradeRcvConnToDuplex' and 'upgradeSndConnToDuplex' do not allow duplex connections - they would also return this error.
|
||||
|
|
|
@ -169,14 +169,14 @@ instance (MonadUnliftIO m, MonadError StoreError m) => MonadAgentStore SQLiteSto
|
|||
createRcvConn st gVar cData q@RcvQueue {server} cMode =
|
||||
createConn_ st gVar cData $ \db connId -> do
|
||||
upsertServer_ db server
|
||||
DB.execute db "INSERT INTO connections (conn_alias, conn_mode) VALUES (?, ?)" (connId, cMode)
|
||||
DB.execute db "INSERT INTO connections (conn_id, conn_mode) VALUES (?, ?)" (connId, cMode)
|
||||
insertRcvQueue_ db connId q
|
||||
|
||||
createSndConn :: SQLiteStore -> TVar ChaChaDRG -> ConnData -> SndQueue -> m ConnId
|
||||
createSndConn st gVar cData q@SndQueue {server} =
|
||||
createConn_ st gVar cData $ \db connId -> do
|
||||
upsertServer_ db server
|
||||
DB.execute db "INSERT INTO connections (conn_alias, conn_mode) VALUES (?, ?)" (connId, SCMInvitation)
|
||||
DB.execute db "INSERT INTO connections (conn_id, conn_mode) VALUES (?, ?)" (connId, SCMInvitation)
|
||||
insertSndQueue_ db connId q
|
||||
|
||||
getConn :: SQLiteStore -> ConnId -> m SomeConn
|
||||
|
@ -190,7 +190,7 @@ instance (MonadUnliftIO m, MonadError StoreError m) => MonadAgentStore SQLiteSto
|
|||
DB.queryNamed
|
||||
db
|
||||
[sql|
|
||||
SELECT q.conn_alias
|
||||
SELECT q.conn_id
|
||||
FROM rcv_queues q
|
||||
WHERE q.host = :host AND q.port = :port AND q.rcv_id = :rcv_id;
|
||||
|]
|
||||
|
@ -204,8 +204,8 @@ instance (MonadUnliftIO m, MonadError StoreError m) => MonadAgentStore SQLiteSto
|
|||
liftIO . withTransaction st $ \db ->
|
||||
DB.executeNamed
|
||||
db
|
||||
"DELETE FROM connections WHERE conn_alias = :conn_alias;"
|
||||
[":conn_alias" := connId]
|
||||
"DELETE FROM connections WHERE conn_id = :conn_id;"
|
||||
[":conn_id" := connId]
|
||||
|
||||
upgradeRcvConnToDuplex :: SQLiteStore -> ConnId -> SndQueue -> m ()
|
||||
upgradeRcvConnToDuplex st connId sq@SndQueue {server} =
|
||||
|
@ -281,7 +281,7 @@ instance (MonadUnliftIO m, MonadError StoreError m) => MonadAgentStore SQLiteSto
|
|||
db
|
||||
[sql|
|
||||
INSERT INTO conn_confirmations
|
||||
(confirmation_id, conn_alias, sender_key, e2e_snd_pub_key, sender_conn_info, accepted) VALUES (?, ?, ?, ?, ?, 0);
|
||||
(confirmation_id, conn_id, sender_key, e2e_snd_pub_key, sender_conn_info, accepted) VALUES (?, ?, ?, ?, ?, 0);
|
||||
|]
|
||||
(confirmationId, connId, senderKey, e2ePubKey, connInfo)
|
||||
|
||||
|
@ -303,7 +303,7 @@ instance (MonadUnliftIO m, MonadError StoreError m) => MonadAgentStore SQLiteSto
|
|||
<$> DB.query
|
||||
db
|
||||
[sql|
|
||||
SELECT conn_alias, sender_key, e2e_snd_pub_key, sender_conn_info
|
||||
SELECT conn_id, sender_key, e2e_snd_pub_key, sender_conn_info
|
||||
FROM conn_confirmations
|
||||
WHERE confirmation_id = ?;
|
||||
|]
|
||||
|
@ -328,7 +328,7 @@ instance (MonadUnliftIO m, MonadError StoreError m) => MonadAgentStore SQLiteSto
|
|||
[sql|
|
||||
SELECT confirmation_id, sender_key, e2e_snd_pub_key, sender_conn_info, own_conn_info
|
||||
FROM conn_confirmations
|
||||
WHERE conn_alias = ? AND accepted = 1;
|
||||
WHERE conn_id = ? AND accepted = 1;
|
||||
|]
|
||||
(Only connId)
|
||||
where
|
||||
|
@ -349,9 +349,9 @@ instance (MonadUnliftIO m, MonadError StoreError m) => MonadAgentStore SQLiteSto
|
|||
db
|
||||
[sql|
|
||||
DELETE FROM conn_confirmations
|
||||
WHERE conn_alias = :conn_alias;
|
||||
WHERE conn_id = :conn_id;
|
||||
|]
|
||||
[":conn_alias" := connId]
|
||||
[":conn_id" := connId]
|
||||
|
||||
createInvitation :: SQLiteStore -> TVar ChaChaDRG -> NewInvitation -> m InvitationId
|
||||
createInvitation st gVar NewInvitation {contactConnId, connReq, recipientConnInfo} =
|
||||
|
@ -442,7 +442,7 @@ instance (MonadUnliftIO m, MonadError StoreError m) => MonadAgentStore SQLiteSto
|
|||
getPendingMsgData :: SQLiteStore -> ConnId -> InternalId -> m (Maybe RcvQueue, (AMsgType, MsgBody))
|
||||
getPendingMsgData st connId msgId =
|
||||
liftIOEither . withTransaction st $ \db -> runExceptT $ do
|
||||
rq_ <- liftIO $ getRcvQueueByConnAlias_ db connId
|
||||
rq_ <- liftIO $ getRcvQueueByConnId_ db connId
|
||||
msgData <-
|
||||
ExceptT $
|
||||
sndMsgData
|
||||
|
@ -451,8 +451,8 @@ instance (MonadUnliftIO m, MonadError StoreError m) => MonadAgentStore SQLiteSto
|
|||
[sql|
|
||||
SELECT m.msg_type, m.msg_body
|
||||
FROM messages m
|
||||
JOIN snd_messages s ON s.conn_alias = m.conn_alias AND s.internal_id = m.internal_id
|
||||
WHERE m.conn_alias = ? AND m.internal_id = ?
|
||||
JOIN snd_messages s ON s.conn_id = m.conn_id AND s.internal_id = m.internal_id
|
||||
WHERE m.conn_id = ? AND m.internal_id = ?
|
||||
|]
|
||||
(connId, msgId)
|
||||
pure (rq_, msgData)
|
||||
|
@ -465,7 +465,7 @@ instance (MonadUnliftIO m, MonadError StoreError m) => MonadAgentStore SQLiteSto
|
|||
getPendingMsgs st connId =
|
||||
liftIO . withTransaction st $ \db ->
|
||||
map fromOnly
|
||||
<$> DB.query db "SELECT internal_id FROM snd_messages WHERE conn_alias = ?" (Only connId)
|
||||
<$> DB.query db "SELECT internal_id FROM snd_messages WHERE conn_id = ?" (Only connId)
|
||||
|
||||
checkRcvMsg :: SQLiteStore -> ConnId -> InternalId -> m ()
|
||||
checkRcvMsg st connId msgId =
|
||||
|
@ -474,9 +474,9 @@ instance (MonadUnliftIO m, MonadError StoreError m) => MonadAgentStore SQLiteSto
|
|||
<$> DB.query
|
||||
db
|
||||
[sql|
|
||||
SELECT conn_alias, internal_id
|
||||
SELECT conn_id, internal_id
|
||||
FROM rcv_messages
|
||||
WHERE conn_alias = ? AND internal_id = ?
|
||||
WHERE conn_id = ? AND internal_id = ?
|
||||
|]
|
||||
(connId, msgId)
|
||||
where
|
||||
|
@ -486,7 +486,7 @@ instance (MonadUnliftIO m, MonadError StoreError m) => MonadAgentStore SQLiteSto
|
|||
deleteMsg :: SQLiteStore -> ConnId -> InternalId -> m ()
|
||||
deleteMsg st connId msgId =
|
||||
liftIO . withTransaction st $ \db ->
|
||||
DB.execute db "DELETE FROM messages WHERE conn_alias = ? AND internal_id = ?;" (connId, msgId)
|
||||
DB.execute db "DELETE FROM messages WHERE conn_id = ? AND internal_id = ?;" (connId, msgId)
|
||||
|
||||
-- * Auxiliary helpers
|
||||
|
||||
|
@ -593,14 +593,14 @@ insertRcvQueue_ dbConn connId RcvQueue {..} = do
|
|||
dbConn
|
||||
[sql|
|
||||
INSERT INTO rcv_queues
|
||||
( host, port, rcv_id, conn_alias, rcv_private_key, rcv_dh_secret, e2e_priv_key, e2e_dh_secret, snd_id, status)
|
||||
( host, port, rcv_id, conn_id, rcv_private_key, rcv_dh_secret, e2e_priv_key, e2e_dh_secret, snd_id, status)
|
||||
VALUES
|
||||
(:host,:port,:rcv_id,:conn_alias,:rcv_private_key,:rcv_dh_secret,:e2e_priv_key,:e2e_dh_secret,:snd_id,:status);
|
||||
(:host,:port,:rcv_id,:conn_id,:rcv_private_key,:rcv_dh_secret,:e2e_priv_key,:e2e_dh_secret,:snd_id,:status);
|
||||
|]
|
||||
[ ":host" := host server,
|
||||
":port" := port server,
|
||||
":rcv_id" := rcvId,
|
||||
":conn_alias" := connId,
|
||||
":conn_id" := connId,
|
||||
":rcv_private_key" := rcvPrivateKey,
|
||||
":rcv_dh_secret" := rcvDhSecret,
|
||||
":e2e_priv_key" := e2ePrivKey,
|
||||
|
@ -617,14 +617,14 @@ insertSndQueue_ dbConn connId SndQueue {..} = do
|
|||
dbConn
|
||||
[sql|
|
||||
INSERT INTO snd_queues
|
||||
( host, port, snd_id, conn_alias, snd_private_key, e2e_dh_secret, status)
|
||||
( host, port, snd_id, conn_id, snd_private_key, e2e_dh_secret, status)
|
||||
VALUES
|
||||
(:host,:port,:snd_id,:conn_alias,:snd_private_key,:e2e_dh_secret,:status);
|
||||
(:host,:port,:snd_id,:conn_id,:snd_private_key,:e2e_dh_secret,:status);
|
||||
|]
|
||||
[ ":host" := host server,
|
||||
":port" := port server,
|
||||
":snd_id" := sndId,
|
||||
":conn_alias" := connId,
|
||||
":conn_id" := connId,
|
||||
":snd_private_key" := sndPrivateKey,
|
||||
":e2e_dh_secret" := e2eDhSecret,
|
||||
":status" := status
|
||||
|
@ -637,8 +637,8 @@ getConn_ dbConn connId =
|
|||
getConnData_ dbConn connId >>= \case
|
||||
Nothing -> pure $ Left SEConnNotFound
|
||||
Just (connData, cMode) -> do
|
||||
rQ <- getRcvQueueByConnAlias_ dbConn connId
|
||||
sQ <- getSndQueueByConnAlias_ dbConn connId
|
||||
rQ <- getRcvQueueByConnId_ dbConn connId
|
||||
sQ <- getSndQueueByConnId_ dbConn connId
|
||||
pure $ case (rQ, sQ, cMode) of
|
||||
(Just rcvQ, Just sndQ, CMInvitation) -> Right $ SomeConn SCDuplex (DuplexConnection connData rcvQ sndQ)
|
||||
(Just rcvQ, Nothing, CMInvitation) -> Right $ SomeConn SCRcv (RcvConnection connData rcvQ)
|
||||
|
@ -649,13 +649,13 @@ getConn_ dbConn connId =
|
|||
getConnData_ :: DB.Connection -> ConnId -> IO (Maybe (ConnData, ConnectionMode))
|
||||
getConnData_ dbConn connId' =
|
||||
connData
|
||||
<$> DB.query dbConn "SELECT conn_alias, conn_mode FROM connections WHERE conn_alias = ?;" (Only connId')
|
||||
<$> DB.query dbConn "SELECT conn_id, conn_mode FROM connections WHERE conn_id = ?;" (Only connId')
|
||||
where
|
||||
connData [(connId, cMode)] = Just (ConnData {connId}, cMode)
|
||||
connData _ = Nothing
|
||||
|
||||
getRcvQueueByConnAlias_ :: DB.Connection -> ConnId -> IO (Maybe RcvQueue)
|
||||
getRcvQueueByConnAlias_ dbConn connId =
|
||||
getRcvQueueByConnId_ :: DB.Connection -> ConnId -> IO (Maybe RcvQueue)
|
||||
getRcvQueueByConnId_ dbConn connId =
|
||||
rcvQueue
|
||||
<$> DB.query
|
||||
dbConn
|
||||
|
@ -664,7 +664,7 @@ getRcvQueueByConnAlias_ dbConn connId =
|
|||
q.e2e_priv_key, q.e2e_dh_secret, q.snd_id, q.status
|
||||
FROM rcv_queues q
|
||||
INNER JOIN servers s ON q.host = s.host AND q.port = s.port
|
||||
WHERE q.conn_alias = ?;
|
||||
WHERE q.conn_id = ?;
|
||||
|]
|
||||
(Only connId)
|
||||
where
|
||||
|
@ -673,8 +673,8 @@ getRcvQueueByConnAlias_ dbConn connId =
|
|||
in Just RcvQueue {server, rcvId, rcvPrivateKey, rcvDhSecret, e2ePrivKey, e2eDhSecret, sndId, status}
|
||||
rcvQueue _ = Nothing
|
||||
|
||||
getSndQueueByConnAlias_ :: DB.Connection -> ConnId -> IO (Maybe SndQueue)
|
||||
getSndQueueByConnAlias_ dbConn connId =
|
||||
getSndQueueByConnId_ :: DB.Connection -> ConnId -> IO (Maybe SndQueue)
|
||||
getSndQueueByConnId_ dbConn connId =
|
||||
sndQueue
|
||||
<$> DB.query
|
||||
dbConn
|
||||
|
@ -682,7 +682,7 @@ getSndQueueByConnAlias_ dbConn connId =
|
|||
SELECT s.key_hash, q.host, q.port, q.snd_id, q.snd_private_key, q.e2e_dh_secret, q.status
|
||||
FROM snd_queues q
|
||||
INNER JOIN servers s ON q.host = s.host AND q.port = s.port
|
||||
WHERE q.conn_alias = ?;
|
||||
WHERE q.conn_id = ?;
|
||||
|]
|
||||
(Only connId)
|
||||
where
|
||||
|
@ -701,9 +701,9 @@ retrieveLastIdsAndHashRcv_ dbConn connId = do
|
|||
[sql|
|
||||
SELECT last_internal_msg_id, last_internal_rcv_msg_id, last_external_snd_msg_id, last_rcv_msg_hash
|
||||
FROM connections
|
||||
WHERE conn_alias = :conn_alias;
|
||||
WHERE conn_id = :conn_id;
|
||||
|]
|
||||
[":conn_alias" := connId]
|
||||
[":conn_id" := connId]
|
||||
return (lastInternalId, lastInternalRcvId, lastExternalSndId, lastRcvHash)
|
||||
|
||||
updateLastIdsRcv_ :: DB.Connection -> ConnId -> InternalId -> InternalRcvId -> IO ()
|
||||
|
@ -714,11 +714,11 @@ updateLastIdsRcv_ dbConn connId newInternalId newInternalRcvId =
|
|||
UPDATE connections
|
||||
SET last_internal_msg_id = :last_internal_msg_id,
|
||||
last_internal_rcv_msg_id = :last_internal_rcv_msg_id
|
||||
WHERE conn_alias = :conn_alias;
|
||||
WHERE conn_id = :conn_id;
|
||||
|]
|
||||
[ ":last_internal_msg_id" := newInternalId,
|
||||
":last_internal_rcv_msg_id" := newInternalRcvId,
|
||||
":conn_alias" := connId
|
||||
":conn_id" := connId
|
||||
]
|
||||
|
||||
-- * createRcvMsg helpers
|
||||
|
@ -730,11 +730,11 @@ insertRcvMsgBase_ dbConn connId RcvMsgData {msgMeta, msgType, msgBody, internalR
|
|||
dbConn
|
||||
[sql|
|
||||
INSERT INTO messages
|
||||
( conn_alias, internal_id, internal_ts, internal_rcv_id, internal_snd_id, msg_type, msg_body)
|
||||
( conn_id, internal_id, internal_ts, internal_rcv_id, internal_snd_id, msg_type, msg_body)
|
||||
VALUES
|
||||
(:conn_alias,:internal_id,:internal_ts,:internal_rcv_id, NULL,:msg_type, :msg_body);
|
||||
(:conn_id,:internal_id,:internal_ts,:internal_rcv_id, NULL,:msg_type, :msg_body);
|
||||
|]
|
||||
[ ":conn_alias" := connId,
|
||||
[ ":conn_id" := connId,
|
||||
":internal_id" := internalId,
|
||||
":internal_ts" := internalTs,
|
||||
":internal_rcv_id" := internalRcvId,
|
||||
|
@ -749,15 +749,15 @@ insertRcvMsgDetails_ dbConn connId RcvMsgData {msgMeta, internalRcvId, internalH
|
|||
dbConn
|
||||
[sql|
|
||||
INSERT INTO rcv_messages
|
||||
( conn_alias, internal_rcv_id, internal_id, external_snd_id,
|
||||
( conn_id, internal_rcv_id, internal_id, external_snd_id,
|
||||
broker_id, broker_ts,
|
||||
internal_hash, external_prev_snd_hash, integrity)
|
||||
VALUES
|
||||
(:conn_alias,:internal_rcv_id,:internal_id,:external_snd_id,
|
||||
(:conn_id,:internal_rcv_id,:internal_id,:external_snd_id,
|
||||
:broker_id,:broker_ts,
|
||||
:internal_hash,:external_prev_snd_hash,:integrity);
|
||||
|]
|
||||
[ ":conn_alias" := connId,
|
||||
[ ":conn_id" := connId,
|
||||
":internal_rcv_id" := internalRcvId,
|
||||
":internal_id" := fst recipient,
|
||||
":external_snd_id" := sndMsgId,
|
||||
|
@ -777,12 +777,12 @@ updateHashRcv_ dbConn connId RcvMsgData {msgMeta, internalHash, internalRcvId} =
|
|||
UPDATE connections
|
||||
SET last_external_snd_msg_id = :last_external_snd_msg_id,
|
||||
last_rcv_msg_hash = :last_rcv_msg_hash
|
||||
WHERE conn_alias = :conn_alias
|
||||
WHERE conn_id = :conn_id
|
||||
AND last_internal_rcv_msg_id = :last_internal_rcv_msg_id;
|
||||
|]
|
||||
[ ":last_external_snd_msg_id" := sndMsgId (msgMeta :: MsgMeta),
|
||||
":last_rcv_msg_hash" := internalHash,
|
||||
":conn_alias" := connId,
|
||||
":conn_id" := connId,
|
||||
":last_internal_rcv_msg_id" := internalRcvId
|
||||
]
|
||||
|
||||
|
@ -796,9 +796,9 @@ retrieveLastIdsAndHashSnd_ dbConn connId = do
|
|||
[sql|
|
||||
SELECT last_internal_msg_id, last_internal_snd_msg_id, last_snd_msg_hash
|
||||
FROM connections
|
||||
WHERE conn_alias = :conn_alias;
|
||||
WHERE conn_id = :conn_id;
|
||||
|]
|
||||
[":conn_alias" := connId]
|
||||
[":conn_id" := connId]
|
||||
return (lastInternalId, lastInternalSndId, lastSndHash)
|
||||
|
||||
updateLastIdsSnd_ :: DB.Connection -> ConnId -> InternalId -> InternalSndId -> IO ()
|
||||
|
@ -809,11 +809,11 @@ updateLastIdsSnd_ dbConn connId newInternalId newInternalSndId =
|
|||
UPDATE connections
|
||||
SET last_internal_msg_id = :last_internal_msg_id,
|
||||
last_internal_snd_msg_id = :last_internal_snd_msg_id
|
||||
WHERE conn_alias = :conn_alias;
|
||||
WHERE conn_id = :conn_id;
|
||||
|]
|
||||
[ ":last_internal_msg_id" := newInternalId,
|
||||
":last_internal_snd_msg_id" := newInternalSndId,
|
||||
":conn_alias" := connId
|
||||
":conn_id" := connId
|
||||
]
|
||||
|
||||
-- * createSndMsg helpers
|
||||
|
@ -824,11 +824,11 @@ insertSndMsgBase_ dbConn connId SndMsgData {..} = do
|
|||
dbConn
|
||||
[sql|
|
||||
INSERT INTO messages
|
||||
( conn_alias, internal_id, internal_ts, internal_rcv_id, internal_snd_id, msg_type, msg_body)
|
||||
( conn_id, internal_id, internal_ts, internal_rcv_id, internal_snd_id, msg_type, msg_body)
|
||||
VALUES
|
||||
(:conn_alias,:internal_id,:internal_ts, NULL,:internal_snd_id,:msg_type, :msg_body);
|
||||
(:conn_id,:internal_id,:internal_ts, NULL,:internal_snd_id,:msg_type, :msg_body);
|
||||
|]
|
||||
[ ":conn_alias" := connId,
|
||||
[ ":conn_id" := connId,
|
||||
":internal_id" := internalId,
|
||||
":internal_ts" := internalTs,
|
||||
":internal_snd_id" := internalSndId,
|
||||
|
@ -842,11 +842,11 @@ insertSndMsgDetails_ dbConn connId SndMsgData {..} =
|
|||
dbConn
|
||||
[sql|
|
||||
INSERT INTO snd_messages
|
||||
( conn_alias, internal_snd_id, internal_id, internal_hash, previous_msg_hash)
|
||||
( conn_id, internal_snd_id, internal_id, internal_hash, previous_msg_hash)
|
||||
VALUES
|
||||
(:conn_alias,:internal_snd_id,:internal_id,:internal_hash,:previous_msg_hash);
|
||||
(:conn_id,:internal_snd_id,:internal_id,:internal_hash,:previous_msg_hash);
|
||||
|]
|
||||
[ ":conn_alias" := connId,
|
||||
[ ":conn_id" := connId,
|
||||
":internal_snd_id" := internalSndId,
|
||||
":internal_id" := internalId,
|
||||
":internal_hash" := internalHash,
|
||||
|
@ -861,11 +861,11 @@ updateHashSnd_ dbConn connId SndMsgData {..} =
|
|||
[sql|
|
||||
UPDATE connections
|
||||
SET last_snd_msg_hash = :last_snd_msg_hash
|
||||
WHERE conn_alias = :conn_alias
|
||||
WHERE conn_id = :conn_id
|
||||
AND last_internal_snd_msg_id = :last_internal_snd_msg_id;
|
||||
|]
|
||||
[ ":last_snd_msg_hash" := internalHash,
|
||||
":conn_alias" := connId,
|
||||
":conn_id" := connId,
|
||||
":last_internal_snd_msg_id" := internalSndId
|
||||
]
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ h #: t = tPutRaw h t >> (<#:) h
|
|||
-- | action and expected response
|
||||
-- `h #:t #> r` is the test that sends `t` to `h` and validates that the response is `r`
|
||||
(#>) :: IO (ATransmissionOrError 'Agent) -> ATransmission 'Agent -> Expectation
|
||||
action #> (corrId, cAlias, cmd) = action `shouldReturn` (corrId, cAlias, Right cmd)
|
||||
action #> (corrId, connId, cmd) = action `shouldReturn` (corrId, connId, Right cmd)
|
||||
|
||||
-- | action and predicate for the response
|
||||
-- `h #:t =#> p` is the test that sends `t` to `h` and validates the response using `p`
|
||||
|
@ -91,13 +91,13 @@ action #> (corrId, cAlias, cmd) = action `shouldReturn` (corrId, cAlias, Right c
|
|||
action =#> p = action >>= (`shouldSatisfy` p . correctTransmission)
|
||||
|
||||
correctTransmission :: ATransmissionOrError a -> ATransmission a
|
||||
correctTransmission (corrId, cAlias, cmdOrErr) = case cmdOrErr of
|
||||
Right cmd -> (corrId, cAlias, cmd)
|
||||
correctTransmission (corrId, connId, cmdOrErr) = case cmdOrErr of
|
||||
Right cmd -> (corrId, connId, cmd)
|
||||
Left e -> error $ show e
|
||||
|
||||
-- | receive message to handle `h` and validate that it is the expected one
|
||||
(<#) :: Transport c => c -> ATransmission 'Agent -> Expectation
|
||||
h <# (corrId, cAlias, cmd) = (h <#:) `shouldReturn` (corrId, cAlias, Right cmd)
|
||||
h <# (corrId, connId, cmd) = (h <#:) `shouldReturn` (corrId, connId, Right cmd)
|
||||
|
||||
-- | receive message to handle `h` and validate it using predicate `p`
|
||||
(<#=) :: Transport c => c -> (ATransmission 'Agent -> Bool) -> Expectation
|
||||
|
@ -416,10 +416,10 @@ syntaxTests t = do
|
|||
it "unknown command" $ ("1", "5678", "HELLO") >#> ("1", "5678", "ERR CMD SYNTAX")
|
||||
describe "NEW" $ do
|
||||
describe "valid" $ do
|
||||
-- TODO: add tests with defined connection alias
|
||||
-- TODO: add tests with defined connection id
|
||||
it "with correct parameter" $ ("211", "", "NEW INV") >#>= \case ("211", _, "INV" : _) -> True; _ -> False
|
||||
describe "invalid" $ do
|
||||
-- TODO: add tests with defined connection alias
|
||||
-- TODO: add tests with defined connection id
|
||||
it "with incorrect parameter" $ ("222", "", "NEW hi") >#> ("222", "", "ERR CMD SYNTAX")
|
||||
|
||||
describe "JOIN" $ do
|
||||
|
@ -445,4 +445,4 @@ syntaxTests t = do
|
|||
|
||||
-- simple test for one command with a predicate for the expected response
|
||||
(>#>=) :: ARawTransmission -> ((ByteString, ByteString, [ByteString]) -> Bool) -> Expectation
|
||||
command >#>= p = smpAgentTest t command >>= (`shouldSatisfy` p . \(cId, cAlias, cmd) -> (cId, cAlias, B.words cmd))
|
||||
command >#>= p = smpAgentTest t command >>= (`shouldSatisfy` p . \(cId, connId, cmd) -> (cId, connId, B.words cmd))
|
||||
|
|
|
@ -135,7 +135,7 @@ testForeignKeysEnabled =
|
|||
let inconsistentQuery =
|
||||
[sql|
|
||||
INSERT INTO snd_queues
|
||||
( host, port, snd_id, conn_alias, snd_private_key, e2e_dh_secret, status)
|
||||
( host, port, snd_id, conn_id, snd_private_key, e2e_dh_secret, status)
|
||||
VALUES
|
||||
('smp.simplex.im', '5223', '1234', '2345', x'', x'', 'new');
|
||||
|]
|
||||
|
|
Reference in New Issue