\begin{code}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE StrictData    #-}
module Tox.Onion.RPC where

import           Data.Binary               (Binary, get, put)
import qualified Data.Binary.Get           as Get
import           Data.Word                 (Word64, Word8)
import           GHC.Generics              (Generic)
import           Test.QuickCheck.Arbitrary (Arbitrary (..))

import           Tox.Crypto.Core.Box               (CipherText)
import           Tox.Crypto.Core.Key               (Nonce, PublicKey)
import           Tox.Network.Core.NodeInfo         (NodeInfo)


{-------------------------------------------------------------------------------
 -
 - :: Implementation.
 -
 ------------------------------------------------------------------------------}


-- | Announce Request Payload (decrypted).
data AnnounceRequestPayload = AnnounceRequestPayload
  { AnnounceRequestPayload -> PublicKey
announceRequestPingId          :: PublicKey -- ^ Ping ID or 0
  , AnnounceRequestPayload -> PublicKey
announceRequestSearchKey       :: PublicKey -- ^ Public key we are searching for
  , AnnounceRequestPayload -> PublicKey
announceRequestDataSendbackKey :: PublicKey -- ^ Key for data packets back to us
  , AnnounceRequestPayload -> Word64
announceRequestSendbackData    :: Word64    -- ^ 8 bytes of sendback data
  }
  deriving (AnnounceRequestPayload -> AnnounceRequestPayload -> Bool
(AnnounceRequestPayload -> AnnounceRequestPayload -> Bool)
-> (AnnounceRequestPayload -> AnnounceRequestPayload -> Bool)
-> Eq AnnounceRequestPayload
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AnnounceRequestPayload -> AnnounceRequestPayload -> Bool
$c/= :: AnnounceRequestPayload -> AnnounceRequestPayload -> Bool
== :: AnnounceRequestPayload -> AnnounceRequestPayload -> Bool
$c== :: AnnounceRequestPayload -> AnnounceRequestPayload -> Bool
Eq, Int -> AnnounceRequestPayload -> ShowS
[AnnounceRequestPayload] -> ShowS
AnnounceRequestPayload -> String
(Int -> AnnounceRequestPayload -> ShowS)
-> (AnnounceRequestPayload -> String)
-> ([AnnounceRequestPayload] -> ShowS)
-> Show AnnounceRequestPayload
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AnnounceRequestPayload] -> ShowS
$cshowList :: [AnnounceRequestPayload] -> ShowS
show :: AnnounceRequestPayload -> String
$cshow :: AnnounceRequestPayload -> String
showsPrec :: Int -> AnnounceRequestPayload -> ShowS
$cshowsPrec :: Int -> AnnounceRequestPayload -> ShowS
Show, ReadPrec [AnnounceRequestPayload]
ReadPrec AnnounceRequestPayload
Int -> ReadS AnnounceRequestPayload
ReadS [AnnounceRequestPayload]
(Int -> ReadS AnnounceRequestPayload)
-> ReadS [AnnounceRequestPayload]
-> ReadPrec AnnounceRequestPayload
-> ReadPrec [AnnounceRequestPayload]
-> Read AnnounceRequestPayload
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [AnnounceRequestPayload]
$creadListPrec :: ReadPrec [AnnounceRequestPayload]
readPrec :: ReadPrec AnnounceRequestPayload
$creadPrec :: ReadPrec AnnounceRequestPayload
readList :: ReadS [AnnounceRequestPayload]
$creadList :: ReadS [AnnounceRequestPayload]
readsPrec :: Int -> ReadS AnnounceRequestPayload
$creadsPrec :: Int -> ReadS AnnounceRequestPayload
Read, (forall x. AnnounceRequestPayload -> Rep AnnounceRequestPayload x)
-> (forall x.
    Rep AnnounceRequestPayload x -> AnnounceRequestPayload)
-> Generic AnnounceRequestPayload
forall x. Rep AnnounceRequestPayload x -> AnnounceRequestPayload
forall x. AnnounceRequestPayload -> Rep AnnounceRequestPayload x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep AnnounceRequestPayload x -> AnnounceRequestPayload
$cfrom :: forall x. AnnounceRequestPayload -> Rep AnnounceRequestPayload x
Generic)

instance Binary AnnounceRequestPayload where
  put :: AnnounceRequestPayload -> Put
put AnnounceRequestPayload
req = do
    PublicKey -> Put
forall t. Binary t => t -> Put
put (PublicKey -> Put) -> PublicKey -> Put
forall a b. (a -> b) -> a -> b
$ AnnounceRequestPayload -> PublicKey
announceRequestPingId AnnounceRequestPayload
req
    PublicKey -> Put
forall t. Binary t => t -> Put
put (PublicKey -> Put) -> PublicKey -> Put
forall a b. (a -> b) -> a -> b
$ AnnounceRequestPayload -> PublicKey
announceRequestSearchKey AnnounceRequestPayload
req
    PublicKey -> Put
forall t. Binary t => t -> Put
put (PublicKey -> Put) -> PublicKey -> Put
forall a b. (a -> b) -> a -> b
$ AnnounceRequestPayload -> PublicKey
announceRequestDataSendbackKey AnnounceRequestPayload
req
    Word64 -> Put
forall t. Binary t => t -> Put
put (Word64 -> Put) -> Word64 -> Put
forall a b. (a -> b) -> a -> b
$ AnnounceRequestPayload -> Word64
announceRequestSendbackData AnnounceRequestPayload
req
  get :: Get AnnounceRequestPayload
get = PublicKey
-> PublicKey -> PublicKey -> Word64 -> AnnounceRequestPayload
AnnounceRequestPayload (PublicKey
 -> PublicKey -> PublicKey -> Word64 -> AnnounceRequestPayload)
-> Get PublicKey
-> Get (PublicKey -> PublicKey -> Word64 -> AnnounceRequestPayload)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get PublicKey
forall t. Binary t => Get t
get Get (PublicKey -> PublicKey -> Word64 -> AnnounceRequestPayload)
-> Get PublicKey
-> Get (PublicKey -> Word64 -> AnnounceRequestPayload)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get PublicKey
forall t. Binary t => Get t
get Get (PublicKey -> Word64 -> AnnounceRequestPayload)
-> Get PublicKey -> Get (Word64 -> AnnounceRequestPayload)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get PublicKey
forall t. Binary t => Get t
get Get (Word64 -> AnnounceRequestPayload)
-> Get Word64 -> Get AnnounceRequestPayload
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get Word64
forall t. Binary t => Get t
get

instance Arbitrary AnnounceRequestPayload where
  arbitrary :: Gen AnnounceRequestPayload
arbitrary = PublicKey
-> PublicKey -> PublicKey -> Word64 -> AnnounceRequestPayload
AnnounceRequestPayload (PublicKey
 -> PublicKey -> PublicKey -> Word64 -> AnnounceRequestPayload)
-> Gen PublicKey
-> Gen (PublicKey -> PublicKey -> Word64 -> AnnounceRequestPayload)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen PublicKey
forall a. Arbitrary a => Gen a
arbitrary Gen (PublicKey -> PublicKey -> Word64 -> AnnounceRequestPayload)
-> Gen PublicKey
-> Gen (PublicKey -> Word64 -> AnnounceRequestPayload)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen PublicKey
forall a. Arbitrary a => Gen a
arbitrary Gen (PublicKey -> Word64 -> AnnounceRequestPayload)
-> Gen PublicKey -> Gen (Word64 -> AnnounceRequestPayload)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen PublicKey
forall a. Arbitrary a => Gen a
arbitrary Gen (Word64 -> AnnounceRequestPayload)
-> Gen Word64 -> Gen AnnounceRequestPayload
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Word64
forall a. Arbitrary a => Gen a
arbitrary


