-- | Protocol definitions for multiaddr.
--
-- Each protocol has a numeric code and an address format.
-- See: https://github.com/multiformats/multicodec/blob/master/table.csv
module Network.LibP2P.Multiaddr.Protocol
  ( Protocol (..)
  , protocolCode
  , protocolName
  , AddressSize (..)
  , protocolAddressSize
  , codeToProtocolName
  ) where

import Data.ByteString (ByteString)
import Data.Text (Text)
import Data.Word (Word16, Word32, Word64)

-- | A single protocol component within a multiaddr.
data Protocol
  = IP4 !Word32        -- ^ IPv4 address (4 bytes big-endian)
  | IP6 !ByteString    -- ^ IPv6 address (16 bytes)
  | TCP !Word16        -- ^ TCP port
  | UDP !Word16        -- ^ UDP port
  | P2P !ByteString    -- ^ Peer ID as multihash bytes
  | QuicV1             -- ^ QUIC v1 (no address)
  | WS                 -- ^ WebSocket (no address)
  | WSS                -- ^ WebSocket Secure (no address)
  | DNS !Text          -- ^ DNS hostname
  | DNS4 !Text         -- ^ DNS4 hostname
  | DNS6 !Text         -- ^ DNS6 hostname
  | DNSAddr !Text      -- ^ DNSAddr hostname
  | P2PCircuit         -- ^ Circuit relay marker (no address)
  | WebTransport       -- ^ WebTransport (no address)
  | NoiseProto         -- ^ Noise protocol marker (no address)
  | YamuxProto         -- ^ Yamux protocol marker (no address)
  deriving (Int -> Protocol -> ShowS
[Protocol] -> ShowS
Protocol -> String
(Int -> Protocol -> ShowS)
-> (Protocol -> String) -> ([Protocol] -> ShowS) -> Show Protocol
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Protocol -> ShowS
showsPrec :: Int -> Protocol -> ShowS
$cshow :: Protocol -> String
show :: Protocol -> String
$cshowList :: [Protocol] -> ShowS
showList :: [Protocol] -> ShowS
Show, Protocol -> Protocol -> Bool
(Protocol -> Protocol -> Bool)
-> (Protocol -> Protocol -> Bool) -> Eq Protocol
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Protocol -> Protocol -> Bool
== :: Protocol -> Protocol -> Bool
$c/= :: Protocol -> Protocol -> Bool
/= :: Protocol -> Protocol -> Bool
Eq)

-- | Address size specification for a protocol.
data AddressSize
  = Fixed !Int       -- ^ Fixed number of bytes
  | VarIntPrefixed   -- ^ Varint-length-prefixed bytes
  | NoAddress        -- ^ No address bytes
  deriving (Int -> AddressSize -> ShowS
[AddressSize] -> ShowS
AddressSize -> String
(Int -> AddressSize -> ShowS)
-> (AddressSize -> String)
-> ([AddressSize] -> ShowS)
-> Show AddressSize
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AddressSize -> ShowS
showsPrec :: Int -> AddressSize -> ShowS
$cshow :: AddressSize -> String
show :: AddressSize -> String
$cshowList :: [AddressSize] -> ShowS
showList :: [AddressSize] -> ShowS
Show, AddressSize -> AddressSize -> Bool
(AddressSize -> AddressSize -> Bool)
-> (AddressSize -> AddressSize -> Bool) -> Eq AddressSize
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AddressSize -> AddressSize -> Bool
== :: AddressSize -> AddressSize -> Bool
$c/= :: AddressSize -> AddressSize -> Bool
/= :: AddressSize -> AddressSize -> Bool
Eq)

-- | Get the multicodec code for a protocol.
protocolCode :: Protocol -> Word64
protocolCode :: Protocol -> Word64
protocolCode (IP4 Word32
_) = Word64
4
protocolCode (IP6 ByteString
_) = Word64
41
protocolCode (TCP Word16
_) = Word64
6
protocolCode (UDP Word16
_) = Word64
273
protocolCode (P2P ByteString
_) = Word64
421
protocolCode Protocol
QuicV1 = Word64
460
protocolCode Protocol
WS = Word64
477
protocolCode Protocol
WSS = Word64
478
protocolCode (DNS Text
_) = Word64
53
protocolCode (DNS4 Text
_) = Word64
54
protocolCode (DNS6 Text
_) = Word64
55
protocolCode (DNSAddr Text
_) = Word64
56
protocolCode Protocol
P2PCircuit = Word64
290
protocolCode Protocol
WebTransport = Word64
465
protocolCode Protocol
NoiseProto = Word64
454
protocolCode Protocol
YamuxProto = Word64
467

