-- | Transport abstraction for libp2p.
--
-- Defines the record-of-functions pattern for transport-agnostic
-- connection management. Stream transports produce a byte stream for the
-- standard security/muxer upgrade; native multiplexed transports such as QUIC
-- provide an already authenticated stream multiplexer.
module LibP2P.Transport
  ( ConnectionEndpoint (..)
  , NativeMuxer (..)
  , RawConnection (..)
  , Listener (..)
  , Transport (..)
  ) where

import LibP2P.Crypto.PeerId (PeerId)
import LibP2P.Multiaddr (Multiaddr)
import LibP2P.MultistreamSelect.Negotiation (ProtocolId, StreamIO)

-- | A transport-native authenticated stream multiplexer.
data NativeMuxer = NativeMuxer
  { NativeMuxer -> PeerId
nativePeerId :: !PeerId
  , NativeMuxer -> ProtocolId
nativeSecurity :: !ProtocolId
  , NativeMuxer -> ProtocolId
nativeMuxerProtocol :: !ProtocolId
  , NativeMuxer -> IO StreamIO
nativeOpenStream :: !(IO StreamIO)
  , NativeMuxer -> IO StreamIO
nativeAcceptStream :: !(IO StreamIO)
  , NativeMuxer -> IO ()
nativeClose :: !(IO ())
  }

-- | The I/O endpoint established by a transport.
data ConnectionEndpoint
  = ByteStreamEndpoint !StreamIO
  | NativeMuxerEndpoint !NativeMuxer

-- | A connection established by a transport.
--
-- TCP and relayed connections carry an unencrypted byte stream. QUIC carries
-- a TLS-authenticated native multiplexer and therefore bypasses Noise/Yamux.
data RawConnection = RawConnection
  { RawConnection -> ConnectionEndpoint
rcEndpoint :: !ConnectionEndpoint
  , RawConnection -> Multiaddr
rcLocalAddr :: !Multiaddr
  , RawConnection -> Multiaddr
rcRemoteAddr :: !Multiaddr
  , RawConnection -> IO ()
rcClose :: !(IO ())
  }

-- | A listener that accepts inbound connections.
data Listener = Listener
  { Listener -> IO RawConnection
listenerAccept :: !(IO RawConnection)
  , Listener -> IO ()
listenerClose :: !(IO ())
  , Listener -> Multiaddr
listenerAddr :: !Multiaddr
  }

-- | Transport provides dial/listen capabilities for a specific protocol.
data Transport = Transport
  { Transport -> Multiaddr -> IO RawConnection
transportDial :: !(Multiaddr -> IO RawConnection)
  , Transport -> Maybe Multiaddr -> Multiaddr -> IO RawConnection
transportDialFrom :: !(Maybe Multiaddr -> Multiaddr -> IO RawConnection)
  , Transport -> Multiaddr -> IO Listener
transportListen :: !(Multiaddr -> IO Listener)
  , Transport -> Multiaddr -> Bool
transportCanDial :: !(Multiaddr -> Bool)
  }