-- | Announce Request Packet (0x83).
data AnnounceRequest = AnnounceRequest
  { AnnounceRequest -> Nonce
announceRequestNonce            :: Nonce
  , AnnounceRequest -> PublicKey
announceRequestSenderPublicKey  :: PublicKey
  , AnnounceRequest -> CipherText
announceRequestEncryptedPayload :: CipherText
  }
  deriving (AnnounceRequest -> AnnounceRequest -> Bool
(AnnounceRequest -> AnnounceRequest -> Bool)
-> (AnnounceRequest -> AnnounceRequest -> Bool)
-> Eq AnnounceRequest
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AnnounceRequest -> AnnounceRequest -> Bool
$c/= :: AnnounceRequest -> AnnounceRequest -> Bool
== :: AnnounceRequest -> AnnounceRequest -> Bool
$c== :: AnnounceRequest -> AnnounceRequest -> Bool
Eq, Int -> AnnounceRequest -> ShowS
[AnnounceRequest] -> ShowS
AnnounceRequest -> String
(Int -> AnnounceRequest -> ShowS)
-> (AnnounceRequest -> String)
-> ([AnnounceRequest] -> ShowS)
-> Show AnnounceRequest
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AnnounceRequest] -> ShowS
$cshowList :: [AnnounceRequest] -> ShowS
show :: AnnounceRequest -> String
$cshow :: AnnounceRequest -> String
showsPrec :: Int -> AnnounceRequest -> ShowS
$cshowsPrec :: Int -> AnnounceRequest -> ShowS
Show, ReadPrec [AnnounceRequest]
ReadPrec AnnounceRequest
Int -> ReadS AnnounceRequest
ReadS [AnnounceRequest]
(Int -> ReadS AnnounceRequest)
-> ReadS [AnnounceRequest]
-> ReadPrec AnnounceRequest
-> ReadPrec [AnnounceRequest]
-> Read AnnounceRequest
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [AnnounceRequest]
$creadListPrec :: ReadPrec [AnnounceRequest]
readPrec :: ReadPrec AnnounceRequest
$creadPrec :: ReadPrec AnnounceRequest
readList :: ReadS [AnnounceRequest]
$creadList :: ReadS [AnnounceRequest]
readsPrec :: Int -> ReadS AnnounceRequest
$creadsPrec :: Int -> ReadS AnnounceRequest
Read, (forall x. AnnounceRequest -> Rep AnnounceRequest x)
-> (forall x. Rep AnnounceRequest x -> AnnounceRequest)
-> Generic AnnounceRequest
forall x. Rep AnnounceRequest x -> AnnounceRequest
forall x. AnnounceRequest -> Rep AnnounceRequest x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep AnnounceRequest x -> AnnounceRequest
$cfrom :: forall x. AnnounceRequest -> Rep AnnounceRequest x
Generic)

instance Binary AnnounceRequest where
  put :: AnnounceRequest -> Put
put AnnounceRequest
req = do
    Nonce -> Put
forall t. Binary t => t -> Put
put (Nonce -> Put) -> Nonce -> Put
forall a b. (a -> b) -> a -> b
$ AnnounceRequest -> Nonce
announceRequestNonce AnnounceRequest
req
    PublicKey -> Put
forall t. Binary t => t -> Put
put (PublicKey -> Put) -> PublicKey -> Put
forall a b. (a -> b) -> a -> b
$ AnnounceRequest -> PublicKey
announceRequestSenderPublicKey AnnounceRequest
req
    CipherText -> Put
forall t. Binary t => t -> Put
put (CipherText -> Put) -> CipherText -> Put
forall a b. (a -> b) -> a -> b
$ AnnounceRequest -> CipherText
announceRequestEncryptedPayload AnnounceRequest
req
  get :: Get AnnounceRequest
get = Nonce -> PublicKey -> CipherText -> AnnounceRequest
AnnounceRequest (Nonce -> PublicKey -> CipherText -> AnnounceRequest)
-> Get Nonce -> Get (PublicKey -> CipherText -> AnnounceRequest)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get Nonce
forall t. Binary t => Get t
get Get (PublicKey -> CipherText -> AnnounceRequest)
-> Get PublicKey -> Get (CipherText -> AnnounceRequest)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get PublicKey
forall t. Binary t => Get t
get Get (CipherText -> AnnounceRequest)
-> Get CipherText -> Get AnnounceRequest
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get CipherText
forall t. Binary t => Get t
get

instance Arbitrary AnnounceRequest where
  arbitrary :: Gen AnnounceRequest
arbitrary = Nonce -> PublicKey -> CipherText -> AnnounceRequest
AnnounceRequest (Nonce -> PublicKey -> CipherText -> AnnounceRequest)
-> Gen Nonce -> Gen (PublicKey -> CipherText -> AnnounceRequest)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Nonce
forall a. Arbitrary a => Gen a
arbitrary Gen (PublicKey -> CipherText -> AnnounceRequest)
-> Gen PublicKey -> Gen (CipherText -> AnnounceRequest)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen PublicKey
forall a. Arbitrary a => Gen a
arbitrary Gen (CipherText -> AnnounceRequest)
-> Gen CipherText -> Gen AnnounceRequest
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen CipherText
forall a. Arbitrary a => Gen a
arbitrary


-- | Announce Response Payload (decrypted).
data AnnounceResponsePayload = AnnounceResponsePayload
  { AnnounceResponsePayload -> Word8
announceResponseIsStored :: Word8     -- ^ 0, 1, or 2
  , AnnounceResponsePayload -> PublicKey
announceResponsePingId   :: PublicKey -- ^ Ping ID or Public Key
  , AnnounceResponsePayload -> [NodeInfo]
announceResponseNodes    :: [NodeInfo] -- ^ Up to 4 nodes
  }
  deriving (AnnounceResponsePayload -> AnnounceResponsePayload -> Bool
(AnnounceResponsePayload -> AnnounceResponsePayload -> Bool)
-> (AnnounceResponsePayload -> AnnounceResponsePayload -> Bool)
-> Eq AnnounceResponsePayload
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AnnounceResponsePayload -> AnnounceResponsePayload -> Bool
$c/= :: AnnounceResponsePayload -> AnnounceResponsePayload -> Bool
== :: AnnounceResponsePayload -> AnnounceResponsePayload -> Bool
$c== :: AnnounceResponsePayload -> AnnounceResponsePayload -> Bool
Eq, Int -> AnnounceResponsePayload -> ShowS
[AnnounceResponsePayload] -> ShowS
AnnounceResponsePayload -> String
(Int -> AnnounceResponsePayload -> ShowS)
-> (AnnounceResponsePayload -> String)
-> ([AnnounceResponsePayload] -> ShowS)
-> Show AnnounceResponsePayload
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AnnounceResponsePayload] -> ShowS
$cshowList :: [AnnounceResponsePayload] -> ShowS
show :: AnnounceResponsePayload -> String
$cshow :: AnnounceResponsePayload -> String
showsPrec :: Int -> AnnounceResponsePayload -> ShowS
$cshowsPrec :: Int -> AnnounceResponsePayload -> ShowS
Show, ReadPrec [AnnounceResponsePayload]
ReadPrec AnnounceResponsePayload
Int -> ReadS AnnounceResponsePayload
ReadS [AnnounceResponsePayload]
(Int -> ReadS AnnounceResponsePayload)
-> ReadS [AnnounceResponsePayload]
-> ReadPrec AnnounceResponsePayload
-> ReadPrec [AnnounceResponsePayload]
-> Read AnnounceResponsePayload
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [AnnounceResponsePayload]
$creadListPrec :: ReadPrec [AnnounceResponsePayload]
readPrec :: ReadPrec AnnounceResponsePayload
$creadPrec :: ReadPrec AnnounceResponsePayload
readList :: ReadS [AnnounceResponsePayload]
$creadList :: ReadS [AnnounceResponsePayload]
readsPrec :: Int -> ReadS AnnounceResponsePayload
$creadsPrec :: Int -> ReadS AnnounceResponsePayload
Read, (forall x.
 AnnounceResponsePayload -> Rep AnnounceResponsePayload x)
