on master help sign in
Simplify server.knot and improve type safety
e4f77cciko
client/App.fs+10−3
@@ -883,8 +883,8 @@ module App =
883 .margin(20.)
883 .margin(20.)
884 )
884 )
885
885
886− let view model =
886+ let private pageContent model =
887− let content =
887+ let page =
888 match model.Page with
888 match model.Page with
889 | Setup -> AnyView(viewSetup ())
889 | Setup -> AnyView(viewSetup ())
890 | Settings -> AnyView(viewSettings model)
890 | Settings -> AnyView(viewSettings model)
@@ -893,12 +893,19 @@ module App =
893 | AddContact(pk, nn) -> AnyView(viewAddContact model pk nn)
893 | AddContact(pk, nn) -> AnyView(viewAddContact model pk nn)
894 | EditProfile(displayName, bio, photo) -> AnyView(viewEditProfile model displayName bio photo)
894 | EditProfile(displayName, bio, photo) -> AnyView(viewEditProfile model displayName bio photo)
895
895
896+ Border(page).background(SolidColorBrush(Colors.White))
897+
898+ let view model =
899+#if MOBILE
900+ SingleViewApplication(pageContent model)
901+#else
896 DesktopApplication() {
902 DesktopApplication() {
897− Window(content)
903+ Window(pageContent model)
898 .title("Skrepka")
904 .title("Skrepka")
899 .width(450.)
905 .width(450.)
900 .height(750.)
906 .height(750.)
901 }
907 }
908+#endif
902
909
903 let program = Program.statefulWithCmdMsg init update mapCmd |> Program.withView view
910 let program = Program.statefulWithCmdMsg init update mapCmd |> Program.withView view
904
911
client/Program.fs → client/Platform/Desktop/Program.fsrenamed

The content is the same.

