-- GENERATED by C->Haskell Compiler, version 0.16.5 Crystal Seed, 24 Jan 2009 (Haskell)
-- Edit the ORIGNAL .chs file instead!


{-# LINE 1 "System/NanoMsg/C/NanoMsg.chs" #-}{-# LANGUAGE CPP, ForeignFunctionInterface #-}
  
-- | This module aims at exposing nanomsg function directly to haskell, no api construct except the use of ForeignFreePointers. Function specific documentation is therefore the official nanomsg documentation. An exception is also done for error handling, here we use maybe or either. Note that it is a c2hs module and that returning type of function may contain function parameter when they may be changed (a tuple with firstly function return type then all parameters in order).
-- Send and receive function are not set unsafe, this is thread unsafe, but waiting for some issue (during tests) to set them safe and use similar work arround as in zmq binding (nowait all the time but use haskell threadWriteRead to wait in a ghc non blocking thread way).
module System.NanoMsg.C.NanoMsg where
import System.NanoMsg.C.NanoMsgStruct
import Foreign
import Foreign.C.Types
import Foreign.C.String
import Control.Monad((<=<),liftM)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as C
import qualified Data.ByteString.Unsafe as U
import qualified Data.List as L
import System.Posix.Types(Fd)
import Control.Concurrent(threadWaitWrite,threadWaitRead)
import qualified Data.ByteString as BS
import Data.List(foldl')
import Control.Monad(foldM,foldM_)
import Data.ByteString.Internal(ByteString(PS))


-- #include "nanomsg/transport.h"
-- #include "nanomsg/protocol.h"

newtype NnSocket = NnSocket CInt deriving (Eq, Show)

socketToCInt :: NnSocket -> CInt
socketToCInt (NnSocket s) = s

newtype NnEndPoint = NnEndPoint CInt deriving (Eq, Show)

endPointToCInt :: NnEndPoint -> CInt
endPointToCInt (NnEndPoint s) = s

data NnError = ENOTSUP
             | ENOMEM
             | EPROTONOSUPPORT
             | ENAMETOOLONG
             | ENODEV
             | ENOBUFS
             | ENETDOWN
             | EADDRINUSE
             | EADDRNOTAVAIL
             | ECONNREFUSED
             | EINPROGRESS
             | ENOTSOCK
             | EAFNOSUPPORT
             | EPROTO
             | EAGAIN
             | EBADF
             | EINVAL
             | EINTR
             | EMFILE
             | EFAULT
             | EACCESS
             | ENETRESET
             | ENETUNREACH
             | EHOSTUNREACH
             | ENOTCONN
             | EMSGSIZE
             | ETIMEDOUT
             | ECONNABORTED
             | ECONNRESET
             | ENOPROTOOPT
             | EISCONN
             | ETERM
             | EFSM
             deriving (Eq,Ord,Show)
instance Enum NnError where
  fromEnum ENOTSUP = 95
  fromEnum ENOMEM = 12
  fromEnum EPROTONOSUPPORT = 93
  fromEnum ENAMETOOLONG = 36
  fromEnum ENODEV = 19
  fromEnum ENOBUFS = 105
  fromEnum ENETDOWN = 100
  fromEnum EADDRINUSE = 98
  fromEnum EADDRNOTAVAIL = 99
  fromEnum ECONNREFUSED = 111
  fromEnum EINPROGRESS = 115
  fromEnum ENOTSOCK = 88
  fromEnum EAFNOSUPPORT = 97
  fromEnum EPROTO = 71
  fromEnum EAGAIN = 11
  fromEnum EBADF = 9
  fromEnum EINVAL = 22
  fromEnum EINTR = 4
  fromEnum EMFILE = 24
  fromEnum EFAULT = 14
  fromEnum EACCESS = 156384729
  fromEnum ENETRESET = 102
  fromEnum ENETUNREACH = 101
  fromEnum EHOSTUNREACH = 113
  fromEnum ENOTCONN = 107
  fromEnum EMSGSIZE = 90
  fromEnum ETIMEDOUT = 110
  fromEnum ECONNABORTED = 103
  fromEnum ECONNRESET = 104
  fromEnum ENOPROTOOPT = 92
  fromEnum EISCONN = 106
  fromEnum ETERM = 156384765
  fromEnum EFSM = 156384766

  toEnum 95 = ENOTSUP
  toEnum 12 = ENOMEM
  toEnum 93 = EPROTONOSUPPORT
  toEnum 36 = ENAMETOOLONG
  toEnum 19 = ENODEV
  toEnum 105 = ENOBUFS
  toEnum 100 = ENETDOWN
  toEnum 98 = EADDRINUSE
  toEnum 99 = EADDRNOTAVAIL
  toEnum 111 = ECONNREFUSED
  toEnum 115 = EINPROGRESS
  toEnum 88 = ENOTSOCK
  toEnum 97 = EAFNOSUPPORT
  toEnum 71 = EPROTO
  toEnum 11 = EAGAIN
  toEnum 9 = EBADF
  toEnum 22 = EINVAL
  toEnum 4 = EINTR
  toEnum 24 = EMFILE
  toEnum 14 = EFAULT
  toEnum 156384729 = EACCESS
  toEnum 102 = ENETRESET
  toEnum 101 = ENETUNREACH
  toEnum 113 = EHOSTUNREACH
  toEnum 107 = ENOTCONN
  toEnum 90 = EMSGSIZE
  toEnum 110 = ETIMEDOUT
  toEnum 103 = ECONNABORTED
  toEnum 104 = ECONNRESET
  toEnum 92 = ENOPROTOOPT
  toEnum 106 = EISCONN
  toEnum 156384765 = ETERM
  toEnum 156384766 = EFSM
  toEnum unmatched = error ("NnError.toEnum: Cannot match " ++ show unmatched)
 -- TODO instance show with nnStrerror (but with code to be able to reverse) 

data AddressFamilies = AF_SP
                     | AF_SP_RAW
                     deriving (Eq,Ord,Show)
instance Enum AddressFamilies where
  fromEnum AF_SP = 1
  fromEnum AF_SP_RAW = 2

  toEnum 1 = AF_SP
  toEnum 2 = AF_SP_RAW
  toEnum unmatched = error ("AddressFamilies.toEnum: Cannot match " ++ show unmatched)

{-# LINE 85 "System/NanoMsg/C/NanoMsg.chs" #-}

data NnTransport = NN_IPC
                 | NN_INPROC
                 | NN_TCP
                 deriving (Eq,Ord,Show)
instance Enum NnTransport where
  fromEnum NN_IPC = (-2)
  fromEnum NN_INPROC = (-1)
  fromEnum NN_TCP = (-3)

  toEnum (-2) = NN_IPC
  toEnum (-1) = NN_INPROC
  toEnum (-3) = NN_TCP
  toEnum unmatched = error ("NnTransport.toEnum: Cannot match " ++ show unmatched)

{-# LINE 90 "System/NanoMsg/C/NanoMsg.chs" #-}
-- TODO link with their protocol
data ProtocolFamilies = NN_PROTO_PUBSUB
                      | NN_PROTO_BUS
                      | NN_PROTO_PAIR
                      | NN_PROTO_PIPELINE
                      | NN_PROTO_REQREP
                      | NN_PROTO_SURVEY
                      deriving (Eq,Ord,Show)
instance Enum ProtocolFamilies where
  fromEnum NN_PROTO_PUBSUB = 2
  fromEnum NN_PROTO_BUS = 7
  fromEnum NN_PROTO_PAIR = 1
  fromEnum NN_PROTO_PIPELINE = 5
  fromEnum NN_PROTO_REQREP = 3
  fromEnum NN_PROTO_SURVEY = 6

  toEnum 2 = NN_PROTO_PUBSUB
  toEnum 7 = NN_PROTO_BUS
  toEnum 1 = NN_PROTO_PAIR
  toEnum 5 = NN_PROTO_PIPELINE
  toEnum 3 = NN_PROTO_REQREP
  toEnum 6 = NN_PROTO_SURVEY
  toEnum unmatched = error ("ProtocolFamilies.toEnum: Cannot match " ++ show unmatched)

{-# LINE 98 "System/NanoMsg/C/NanoMsg.chs" #-}

data NnProtocol = NN_PUB
                | NN_SUB
                | NN_BUS
                | NN_PAIR
                | NN_PUSH
                | NN_PULL
                | NN_REQ
                | NN_REP
                | NN_SURVEYOR
                | NN_RESPONDENT
                deriving (Eq,Ord,Show)
instance Enum NnProtocol where
  fromEnum NN_PUB = 32
  fromEnum NN_SUB = 33
  fromEnum NN_BUS = 112
  fromEnum NN_PAIR = 16
  fromEnum NN_PUSH = 80
  fromEnum NN_PULL = 81
  fromEnum NN_REQ = 48
  fromEnum NN_REP = 49
  fromEnum NN_SURVEYOR = 96
  fromEnum NN_RESPONDENT = 97

  toEnum 32 = NN_PUB
  toEnum 33 = NN_SUB
  toEnum 112 = NN_BUS
  toEnum 16 = NN_PAIR
  toEnum 80 = NN_PUSH
  toEnum 81 = NN_PULL
  toEnum 48 = NN_REQ
  toEnum 49 = NN_REP
  toEnum 96 = NN_SURVEYOR
  toEnum 97 = NN_RESPONDENT
  toEnum unmatched = error ("NnProtocol.toEnum: Cannot match " ++ show unmatched)

{-# LINE 110 "System/NanoMsg/C/NanoMsg.chs" #-}


-- | those constants might be useless, if they are of any use we might consider using c2hs #const instead
data NNConstants = NN_SOCKADDR_MAX
                 deriving (Eq,Ord,Show)
instance Enum NNConstants where
  fromEnum NN_SOCKADDR_MAX = 128

  toEnum 128 = NN_SOCKADDR_MAX
  toEnum unmatched = error ("NNConstants.toEnum: Cannot match " ++ show unmatched)

{-# LINE 116 "System/NanoMsg/C/NanoMsg.chs" #-}

data SolSocket = NN_SOL_SOCKET
               deriving (Eq,Ord,Show)
instance Enum SolSocket where
  fromEnum NN_SOL_SOCKET = 0

  toEnum 0 = NN_SOL_SOCKET
  toEnum unmatched = error ("SolSocket.toEnum: Cannot match " ++ show unmatched)

{-# LINE 120 "System/NanoMsg/C/NanoMsg.chs" #-}


data SocketOptions = NN_LINGER
                   | NN_SNDBUF
                   | NN_RCVBUF
                   | NN_SNDTIMEO
                   | NN_RCVTIMEO
                   | NN_RECONNECT_IVL
                   | NN_RECONNECT_IVL_MAX
                   | NN_SNDPRIO
                   | NN_SNDFD
                   | NN_RCVFD
                   | NN_IPV4ONLY
                   deriving (Eq,Ord,Show)
instance Enum SocketOptions where
  fromEnum NN_LINGER = 1
  fromEnum NN_SNDBUF = 2
  fromEnum NN_RCVBUF = 3
  fromEnum NN_SNDTIMEO = 4
  fromEnum NN_RCVTIMEO = 5
  fromEnum NN_RECONNECT_IVL = 6
  fromEnum NN_RECONNECT_IVL_MAX = 7
  fromEnum NN_SNDPRIO = 8
  fromEnum NN_SNDFD = 10
  fromEnum NN_RCVFD = 11
  fromEnum NN_IPV4ONLY = 14

  toEnum 1 = NN_LINGER
  toEnum 2 = NN_SNDBUF
  toEnum 3 = NN_RCVBUF
  toEnum 4 = NN_SNDTIMEO
  toEnum 5 = NN_RCVTIMEO
  toEnum 6 = NN_RECONNECT_IVL
  toEnum 7 = NN_RECONNECT_IVL_MAX
  toEnum 8 = NN_SNDPRIO
  toEnum 10 = NN_SNDFD
  toEnum 11 = NN_RCVFD
  toEnum 14 = NN_IPV4ONLY
  toEnum unmatched = error ("SocketOptions.toEnum: Cannot match " ++ show unmatched)

{-# LINE 135 "System/NanoMsg/C/NanoMsg.chs" #-}

data SocketReadOptions = NN_DOMAIN
                       | NN_PROTOCOL
                       deriving (Eq,Ord,Show)
instance Enum SocketReadOptions where
  fromEnum NN_DOMAIN = 12
  fromEnum NN_PROTOCOL = 13

  toEnum 12 = NN_DOMAIN
  toEnum 13 = NN_PROTOCOL
  toEnum unmatched = error ("SocketReadOptions.toEnum: Cannot match " ++ show unmatched)

{-# LINE 140 "System/NanoMsg/C/NanoMsg.chs" #-}
 
data PubSubOptions = NN_REQ_RESEND_IVL
                   deriving (Eq,Ord,Show)
instance Enum PubSubOptions where
  fromEnum NN_REQ_RESEND_IVL = 1

  toEnum 1 = NN_REQ_RESEND_IVL
  toEnum unmatched = error ("PubSubOptions.toEnum: Cannot match " ++ show unmatched)

{-# LINE 144 "System/NanoMsg/C/NanoMsg.chs" #-}

data SurveyOptions = NN_SURVEYOR_DEADLINE
                   deriving (Eq,Ord,Show)
instance Enum SurveyOptions where
  fromEnum NN_SURVEYOR_DEADLINE = 1

  toEnum 1 = NN_SURVEYOR_DEADLINE
  toEnum unmatched = error ("SurveyOptions.toEnum: Cannot match " ++ show unmatched)

{-# LINE 148 "System/NanoMsg/C/NanoMsg.chs" #-}


data ReqRepOptions = NN_SUB_SUBSCRIBE
                   | NN_SUB_UNSUBSCRIBE
                   deriving (Eq,Ord,Show)
instance Enum ReqRepOptions where
  fromEnum NN_SUB_SUBSCRIBE = 1
  fromEnum NN_SUB_UNSUBSCRIBE = 2

  toEnum 1 = NN_SUB_SUBSCRIBE
  toEnum 2 = NN_SUB_UNSUBSCRIBE
  toEnum unmatched = error ("ReqRepOptions.toEnum: Cannot match " ++ show unmatched)

{-# LINE 154 "System/NanoMsg/C/NanoMsg.chs" #-}

data TcpOptions = NN_TCP_NODELAY
                deriving (Eq,Ord,Show)
instance Enum TcpOptions where
  fromEnum NN_TCP_NODELAY = 1

  toEnum 1 = NN_TCP_NODELAY
  toEnum unmatched = error ("TcpOptions.toEnum: Cannot match " ++ show unmatched)

{-# LINE 158 "System/NanoMsg/C/NanoMsg.chs" #-}


-- | internal only
class (Enum a, Show a, Eq a) => AllSocketOptions a
instance AllSocketOptions ReqRepOptions
instance AllSocketOptions SurveyOptions
instance AllSocketOptions PubSubOptions
instance AllSocketOptions SocketOptions
instance AllSocketOptions TcpOptions
instance AllSocketOptions SocketReadOptions
-- | internal only
class (Enum a, Show a, Eq a) => AllLevelOptions a
instance AllLevelOptions NnProtocol
instance AllLevelOptions SolSocket
instance AllLevelOptions NnTransport




data SndRcvFlags = NN_DONTWAIT
                 deriving (Eq,Ord,Show)
instance Enum SndRcvFlags where
  fromEnum NN_DONTWAIT = 1

  toEnum 1 = NN_DONTWAIT
  toEnum unmatched = error ("SndRcvFlags.toEnum: Cannot match " ++ show unmatched)

{-# LINE 179 "System/NanoMsg/C/NanoMsg.chs" #-}

flagsToCInt :: Enum a => [a] -> CInt
flagsToCInt b = L.foldl' (\ac en -> ac + cIntFromEnum en ) 0  b

rFlagsToCInt :: Enum a => [a] -> (CInt,Bool)
rFlagsToCInt b = let f = L.foldl' (\ac en -> ac + cIntFromEnum en ) 0  b in
                 if (nN_DONTWAIT .&. f) == 0 then (nN_DONTWAIT `xor` f, True) else (f, False)

sFlagsToCInt :: Enum a => [a] -> (CInt,Bool)
sFlagsToCInt = rFlagsToCInt

cIntToEnum :: Enum a => CInt -> a
cIntToEnum = toEnum . fromIntegral

cIntFromEnum :: Enum a => a -> CInt
cIntFromEnum = fromIntegral . fromEnum

peekInt :: (Storable a, Integral a) => Ptr a -> IO Int
peekInt = (liftM fromIntegral) . peek

-- TODO inline
withPStorable :: (Storable a) => a -> (Ptr a -> IO b)  -> IO b
withPStorable i r = alloca (\p -> poke p i >> r p) 

withPStorable' :: (Storable a) => a -> (Ptr c -> IO b)  -> IO b
withPStorable' i r = alloca (\p -> poke p i >> r (castPtr p)) 

withPIntegral :: (Storable a, Num a, Integral c) => c -> (Ptr a -> IO b)  -> IO b
withPIntegral i = withPStorable (fromIntegral i)

--withPForeign :: ForeignPtr () -> (Ptr () -> IO b)  -> IO b
--withPForeign fp r = withForeignPtr fp (\p -> alloca (\pp -> poke pp p >> r (castPtr pp)))

withPPtr :: Ptr () -> (Ptr () -> IO b)  -> IO b
withPPtr p r = alloca (\pp -> poke pp p >> r (castPtr pp))


foreignFree :: Ptr a -> IO(ForeignPtr a)
foreignFree = newForeignPtr finalizerFree

foreignVoid :: Ptr () -> IO(ForeignPtr ())
foreignVoid = newForeignPtr finalizerFree

foreignPMsg :: Ptr () -> IO(ForeignPtr ())
foreignPMsg pv = do 
  v <- peek (castPtr pv)
  free pv
  newForeignPtr nnFunPtrFreeMsg v

pVoid :: Ptr () -> IO(Ptr ())
pVoid pv = do 
  v <- peek (castPtr pv)
  free pv
  return v


foreignFreeMsg :: Ptr () -> IO(Either NnError (ForeignPtr ()))
foreignFreeMsg =  either (return . Left) (return . Right <=< newForeignPtr nnFunPtrFreeMsg) <=< errorFromNewPointer

cPackCString :: CString -> IO ByteString
cPackCString = C.packCString
ucPackCString :: Ptr a -> IO ByteString
ucPackCString = C.packCString . castPtr
uPackCString :: CString -> IO ByteString
uPackCString = U.unsafePackCString
uuPackCString :: Ptr a -> IO ByteString
uuPackCString = U.unsafePackCString . castPtr

errorFromRetCode :: CInt -> IO(Maybe NnError)
errorFromRetCode r = if r < 0 then nnErrno >>= return . Just else return Nothing

errorFromNewPointer :: Ptr () -> IO(Either NnError (Ptr ()))
errorFromNewPointer ptr = if ptr == nullPtr then nnErrno >>= return . Left else return $ Right ptr


errorFromLength :: CInt -> IO(Either NnError Int)
errorFromLength r = if r < 0 then nnErrno >>= return . Left else (return . Right . fromIntegral) r

errorFromSocket :: CInt -> IO(Either NnError NnSocket)
errorFromSocket r = if r < 0 then nnErrno >>= return . Left else (return . Right . NnSocket) r

errorFromEndPoint :: CInt -> IO(Either NnError NnEndPoint)
errorFromEndPoint r = if r < 0 then nnErrno >>= return . Left else (return . Right . NnEndPoint) r


nnErrno :: IO ((NnError))
nnErrno =
  nnErrno'_ >>= \res ->
  let {res' = cIntToEnum res} in
  return (res')
{-# LINE 265 "System/NanoMsg/C/NanoMsg.chs" #-}
-- Mostly useless as c2hs uses macro, so no mapping from Int values to Enum
nnSymbol :: (Int) -> IO ((String), (Int))
nnSymbol a1 =
  let {a1' = fromIntegral a1} in 
  alloca $ \a2' -> 
  nnSymbol'_ a1' a2' >>= \res ->
  peekCString res >>= \res' ->
  peekInt  a2'>>= \a2'' -> 
  return (res', a2'')
{-# LINE 267 "System/NanoMsg/C/NanoMsg.chs" #-}
nnStrerror :: (NnError) -> IO ((String))
nnStrerror a1 =
  let {a1' = cIntFromEnum a1} in 
  nnStrerror'_ a1' >>= \res ->
  peekCString res >>= \res' ->
  return (res')
{-# LINE 268 "System/NanoMsg/C/NanoMsg.chs" #-}

dummy' :: IO ()
dummy' = nnTerm
{-# LINE 271 "System/NanoMsg/C/NanoMsg.chs" #-}

-- type of allocation is transport dependant -- see transport implementation --> for haskell api link it to the transport used -- TODO (tricky??)
nnAllocmsg' :: (Int) -> (Int) -> IO ((Either NnError (ForeignPtr ())))
nnAllocmsg' a1 a2 =
  let {a1' = fromIntegral a1} in 
  let {a2' = fromIntegral a2} in 
  nnAllocmsg''_ a1' a2' >>= \res ->
  foreignFreeMsg res >>= \res' ->
  return (res')
{-# LINE 274 "System/NanoMsg/C/NanoMsg.chs" #-}
nnAllocmsg :: (Int) -> (Int) -> IO ((Either NnError (Ptr ())))
nnAllocmsg a1 a2 =
  let {a1' = fromIntegral a1} in 
  let {a2' = fromIntegral a2} in 
  nnAllocmsg'_ a1' a2' >>= \res ->
  errorFromNewPointer res >>= \res' ->
  return (res')
{-# LINE 275 "System/NanoMsg/C/NanoMsg.chs" #-}

-- do not use if nnAllocmsg' used
nnFreemsg :: (Ptr ()) -> IO ((Maybe NnError))
nnFreemsg a1 =
  let {a1' = id a1} in 
  nnFreemsg'_ a1' >>= \res ->
  errorFromRetCode res >>= \res' ->
  return (res')
{-# LINE 278 "System/NanoMsg/C/NanoMsg.chs" #-}

cmsgFirstHdr :: (NNMsgHdr) -> IO ((Maybe NNCMsgHdr))
cmsgFirstHdr a1 =
  fromMsgHdr a1 $ \a1' -> 
  cmsgFirstHdr'_ a1' >>= \res ->
  maybeCMsg res >>= \res' ->
  return (res')
{-# LINE 280 "System/NanoMsg/C/NanoMsg.chs" #-}
cmsgNxtHdr :: (NNMsgHdr) -> (NNCMsgHdr) -> IO ((Maybe NNCMsgHdr))
cmsgNxtHdr a1 a2 =
  fromMsgHdr a1 $ \a1' -> 
  fromCMsgHdr a2 $ \a2' -> 
  cmsgNxtHdr'_ a1' a2' >>= \res ->
  maybeCMsg res >>= \res' ->
  return (res')
{-# LINE 281 "System/NanoMsg/C/NanoMsg.chs" #-}
-- | use of byteString for char * here. Note that Bytestring is copied. -- not we use unsigned char and do a cast ptr : ByteString should not be use with unicode.
cmsgData :: (NNCMsgHdr) -> IO ((ByteString))
cmsgData a1 =
  fromCMsgHdr a1 $ \a1' -> 
  cmsgData'_ a1' >>= \res ->
  ucPackCString res >>= \res' ->
  return (res')
{-# LINE 283 "System/NanoMsg/C/NanoMsg.chs" #-}
-- | unsafe version for efficiency. To test but might be ok.
cmsgData' :: (NNCMsgHdr) -> IO ((ByteString))
cmsgData' a1 =
  fromCMsgHdr a1 $ \a1' -> 
  cmsgData''_ a1' >>= \res ->
  uuPackCString res >>= \res' ->
  return (res')
{-# LINE 285 "System/NanoMsg/C/NanoMsg.chs" #-}
-- | might not be pure in the future but given current nanomsg implementation it is ok
cmsgLen :: (Int) -> (Int)
cmsgLen a1 =
  let {a1' = fromIntegral a1} in 
  let {res = cmsgLen'_ a1'} in
  let {res' = fromIntegral res} in
  (res')
{-# LINE 287 "System/NanoMsg/C/NanoMsg.chs" #-}
cmsgLen' :: (Int) -> IO ((Int))
cmsgLen' a1 =
  let {a1' = fromIntegral a1} in 
  cmsgLen''_ a1' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')
{-# LINE 288 "System/NanoMsg/C/NanoMsg.chs" #-}
-- | might not be pure in the future but given current nanomsg implementation it is ok
cmsgSpace :: (Int) -> (Int)
cmsgSpace a1 =
  let {a1' = fromIntegral a1} in 
  let {res = cmsgSpace'_ a1'} in
  let {res' = fromIntegral res} in
  (res')
{-# LINE 290 "System/NanoMsg/C/NanoMsg.chs" #-}
cmsgSpace' :: (Int) -> IO ((Int))
cmsgSpace' a1 =
  let {a1' = fromIntegral a1} in 
  cmsgSpace''_ a1' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')
{-# LINE 291 "System/NanoMsg/C/NanoMsg.chs" #-}


-- TODO enum for domain???
nnSocket :: (AddressFamilies) -> (NnProtocol) -> IO ((Either NnError NnSocket))
nnSocket a1 a2 =
  let {a1' = cIntFromEnum a1} in 
  let {a2' = cIntFromEnum a2} in 
  nnSocket'_ a1' a2' >>= \res ->
  errorFromSocket res >>= \res' ->
  return (res')
{-# LINE 295 "System/NanoMsg/C/NanoMsg.chs" #-}

nnClose :: (NnSocket) -> IO ((Maybe NnError))
nnClose a1 =
  let {a1' = socketToCInt a1} in 
  nnClose'_ a1' >>= \res ->
  errorFromRetCode res >>= \res' ->
  return (res')
{-# LINE 297 "System/NanoMsg/C/NanoMsg.chs" #-}

nnSetsockopt :: (AllSocketOptions a, AllLevelOptions b) => (NnSocket) -> (b) -> (a) -> (Ptr ()) -> (Int) -> IO ((Maybe NnError))
nnSetsockopt a1 a2 a3 a4 a5 =
  let {a1' = socketToCInt a1} in 
  let {a2' = cIntFromEnum a2} in 
  let {a3' = cIntFromEnum a3} in 
  let {a4' = id a4} in 
  let {a5' = fromIntegral a5} in 
  nnSetsockopt'_ a1' a2' a3' a4' a5' >>= \res ->
  errorFromRetCode res >>= \res' ->
  return (res')
{-# LINE 299 "System/NanoMsg/C/NanoMsg.chs" #-}

withNullPPtr :: (Ptr () -> IO b) -> IO b
withNullPPtr r = do 
  pp <- malloc
  poke pp nullPtr
  r $ castPtr pp
withNullPtr :: (Ptr () -> IO b) -> IO b
withNullPtr r = r nullPtr
-- | handling of values for options out of c api - we do not allocate memory for return value of option -- and do not send size -- should use a stablepointer?? -- to test thoroughly (doc initiate size and pointer which does not make any sense
--{#fun unsafe nn_getsockopt as ^ `(AllSocketOptions a, AllLevelOptions b)' => {socketToCInt `NnSocket', cIntFromEnum `b', cIntFromEnum `a', withNullPtr- `Ptr ()' id,  alloca- `Int' peekInt*} -> `Maybe NnError' errorFromRetCode* #}
nnGetsockopt :: (AllSocketOptions a, AllLevelOptions b) => (NnSocket) -> (b) -> (a) -> (Ptr ()) -> (Int) -> IO ((Maybe NnError), (Ptr ()), (Int))
nnGetsockopt a1 a2 a3 a4 a5 =
  let {a1' = socketToCInt a1} in 
  let {a2' = cIntFromEnum a2} in 
  let {a3' = cIntFromEnum a3} in 
  let {a4' = id a4} in 
  withPIntegral a5 $ \a5' -> 
  nnGetsockopt'_ a1' a2' a3' a4' a5' >>= \res ->
  errorFromRetCode res >>= \res' ->
  let {a4'' = id  a4'} in 
  peekInt  a5'>>= \a5'' -> 
  return (res', a4'', a5'')
{-# LINE 310 "System/NanoMsg/C/NanoMsg.chs" #-}

-- TODO bind an address type to avoid address without :// (in api(one per transport) using NN_SOCKADDR_MAX)
nnBind :: (NnSocket) -> (String) -> IO ((Either NnError NnEndPoint))
nnBind a1 a2 =
  let {a1' = socketToCInt a1} in 
  withCString a2 $ \a2' -> 
  nnBind'_ a1' a2' >>= \res ->
  errorFromEndPoint res >>= \res' ->
  return (res')
{-# LINE 313 "System/NanoMsg/C/NanoMsg.chs" #-}

nnConnect :: (NnSocket) -> (String) -> IO ((Either NnError NnEndPoint))
nnConnect a1 a2 =
  let {a1' = socketToCInt a1} in 
  withCString a2 $ \a2' -> 
  nnConnect'_ a1' a2' >>= \res ->
  errorFromEndPoint res >>= \res' ->
  return (res')
{-# LINE 315 "System/NanoMsg/C/NanoMsg.chs" #-}

nnShutdown :: (NnSocket) -> (NnEndPoint) -> IO ((Maybe NnError))
nnShutdown a1 a2 =
  let {a1' = socketToCInt a1} in 
  let {a2' = endPointToCInt a2} in 
  nnShutdown'_ a1' a2' >>= \res ->
  errorFromRetCode res >>= \res' ->
  return (res')
{-# LINE 317 "System/NanoMsg/C/NanoMsg.chs" #-}

-- All recv functions are derived from C2hs generation to enforce nn_dont_wait and depending on set flags wait in haskell (issue with poll c function when using ffi). Normal c2hs receive are kept postfixed B (as Bogus).
nnRecvDynB' :: (NnSocket) -> ([SndRcvFlags]) -> IO ((Either NnError Int), (Ptr ()))
nnRecvDynB' a1 a4 =
  let {a1' = socketToCInt a1} in 
  withNullPPtr $ \a2' -> 
  withNnMSG $ \a3' -> 
  let {a4' = flagsToCInt a4} in 
  nnRecvDynB''_ a1' a2' a3' a4' >>= \res ->
  errorFromLength res >>= \res' ->
  pVoid  a2'>>= \a2'' -> 
  return (res', a2'')
{-# LINE 320 "System/NanoMsg/C/NanoMsg.chs" #-}
nnRecvDynB :: (NnSocket) -> ([SndRcvFlags]) -> IO ((Either NnError Int), (ForeignPtr ()))
nnRecvDynB a1 a4 =
  let {a1' = socketToCInt a1} in 
  withNullPPtr $ \a2' -> 
  withNnMSG $ \a3' -> 
  let {a4' = flagsToCInt a4} in 
  nnRecvDynB'_ a1' a2' a3' a4' >>= \res ->
  errorFromLength res >>= \res' ->
  foreignPMsg  a2'>>= \a2'' -> 
  return (res', a2'')
{-# LINE 321 "System/NanoMsg/C/NanoMsg.chs" #-}
-- TODO fn with foreign does not make too much sense (should be in api)
nnRecvB :: (NnSocket) -> (ForeignPtr ()) -> (Int) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnRecvB a1 a2 a3 a4 =
  let {a1' = socketToCInt a1} in 
  withForeignPtr a2 $ \a2' -> 
  let {a3' = fromIntegral a3} in 
  let {a4' = flagsToCInt a4} in 
  nnRecvB'_ a1' a2' a3' a4' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')
{-# LINE 323 "System/NanoMsg/C/NanoMsg.chs" #-}
nnRecvB' :: (NnSocket) -> (Ptr ()) -> (Int) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnRecvB' a1 a2 a3 a4 =
  let {a1' = socketToCInt a1} in 
  let {a2' = id a2} in 
  let {a3' = fromIntegral a3} in 
  let {a4' = flagsToCInt a4} in 
  nnRecvB''_ a1' a2' a3' a4' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')
{-# LINE 324 "System/NanoMsg/C/NanoMsg.chs" #-}

nn_recvmsgB :: (NnSocket) -> (NNMsgHdr) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nn_recvmsgB a1 a2 a3 =
  let {a1' = socketToCInt a1} in 
  fromMsgHdr a2 $ \a2' -> 
  let {a3' = flagsToCInt a3} in 
  nn_recvmsgB'_ a1' a2' a3' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')
{-# LINE 326 "System/NanoMsg/C/NanoMsg.chs" #-}
nnRecvfmsgB :: (NnSocket) -> (NNFMsgHdr) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnRecvfmsgB a1 a2 a3 =
  let {a1' = socketToCInt a1} in 
  fromFMsgHdr a2 $ \a2' -> 
  let {a3' = flagsToCInt a3} in 
  nnRecvfmsgB'_ a1' a2' a3' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')
{-# LINE 327 "System/NanoMsg/C/NanoMsg.chs" #-}

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_recv"
  nn_recv_c :: (CInt -> ((Ptr ()) -> (CULong -> (CInt -> (IO CInt)))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_recvmsg"
  nn_recvmsg_c :: (CInt -> ((Ptr ()) -> (CInt -> (IO CInt))))

pollRecFd :: Bool -> CInt -> Ptr () -> CULong -> CInt -> IO CInt
pollRecFd True s ptr psize fls = do
  res <- nn_recv_c s ptr psize fls
  if res == (-1) then do
    err <- nnErrno
    if err == EAGAIN then do
      getFd NN_RCVFD s >>= threadWaitRead >> pollRecFd True s ptr psize fls
    else return res
  else return res
pollRecFd False s ptr psize fls = nn_recv_c s ptr psize fls
pollRecFdMsg :: Bool -> CInt -> Ptr () -> CInt -> IO CInt
pollRecFdMsg True s ptr fls = do
  res <- nn_recvmsg_c s ptr fls
  if res == (-1) then do
    err <- nnErrno
    if err == EAGAIN then do
      getFd NN_RCVFD s >>= threadWaitRead >> pollRecFdMsg True s ptr fls 
    else return res
  else return res
pollRecFdMsg False s ptr fls = nn_recvmsg_c s ptr fls

pollSndFd :: Bool -> CInt -> Ptr () -> CULong -> CInt -> IO CInt
pollSndFd True s ptr psize fls = do
  res <- nn_send_c s ptr psize fls
  if res == (-1) then do
    err <- nnErrno
    if err == EAGAIN then do
      getFd NN_SNDFD s >>= threadWaitWrite >> pollSndFd True s ptr psize fls
    else return res
  else return res
pollSndFd False s ptr psize fls = nn_send_c s ptr psize fls

pollSndFdMsg :: Bool -> CInt -> Ptr () -> CInt -> IO CInt
pollSndFdMsg True s ptr fls = do
  res <- nn_sendmsg_c s ptr fls
  if res == (-1) then do
    err <- nnErrno
    if err == EAGAIN then do
      getFd NN_SNDFD s >>= threadWaitWrite >> pollSndFdMsg True s ptr fls
    else return res
  else return res
pollSndFdMsg False s ptr fls = nn_sendmsg_c s ptr fls


-- TODO manage error (no fd result from getOption)
getFd :: (Enum c) => c -> CInt -> IO Fd
getFd f s = 
  let sol = cIntFromEnum NN_SOL_SOCKET
      fdo = cIntFromEnum f 
      fdSize = fromIntegral $ sizeOf (undefined :: Fd) in
    alloca $ \ptr ->
      alloca $ \psize -> do
        poke psize fdSize
        size <- nnGetsockopt'_ s sol fdo (castPtr (ptr :: Ptr Fd)) psize
        peek ptr

-- boileplate copy from c2hs generated code to include test on dont wait and haskell polling of file descriptor
nnRecvDyn' :: (NnSocket) -> ([SndRcvFlags]) -> IO ((Either NnError Int), (Ptr ()))
nnRecvDyn' soc fls =
  let s = socketToCInt soc in 
  withNullPPtr $ \nulptr -> 
  withNnMSG $ \size -> 
  let {(f,w) = rFlagsToCInt fls} in 
  pollRecFd w s nulptr size f >>= \res ->
  errorFromLength res >>= \res' ->
  pVoid  nulptr>>= \a2'' -> 
  return (res', a2'')
nnRecvDyn :: (NnSocket) -> ([SndRcvFlags]) -> IO ((Either NnError Int), (ForeignPtr ()))
nnRecvDyn a1 a4 =
  let {a1' = socketToCInt a1} in 
  withNullPPtr $ \a2' -> 
  withNnMSG $ \a3' -> 
  let {(a4',w) = rFlagsToCInt a4} in 
  pollRecFd w a1' a2' a3' a4' >>= \res ->
  errorFromLength res >>= \res' ->
  foreignPMsg  a2'>>= \a2'' -> 
  return (res', a2'')
nnRecv :: (NnSocket) -> (ForeignPtr ()) -> (Int) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnRecv a1 a2 a3 a4 =
  let {a1' = socketToCInt a1} in 
  withForeignPtr a2 $ \a2' -> 
  let {a3' = fromIntegral a3} in 
  let {(a4',w) = rFlagsToCInt a4} in 
  pollRecFd w a1' a2' a3' a4' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')

nnRecv' :: (NnSocket) -> (Ptr ()) -> (Int) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnRecv' a1 a2 a3 a4 =
  let {a1' = socketToCInt a1} in 
  let {a2' = id a2} in 
  let {a3' = fromIntegral a3} in 
  let {(a4',w) = rFlagsToCInt a4} in 
  pollRecFd w a1' a2' a3' a4' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')

nnRecvmsg :: (NnSocket) -> (NNMsgHdr) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnRecvmsg a1 a2 a3 =
  let {a1' = socketToCInt a1} in 
  fromMsgHdr a2 $ \a2' -> 
  let {(a3',w) = rFlagsToCInt a3} in 
  pollRecFdMsg w a1' a2' a3' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')

nnRecvfmsg :: (NnSocket) -> (NNFMsgHdr) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnRecvfmsg a1 a2 a3 =
  let {a1' = socketToCInt a1} in 
  fromFMsgHdr a2 $ \a2' -> 
  let {(a3',w) = rFlagsToCInt a3} in 
  pollRecFdMsg w a1' a2' a3' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')


-- | type to send not in C (not even storable)
nnSendB :: (NnSocket) -> (ForeignPtr ()) -> (Int) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnSendB a1 a2 a3 a4 =
  let {a1' = socketToCInt a1} in 
  withForeignPtr a2 $ \a2' -> 
  let {a3' = fromIntegral a3} in 
  let {a4' = flagsToCInt a4} in 
  nnSendB'_ a1' a2' a3' a4' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')
{-# LINE 452 "System/NanoMsg/C/NanoMsg.chs" #-}
-- | not ForeignFree
nnSendB' :: (NnSocket) -> (Ptr ()) -> (Int) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnSendB' a1 a2 a3 a4 =
  let {a1' = socketToCInt a1} in 
  let {a2' = id a2} in 
  let {a3' = fromIntegral a3} in 
  let {a4' = flagsToCInt a4} in 
  nnSendB''_ a1' a2' a3' a4' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')
{-# LINE 454 "System/NanoMsg/C/NanoMsg.chs" #-}
-- | no foreign (deallocate is managed by nanomq)
nnSendDynB :: (NnSocket) -> (Ptr ()) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnSendDynB a1 a2 a4 =
  let {a1' = socketToCInt a1} in 
  withPPtr a2 $ \a2' -> 
  withNnMSG $ \a3' -> 
  let {a4' = flagsToCInt a4} in 
  nnSendDynB'_ a1' a2' a3' a4' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')
{-# LINE 456 "System/NanoMsg/C/NanoMsg.chs" #-}
--{#fun unsafe nn_send as nnSendDyn {socketToCInt `NnSocket', withPForeign* `ForeignPtr ()', withNnMSG- `Int', flagsToCInt `[SndRcvFlags]'} -> `Either NnError Int' errorFromLength* #} -- Do no send with foreing free pointer because nn deallocate

nnSendmsgB :: (NnSocket) -> (NNMsgHdr) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnSendmsgB a1 a2 a3 =
  let {a1' = socketToCInt a1} in 
  fromMsgHdr a2 $ \a2' -> 
  let {a3' = flagsToCInt a3} in 
  nnSendmsgB'_ a1' a2' a3' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')
{-# LINE 459 "System/NanoMsg/C/NanoMsg.chs" #-}
nnSendfmsgB :: (NnSocket) -> (NNFMsgHdr) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnSendfmsgB a1 a2 a3 =
  let {a1' = socketToCInt a1} in 
  fromFMsgHdr a2 $ \a2' -> 
  let {a3' = flagsToCInt a3} in 
  nnSendfmsgB'_ a1' a2' a3' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')
{-# LINE 460 "System/NanoMsg/C/NanoMsg.chs" #-}

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_send"
  nn_send_c :: (CInt -> ((Ptr ()) -> (CULong -> (CInt -> (IO CInt)))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_sendmsg"
  nn_sendmsg_c :: (CInt -> ((Ptr ()) -> (CInt -> (IO CInt))))


-- same as with receive (issue with poll)
-- | type to send not in C (not even storable) 
nnSend :: (NnSocket) -> (ForeignPtr ()) -> (Int) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnSend a1 a2 a3 a4 =
  let {a1' = socketToCInt a1} in 
  withForeignPtr a2 $ \a2' -> 
  let {a3' = fromIntegral a3} in 
  let {(a4',w) = sFlagsToCInt a4} in 
  pollSndFd w a1' a2' a3' a4' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')
-- | not ForeignFree
nnSend' :: (NnSocket) -> (Ptr ()) -> (Int) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnSend' a1 a2 a3 a4 =
  let {a1' = socketToCInt a1} in 
  let {a2' = id a2} in 
  let {a3' = fromIntegral a3} in 
  let {(a4',w) = sFlagsToCInt a4} in 
  pollSndFd w a1' a2' a3' a4' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')
{-# LINE 315 "System/NanoMsg/C/NanoMsg.chs" #-}
-- | no foreign (deallocate is managed by nanomq)
nnSendDyn :: (NnSocket) -> (Ptr ()) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnSendDyn a1 a2 a4 =
  let {a1' = socketToCInt a1} in 
  withPPtr a2 $ \a2' -> 
  withNnMSG $ \a3' -> 
  let {(a4',w) = sFlagsToCInt a4} in 
  pollSndFd w a1' a2' a3' a4' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')
nnSendmsg :: (NnSocket) -> (NNMsgHdr) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnSendmsg a1 a2 a3 =
  let {a1' = socketToCInt a1} in 
  fromMsgHdr a2 $ \a2' -> 
  let {(a3',w) = sFlagsToCInt a3} in 
  pollSndFdMsg w a1' a2' a3' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')
nnSendfmsg :: (NnSocket) -> (NNFMsgHdr) -> ([SndRcvFlags]) -> IO ((Either NnError Int))
nnSendfmsg a1 a2 a3 =
  let {a1' = socketToCInt a1} in 
  fromFMsgHdr a2 $ \a2' -> 
  let {(a3',w) = sFlagsToCInt a3} in 
  pollSndFdMsg w a1' a2' a3' >>= \res ->
  errorFromLength res >>= \res' ->
  return (res')

withFmsghdr :: ForeignPtr a -> (Ptr c -> IO b) -> IO b
withFmsghdr f r =  withForeignPtr f (r . castPtr)

withNnMSG :: Num a => (a -> b) -> b
withNnMSG a = a (fromIntegral nN_MSG)

-- TODO api with fork (with correct mask) + socket type incompatibilities?
nnDevice :: (NnSocket) -> (NnSocket) -> IO ((Maybe NnError))
nnDevice a1 a2 =
  let {a1' = socketToCInt a1} in 
  let {a2' = socketToCInt a2} in 
  nnDevice'_ a1' a2' >>= \res ->
  errorFromRetCode res >>= \res' ->
  return (res')
{-# LINE 525 "System/NanoMsg/C/NanoMsg.chs" #-}

-- Struct related Code for simplicity and to avoid boilerplate code, this could be refactor in a separate hs2c module with usage of data, or moved in c helper functions.

fromMsgHdr ::  NNMsgHdr -> (Ptr () -> IO b) -> IO b
fromMsgHdr  = withPStorable'
fromFMsgHdr ::  NNFMsgHdr -> (Ptr () -> IO b) -> IO b
fromFMsgHdr  = withPStorable'
fromCMsgHdr ::  NNCMsgHdr -> (Ptr () -> IO b) -> IO b
fromCMsgHdr  = withPStorable'
toCMsgHdr :: Ptr () -> IO NNCMsgHdr
toCMsgHdr = peek . castPtr

maybeCMsg :: Ptr () -> IO (Maybe NNCMsgHdr)
maybeCMsg m = if m == nullPtr then return Nothing else toCMsgHdr m >>= (return . Just)

-- | MsgHdr helpers


newRawMsgHdr :: (Storable s) => s -> IO (Either NnError (Ptr NNCMsgHdr))
newRawMsgHdr s = do 
  let totle = sizeOf s
  mem <- nnAllocmsg (totle) 0
  case mem of 
    (Left e) -> return $ Left e
    (Right ptr') -> do
      let ptr = castPtr ptr'
      poke ptr s
      return $ Right ptr

getRawMsgHdr :: (Storable s) => (Ptr NNCMsgHdr) -> IO (Either NnError s)
getRawMsgHdr pt = do 
   r  <- peek (castPtr pt)
   er <- nnFreemsg (castPtr pt) -- as bs are copied
   case er of
      (Just e) -> return $ Left e
      Nothing  -> return $ Right r
 
newMSgHdr :: [(BS.ByteString, Int, Int)] -> IO (Either NnError (Ptr NNCMsgHdr))
newMSgHdr hdrs = do 
  let totle = foldl' (\acc (bs, _, _)-> acc + BS.length bs + hdrsize) 0 hdrs -- TODO do not use BS.length
  mem <- nnAllocmsg (totle) 0
  case mem of 
    (Left e) -> return $ Left e
    (Right ptr') -> do
      let ptr = castPtr ptr'
      foldM_ (pokeEl (ptr)) 0 hdrs
      return $ Right ptr
    where pokeEl :: (Ptr NNCMsgHdr) -> Int -> (BS.ByteString, Int, Int) -> IO Int
          pokeEl ptr offset ((PS pbs pof ple), lev, typ ) = do
                                        poke  (ptr `plusPtr` offset) $ NNCMsgHdr (fromIntegral (ple - pof)) (fromIntegral lev) (fromIntegral typ)
                                        --pokeElemOff ptr (offset + sizeOf hdr) bs
                                        withForeignPtr pbs $ \pbs' -> copyBytes (ptr `plusPtr` (offset + hdrsize)) ((castPtr pbs') `plusPtr` pof) (ple - pof) -- TODO use unsafe bytestring api instead
                                        return (offset + hdrsize + (ple - pof))
          hdrsize = sizeOf (undefined :: NNCMsgHdr)

-- test MsgHdr not nullPtr not here
getMSgHdr :: (Ptr NNCMsgHdr) -> Int -> IO (Either NnError [(BS.ByteString, Int, Int)])
getMSgHdr pt nbh = do
  r <- if nbh == fromIntegral nN_MSG then do
     id <- peek (castPtr pt) :: IO CUInt
     return [(BS.pack [],fromIntegral id,0)]
  else do 
     (_,r) <- foldM (\acc _ -> peekmsg pt acc ) (0,[]) [1..nbh]
     return r
  er <- nnFreemsg (castPtr pt) -- as bs are copied
  case er of
      (Just e) -> return $ Left e
      Nothing  -> return $ Right $ reverse r
  where
         peekmsg ptr' (offset, acc) = do 
           let ptr =  ptr' `plusPtr` offset
           ptch <- peek ptr
           bs <- BS.packCStringLen (ptr `plusPtr` (sizeOf ptch ), (fromIntegral (cmsglen ptch))) -- here use bytestring PS instead
           let newoffset = offset + sizeOf ptch + fromIntegral (cmsglen ptch)
           return (newoffset, (bs, fromIntegral (cmsglev ptch), fromIntegral (cmsgtyp ptch)) : acc)




foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_errno"
  nnErrno'_ :: (IO CInt)

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_symbol"
  nnSymbol'_ :: (CInt -> ((Ptr CInt) -> (IO (Ptr CChar))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_strerror"
  nnStrerror'_ :: (CInt -> (IO (Ptr CChar)))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_term"
  nnTerm :: (IO ())

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_allocmsg"
  nnAllocmsg''_ :: (CULong -> (CInt -> (IO (Ptr ()))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_allocmsg"
  nnAllocmsg'_ :: (CULong -> (CInt -> (IO (Ptr ()))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_freemsg"
  nnFreemsg'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h wfirsthdr"
  cmsgFirstHdr'_ :: ((Ptr ()) -> (IO (Ptr ())))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h wnxthdr"
  cmsgNxtHdr'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h wdata"
  cmsgData'_ :: ((Ptr ()) -> (IO (Ptr CUChar)))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h wdata"
  cmsgData''_ :: ((Ptr ()) -> (IO (Ptr CUChar)))

foreign import ccall safe "System/NanoMsg/C/NanoMsg.chs.h wlen"
  cmsgLen'_ :: (CULong -> CULong)

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h wlen"
  cmsgLen''_ :: (CULong -> (IO CULong))

foreign import ccall safe "System/NanoMsg/C/NanoMsg.chs.h wspace"
  cmsgSpace'_ :: (CULong -> CULong)

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h wspace"
  cmsgSpace''_ :: (CULong -> (IO CULong))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_socket"
  nnSocket'_ :: (CInt -> (CInt -> (IO CInt)))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_close"
  nnClose'_ :: (CInt -> (IO CInt))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_setsockopt"
  nnSetsockopt'_ :: (CInt -> (CInt -> (CInt -> ((Ptr ()) -> (CULong -> (IO CInt))))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_getsockopt"
  nnGetsockopt'_ :: (CInt -> (CInt -> (CInt -> ((Ptr ()) -> ((Ptr CULong) -> (IO CInt))))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_bind"
  nnBind'_ :: (CInt -> ((Ptr CChar) -> (IO CInt)))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_connect"
  nnConnect'_ :: (CInt -> ((Ptr CChar) -> (IO CInt)))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_shutdown"
  nnShutdown'_ :: (CInt -> (CInt -> (IO CInt)))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_recv"
  nnRecvDynB''_ :: (CInt -> ((Ptr ()) -> (CULong -> (CInt -> (IO CInt)))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_recv"
  nnRecvDynB'_ :: (CInt -> ((Ptr ()) -> (CULong -> (CInt -> (IO CInt)))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_recv"
  nnRecvB'_ :: (CInt -> ((Ptr ()) -> (CULong -> (CInt -> (IO CInt)))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_recv"
  nnRecvB''_ :: (CInt -> ((Ptr ()) -> (CULong -> (CInt -> (IO CInt)))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_recvmsg"
  nn_recvmsgB'_ :: (CInt -> ((Ptr ()) -> (CInt -> (IO CInt))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_recvmsg"
  nnRecvfmsgB'_ :: (CInt -> ((Ptr ()) -> (CInt -> (IO CInt))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_send"
  nnSendB'_ :: (CInt -> ((Ptr ()) -> (CULong -> (CInt -> (IO CInt)))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_send"
  nnSendB''_ :: (CInt -> ((Ptr ()) -> (CULong -> (CInt -> (IO CInt)))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_send"
  nnSendDynB'_ :: (CInt -> ((Ptr ()) -> (CULong -> (CInt -> (IO CInt)))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_sendmsg"
  nnSendmsgB'_ :: (CInt -> ((Ptr ()) -> (CInt -> (IO CInt))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_sendmsg"
  nnSendfmsgB'_ :: (CInt -> ((Ptr ()) -> (CInt -> (IO CInt))))

foreign import ccall unsafe "System/NanoMsg/C/NanoMsg.chs.h nn_device"
  nnDevice'_ :: (CInt -> (CInt -> (IO CInt)))
