@@ -62,7 +62,7 @@ route ClientApi where
6262
6363route FederationApi where
6464 /federation
65− POST {events: [GossipEvent], hopsRemaining: Int} /gossip headers {authorization: Text}
65+ POST {events: [GossipEvent], hopsRemaining: Int, fromServer: Text} /gossip headers {authorization: Text}
6666 -> {ok: Bool}
6767 = RecvGossip
6868 POST {toKey: Text, fromKey: Text, encryptedBlob: Text, timestamp: Int, originServer: Text, messageId: Text} /forward headers {authorization: Text}
@@ -231,7 +231,7 @@ serve = \req -> case req of
231231 then sendToEach result.peerServers (\server ->
232232 httpPost (federationScheme ++ server ++ "/federation/gossip")
233233 {authorization: "Bearer " ++ federationSecret}
234− {events: [{eventType: "online", pubkey: pubkey, server: serverHost, timestamp: t, ttl: 3600}], hopsRemaining: 2})
234+ {events: [{eventType: "online", pubkey: pubkey, server: serverHost, timestamp: t, ttl: 3600}], hopsRemaining: 2, fromServer: serverHost})
235235 else yield {}
236236
237237 Poll {cursor, authorization, respond} -> do
@@ -315,6 +315,9 @@ serve = \req -> case req of
315315
316316 AckMessages {messageIds, authorization, respond} -> do
317317 t <- now
318+ let dedupedIds = fold (\acc mid ->
319+ if count (do a <- acc; where a == mid; yield a) > 0 then acc
320+ else union acc [mid]) [] messageIds
318321 result <- atomic do
319322 pruneExpired t
320323 sessions <- *sessions
@@ -324,7 +327,7 @@ serve = \req -> case req of
324327 Nothing {} -> []
325328 Just {value: s} -> do
326329 m <- messages
327− mid <- messageIds
330+ mid <- dedupedIds
328331 where m.messageId == mid
329332 where m.toKey == s.pubkey
330333 yield m
@@ -383,7 +386,7 @@ serve = \req -> case req of
383386 then respond {online: not (result.foundServer == ""), server: result.foundServer}
384387 else respond {online: False {}, server: "unauthorized"}
385388
386− RecvGossip {events, hopsRemaining, authorization, respond} -> do
389+ RecvGossip {events, hopsRemaining, fromServer, authorization, respond} -> do
387390 t <- now
388391 let authorized = verifyFederationAuth authorization
389392 let cappedHops = if hopsRemaining > 5 then 5 else hopsRemaining
@@ -448,7 +451,14 @@ serve = \req -> case req of
448451 set *presence = if validRequest
449452 then union cleaned deduped
450453 else presence
451− if validRequest && cappedHops > 1 && not (federationSecret == "")
454+ let validEvents = do
455+ e <- events
456+ where not (e.server == "")
457+ where not (e.pubkey == "")
458+ where e.timestamp <= t
459+ where e.timestamp + (clampTtl e.ttl) * 1000 > t
460+ yield e
461+ if validRequest && cappedHops > 1 && not (federationSecret == "") && count validEvents > 0
452462 then do
453463 peerServers <- atomic do
454464 presence <- *presence
@@ -458,7 +468,7 @@ serve = \req -> case req of
458468 else union acc [p.server]) [] presence)
459469 let senderServers = fold (\acc e ->
460470 if count (do a <- acc; where a == e.server; yield a) > 0 then acc
461− else union acc [e.server]) [] events
471+ else union acc [e.server]) (if fromServer == "" then [] else [fromServer]) events
462472 let targets = do
463473 s <- peerServers
464474 where count (do ss <- senderServers; where ss == s; yield ss) == 0
@@ -466,7 +476,7 @@ serve = \req -> case req of
466476 sendToEach targets (\server ->
467477 httpPost (federationScheme ++ server ++ "/federation/gossip")
468478 {authorization: "Bearer " ++ federationSecret}
469− {events: events, hopsRemaining: cappedHops - 1})
479+ {events: validEvents, hopsRemaining: cappedHops - 1, fromServer: serverHost})
470480 else yield {}
471481 respond {ok: validRequest}
472482