mptcpanalyzer-0.0.2.0: src/Tshark/Sharkd.hs
{-# LANGUAGE OverloadedStrings #-}
--
--
-- Format of request listed at <https://gitlab.com/wireshark/wireshark/-/wikis/sharkd-Request-Syntax#tap>
module Tshark.Sharkd (
defaultSocketPath
, launchSharkd
, connectToSharkd
, loadFile
)
where
import Network.Socket
import Network.Socket.ByteString
import Data.Aeson
import Data.Aeson.Encode.Pretty
import Data.Aeson.Extra.Merge (lodashMerge)
import System.Process hiding (runCommand)
import qualified Control.Exception as E
import Data.ByteString.Lazy (toStrict)
import GHC.IO.Handle
import Control.Concurrent
import qualified Data.ByteString as S
import Foreign (Ptr)
import Foreign.C (CChar)
import Data.Aeson.Encoding (encodingToLazyByteString)
defaultSocketPath :: FilePath
defaultSocketPath = "/tmp/sharkd.sock"
basicPayload :: String -> Series
basicPayload method =
"method" .= toJSON method
<> "jsonrpc" .= toJSON ("2.0" :: String)
<> "id" .= toJSON (1 ::Int)
-- , "params" .= object [
-- "file" .= pcapPath
-- ]
basicPayloadStr :: String -> String
basicPayloadStr inside = "{'jsonrpc': '2.0', 'id': 1, 'method':'info'}"
-- | Launches the wireshark daemon
launchSharkd :: FilePath -- ^ Unix socket path
-> IO ()
launchSharkd socketPath = let
createProc :: CreateProcess
createProc = (proc "sharkd" [ socketPath ]) {
delegate_ctlc = True
}
in do
putStrLn $ "Launching " ++ show createProc
(_, _, mbHerr, ph) <- createProcess createProc
pure ()
-- waitForProcess ph
-- |
-- serializingConfig :: Config
-- serializingConfig = defConfig { confCompare = compare }
connectToSharkd :: FilePath -> IO ()
connectToSharkd = undefined
-- TODO should return a Either String Value instead ?
sendRequestToSharkd :: FilePath -> Encoding -> IO (Either String Value)
sendRequestToSharkd sockPath payload = do
E.bracketOnError (socket AF_UNIX Stream defaultProtocol) close $ \sock -> do
-- setSocketOption sock ReuseAddr 1
-- withFdSocket sock setCloseOnExecIfNeeded
-- sock <- socket AF_UNIX Stream defaultProtocol
putStrLn $ "connecting to socket " ++ show sockPath
connect sock (SockAddrUnix sockPath)
putStrLn "connected"
-- m <- newEmptyMVar
-- forkIO $ (listenForResponse h m)
putStrLn $ "sending payload " ++ show payload
let bsPayload = (toStrict $ encodingToLazyByteString payload ) <> "\n"
putStrLn $ "sending payload " ++ show bsPayload
sendAll sock bsPayload
putStrLn "sent"
bs <- recv sock 1024
putStrLn "recv"
print bs
return $ eitherDecodeStrict bs
where
-- socket AF_UNIX Stream defaultProtocol
addr = defaultHints { addrFamily = AF_UNIX, addrAddress = SockAddrUnix sockPath }
-- |
-- {"req":"load","file":"c:/traces/Contoso_01/web01/web01_00001_20161012151754.pcapng"}
loadFile :: FilePath -> FilePath -> IO ()
loadFile pcapPath sockPath =
sendRequestToSharkd sockPath (pairs payload) >> return ()
where
payload = basicPayload "load" <> paramsPayload
paramsPayload =
"params" .= object [
"file" .= pcapPath
]
-- this works
getInfo :: FilePath -> IO ()
getInfo sockPath = sendRequestToSharkd sockPath (pairs payload) >> return ()
where
payload = basicPayload "info"
-- {"req":"status"}
-- getStatus :: Socket -> IO ()
-- getStatus sock = sendRequestToSharkd defaultSocketPath payload >> return ()
-- where
-- payload = object [
-- "req" .= toJSON ("status" :: String)
-- ]
-- {"req":"frames","filter":"frame.number<=20"}
-- getFrames
-- getFrames