packages feed

netw-0.1.0.0: test/send-and-recv-msgs/Main.hs

{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE ViewPatterns #-}
module Main where
import Netw.Socket
import Netw.SockAddr 

import Control.Monad

import Data.Function
import Data.Primitive
import Data.Bits
import Data.Word

import System.Posix
import System.Exit


messages :: [ByteArray]
messages = map mkByteArray [45, 742, 33, 554, 123, 74]
  where mkByteArray len = byteArrayFromListN @Word8 len (take len (cycle [0..]))
--messages =
--  [[0x03, 0xf1, 0x44, 0x11]
--  ,[0x5f, 0xc1, 0x02, 0xab]
--  ,[0x1c, 0xa2, 0xbf, 0x7d]
--  ,[0x33, 0x7d, 0x30, 0x0a]]

serverPath :: FilePath
serverPath = "/run/user/1000/unix-sock"

server :: IO ()
server = do
  servSock <- socket PF_UNIX SOCK_STREAM DefaultProtocol
  bind servSock (SockAddrUn serverPath)
  listen servSock 1
  clieSock <- accept_ servSock
  
  bufs <- mapM (\ (sizeofByteArray -> n) -> (, 0, n) <$> newByteArray n) messages
  fix (\ recvmore buffers nbytes ->
    let incrementBuffer 0 b      = b
        incrementBuffer n (b:bs) =
          let (mba, offs, size) = b
          in  if size > n
              then
                (mba, offs + n, size - n):bs
              else
                incrementBuffer (n - size) bs
        incrementBuffer n []
          | n == 0    = []
          | otherwise = error "Impossible"
    in  when (nbytes > 0) $
      do
      (brecv, _, _) <- recvmsg_ clieSock buffers 0 zeroBits
      recvmore (incrementBuffer brecv buffers) (nbytes - brecv)) bufs (sum (sizeofByteArray <$> messages))
  receivedMessage <- mapM (\ (b, _, _) -> unsafeFreezeByteArray b) bufs
  
  print (if receivedMessage == messages then "Success" else "Failure")

  closeSocket clieSock
  closeSocket servSock
  removeLink serverPath

client :: IO ()
client = do
  servSock <- socket PF_UNIX SOCK_STREAM DefaultProtocol
  connect servSock (SockAddrUn serverPath)
  fix (\ sendmore buffers nbytes ->
    let incrementBuffer 0 b      = b
        incrementBuffer n (b:bs) =
          let (mba, offs, size) = b
          in  if size > n
              then
                (mba, offs + n, size - n):bs
              else
                incrementBuffer (n - size) bs
        incrementBuffer n []
          | n == 0    = []
          | otherwise = error "Impossible"
    in  when (nbytes > 0) $
      do
        bsent <- sendmsg servSock SockAddrNull buffers [] zeroBits
        sendmore (incrementBuffer bsent buffers) (nbytes - bsent)) (map (\ b -> (b, 0, sizeofByteArray b)) messages) (sum (map sizeofByteArray messages))
  closeSocket servSock

main :: IO ()
main = do
  s <- forkProcess server
  c <- forkProcess client
  serverExit <- maybe (fail "Server failure") return =<< getProcessStatus True True s
  clientExit <- maybe (fail "Client failure") return =<< getProcessStatus True True c

  case (serverExit, clientExit) of
    (Exited ExitSuccess, Exited ExitSuccess) -> exitSuccess
    _otherwise -> exitFailure