-> (forall x.
    Rep AnnounceResponsePayload x -> AnnounceResponsePayload)
-> Generic AnnounceResponsePayload
forall x. Rep AnnounceResponsePayload x -> AnnounceResponsePayload
forall x. AnnounceResponsePayload -> Rep AnnounceResponsePayload x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep AnnounceResponsePayload x -> AnnounceResponsePayload
$cfrom :: forall x. AnnounceResponsePayload -> Rep AnnounceResponsePayload x
Generic)

instance Binary AnnounceResponsePayload where
  put :: AnnounceResponsePayload -> Put
put AnnounceResponsePayload
res = do
    Word8 -> Put
forall t. Binary t => t -> Put
put (Word8 -> Put) -> Word8 -> Put
forall a b. (a -> b) -> a -> b
$ AnnounceResponsePayload -> Word8
announceResponseIsStored AnnounceResponsePayload
res
    PublicKey -> Put
forall t. Binary t => t -> Put
put (PublicKey -> Put) -> PublicKey -> Put
forall a b. (a -> b) -> a -> b
$ AnnounceResponsePayload -> PublicKey
announceResponsePingId AnnounceResponsePayload
res
    (NodeInfo -> Put) -> [NodeInfo] -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ NodeInfo -> Put
forall t. Binary t => t -> Put
put (Int -> [NodeInfo] -> [NodeInfo]
forall a. Int -> [a] -> [a]
take Int
4 ([NodeInfo] -> [NodeInfo]) -> [NodeInfo] -> [NodeInfo]
forall a b. (a -> b) -> a -> b
$ AnnounceResponsePayload -> [NodeInfo]
announceResponseNodes AnnounceResponsePayload
res)
  get :: Get AnnounceResponsePayload
get = do
    Word8
isStored <- Get Word8
forall t. Binary t => Get t
get
    PublicKey
pingId <- Get PublicKey
forall t. Binary t => Get t
get
    Word8 -> PublicKey -> [NodeInfo] -> AnnounceResponsePayload
AnnounceResponsePayload Word8
isStored PublicKey
pingId ([NodeInfo] -> AnnounceResponsePayload)
-> Get [NodeInfo] -> Get AnnounceResponsePayload
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get [NodeInfo]
getNodes
    where
      getNodes :: Get [NodeInfo]
getNodes = do
        Bool
empty <- Get Bool
Get.isEmpty
        if Bool
empty
          then [NodeInfo] -> Get [NodeInfo]
forall (m :: * -> *) a. Monad m => a -> m a
return []
          else (:) (NodeInfo -> [NodeInfo] -> [NodeInfo])
-> Get NodeInfo -> Get ([NodeInfo] -> [NodeInfo])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get NodeInfo
forall t. Binary t => Get t
get Get ([NodeInfo] -> [NodeInfo]) -> Get [NodeInfo] -> Get [NodeInfo]
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get [NodeInfo]
getNodes

instance Arbitrary AnnounceResponsePayload where
  arbitrary :: Gen AnnounceResponsePayload
arbitrary = Word8 -> PublicKey -> [NodeInfo] -> AnnounceResponsePayload
AnnounceResponsePayload (Word8 -> PublicKey -> [NodeInfo] -> AnnounceResponsePayload)
-> Gen Word8
-> Gen (PublicKey -> [NodeInfo] -> AnnounceResponsePayload)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Word8
forall a. Arbitrary a => Gen a
arbitrary Gen (PublicKey -> [NodeInfo] -> AnnounceResponsePayload)
-> Gen PublicKey -> Gen ([NodeInfo] -> AnnounceResponsePayload)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen PublicKey
forall a. Arbitrary a => Gen a
arbitrary Gen ([NodeInfo] -> AnnounceResponsePayload)
-> Gen [NodeInfo] -> Gen AnnounceResponsePayload
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen [NodeInfo]
forall a. Arbitrary a => Gen a
arbitrary


-- | Announce Response Packet (0x84).
data AnnounceResponse = AnnounceResponse
  { AnnounceResponse -> Word64
announceResponseSendbackData    :: Word64 -- ^ 8 bytes of sendback data
  , AnnounceResponse -> Nonce
announceResponseNonce           :: Nonce
  , AnnounceResponse -> CipherText
announceResponseEncryptedPayload :: CipherText
  }
  deriving (AnnounceResponse -> AnnounceResponse -> Bool
(AnnounceResponse -> AnnounceResponse -> Bool)
-> (AnnounceResponse -> AnnounceResponse -> Bool)
-> Eq AnnounceResponse
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AnnounceResponse -> AnnounceResponse -> Bool
$c/= :: AnnounceResponse -> AnnounceResponse -> Bool
== :: AnnounceResponse -> AnnounceResponse -> Bool
$c== :: AnnounceResponse -> AnnounceResponse -> Bool
Eq, Int -> AnnounceResponse -> ShowS
[AnnounceResponse] -> ShowS
AnnounceResponse -> String
(Int -> AnnounceResponse -> ShowS)
-> (AnnounceResponse -> String)
-> ([AnnounceResponse] -> ShowS)
-> Show AnnounceResponse
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AnnounceResponse] -> ShowS
$cshowList :: [AnnounceResponse] -> ShowS
show :: AnnounceResponse -> String
$cshow :: AnnounceResponse -> String
showsPrec :: Int -> AnnounceResponse -> ShowS
$cshowsPrec :: Int -> AnnounceResponse -> ShowS
Show, ReadPrec [AnnounceResponse]
ReadPrec AnnounceResponse
Int -> ReadS AnnounceResponse
ReadS [AnnounceResponse]
(Int -> ReadS AnnounceResponse)
-> ReadS [AnnounceResponse]
-> ReadPrec AnnounceResponse
-> ReadPrec [AnnounceResponse]
-> Read AnnounceResponse
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [AnnounceResponse]
$creadListPrec :: ReadPrec [AnnounceResponse]
readPrec :: ReadPrec AnnounceResponse
$creadPrec :: ReadPrec AnnounceResponse
readList :: ReadS [AnnounceResponse]
$creadList :: ReadS [AnnounceResponse]
readsPrec :: Int -> ReadS AnnounceResponse
$creadsPrec :: Int -> ReadS AnnounceResponse
Read, (forall x. AnnounceResponse -> Rep AnnounceResponse x)
-> (forall x. Rep AnnounceResponse x -> AnnounceResponse)
-> Generic AnnounceResponse
forall x. Rep AnnounceResponse x -> AnnounceResponse
forall x. AnnounceResponse -> Rep AnnounceResponse x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep AnnounceResponse x -> AnnounceResponse
$cfrom :: forall x. AnnounceResponse -> Rep AnnounceResponse x
Generic)

