diff options
author | joe <joe@jerkface.net> | 2017-08-11 01:08:30 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2017-08-11 01:08:30 -0400 |
commit | cd5091c4a3ab1c05b48ff3ad2fea666d77b8e39c (patch) | |
tree | 45bd1073d40830e6311bbaf8021899fec236abbc | |
parent | 85a004ac92cac382a8c2824ca6b584764ab7782d (diff) |
Reply to Announce with AnnounceResponse.
-rw-r--r-- | Tox.hs | 144 | ||||
-rw-r--r-- | ToxMessage.hs | 124 | ||||
-rw-r--r-- | src/Network/QueryResponse.hs | 10 |
3 files changed, 182 insertions, 96 deletions
@@ -3,6 +3,7 @@ | |||
3 | {-# LANGUAGE DeriveFunctor #-} | 3 | {-# LANGUAGE DeriveFunctor #-} |
4 | {-# LANGUAGE DeriveGeneric #-} | 4 | {-# LANGUAGE DeriveGeneric #-} |
5 | {-# LANGUAGE DeriveTraversable #-} | 5 | {-# LANGUAGE DeriveTraversable #-} |
6 | {-# LANGUAGE ExistentialQuantification #-} | ||
6 | {-# LANGUAGE FlexibleInstances #-} | 7 | {-# LANGUAGE FlexibleInstances #-} |
7 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} | 8 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} |
8 | {-# LANGUAGE NamedFieldPuns #-} | 9 | {-# LANGUAGE NamedFieldPuns #-} |
@@ -12,6 +13,8 @@ | |||
12 | {-# LANGUAGE TupleSections #-} | 13 | {-# LANGUAGE TupleSections #-} |
13 | module Tox where | 14 | module Tox where |
14 | 15 | ||
16 | import Debug.Trace | ||
17 | import Control.Exception hiding (Handler) | ||
15 | import Control.Applicative | 18 | import Control.Applicative |
16 | import Control.Arrow | 19 | import Control.Arrow |
17 | import Control.Concurrent (MVar) | 20 | import Control.Concurrent (MVar) |
@@ -75,10 +78,11 @@ import System.IO | |||
75 | import qualified Text.ParserCombinators.ReadP as RP | 78 | import qualified Text.ParserCombinators.ReadP as RP |
76 | import Text.Printf | 79 | import Text.Printf |
77 | import Text.Read | 80 | import Text.Read |
78 | import qualified ToxMessage as Tox | 81 | import ToxMessage as Tox hiding (Ping,Pong,SendNodes,GetNodes,AnnounceResponse) |
79 | ;import ToxMessage (bin2hex, quoted) | 82 | ;import ToxMessage (bin2hex, quoted) |
80 | import TriadCommittee | 83 | import TriadCommittee |
81 | import Network.BitTorrent.DHT.Token as Token | 84 | import Network.BitTorrent.DHT.Token as Token |
85 | import GHC.TypeLits | ||
82 | 86 | ||
83 | {- | 87 | {- |
84 | newtype NodeId = NodeId ByteString | 88 | newtype NodeId = NodeId ByteString |
@@ -235,53 +239,13 @@ data TransactionId = TransactionId | |||
235 | , cryptoNonce :: Tox.Nonce24 -- ^ Used during the encryption layer. | 239 | , cryptoNonce :: Tox.Nonce24 -- ^ Used during the encryption layer. |
236 | } | 240 | } |
237 | 241 | ||
238 | pattern PingType = Tox.PacketKind 0 -- 0x00 Ping Request | ||
239 | pattern PongType = Tox.PacketKind 1 -- 0x01 Ping Response | ||
240 | pattern GetNodesType = Tox.PacketKind 2 -- 0x02 Nodes Request | ||
241 | pattern SendNodesType = Tox.PacketKind 4 -- 0x04 Nodes Response | ||
242 | -- 0x18 Cookie Request | 242 | -- 0x18 Cookie Request |
243 | -- 0x19 Cookie Response | 243 | -- 0x19 Cookie Response |
244 | -- 0x1a Crypto Handshake | 244 | -- 0x1a Crypto Handshake |
245 | -- 0x1b Crypto Data | 245 | -- 0x1b Crypto Data |
246 | 246 | ||
247 | -- TODO: Auth fail: | ||
248 | pattern DHTRequestType = Tox.PacketKind 32 -- 0x20 DHT Request | ||
249 | |||
250 | -- 0x21 LAN Discovery | 247 | -- 0x21 LAN Discovery |
251 | 248 | ||
252 | -- TODO: Auth fail: | ||
253 | pattern OnionRequest0 = Tox.PacketKind 128 -- 0x80 Onion Request 0 | ||
254 | pattern OnionRequest1 = Tox.PacketKind 129 -- 0x81 Onion Request 1 | ||
255 | pattern OnionRequest2 = Tox.PacketKind 130 -- 0x82 Onion Request 2 | ||
256 | pattern AnnounceType = Tox.PacketKind 131 -- 0x83 Announce Request | ||
257 | pattern AnnounceResponseType = Tox.PacketKind 132 -- 0x84 Announce Response | ||
258 | -- 0x85 Onion Data Request (data to route request packet) | ||
259 | -- 0x86 Onion Data Response (data to route response packet) | ||
260 | -- 0x8c Onion Response 3 | ||
261 | -- 0x8d Onion Response 2 | ||
262 | pattern OnionResponse1 = Tox.PacketKind 142 -- 0x8e Onion Response 1 | ||
263 | -- 0xf0 Bootstrap Info | ||
264 | |||
265 | -- TODO Fix these fails... | ||
266 | -- GetNodesType decipherAndAuth: auth fail | ||
267 | -- MessageType 128 decipherAndAuth: auth fail | ||
268 | -- MessageType 129 decipherAndAuth: auth fail | ||
269 | -- MessageType 130 decipherAndAuth: auth fail | ||
270 | -- MessageType 131 decipherAndAuth: auth fail | ||
271 | -- MessageType 32 decipherAndAuth: auth fail | ||
272 | |||
273 | |||
274 | instance Show Tox.PacketKind where | ||
275 | showsPrec d PingType = mappend "PingType" | ||
276 | showsPrec d PongType = mappend "PongType" | ||
277 | showsPrec d GetNodesType = mappend "GetNodesType" | ||
278 | showsPrec d SendNodesType = mappend "SendNodesType" | ||
279 | showsPrec d DHTRequestType = mappend "DHTRequestType" | ||
280 | showsPrec d OnionRequest0 = mappend "OnionRequest0" | ||
281 | showsPrec d OnionResponse1 = mappend "OnionResponse1" | ||
282 | showsPrec d AnnounceType = mappend "AnnounceType" | ||
283 | showsPrec d (Tox.PacketKind x) = mappend "PacketKind " . showsPrec (d+1) x | ||
284 | |||
285 | {- | 249 | {- |
286 | newtype Tox.Nonce24 = Tox.Nonce24 ByteString | 250 | newtype Tox.Nonce24 = Tox.Nonce24 ByteString |
287 | deriving (Eq, Ord, ByteArrayAccess) | 251 | deriving (Eq, Ord, ByteArrayAccess) |
@@ -317,8 +281,8 @@ data Msg = Msg | |||
317 | deriving Show | 281 | deriving Show |
318 | 282 | ||
319 | 283 | ||
320 | typeHasEncryptedPayload OnionResponse1 = False | 284 | -- typeHasEncryptedPayload OnionResponse1Type = False |
321 | typeHasEncryptedPayload _ = True | 285 | -- typeHasEncryptedPayload _ = True |
322 | 286 | ||
323 | {- | 287 | {- |
324 | msgDHTKey Message{ msgOrigin, msgType = PingType } = Just msgOrigin | 288 | msgDHTKey Message{ msgOrigin, msgType = PingType } = Just msgOrigin |
@@ -579,42 +543,60 @@ encodePacket sk cache msg ni = ( S.runPut . putMessage $ encryptMessage sk cache | |||
579 | , nodeAddr ni ) | 543 | , nodeAddr ni ) |
580 | -} | 544 | -} |
581 | 545 | ||
546 | data ToxPath = forall n. (Tox.OnionPacket n) => ToxPath NodeInfo (Tox.ReturnPath n) | ||
547 | |||
548 | instance Show ToxPath where | ||
549 | show (ToxPath ni rpath) | ||
550 | | natVal rpath == 0 = show ni | ||
551 | | otherwise = "Aliased("++show ni++")" | ||
552 | |||
582 | msgLayer :: SecretKey | 553 | msgLayer :: SecretKey |
583 | -> NodeId | 554 | -> NodeId |
584 | -> Transport String NodeInfo (Tox.PacketKind,InterediateRep) | 555 | -> Transport String ToxPath (Tox.PacketKind,InterediateRep) |
585 | -> Transport String NodeInfo Msg | 556 | -> Transport String ToxPath Msg |
586 | msgLayer sk pk = layerTransport parse serialize | 557 | msgLayer sk pk = layerTransport parse serialize |
587 | where | 558 | where |
559 | parse :: (Tox.PacketKind,InterediateRep) -> ToxPath -> Either String (Msg,ToxPath) | ||
588 | parse (typ,Assym x) addr = fmap (,addr) $ decryptAssymetric sk typ x | 560 | parse (typ,Assym x) addr = fmap (,addr) $ decryptAssymetric sk typ x |
589 | parse (typ,Assym' x) addr = fmap (,addr) $ decryptAssymetric sk typ x | 561 | parse (typ,Assym' x) addr = fmap (,addr) $ decryptAssymetric sk typ x |
590 | parse (typ,Unclm n x) addr = Right ( Msg typ (Tox.assymetricNonce x) (S.encode (Tox.assymetricData x)) n | 562 | parse (typ,Unclm n x) addr = Right ( Msg typ (Tox.assymetricNonce x) (S.encode (Tox.assymetricData x)) n |
591 | , addr) | 563 | , addr) |
592 | serialize x addr = case Tox.pktClass (msgType x) of | 564 | serialize :: Msg -> ToxPath -> ((Tox.PacketKind,InterediateRep),ToxPath) |
593 | Tox.AssymetricClass {} -> ((msgType x, Assym $ encryptAssymetric sk pk (nodeId addr) x), addr) | 565 | serialize x addr@(ToxPath ni _) = case Tox.pktClass (msgType x) of |
594 | Tox.AliasedClass {} -> ((msgType x, Assym' $ encryptAssymetric sk pk (nodeId addr) x), addr) | 566 | Tox.AssymetricClass {} -> ((msgType x, Assym $ encryptAssymetric sk pk (nodeId ni) x), addr) |
595 | Tox.NoncedUnclaimedClass {} -> ((msgType x, Unclm (msgSendBack x) $ encryptUnclm sk pk (nodeId addr) x),addr) | 567 | Tox.AliasedClass {} -> ((msgType x, Assym' $ encryptAssymetric sk pk (nodeId ni) x), addr) |
568 | Tox.NoncedUnclaimedClass {} -> ((msgType x, Unclm (msgSendBack x) $ encryptUnclm sk pk (nodeId ni) x),addr) | ||
596 | 569 | ||
597 | data InterediateRep = Assym Tox.Assymetric | 570 | data InterediateRep = Assym Tox.Assymetric |
598 | | Assym' Tox.Assymetric | 571 | | Assym' Tox.Assymetric |
599 | | Unclm Tox.Nonce8 Tox.UnclaimedAssymetric | 572 | | Unclm Tox.Nonce8 Tox.UnclaimedAssymetric |
600 | 573 | ||
601 | asymLayer :: Transport String SockAddr Tox.Packet -> Transport String NodeInfo (Tox.PacketKind,InterediateRep) | 574 | asymLayer :: Transport String SockAddr Tox.Packet -> Transport String ToxPath (Tox.PacketKind,InterediateRep) |
602 | asymLayer = layerTransport parse serialize | 575 | asymLayer = layerTransport parse (\p@(typ,_) -> trace ("SERIALIZE "++show typ) $ serialize p) |
603 | where | 576 | where |
577 | parse :: Tox.Packet -> SockAddr -> Either String ((Tox.PacketKind,InterediateRep),ToxPath) | ||
604 | parse x addr = case Tox.pktClass (Tox.pktKind x) of | 578 | parse x addr = case Tox.pktClass (Tox.pktKind x) of |
605 | Tox.AssymetricClass top fromp -> go Tox.senderKey fromp Assym | 579 | Tox.AssymetricClass top fromp -> go Tox.senderKey fromp Assym |
606 | Tox.AliasedClass top fromp -> go Tox.senderKey ((\(Tox.Aliased a) -> a) . fromp) Assym' | 580 | Tox.AliasedClass top fromp -> let (Tox.Aliased a,rpath) = fromp x |
581 | in fmap (\ni -> ( (Tox.pktKind x, Assym' a) | ||
582 | , ToxPath ni rpath )) | ||
583 | $ nodeInfo (Tox.senderKey a) addr | ||
607 | Tox.NoncedUnclaimedClass top fromp -> go (const zeroID) fromp (uncurry Unclm) | 584 | Tox.NoncedUnclaimedClass top fromp -> go (const zeroID) fromp (uncurry Unclm) |
585 | -- OnionClass | ||
608 | where go mkaddr fromp c = let y = fromp x | 586 | where go mkaddr fromp c = let y = fromp x |
609 | in fmap ((Tox.pktKind x,c y),) | 587 | in fmap ( ((Tox.pktKind x,c y),) |
610 | $ nodeInfo (mkaddr y) addr | 588 | . (\ni -> ToxPath ni Tox.emptyReturnPath) |
589 | ) | ||
590 | $ nodeInfo (mkaddr y) addr | ||
611 | 591 | ||
612 | serialize (typ,Assym assym) addr = (x,nodeAddr addr) | 592 | serialize :: (Tox.PacketKind,InterediateRep) -> ToxPath -> (Tox.Packet,SockAddr) |
593 | serialize (typ,Assym assym) (ToxPath addr rpath) = (x,nodeAddr addr) | ||
613 | where x = case Tox.pktClass typ of Tox.AssymetricClass top _ -> top assym | 594 | where x = case Tox.pktClass typ of Tox.AssymetricClass top _ -> top assym |
614 | serialize (typ,Assym' assym) addr = (x,nodeAddr addr) | 595 | serialize (typ,Assym' assym) (ToxPath addr rpath) = (x,nodeAddr addr) -- TODO rpath |
615 | where x = case Tox.pktClass typ of Tox.AliasedClass top _ -> top (Tox.Aliased assym) | 596 | where x = case Tox.pktClass typ of Tox.AliasedClass top _ -> top (Tox.Aliased assym, error "todo: ReturnPath") |
616 | serialize (typ,Unclm nonce unclm) addr = (x,nodeAddr addr) | 597 | serialize (typ,Unclm nonce unclm) (ToxPath addr rpath) = (Tox.mkOnion rpath x,nodeAddr addr) |
617 | where x = case Tox.pktClass typ of Tox.NoncedUnclaimedClass top _ -> top nonce unclm | 598 | where x = case Tox.pktClass typ of Tox.NoncedUnclaimedClass top _ -> top nonce unclm |
599 | -- OnionClass | ||
618 | 600 | ||
619 | toxLayer :: Transport String SockAddr ByteString -> Transport String SockAddr Tox.Packet | 601 | toxLayer :: Transport String SockAddr ByteString -> Transport String SockAddr Tox.Packet |
620 | toxLayer = layerTransport (\x addr -> (,addr) <$> S.decode x) | 602 | toxLayer = layerTransport (\x addr -> (,addr) <$> S.decode x) |
@@ -630,7 +612,7 @@ data Routing = Routing | |||
630 | , committee6 :: TriadCommittee NodeId SockAddr | 612 | , committee6 :: TriadCommittee NodeId SockAddr |
631 | } | 613 | } |
632 | 614 | ||
633 | type ToxClient = Client String Tox.PacketKind TransactionId NodeInfo Msg | 615 | type ToxClient = Client String Tox.PacketKind TransactionId ToxPath Msg |
634 | 616 | ||
635 | encodePayload :: S.Serialize b => Tox.PacketKind -> TransactionId -> addr -> addr -> b -> Msg | 617 | encodePayload :: S.Serialize b => Tox.PacketKind -> TransactionId -> addr -> addr -> b -> Msg |
636 | encodePayload typ (TransactionId nonce8 nonce24) _ _ b = Msg typ nonce24 (S.encode b) nonce8 | 618 | encodePayload typ (TransactionId nonce8 nonce24) _ _ b = Msg typ nonce24 (S.encode b) nonce8 |
@@ -645,6 +627,7 @@ trimPackets addr bs = do | |||
645 | GetNodesType -> Just id | 627 | GetNodesType -> Just id |
646 | AnnounceType -> Just id | 628 | AnnounceType -> Just id |
647 | AnnounceResponseType -> Just id | 629 | AnnounceResponseType -> Just id |
630 | OnionResponse3Type -> Just id | ||
648 | _ -> Nothing | 631 | _ -> Nothing |
649 | 632 | ||
650 | newClient :: SockAddr -> IO (ToxClient, Routing) | 633 | newClient :: SockAddr -> IO (ToxClient, Routing) |
@@ -767,14 +750,15 @@ newClient addr = do | |||
767 | -> ToxClient | 750 | -> ToxClient |
768 | mkclient (tbl,var) handlers = Client | 751 | mkclient (tbl,var) handlers = Client |
769 | { clientNet = net | 752 | { clientNet = net |
770 | , clientDispatcher = dispatch tbl var handlers | 753 | , clientDispatcher = dispatch tbl var (fmap (contramapAddr (\(ToxPath ni _) -> ni)) . handlers) |
771 | , clientErrorReporter = (printErrors stderr) { reportTimeout = reportTimeout ignoreErrors } | 754 | , clientErrorReporter = (printErrors stderr) { reportTimeout = reportTimeout ignoreErrors } |
772 | , clientPending = var | 755 | , clientPending = var |
773 | , clientAddress = \maddr -> atomically $ do | 756 | , clientAddress = \maddr -> atomically $ do |
774 | let var = case flip prefer4or6 Nothing <$> maddr of | 757 | let var = case flip prefer4or6 Nothing . (\(ToxPath ni _) -> ni) <$> maddr of |
775 | Just Want_IP6 -> routing6 routing | 758 | Just Want_IP6 -> routing6 routing |
776 | _ -> routing4 routing | 759 | _ -> routing4 routing |
777 | R.thisNode <$> readTVar var | 760 | a <- readTVar var |
761 | return $ ToxPath (R.thisNode a) Tox.emptyReturnPath | ||
778 | , clientResponseId = genNonce24 var | 762 | , clientResponseId = genNonce24 var |
779 | } | 763 | } |
780 | 764 | ||
@@ -847,6 +831,7 @@ addVerbosity2 tr = | |||
847 | forM_ m $ mapM_ $ \(msg,addr) -> do | 831 | forM_ m $ mapM_ $ \(msg,addr) -> do |
848 | hPutStrLn stderr ( (show addr) | 832 | hPutStrLn stderr ( (show addr) |
849 | ++ " -2-> " ++ show (Tox.PacketKind $ B.head msg)) | 833 | ++ " -2-> " ++ show (Tox.PacketKind $ B.head msg)) |
834 | -- forM_ (xxd 0 msg) (hPutStrLn stderr) | ||
850 | kont m | 835 | kont m |
851 | , sendMessage = \addr msg -> do | 836 | , sendMessage = \addr msg -> do |
852 | hPutStrLn stderr ( (show addr) | 837 | hPutStrLn stderr ( (show addr) |
@@ -863,16 +848,19 @@ classify (Msg { msgType = typ | |||
863 | , msgNonce = nonce24 }) = go $ TransactionId nonce8 nonce24 | 848 | , msgNonce = nonce24 }) = go $ TransactionId nonce8 nonce24 |
864 | where | 849 | where |
865 | go = case typ of | 850 | go = case typ of |
866 | PingType -> IsQuery typ | 851 | PingType -> IsQuery typ |
867 | GetNodesType -> IsQuery typ | 852 | GetNodesType -> IsQuery typ |
868 | PongType -> IsResponse | 853 | PongType -> IsResponse |
869 | SendNodesType -> IsResponse | 854 | SendNodesType -> IsResponse |
870 | DHTRequestType -> IsQuery typ | 855 | OnionResponse1Type -> IsResponse |
871 | OnionRequest0 -> IsQuery typ | 856 | OnionResponse2Type -> IsResponse |
872 | OnionRequest1 -> IsQuery typ | 857 | OnionResponse3Type -> IsResponse |
873 | OnionRequest2 -> IsQuery typ | 858 | DHTRequestType -> IsQuery typ |
874 | AnnounceType -> IsQuery typ | 859 | OnionRequest0Type -> IsQuery typ |
875 | _ -> const $ IsUnknown ("Unknown message type: "++show typ) | 860 | OnionRequest1Type -> IsQuery typ |
861 | OnionRequest2Type -> IsQuery typ | ||
862 | AnnounceType -> IsQuery typ | ||
863 | _ -> const $ IsUnknown ("Unknown message type: "++show typ) | ||
876 | 864 | ||
877 | {- | 865 | {- |
878 | encodePayload typ (TransactionId (Tox.Nonce8 tid) nonce) self dest b | 866 | encodePayload typ (TransactionId (Tox.Nonce8 tid) nonce) self dest b |
@@ -905,13 +893,14 @@ transitionCommittee committee (RoutingTransition ni Stranger) = do | |||
905 | hPutStrLn stderr $ "delVote "++show (nodeId ni) | 893 | hPutStrLn stderr $ "delVote "++show (nodeId ni) |
906 | transitionCommittee committee _ = return $ return () | 894 | transitionCommittee committee _ = return $ return () |
907 | 895 | ||
908 | updateRouting :: ToxClient -> Routing -> NodeInfo -> (Tox.PacketKind, InterediateRep) -> IO () | 896 | updateRouting :: ToxClient -> Routing -> ToxPath -> (Tox.PacketKind, InterediateRep) -> IO () |
909 | updateRouting client routing naddr (typ,Assym msg) = do | 897 | updateRouting client routing (ToxPath naddr _) (typ,Assym msg) = do |
910 | hPutStrLn stderr $ "updateRouting "++show typ | 898 | hPutStrLn stderr $ "updateRouting "++show typ |
911 | case prefer4or6 naddr Nothing of | 899 | case prefer4or6 naddr Nothing of |
912 | Want_IP4 -> updateTable client naddr (routing4 routing) (committee4 routing) (sched4 routing) | 900 | Want_IP4 -> updateTable client naddr (routing4 routing) (committee4 routing) (sched4 routing) |
913 | Want_IP6 -> updateTable client naddr (routing6 routing) (committee6 routing) (sched6 routing) | 901 | Want_IP6 -> updateTable client naddr (routing6 routing) (committee6 routing) (sched6 routing) |
914 | updateRouting _ _ _ _ = return () | 902 | updateRouting _ _ _ (typ,_) = do |
903 | hPutStrLn stderr $ "updateRouting (ignored) "++show typ | ||
915 | 904 | ||
916 | updateTable client naddr tbl committee sched = do | 905 | updateTable client naddr tbl committee sched = do |
917 | self <- atomically $ R.thisNode <$> readTVar tbl | 906 | self <- atomically $ R.thisNode <$> readTVar tbl |
@@ -1180,6 +1169,7 @@ announceH routing toks keydb naddr req = do | |||
1180 | _ | Nonce32 bs <- announcePingId req | 1169 | _ | Nonce32 bs <- announcePingId req |
1181 | , let tok = fromPaddedByteString 32 bs | 1170 | , let tok = fromPaddedByteString 32 bs |
1182 | -> checkToken toks naddr tok >>= go | 1171 | -> checkToken toks naddr tok >>= go |
1172 | `catch` (\(SomeException e) -> hPutStrLn stderr ("announceH Exception! "++show e) >> throw e) | ||
1183 | where | 1173 | where |
1184 | go withTok = do | 1174 | go withTok = do |
1185 | ns <- getNodesH routing naddr (GetNodes (announceSeeking req)) | 1175 | ns <- getNodesH routing naddr (GetNodes (announceSeeking req)) |
@@ -1302,7 +1292,7 @@ gen g = let (bs, g') = randomBytesGenerate 24 g | |||
1302 | 1292 | ||
1303 | 1293 | ||
1304 | toxSend meth unwrap msg client nid addr = do | 1294 | toxSend meth unwrap msg client nid addr = do |
1305 | reply <- sendQuery client serializer (msg nid) addr | 1295 | reply <- sendQuery client serializer (msg nid) (ToxPath addr Tox.emptyReturnPath) |
1306 | -- sendQuery will return (Just (Left _)) on a parse error. We're going to | 1296 | -- sendQuery will return (Just (Left _)) on a parse error. We're going to |
1307 | -- blow it away with the join-either sequence. | 1297 | -- blow it away with the join-either sequence. |
1308 | -- TODO: Do something with parse errors. | 1298 | -- TODO: Do something with parse errors. |
diff --git a/ToxMessage.hs b/ToxMessage.hs index 9ea57d27..06026b49 100644 --- a/ToxMessage.hs +++ b/ToxMessage.hs | |||
@@ -1,9 +1,15 @@ | |||
1 | {-# LANGUAGE PatternSynonyms #-} | ||
1 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} | 2 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} |
2 | {-# LANGUAGE DeriveFunctor, DeriveTraversable,DeriveDataTypeable #-} | 3 | {-# LANGUAGE DeriveFunctor, DeriveTraversable,DeriveDataTypeable #-} |
3 | {-# LANGUAGE GADTs #-} | 4 | {-# LANGUAGE GADTs #-} |
4 | {-# LANGUAGE FlexibleInstances #-} | 5 | {-# LANGUAGE FlexibleInstances #-} |
6 | {-# LANGUAGE ScopedTypeVariables #-} | ||
7 | {-# LANGUAGE TypeApplications #-} | ||
8 | {-# LANGUAGE ExistentialQuantification #-} | ||
9 | {-# LANGUAGE DataKinds, KindSignatures #-} | ||
5 | module ToxMessage where | 10 | module ToxMessage where |
6 | 11 | ||
12 | import Debug.Trace | ||
7 | import Data.ByteString (ByteString) | 13 | import Data.ByteString (ByteString) |
8 | import qualified Crypto.MAC.Poly1305 as Poly1305 (Auth(..)) | 14 | import qualified Crypto.MAC.Poly1305 as Poly1305 (Auth(..)) |
9 | import qualified Crypto.PubKey.Curve25519 as Curve25519 | 15 | import qualified Crypto.PubKey.Curve25519 as Curve25519 |
@@ -23,6 +29,8 @@ import Foreign.Ptr | |||
23 | import Foreign.Marshal.Alloc | 29 | import Foreign.Marshal.Alloc |
24 | import System.Endian | 30 | import System.Endian |
25 | import Foreign.Storable | 31 | import Foreign.Storable |
32 | import GHC.TypeLits | ||
33 | import Data.Tuple | ||
26 | 34 | ||
27 | newtype Auth = Auth Poly1305.Auth | 35 | newtype Auth = Auth Poly1305.Auth |
28 | deriving (Eq, ByteArrayAccess) | 36 | deriving (Eq, ByteArrayAccess) |
@@ -165,6 +173,17 @@ instance Serialize (Aliased Assymetric) where | |||
165 | newtype Cookie = Cookie UnclaimedAssymetric | 173 | newtype Cookie = Cookie UnclaimedAssymetric |
166 | deriving (Eq, Ord,Data) | 174 | deriving (Eq, Ord,Data) |
167 | 175 | ||
176 | newtype ReturnPath (n::Nat) = ReturnPath ByteString | ||
177 | deriving (Eq, Ord,Data) | ||
178 | |||
179 | emptyReturnPath :: ReturnPath 0 | ||
180 | emptyReturnPath = ReturnPath B.empty | ||
181 | |||
182 | instance KnownNat n => Serialize (ReturnPath n) where | ||
183 | -- Size: 59 = 1(family) + 16(ip) + 2(port) +16(mac) + 24(nonce) | ||
184 | get = ReturnPath <$> getBytes ( 59 * (fromIntegral $ natVal $ Proxy @n) ) | ||
185 | put (ReturnPath bs) = putByteString bs | ||
186 | |||
168 | data Symmetric = Symmetric | 187 | data Symmetric = Symmetric |
169 | { symmetricNonce :: Nonce24 | 188 | { symmetricNonce :: Nonce24 |
170 | , symmetricAuth :: Auth | 189 | , symmetricAuth :: Auth |
@@ -209,10 +228,10 @@ data Packet where | |||
209 | -- | 228 | -- |
210 | -- If the return path is non empty, we should respond with OnionResponse3 | 229 | -- If the return path is non empty, we should respond with OnionResponse3 |
211 | -- rather than AnnounceResponse directly. | 230 | -- rather than AnnounceResponse directly. |
212 | Announce :: Aliased Assymetric -> Packet --0x83 | 231 | Announce :: Aliased Assymetric -> ReturnPath 3 -> Packet --0x83 |
213 | AnnounceResponse :: Nonce8 -> UnclaimedAssymetric -> Packet -- 0x84 | 232 | AnnounceResponse :: Nonce8 -> UnclaimedAssymetric -> Packet -- 0x84 |
214 | 233 | ||
215 | OnionResponse3 :: Symmetric -> ByteString -> Packet -- 0x8c | 234 | OnionResponse3 :: ReturnPath 3 -> Packet -> Packet -- 0x8c |
216 | OnionResponse2 :: Symmetric -> ByteString -> Packet -- 0x8d | 235 | OnionResponse2 :: Symmetric -> ByteString -> Packet -- 0x8d |
217 | OnionResponse1 :: Symmetric -> ByteString -> Packet -- 0x8e | 236 | OnionResponse1 :: Symmetric -> ByteString -> Packet -- 0x8e |
218 | 237 | ||
@@ -222,9 +241,59 @@ data Packet where | |||
222 | 241 | ||
223 | deriving (Eq, Ord,Data) | 242 | deriving (Eq, Ord,Data) |
224 | 243 | ||
244 | class KnownNat n => OnionPacket n where | ||
245 | mkOnion :: ReturnPath n -> Packet -> Packet | ||
246 | |||
247 | instance OnionPacket 0 where mkOnion _ = id | ||
248 | instance OnionPacket 3 where mkOnion = OnionResponse3 | ||
249 | |||
225 | newtype PacketKind = PacketKind Word8 | 250 | newtype PacketKind = PacketKind Word8 |
226 | deriving (Eq, Ord, Serialize) | 251 | deriving (Eq, Ord, Serialize) |
227 | 252 | ||
253 | -- TODO: Auth fail: | ||
254 | pattern OnionRequest0Type = PacketKind 128 -- 0x80 Onion Request 0 | ||
255 | pattern OnionRequest1Type = PacketKind 129 -- 0x81 Onion Request 1 | ||
256 | pattern OnionRequest2Type = PacketKind 130 -- 0x82 Onion Request 2 | ||
257 | pattern AnnounceType = PacketKind 131 -- 0x83 Announce Request | ||
258 | pattern AnnounceResponseType = PacketKind 132 -- 0x84 Announce Response | ||
259 | -- 0x85 Onion Data Request (data to route request packet) | ||
260 | -- 0x86 Onion Data Response (data to route response packet) | ||
261 | -- 0x8c Onion Response 3 | ||
262 | -- 0x8d Onion Response 2 | ||
263 | pattern OnionResponse3Type = PacketKind 140 -- 0x8c Onion Response 3 | ||
264 | pattern OnionResponse2Type = PacketKind 141 -- 0x8d Onion Response 2 | ||
265 | pattern OnionResponse1Type = PacketKind 142 -- 0x8e Onion Response 1 | ||
266 | -- 0xf0 Bootstrap Info | ||
267 | |||
268 | -- TODO Fix these fails... | ||
269 | -- GetNodesType decipherAndAuth: auth fail | ||
270 | -- MessageType 128 decipherAndAuth: auth fail | ||
271 | -- MessageType 129 decipherAndAuth: auth fail | ||
272 | -- MessageType 130 decipherAndAuth: auth fail | ||
273 | -- MessageType 131 decipherAndAuth: auth fail | ||
274 | -- MessageType 32 decipherAndAuth: auth fail | ||
275 | |||
276 | -- TODO: Auth fail: | ||
277 | pattern DHTRequestType = PacketKind 32 -- 0x20 DHT Request | ||
278 | |||
279 | pattern PingType = PacketKind 0 -- 0x00 Ping Request | ||
280 | pattern PongType = PacketKind 1 -- 0x01 Ping Response | ||
281 | pattern GetNodesType = PacketKind 2 -- 0x02 Nodes Request | ||
282 | pattern SendNodesType = PacketKind 4 -- 0x04 Nodes Response | ||
283 | |||
284 | |||
285 | instance Show PacketKind where | ||
286 | showsPrec d PingType = mappend "PingType" | ||
287 | showsPrec d PongType = mappend "PongType" | ||
288 | showsPrec d GetNodesType = mappend "GetNodesType" | ||
289 | showsPrec d SendNodesType = mappend "SendNodesType" | ||
290 | showsPrec d DHTRequestType = mappend "DHTRequestType" | ||
291 | showsPrec d OnionRequest0Type = mappend "OnionRequest0" | ||
292 | showsPrec d OnionResponse1Type = mappend "OnionResponse1" | ||
293 | showsPrec d OnionResponse3Type = mappend "OnionResponse3" | ||
294 | showsPrec d AnnounceType = mappend "AnnounceType" | ||
295 | showsPrec d (PacketKind x) = mappend "PacketKind " . showsPrec (d+1) x | ||
296 | |||
228 | pktKind :: Packet -> PacketKind | 297 | pktKind :: Packet -> PacketKind |
229 | 298 | ||
230 | -- These are (Assymetric -> Assymetric) queries. | 299 | -- These are (Assymetric -> Assymetric) queries. |
@@ -286,10 +355,25 @@ pktKind OnionResponse3 {} = PacketKind 0x8c | |||
286 | 355 | ||
287 | data PacketClass = | 356 | data PacketClass = |
288 | AssymetricClass (Assymetric -> Packet) (Packet -> Assymetric) | 357 | AssymetricClass (Assymetric -> Packet) (Packet -> Assymetric) |
289 | | AliasedClass (Aliased Assymetric -> Packet) (Packet -> Aliased Assymetric) | 358 | | forall n. OnionPacket n => AliasedClass ((Aliased Assymetric,ReturnPath n) -> Packet) (Packet -> (Aliased Assymetric,ReturnPath n)) |
359 | | forall n. OnionPacket n => OnionClass ((Packet,ReturnPath n) -> Packet) (Packet -> (Packet,ReturnPath n)) | ||
290 | | NoncedUnclaimedClass (Nonce8 -> UnclaimedAssymetric -> Packet) | 360 | | NoncedUnclaimedClass (Nonce8 -> UnclaimedAssymetric -> Packet) |
291 | (Packet -> (Nonce8, UnclaimedAssymetric)) | 361 | (Packet -> (Nonce8, UnclaimedAssymetric)) |
292 | | Unclassified | 362 | | Unclassified |
363 | {- | ||
364 | data Packet' where | ||
365 | :: Assymetric -> Packet | ||
366 | :: UnclaimedAssymetric -> Packet | ||
367 | :: Word16 -> ImplicitAssymetric -> Packet | ||
368 | :: PubKey -> Assymetric -> Packet | ||
369 | :: PubKey -> Packet | ||
370 | :: Aliased Assymetric -> Symmetric -> Packet | ||
371 | :: ByteString -> Symmetric -> Packet | ||
372 | :: Aliased Assymetric -> Packet | ||
373 | :: Symmetric -> ByteString -> Packet | ||
374 | :: ByteString -> Packet | ||
375 | :: Word32 -> ByteString -> Packet | ||
376 | -} | ||
293 | 377 | ||
294 | pktClass :: PacketKind -> PacketClass | 378 | pktClass :: PacketKind -> PacketClass |
295 | pktClass (PacketKind 0) = AssymetricClass Ping (\(Ping a) -> a) | 379 | pktClass (PacketKind 0) = AssymetricClass Ping (\(Ping a) -> a) |
@@ -301,9 +385,11 @@ pktClass (PacketKind 0x18) = AssymetricClass CookieRequest (\(CookieRequest a) - | |||
301 | pktClass (PacketKind 0x80) = AssymetricClass OnionRequest0 (\(OnionRequest0 a) -> a) | 385 | pktClass (PacketKind 0x80) = AssymetricClass OnionRequest0 (\(OnionRequest0 a) -> a) |
302 | -- pktClass (PacketKind 0x86) = AssymetricClass (DataToRouteResponse . Aliased) (\(DataToRouteResponse (Aliased a)) -> a) | 386 | -- pktClass (PacketKind 0x86) = AssymetricClass (DataToRouteResponse . Aliased) (\(DataToRouteResponse (Aliased a)) -> a) |
303 | 387 | ||
304 | pktClass (PacketKind 0x83) = AliasedClass Announce (\(Announce a)-> a) | 388 | pktClass (PacketKind 0x83) = AliasedClass (uncurry Announce) (\(Announce a r)-> (a,r)) |
305 | pktClass (PacketKind 0x84) = NoncedUnclaimedClass AnnounceResponse (\(AnnounceResponse n8 uncl)-> (n8,uncl)) | 389 | pktClass (PacketKind 0x84) = NoncedUnclaimedClass AnnounceResponse (\(AnnounceResponse n8 uncl)-> (n8,uncl)) |
306 | 390 | ||
391 | pktClass (PacketKind 0x8c) = OnionClass (uncurry OnionResponse3 . swap) (\(OnionResponse3 r a)-> (a,r)) | ||
392 | |||
307 | pktClass _ = Unclassified | 393 | pktClass _ = Unclassified |
308 | 394 | ||
309 | 395 | ||
@@ -315,27 +401,27 @@ getPacket = do | |||
315 | typ <- get | 401 | typ <- get |
316 | case pktClass typ of | 402 | case pktClass typ of |
317 | AssymetricClass toPacket _ -> toPacket <$> get | 403 | AssymetricClass toPacket _ -> toPacket <$> get |
318 | AliasedClass toPacket _ -> toPacket <$> get | 404 | AliasedClass toPacket _ -> do |
405 | trace ("PARSE "++show typ) $ return () | ||
406 | cnt <- remaining | ||
407 | a <- isolate (cnt - 59*3) get | ||
408 | r <- get | ||
409 | trace ("PARSED "++show typ) $ return () | ||
410 | return $ toPacket (a,r) | ||
411 | OnionClass toPacket _ -> do | ||
412 | trace ("ONION-PARSE "++show typ) $ return () | ||
413 | p <- get | ||
414 | trace ("ONION-PARSED "++show typ) $ return () | ||
415 | return $ toPacket p | ||
319 | NoncedUnclaimedClass toPacket _ -> toPacket <$> get <*> get | 416 | NoncedUnclaimedClass toPacket _ -> toPacket <$> get <*> get |
417 | Unclassified -> fail $ "todo: unserialize packet "++show typ | ||
320 | 418 | ||
321 | putPacket p = do | 419 | putPacket p = do |
322 | put $ pktKind p | 420 | put $ pktKind p |
323 | case pktClass (pktKind p) of | 421 | case pktClass (pktKind p) of |
324 | AssymetricClass _ fromPacket -> put $ fromPacket p | 422 | AssymetricClass _ fromPacket -> put $ fromPacket p |
325 | AliasedClass _ fromPacket -> put $ fromPacket p | 423 | AliasedClass _ fromPacket -> put $ fromPacket p |
424 | OnionClass _ fromPacket -> put $ swap $ fromPacket p | ||
326 | NoncedUnclaimedClass _ fromPacket -> put $ fromPacket p -- putting a pair. | 425 | NoncedUnclaimedClass _ fromPacket -> put $ fromPacket p -- putting a pair. |
426 | Unclassified -> fail $ "todo: serialize packet "++show (pktKind p) | ||
327 | 427 | ||
328 | {- | ||
329 | data Packet' where | ||
330 | :: Assymetric -> Packet | ||
331 | :: UnclaimedAssymetric -> Packet | ||
332 | :: Word16 -> ImplicitAssymetric -> Packet | ||
333 | :: PubKey -> Assymetric -> Packet | ||
334 | :: PubKey -> Packet | ||
335 | :: Aliased Assymetric -> Symmetric -> Packet | ||
336 | :: ByteString -> Symmetric -> Packet | ||
337 | :: Aliased Assymetric -> Packet | ||
338 | :: Symmetric -> ByteString -> Packet | ||
339 | :: ByteString -> Packet | ||
340 | :: Word32 -> ByteString -> Packet | ||
341 | -} | ||
diff --git a/src/Network/QueryResponse.hs b/src/Network/QueryResponse.hs index 190cc73e..11fe7c32 100644 --- a/src/Network/QueryResponse.hs +++ b/src/Network/QueryResponse.hs | |||
@@ -181,6 +181,16 @@ data MethodHandler err tid addr x = forall a b. MethodHandler | |||
181 | , noreplyAction :: addr -> a -> IO () | 181 | , noreplyAction :: addr -> a -> IO () |
182 | } | 182 | } |
183 | 183 | ||
184 | contramapAddr :: (a -> b) -> MethodHandler err tid b x -> MethodHandler err tid a x | ||
185 | contramapAddr f (MethodHandler p s a) | ||
186 | = MethodHandler | ||
187 | p | ||
188 | (\tid src dst result -> s tid (f src) (f dst) result) | ||
189 | (\addr arg -> a (f addr) arg) | ||
190 | contramapAddr f (NoReply p a) | ||
191 | = NoReply p (\addr arg -> a (f addr) arg) | ||
192 | |||
193 | |||
184 | -- | Attempt to invoke a 'MethodHandler' upon a given inbound query. If the | 194 | -- | Attempt to invoke a 'MethodHandler' upon a given inbound query. If the |
185 | -- parse is successful, the returned IO action will construct our reply if | 195 | -- parse is successful, the returned IO action will construct our reply if |
186 | -- there is one. Otherwise, a parse err is returned. | 196 | -- there is one. Otherwise, a parse err is returned. |