packages feed

bindings-sipc-1.0: src/Examples/MQSender.hs

-- A program to test sending messages to a message queue.
-- 
-- Based on sipc code from: examples/mq_sender.c
--
module Main where

import Bindings.SELinux.SIPC
import Control.Monad (when)
import Foreign
import Foreign.C
import Foreign.Ptr
import Foreign.Storable
import System.IO

-- Key which sender and receiver have agreed upon 
sipcKey = "sipc_mq_test"

-- # of bytes we allocate for the IPC's internal buffer.
-- This should be >= the amount of data copied into the IPC 
ipcLen = 8192

-- # of bytes to read from data file at a time
readLen = 4096

-- Amount of data to allocate inside the IPC handle
dataLen = 8192

-- End of message marker which sender and receiver have agreed upon
dataEnd = "0xDEADBEEF"  

-- Data file
inFile = "data.txt"

main :: IO ()
main = do
  sipc <- sipcOpen "sipc_mq_test" SipcSender SipcSysvMqueues ipcLen 
  if sipc == nullPtr
     then do
        hPutStrLn stderr "Error: Unable to create message queue"
        sipcClose sipc
     else do
        dataP <- sipcGetDataPtr sipc
        if dataP == nullPtr
           then do
              hPutStrLn stderr "Error: Unable to get data pointer"
              sipcClose sipc
           else do 
              sendFileData sipc dataP
              sendEndXmit sipc dataP
              sipcClose sipc

-- |Read and enqueue file data
sendFileData :: SipcPtr -> Ptr CChar -> IO ()
sendFileData sipc dataP = do
  f <- openFile inFile ReadMode
  fData <- hGetContents f
  sendFileChunks sipc dataP fData
  hClose f

-- |Send all chunks of a file to the queue
sendFileChunks sipc dataP chunkList = do
  let (c, cs) = splitAt readLen chunkList
  clearBuffer dataP
  sendMessage sipc dataP c
  when (not $ null cs) $ sendFileChunks sipc dataP cs

-- |Send data to the message queue
sendMessage :: SipcPtr -> Ptr CChar -> String -> IO ()
sendMessage sipc dataP msg = do
    tmpP <- newArray $ map castCharToCChar msg
    _ <- copyBytes dataP tmpP $ length msg
    free tmpP
    result <- sipcSendData sipc ipcLen
    when (result < 0) $ putStrLn $ "Unable to send IPC message"

-- |Send end of transmission marker
sendEndXmit sipc dataP = do
    tmpP <- newCAString dataEnd
    _ <- copyBytes dataP tmpP $ 1 + length dataEnd
    free tmpP
    result <- sipcSendData sipc ipcLen
    when (result < 0) $ putStrLn $ "Unable to send IPC message"

-- FUTURE: just replace this with memcpy?
-- A quick-and-dirty bzero
clearBuffer dataP = do
    let buffer = take (fromIntegral ipcLen) $ repeat '\0'
    tmpP <- newArray $ map castCharToCChar buffer
    _ <- copyBytes dataP tmpP $ length buffer
    free tmpP