instance Binary AnnounceResponse where
  put :: AnnounceResponse -> Put
put AnnounceResponse
res = do
    Word64 -> Put
forall t. Binary t => t -> Put
put (Word64 -> Put) -> Word64 -> Put
forall a b. (a -> b) -> a -> b
$ AnnounceResponse -> Word64
announceResponseSendbackData AnnounceResponse
res
    Nonce -> Put
forall t. Binary t => t -> Put
put (Nonce -> Put) -> Nonce -> Put
forall a b. (a -> b) -> a -> b
$ AnnounceResponse -> Nonce
announceResponseNonce AnnounceResponse
res
    CipherText -> Put
forall t. Binary t => t -> Put
put (CipherText -> Put) -> CipherText -> Put
forall a b. (a -> b) -> a -> b
$ AnnounceResponse -> CipherText
announceResponseEncryptedPayload AnnounceResponse
res
  get :: Get AnnounceResponse
get = Word64 -> Nonce -> CipherText -> AnnounceResponse
AnnounceResponse (Word64 -> Nonce -> CipherText -> AnnounceResponse)
-> Get Word64 -> Get (Nonce -> CipherText -> AnnounceResponse)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get Word64
forall t. Binary t => Get t
get Get (Nonce -> CipherText -> AnnounceResponse)
-> Get Nonce -> Get (CipherText -> AnnounceResponse)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get Nonce
forall t. Binary t => Get t
get Get (CipherText -> AnnounceResponse)
-> Get CipherText -> Get AnnounceResponse
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get CipherText
forall t. Binary t => Get t
get

instance Arbitrary AnnounceResponse where
  arbitrary :: Gen AnnounceResponse
arbitrary = Word64 -> Nonce -> CipherText -> AnnounceResponse
AnnounceResponse (Word64 -> Nonce -> CipherText -> AnnounceResponse)
-> Gen Word64 -> Gen (Nonce -> CipherText -> AnnounceResponse)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Word64
forall a. Arbitrary a => Gen a
arbitrary Gen (Nonce -> CipherText -> AnnounceResponse)
-> Gen Nonce -> Gen (CipherText -> AnnounceResponse)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Nonce
forall a. Arbitrary a => Gen a
arbitrary Gen (CipherText -> AnnounceResponse)
-> Gen CipherText -> Gen AnnounceResponse
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen CipherText
forall a. Arbitrary a => Gen a
arbitrary


-- | Data to Route Request Packet (0x85).
data DataRouteRequest = DataRouteRequest
  { DataRouteRequest -> PublicKey
dataRouteRequestDestination      :: PublicKey -- ^ Destination real PK
  , DataRouteRequest -> Nonce
dataRouteRequestNonce            :: Nonce
  , DataRouteRequest -> PublicKey
dataRouteRequestTemporaryKey     :: PublicKey
  , DataRouteRequest -> CipherText
dataRouteRequestEncryptedPayload :: CipherText
  }
  deriving (DataRouteRequest -> DataRouteRequest -> Bool
(DataRouteRequest -> DataRouteRequest -> Bool)
-> (DataRouteRequest -> DataRouteRequest -> Bool)
-> Eq DataRouteRequest
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DataRouteRequest -> DataRouteRequest -> Bool
$c/= :: DataRouteRequest -> DataRouteRequest -> Bool
== :: DataRouteRequest -> DataRouteRequest -> Bool
$c== :: DataRouteRequest -> DataRouteRequest -> Bool
Eq, Int -> DataRouteRequest -> ShowS
[DataRouteRequest] -> ShowS
DataRouteRequest -> String
(Int -> DataRouteRequest -> ShowS)
-> (DataRouteRequest -> String)
-> ([DataRouteRequest] -> ShowS)
-> Show DataRouteRequest
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DataRouteRequest] -> ShowS
$cshowList :: [DataRouteRequest] -> ShowS
show :: DataRouteRequest -> String
$cshow :: DataRouteRequest -> String
showsPrec :: Int -> DataRouteRequest -> ShowS
$cshowsPrec :: Int -> DataRouteRequest -> ShowS
Show, ReadPrec [DataRouteRequest]
ReadPrec DataRouteRequest
Int -> ReadS DataRouteRequest
ReadS [DataRouteRequest]
(Int -> ReadS DataRouteRequest)
-> ReadS [DataRouteRequest]
-> ReadPrec DataRouteRequest
-> ReadPrec [DataRouteRequest]
-> Read DataRouteRequest
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [DataRouteRequest]
$creadListPrec :: ReadPrec [DataRouteRequest]
readPrec :: ReadPrec DataRouteRequest
$creadPrec :: ReadPrec DataRouteRequest
readList :: ReadS [DataRouteRequest]
$creadList :: ReadS [DataRouteRequest]
readsPrec :: Int -> ReadS DataRouteRequest
$creadsPrec :: Int -> ReadS DataRouteRequest
Read, (forall x. DataRouteRequest -> Rep DataRouteRequest x)
-> (forall x. Rep DataRouteRequest x -> DataRouteRequest)
-> Generic DataRouteRequest
forall x. Rep DataRouteRequest x -> DataRouteRequest
forall x. DataRouteRequest -> Rep DataRouteRequest x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep DataRouteRequest x -> DataRouteRequest
$cfrom :: forall x. DataRouteRequest -> Rep DataRouteRequest x
Generic)

instance Binary DataRouteRequest where
  put :: DataRouteRequest -> Put
put DataRouteRequest
req = do
    PublicKey -> Put
forall t. Binary t => t -> Put
put (PublicKey -> Put) -> PublicKey -> Put
forall a b. (a -> b) -> a -> b
$ DataRouteRequest -> PublicKey
dataRouteRequestDestination DataRouteRequest
req
    Nonce -> Put
forall t. Binary t => t -> Put
put (Nonce -> Put) -> Nonce -> Put
forall a b. (a -> b) -> a -> b
$ DataRouteRequest -> Nonce
dataRouteRequestNonce DataRouteRequest
req
    PublicKey -> Put
forall t. Binary t => t -> Put
put (PublicKey -> Put) -> PublicKey -> Put
forall a b. (a -> b) -> a -> b
$ DataRouteRequest -> PublicKey
dataRouteRequestTemporaryKey DataRouteRequest
req
    CipherText -> Put
forall t. Binary t => t -> Put
put (CipherText -> Put) -> CipherText -> Put
forall a b. (a -> b) -> a -> b
$ DataRouteRequest -> CipherText
dataRouteRequestEncryptedPayload DataRouteRequest
req
  get :: Get DataRouteRequest
get = PublicKey -> Nonce -> PublicKey -> CipherText -> DataRouteRequest
DataRouteRequest (PublicKey -> Nonce -> PublicKey -> CipherText -> DataRouteRequest)
-> Get PublicKey
-> Get (Nonce -> PublicKey -> CipherText -> DataRouteRequest)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get PublicKey
forall t. Binary t => Get t
get Get (Nonce -> PublicKey -> CipherText -> DataRouteRequest)
-> Get Nonce -> Get (PublicKey -> CipherText -> DataRouteRequest)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get Nonce
forall t. Binary t => Get t
get Get (PublicKey -> CipherText -> DataRouteRequest)
-> Get PublicKey -> Get (CipherText -> DataRouteRequest)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get PublicKey
forall t. Binary t => Get t
get Get (CipherText -> DataRouteRequest)
-> Get CipherText -> Get DataRouteRequest
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get CipherText
forall t. Binary t => Get t
get

