@@ -50,21 +50,23 @@ federationEnabled = federationSecret != ""
5050
5151type PollEvent = {id: MessageIdHex, eventType: Text, payload: {encryptedBlob: BlobHex, fromKey: PubkeyHex, timestamp: Timestamp, toKey: PubkeyHex}}
5252
53−type GossipEventType = GossipOnline {} | GossipOffline {}
53+type GossipEventType = GossipOnline {} | GossipOffline {} | GossipUnknown {}
5454
5555impl ToJSON GossipEventType where
5656 toJson et = toJson (case et of
5757 GossipOnline {} -> "online"
58− GossipOffline {} -> "offline")
58+ GossipOffline {} -> "offline"
59+ GossipUnknown {} -> "unknown")
5960
6061impl FromJSON GossipEventType where
6162 parseJson t =
6263 let s : Text = parseJson t in
6364 if s == "online" then GossipOnline {}
6465 else if s == "offline" then GossipOffline {}
65− else GossipOffline {}
66+ else GossipUnknown {}
6667
6768isGossipOnline = \et -> case et of GossipOnline {} -> True {}; _ -> False {}
69+isGossipOffline = \et -> case et of GossipOffline {} -> True {}; _ -> False {}
6870
6971type GossipEvent = {eventType: GossipEventType, pubkey: PubkeyHex, server: ServerName, timestamp: Timestamp, ttl: Int<S>}
7072
@@ -80,16 +82,6 @@ impl ToJSON MessageStatus where
8082 MsFederated {} -> "federated"
8183 MsQueued {} -> "queued")
8284
83−impl FromJSON MessageStatus where
84− parseJson t =
85− let s : Text = parseJson t in
86− if s == "unauthorized" then MsUnauthorized {}
87− else if s == "rejected" then MsRejected {}
88− else if s == "delivered" then MsDelivered {}
89− else if s == "federated" then MsFederated {}
90− else if s == "queued" then MsQueued {}
91− else MsQueued {}
92−
9385type PubkeyHex = Text where \s -> isValidHex s && not (tooLong s maxPubkeyLen) && s == normalizeHex s
9486type BlobHex = Text where \s -> isValidHex s && not (tooLong s maxBlobLen) && s == normalizeHex s
9587type SignatureHex = Text where \s -> isValidHex s && not (tooLong s maxSignatureLen) && s == normalizeHex s
@@ -253,7 +245,7 @@ isCgnatRange = \s ->
253245 then True {}
254246 else False {}
255247
256−containsMultipleColons = \s -> fold (\n c -> if c == ":" then n + 1 else n) 0 (chars s) > 1
248+containsMultipleColons = \s -> count (do c <- chars s; where c == ":"; yield c) > 1
257249
258250hasOctalOctet = \s ->
259251 if take 1 s == "0" && isDigitChar (take 1 (drop 1 s)) && isAllDigitsOrDotsUntilColonOrEnd (drop 2 s) then True {}
@@ -507,7 +499,7 @@ capGossipPresence = \afterOffline appliedOnline trustedDeduped presence trustedO
507499 withinCapacity: False {}}
508500
509501countMessagesFor = \messages toKey t ->
510− fold (\n m -> if m.toKey == toKey && m.receivedAt >= t - messageMaxAge then n + 1 else n) 0 messages
502+ count (do m <- messages; where m.toKey == toKey && m.receivedAt >= t - messageMaxAge; yield m)
511503
512504
513505validGossipEvents : [GossipEvent] -> Timestamp -> [ValidGossipEntry]
@@ -908,11 +900,9 @@ serve = \req -> case req of
908900 p <- presence
909901 where p.pubkey == pubkey && p.expiresAt > t
910902 yield p
911− let foundServer = (fold (\acc p ->
912− if acc.server == serverHostN then acc
913− else if p.server == serverHostN then {server: serverHostN, best: 0}
914− else if p.expiresAt > acc.best then {server: p.server, best: p.expiresAt}
915− else acc) {server: "", best: 0} valid).server
903+ let localOnline = any valid (\p -> p.server == serverHostN)
904+ let foundServer = if localOnline then serverHostN
905+ else (fold (\acc p -> if p.expiresAt > acc.best then {server: p.server, best: p.expiresAt} else acc) {server: "", best: 0} valid).server
916906 yield {pr: pr, authorized: True {}, foundServer: foundServer}
917907 forkBroadcastOffline t result.pr
918908 yield (respond {online: result.foundServer != "", server: result.foundServer, authorized: result.authorized})
@@ -928,14 +918,13 @@ serve = \req -> case req of
928918 else do
929919 let allValidEntries = validGossipEvents events t
930920 let onlineEntries = do e <- allValidEntries; where isGossipOnline e.eventType; yield e
931− let offlineEntries = do e <- allValidEntries; where not (isGossipOnline e.eventType); yield e
932− let trustedOffline = do e <- offlineEntries; where e.server == fromServer; yield e
921+ let trustedOffline = do e <- allValidEntries; where isGossipOffline e.eventType && e.server == fromServer; yield e
933922 let filteredOnline = do
934923 e <- onlineEntries
935924 where none trustedOffline (\o -> samePubkeyServer o e && o.timestamp > e.timestamp)
936925 yield e
937926 let filteredOffline = do
938− e <- offlineEntries
927+ e <- trustedOffline
939928 where none onlineEntries (\o -> samePubkeyServer o e && o.timestamp > e.timestamp)
940929 yield e
941930 let deduped = mergeByPubkeyServer [] filteredOnline