\section{Node Info (packed node format)}

The Node Info data structure contains a Transport Protocol, a Socket Address,
and a Public Key.  This is sufficient information to start communicating with
that node.  The binary representation of a Node Info is called the "packed node
format".

\begin{tabular}{l|l|l}
  Length             & Type               & Contents \\
  \hline
  \texttt{1} bit     & Transport Protocol & UDP = 0, TCP = 1 \\
  \texttt{7} bit     & Address Family     & 2 = IPv4, 10 = IPv6 \\
  \texttt{4 $|$ 16}  & IP address         & 4 bytes for IPv4, 16 bytes for IPv6 \\
  \texttt{2}         & Port Number        & Port number \\
  \texttt{32}        & Public Key         & Node ID \\
\end{tabular}

The packed node format is a way to store the node info in a small yet easy to
parse format.  To store more than one node, simply append another one to the
previous one: \texttt{[packed node 1][packed node 2][...]}.

In the packed node format, the first byte (high bit protocol, lower 7 bits
address family) are called the IP Type.  The following table is informative and
can be used to simplify the implementation.

\begin{tabular}{l|l|l}
  IP Type               & Transport Protocol & Address Family \\
  \hline
  \texttt{2   (0x02)}   & UDP                & IPv4 \\
  \texttt{10  (0x0a)}   & UDP                & IPv6 \\
  \texttt{130 (0x82)}   & TCP                & IPv4 \\
  \texttt{138 (0x8a)}   & TCP                & IPv6 \\
\end{tabular}

The number \texttt{130} is used for an IPv4 TCP relay and \texttt{138} is used
to indicate an IPv6 TCP relay.

The reason for these numbers is that the numbers on Linux for IPv4 and IPv6
(the \texttt{AF\_INET} and \texttt{AF\_INET6} defines) are \texttt{2} and
\texttt{10}.  The TCP numbers are just the UDP numbers \texttt{+ 128}.

\begin{code}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric      #-}
{-# LANGUAGE Safe               #-}
module Network.Tox.NodeInfo.NodeInfo where

import           Control.Applicative                    ((<$>), (<*>))
import           Data.Binary                            (Binary)
import qualified Data.Binary                            as Binary (get, put)
import           Data.MessagePack                       (MessagePack)
import           Data.Typeable                          (Typeable)
import           GHC.Generics                           (Generic)
import           Test.QuickCheck.Arbitrary              (Arbitrary, arbitrary)

import           Network.Tox.Crypto.Key                 (PublicKey)
import           Network.Tox.NodeInfo.SocketAddress     (SocketAddress)
import qualified Network.Tox.NodeInfo.SocketAddress     as SocketAddress
import           Network.Tox.NodeInfo.TransportProtocol (TransportProtocol)


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


data NodeInfo = NodeInfo
  { protocol  :: TransportProtocol
  , address   :: SocketAddress
  , publicKey :: PublicKey
  }
  deriving (Eq, Ord, Show, Read, Generic, Typeable)

instance MessagePack NodeInfo


instance Binary NodeInfo where
  get =
    uncurry NodeInfo <$> SocketAddress.getSocketAddress <*> Binary.get

  put ni = do
    SocketAddress.putSocketAddress (protocol ni) (address ni)
    Binary.put $ publicKey ni


{-------------------------------------------------------------------------------
 -
 - :: Tests.
 -
 ------------------------------------------------------------------------------}


instance Arbitrary NodeInfo where
  arbitrary =
    NodeInfo <$> arbitrary <*> arbitrary <*> arbitrary
\end{code}