instance Arbitrary DataRouteRequest where
  arbitrary :: Gen DataRouteRequest
arbitrary = PublicKey -> Nonce -> PublicKey -> CipherText -> DataRouteRequest
DataRouteRequest (PublicKey -> Nonce -> PublicKey -> CipherText -> DataRouteRequest)
-> Gen PublicKey
-> Gen (Nonce -> PublicKey -> CipherText -> DataRouteRequest)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen PublicKey
forall a. Arbitrary a => Gen a
arbitrary Gen (Nonce -> PublicKey -> CipherText -> DataRouteRequest)
-> Gen Nonce -> Gen (PublicKey -> CipherText -> DataRouteRequest)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Nonce
forall a. Arbitrary a => Gen a
arbitrary Gen (PublicKey -> CipherText -> DataRouteRequest)
-> Gen PublicKey -> Gen (CipherText -> DataRouteRequest)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen PublicKey
forall a. Arbitrary a => Gen a
arbitrary Gen (CipherText -> DataRouteRequest)
-> Gen CipherText -> Gen DataRouteRequest
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen CipherText
forall a. Arbitrary a => Gen a
arbitrary


-- | Data to Route Response Packet (0x86).
data DataRouteResponse = DataRouteResponse
  { DataRouteResponse -> Nonce
dataRouteResponseNonce            :: Nonce
  , DataRouteResponse -> PublicKey
dataRouteResponseTemporaryKey     :: PublicKey
  , DataRouteResponse -> CipherText
dataRouteResponseEncryptedPayload :: CipherText
  }
  deriving (DataRouteResponse -> DataRouteResponse -> Bool
(DataRouteResponse -> DataRouteResponse -> Bool)
-> (DataRouteResponse -> DataRouteResponse -> Bool)
-> Eq DataRouteResponse
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DataRouteResponse -> DataRouteResponse -> Bool
$c/= :: DataRouteResponse -> DataRouteResponse -> Bool
== :: DataRouteResponse -> DataRouteResponse -> Bool
$c== :: DataRouteResponse -> DataRouteResponse -> Bool
Eq, Int -> DataRouteResponse -> ShowS
[DataRouteResponse] -> ShowS
DataRouteResponse -> String
(Int -> DataRouteResponse -> ShowS)
-> (DataRouteResponse -> String)
-> ([DataRouteResponse] -> ShowS)
-> Show DataRouteResponse
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DataRouteResponse] -> ShowS
$cshowList :: [DataRouteResponse] -> ShowS
show :: DataRouteResponse -> String
$cshow :: DataRouteResponse -> String
showsPrec :: Int -> DataRouteResponse -> ShowS
$cshowsPrec :: Int -> DataRouteResponse -> ShowS
Show, ReadPrec [DataRouteResponse]
ReadPrec DataRouteResponse
Int -> ReadS DataRouteResponse
ReadS [DataRouteResponse]
(Int -> ReadS DataRouteResponse)
-> ReadS [DataRouteResponse]
-> ReadPrec DataRouteResponse
-> ReadPrec [DataRouteResponse]
-> Read DataRouteResponse
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [DataRouteResponse]
$creadListPrec :: ReadPrec [DataRouteResponse]
readPrec :: ReadPrec DataRouteResponse
$creadPrec :: ReadPrec DataRouteResponse
readList :: ReadS [DataRouteResponse]
$creadList :: ReadS [DataRouteResponse]
readsPrec :: Int -> ReadS DataRouteResponse
$creadsPrec :: Int -> ReadS DataRouteResponse
Read, (forall x. DataRouteResponse -> Rep DataRouteResponse x)
-> (forall x. Rep DataRouteResponse x -> DataRouteResponse)
-> Generic DataRouteResponse
forall x. Rep DataRouteResponse x -> DataRouteResponse
forall x. DataRouteResponse -> Rep DataRouteResponse x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep DataRouteResponse x -> DataRouteResponse
$cfrom :: forall x. DataRouteResponse -> Rep DataRouteResponse x
Generic)

instance Binary DataRouteResponse where
  put :: DataRouteResponse -> Put
put DataRouteResponse
res = do
    Nonce -> Put
forall t. Binary t => t -> Put
put (Nonce -> Put) -> Nonce -> Put
forall a b. (a -> b) -> a -> b
$ DataRouteResponse -> Nonce
dataRouteResponseNonce DataRouteResponse
res
    PublicKey -> Put
forall t. Binary t => t -> Put
put (PublicKey -> Put) -> PublicKey -> Put
forall a b. (a -> b) -> a -> b
$ DataRouteResponse -> PublicKey
dataRouteResponseTemporaryKey DataRouteResponse
res
    CipherText -> Put
forall t. Binary t => t -> Put
put (CipherText -> Put) -> CipherText -> Put
forall a b. (a -> b) -> a -> b
$ DataRouteResponse -> CipherText
dataRouteResponseEncryptedPayload DataRouteResponse
res
  get :: Get DataRouteResponse
get = Nonce -> PublicKey -> CipherText -> DataRouteResponse
DataRouteResponse (Nonce -> PublicKey -> CipherText -> DataRouteResponse)
-> Get Nonce -> Get (PublicKey -> CipherText -> DataRouteResponse)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get Nonce
forall t. Binary t => Get t
get Get (PublicKey -> CipherText -> DataRouteResponse)
-> Get PublicKey -> Get (CipherText -> DataRouteResponse)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get PublicKey
forall t. Binary t => Get t
get Get (CipherText -> DataRouteResponse)
-> Get CipherText -> Get DataRouteResponse
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get CipherText
forall t. Binary t => Get t
get

instance Arbitrary DataRouteResponse where
  arbitrary :: Gen DataRouteResponse
arbitrary = Nonce -> PublicKey -> CipherText -> DataRouteResponse
DataRouteResponse (Nonce -> PublicKey -> CipherText -> DataRouteResponse)
-> Gen Nonce -> Gen (PublicKey -> CipherText -> DataRouteResponse)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Nonce
forall a. Arbitrary a => Gen a
arbitrary Gen (PublicKey -> CipherText -> DataRouteResponse)
-> Gen PublicKey -> Gen (CipherText -> DataRouteResponse)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen PublicKey
forall a. Arbitrary a => Gen a
arbitrary Gen (CipherText -> DataRouteResponse)
-> Gen CipherText -> Gen DataRouteResponse
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen CipherText
forall a. Arbitrary a => Gen a
arbitrary


