\section{Packet Kind}
The following is an exhaustive list of top level packet kind names and their
number. Their payload is specified in dedicated sections. Each section is
named after the Packet Kind it describes followed by the byte value in
parentheses, e.g. \href{#ping-request-0x00}{Ping Request (0x00)}.
\begin{tabular}{l|l}
Byte value & Packet Kind \\
\hline
\texttt{0x00} & Ping Request \\
\texttt{0x01} & Ping Response \\
\texttt{0x02} & Nodes Request \\
\texttt{0x04} & Nodes Response \\
\texttt{0x18} & Cookie Request \\
\texttt{0x19} & Cookie Response \\
\texttt{0x1a} & Crypto Handshake \\
\texttt{0x1b} & Crypto Data \\
\texttt{0x20} & DHT Request \\
\texttt{0x21} & LAN Discovery \\
\texttt{0x80} & Onion Request 0 \\
\texttt{0x81} & Onion Request 1 \\
\texttt{0x82} & Onion Request 2 \\
\texttt{0x83} & Announce Request \\
\texttt{0x84} & Announce Response \\
\texttt{0x85} & Onion Data Request \\
\texttt{0x86} & Onion Data Response \\
\texttt{0x8c} & Onion Response 3 \\
\texttt{0x8d} & Onion Response 2 \\
\texttt{0x8e} & Onion Response 1 \\
\texttt{0xf0} & Bootstrap Info \\
\end{tabular}
\begin{code}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE Safe #-}
module Network.Tox.Protocol.PacketKind where
import Control.Arrow ((&&&))
import Data.Binary (Binary, get, put)
import Data.MessagePack (MessagePack)
import Data.Typeable (Typeable)
import Data.Word (Word8)
import GHC.Generics (Generic)
import Test.QuickCheck.Arbitrary (Arbitrary, arbitrary,
arbitraryBoundedEnum)
data PacketKind
= PingRequest
| PingResponse
| NodesRequest
| NodesResponse
| CookieRequest
| CookieResponse
| CryptoHandshake
| CryptoData
| Crypto
| LanDiscovery
| OnionRequest0
| OnionRequest1
| OnionRequest2
| AnnounceRequest
| AnnounceResponse
| OnionDataRequest
| OnionDataResponse
| OnionResponse3
| OnionResponse2
| OnionResponse1
| BootstrapInfo
deriving (Eq, Read, Show, Bounded, Enum, Generic, Typeable)
instance MessagePack PacketKind
kindDescription :: PacketKind -> String
kindDescription = \case
PingRequest -> "Ping request"
PingResponse -> "Ping response"
NodesRequest -> "Nodes request"
NodesResponse -> "Nodes response"
CookieRequest -> "Cookie request"
CookieResponse -> "Cookie response"
CryptoHandshake -> "Crypto handshake"
CryptoData -> "Crypto data"
Crypto -> "Encrypted data"
LanDiscovery -> "LAN discovery"
OnionRequest0 -> "Initial onion request"
OnionRequest1 -> "First level wrapped onion request"
OnionRequest2 -> "Second level wrapped onion request"
AnnounceRequest -> "Announce request"
AnnounceResponse -> "Announce response"
OnionDataRequest -> "Onion data request"
OnionDataResponse -> "Onion data response"
OnionResponse3 -> "Third level wrapped onion response"
OnionResponse2 -> "Second level wrapped onion response"
OnionResponse1 -> "First level wrapped onion response"
BootstrapInfo -> "Bootstrap node info request and response"
kindToByte :: PacketKind -> Word8
kindToByte = \case
PingRequest -> 0x00
PingResponse -> 0x01
NodesRequest -> 0x02
NodesResponse -> 0x04
CookieRequest -> 0x18
CookieResponse -> 0x19
CryptoHandshake -> 0x1a
CryptoData -> 0x1b
Crypto -> 0x20
LanDiscovery -> 0x21
OnionRequest0 -> 0x80
OnionRequest1 -> 0x81
OnionRequest2 -> 0x82
AnnounceRequest -> 0x83
AnnounceResponse -> 0x84
OnionDataRequest -> 0x85
OnionDataResponse -> 0x86
OnionResponse3 -> 0x8c
OnionResponse2 -> 0x8d
OnionResponse1 -> 0x8e
BootstrapInfo -> 0xf0
byteToKind :: Word8 -> Maybe PacketKind
byteToKind =
flip lookup mapping
where
mapping = map (kindToByte &&& id) [minBound..maxBound]
instance Binary PacketKind where
put = put . kindToByte
get = do
byte <- get
case byteToKind byte of
Nothing -> fail $ "no binary mapping for packet kind " ++ show byte
Just kind -> return kind
instance Arbitrary PacketKind where
arbitrary = arbitraryBoundedEnum
\end{code}