From df6292eef942c11b9ac58b337f29641dae404116 Mon Sep 17 00:00:00 2001 From: Joe Crayne Date: Thu, 6 Dec 2018 21:32:55 -0500 Subject: Intances for TCP.NodeInfo. --- src/Network/Tox/NodeId.hs | 2 ++ src/Network/Tox/TCP.hs | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) (limited to 'src/Network/Tox') diff --git a/src/Network/Tox/NodeId.hs b/src/Network/Tox/NodeId.hs index 56ddf03c..98be1e3a 100644 --- a/src/Network/Tox/NodeId.hs +++ b/src/Network/Tox/NodeId.hs @@ -335,6 +335,8 @@ instance Read NodeInfo where return $ NodeInfo nid ip port -- The Hashable instance depends only on the IP address and port number. +-- +-- TODO: Why is the node id excluded? instance Hashable NodeInfo where hashWithSalt s ni = hashWithSalt s (nodeIP ni , nodePort ni) {-# INLINE hashWithSalt #-} diff --git a/src/Network/Tox/TCP.hs b/src/Network/Tox/TCP.hs index 5b5b4f4e..eede869f 100644 --- a/src/Network/Tox/TCP.hs +++ b/src/Network/Tox/TCP.hs @@ -9,11 +9,18 @@ import Control.Concurrent import Control.Concurrent.STM import Control.Monad import Crypto.Random +import Data.Aeson (ToJSON(..),FromJSON(..)) +import qualified Data.Aeson as JSON import Data.Functor.Contravariant import Data.Functor.Identity +import Data.Hashable +import qualified Data.HashMap.Strict as HashMap import Data.IP import Data.Serialize +import Data.Word +import qualified Data.Vector as Vector import Network.Socket (SockAddr(..)) +import qualified Text.ParserCombinators.ReadP as RP import Crypto.Tox import Data.ByteString (hPut,hGet,ByteString) @@ -39,12 +46,45 @@ data NodeInfo = NodeInfo { udpNodeInfo :: UDP.NodeInfo , tcpPort :: PortNumber } + deriving (Eq,Ord) type NodeId = UDP.NodeId +-- example: +-- KEyW2Bm.S-DpIGp72380BAfgintUWX1KX.6ZU.4m5Ex@80.99.99.99:33400{tcp:443} instance Show NodeInfo where show (NodeInfo udp port) = show udp ++ "{tcp:"++show port++"}" +instance Read NodeInfo where + readsPrec _ = RP.readP_to_S $ do + udp <- RP.readS_to_P reads + port <- RP.between (RP.char '{') (RP.char '}') $ do + mapM_ RP.char ("tcp:" :: String) + w16 <- RP.readS_to_P reads + return $ fromIntegral (w16 :: Word16) + return $ NodeInfo udp port + +instance ToJSON NodeInfo where + toJSON (NodeInfo udp port) = case (toJSON udp) of + JSON.Object tbl -> JSON.Object $ HashMap.insert "tcp_ports" + (JSON.Array $ Vector.fromList + [JSON.Number (fromIntegral port)]) + tbl + x -> x -- Shouldn't happen. + +instance FromJSON NodeInfo where + parseJSON json = do + udp <- parseJSON json + port <- case json of + JSON.Object v -> do + portnum:_ <- v JSON..: "tcp_ports" + return (fromIntegral (portnum :: Word16)) + _ -> fail "TCP.NodeInfo: Expected JSON object." + return $ NodeInfo udp port + +instance Hashable NodeInfo where + hashWithSalt s n = hashWithSalt s (udpNodeInfo n) + nodeId :: NodeInfo -> NodeId nodeId ni = UDP.nodeId $ udpNodeInfo ni -- cgit v1.2.3