packages feed

socket-unix 0.1.0.0 → 0.1.1.0

raw patch · 11 files changed

+410/−252 lines, 11 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- System.Socket.Family.Unix: getUnixPath :: SocketAddress Unix -> Maybe (ByteString)
- System.Socket.Family.Unix: instance Foreign.Storable.Storable (System.Socket.Internal.Socket.SocketAddress System.Socket.Family.Unix.Unix)
- System.Socket.Family.Unix: instance GHC.Classes.Eq (System.Socket.Internal.Socket.SocketAddress System.Socket.Family.Unix.Unix)
- System.Socket.Family.Unix: instance GHC.Show.Show (System.Socket.Internal.Socket.SocketAddress System.Socket.Family.Unix.Unix)
- System.Socket.Family.Unix: instance System.Socket.Internal.Socket.Family System.Socket.Family.Unix.Unix
- System.Socket.Family.Unix: instance System.Socket.Internal.Socket.Protocol System.Socket.Family.Unix.Unix
- System.Socket.Family.Unix: socketAddressUnixAbstract :: ByteString -> Maybe (SocketAddress Unix)
- System.Socket.Family.Unix: socketAddressUnixPath :: ByteString -> Maybe (SocketAddress Unix)
+ System.Socket.Family.Unix: eNoEntry :: SocketException

Files

