summaryrefslogtreecommitdiff
path: root/dht/src/Network/Tox/TCP/NodeId.hs
diff options
context:
space:
mode:
Diffstat (limited to 'dht/src/Network/Tox/TCP/NodeId.hs')
-rw-r--r--dht/src/Network/Tox/TCP/NodeId.hs89
1 files changed, 89 insertions, 0 deletions
diff --git a/dht/src/Network/Tox/TCP/NodeId.hs b/dht/src/Network/Tox/TCP/NodeId.hs
new file mode 100644
index 00000000..c218c88f
--- /dev/null
+++ b/dht/src/Network/Tox/TCP/NodeId.hs
@@ -0,0 +1,89 @@
1{-# LANGUAGE CPP #-}
2module Network.Tox.TCP.NodeId where
3
4import Crypto.Tox
5import qualified Network.Tox.NodeId as UDP
6
7import qualified Data.Aeson as JSON
8 ;import Data.Aeson (FromJSON (..), ToJSON (..))
9import Data.Functor.Contravariant
10import Data.Hashable
11import qualified Data.HashMap.Strict as HashMap
12import qualified Data.Vector as Vector
13import Data.Word
14import Network.Socket
15import qualified Text.ParserCombinators.ReadP as RP
16import Data.Serialize as S
17
18#if MIN_VERSION_iproute(1,7,4)
19import Data.IP hiding (fromSockAddr)
20#else
21import Data.IP
22#endif
23
24data NodeInfo = NodeInfo
25 { udpNodeInfo :: UDP.NodeInfo
26 , tcpPort :: PortNumber
27 }
28 deriving (Eq,Ord)
29
30instance Read NodeInfo where
31 readsPrec _ = RP.readP_to_S $ do
32 udp <- RP.readS_to_P reads
33 port <- RP.between (RP.char '{') (RP.char '}') $ do
34 mapM_ RP.char ("tcp:" :: String)
35 w16 <- RP.readS_to_P reads
36 return $ fromIntegral (w16 :: Word16)
37 return $ NodeInfo udp port
38
39instance ToJSON NodeInfo where
40 toJSON (NodeInfo udp port) = case (toJSON udp) of
41 JSON.Object tbl -> JSON.Object $ HashMap.insert "tcp_ports"
42 (JSON.Array $ Vector.fromList
43 [JSON.Number (fromIntegral port)])
44 tbl
45 x -> x -- Shouldn't happen.
46
47-- example:
48-- KEyW2Bm.S-DpIGp72380BAfgintUWX1KX.6ZU.4m5Ex@80.99.99.99:33400{tcp:443}
49instance Show NodeInfo where
50 show (NodeInfo udp port) = show udp ++ "{tcp:"++show port++"}"
51
52instance Sized NodeInfo where
53 size = contramap udpNodeInfo size
54
55
56getIP :: Word8 -> S.Get (Bool, IP)
57getIP 0x02 = (,) False . IPv4 <$> S.get -- UDP 4
58getIP 0x0a = (,) False . IPv6 <$> S.get -- UDP 6
59getIP 0x82 = (,) True . IPv4 <$> S.get -- TCP 4
60getIP 0x8a = (,) True . IPv6 <$> S.get -- TCP 6
61getIP x = fail ("unsupported address family ("++show x++")")
62
63instance S.Serialize NodeInfo where
64 get = do
65 addrfam <- S.get :: S.Get Word8
66 (istcp, ip) <- getIP addrfam
67 port <- S.get :: S.Get PortNumber
68 nid <- S.get
69 let (udpport, tcpport) = if istcp
70 then (0, port)
71 else (port, 0)
72 return $ NodeInfo (UDP.NodeInfo nid ip udpport) tcpport
73
74 put (NodeInfo (UDP.NodeInfo nid ip udpport) tcpport) = do
75 if tcpport==0
76 then do
77 case ip of
78 IPv4 ip4 -> S.put (2 :: Word8) >> S.put ip4
79 IPv6 ip6 -> S.put (10 :: Word8) >> S.put ip6
80 S.put udpport
81 else do
82 case ip of
83 IPv4 ip4 -> S.put (0x82 :: Word8) >> S.put ip4
84 IPv6 ip6 -> S.put (0x8a :: Word8) >> S.put ip6
85 S.put tcpport
86 S.put nid
87
88fromUDPNode :: UDP.NodeInfo -> NodeInfo
89fromUDPNode ni = NodeInfo ni 0