packages feed

mptcpanalyzer-0.0.2.0: src/MptcpAnalyzer/Commands/ListMptcp.hs

{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE PackageImports #-}
module MptcpAnalyzer.Commands.ListMptcp (
  piListMpTcpOpts
  , cmdListMptcpConnections
  , cmdListSubflows
)
where

import MptcpAnalyzer.Cache
import MptcpAnalyzer.Commands.Definitions as CMD
import MptcpAnalyzer.Commands.List as CMD
import MptcpAnalyzer.Pcap
import MptcpAnalyzer.Stream
import MptcpAnalyzer.Types
import Net.Mptcp

-- import Net.Mptcp.Types (MptcpConnection(..), MptcpSubflow, showMptcpConnection)

import qualified Control.Foldl as L
import Control.Lens hiding (argument)
import Data.Either (fromRight)
import Data.Maybe (catMaybes, fromJust)
import qualified Data.Set as Set
import Data.Word (Word16, Word32, Word64, Word8)
import Frames
import "mptcp-pm" Net.Tcp.Constants (TcpFlag(..))
import Options.Applicative
import qualified Pipes.Prelude as PP
import Polysemy (Embed, Member, Members, Sem)
import qualified Polysemy as P
import Polysemy.State as P
import Polysemy.Trace as P

import Polysemy.Log (Log)
import qualified Polysemy.Log as Log

piListMpTcpOpts :: ParserInfo CommandArgs
piListMpTcpOpts = info (
    parserList <**> helper)
  ( progDesc "List MPTCP connections"
  )
  where
    parserList = ArgsListMpTcpConnections <$> switch ( long "detailed" <> help "detail connections")

piListMptcpSubflowOpts :: ParserInfo CommandArgs
piListMptcpSubflowOpts = info (
    parserList <**> helper)
  ( progDesc "List MPTCP connections"
  )
  where
    parserList = ArgsListSubflows <$> switch ( long "detailed" <> help "detail connections")


-- piListMptcpReinjectionsOpts :: ParserInfo CommandArgs
-- piListMptcpReinjectionsOpts = info (
--     parserList <**> helper)
--   ( progDesc "List MPTCP reinjections"
--   )
--   where
--     parserList = ArgsListSubflows <$> switch ( long "detailed" <> help "detail connections")

type SomeFrame = Frame Packet

-- TODO return mpconStreamId instead
getMpTcpStreams :: SomeFrame -> [StreamIdMptcp]
getMpTcpStreams ps =
    catMaybes $
    L.fold L.nub (view mptcpStream <$> ps)

filterMptcpConnection :: SomeFrame -> StreamId Mptcp -> SomeFrame
filterMptcpConnection frame streamId =
  streamPackets
  where
    streamPackets = filterFrame  (\x -> x ^. mptcpStream == Just streamId) frame




-- buildMptcpConnectionFromRow :: Packet -> TcpConnection
-- buildMptcpConnectionFromRow r =
  -- MptcpConnection {
    -- srcIp = r ^. ipSource
    -- , dstIp = r ^. ipDest
    -- , srcPort = r ^. tcpSrcPort
    -- , dstPort = r ^. tcpDestPort
    -- , priority = Nothing  -- for now
    -- , localId = 0
    -- , remoteId = 0
    -- , subflowInterface = Nothing
  -- }



cmdListSubflows :: (Members '[Log, P.State MyState, P.Trace, Cache, Embed IO] r)
  => Bool -- ^ Detailed
  -> Sem r RetCode
cmdListSubflows detailed = do
  P.trace "not implemented yet"
  return CMD.Continue

{-
-}
cmdListMptcpConnections ::
  (Members [Log, P.Trace, P.State MyState, Cache, P.Embed IO] r)
  => Bool -- ^ Detailed
  -> Sem r RetCode
cmdListMptcpConnections _detailed = do
    -- TODO this part should be extracted so that
    state <- P.get
    let loadedPcap = view loadedFile state
    case loadedPcap of
      Nothing -> do
        P.trace "please load a pcap first"
        return CMD.Continue
      Just frame -> do
        -- log $ "Number of rows " ++ show (frameLength frame)
        P.trace $ "Number of MPTCP connections " ++ show (length mptcpStreams)
        P.trace $ show mptcpStreams
        P.trace $ concatMap showEitherCon mptcpConnections
        -- >>
        return CMD.Continue
        where
          mptcpConnections :: [Either String MptcpConnection]
          mptcpConnections = map (fmap ffCon . buildMptcpConnectionFromStreamId frame ) mptcpStreams

          showEitherCon :: Either String MptcpConnection -> String
          showEitherCon (Left msg) = msg ++ "\n"
          showEitherCon (Right mptcpCon) = showConnection mptcpCon ++ "\n"

          mptcpStreams = getMpTcpStreams frame