@@ -286,9 +286,11 @@ stripTrailingDot = \s ->
286 else if take 1 s == "." && isTrailingDots (drop 1 s) then stripTrailingDot (drop 1 s)
286 else if take 1 s == "." && isTrailingDots (drop 1 s) then stripTrailingDot (drop 1 s)
287 else take 1 s ++ stripTrailingDot (drop 1 s)
287 else take 1 s ++ stripTrailingDot (drop 1 s)
289+normalizeServerName : Text -> Text
289normalizeServerName = \s -> toLower (stripTrailingDot s)
290normalizeServerName = \s -> toLower (stripTrailingDot s)
291serverHostN = normalizeServerName serverHost
292serverHostN = normalizeServerName serverHost
293+isLocalServer : Text -> Bool
292isLocalServer = \s -> s == serverHostN
294isLocalServer = \s -> s == serverHostN
294containsSuffixN = \suffix suffixLen s ->
296containsSuffixN = \suffix suffixLen s ->
@@ -323,6 +325,7 @@ matchesHostname = \sn name ->
323matchesHostnameOrSubdomain = \sn name ->
325matchesHostnameOrSubdomain = \sn name ->
324 matchesHostname sn name || containsSuffix ("." ++ name) sn
326 matchesHostname sn name || containsSuffix ("." ++ name) sn
328+isBadServerName : Text -> Bool
326isBadServerName = \sn ->
329isBadServerName = \sn ->
328 || take 1 sn == "."
331 || take 1 sn == "."
@@ -363,32 +366,40 @@ extractToken = \authHeader ->
363 then Just {value: token}
366 then Just {value: token}
364 else Nothing {}
367 else Nothing {}
369+verifySecret : Text -> Text -> Bool
366verifySecret = \token secret ->
370verifySecret = \token secret ->
367 secret != "" && safeCompare token secret
371 secret != "" && safeCompare token secret
373+verifyFederationAuth : Text -> Bool
369verifyFederationAuth = \authorization ->
374verifyFederationAuth = \authorization ->
370 case extractToken authorization of
375 case extractToken authorization of
371 Nothing {} -> False {}
376 Nothing {} -> False {}
372 Just {value: token} -> verifySecret token federationSecret
377 Just {value: token} -> verifySecret token federationSecret
379+verifyMaintenanceAuth : Text -> Bool
374verifyMaintenanceAuth = \authorization ->
380verifyMaintenanceAuth = \authorization ->
375 case extractToken authorization of
381 case extractToken authorization of
376 Nothing {} -> False {}
382 Nothing {} -> False {}
377 Just {value: token} -> verifySecret token federationSecret || verifySecret token maintenanceSecret
383 Just {value: token} -> verifySecret token federationSecret || verifySecret token maintenanceSecret
385+clampTtl : Int<S> -> Int<S>
379clampTtl = clamp 1 maxPresenceTtl
386clampTtl = clamp 1 maxPresenceTtl
388+clampTimestamp : Timestamp -> Timestamp -> Timestamp
381clampTimestamp = \timestamp t -> clamp (t - messageMaxAge) t timestamp
389clampTimestamp = \timestamp t -> clamp (t - messageMaxAge) t timestamp
391+deliveryToMessageStatus : DeliveryStatus -> MessageStatus
383deliveryToMessageStatus = \ds -> case ds of
392deliveryToMessageStatus = \ds -> case ds of
384 DsDelivered {} -> MsDelivered {}
393 DsDelivered {} -> MsDelivered {}
385 DsFederated {} -> MsFederated {}
394 DsFederated {} -> MsFederated {}
386 DsQueued {} -> MsQueued {}
395 DsQueued {} -> MsQueued {}
397+nextSeqTs : Timestamp -> Timestamp -> Timestamp
388nextSeqTs = \t seqCounter -> if t > seqCounter then t else seqCounter + 1
398nextSeqTs = \t seqCounter -> if t > seqCounter then t else seqCounter + 1
390takeN = \items n -> (fold (\acc e -> if acc.n >= n then acc else {n: acc.n + 1, items: union acc.items [e]}) {n: 0, items: []} items).items
400takeN = \items n -> (fold (\acc e -> if acc.n >= n then acc else {n: acc.n + 1, items: union acc.items [e]}) {n: 0, items: []} items).items
402+dedupMessageIds : [MessageIdHex] -> [MessageIdHex]
392dedupMessageIds = \messageIds ->
403dedupMessageIds = \messageIds ->
393 fold (\acc mid ->
404 fold (\acc mid ->
394 if count acc >= maxMessageIds then acc
405 if count acc >= maxMessageIds then acc
@@ -502,9 +513,11 @@ capGossipPresence = \args ->
502 (do e <- reclaimedEntries; yield (pubkeyServer e)),
513 (do e <- reclaimedEntries; yield (pubkeyServer e)),
503 withinCapacity: False {}}
514 withinCapacity: False {}}
516+countMessagesFor : [Message] -> PubkeyHex -> Timestamp -> Int
505countMessagesFor = \messages toKey t ->
517countMessagesFor = \messages toKey t ->
506 count (do m <- messages; where m.toKey == toKey && m.receivedAt >= t - messageMaxAge; yield m)
518 count (do m <- messages; where m.toKey == toKey && m.receivedAt >= t - messageMaxAge; yield m)
520+hasMessage : MessageIdHex -> PubkeyHex -> [{messageId: MessageIdHex, toKey: PubkeyHex | a}] -> Bool
508hasMessage = \mid toKey items -> any items (\x -> x.messageId == mid && x.toKey == toKey)
521hasMessage = \mid toKey items -> any items (\x -> x.messageId == mid && x.toKey == toKey)
@@ -627,13 +640,11 @@ mergeGossipPresence = \presence deduped trustedOffline fromServer t ->
627 gossipPeerServers: collectPeerServers capResult.finalPresence (\p -> p.server),
640 gossipPeerServers: collectPeerServers capResult.finalPresence (\p -> p.server),
628 withinCapacity: capResult.withinCapacity}
641 withinCapacity: capResult.withinCapacity}
630−rejectFederation = \t respond -> do
631− maybePruneAndBroadcast t
632− yield (respond {ok: False {}})
634withFederationAuth = \authorization t respond precondition action ->
643withFederationAuth = \authorization t respond precondition action ->
635 if not (verifyFederationAuth authorization) || not precondition
644 if not (verifyFederationAuth authorization) || not precondition
636− then rejectFederation t respond
645+ then do
646+ maybePruneAndBroadcast t
647+ yield (respond {ok: False {}})
637 else action
648 else action
639maybePruneAndBroadcast = \t -> do
650maybePruneAndBroadcast = \t -> do