summaryrefslogtreecommitdiffhomepage
path: root/Role/Developer.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Role/Developer.hs')
-rw-r--r--Role/Developer.hs45
1 files changed, 33 insertions, 12 deletions
diff --git a/Role/Developer.hs b/Role/Developer.hs
index 604ac6d..d8d9d2c 100644
--- a/Role/Developer.hs
+++ b/Role/Developer.hs
@@ -108,8 +108,10 @@ data DeveloperState = DeveloperState
, enteredSince :: [Hash]
-- ^ Messages we've sent since the last Seen.
, lastActivity :: Hash
+ -- ^ Last Entered or Seen activity
, lastActivityTs :: POSIXTime
- -- ^ Last message sent or received.
+ , lastEntered :: Maybe Hash
+ -- ^ Last Entered activity (either from us or another developer).
, fromOtherDevelopersSince :: [Hash]
-- ^ Messages received from other developers since the last Seen.
-- (The next Seen may chain from one of these.)
@@ -126,7 +128,8 @@ data DeveloperState = DeveloperState
developerStateRecentActivity :: TVar DeveloperState -> RecentActivity
developerStateRecentActivity devstate = do
st <- readTVar devstate
- let hs = lastSeen st : enteredSince st ++ fromOtherDevelopersSince st
+ let hs = lastSeen st : fromMaybe (lastSeen st) (lastEntered st)
+ : enteredSince st ++ fromOtherDevelopersSince st
return (userSigVerifier st <> developerSigVerifier st, hs)
-- | Read things typed by the developer, and forward them to the TMChan.
@@ -154,6 +157,7 @@ sendTtyInput ichan devstate logger = go
let act = mkSigned (developerSessionKey ds) $
Activity entered
(Just $ lastActivity ds)
+ (lastEntered ds)
(mkElapsedTime (lastActivityTs ds) ts)
writeTMChan ichan (ActivityMessage act)
let acth = hash act
@@ -162,6 +166,7 @@ sendTtyInput ichan devstate logger = go
, enteredSince = enteredSince ds ++ [acth]
, lastActivity = acth
, lastActivityTs = ts
+ , lastEntered = Just acth
}
writeTVar devstate ds'
return act
@@ -203,11 +208,11 @@ sendTtyOutput ochan devstate controlinput logger = go
forwardcontrol msg = case msg of
User (ControlMessage c) -> fwd c
Developer (ControlMessage c) -> case control c of
- Rejected _ -> return ()
- SessionKey _ -> return ()
- SessionKeyAccepted _ -> return ()
- SessionKeyRejected _ -> return ()
- ChatMessage _ _ -> fwd c
+ EnteredRejected {} -> return ()
+ SessionKey {} -> return ()
+ SessionKeyAccepted {} -> return ()
+ SessionKeyRejected {} -> return ()
+ ChatMessage {} -> fwd c
_ -> return ()
fwd = atomically . writeTMChan controlinput . ControlInputAction . control
@@ -308,20 +313,21 @@ getServerMessage ochan devstate ts = do
ignore = getServerMessage ochan devstate ts
- processuser ds (ActivityMessage act@(Activity (Seen (Val b)) _ _ _)) = do
+ processuser ds (ActivityMessage act@(Activity (Seen (Val b)) _ _ _ _)) = do
let (legal, ds') = isLegalSeen act ds ts
if legal
then do
writeTVar devstate ds'
return (TtyOutput b)
else return (ProtocolError ds $ "Illegal Seen value: " ++ show act)
- processuser ds (ControlMessage (Control (Rejected _) _)) = do
+ processuser ds (ControlMessage (Control (er@EnteredRejected {}) _)) = do
-- When they rejected a message we sent,
-- anything we sent subsequently will
-- also be rejected, so forget about it.
let ds' = ds
{ sentSince = mempty
, enteredSince = mempty
+ , lastEntered = enteredLastAccepted er
}
writeTVar devstate ds'
return Beep
@@ -345,8 +351,8 @@ getServerMessage ochan devstate ts = do
--
-- Does not check the signature.
isLegalSeen :: Activity Seen -> DeveloperState -> POSIXTime -> (Bool, DeveloperState)
-isLegalSeen (Activity _ Nothing _ _) ds _ = (False, ds)
-isLegalSeen act@(Activity (Seen (Val b)) (Just hp) _ _) ds ts
+isLegalSeen (Activity _ Nothing _ _ _) ds _ = (False, ds)
+isLegalSeen act@(Activity (Seen (Val b)) (Just hp) _ _ _) ds ts
-- Does it chain to the last Seen activity or to
-- something sent by another developer since the last Seen?
| hp == lastSeen ds || hp `elem` fromOtherDevelopersSince ds =
@@ -364,6 +370,7 @@ isLegalSeen act@(Activity (Seen (Val b)) (Just hp) _ _) ds ts
, enteredSince = es'
, lastActivity = acth
, lastActivityTs = ts
+ , lastEntered = newlastentered
, fromOtherDevelopersSince = mempty
}
-- Does it chain to something we've entered since the last Seen
@@ -384,12 +391,25 @@ isLegalSeen act@(Activity (Seen (Val b)) (Just hp) _ _) ds ts
, enteredSince = es'
, lastActivity = acth
, lastActivityTs = ts
+ , lastEntered = newlastentered
, fromOtherDevelopersSince = mempty
}
where
acth = hash act
yes ds' = (True, ds')
+ -- If there are multiple developers, need to set our lastEntered
+ -- to the prevEntered from the Activity Seen, so we can follow on to
+ -- another developer's activity.
+ --
+ -- But, if there's lag, we may have sent some Activity Entered
+ -- that had not reached the user yet when it constructed the
+ -- Activity Seen, so check if the prevEntered is one of the
+ -- things we've enteredSince; if so keep our lastEntered.
+ newlastentered = case prevEntered act of
+ Just v | v `notElem` enteredSince ds -> Just v
+ _ -> lastEntered ds
+
-- | Start by reading the initial two messages from the user,
-- their session key and the startup message.
processSessionStart :: MySessionKey -> TMChan (MissingHashes AnyMessage) -> Logger -> TMVar (TVar DeveloperState) -> IO (TVar DeveloperState, Output)
@@ -412,7 +432,7 @@ processSessionStart sk ochan logger dsv = do
<$> atomically (readTMChan ochan)
logger startmsg
let (starthash, output) = case startmsg of
- User (ActivityMessage act@(Activity (Seen (Val b)) Nothing _ _))
+ User (ActivityMessage act@(Activity (Seen (Val b)) Nothing Nothing _ _))
| verifySigned sigverifier act ->
(hash act, TtyOutput b)
| otherwise ->
@@ -424,6 +444,7 @@ processSessionStart sk ochan logger dsv = do
, enteredSince = mempty
, lastActivity = starthash
, lastActivityTs = ts
+ , lastEntered = Nothing
, fromOtherDevelopersSince = mempty
, developerSessionKey = sk
, userSigVerifier = sigverifier