-- | Inner payload of a Data Route packet (decrypted by destination).
data DataRouteInner = DataRouteInner
  { DataRouteInner -> PublicKey
dataRouteInnerSenderPublicKey :: PublicKey -- ^ Sender real PK
  , DataRouteInner -> CipherText
dataRouteInnerEncryptedPayload :: CipherText
  }
  deriving (DataRouteInner -> DataRouteInner -> Bool
(DataRouteInner -> DataRouteInner -> Bool)
-> (DataRouteInner -> DataRouteInner -> Bool) -> Eq DataRouteInner
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DataRouteInner -> DataRouteInner -> Bool
$c/= :: DataRouteInner -> DataRouteInner -> Bool
== :: DataRouteInner -> DataRouteInner -> Bool
$c== :: DataRouteInner -> DataRouteInner -> Bool
Eq, Int -> DataRouteInner -> ShowS
[DataRouteInner] -> ShowS
DataRouteInner -> String
(Int -> DataRouteInner -> ShowS)
-> (DataRouteInner -> String)
-> ([DataRouteInner] -> ShowS)
-> Show DataRouteInner
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DataRouteInner] -> ShowS
$cshowList :: [DataRouteInner] -> ShowS
show :: DataRouteInner -> String
$cshow :: DataRouteInner -> String
showsPrec :: Int -> DataRouteInner -> ShowS
$cshowsPrec :: Int -> DataRouteInner -> ShowS
Show, ReadPrec [DataRouteInner]
ReadPrec DataRouteInner
Int -> ReadS DataRouteInner
ReadS [DataRouteInner]
(Int -> ReadS DataRouteInner)
-> ReadS [DataRouteInner]
-> ReadPrec DataRouteInner
-> ReadPrec [DataRouteInner]
-> Read DataRouteInner
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [DataRouteInner]
$creadListPrec :: ReadPrec [DataRouteInner]
readPrec :: ReadPrec DataRouteInner
$creadPrec :: ReadPrec DataRouteInner
readList :: ReadS [DataRouteInner]
$creadList :: ReadS [DataRouteInner]
readsPrec :: Int -> ReadS DataRouteInner
$creadsPrec :: Int -> ReadS DataRouteInner
Read, (forall x. DataRouteInner -> Rep DataRouteInner x)
-> (forall x. Rep DataRouteInner x -> DataRouteInner)
-> Generic DataRouteInner
forall x. Rep DataRouteInner x -> DataRouteInner
forall x. DataRouteInner -> Rep DataRouteInner x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep DataRouteInner x -> DataRouteInner
$cfrom :: forall x. DataRouteInner -> Rep DataRouteInner x
Generic)

instance Binary DataRouteInner where
  put :: DataRouteInner -> Put
put DataRouteInner
inner = do
    PublicKey -> Put
forall t. Binary t => t -> Put
put (PublicKey -> Put) -> PublicKey -> Put
forall a b. (a -> b) -> a -> b
$ DataRouteInner -> PublicKey
dataRouteInnerSenderPublicKey DataRouteInner
inner
    CipherText -> Put
forall t. Binary t => t -> Put
put (CipherText -> Put) -> CipherText -> Put
forall a b. (a -> b) -> a -> b
$ DataRouteInner -> CipherText
dataRouteInnerEncryptedPayload DataRouteInner
inner
  get :: Get DataRouteInner
get = PublicKey -> CipherText -> DataRouteInner
DataRouteInner (PublicKey -> CipherText -> DataRouteInner)
-> Get PublicKey -> Get (CipherText -> DataRouteInner)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get PublicKey
forall t. Binary t => Get t
get Get (CipherText -> DataRouteInner)
-> Get CipherText -> Get DataRouteInner
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get CipherText
forall t. Binary t => Get t
get

instance Arbitrary DataRouteInner where
  arbitrary :: Gen DataRouteInner
arbitrary = PublicKey -> CipherText -> DataRouteInner
DataRouteInner (PublicKey -> CipherText -> DataRouteInner)
-> Gen PublicKey -> Gen (CipherText -> DataRouteInner)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen PublicKey
forall a. Arbitrary a => Gen a
arbitrary Gen (CipherText -> DataRouteInner)
-> Gen CipherText -> Gen DataRouteInner
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen CipherText
forall a. Arbitrary a => Gen a
arbitrary


-- | DHT Public Key Packet (0x9c).
-- Sent anonymously via Onion to help friends connect back.
data DHTPublicKeyPacket = DHTPublicKeyPacket
  { DHTPublicKeyPacket -> Word64
dhtPKPacketNoReplay   :: Word64
  , DHTPublicKeyPacket -> PublicKey
dhtPKPacketOurDHTKey  :: PublicKey
  , DHTPublicKeyPacket -> [NodeInfo]
dhtPKPacketNodes      :: [NodeInfo] -- ^ Up to 4 nodes
  }
  deriving (DHTPublicKeyPacket -> DHTPublicKeyPacket -> Bool
(DHTPublicKeyPacket -> DHTPublicKeyPacket -> Bool)
-> (DHTPublicKeyPacket -> DHTPublicKeyPacket -> Bool)
-> Eq DHTPublicKeyPacket
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DHTPublicKeyPacket -> DHTPublicKeyPacket -> Bool
$c/= :: DHTPublicKeyPacket -> DHTPublicKeyPacket -> Bool
== :: DHTPublicKeyPacket -> DHTPublicKeyPacket -> Bool
$c== :: DHTPublicKeyPacket -> DHTPublicKeyPacket -> Bool
Eq, Int -> DHTPublicKeyPacket -> ShowS
[DHTPublicKeyPacket] -> ShowS
DHTPublicKeyPacket -> String
(Int -> DHTPublicKeyPacket -> ShowS)
-> (DHTPublicKeyPacket -> String)
-> ([DHTPublicKeyPacket] -> ShowS)
-> Show DHTPublicKeyPacket
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DHTPublicKeyPacket] -> ShowS
$cshowList :: [DHTPublicKeyPacket] -> ShowS
show :: DHTPublicKeyPacket -> String
$cshow :: DHTPublicKeyPacket -> String
showsPrec :: Int -> DHTPublicKeyPacket -> ShowS
$cshowsPrec :: Int -> DHTPublicKeyPacket -> ShowS
Show, ReadPrec [DHTPublicKeyPacket]
ReadPrec DHTPublicKeyPacket
Int -> ReadS DHTPublicKeyPacket
ReadS [DHTPublicKeyPacket]
(Int -> ReadS DHTPublicKeyPacket)
-> ReadS [DHTPublicKeyPacket]
-> ReadPrec DHTPublicKeyPacket
-> ReadPrec [DHTPublicKeyPacket]
-> Read DHTPublicKeyPacket
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [DHTPublicKeyPacket]
$creadListPrec :: ReadPrec [DHTPublicKeyPacket]
readPrec :: ReadPrec DHTPublicKeyPacket
$creadPrec :: ReadPrec DHTPublicKeyPacket
readList :: ReadS [DHTPublicKeyPacket]
$creadList :: ReadS [DHTPublicKeyPacket]
readsPrec :: Int -> ReadS DHTPublicKeyPacket
$creadsPrec :: Int -> ReadS DHTPublicKeyPacket
Read, (forall x. DHTPublicKeyPacket -> Rep DHTPublicKeyPacket x)
-> (forall x. Rep DHTPublicKeyPacket x -> DHTPublicKeyPacket)
-> Generic DHTPublicKeyPacket
forall x. Rep DHTPublicKeyPacket x -> DHTPublicKeyPacket
forall x. DHTPublicKeyPacket -> Rep DHTPublicKeyPacket x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep DHTPublicKeyPacket x -> DHTPublicKeyPacket
$cfrom :: forall x. DHTPublicKeyPacket -> Rep DHTPublicKeyPacket x
Generic)

instance Binary DHTPublicKeyPacket where
  put :: DHTPublicKeyPacket -> Put
put DHTPublicKeyPacket
pkt = do
    Word64 -> Put
