module Network.Tox.Onion.Transport ( parseOnionAddr , encodeOnionAddr , parseDataToRoute , encodeDataToRoute , forwardOnions , AliasSelector(..) , OnionDestination(..) , OnionMessage(..) , Rendezvous(..) , DataToRoute(..) , OnionData(..) , AnnouncedRendezvous(..) , AnnounceResponse(..) , AnnounceRequest(..) , Forwarding(..) , ReturnPath(..) , OnionRequest(..) , OnionResponse(..) , Addressed(..) , UDPTransport , KeyRecord(..) , encrypt , decrypt , peelSymmetric , OnionRoute(..) , N0 , N1 , N2 , N3 , onionKey , onionAliasSelector , selectAlias , RouteId(..) , routeId , putRequest , wrapForRoute , wrapSymmetric , wrapOnion , wrapOnionPure ) where import Data.ByteString (ByteString) import Data.Serialize import Network.Socket import Crypto.Tox hiding (encrypt,decrypt) import qualified Data.Tox.Relay as TCP import Data.Tox.Onion import Network.Tox.NodeId {- encodeOnionAddr :: TransportCrypto -> (NodeInfo -> RouteId -> IO (Maybe OnionRoute)) -> (OnionMessage Encrypted,OnionDestination RouteId) -> IO (Maybe (ByteString, SockAddr)) -} encodeOnionAddr :: TransportCrypto -> (NodeInfo -> RouteId -> IO (Maybe OnionRoute)) -> (OnionMessage Encrypted, OnionDestination RouteId) -> IO (Maybe (Either (TCP.RelayPacket, TCP.NodeInfo) (ByteString, SockAddr))) encodeOnionAddr crypto _ (msg,OnionToOwner ni p) = return $ Just $ Right ( runPut $ putResponse (OnionResponse p msg) , nodeAddr ni ) encodeOnionAddr crypto getRoute (msg,OnionDestination x ni Nothing) = do encodeOnionAddr crypto getRoute (msg,OnionDestination x ni (Just $ routeId $ nodeId ni) ) -- dput XMisc $ "ONION encode missing routeid" -- return Nothing encodeOnionAddr crypto getRoute (msg,OnionDestination _ ni (Just rid)) = do let go route = do mreq <- wrapForRoute crypto msg ni route case mreq of Right req -> return $ Right ( runPut $ putRequest req , nodeAddr $ routeNodeA route) Left o | Just port <- routeRelayPort route -> return $ Left ( o, TCP.NodeInfo (routeNodeA route) port) m <- {-# SCC "encodeOnionAddr.getRoute" #-} getRoute ni rid x <- {-# SCC "encodeOnionAddr.wrapForRoute" #-} mapM go m return x -- wrapForRoute :: TransportCrypto -> OnionMessage Encrypted -> NodeInfo -> OnionRoute -> IO (OnionRequest N0) wrapForRoute :: TransportCrypto -> OnionMessage Encrypted -> NodeInfo -> OnionRoute -> IO (Either TCP.RelayPacket (OnionRequest N0)) wrapForRoute crypto msg ni r@OnionRoute{routeRelayPort=Nothing} = do -- We needn't use the same nonce value here, but I think it is safe to do so. let nonce = msgNonce msg fwd <- wrapOnion crypto (routeAliasA r) nonce (id2key . nodeId $ routeNodeA r) (nodeAddr $ routeNodeB r) =<< wrapOnion crypto (routeAliasB r) nonce (id2key . nodeId $ routeNodeB r) (nodeAddr $ routeNodeC r) =<< wrapOnion crypto (routeAliasC r) nonce (id2key . nodeId $ routeNodeC r) (nodeAddr ni) (NotForwarded msg) return $ Right OnionRequest { onionNonce = nonce , onionForward = fwd , pathFromOwner = NoReturnPath } wrapForRoute crypto msg ni r@OnionRoute{routeRelayPort = Just tcpport} = do let nonce = msgNonce msg fwd <- wrapOnion crypto (routeAliasB r) nonce (id2key . nodeId $ routeNodeB r) (nodeAddr $ routeNodeC r) =<< wrapOnion crypto (routeAliasC r) nonce (id2key . nodeId $ routeNodeC r) (nodeAddr ni) (NotForwarded msg) return $ Left $ TCP.OnionPacket nonce $ Addressed (nodeAddr $ routeNodeB r) fwd