This commit is contained in:
Joey Hess 2016-11-17 22:06:59 -04:00
parent 27c8a4a229
commit b121078b35
No known key found for this signature in database
GPG key ID: C910D9222512E3C7

View file

@ -55,7 +55,7 @@ data Message
| SUCCESS | SUCCESS
| FAILURE | FAILURE
| DATA Len -- followed by bytes | DATA Len -- followed by bytes
| PROTO_ERROR String | ERROR String
deriving (Show) deriving (Show)
-- | Free monad for implementing actions that use the protocol. -- | Free monad for implementing actions that use the protocol.
@ -121,7 +121,7 @@ auth myuuid t = do
AUTH_SUCCESS theiruuid -> return $ Just theiruuid AUTH_SUCCESS theiruuid -> return $ Just theiruuid
AUTH_FAILURE -> return Nothing AUTH_FAILURE -> return Nothing
_ -> do _ -> do
sendMessage (PROTO_ERROR "auth failed") sendMessage (ERROR "auth failed")
return Nothing return Nothing
checkPresent :: Key -> Proto Bool checkPresent :: Key -> Proto Bool
@ -145,7 +145,7 @@ put key = do
PUT_FROM offset -> sendContent key offset PUT_FROM offset -> sendContent key offset
ALREADY_HAVE -> return True ALREADY_HAVE -> return True
_ -> do _ -> do
sendMessage (PROTO_ERROR "expected PUT_FROM") sendMessage (ERROR "expected PUT_FROM")
return False return False
-- | Serve the protocol. -- | Serve the protocol.
@ -157,7 +157,7 @@ put key = do
-- talking to a server that does not support some new feature, and fall -- talking to a server that does not support some new feature, and fall
-- back. -- back.
-- --
-- When the client sends PROTO_ERROR to the server, the server gives up, -- When the client sends ERROR to the server, the server gives up,
-- since it's not clear what state the client is is, and so not possible to -- since it's not clear what state the client is is, and so not possible to
-- recover. -- recover.
serve :: UUID -> Proto () serve :: UUID -> Proto ()
@ -175,20 +175,16 @@ serve myuuid = go Nothing
else do else do
sendMessage AUTH_FAILURE sendMessage AUTH_FAILURE
go autheduuid go autheduuid
PROTO_ERROR _ -> return () ERROR _ -> return ()
_ -> do _ -> do
case autheduuid of case autheduuid of
Just theiruuid -> authed theiruuid r Just theiruuid -> authed theiruuid r
Nothing -> sendMessage (PROTO_ERROR "must AUTH first") Nothing -> sendMessage (ERROR "must AUTH first")
go autheduuid go autheduuid
authed _theiruuid r = case r of authed _theiruuid r = case r of
CHECKPRESENT key -> do CHECKPRESENT key -> sendSuccess =<< checkContentPresent key
ok <- checkContentPresent key REMOVE key -> sendSuccess =<< removeKeyFile key
sendMessage $ if ok then SUCCESS else FAILURE
REMOVE key -> do
ok <- removeKeyFile key
sendMessage $ if ok then SUCCESS else FAILURE
PUT key -> do PUT key -> do
have <- checkContentPresent key have <- checkContentPresent key
if have if have
@ -200,7 +196,7 @@ serve myuuid = go Nothing
-- setPresent not called because the peer may have -- setPresent not called because the peer may have
-- requested the data but not permanatly stored it. -- requested the data but not permanatly stored it.
GET offset key -> void $ sendContent key offset GET offset key -> void $ sendContent key offset
_ -> sendMessage (PROTO_ERROR "unexpected command") _ -> sendMessage (ERROR "unexpected command")
sendContent :: Key -> Offset -> Proto Bool sendContent :: Key -> Offset -> Proto Bool
sendContent key offset = do sendContent key offset = do
@ -218,10 +214,10 @@ receiveContent key mkmsg = do
case r of case r of
DATA len -> do DATA len -> do
ok <- writeKeyFile key offset len =<< receiveBytes len ok <- writeKeyFile key offset len =<< receiveBytes len
sendMessage $ if ok then SUCCESS else FAILURE sendSuccess ok
return ok return ok
_ -> do _ -> do
sendMessage (PROTO_ERROR "expected DATA") sendMessage (ERROR "expected DATA")
return False return False
checkSuccess :: Proto Bool checkSuccess :: Proto Bool
@ -231,9 +227,13 @@ checkSuccess = do
SUCCESS -> return True SUCCESS -> return True
FAILURE -> return False FAILURE -> return False
_ -> do _ -> do
sendMessage (PROTO_ERROR "expected SUCCESS or FAILURE") sendMessage (ERROR "expected SUCCESS or FAILURE")
return False return False
sendSuccess :: Bool -> Proto ()
sendSuccess True = sendMessage SUCCESS
sendSuccess False = sendMessage FAILURE
-- Reads key file from an offset. The Len should correspond to -- Reads key file from an offset. The Len should correspond to
-- the length of the ByteString, but to avoid buffering the content -- the length of the ByteString, but to avoid buffering the content
-- in memory, is gotten using keyFileSize. -- in memory, is gotten using keyFileSize.
@ -260,7 +260,7 @@ instance Proto.Sendable Message where
formatMessage SUCCESS = ["SUCCESS"] formatMessage SUCCESS = ["SUCCESS"]
formatMessage FAILURE = ["FAILURE"] formatMessage FAILURE = ["FAILURE"]
formatMessage (DATA leng) = ["DATA", Proto.serialize leng] formatMessage (DATA leng) = ["DATA", Proto.serialize leng]
formatMessage (PROTO_ERROR err) = ["PROTO-ERROR", Proto.serialize err] formatMessage (ERROR err) = ["ERROR", Proto.serialize err]
instance Proto.Receivable Message where instance Proto.Receivable Message where
parseCommand "AUTH" = Proto.parse2 AUTH parseCommand "AUTH" = Proto.parse2 AUTH
@ -275,7 +275,7 @@ instance Proto.Receivable Message where
parseCommand "SUCCESS" = Proto.parse0 SUCCESS parseCommand "SUCCESS" = Proto.parse0 SUCCESS
parseCommand "FAILURE" = Proto.parse0 FAILURE parseCommand "FAILURE" = Proto.parse0 FAILURE
parseCommand "DATA" = Proto.parse1 DATA parseCommand "DATA" = Proto.parse1 DATA
parseCommand "PROTO-ERROR" = Proto.parse1 PROTO_ERROR parseCommand "ERROR" = Proto.parse1 ERROR
parseCommand _ = Proto.parseFail parseCommand _ = Proto.parseFail
instance Proto.Serializable Offset where instance Proto.Serializable Offset where