\begin{code}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric      #-}
{-# LANGUAGE StrictData         #-}
module Network.Tox.Protocol.Packet where

import           Data.Binary                     (Binary)
import           Data.MessagePack                (MessagePack)
import           Data.Typeable                   (Typeable)
import           GHC.Generics                    (Generic)
import           Network.Tox.Protocol.PacketKind (PacketKind)
import           Test.QuickCheck.Arbitrary       (Arbitrary, arbitrary)


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

\end{code}

A Protocol Packet is the top level Tox protocol element.  All other packet
types are wrapped in Protocol Packets.  It consists of a Packet Kind and a
payload.  The binary representation of a Packet Kind is a single byte (8 bits).
The payload is an arbitrary sequence of bytes.

\begin{tabular}{l|l|l}
  Length             & Type        & Contents \\
  \hline
  \texttt{1}         & Packet Kind & The packet kind identifier \\
  \texttt{[0,]}      & Bytes       & Payload \\
\end{tabular}

\begin{code}

data Packet payload = Packet
  { Packet payload -> PacketKind
packetKind    :: PacketKind
  , Packet payload -> payload
packetPayload :: payload
  }
  deriving (Packet payload -> Packet payload -> Bool
(Packet payload -> Packet payload -> Bool)
-> (Packet payload -> Packet payload -> Bool)
-> Eq (Packet payload)
forall payload.
Eq payload =>
Packet payload -> Packet payload -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Packet payload -> Packet payload -> Bool
$c/= :: forall payload.
Eq payload =>
Packet payload -> Packet payload -> Bool
== :: Packet payload -> Packet payload -> Bool
$c== :: forall payload.
Eq payload =>
Packet payload -> Packet payload -> Bool
Eq, ReadPrec [Packet payload]
ReadPrec (Packet payload)
Int -> ReadS (Packet payload)
ReadS [Packet payload]
(Int -> ReadS (Packet payload))
-> ReadS [Packet payload]
-> ReadPrec (Packet payload)
-> ReadPrec [Packet payload]
-> Read (Packet payload)
forall payload. Read payload => ReadPrec [Packet payload]
forall payload. Read payload => ReadPrec (Packet payload)
forall payload. Read payload => Int -> ReadS (Packet payload)
forall payload. Read payload => ReadS [Packet payload]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Packet payload]
$creadListPrec :: forall payload. Read payload => ReadPrec [Packet payload]
readPrec :: ReadPrec (Packet payload)
$creadPrec :: forall payload. Read payload => ReadPrec (Packet payload)
readList :: ReadS [Packet payload]
$creadList :: forall payload. Read payload => ReadS [Packet payload]
readsPrec :: Int -> ReadS (Packet payload)
$creadsPrec :: forall payload. Read payload => Int -> ReadS (Packet payload)
Read, Int -> Packet payload -> ShowS
[Packet payload] -> ShowS
Packet payload -> String
(Int -> Packet payload -> ShowS)
-> (Packet payload -> String)
-> ([Packet payload] -> ShowS)
-> Show (Packet payload)
forall payload. Show payload => Int -> Packet payload -> ShowS
forall payload. Show payload => [Packet payload] -> ShowS
forall payload. Show payload => Packet payload -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Packet payload] -> ShowS
$cshowList :: forall payload. Show payload => [Packet payload] -> ShowS
show :: Packet payload -> String
$cshow :: forall payload. Show payload => Packet payload -> String
showsPrec :: Int -> Packet payload -> ShowS
$cshowsPrec :: forall payload. Show payload => Int -> Packet payload -> ShowS
Show, (forall x. Packet payload -> Rep (Packet payload) x)
-> (forall x. Rep (Packet payload) x -> Packet payload)
-> Generic (Packet payload)
forall x. Rep (Packet payload) x -> Packet payload
forall x. Packet payload -> Rep (Packet payload) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall payload x. Rep (Packet payload) x -> Packet payload
forall payload x. Packet payload -> Rep (Packet payload) x
$cto :: forall payload x. Rep (Packet payload) x -> Packet payload
$cfrom :: forall payload x. Packet payload -> Rep (Packet payload) x
Generic, Typeable)

instance Binary payload => Binary (Packet payload)
instance MessagePack payload => MessagePack (Packet payload)

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


instance Arbitrary payload => Arbitrary (Packet payload) where
  arbitrary :: Gen (Packet payload)
arbitrary =
    PacketKind -> payload -> Packet payload
forall payload. PacketKind -> payload -> Packet payload
Packet (PacketKind -> payload -> Packet payload)
-> Gen PacketKind -> Gen (payload -> Packet payload)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen PacketKind
forall a. Arbitrary a => Gen a
arbitrary Gen (payload -> Packet payload)
-> Gen payload -> Gen (Packet payload)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen payload
forall a. Arbitrary a => Gen a
arbitrary
\end{code}

These top level packets can be transported in a number of ways, the most common
way being over the network using UDP or TCP.  The protocol itself does not
prescribe transport methods, and an implementation is free to implement
additional transports such as WebRTC, IRC, or pipes.

In the remainder of the document, different kinds of Protocol Packet are
specified with their packet kind and payload.  The packet kind is not repeated
in the payload description (TODO: actually it mostly is, but later it won't).

Inside Protocol Packets payload, other packet types can specify additional
packet kinds.  E.g. inside a Crypto Data packet (\texttt{0x1b}), the
\href{#messenger}{Messenger} module defines its protocols for messaging, file
transfers, etc.  Top level Protocol Packets are themselves not encrypted,
though their payload may be.