toxcore-0.2.11: src/Network/Tox/SaveData/DHT.lhs
\subsection{DHT (0x02)}
\begin{code}
module Network.Tox.SaveData.DHT (DHT) where
import Control.Arrow (second)
import Control.Monad (when)
import Data.Binary (Binary (..))
import Data.Binary.Get (Get)
import qualified Data.Binary.Get as Get
import Data.Binary.Put (Put)
import qualified Data.Binary.Put as Put
import qualified Data.ByteString.Lazy as LBS
import Data.Word (Word16, Word32)
import Network.Tox.SaveData.Nodes (Nodes)
import qualified Network.Tox.SaveData.Util as Util
import Test.QuickCheck.Arbitrary (Arbitrary, arbitrary)
import qualified Test.QuickCheck.Gen as Gen
\end{code}
This section contains a list of DHT-related sections.
\begin{tabular}{l|l}
Length & Contents \\
\hline
\texttt{4} & \texttt{uint32\_t} (0x159000D) \\
\texttt{?} & List of DHT sections \\
\end{tabular}
\subsubsection{DHT Sections}
Every DHT section has the following structure:
\begin{tabular}{l|l}
Length & Contents \\
\hline
\texttt{4} & \texttt{uint32\_t} Length of this section \\
\texttt{2} & \texttt{uint16\_t} DHT section type \\
\texttt{2} & \texttt{uint16\_t} (0x11CE) \\
\texttt{?} & DHT section \\
\end{tabular}
DHT section types:
\begin{tabular}{l|l}
Name & Value \\
\hline
Nodes & 0x04 \\
\end{tabular}
\paragraph{Nodes (0x04)}
This section contains a list of nodes. These nodes are used to quickly reconnect
to the DHT after a Tox client is restarted.
\begin{tabular}{l|l}
Length & Contents \\
\hline
\texttt{?} & List of nodes \\
\end{tabular}
The structure of a node is the same as \texttt{Node Info}. Note: this means
that the integers stored in these nodes are stored in Big Endian as well.
\begin{code}
dhtMagic :: Word32
dhtMagic = 0x0159000D
sectionMagic :: Word16
sectionMagic = 0x11CE
newtype DHT = DHT [DhtSection]
deriving (Eq, Show, Read)
instance Arbitrary DHT where
arbitrary = DHT <$> arbitrary
instance Binary DHT where
get = do
magic <- Get.getWord32le
when (magic /= dhtMagic) $
fail $ "wrong magic number for DHT savedata: "
++ show magic ++ " != " ++ show dhtMagic
DHT <$> Util.getList
put (DHT sections) = do
Put.putWord32le dhtMagic
mapM_ put sections
newtype DhtSection
= DhtSectionNodes Nodes
deriving (Eq, Show, Read)
instance Binary DhtSection where
get = do
(len, ty) <- Util.getSectionHeader sectionMagic
Get.isolate len $ case ty of
0x04 -> DhtSectionNodes <$> get
_ -> fail $ show ty
put section = do
let (ty, bytes) = second Put.runPut output
Util.putSectionHeader sectionMagic (fromIntegral $ LBS.length bytes) ty
Put.putLazyByteString bytes
where
output = case section of
DhtSectionNodes x -> (0x04, put x)
instance Arbitrary DhtSection where
arbitrary = Gen.oneof
[ DhtSectionNodes <$> arbitrary
]
\end{code}