pairing works!!
Finally. Last bug fixes here: Send PairResp with same UUID in the PairReq. Fix off-by-one in code that filters out our own pairing messages. Also reworked the pairing alerts, which are still slightly buggy.
This commit is contained in:
parent
aace44454a
commit
2c1ceeeaf9
6 changed files with 51 additions and 40 deletions
|
@ -32,7 +32,7 @@ data AlertName
|
|||
= FileAlert TenseChunk
|
||||
| SanityCheckFixAlert
|
||||
| WarningAlert String
|
||||
| PairRequestReceivedAlert String
|
||||
| PairAlert String
|
||||
deriving (Eq)
|
||||
|
||||
{- The first alert is the new alert, the second is an old alert.
|
||||
|
@ -293,18 +293,27 @@ pairingAlert button = baseActivityAlert
|
|||
, alertButton = Just button
|
||||
}
|
||||
|
||||
pairRequestReceivedAlert :: String -> String -> AlertButton -> Alert
|
||||
pairRequestReceivedAlert repo msg button = Alert
|
||||
pairRequestReceivedAlert :: String -> AlertButton -> Alert
|
||||
pairRequestReceivedAlert repo button = Alert
|
||||
{ alertClass = Message
|
||||
, alertHeader = Nothing
|
||||
, alertMessageRender = tenseWords
|
||||
, alertData = [UnTensed $ T.pack msg]
|
||||
, alertData = [UnTensed $ T.pack $ repo ++ " is sending a pair request."]
|
||||
, alertBlockDisplay = False
|
||||
, alertPriority = High
|
||||
, alertClosable = True
|
||||
, alertIcon = Just InfoIcon
|
||||
, alertName = Just $ PairRequestReceivedAlert repo
|
||||
, alertCombiner = Just $ dataCombiner $ const id
|
||||
, alertName = Just $ PairAlert repo
|
||||
, alertCombiner = Just $ dataCombiner $ \_old new -> new
|
||||
, alertButton = Just button
|
||||
}
|
||||
|
||||
pairRequestAcknowledgedAlert :: String -> AlertButton -> Alert
|
||||
pairRequestAcknowledgedAlert repo button = baseActivityAlert
|
||||
{ alertData = ["Pair request with", UnTensed (T.pack repo), Tensed "in progress" "complete"]
|
||||
, alertPriority = High
|
||||
, alertName = Just $ PairAlert repo
|
||||
, alertCombiner = Just $ dataCombiner $ \_old new -> new
|
||||
, alertButton = Just button
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ data PairingInProgress = PairingInProgress
|
|||
, inProgressPairData :: PairData
|
||||
, inProgressPairStage :: PairStage
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
data SomeAddr = IPv4Addr HostAddress | IPv6Addr HostAddress6
|
||||
deriving (Ord, Eq, Read, Show)
|
||||
|
|
|
@ -58,14 +58,14 @@ multicastPairMsg repeats secret pairdata stage = go M.empty repeats
|
|||
threadDelaySeconds (Seconds 2)
|
||||
go cache' $ pred <$> n
|
||||
sendinterface cache i = void $ catchMaybeIO $
|
||||
withSocketsDo $ bracket
|
||||
(multicastSender (multicastAddress i) pairingPort)
|
||||
(sClose . fst)
|
||||
(\(sock, addr) -> do
|
||||
withSocketsDo $ bracket setup cleanup use
|
||||
where
|
||||
setup = multicastSender (multicastAddress i) pairingPort
|
||||
cleanup (sock, _) = sClose sock -- FIXME does not work
|
||||
use (sock, addr) = do
|
||||
setInterface sock (showAddr i)
|
||||
maybe noop (\s -> void $ sendTo sock s addr)
|
||||
(M.lookup i cache)
|
||||
)
|
||||
updatecache cache [] = cache
|
||||
updatecache cache (i:is)
|
||||
| M.member i cache = updatecache cache is
|
||||
|
@ -106,3 +106,19 @@ activeNetworkAddresses :: IO [SomeAddr]
|
|||
activeNetworkAddresses = filter (not . all (`elem` "0.:") . showAddr)
|
||||
. concat . map (\ni -> [toSomeAddr $ ipv4 ni, toSomeAddr $ ipv6 ni])
|
||||
<$> getNetworkInterfaces
|
||||
|
||||
{- A human-visible description of the repository being paired with.
|
||||
- Note that the repository's description is not shown to the user, because
|
||||
- it could be something like "my repo", which is confusing when pairing
|
||||
- with someone else's repo. However, this has the same format as the
|
||||
- default decription of a repo. -}
|
||||
pairRepo :: PairMsg -> String
|
||||
pairRepo msg = concat
|
||||
[ remoteUserName d
|
||||
, "@"
|
||||
, fromMaybe (showAddr $ pairMsgAddr msg) (remoteHostName d)
|
||||
, ":"
|
||||
, remoteDirectory d
|
||||
]
|
||||
where
|
||||
d = pairMsgData msg
|
||||
|
|
|
@ -32,6 +32,9 @@ data SshKeyPair = SshKeyPair
|
|||
, sshPrivKey :: String
|
||||
}
|
||||
|
||||
instance Show SshKeyPair where
|
||||
show = sshPubKey
|
||||
|
||||
type SshPubKey = String
|
||||
|
||||
{- ssh -ofoo=bar command-line option -}
|
||||
|
|
|
@ -17,7 +17,6 @@ import Assistant.DaemonStatus
|
|||
import Assistant.WebApp
|
||||
import Assistant.WebApp.Types
|
||||
import Assistant.Alert
|
||||
import Utility.Tense
|
||||
|
||||
import Network.Multicast
|
||||
import Network.Socket
|
||||
|
@ -40,7 +39,7 @@ pairListenerThread st dstatus scanremotes urlrenderer = thread $ withSocketsDo $
|
|||
sane <- checkSane msg
|
||||
(pip, verified) <- verificationCheck m
|
||||
=<< (pairingInProgress <$> getDaemonStatus dstatus)
|
||||
let wrongstage = maybe False (\p -> pairMsgStage m < inProgressPairStage p) pip
|
||||
let wrongstage = maybe False (\p -> pairMsgStage m <= inProgressPairStage p) pip
|
||||
case (wrongstage, sane, pairMsgStage m) of
|
||||
-- ignore our own messages, and
|
||||
-- out of order messages
|
||||
|
@ -107,32 +106,13 @@ pairReqReceived True _ _ _ = noop -- ignore our own PairReq
|
|||
pairReqReceived False dstatus urlrenderer msg = do
|
||||
url <- renderUrl urlrenderer (FinishPairR msg) []
|
||||
void $ addAlert dstatus $ pairRequestReceivedAlert repo
|
||||
(repo ++ " is sending a pair request.") $
|
||||
AlertButton
|
||||
{ buttonUrl = url
|
||||
, buttonLabel = T.pack "Respond"
|
||||
, buttonAction = Just onclick
|
||||
, buttonAction = Nothing
|
||||
}
|
||||
where
|
||||
pairdata = pairMsgData msg
|
||||
repo = concat
|
||||
[ remoteUserName pairdata
|
||||
, "@"
|
||||
, fromMaybe (showAddr $ pairMsgAddr msg)
|
||||
(remoteHostName pairdata)
|
||||
, ":"
|
||||
, (remoteDirectory pairdata)
|
||||
]
|
||||
{- Remove the button when it's clicked, and change the
|
||||
- alert to be in progress. This alert cannot be entirely
|
||||
- removed since more pair request messages are coming in
|
||||
- and would re-add it. -}
|
||||
onclick i = updateAlert dstatus i $ \alert -> Just $ alert
|
||||
{ alertButton = Nothing
|
||||
, alertClass = Activity
|
||||
, alertIcon = Just ActivityIcon
|
||||
, alertData = [UnTensed $ T.pack $ "pair request with " ++ repo ++ " in progress"]
|
||||
}
|
||||
repo = pairRepo msg
|
||||
|
||||
{- When a verified PairAck is seen, a host is ready to pair with us, and has
|
||||
- already configured our ssh key. Stop sending PairReqs, finish the pairing,
|
||||
|
|
|
@ -42,7 +42,7 @@ import Control.Concurrent
|
|||
{- Starts sending out pair requests. -}
|
||||
getStartPairR :: Handler RepHtml
|
||||
#ifdef WITH_PAIRING
|
||||
getStartPairR = promptSecret Nothing $ startPairing PairReq noop
|
||||
getStartPairR = promptSecret Nothing $ startPairing PairReq noop pairingAlert Nothing
|
||||
#else
|
||||
getStartPairR = noPairing
|
||||
#endif
|
||||
|
@ -54,11 +54,13 @@ getFinishPairR :: PairMsg -> Handler RepHtml
|
|||
#ifdef WITH_PAIRING
|
||||
getFinishPairR msg = promptSecret (Just msg) $ \_ secret -> do
|
||||
liftIO $ setup
|
||||
startPairing PairAck cleanup "" secret
|
||||
startPairing PairAck cleanup alert uuid "" secret
|
||||
where
|
||||
alert = pairRequestAcknowledgedAlert $ pairRepo msg
|
||||
setup = setupAuthorizedKeys msg
|
||||
cleanup = removeAuthorizedKeys False $
|
||||
remoteSshPubKey $ pairMsgData msg
|
||||
uuid = Just $ pairUUID $ pairMsgData msg
|
||||
#else
|
||||
getFinishPairR _ = noPairing
|
||||
#endif
|
||||
|
@ -83,8 +85,8 @@ getInprogressPairR _ = noPairing
|
|||
-
|
||||
- Redirects to the pairing in progress page.
|
||||
-}
|
||||
startPairing :: PairStage -> IO () -> Text -> Secret -> Widget
|
||||
startPairing stage oncancel displaysecret secret = do
|
||||
startPairing :: PairStage -> IO () -> (AlertButton -> Alert) -> Maybe UUID -> Text -> Secret -> Widget
|
||||
startPairing stage oncancel alert muuid displaysecret secret = do
|
||||
keypair <- liftIO $ genSshKeyPair
|
||||
dstatus <- daemonStatus <$> lift getYesod
|
||||
urlrender <- lift getUrlRender
|
||||
|
@ -93,7 +95,7 @@ startPairing stage oncancel displaysecret secret = do
|
|||
<*> liftIO getUserName
|
||||
<*> (fromJust . relDir <$> lift getYesod)
|
||||
<*> pure (sshPubKey keypair)
|
||||
<*> liftIO genUUID
|
||||
<*> liftIO (maybe genUUID return muuid)
|
||||
liftIO $ do
|
||||
let sender = multicastPairMsg Nothing secret pairdata
|
||||
let pip = PairingInProgress secret Nothing keypair pairdata stage
|
||||
|
@ -117,7 +119,7 @@ startPairing stage oncancel displaysecret secret = do
|
|||
oncancel
|
||||
killThread tid
|
||||
}
|
||||
alertDuring dstatus (pairingAlert selfdestruct) $ do
|
||||
alertDuring dstatus (alert selfdestruct) $ do
|
||||
_ <- E.try (sender stage) :: IO (Either E.SomeException ())
|
||||
return ()
|
||||
|
||||
|
|
Loading…
Reference in a new issue