diff options
author | joe <joe@jerkface.net> | 2017-06-08 13:53:37 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2017-06-08 13:53:37 -0400 |
commit | cb2bd0bf4b5977ef6ec7ca7ab9ac0189457c2250 (patch) | |
tree | 7fc115e4343411659a3b7822fdfa2476deafa9a1 /src/Network | |
parent | 71427b224f25f01c0ce4ddfb1870378e7cc38822 (diff) |
Renamed Data.Tox -> Network.DatagramServer.Tox
Diffstat (limited to 'src/Network')
-rw-r--r-- | src/Network/BitTorrent/DHT/Message.hs | 4 | ||||
-rw-r--r-- | src/Network/BitTorrent/DHT/Query.hs | 2 | ||||
-rw-r--r-- | src/Network/BitTorrent/DHT/Routing.hs | 2 | ||||
-rw-r--r-- | src/Network/BitTorrent/DHT/Search.hs | 2 | ||||
-rw-r--r-- | src/Network/BitTorrent/DHT/Session.hs | 2 | ||||
-rw-r--r-- | src/Network/DatagramServer.hs | 2 | ||||
-rw-r--r-- | src/Network/DatagramServer/Mainline.hs | 2 | ||||
-rw-r--r-- | src/Network/DatagramServer/Tox.hs | 279 |
8 files changed, 287 insertions, 8 deletions
diff --git a/src/Network/BitTorrent/DHT/Message.hs b/src/Network/BitTorrent/DHT/Message.hs index cfe24fc5..4410a296 100644 --- a/src/Network/BitTorrent/DHT/Message.hs +++ b/src/Network/BitTorrent/DHT/Message.hs | |||
@@ -94,8 +94,8 @@ import Data.Bool | |||
94 | import Data.BEncode as BE | 94 | import Data.BEncode as BE |
95 | import Data.BEncode.BDict as BDict | 95 | import Data.BEncode.BDict as BDict |
96 | #else | 96 | #else |
97 | import qualified Data.Tox as Tox | 97 | import qualified Network.DatagramServer.Tox as Tox |
98 | import Data.Tox (NodeId) | 98 | import Network.DatagramServer.Tox (NodeId) |
99 | import Data.Word | 99 | import Data.Word |
100 | import Control.Monad | 100 | import Control.Monad |
101 | import Network.KRPC.Method | 101 | import Network.KRPC.Method |
diff --git a/src/Network/BitTorrent/DHT/Query.hs b/src/Network/BitTorrent/DHT/Query.hs index 1c4df267..fc6625ae 100644 --- a/src/Network/BitTorrent/DHT/Query.hs +++ b/src/Network/BitTorrent/DHT/Query.hs | |||
@@ -96,7 +96,7 @@ import Network.DHT.Mainline hiding (NodeId) | |||
96 | import Network.DatagramServer.Mainline (KMessageOf) | 96 | import Network.DatagramServer.Mainline (KMessageOf) |
97 | #else | 97 | #else |
98 | import Data.ByteString (ByteString) | 98 | import Data.ByteString (ByteString) |
99 | import Data.Tox | 99 | import Network.DatagramServer.Tox |
100 | #endif | 100 | #endif |
101 | import Network.BitTorrent.Address hiding (NodeId) | 101 | import Network.BitTorrent.Address hiding (NodeId) |
102 | import Network.DatagramServer.Types as RPC hiding (Query,Response) | 102 | import Network.DatagramServer.Types as RPC hiding (Query,Response) |
diff --git a/src/Network/BitTorrent/DHT/Routing.hs b/src/Network/BitTorrent/DHT/Routing.hs index d147bb94..fc7c76b0 100644 --- a/src/Network/BitTorrent/DHT/Routing.hs +++ b/src/Network/BitTorrent/DHT/Routing.hs | |||
@@ -89,7 +89,7 @@ import Network.BitTorrent.Address | |||
89 | import Network.DHT.Mainline () | 89 | import Network.DHT.Mainline () |
90 | import Network.DatagramServer.Mainline (KMessageOf) | 90 | import Network.DatagramServer.Mainline (KMessageOf) |
91 | #else | 91 | #else |
92 | import Data.Tox as Tox | 92 | import Network.DatagramServer.Tox as Tox |
93 | type KMessageOf = Tox.Message | 93 | type KMessageOf = Tox.Message |
94 | #endif | 94 | #endif |
95 | 95 | ||
diff --git a/src/Network/BitTorrent/DHT/Search.hs b/src/Network/BitTorrent/DHT/Search.hs index 7a587644..367a6a9b 100644 --- a/src/Network/BitTorrent/DHT/Search.hs +++ b/src/Network/BitTorrent/DHT/Search.hs | |||
@@ -30,7 +30,7 @@ import Network.DHT.Mainline () | |||
30 | import Network.DatagramServer.Mainline (KMessageOf) | 30 | import Network.DatagramServer.Mainline (KMessageOf) |
31 | type Ann = () | 31 | type Ann = () |
32 | #else | 32 | #else |
33 | import Data.Tox as Tox | 33 | import Network.DatagramServer.Tox as Tox |
34 | type KMessageOf = Tox.Message | 34 | type KMessageOf = Tox.Message |
35 | type Ann = Bool | 35 | type Ann = Bool |
36 | #endif | 36 | #endif |
diff --git a/src/Network/BitTorrent/DHT/Session.hs b/src/Network/BitTorrent/DHT/Session.hs index ead4a723..f874b62e 100644 --- a/src/Network/BitTorrent/DHT/Session.hs +++ b/src/Network/BitTorrent/DHT/Session.hs | |||
@@ -110,7 +110,7 @@ import qualified Network.DatagramServer as KRPC (def) | |||
110 | import Data.BEncode (BValue) | 110 | import Data.BEncode (BValue) |
111 | import Network.DatagramServer.Mainline (KMessageOf) | 111 | import Network.DatagramServer.Mainline (KMessageOf) |
112 | #else | 112 | #else |
113 | import Data.Tox as Tox | 113 | import Network.DatagramServer.Tox as Tox |
114 | #endif | 114 | #endif |
115 | import Network.BitTorrent.Address | 115 | import Network.BitTorrent.Address |
116 | import Network.BitTorrent.DHT.ContactInfo (PeerStore) | 116 | import Network.BitTorrent.DHT.ContactInfo (PeerStore) |
diff --git a/src/Network/DatagramServer.hs b/src/Network/DatagramServer.hs index d22bc893..21300108 100644 --- a/src/Network/DatagramServer.hs +++ b/src/Network/DatagramServer.hs | |||
@@ -118,7 +118,7 @@ import Data.BEncode as BE | |||
118 | import Data.BEncode.Internal as BE | 118 | import Data.BEncode.Internal as BE |
119 | import Data.BEncode.Pretty (showBEncode) | 119 | import Data.BEncode.Pretty (showBEncode) |
120 | #else | 120 | #else |
121 | import qualified Data.Tox as Tox | 121 | import qualified Network.DatagramServer.Tox as Tox |
122 | #endif | 122 | #endif |
123 | import qualified Data.ByteString.Base16 as Base16 | 123 | import qualified Data.ByteString.Base16 as Base16 |
124 | import Data.ByteString as BS | 124 | import Data.ByteString as BS |
diff --git a/src/Network/DatagramServer/Mainline.hs b/src/Network/DatagramServer/Mainline.hs index 2177d076..70b9b184 100644 --- a/src/Network/DatagramServer/Mainline.hs +++ b/src/Network/DatagramServer/Mainline.hs | |||
@@ -65,7 +65,7 @@ import Control.Exception.Lifted as Lifted | |||
65 | #ifdef VERSION_bencoding | 65 | #ifdef VERSION_bencoding |
66 | import Data.BEncode as BE | 66 | import Data.BEncode as BE |
67 | #else | 67 | #else |
68 | import qualified Data.Tox as Tox | 68 | import qualified Network.DatagramServer.Tox as Tox |
69 | #endif | 69 | #endif |
70 | import Data.ByteString as B | 70 | import Data.ByteString as B |
71 | import Data.ByteString.Char8 as BC | 71 | import Data.ByteString.Char8 as BC |
diff --git a/src/Network/DatagramServer/Tox.hs b/src/Network/DatagramServer/Tox.hs new file mode 100644 index 00000000..ad376c68 --- /dev/null +++ b/src/Network/DatagramServer/Tox.hs | |||
@@ -0,0 +1,279 @@ | |||
1 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} | ||
2 | {-# LANGUAGE StandaloneDeriving #-} | ||
3 | {-# LANGUAGE FlexibleInstances #-} | ||
4 | {-# LANGUAGE DeriveDataTypeable #-} | ||
5 | {-# LANGUAGE DeriveFunctor #-} | ||
6 | {-# LANGUAGE DeriveGeneric #-} | ||
7 | {-# LANGUAGE DeriveTraversable #-} | ||
8 | {-# LANGUAGE MultiParamTypeClasses #-} | ||
9 | {-# LANGUAGE PatternSynonyms #-} | ||
10 | {-# LANGUAGE RecordWildCards #-} | ||
11 | {-# LANGUAGE TupleSections #-} | ||
12 | {-# LANGUAGE TypeFamilies #-} | ||
13 | {-# LANGUAGE UnboxedTuples #-} | ||
14 | module Network.DatagramServer.Tox where | ||
15 | |||
16 | import Data.Bits | ||
17 | import Data.ByteString (ByteString) | ||
18 | import Data.Data (Data) | ||
19 | import Data.Word | ||
20 | import Data.LargeWord | ||
21 | import Data.IP | ||
22 | import Data.Serialize | ||
23 | -- import Network.BitTorrent.Address (NodeInfo(..)) -- Serialize IP | ||
24 | import GHC.Generics (Generic) | ||
25 | import Network.Socket | ||
26 | import Network.DatagramServer.Types | ||
27 | import qualified Network.DatagramServer.Types as Envelope (NodeId) | ||
28 | import Crypto.PubKey.ECC.Types | ||
29 | |||
30 | type Key32 = Word256 -- 32 byte key | ||
31 | type Nonce8 = Word64 -- 8 bytes | ||
32 | type Nonce24 = Word192 -- 24 bytes | ||
33 | |||
34 | |||
35 | data NodeFormat = NodeFormat | ||
36 | { nodePublicKey :: Key32 -- 32 byte public key | ||
37 | , nodeIsTCP :: Bool -- This has no analog in mainline NodeInfo structure | ||
38 | , nodeIP :: IP -- IPv4 or IPv6 address | ||
39 | , nodePort :: PortNumber | ||
40 | } | ||
41 | deriving (Eq, Ord, Show) | ||
42 | |||
43 | encodeFamily :: (Family, SocketType) -> Word8 | ||
44 | encodeFamily (AF_INET , Datagram) = 2 | ||
45 | encodeFamily (AF_INET6 , Datagram) = 10 | ||
46 | encodeFamily (AF_INET , Stream ) = 130 | ||
47 | encodeFamily (AF_INET6 , Stream ) = 138 | ||
48 | encodeFamily _ = error "Unsupported protocol" | ||
49 | |||
50 | newtype MessageType = MessageType Word8 | ||
51 | deriving (Eq, Ord, Show, Read) | ||
52 | |||
53 | instance Serialize MessageType where | ||
54 | put (MessageType b) = put b | ||
55 | get = MessageType <$> get | ||
56 | |||
57 | pattern Ping = MessageType 0 | ||
58 | pattern Pong = MessageType 1 | ||
59 | pattern GetNodes = MessageType 2 | ||
60 | pattern SendNodes = MessageType 4 | ||
61 | {- | ||
62 | #define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */ | ||
63 | #define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */ | ||
64 | #define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */ | ||
65 | #define NET_PACKET_SEND_NODES_IPV6 4 /* Send nodes response packet ID for other addresses. */ | ||
66 | #define NET_PACKET_COOKIE_REQUEST 24 /* Cookie request packet */ | ||
67 | #define NET_PACKET_COOKIE_RESPONSE 25 /* Cookie response packet */ | ||
68 | #define NET_PACKET_CRYPTO_HS 26 /* Crypto handshake packet */ | ||
69 | #define NET_PACKET_CRYPTO_DATA 27 /* Crypto data packet */ | ||
70 | #define NET_PACKET_CRYPTO 32 /* Encrypted data packet ID. */ | ||
71 | #define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */ | ||
72 | |||
73 | /* See: docs/Prevent_Tracking.txt and onion.{c, h} */ | ||
74 | #define NET_PACKET_ONION_SEND_INITIAL 128 | ||
75 | #define NET_PACKET_ONION_SEND_1 129 | ||
76 | #define NET_PACKET_ONION_SEND_2 130 | ||
77 | |||
78 | #define NET_PACKET_ANNOUNCE_REQUEST 131 | ||
79 | #define NET_PACKET_ANNOUNCE_RESPONSE 132 | ||
80 | #define NET_PACKET_ONION_DATA_REQUEST 133 | ||
81 | #define NET_PACKET_ONION_DATA_RESPONSE 134 | ||
82 | |||
83 | #define NET_PACKET_ONION_RECV_3 140 | ||
84 | #define NET_PACKET_ONION_RECV_2 141 | ||
85 | #define NET_PACKET_ONION_RECV_1 142 | ||
86 | -} | ||
87 | |||
88 | |||
89 | -- FIXME Orphan Serialize intance for large words | ||
90 | instance (Serialize a, Serialize b) => Serialize (LargeKey a b) where | ||
91 | put (LargeKey lo hi) = put hi >> put lo | ||
92 | get = flip LargeKey <$> get <*> get | ||
93 | |||
94 | -- | Use with 'PingPayload', 'GetNodesPayload', or 'SendNodesPayload' | ||
95 | data Message a = Message | ||
96 | { msgType :: MessageType | ||
97 | , msgClient :: NodeId Message | ||
98 | , msgNonce :: Nonce24 | ||
99 | , msgPayload :: a | ||
100 | } | ||
101 | deriving (Show, Generic, Functor, Foldable, Traversable) | ||
102 | |||
103 | deriving instance Show (NodeId Message) -- TODO: print as hex | ||
104 | |||
105 | isQuery :: Message a -> Bool | ||
106 | isQuery (Message { msgType = SendNodes }) = False | ||
107 | isQuery (Message { msgType = MessageType typ }) | even typ = True | ||
108 | isQuery _ = False | ||
109 | |||
110 | isResponse :: Message a -> Bool | ||
111 | isResponse m = not (isQuery m) | ||
112 | |||
113 | isError :: Message a -> Bool | ||
114 | isError _ = False | ||
115 | |||
116 | data PingPayload = PingPayload | ||
117 | { isPong :: Bool | ||
118 | , pingId :: Nonce8 | ||
119 | } | ||
120 | |||
121 | data GetNodesPayload = GetNodesPayload | ||
122 | { nodesForWho :: NodeId Message | ||
123 | , nodesNonce :: Nonce8 | ||
124 | } | ||
125 | |||
126 | data SendNodesPayload = SendNodesPayload | ||
127 | |||
128 | -- From: docs/updates/DHT.md | ||
129 | -- | ||
130 | -- Node format: | ||
131 | -- [uint8_t family (2 == IPv4, 10 == IPv6, 130 == TCP IPv4, 138 == TCP IPv6)] | ||
132 | -- [ip (in network byte order), length=4 bytes if ipv4, 16 bytes if ipv6] | ||
133 | -- [port (in network byte order), length=2 bytes] | ||
134 | -- [char array (node_id), length=32 bytes] | ||
135 | -- | ||
136 | -- see also: DHT.h (pack_nodes() and unpack_nodes()) | ||
137 | instance Serialize NodeFormat where | ||
138 | |||
139 | get = do | ||
140 | typ <- get :: Get Word8 | ||
141 | (ip,istcp) <- | ||
142 | case typ :: Word8 of | ||
143 | 2 -> (,False) . IPv4 <$> get | ||
144 | 130 -> (,True) . IPv4 <$> get | ||
145 | 10 -> (,False) . IPv6 <$> get | ||
146 | 138 -> (,True) . IPv6 <$> get | ||
147 | _ -> fail "Unsupported type of Tox node_format structure" | ||
148 | port <- get | ||
149 | pubkey <- get | ||
150 | return $ NodeFormat { nodeIsTCP = istcp | ||
151 | , nodeIP = ip | ||
152 | , nodePort = port | ||
153 | , nodePublicKey = pubkey | ||
154 | } | ||
155 | |||
156 | put (NodeFormat{..}) = do | ||
157 | put $ case (# nodeIP, nodeIsTCP #) of | ||
158 | (# IPv4 _, False #) -> 2 | ||
159 | (# IPv4 _, True #) -> 130 | ||
160 | (# IPv6 _, False #) -> 10 | ||
161 | (# IPv6 _, True #) -> 138 :: Word8 | ||
162 | put nodeIP | ||
163 | put nodePort | ||
164 | put nodePublicKey | ||
165 | |||
166 | -- Note: the char array is a public key, the 32-bytes is provided by libsodium-dev | ||
167 | -- in /usr/include/sodium/crypto_box.h as the symbol crypto_box_PUBLICKEYBYTES | ||
168 | -- but toxcore/crypto_core.c will fail to compile if it is not 32. | ||
169 | |||
170 | |||
171 | -- Ping(Request and response): | ||
172 | -- | ||
173 | -- [byte with value: 00 for request, 01 for response] | ||
174 | -- [char array (client node_id), length=32 bytes] | ||
175 | -- [random 24 byte nonce] | ||
176 | -- [Encrypted with the nonce and private key of the sender: | ||
177 | -- [1 byte type (0 for request, 1 for response)] | ||
178 | -- [random 8 byte (ping_id)] | ||
179 | -- ] | ||
180 | -- | ||
181 | -- ping_id = a random integer, the response must contain the exact same number as the request | ||
182 | |||
183 | |||
184 | -- Get nodes (Request): | ||
185 | -- | ||
186 | -- [byte with value: 02] | ||
187 | -- [char array (client node_id), length=32 bytes] | ||
188 | -- [random 24 byte nonce] | ||
189 | -- [Encrypted with the nonce and private key of the sender: | ||
190 | -- [char array: requested_node_id (node_id of which we want the ip), length=32 bytes] | ||
191 | -- [Sendback data (must be sent back unmodified by in the response), length=8 bytes] | ||
192 | -- ] | ||
193 | -- | ||
194 | -- Valid replies: a send_nodes packet | ||
195 | |||
196 | -- Send_nodes (response (for all addresses)): | ||
197 | -- | ||
198 | -- [byte with value: 04] | ||
199 | -- [char array (client node_id), length=32 bytes] | ||
200 | -- [random 24 byte nonce] | ||
201 | -- [Encrypted with the nonce and private key of the sender: | ||
202 | -- [uint8_t number of nodes in this packet] | ||
203 | -- [Nodes in node format, length=?? * (number of nodes (maximum of 4 nodes)) bytes] | ||
204 | -- [Sendback data, length=8 bytes] | ||
205 | -- ] | ||
206 | |||
207 | data ToxCipherContext = ToxCipherContext -- TODO | ||
208 | |||
209 | newtype Ciphered = Ciphered { cipheredBytes :: ByteString } | ||
210 | |||
211 | getMessage :: Get (Message Ciphered) | ||
212 | getMessage = do | ||
213 | typ <- get | ||
214 | nid <- get | ||
215 | tid <- get | ||
216 | cnt <- remaining | ||
217 | bs <- getBytes cnt | ||
218 | return Message { msgType = typ | ||
219 | , msgClient = nid | ||
220 | , msgNonce = tid | ||
221 | , msgPayload = Ciphered bs } | ||
222 | |||
223 | putMessage :: Message Ciphered -> Put | ||
224 | putMessage (Message {..}) = do | ||
225 | put msgType | ||
226 | put msgClient | ||
227 | put msgNonce | ||
228 | let Ciphered bs = msgPayload | ||
229 | putByteString bs | ||
230 | |||
231 | decipher :: ToxCipherContext -> Message Ciphered -> Either String (Message ByteString) | ||
232 | decipher = error "TODO TOX: decipher" | ||
233 | |||
234 | encipher :: ToxCipherContext -> Message ByteString -> Message Ciphered | ||
235 | encipher = error "TODO TOX: encipher" | ||
236 | |||
237 | -- see rfc7748 | ||
238 | curve25519 :: Curve | ||
239 | curve25519 = CurveFP (CurvePrime prime curvecommon) | ||
240 | where | ||
241 | prime = 2^255 - 19 -- (≅ 1 modulo 4) | ||
242 | |||
243 | -- 1 * v^2 = u^3 + 486662*u^2 + u | ||
244 | |||
245 | curvecommon = CurveCommon | ||
246 | { ecc_a = 486662 | ||
247 | , ecc_b = 1 | ||
248 | , ecc_g = Point 9 14781619447589544791020593568409986887264606134616475288964881837755586237401 -- base point | ||
249 | , ecc_n = 2^252 + 0x14def9dea2f79cd65812631a5cf5d3ed -- order | ||
250 | , ecc_h = 8 -- cofactor | ||
251 | } | ||
252 | |||
253 | |||
254 | |||
255 | instance Envelope Message where | ||
256 | type TransactionID Message = Nonce24 | ||
257 | newtype NodeId Message = NodeId Word256 | ||
258 | deriving (Serialize, Eq, Ord, Bits, FiniteBits) | ||
259 | |||
260 | envelopePayload = msgPayload | ||
261 | |||
262 | envelopeTransaction = msgNonce | ||
263 | |||
264 | envelopeClass Message { msgType = Ping } = Query | ||
265 | envelopeClass Message { msgType = Pong } = Response | ||
266 | envelopeClass Message { msgType = GetNodes } = Query | ||
267 | envelopeClass Message { msgType = SendNodes } = Response | ||
268 | |||
269 | buildReply self addr qry payload = (fmap (const payload) qry) { msgClient = self } | ||
270 | |||
271 | instance WireFormat ByteString Message where | ||
272 | type SerializableTo ByteString = Serialize | ||
273 | type CipherContext ByteString Message = ToxCipherContext | ||
274 | |||
275 | decodePayload = mapM decode | ||
276 | encodePayload = fmap encode | ||
277 | |||
278 | decodeHeaders ctx bs = runGet getMessage bs >>= decipher ctx | ||
279 | encodeHeaders ctx msg = runPut $ putMessage $ encipher ctx msg | ||