bustle-0.8.0: Bustle/Reader.hs
{-
Bustle.Reader: Haskell binding for pcap-reader.c
Copyright © 2020 Will Thompson
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-}
{-# LANGUAGE ForeignFunctionInterface #-}
module Bustle.Reader
(
-- * Types
Reader
-- * Methods
, readerOpen
, readerReadOne
, readerClose
, withReader
)
where
import Control.Exception (bracket)
import Foreign.C
import Foreign.ForeignPtr
import Foreign.Marshal.Alloc
import Foreign.Ptr
import Foreign.Storable
import System.Glib.GObject
import System.Glib.GError
import Bustle.GDBusMessage
import Bustle.Types (Microseconds)
-- Gtk2HS boilerplate
newtype Reader = Reader { unReader :: ForeignPtr Reader }
deriving (Eq, Ord)
mkReader :: (ForeignPtr Reader -> Reader, FinalizerPtr a)
mkReader = (Reader, objectUnref)
instance GObjectClass Reader where
toGObject = GObject . castForeignPtr . unReader
unsafeCastGObject = Reader . castForeignPtr . unGObject
-- Foreign imports
foreign import ccall "bustle_pcap_reader_open"
bustle_pcap_reader_open :: CString
-> Ptr (Ptr ())
-> IO (Ptr Reader)
-- Foreign imports
foreign import ccall "bustle_pcap_reader_read_one"
bustle_pcap_reader_read_one :: Ptr Reader
-> Ptr CLong
-> Ptr CLong
-> Ptr (Ptr CChar)
-> Ptr CUInt
-> Ptr (Ptr GDBusMessage)
-> Ptr (Ptr ())
-> IO CInt
foreign import ccall "bustle_pcap_reader_close"
bustle_pcap_reader_close :: Ptr Reader
-> IO ()
-- Throws a GError if the file can't be opened
readerOpen :: FilePath
-> IO Reader
readerOpen filename =
wrapNewGObject mkReader $
propagateGError $ \gerrorPtr ->
withCString filename $ \c_filename ->
bustle_pcap_reader_open c_filename gerrorPtr
readerReadOne :: Reader
-> IO (Maybe (Microseconds, Int, GDBusMessage))
readerReadOne reader =
withForeignPtr (unReader reader) $ \c_reader ->
alloca $ \secPtr ->
alloca $ \usecPtr ->
alloca $ \blobPtrPtr ->
alloca $ \lengthPtr ->
alloca $ \messagePtr -> do
poke messagePtr nullPtr
propagateGError $ bustle_pcap_reader_read_one c_reader secPtr usecPtr blobPtrPtr lengthPtr messagePtr
blob <- peek blobPtrPtr
if blob == nullPtr
then return Nothing
else do
sec <- peek secPtr
usec <- peek usecPtr
blobLength <- peek lengthPtr
let µsec = fromIntegral sec * (10 ^ (6 :: Int)) + fromIntegral usec
message <- wrapNewGDBusMessage $ peek messagePtr
return $ Just (µsec, fromIntegral blobLength, message)
readerClose :: Reader
-> IO ()
readerClose reader =
withForeignPtr (unReader reader) bustle_pcap_reader_close
withReader :: FilePath
-> (Reader -> IO a)
-> IO a
withReader filename f = do
bracket (readerOpen filename) readerClose f