README.md view
@@ -23,7 +23,7 @@ ### Symlinks Binding to a socket with a filename creates a socket in the filesystem, but does not unlink it after `close` called. You should handle deleting links yourself. ## Portability-Only Linux is supported.+Linux and OS X are supported.   [badge-travis]: https://img.shields.io/travis/VyacheslavHashov/haskell-socket-unix.svg
+ platform/linux/System/Socket/Family/Unix/Platform.hsc view
@@ -0,0 +1,99 @@+-- |+-- Stability   :  experimental+-- Portability :  Linux++{-# options_ghc -fno-warn-orphans #-}+{-# language TypeFamilies #-}+{-# language FlexibleInstances #-}++module System.Socket.Family.Unix.Platform+    ( SocketAddress+    , socketAddressUnixPath+    , socketAddressUnixAbstract+    , getUnixPath+    ) where++import           Foreign.Ptr (castPtr, plusPtr)+import           Foreign.Storable (Storable(..))+import           Foreign.Marshal.Utils (fillBytes, copyBytes)++import           Data.Word (Word16, Word8)+import           Data.ByteString (ByteString)+import           Data.ByteString.Unsafe (unsafeUseAsCStringLen)+import qualified Data.ByteString as B++import           System.Socket (SocketAddress)+import           System.Socket.Family.Unix.Internal (Unix)++#include "hs_socket.h"++#if __GLASGOW_HASKELL__ < 800+#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)+#endif++-- | A Unix socket address+data instance SocketAddress Unix+    -- | Address is connected to a filesystem pathname. When used to bind+    -- a socket file with this name is created in the file system.+    = SocketAddressUnixPath ByteString+    -- | Address is in abstract namespace which is a Linux-specific feature+    -- that allows us to bind a UNIX domain socket to a name without that+    -- name being created in the file system.+    | SocketAddressUnixAbstract ByteString+    deriving (Eq, Show)++-- | The maximal length of a address path.+-- SUSv3 doesn’t specify the size of the sun_path field. Early BSD+-- implementations used 108 and 104 bytes, and one contemporary implementation+-- (HP-UX 11) uses 92 bytes.  On linux it is declared as+-- > char sun_path[108];+-- and 1 byte is reserved for null byte.+maxPathLength :: Int+maxPathLength = 107++-- | Creates address which is connected to a filesystem pathname.+-- Returns Nothing if @path@'s length exceeds maximal supported.+socketAddressUnixPath :: ByteString -> Maybe (SocketAddress Unix)+socketAddressUnixPath path+    | B.length path <= maxPathLength = Just $ SocketAddressUnixPath path+    | otherwise = Nothing++-- | Creates address with name in abstract namespace.+-- Returns Nothing if @path@'s length exceeds maximal supported.+socketAddressUnixAbstract :: ByteString -> Maybe (SocketAddress Unix)+socketAddressUnixAbstract path+    | len <= maxPathLength = Just . SocketAddressUnixAbstract $+        path `B.append` B.replicate (maxPathLength - len) 0+    | otherwise = Nothing+  where len = B.length path++-- | Returns filesystem pathname where address is connected to.+getUnixPath :: SocketAddress Unix -> Maybe (ByteString)+getUnixPath (SocketAddressUnixPath path) = Just path+getUnixPath _ = Nothing++-- For implementation details see @man unix@+instance Storable (SocketAddress Unix) where+    sizeOf    _ = (#size struct sockaddr_un)+    alignment _ = (#alignment struct sockaddr_un)++    peek ptr = do+        first <- peek (sun_path ptr) :: IO Word8+        case first of+            0 -> SocketAddressUnixAbstract <$>+                    B.packCStringLen (castPtr $ sun_path ptr `plusPtr` 1, maxPathLength)+            _ -> SocketAddressUnixPath <$> B.packCString (castPtr $ sun_path ptr)+      where+        sun_path   = (#ptr struct sockaddr_un, sun_path)++    poke ptr socketAddress = do+        fillBytes ptr 0 (#const sizeof(struct sockaddr_un))+        poke (sun_family ptr) ((#const AF_UNIX) :: Word16)+        case socketAddress of+            SocketAddressUnixPath path -> unsafeUseAsCStringLen path $+                \(src, len) -> copyBytes (sun_path ptr) src len+            SocketAddressUnixAbstract path -> unsafeUseAsCStringLen path $+                \(src, len) -> copyBytes (sun_path ptr `plusPtr` 1) src len+      where+        sun_family = (#ptr struct sockaddr_un, sun_family)+        sun_path   = (#ptr struct sockaddr_un, sun_path)
+ platform/unix/System/Socket/Family/Unix/Platform.hsc view
@@ -0,0 +1,76 @@+-- |+-- Stability   :  experimental+-- Portability :  Unix++{-# options_ghc -fno-warn-orphans #-}+{-# language TypeFamilies #-}+{-# language FlexibleInstances #-}++module System.Socket.Family.Unix.Platform+    ( SocketAddress+    , socketAddressUnixPath+    , getUnixPath+    ) where++import           Foreign.Ptr (castPtr, plusPtr)+import           Foreign.Storable (Storable(..))+import           Foreign.Marshal.Utils (fillBytes, copyBytes)++import           Data.Word (Word16 )+import           Data.ByteString (ByteString)+import           Data.ByteString.Unsafe (unsafeUseAsCStringLen)+import qualified Data.ByteString as B++import           System.Socket (SocketAddress)+import           System.Socket.Family.Unix.Internal (Unix)++#include "hs_socket.h"++#if __GLASGOW_HASKELL__ < 800+#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)+#endif++-- | A Unix socket address+data instance SocketAddress Unix+    -- | Address is connected to a filesystem pathname. When used to bind+    -- a socket file with this name is created in the file system.+    = SocketAddressUnixPath ByteString+    deriving (Eq, Show)++-- | The maximal length of a address path.+-- SUSv3 doesn’t specify the size of the sun_path field. Early BSD+-- implementations used 108 and 104 bytes, and one contemporary implementation+-- (HP-UX 11) uses 92 bytes.  On linux it is declared as+-- > char sun_path[108];+-- and 1 byte is reserved for null byte.+maxPathLength :: Int+maxPathLength = 107++-- | Creates address which is connected to a filesystem pathname.+-- Returns Nothing if @path@'s length exceeds maximal supported.+socketAddressUnixPath :: ByteString -> Maybe (SocketAddress Unix)+socketAddressUnixPath path+    | B.length path <= maxPathLength = Just $ SocketAddressUnixPath path+    | otherwise = Nothing++-- | Returns filesystem pathname where address is connected to.+getUnixPath :: SocketAddress Unix -> Maybe (ByteString)+getUnixPath (SocketAddressUnixPath path) = Just path++-- For implementation details see @man unix@+instance Storable (SocketAddress Unix) where+    sizeOf    _ = (#size struct sockaddr_un)+    alignment _ = (#alignment struct sockaddr_un)++    peek ptr = SocketAddressUnixPath <$> B.packCString (castPtr $ sun_path ptr)+      where+        sun_path   = (#ptr struct sockaddr_un, sun_path)++    poke ptr (SocketAddressUnixPath path) = do+        fillBytes ptr 0 (#const sizeof(struct sockaddr_un))+        poke (sun_family ptr) ((#const AF_UNIX) :: Word16)+        unsafeUseAsCStringLen path $+            \(src, len) -> copyBytes (sun_path ptr) src len+      where+        sun_family = (#ptr struct sockaddr_un, sun_family)+        sun_path   = (#ptr struct sockaddr_un, sun_path)
+ platform_test/linux/Platform.hs view
@@ -0,0 +1,42 @@+module Platform where++import Data.Maybe (fromJust)+import Control.Exception (bracket, throwIO, try)+import Test.Tasty+import Test.Tasty.HUnit++import System.Socket+import System.Socket.Type.Stream+import System.Socket.Type.Datagram+import System.Socket.Family.Unix++import Internal++groupAbstractName :: TestTree+groupAbstractName = testGroup "Abstract path name"+    [ testCase "connect to non-existing path name" $ bracket+        unixSocketStream+        close+        (\s -> do+            r <- try $ connect s addr+            case r of+                Left e | e == eConnectionRefused -> return ()+                       | otherwise               -> throwIO e+                Right () -> assertFailure "connection should have failed"+        )+    , testCase "server\\client stream" $ bracket+        ( (,) <$> unixSocketStream <*> unixSocketStream)+        closeSockets+        (testServerClientStream addr)+    , testCase "server\\client datagram" $ bracket+        ((,) <$> unixSocketDatagram <*> unixSocketDatagram)+        closeSockets+        (testServerClientDatagram addr cAddr)+    ]+  where+    addr = fromJust $ socketAddressUnixAbstract abstractPath+    cAddr = fromJust $ socketAddressUnixAbstract clientAbstractPath+    closeSockets (server, client) = do+        close server+        close client+
+ platform_test/unix/Platform.hs view
@@ -0,0 +1,7 @@+module Platform where++import Test.Tasty++groupAbstractName :: TestTree+groupAbstractName = testGroup "Abstract path name" []+
socket-unix.cabal view
@@ -1,6 +1,6 @@ name:                socket-unix-version:             0.1.0.0-synopsis:            A Unix domain sockets+version:             0.1.1.0+synopsis:            Unix domain sockets description:         A Unix domain socket extension for the socket library homepage:            https://github.com/vyacheslavhashov/haskell-socket-unix#readme license:             MIT @@ -9,13 +9,20 @@ maintainer:          vyacheslavhashov@gmail.com copyright:           2017 Vyacheslav Hashov category:            System, Network+stability:           Experimental build-type:          Simple extra-source-files:  README.md cabal-version:       >=1.10  library   hs-source-dirs:      src+  if os(linux)+    hs-source-dirs:    platform/linux+  if os(osx) || os(darwin) || os(freebsd) || os(openbsd) || os(netbsd) || os(solaris)+    hs-source-dirs:    platform/unix   exposed-modules:     System.Socket.Family.Unix+  other-modules:       System.Socket.Family.Unix.Internal+                       System.Socket.Family.Unix.Platform   build-depends:       base         >= 4.7      && < 5                      , socket       >= 0.6.0.0  && < 0.8.0.0                      , bytestring   >= 0.10.0.0 && < 0.11@@ -26,7 +33,13 @@ test-suite default   type:                exitcode-stdio-1.0   hs-source-dirs:      test+  if os(linux)+    hs-source-dirs:    platform_test/linux+  if os(osx) || os(darwin) || os(freebsd) || os(openbsd) || os(netbsd) || os(solaris)+    hs-source-dirs:    platform_test/unix   main-is:             test.hs+  other-modules:       Internal+                       Platform   build-depends:       base         >= 4.7      && < 5                      , socket       >= 0.6.0.0  && < 0.8.0.0                      , socket-unix@@ -40,7 +53,13 @@ test-suite threaded   type:                exitcode-stdio-1.0   hs-source-dirs:      test+  if os(linux)+    hs-source-dirs:    platform_test/linux+  if os(osx) || os(darwin) || os(freebsd) || os(openbsd) || os(netbsd) || os(solaris)+    hs-source-dirs:    platform_test/unix   main-is:             test.hs+  other-modules:       Internal+                       Platform   build-depends:       base         >= 4.7      && < 5                      , socket       >= 0.6.0.0  && < 0.8.0.0                      , socket-unix
+ src/System/Socket/Family/Unix.hs view
@@ -0,0 +1,14 @@+-- |+-- Stability   :  experimental+-- Portability :  Linux, OS X++module System.Socket.Family.Unix+    ( Unix+    , module Exports+    -- * Exceptions+    , eNoEntry+    ) where++import System.Socket.Family.Unix.Internal+import System.Socket.Family.Unix.Platform as Exports+
− src/System/Socket/Family/Unix.hsc
@@ -1,108 +0,0 @@--- |--- Stability   :  experimental--- Portability :  Linux--{-# language TypeFamilies #-}-{-# language FlexibleInstances #-}--module System.Socket.Family.Unix-    ( Unix-    , SocketAddress-    , socketAddressUnixPath-    , socketAddressUnixAbstract-    , getUnixPath-    ) where--import           Foreign.Ptr (castPtr, plusPtr)-import           Foreign.Storable (Storable(..))-import           Foreign.Marshal.Utils (fillBytes, copyBytes)--import           Data.Word (Word16, Word8)-import           Data.ByteString (ByteString)-import           Data.ByteString.Unsafe (unsafeUseAsCStringLen)-import qualified Data.ByteString as B--import          System.Socket (Family(..), SocketAddress, Protocol(..))--#include "hs_socket.h"--#if __GLASGOW_HASKELL__ < 800-#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)-#endif---- | The [Unix domain socket]--- (https://en.wikipedia.org/wiki/Unix_domain_socket)-data Unix--instance Family Unix where-    familyNumber _ = (#const AF_UNIX)--instance Protocol Unix where-    protocolNumber _ = 0---- | A Unix socket address-data instance SocketAddress Unix-    -- | Address is connected to a filesystem pathname. When used to bind-    -- a socket file with this name is created in the file system.-    = SocketAddressUnixPath ByteString-    -- | Address is in abstract namespace which is a Linux-specific feature-    -- that allows us to bind a UNIX domain socket to a name without that-    -- name being created in the file system.-    | SocketAddressUnixAbstract ByteString-    deriving (Eq, Show)---- | The maximal length of a address path.--- SUSv3 doesn’t specify the size of the sun_path field. Early BSD--- implementations used 108 and 104 bytes, and one contemporary implementation--- (HP-UX 11) uses 92 bytes.  On linux it is declared as--- > char sun_path[108];--- and 1 byte is reserved for null byte.-maxPathLength :: Int-maxPathLength = 107---- | Creates address which is connected to a filesystem pathname.--- Returns Nothing if @path@'s length exceeds maximal supported.-socketAddressUnixPath :: ByteString -> Maybe (SocketAddress Unix)-socketAddressUnixPath path-    | B.length path <= maxPathLength = Just $ SocketAddressUnixPath path-    | otherwise = Nothing---- | Creates address with name in abstract namespace.--- Returns Nothing if @path@'s length exceeds maximal supported.-socketAddressUnixAbstract :: ByteString -> Maybe (SocketAddress Unix)-socketAddressUnixAbstract path-    | len <= maxPathLength = Just . SocketAddressUnixAbstract $-        path `B.append` B.replicate (maxPathLength - len) 0-    | otherwise = Nothing-  where len = B.length path---- | Returns filesystem pathname where address is connected to.-getUnixPath :: SocketAddress Unix -> Maybe (ByteString)-getUnixPath (SocketAddressUnixPath path) = Just path-getUnixPath _ = Nothing---- For implementation details see @man unix@-instance Storable (SocketAddress Unix) where-    sizeOf    _ = (#size struct sockaddr_un)-    alignment _ = (#alignment struct sockaddr_un)--    peek ptr = do-        first <- peek (sun_path ptr) :: IO Word8-        case first of-            0 -> SocketAddressUnixAbstract <$>-                    B.packCStringLen (castPtr $ sun_path ptr `plusPtr` 1, maxPathLength)-            _ -> SocketAddressUnixPath <$> B.packCString (castPtr $ sun_path ptr)-      where-        sun_path   = (#ptr struct sockaddr_un, sun_path)--    poke ptr socketAddress = do-        fillBytes ptr 0 (#const sizeof(struct sockaddr_un))-        poke (sun_family ptr) ((#const AF_UNIX) :: Word16)-        case socketAddress of-            SocketAddressUnixPath path -> unsafeUseAsCStringLen path $-                \(src, len) -> copyBytes (sun_path ptr) src len-            SocketAddressUnixAbstract path -> unsafeUseAsCStringLen path $-                \(src, len) -> copyBytes (sun_path ptr `plusPtr` 1) src len-      where-        sun_family = (#ptr struct sockaddr_un, sun_family)-        sun_path   = (#ptr struct sockaddr_un, sun_path)
+ src/System/Socket/Family/Unix/Internal.hsc view
@@ -0,0 +1,32 @@+-- |+-- Stability   :  experimental+-- Portability :  Linux, Unix++module System.Socket.Family.Unix.Internal+    ( Unix+    -- * Exceptions+    , eNoEntry+    ) where++import System.Socket (Family(..), Protocol(..), SocketException(..))++#include "hs_socket.h"++#if __GLASGOW_HASKELL__ < 800+#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)+#endif++-- | The [Unix domain socket]+-- (https://en.wikipedia.org/wiki/Unix_domain_socket)+data Unix++instance Family Unix where+    familyNumber _ = (#const AF_UNIX)++instance Protocol Unix where+    protocolNumber _ = 0++-- | > SocketException "No such file or directory"+eNoEntry :: SocketException+eNoEntry = SocketException (#const ENOENT)+
+ test/Internal.hs view
@@ -0,0 +1,115 @@+{-# language OverloadedStrings #-}+module Internal where++import Control.Concurrent.Async (async, wait)+import Control.Exception (bracket, throwIO, try)+import Control.Monad (when)+import Data.Maybe (fromJust)+import Data.String (IsString)+import Data.ByteString (ByteString)+import System.Posix.Files.ByteString (removeLink, fileExist)+import Test.Tasty+import Test.Tasty.HUnit++import System.Socket+import System.Socket.Type.Stream+import System.Socket.Type.Datagram+import System.Socket.Family.Unix++groupUnixPathname :: TestTree+groupUnixPathname = testGroup "Unix path name"+    [ testCase "connect to non-existing path name" $ bracket+        unixSocketStream+        close+        (\s -> do+            r <- try $ connect s addr+            case r of+                Left e | e == eNoEntry -> return ()+                       | otherwise     -> throwIO e+                Right () -> assertFailure "connection should have failed"+        )++    , testCase "server\\client stream" $ bracket+        ( (,) <$> unixSocketStream <*> unixSocketStream)+        closeSockets+        (testServerClientStream addr)++    , testCase "server\\client datagram" $ bracket+        ((,) <$> unixSocketDatagram <*> unixSocketDatagram)+        closeSockets+        (testServerClientDatagram addr cAddr)+    ]+  where+    addr = fromJust $ socketAddressUnixPath unixPath+    cAddr = fromJust $ socketAddressUnixPath clientUnixPath+    closeSockets (server, client) = do+        close server+        close client+        unlink unixPath+        unlink clientUnixPath+    -- Sockets with real pathname should be unlinked after closing+    unlink path = fileExist path >>= flip when (removeLink path)++clientMessage :: ByteString+clientMessage = "client message"++serverMessage :: ByteString+serverMessage = "server message"++unixPath :: ByteString+unixPath = "Woum5ag3oohuaLee.socket"++clientUnixPath :: ByteString+clientUnixPath = "Io4meo0epoquashi.socket"++abstractPath :: ByteString+abstractPath = "/tmp/uth4Aechiereejae.socket"++clientAbstractPath :: ByteString+clientAbstractPath = "/tmp/FieNg4shamo4Thie.socket"++unixSocketStream :: IO (Socket Unix Stream Unix)+unixSocketStream = socket++unixSocketDatagram :: IO (Socket Unix Datagram Unix)+unixSocketDatagram = socket++testServerClientStream+    :: SocketAddress Unix+    -> (Socket Unix Stream Unix, Socket Unix Stream Unix)+    -> IO ()+testServerClientStream addr (server, client) = do+    bind server addr+    listen server 5+    serverRecv <- async $ do+        (peerSock, peerAddr) <- accept server+        r <- receive peerSock 4096 mempty+        send peerSock serverMessage mempty+        pure r+    connect client addr+    send client clientMessage mempty++    clientMessageReceived <- wait serverRecv+    serverMessageReceived <- receive client 4096 mempty+    clientMessageReceived @?= clientMessage+    serverMessageReceived @?= serverMessage++testServerClientDatagram+    :: SocketAddress Unix+    -> SocketAddress Unix+    -> (Socket Unix Datagram Unix, Socket Unix Datagram Unix)+    -> IO ()+testServerClientDatagram sAddr cAddr (server, client) = do+    bind server sAddr+    bind client cAddr+    serverRecv <- async $ do+        (r, peerAddr) <- receiveFrom server 4096 mempty+        sendTo server serverMessage mempty peerAddr+        pure r+    sendTo client clientMessage mempty sAddr++    clientMessageReceived <- wait serverRecv+    serverMessageReceived <- receive client 4096 mempty+    clientMessageReceived @?= clientMessage+    serverMessageReceived @?= serverMessage+
test/test.hs view
@@ -1,150 +1,12 @@-{-# language OverloadedStrings #-} module Main where -import Control.Concurrent.Async (async, wait)-import Control.Exception (bracket, throwIO, try)-import Control.Monad (when)-import Data.Maybe (fromJust)-import Data.String (IsString)-import Data.ByteString (ByteString)-import System.Posix.Files (removeLink, fileExist)-import Test.Tasty-import Test.Tasty.HUnit--import System.Socket-import System.Socket.Type.Stream-import System.Socket.Type.Datagram-import System.Socket.Family.Unix+import Test.Tasty (defaultMain, testGroup) +import Internal+import Platform  main :: IO () main = defaultMain $ testGroup "unix domain socket"     [ groupUnixPathname     , groupAbstractName ]--groupUnixPathname :: TestTree-groupUnixPathname = testGroup "Unix path name"-    [ testCase "connect to non-existing path name" $ bracket-        unixSocketStream-        close-        (\s -> do-            r <- try $ connect s addr-            case r of-                Left e | e == SocketException 2 -> return ()-                       | otherwise              -> throwIO e-                Right () -> assertFailure "connection should have failed"-        )--    , testCase "server\\client stream" $ bracket-        ( (,) <$> unixSocketStream <*> unixSocketStream)-        closeSockets-        (testServerClientStream addr)--    , testCase "server\\client datagram" $ bracket-        ((,) <$> unixSocketDatagram <*> unixSocketDatagram)-        closeSockets-        (testServerClientDatagram addr cAddr)-    ]-  where-    addr = fromJust $ socketAddressUnixPath unixPath-    cAddr = fromJust $ socketAddressUnixPath clientUnixPath-    closeSockets (server, client) = do-        close server-        close client-        unlink unixPath-        unlink clientUnixPath-    -- Sockets with real pathname should be unlinked after closing-    unlink path = fileExist path >>= flip when (removeLink path)--groupAbstractName :: TestTree-groupAbstractName = testGroup "Abstract path name"-    [ testCase "connect to non-existing path name" $ bracket-        unixSocketStream-        close-        (\s -> do-            r <- try $ connect s addr-            case r of-                Left e | e == eConnectionRefused -> return ()-                       | otherwise               -> throwIO e-                Right () -> assertFailure "connection should have failed"-        )-    , testCase "server\\client stream" $ bracket-        ( (,) <$> unixSocketStream <*> unixSocketStream)-        closeSockets-        (testServerClientStream addr)-    , testCase "server\\client datagram" $ bracket-        ((,) <$> unixSocketDatagram <*> unixSocketDatagram)-        closeSockets-        (testServerClientDatagram addr cAddr)-    ]-  where-    addr = fromJust $ socketAddressUnixAbstract abstractPath-    cAddr = fromJust $ socketAddressUnixAbstract clientAbstractPath-    closeSockets (server, client) = do-        close server-        close client---clientMessage :: ByteString-clientMessage = "client message"--serverMessage :: ByteString-serverMessage = "server message"--unixPath :: IsString a => a-unixPath = "Woum5ag3oohuaLee.socket"--clientUnixPath :: IsString a => a-clientUnixPath = "Io4meo0epoquashi.socket"--abstractPath :: ByteString-abstractPath = "/tmp/uth4Aechiereejae.socket"--clientAbstractPath :: ByteString-clientAbstractPath = "/tmp/FieNg4shamo4Thie.socket"--unixSocketStream :: IO (Socket Unix Stream Unix)-unixSocketStream = socket--unixSocketDatagram :: IO (Socket Unix Datagram Unix)-unixSocketDatagram = socket--testServerClientStream-    :: SocketAddress Unix-    -> (Socket Unix Stream Unix, Socket Unix Stream Unix)-    -> IO ()-testServerClientStream addr (server, client) = do-    bind server addr-    listen server 5-    serverRecv <- async $ do-        (peerSock, peerAddr) <- accept server-        r <- receive peerSock 4096 mempty-        send peerSock serverMessage mempty-        pure r-    connect client addr-    send client clientMessage mempty--    clientMessageReceived <- wait serverRecv-    serverMessageReceived <- receive client 4096 mempty-    clientMessageReceived @?= clientMessage-    serverMessageReceived @?= serverMessage--testServerClientDatagram-    :: SocketAddress Unix-    -> SocketAddress Unix-    -> (Socket Unix Datagram Unix, Socket Unix Datagram Unix)-    -> IO ()-testServerClientDatagram sAddr cAddr (server, client) = do-    bind server sAddr-    bind client cAddr-    serverRecv <- async $ do-        (r, peerAddr) <- receiveFrom server 4096 mempty-        sendTo server serverMessage mempty peerAddr-        pure r-    sendTo client clientMessage mempty sAddr--    clientMessageReceived <- wait serverRecv-    serverMessageReceived <- receive client 4096 mempty-    clientMessageReceived @?= clientMessage-    serverMessageReceived @?= serverMessage