@@ -626,7 +626,7 @@ retryPendingForwards = \pending -> do
626 retryForwardsForServer (do x <- pending; where x.toServer == server; yield x) maxForwardRetriesPerServer)
626 retryForwardsForServer (do x <- pending; where x.toServer == server; yield x) maxForwardRetriesPerServer)
629−sendBatchedAcksToServer : [{messageId: MessageIdHex, toKey: PubkeyHex, originServer: Text, | a}] -> Text -> IO {network} {}
629+sendBatchedAcksToServer : [{messageId: MessageIdHex, toKey: PubkeyHex, originServer: ServerName, | a}] -> ServerName -> IO {network} {}
630sendBatchedAcksToServer = \serverAcks server ->
630sendBatchedAcksToServer = \serverAcks server ->
631 forEachBatch serverAcks maxMessageIds (\batch -> do
631 forEachBatch serverAcks maxMessageIds (\batch -> do
632 result <- fetch (federationScheme ++ server) (FederationAck {
632 result <- fetch (federationScheme ++ server) (FederationAck {
@@ -643,7 +643,7 @@ sendBatchedAcksToServer = \serverAcks server ->
644 Err _ -> yield {})
644 Err _ -> yield {})
646−sendAcksAndClean : [{messageId: MessageIdHex, toKey: PubkeyHex, originServer: Text, | a}] -> [Text] -> IO {network} {}
646+sendAcksAndClean : [{messageId: MessageIdHex, toKey: PubkeyHex, originServer: ServerName, | a}] -> [ServerName] -> IO {network} {}
647sendAcksAndClean = \pendingAcks servers ->
647sendAcksAndClean = \pendingAcks servers ->
648 sendToEach servers (\server ->
648 sendToEach servers (\server ->
649 sendBatchedAcksToServer (do a <- pendingAcks; where a.originServer == server; yield a) server)
649 sendBatchedAcksToServer (do a <- pendingAcks; where a.originServer == server; yield a) server)
@@ -668,15 +668,15 @@ pollOnce = \token cursor -> do
669 atomic do
669 atomic do
670 sessions <- *sessions
670 sessions <- *sessions
671− seqCounter <- *seqCounter
672 let auth = authenticateSession sessions token t
671 let auth = authenticateSession sessions token t
673− let cursorCeil = if seqCounter > t then seqCounter else t
674− let clampedCursor = if cursor < 0 then 0 else if cursor > cursorCeil then cursorCeil else cursor
675 case auth of
672 case auth of
676 Unauthorized {} ->
673 Unauthorized {} ->
677 yield {events: [], cursor: -1, authorized: False {}}
674 yield {events: [], cursor: -1, authorized: False {}}
678 Authorized {pubkey} -> do
675 Authorized {pubkey} -> do
676+ seqCounter <- *seqCounter
679 messages <- *messages
677 messages <- *messages
678+ let cursorCeil = if seqCounter > t then seqCounter else t
679+ let clampedCursor = if cursor < 0 then 0 else if cursor > cursorCeil then cursorCeil else cursor
680 let matchingMsgs = do
680 let matchingMsgs = do
681 m <- messages
681 m <- messages
682 where m.toKey == pubkey
682 where m.toKey == pubkey
@@ -808,7 +808,7 @@ serve = \req -> case req of
808 let auth = authenticateSession sessions (extractToken authorization) t
808 let auth = authenticateSession sessions (extractToken authorization) t
809 case auth of
809 case auth of
810 Unauthorized {} ->
810 Unauthorized {} ->
811− yield {status: "unauthorized", shouldInsert: False {}, remoteServers: [], fromKey: "", expiredLocal: pr.expiredLocal, peerServers: pr.peerServers, forwardsAtCapacity: False {}}
811+ yield {status: "unauthorized", shouldInsert: False {}, remoteServers: [], fromKey: "", expiredLocal: pr.expiredLocal, peerServers: pr.peerServers}
812 Authorized {pubkey: fromKey} -> do
812 Authorized {pubkey: fromKey} -> do
813 messages <- *messages
813 messages <- *messages
814 presence <- *presence
814 presence <- *presence
@@ -825,17 +825,15 @@ serve = \req -> case req of
825 let localOnline = any toPresence (\p -> p.server == serverHostN)
825 let localOnline = any toPresence (\p -> p.server == serverHostN)
826 let remoteServers = do p <- toPresence; where not (p.server == serverHostN); yield p.server
826 let remoteServers = do p <- toPresence; where not (p.server == serverHostN); yield p.server
827 forwards <- *forwards
827 forwards <- *forwards
828− let forwardsAtCapacity = count forwards >= maxForwardsEntries
828+ let forwardServers = takeN remoteServers (maxForwardsEntries - count forwards)
829 let status = if not shouldInsert then "rejected"
829 let status = if not shouldInsert then "rejected"
830 else if localOnline then "delivered"
830 else if localOnline then "delivered"
831− else if count remoteServers > 0 && federationEnabled && not forwardsAtCapacity then "federated"
831+ else if federationEnabled && count forwardServers > 0 then "federated"
832 else "queued"
832 else "queued"
833− let forwardSlots = maxForwardsEntries - count forwards
834− let forwardServers = takeN remoteServers forwardSlots
835− set *forwards = if shouldInsert && not forwardsAtCapacity && count forwardServers > 0 && federationEnabled
833+ set *forwards = if shouldInsert && federationEnabled && count forwardServers > 0
836 then union forwards (do s <- forwardServers; yield {messageId: msgId, toServer: s, createdAt: t, toKey: to, fromKey: fromKey, encryptedBlob: encryptedBlob, timestamp: clampedTs})
834 then union forwards (do s <- forwardServers; yield {messageId: msgId, toServer: s, createdAt: t, toKey: to, fromKey: fromKey, encryptedBlob: encryptedBlob, timestamp: clampedTs})
837 else forwards
835 else forwards
838− yield {status: status, shouldInsert: shouldInsert, remoteServers: remoteServers, fromKey: fromKey, expiredLocal: pr.expiredLocal, peerServers: pr.peerServers, forwardsAtCapacity: forwardsAtCapacity}
836+ yield {status: status, shouldInsert: shouldInsert, remoteServers: remoteServers, fromKey: fromKey, expiredLocal: pr.expiredLocal, peerServers: pr.peerServers}
840 when (count result.remoteServers > 0 && result.shouldInsert && federationEnabled)
838 when (count result.remoteServers > 0 && result.shouldInsert && federationEnabled)
841 (sendToEach result.remoteServers (\server -> do
839 (sendToEach result.remoteServers (\server -> do
@@ -846,7 +844,7 @@ serve = \req -> case req of
846 case fwdResult of
844 case fwdResult of
847 Ok _ -> removeForward msgId server
845 Ok _ -> removeForward msgId server
848 Err _ -> yield {}))
846 Err _ -> yield {}))
849− when (result.forwardsAtCapacity && count result.remoteServers > 0 && result.shouldInsert)
847+ when (result.status == "queued" && count result.remoteServers > 0 && result.shouldInsert && federationEnabled)
850 (println ("sendMessage: forwards at capacity (" ++ show maxForwardsEntries ++ "), skipping forward tracking"))
848 (println ("sendMessage: forwards at capacity (" ++ show maxForwardsEntries ++ "), skipping forward tracking"))
851 broadcastOfflineGossip t result.peerServers result.expiredLocal)
849 broadcastOfflineGossip t result.peerServers result.expiredLocal)
852 yield (respond {status: result.status, messageId: if result.shouldInsert then msgId else ""})
850 yield (respond {status: result.status, messageId: if result.shouldInsert then msgId else ""})
@@ -953,9 +951,14 @@ serve = \req -> case req of
953 e <- onlineEntries
951 e <- onlineEntries
954 where none offlineEntries (\o -> o.server == fromServer && samePubkeyServer o e && o.timestamp > e.timestamp)
952 where none offlineEntries (\o -> o.server == fromServer && samePubkeyServer o e && o.timestamp > e.timestamp)
956− let affectedKeys = do
954+ let filteredOffline = do
957− e <- allValidEntries
955+ e <- offlineEntries
958− yield {pubkey: e.pubkey, server: e.server}
956+ where none onlineEntries (\o -> samePubkeyServer o e && o.timestamp > e.timestamp)
958+ let trustedOffline = do
960+ where e.server == fromServer
959 let deduped = mergeByPubkeyServer [] filteredOnline
962 let deduped = mergeByPubkeyServer [] filteredOnline
960 gossipResult <- atomic do
963 gossipResult <- atomic do
961 pr <- maybePrune t
964 pr <- maybePrune t
@@ -964,19 +967,15 @@ serve = \req -> case req of
964 e <- deduped
967 e <- deduped
965 where e.server == fromServer || any presence (\p -> p.server == e.server && p.expiresAt > t)
968 where e.server == fromServer || any presence (\p -> p.server == e.server && p.expiresAt > t)
967− let trustedOffline = do
969− where e.server == fromServer
971 let appliedOnline = do
970 let appliedOnline = do
972 e <- trustedDeduped
971 e <- trustedDeduped
973 where none presence (\p -> samePubkeyServer p e && p.expiresAt >= e.expiresAt)
972 where none presence (\p -> samePubkeyServer p e && p.expiresAt >= e.expiresAt)
974 yield {pubkey: e.pubkey, server: e.server}
973 yield {pubkey: e.pubkey, server: e.server}
975 let merged = mergeByPubkeyServer presence trustedDeduped
974 let merged = mergeByPubkeyServer presence trustedDeduped
976 let offlineOnlyKeys = do
975 let offlineOnlyKeys = do
977− k <- affectedKeys
976+ e <- allValidEntries
978− where none trustedDeduped (\d -> samePubkeyServer d k)
977+ where none trustedDeduped (\d -> samePubkeyServer d e)
980 let appliedOffline = do
979 let appliedOffline = do
981 k <- offlineOnlyKeys
980 k <- offlineOnlyKeys
982 where any presence (\p -> samePubkeyServer p k && any trustedOffline (\o -> samePubkeyServer o k && (if o.timestamp > t then t else o.timestamp) > p.timestamp))
981 where any presence (\p -> samePubkeyServer p k && any trustedOffline (\o -> samePubkeyServer o k && (if o.timestamp > t then t else o.timestamp) > p.timestamp))
@@ -1000,10 +999,6 @@ serve = \req -> case req of
1000 set *presence = finalPresence
999 set *presence = finalPresence
1001 let gossipPeerServers = collectPeerServers finalPresence (\p -> p.server)
1000 let gossipPeerServers = collectPeerServers finalPresence (\p -> p.server)
1002 yield {appliedKeys: union capResult.appliedOnline appliedOffline, expiredLocal: pr.expiredLocal, peerServers: pr.peerServers, gossipPeerServers: gossipPeerServers, withinCapacity: withinCapacity}
1001 yield {appliedKeys: union capResult.appliedOnline appliedOffline, expiredLocal: pr.expiredLocal, peerServers: pr.peerServers, gossipPeerServers: gossipPeerServers, withinCapacity: withinCapacity}
1003− let filteredOffline = do
1004− e <- offlineEntries
1005− where none onlineEntries (\o -> samePubkeyServer o e && o.timestamp > e.timestamp)
1007 let effectiveEvents = do
1002 let effectiveEvents = do
1008 e <- union filteredOnline filteredOffline
1003 e <- union filteredOnline filteredOffline
1009 where any gossipResult.appliedKeys (\a -> samePubkeyServer a e)
1004 where any gossipResult.appliedKeys (\a -> samePubkeyServer a e)