-- | Get the human-readable name for a protocol.
protocolName :: Protocol -> Text
protocolName :: Protocol -> Text
protocolName (IP4 Word32
_) = Text
"ip4"
protocolName (IP6 ByteString
_) = Text
"ip6"
protocolName (TCP Word16
_) = Text
"tcp"
protocolName (UDP Word16
_) = Text
"udp"
protocolName (P2P ByteString
_) = Text
"p2p"
protocolName Protocol
QuicV1 = Text
"quic-v1"
protocolName Protocol
WS = Text
"ws"
protocolName Protocol
WSS = Text
"wss"
protocolName (DNS Text
_) = Text
"dns"
protocolName (DNS4 Text
_) = Text
"dns4"
protocolName (DNS6 Text
_) = Text
"dns6"
protocolName (DNSAddr Text
_) = Text
"dnsaddr"
protocolName Protocol
P2PCircuit = Text
"p2p-circuit"
protocolName Protocol
WebTransport = Text
"webtransport"
protocolName Protocol
NoiseProto = Text
"noise"
protocolName Protocol
YamuxProto = Text
"yamux"

-- | Get the address size specification for a protocol code.
protocolAddressSize :: Word64 -> Maybe AddressSize
protocolAddressSize :: Word64 -> Maybe AddressSize
protocolAddressSize Word64
4 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just (Int -> AddressSize
Fixed Int
4)        -- ip4
protocolAddressSize Word64
41 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just (Int -> AddressSize
Fixed Int
16)      -- ip6
protocolAddressSize Word64
6 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just (Int -> AddressSize
Fixed Int
2)        -- tcp
protocolAddressSize Word64
273 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just (Int -> AddressSize
Fixed Int
2)      -- udp
protocolAddressSize Word64
421 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just AddressSize
VarIntPrefixed -- p2p
protocolAddressSize Word64
460 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just AddressSize
NoAddress      -- quic-v1
protocolAddressSize Word64
477 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just AddressSize
NoAddress      -- ws
protocolAddressSize Word64
478 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just AddressSize
NoAddress      -- wss
protocolAddressSize Word64
53 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just AddressSize
VarIntPrefixed  -- dns
protocolAddressSize Word64
54 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just AddressSize
VarIntPrefixed  -- dns4
protocolAddressSize Word64
55 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just AddressSize
VarIntPrefixed  -- dns6
protocolAddressSize Word64
56 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just AddressSize
VarIntPrefixed  -- dnsaddr
protocolAddressSize Word64
290 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just AddressSize
NoAddress      -- p2p-circuit
protocolAddressSize Word64
465 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just AddressSize
NoAddress      -- webtransport
protocolAddressSize Word64
454 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just AddressSize
NoAddress      -- noise
protocolAddressSize Word64
467 = AddressSize -> Maybe AddressSize
forall a. a -> Maybe a
Just AddressSize
NoAddress      -- yamux
protocolAddressSize Word64
_ = Maybe AddressSize
forall a. Maybe a
Nothing

-- | Map protocol code to name (for text parsing).
codeToProtocolName :: Word64 -> Maybe Text
codeToProtocolName :: Word64 -> Maybe Text
codeToProtocolName Word64
4 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"ip4"
codeToProtocolName Word64
41 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"ip6"
codeToProtocolName Word64
6 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"tcp"
codeToProtocolName Word64
273 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"udp"
codeToProtocolName Word64
421 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"p2p"
codeToProtocolName Word64
460 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"quic-v1"
codeToProtocolName Word64
477 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"ws"
codeToProtocolName Word64
478 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"wss"
codeToProtocolName Word64
53 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"dns"
codeToProtocolName Word64
54 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"dns4"
codeToProtocolName Word64
55 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"dns6"
codeToProtocolName Word64
56 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"dnsaddr"
codeToProtocolName Word64
290 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"p2p-circuit"
codeToProtocolName Word64
465 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"webtransport"
codeToProtocolName Word64
454 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"noise"
codeToProtocolName Word64
467 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"yamux"
codeToProtocolName Word64
_ = Maybe Text
forall a. Maybe a
Nothing