{-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeOperators #-} module Network.Tox.Transport (toxTransport, RouteId) where import Network.QueryResponse import Crypto.Tox import Data.Tox.Relay as TCP import qualified Data.Tox.DHT.Multi as Multi import Network.Tox.DHT.Transport as UDP import Network.Tox.TCP (ViaRelay) import Network.Tox.Onion.Transport import Network.Tox.Crypto.Transport import Network.Tox.Onion.Routes import Control.Concurrent.STM import qualified Data.ByteString as B import qualified Data.Dependent.Map as DMap import Data.Dependent.Sum import Data.Functor.Identity import Network.Socket pendingCookiesUDP :: TransportCrypto -> STM [(SockAddr, (Int, PublicKey))] pendingCookiesUDP crypto = readTVar $ pendingCookies crypto pendingCookiesTCP :: TransportCrypto -> STM [(ViaRelay, (Int, PublicKey))] pendingCookiesTCP crypto = return [] -- TODO toxTransport :: TransportCrypto -> OnionRouter -> (PublicKey -> IO (Maybe UDP.NodeInfo)) -> SockAddr -- ^ UDP bind-address -> UDPTransport -> Transport String ViaRelay B.ByteString -> (TCP.NodeInfo -> RelayPacket -> IO ()) -- ^ (UNUSED) TCP server-bound callback. -> (Int -> OnionMessage Encrypted -> IO ()) -- ^ TCP client-bound callback. -> IO ( Transport String Multi.SessionAddress (CryptoPacket Encrypted) , Transport String Multi.NodeInfo (DHTMessage Encrypted8) , Transport String (OnionDestination RouteId) (OnionMessage Encrypted) , Transport String AnnouncedRendezvous (PublicKey,OnionData) , Transport String Multi.SessionAddress (Handshake Encrypted)) toxTransport crypto orouter closeLookup addr udp relaynet _ tcp2client = do (netcrypto, udp0) <- partitionTransport parseCrypto encodeCrypto udp (dhtUDP,udp1) <- partitionTransportM (parseDHTAddr (pendingCookiesUDP crypto) nodeInfo) (fmap Just . encodeDHTAddr nodeAddr) $ forwardOnions crypto addr udp0 tcp2client -- rlynet0 = layerTransportM (DHT.decrypt crypto Multi.relayNodeId) (DHT.encrypt crypto Multi.relayNodeId) relaynet (dhtTCP,relaynet0) <- partitionTransportM (parseDHTAddr (pendingCookiesTCP crypto) (\nid viarelay -> Right viarelay)) (fmap Just . encodeDHTAddr id) relaynet let _ = dhtTCP :: Transport String ViaRelay (DHTMessage Encrypted8) dht <- mergeTransports $ DMap.fromList [ Multi.UDP :=> ByAddress dhtUDP , Multi.TCP :=> ByAddress dhtTCP ] (onion1,udp2) <- partitionTransportM (parseOnionAddr $ lookupSender orouter) (encodeOnionAddr crypto $ lookupRoute orouter) udp1 (dta,onion) <- partitionTransportM (parseDataToRoute crypto) (encodeDataToRoute crypto) onion1 (netcryptoTCP, relaynet1) <- partitionTransport parseCrypto encodeCrypto relaynet0 multi_netcrypto <- mergeTransports $ DMap.fromList [ Multi.SessionUDP :=> ByAddress netcrypto , Multi.SessionTCP :=> ByAddress netcryptoTCP ] let handshakes = layerTransport parseHandshakes encodeHandshakes udp2 handshakesTCP = layerTransport parseHandshakes encodeHandshakes relaynet1 multi_handshakes <- mergeTransports $ DMap.fromList [ Multi.SessionUDP :=> ByAddress handshakes , Multi.SessionTCP :=> ByAddress handshakesTCP ] return ( multi_netcrypto , forwardDHTRequests crypto (fmap (fmap (Multi.UDP ==>)) . closeLookup) dht , onion , dta , multi_handshakes ) -- instance (Sized a, Sized b) => Sized (a,b) where size = _todo -- Byte value Packet Kind Return address -- :----------- :-------------------- -- `0x00` Ping Request DHTNode -- `0x01` Ping Response - -- `0x02` Nodes Request DHTNode -- `0x04` Nodes Response - -- `0x18` Cookie Request DHTNode, but without sending pubkey in response -- `0x19` Cookie Response - (no pubkey) -- -- `0x21` LAN Discovery DHTNode (No reply, port 33445, trigger Nodes Request/Response) -- -- `0x20` DHT Request DHTNode/-forward -- -- `0x1a` Crypto Handshake CookieAddress -- -- `0x1b` Crypto Data SessionAddress -- -- `0x83` Announce Request OnionToOwner -- `0x84` Announce Response - -- `0x85` Onion Data Request OnionToOwner -- `0x86` Onion Data Response - -- -- `0xf0` Bootstrap Info SockAddr? -- -- `0x80` Onion Request 0 -forward -- `0x81` Onion Request 1 -forward -- `0x82` Onion Request 2 -forward -- `0x8c` Onion Response 3 -return -- `0x8d` Onion Response 2 -return -- `0x8e` Onion Response 1 -return