forall t. Binary t => t -> Put
put (Word64 -> Put) -> Word64 -> Put
forall a b. (a -> b) -> a -> b
$ DHTPublicKeyPacket -> Word64
dhtPKPacketNoReplay DHTPublicKeyPacket
pkt
    PublicKey -> Put
forall t. Binary t => t -> Put
put (PublicKey -> Put) -> PublicKey -> Put
forall a b. (a -> b) -> a -> b
$ DHTPublicKeyPacket -> PublicKey
dhtPKPacketOurDHTKey DHTPublicKeyPacket
pkt
    (NodeInfo -> Put) -> [NodeInfo] -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ NodeInfo -> Put
forall t. Binary t => t -> Put
put (Int -> [NodeInfo] -> [NodeInfo]
forall a. Int -> [a] -> [a]
take Int
4 ([NodeInfo] -> [NodeInfo]) -> [NodeInfo] -> [NodeInfo]
forall a b. (a -> b) -> a -> b
$ DHTPublicKeyPacket -> [NodeInfo]
dhtPKPacketNodes DHTPublicKeyPacket
pkt)
  get :: Get DHTPublicKeyPacket
get = do
    Word64
noReplay <- Get Word64
forall t. Binary t => Get t
get
    PublicKey
dhtKey <- Get PublicKey
forall t. Binary t => Get t
get
    Word64 -> PublicKey -> [NodeInfo] -> DHTPublicKeyPacket
DHTPublicKeyPacket Word64
noReplay PublicKey
dhtKey ([NodeInfo] -> DHTPublicKeyPacket)
-> Get [NodeInfo] -> Get DHTPublicKeyPacket
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get [NodeInfo]
getNodes
    where
      getNodes :: Get [NodeInfo]
getNodes = do
        Bool
empty <- Get Bool
Get.isEmpty
        if Bool
empty
          then [NodeInfo] -> Get [NodeInfo]
forall (m :: * -> *) a. Monad m => a -> m a
return []
          else (:) (NodeInfo -> [NodeInfo] -> [NodeInfo])
-> Get NodeInfo -> Get ([NodeInfo] -> [NodeInfo])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get NodeInfo
forall t. Binary t => Get t
get Get ([NodeInfo] -> [NodeInfo]) -> Get [NodeInfo] -> Get [NodeInfo]
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get [NodeInfo]
getNodes

instance Arbitrary DHTPublicKeyPacket where
  arbitrary :: Gen DHTPublicKeyPacket
arbitrary = Word64 -> PublicKey -> [NodeInfo] -> DHTPublicKeyPacket
DHTPublicKeyPacket (Word64 -> PublicKey -> [NodeInfo] -> DHTPublicKeyPacket)
-> Gen Word64
-> Gen (PublicKey -> [NodeInfo] -> DHTPublicKeyPacket)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Word64
forall a. Arbitrary a => Gen a
arbitrary Gen (PublicKey -> [NodeInfo] -> DHTPublicKeyPacket)
-> Gen PublicKey -> Gen ([NodeInfo] -> DHTPublicKeyPacket)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen PublicKey
forall a. Arbitrary a => Gen a
arbitrary Gen ([NodeInfo] -> DHTPublicKeyPacket)
-> Gen [NodeInfo] -> Gen DHTPublicKeyPacket
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen [NodeInfo]
forall a. Arbitrary a => Gen a
arbitrary
\end{code}

This explained how to create onion packets and how they are sent back.  Next is
what is actually sent and received on top of these onion packets or paths.

Note: nonce is a 24 byte nonce.

announce request packet:

\begin{tabular}{l|l}
  Length             & Contents \\
  \hline
  \texttt{1}         & \texttt{uint8\_t} (0x83) \\
  \texttt{24}        & Nonce \\
  \texttt{32}        & A public key (real or temporary) \\
  \texttt{?}         & Payload \\
\end{tabular}

The public key is our real long term public key if we want to announce
ourselves, a temporary one if we are searching for friends.

The payload is encrypted with the secret key part of the sent public key, the
public key of Node D and the nonce, and contains:

\begin{tabular}{l|l}
  Length             & Contents \\
  \hline
  \texttt{32}        & Ping ID \\
  \texttt{32}        & Public key we are searching for \\
  \texttt{32}        & Public key that we want those sending back data packets to use \\
  \texttt{8}         & Data to send back in response \\
\end{tabular}

If the ping id is zero, respond with an announce response packet.

If the ping id matches the one the node sent in the announce response and the
public key matches the one being searched for, add the part used to send data
to our list.  If the list is full make it replace the furthest entry.

data to route request packet:

\begin{tabular}{l|l}
  Length             & Contents \\
  \hline
  \texttt{1}         & \texttt{uint8\_t} (0x85) \\
  \texttt{32}        & Public key of destination node \\
  \texttt{24}        & Nonce \\
  \texttt{32}        & Temporary just generated public key \\
  variable           & Payload \\
\end{tabular}

The payload is encrypted with that temporary secret key and the nonce and the
public key from the announce response packet of the destination node.  If Node
D contains the ret data for the node, it sends the stuff in this packet as a
data to route response packet to the right node.

The data in the previous packet is in format:

\begin{tabular}{l|l}
  Length             & Contents \\
  \hline
  \texttt{32}        & Real public key of sender \\
  variable           & Payload \\
\end{tabular}

The payload is encrypted with real secret key of the sender, the nonce in the
data packet and the real public key of the receiver:

\begin{tabular}{l|l}
  Length             & Contents \\
  \hline
  \texttt{1}         & \texttt{uint8\_t} id \\
  variable           & Data (optional) \\
\end{tabular}

Data sent to us:

announce response packet:

\begin{tabular}{l|l}
  Length             & Contents \\
  \hline
  \texttt{1}         & \texttt{uint8\_t} (0x84) \\
  \texttt{8}         & Data to send back in response \\
  \texttt{24}        & Nonce \\
  variable           & Payload \\
\end{tabular}

The payload is encrypted with the DHT secret key of Node D, the public key in
the request and the nonce:

\begin{tabular}{l|l}
  Length             & Contents \\
  \hline
  \texttt{1}         & \texttt{uint8\_t} \texttt{is\_stored} \\
  \texttt{32}        & Ping ID or Public Key \\
  variable           & Maximum of 4 nodes in packed node format (see DHT) \\
\end{tabular}

The packet contains a ping ID if \texttt{is\_stored} is 0 or 2, or the public
key that must be used to send data packets if \texttt{is\_stored} is 1.

If the \texttt{is\_stored} is not 0, it means the information to reach the
public key we are searching for is stored on this node.  \texttt{is\_stored} is
2 as a response to a peer trying to announce himself to tell the peer that he
is currently announced successfully.

data to route response packet:

\begin{tabular}{l|l}
  Length             & Contents \\
  \hline
  \texttt{1}         & \texttt{uint8\_t} (0x86) \\
  \texttt{24}        & Nonce \\
  \texttt{32}        & Temporary just generated public key \\
  variable           & Payload \\
\end{tabular}

The payload is encrypted with that temporary secret key, the nonce and the
public key from the announce response packet of the destination node.

There are 2 types of request packets and 2 'response' packets to go with them.
The announce request is used to announce ourselves to a node and announce
response packet is used by the node to respond to this packet.  The data to
route request packet is a packet used to send packets through the node to
another peer that has announced itself and that we have found.  The data to
route response packet is what the node transforms this packet into.