client/Platform/iOS/AppDelegate.fsnew file+26
@@ -0,0 +1,26 @@
1+namespace Skrepka.iOS
2+
3+open Foundation
4+open UIKit
5+open Avalonia
6+open Avalonia.iOS
7+open Fabulous.Avalonia
8+open Skrepka
9+
10+[<Register(nameof AppDelegate)>]
11+type AppDelegate() =
12+ inherit AvaloniaAppDelegate<FabApplication>()
13+ override this.CreateAppBuilder() = App.create().UseiOS()
14+
15+ [<Export("application:didFinishLaunchingWithOptions:")>]
16+ member this.FinishedLaunching(app: UIApplication, options: NSDictionary) : bool =
17+ let result = base.FinishedLaunching(app, options)
18+ if this.Window <> null then
19+ this.Window.BackgroundColor <- UIColor.White
20+ result
21+
22+module Main =
23+ [<EntryPoint>]
24+ let main (args: string array) =
25+ UIApplication.Main(args, null, typeof<AppDelegate>)
26+ 0
client/Platform/iOS/Entitlements.plistnew file+6
@@ -0,0 +1,6 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+<plist version="1.0">
4+<dict>
5+</dict>
6+</plist>
client/Platform/iOS/Info.plistnew file+39
@@ -0,0 +1,39 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+<plist version="1.0">
4+<dict>
5+ <key>CFBundleDisplayName</key>
6+ <string>Skrepka</string>
7+ <key>CFBundleIdentifier</key>
8+ <string>com.skrepka.client</string>
9+ <key>CFBundleShortVersionString</key>
10+ <string>1.0</string>
11+ <key>CFBundleVersion</key>
12+ <string>1.0</string>
13+ <key>LSRequiresIPhoneOS</key>
14+ <true/>
15+ <key>MinimumOSVersion</key>
16+ <string>15.0</string>
17+ <key>UIDeviceFamily</key>
18+ <array>
19+ <integer>1</integer>
20+ <integer>2</integer>
21+ </array>
22+ <key>UILaunchStoryboardName</key>
23+ <string>LaunchScreen</string>
24+ <key>UIRequiredDeviceCapabilities</key>
25+ <array>
26+ <string>armv7</string>
27+ </array>
28+ <key>UISupportedInterfaceOrientations</key>
29+ <array>
30+ <string>UIInterfaceOrientationPortrait</string>
31+ <string>UIInterfaceOrientationLandscapeLeft</string>
32+ <string>UIInterfaceOrientationLandscapeRight</string>
33+ </array>
34+ <key>UIStatusBarHidden</key>
35+ <true/>
36+ <key>UIViewControllerBasedStatusBarAppearance</key>
37+ <false/>
38+</dict>
39+</plist>
client/Platform/iOS/Resources/LaunchScreen.xibnew file+32
@@ -0,0 +1,32 @@
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6214" systemVersion="14A314h" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
3+ <dependencies>
4+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6207" />
5+ <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1" />
6+ </dependencies>
7+ <objects>
8+ <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" />
9+ <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder" />
10+ <view contentMode="scaleToFill" id="iN0-l3-epB">
11+ <rect key="frame" x="0.0" y="0.0" width="480" height="480" />
12+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" />
13+ <subviews>
14+ <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Skrepka" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
15+ <rect key="frame" x="20" y="140" width="441" height="43" />
16+ <fontDescription key="fontDescription" type="boldSystem" pointSize="36" />
17+ <color key="textColor" cocoaTouchSystemColor="darkTextColor" />
18+ <nil key="highlightedColor" />
19+ </label>
20+ </subviews>
21+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite" />
22+ <constraints>
23+ <constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC" />
24+ <constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk" />
25+ <constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g" />
26+ </constraints>
27+ <nil key="simulatedStatusBarMetrics" />
28+ <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics" />
29+ <point key="canvasLocation" x="548" y="455" />
30+ </view>
31+ </objects>
32+</document>
client/Skrepka.fsproj+39−3
@@ -2,9 +2,27 @@
2
2
3 <PropertyGroup>
3 <PropertyGroup>
4 <OutputType>Exe</OutputType>
4 <OutputType>Exe</OutputType>
5− <TargetFramework>net10.0</TargetFramework>
5+ <TargetFrameworks>net10.0</TargetFrameworks>
6+ <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('osx'))">$(TargetFrameworks);net10.0-ios</TargetFrameworks>
6 <RootNamespace>Skrepka</RootNamespace>
7 <RootNamespace>Skrepka</RootNamespace>
7 <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
8 <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
9+ <NoWarn>MT7091;NETSDK1206</NoWarn>
10+ </PropertyGroup>
11+
12+ <PropertyGroup>
13+ <AvaloniaPlatform>$([MSBuild]::GetTargetPlatformIdentifier($(TargetFramework)))</AvaloniaPlatform>
14+ <AvaloniaPlatform Condition="'$(AvaloniaPlatform)' == ''">Desktop</AvaloniaPlatform>
15+ <AvaloniaPlatform Condition="'$(AvaloniaPlatform)' == 'ios'">iOS</AvaloniaPlatform>
16+
17+ <iOSPlatformFolder>Platform/iOS/</iOSPlatformFolder>
18+ <DesktopPlatformFolder>Platform/Desktop/</DesktopPlatformFolder>
19+ </PropertyGroup>
20+
21+ <PropertyGroup Condition="'$(AvaloniaPlatform)' == 'iOS'">
22+ <DefineConstants>$(DefineConstants);MOBILE</DefineConstants>
23+ <SupportedOSPlatformVersion>15.0</SupportedOSPlatformVersion>
24+ <RuntimeIdentifier>iossimulator-arm64</RuntimeIdentifier>
25+ <ValidateXcodeVersion>false</ValidateXcodeVersion>
8 </PropertyGroup>
26 </PropertyGroup>
9
27
10 <ItemGroup>
28 <ItemGroup>
@@ -15,7 +33,6 @@
15 <Compile Include="Store.fs" />
33 <Compile Include="Store.fs" />
16 <Compile Include="Buttons.fs" />
34 <Compile Include="Buttons.fs" />
17 <Compile Include="App.fs" />
35 <Compile Include="App.fs" />
18− <Compile Include="Program.fs" />
19 </ItemGroup>
36 </ItemGroup>
20
37
21 <ItemGroup>
38 <ItemGroup>
@@ -23,8 +40,27 @@
23 <AvaloniaResource Include="Assets\Images\*" />
40 <AvaloniaResource Include="Assets\Images\*" />
24 </ItemGroup>
41 </ItemGroup>
25
42
26− <ItemGroup>
43+ <ItemGroup Condition="$(AvaloniaPlatform) == 'Desktop'">
44+ <Compile Include="$(DesktopPlatformFolder)Program.fs" />
27 <PackageReference Include="Avalonia.Desktop" Version="11.3.0" />
45 <PackageReference Include="Avalonia.Desktop" Version="11.3.0" />
46+ </ItemGroup>
47+
48+ <ItemGroup Condition="$(AvaloniaPlatform) == 'iOS'">
49+ <None Include="$(iOSPlatformFolder)Entitlements.plist" />
50+ <None Include="$(iOSPlatformFolder)Info.plist" LogicalName="Info.plist" />
51+ <InterfaceDefinition Include="$(iOSPlatformFolder)Resources\LaunchScreen.xib" />
52+ <Compile Include="$(iOSPlatformFolder)AppDelegate.fs" />
53+ <PackageReference Include="Avalonia.iOS" Version="11.3.0" />
54+ </ItemGroup>
55+
56+ <ItemGroup Condition="$(AvaloniaPlatform) == 'iOS' And $(RuntimeIdentifier.StartsWith('iossimulator'))">
57+ <NativeReference Include="native/iossimulator-arm64/libsodium.a">
58+ <Kind>Static</Kind>
59+ <ForceLoad>true</ForceLoad>
60+ </NativeReference>
61+ </ItemGroup>
62+
63+ <ItemGroup>
28 <PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.0" />
64 <PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.0" />
29 <PackageReference Include="FSharp.Core" Version="9.0.100" />
65 <PackageReference Include="FSharp.Core" Version="9.0.100" />
30 <PackageReference Include="Fabulous" Version="3.0.0-pre22" />
66 <PackageReference Include="Fabulous" Version="3.0.0-pre22" />
client/run-ios.sh+1−1
@@ -6,7 +6,7 @@ DEVICE="${1:-iPhone 17 Pro}"
6BUNDLE_ID="com.skrepka.client"
6BUNDLE_ID="com.skrepka.client"
7APP="bin/Debug/net10.0-ios/iossimulator-arm64/Skrepka.app"
7APP="bin/Debug/net10.0-ios/iossimulator-arm64/Skrepka.app"
8
8
9−dotnet build Skrepka.fsproj -f net10.0-ios -r iossimulator-arm64
9+dotnet build Skrepka.fsproj -f net10.0-ios
10
10
11UDID=$(xcrun simctl list devices available -j | python3 -c "
11UDID=$(xcrun simctl list devices available -j | python3 -c "
12import json, sys
12import json, sys
client/run-mac.sh+1−2
@@ -1,5 +1,4 @@
1#!/bin/bash
1#!/bin/bash
2set -e
2set -e
3cd "$(dirname "$0")"
3cd "$(dirname "$0")"
4−dotnet build Skrepka.fsproj -f net10.0-maccatalyst
4+dotnet run -f net10.0
5−open bin/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.app
server.knot+41−49
@@ -360,18 +360,21 @@ authenticateSession = \sessions token t ->
360extractToken = \authHeader ->
360extractToken = \authHeader ->
361 let token = drop 7 authHeader in
361 let token = drop 7 authHeader in
362 if toLower (take 7 authHeader) == "bearer " && not (tooLong token maxTokenLen)
362 if toLower (take 7 authHeader) == "bearer " && not (tooLong token maxTokenLen)
363− then token
363+ then Just {value: token}
364− else ""
364+ else Nothing {}
365
365
366verifySecret = \token secret ->
366verifySecret = \token secret ->
367 secret != "" && safeCompare token secret
367 secret != "" && safeCompare token secret
368
368
369verifyFederationAuth = \authorization ->
369verifyFederationAuth = \authorization ->
370− verifySecret (extractToken authorization) federationSecret
370+ case extractToken authorization of
371+ Nothing {} -> False {}
372+ Just {value: token} -> verifySecret token federationSecret
371
373
372verifyMaintenanceAuth = \authorization ->
374verifyMaintenanceAuth = \authorization ->
373− let token = extractToken authorization in
375+ case extractToken authorization of
376+ Nothing {} -> False {}
374− verifySecret token federationSecret || verifySecret token maintenanceSecret
377+ Just {value: token} -> verifySecret token federationSecret || verifySecret token maintenanceSecret
375
378
376clampTtl = clamp 1 maxPresenceTtl
379clampTtl = clamp 1 maxPresenceTtl
377
380
@@ -435,17 +438,7 @@ safeCompare = \a b ->
435 safeCompareLoop a b maxTokenLen 0 + (if a == "" then 1 else 0) + (if b == "" then 1 else 0) == 0
438 safeCompareLoop a b maxTokenLen 0 + (if a == "" then 1 else 0) + (if b == "" then 1 else 0) == 0
436
439
437evictOneOldest = \items getKey ->
440evictOneOldest = \items getKey ->
438− let oldest = fold (\acc x -> let k = getKey x in Just {value: case acc of
441+ diff items (boundedSmallest items 1 getKey)
439− Nothing {} -> k
440− Just {value: v} -> min k v
441− }) Nothing {} items in
442− case oldest of
443− Nothing {} -> items
444− Just {value: oldestKey} ->
445− (fold (\acc x ->
446− if not acc.removed && getKey x == oldestKey
447− then {removed: True {}, items: acc.items}
448− else {removed: acc.removed, items: union acc.items [x]}) {removed: False {}, items: []} items).items
449
442
450capPerKey = \items matchKey maxPerKey getExpiry t ->
443capPerKey = \items matchKey maxPerKey getExpiry t ->
451 let active = do x <- items; where getExpiry x > t; yield x in
444 let active = do x <- items; where getExpiry x > t; yield x in
@@ -638,8 +631,8 @@ rejectFederation = \t respond -> do
638 maybePruneAndBroadcast t
631 maybePruneAndBroadcast t
639 yield (respond {ok: False {}})
632 yield (respond {ok: False {}})
640
633
641−withFederationAuth = \authorization t respond extraCheck action ->
634+withFederationAuth = \authorization t respond precondition action ->
642− if not (verifyFederationAuth authorization) || extraCheck
635+ if not (verifyFederationAuth authorization) || not precondition
643 then rejectFederation t respond
636 then rejectFederation t respond
644 else action
637 else action
645
638
@@ -647,6 +640,15 @@ maybePruneAndBroadcast = \t -> do
647 pruneResult <- atomic do maybePrune t
640 pruneResult <- atomic do maybePrune t
648 forkBroadcastOffline t pruneResult
641 forkBroadcastOffline t pruneResult
649
642
643+withSessionAuth = \authorization t onUnauth onAuth -> do
644+ sessions <- *sessions
645+ case extractToken authorization of
646+ Nothing {} -> onUnauth
647+ Just {value: token} ->
648+ case authenticateSession sessions token t of
649+ Unauthorized {} -> onUnauth
650+ Authorized {pubkey} -> onAuth pubkey
651+
650removeForward = \mid srv -> atomic do
652removeForward = \mid srv -> atomic do
651 forwards <- *forwards
653 forwards <- *forwards
652 set *forwards = do
654 set *forwards = do
@@ -842,8 +844,9 @@ serve = \req -> case req of
842 t <- now
844 t <- now
843 let clampedTimeout = clamp 0 maxPollTimeout timeout
845 let clampedTimeout = clamp 0 maxPollTimeout timeout
844 let deadline = t + clampedTimeout
846 let deadline = t + clampedTimeout
845− let token = extractToken authorization
847+ result <- case extractToken authorization of
848+ Nothing {} -> yield (PollUnauthorized {})
846− result <- pollLoop token cursor deadline
849+ Just {value: token} -> pollLoop token cursor deadline
847 tAfterPoll <- now
850 tAfterPoll <- now
848 maybePruneAndBroadcast tAfterPoll
851 maybePruneAndBroadcast tAfterPoll
849 yield (respond (case result of
852 yield (respond (case result of
@@ -856,12 +859,9 @@ serve = \req -> case req of
856 let clampedTs = clampTimestamp timestamp t
859 let clampedTs = clampTimestamp timestamp t
857 result <- atomic do
860 result <- atomic do
858 pr <- maybePrune t
861 pr <- maybePrune t
859− sessions <- *sessions
862+ withSessionAuth authorization t
860− let auth = authenticateSession sessions (extractToken authorization) t
861− case auth of
862− Unauthorized {} ->
863− yield {pr: pr, send: SendFailed {status: MsUnauthorized {}}}
863+ (yield {pr: pr, send: SendFailed {status: MsUnauthorized {}}})
864− Authorized {pubkey: fromKey} -> do
864+ (\fromKey -> do
865 messages <- *messages
865 messages <- *messages
866 if countMessagesFor messages to t >= maxMessagesPerRecipient
866 if countMessagesFor messages to t >= maxMessagesPerRecipient
867 then yield {pr: pr, send: SendFailed {status: MsRejected {}}}
867 then yield {pr: pr, send: SendFailed {status: MsRejected {}}}
@@ -885,7 +885,7 @@ serve = \req -> case req of
885 set *forwards = if shouldForward
885 set *forwards = if shouldForward
886 then union forwards (do s <- forwardServers; yield {messageId: msgId, toServer: s, createdAt: t, toKey: to, fromKey: fromKey, encryptedBlob: encryptedBlob, timestamp: clampedTs})
886 then union forwards (do s <- forwardServers; yield {messageId: msgId, toServer: s, createdAt: t, toKey: to, fromKey: fromKey, encryptedBlob: encryptedBlob, timestamp: clampedTs})
887 else forwards
887 else forwards
888− yield {pr: pr, send: SendDone {delivery: delivery, remoteServers: remoteServers, forwardServers: forwardServers, fromKey: fromKey}}
888+ yield {pr: pr, send: SendDone {delivery: delivery, remoteServers: remoteServers, forwardServers: forwardServers, fromKey: fromKey}})
889 case result.send of
889 case result.send of
890 SendDone {delivery, remoteServers, forwardServers, fromKey} ->
890 SendDone {delivery, remoteServers, forwardServers, fromKey} ->
891 fork (do
891 fork (do
@@ -897,9 +897,8 @@ serve = \req -> case req of
897 authorization: federationAuth})
897 authorization: federationAuth})
898 when (any forwardServers (\s -> s == server))
898 when (any forwardServers (\s -> s == server))
899 (whenOk fwdResult (removeForward msgId server)))
899 (whenOk fwdResult (removeForward msgId server)))
900− case delivery of
900+ when (case delivery of DsQueued {} -> True {}; _ -> False {})
901− DsQueued {} -> println ("sendMessage: forwards at capacity (" ++ show maxForwardsEntries ++ "), skipping forward tracking")
901+ (println ("sendMessage: forwards at capacity (" ++ show maxForwardsEntries ++ "), skipping forward tracking")))
902− _ -> yield {})
903 broadcastOfflineGossip t result.pr.peerServers result.pr.expiredLocal)
902 broadcastOfflineGossip t result.pr.peerServers result.pr.expiredLocal)
904 _ -> forkBroadcastOffline t result.pr
903 _ -> forkBroadcastOffline t result.pr
905 yield (case result.send of
904 yield (case result.send of
@@ -911,12 +910,9 @@ serve = \req -> case req of
911 let dedupedIds = dedupMessageIds messageIds
910 let dedupedIds = dedupMessageIds messageIds
912 result <- atomic do
911 result <- atomic do
913 pr <- maybePrune t
912 pr <- maybePrune t
914− sessions <- *sessions
913+ withSessionAuth authorization t
915− let auth = authenticateSession sessions (extractToken authorization) t
916− case auth of
917− Unauthorized {} ->
918− yield {pr: pr, ack: AckUnauthorized {}}
914+ (yield {pr: pr, ack: AckUnauthorized {}})
919− Authorized {pubkey} -> do
915+ (\pubkey -> do
920 messages <- *messages
916 messages <- *messages
921 let ackedMessages = do
917 let ackedMessages = do
922 m <- messages
918 m <- messages
@@ -933,7 +929,7 @@ serve = \req -> case req of
933 let evictedEntries = let excessCount = count combinedAckedIds - maxAckedIds in
929 let evictedEntries = let excessCount = count combinedAckedIds - maxAckedIds in
934 if excessCount <= 0 then [] else boundedSmallest combinedAckedIds excessCount (\a -> a.ackedAt)
930 if excessCount <= 0 then [] else boundedSmallest combinedAckedIds excessCount (\a -> a.ackedAt)
935 set *ackedIds = diff combinedAckedIds evictedEntries
931 set *ackedIds = diff combinedAckedIds evictedEntries
936− yield {pr: pr, ack: AckDone {pendingAcks: ackedFederated, evictedEntries: evictedEntries}}
932+ yield {pr: pr, ack: AckDone {pendingAcks: ackedFederated, evictedEntries: evictedEntries}})
937 fork (do
933 fork (do
938 case result.ack of
934 case result.ack of
939 AckDone {pendingAcks, evictedEntries} ->
935 AckDone {pendingAcks, evictedEntries} ->
@@ -948,12 +944,9 @@ serve = \req -> case req of
948 t <- now
944 t <- now
949 result <- atomic do
945 result <- atomic do
950 pr <- maybePrune t
946 pr <- maybePrune t
951− sessions <- *sessions
947+ withSessionAuth authorization t
952− let auth = authenticateSession sessions (extractToken authorization) t
953− case auth of
954− Unauthorized {} ->
955− yield {pr: pr, server: "", authorized: False {}}
948+ (yield {pr: pr, server: "", authorized: False {}})
956− Authorized _ -> do
949+ (\_ -> do
957 presence <- *presence
950 presence <- *presence
958 let valid = do
951 let valid = do
959 p <- presence
952 p <- presence
@@ -964,14 +957,14 @@ serve = \req -> case req of
964 let bestRemote = maxBy remoteValid (\p -> p.expiresAt)
957 let bestRemote = maxBy remoteValid (\p -> p.expiresAt)
965 let foundServer = if localOnline then serverHostN
958 let foundServer = if localOnline then serverHostN
966 else case bestRemote of Just {value: p} -> p.server; Nothing {} -> ""
959 else case bestRemote of Just {value: p} -> p.server; Nothing {} -> ""
967− yield {pr: pr, server: foundServer, authorized: True {}}
960+ yield {pr: pr, server: foundServer, authorized: True {}})
968 forkBroadcastOffline t result.pr
961 forkBroadcastOffline t result.pr
969 yield (respond {server: result.server, authorized: result.authorized})
962 yield (respond {server: result.server, authorized: result.authorized})
970
963
971 RecvGossip {events, hopsRemaining, fromServer, authorization, respond} -> do
964 RecvGossip {events, hopsRemaining, fromServer, authorization, respond} -> do
972 t <- now
965 t <- now
973 let cappedHops = clamp 0 maxGossipHops hopsRemaining
966 let cappedHops = clamp 0 maxGossipHops hopsRemaining
974− withFederationAuth authorization t respond (cappedHops < 1 || isLocalServer fromServer || count events > maxGossipEvents) (do
967+ withFederationAuth authorization t respond (cappedHops >= 1 && not (isLocalServer fromServer) && count events <= maxGossipEvents) (do
975 let validated = validGossipEvents events t
968 let validated = validGossipEvents events t
976 let onlineEntries = validated.online
969 let onlineEntries = validated.online
977 let trustedOffline = do e <- validated.offline; where e.server == fromServer; yield e
970 let trustedOffline = do e <- validated.offline; where e.server == fromServer; yield e
@@ -999,7 +992,7 @@ serve = \req -> case req of
999
992
1000 ForwardMessage {toKey, fromKey, encryptedBlob, timestamp, originServer, messageId, authorization, respond} -> do
993 ForwardMessage {toKey, fromKey, encryptedBlob, timestamp, originServer, messageId, authorization, respond} -> do
1001 t <- now
994 t <- now
1002− withFederationAuth authorization t respond (isLocalServer originServer) (do
995+ withFederationAuth authorization t respond (not (isLocalServer originServer)) (do
1003 let clampedTs = clampTimestamp timestamp t
996 let clampedTs = clampTimestamp timestamp t
1004 result <- atomic do
997 result <- atomic do
1005 pr <- maybePrune t
998 pr <- maybePrune t
@@ -1020,12 +1013,11 @@ serve = \req -> case req of
1020 forkBroadcastOffline t result.pr
1013 forkBroadcastOffline t result.pr
1021 yield (respond {ok: case result.forward of
1014 yield (respond {ok: case result.forward of
1022 ForwardRejected {} -> False {}
1015 ForwardRejected {} -> False {}
1023− ForwardDuplicate {} -> True {}
1016+ _ -> True {}}))
1024− ForwardStored {} -> True {}}))
1025
1017
1026 FederationAck {messageIds, originServer, fromServer, authorization, respond} -> do
1018 FederationAck {messageIds, originServer, fromServer, authorization, respond} -> do
1027 t <- now
1019 t <- now
1028− withFederationAuth authorization t respond (not (isLocalServer originServer) || isLocalServer fromServer) (do
1020+ withFederationAuth authorization t respond (isLocalServer originServer && not (isLocalServer fromServer)) (do
1029 let dedupedIds = dedupMessageIds messageIds
1021 let dedupedIds = dedupMessageIds messageIds
1030 pruneResult <- atomic do
1022 pruneResult <- atomic do
1031 pr <- maybePrune t
1023 pr <- maybePrune t