To announce ourselves to the network we must first find, using announce
packets, the peers with the DHT public key closest to our real public key.  We
must then announce ourselves to these peers.  Friends will then be able to send
messages to us using data to route packets by sending them to these peers.  To
find the peers we have announced ourselves to, our friends will find the peers
closest to our real public key and ask them if they know us.  They will then be
able to use the peers that know us to send us some messages that will contain
their DHT public key (which we need to know to connect directly to them), TCP
relays that they are connected to (so we can connect to them with these relays
if we need to) and some DHT peers they are connected to (so we can find them
faster in the DHT).

Announce request packets are the same packets used slightly differently if we
are announcing ourselves or searching for peers that know one of our friends.

If we are announcing ourselves we must put our real long term public key in the
packet and encrypt it with our long term private key.  This is so the peer we
are announcing ourselves to can be sure that we actually own that public key.
If we are looking for peers we use a temporary public key used only for packets
looking for that peer in order to leak as little information as possible.  The
\texttt{ping\_id} is a 32 byte number which is sent to us in the announce
response and we must send back to the peer in another announce request.  This
is done in order to prevent people from easily announcing themselves many times
as they have to prove they can respond to packets from the peer before the peer
will let them announce themselves.  This \texttt{ping\_id} is set to 0 when none
is known.

The public key we are searching for is set to our long term public key when
announcing ourselves and set to the long term public key of the friend we are
searching for if we are looking for peers.

When announcing ourselves, the public key we want others to use to send us data
back is set to a temporary public key and we use the private key part of this
key to decrypt packet routing data sent to us.  This public key is to prevent
peers from saving old data to route packets from previous sessions and be able
to replay them in future Tox sessions.  This key is set to zero when searching
for peers.

The sendback data is an 8 byte number that will be sent back in the announce
packet response.  Its goal is to be used to learn which announce request packet
the response is responding to, and hence its location in the unencrypted part
of the response.  This is needed in toxcore to find and check info about the
packet in order to decrypt it and handle it correctly.  Toxcore uses it as an
index to its special \texttt{ping\_array}.

Why don't we use different packets instead of having one announce packet
request and one response that does everything? It makes it a lot more difficult
for possible attackers to know if we are merely announcing ourselves or if we
are looking for friends as the packets for both look the same and are the same
size.

The unencrypted part of an announce response packet contains the sendback data,
which was sent in the request this packet is responding to and a 24 byte random
nonce used to encrypt the encrypted part.

The \texttt{is\_stored} number is set to either 0, 1 or 2.  0 means that the
public key that was being searched in the request isn't stored or known by this
peer.  1 means that it is and 2 means that we are announced successfully at
that node.  Both 1 and 2 are needed so that when clients are restarted it is
possible to reannounce without waiting for the timeout of the previous
announce.  This would not otherwise be possible as a client would receive
response 1 without a \texttt{ping\_id} which is needed in order to reannounce
successfully.

When the \texttt{is\_stored} number is 0 or 2, the next 32 bytes is a
\texttt{ping\_id}.  When \texttt{is\_stored} is 1 it corresponds to a public key
(the send back data public key set by the friend in their announce request)
that must be used to encrypt and send data to the friend.

Then there is an optional maximum 4 nodes, in DHT packed nodes format (see
DHT), attached to the response which denote the 4 DHT peers with the DHT public
keys closest to the searched public key in the announce request known by the
peer (see DHT).  To find these peers, toxcore uses the same function as is used
to find peers for get node DHT responses.  Peers wanting to announce themselves
or searching for peers that 'know' their friends will recursively query closer
and closer peers until they find the closest possible and then either announce
themselves to them or just ping them every once in a while to know if their
friend can be contacted.  Note that the distance function used for this is the
same as the Tox DHT.

Data to route request packets are packets used to send data directly to another
peer via a node that knows that peer.  The public key is the public key of the
final destination where we want the packet to be sent (the real public key of
our friend).  The nonce is a 24 byte random nonce and the public key is a
random temporary public key used to encrypt the data in the packet and, if
possible, only to send packets to this friend (we want to leak as little info
to the network as possible so we use temp public keys as we don't want a peer
to see the same public keys and be able to link things together).  The data is
encrypted data that we want to send to the peer with the public key.

The route response packets are just the last elements (nonce, public key,
encrypted data) of the data to route request packet copied into a new packet
and sent to the appropriate destination.

To handle onion announce packets, toxcore first receives an announce packet and
decrypts it.

Toxcore generates \texttt{ping\_id}s by taking a 32 byte sha hash of the current
time, some secret bytes generated when the instance is created, the current
time divided by a 300 second timeout, the public key of the requester and the
source ip/port that the packet was received from.  Since the ip/port that the
packet was received from is in the \texttt{ping\_id}, the announce packets being
sent with a ping id must be sent using the same path as the packet that we
received the \texttt{ping\_id} from or announcing will fail.

The reason for this 300 second timeout in toxcore is that it gives a reasonable
time (300 to 600 seconds) for peers to announce themselves.

Toxcore generates 2 different ping ids, the first is generated with the current
time (divided by 300) and the second with the current time + 300 (divided by 300).
The two ping ids are then compared to the ping ids in the received packets.
The reason for doing this is that storing every ping id received might be
expensive and leave us vulnerable to a DoS attack, this method makes sure that
the other cannot generate \texttt{ping\_id}s and must ask for them.  The reason
for the 2 \texttt{ping\_id}s is that we want to make sure that the timeout is at
least 300 seconds and cannot be 0.

If one of the two ping ids is equal to the ping id in the announce request,
the sendback data public key and the sendback data are stored in the
datastructure used to store announced peers.  If the implementation has a
limit to how many announced entries it can store, it should only store the
entries closest (determined by the DHT distance function) to its DHT public
key.  If the entry is already there, the information will simply be updated
with the new one and the timeout will be reset for that entry.

Toxcore has a timeout of 300 seconds for announce entries after which they are
removed which is long enough to make sure the entries don't expire prematurely
but not long enough for peers to stay announced for extended amounts of time
after they go offline.

Toxcore will then copy the 4 DHT nodes closest to the public key being searched
to a new packet (the response).

Toxcore will look if the public key being searched is in the datastructure.  If
it isn't it will copy the second generated \texttt{ping\_id} (the one generated
with the current time plus 300 seconds) to the response, set the
\texttt{is\_stored} number to 0 and send the packet back.

If the public key is in the datastructure, it will check whether the public key
that was used to encrypt the announce packet is equal to the announced public
key, if it isn't then it means that the peer is searching for a peer and that
we know it.  This means the \texttt{is\_stored} is set to 1 and the sending back
data public key in the announce entry is copied to the packet.

If it (key used to encrypt the announce packet) is equal (to the announced
public key which is also the 'public key we are searching for' in the announce
packet) meaning the peer is announcing itself and an entry for it exists, the
sending back data public key is checked to see if it equals the one in the
packet.  If it is not equal it means that it is outdated, probably because the
announcing peer's toxcore instance was restarted and so their
\texttt{is\_stored} is set to 0, if it is equal it means the peer is announced
correctly so the \texttt{is\_stored} is set to 2.  The second generated
\texttt{ping\_id} is then copied to the packet.

Once the packet is contructed a random 24 byte nonce is generated, the packet
is encrypted (the shared key used to decrypt the request can be saved and used
to encrypt the response to save an expensive key derivation operation), the
data to send back is copied to the unencrypted part and the packet is sent back
as an onion response packet.