{-# language BangPatterns #-} {-# language DataKinds #-} {-# language DeriveAnyClass #-} {-# language DerivingStrategies #-} {-# language DuplicateRecordFields #-} {-# language GADTs #-} {-# language KindSignatures #-} module Socket ( SocketException(..) , SocketUnrecoverableException(..) , Direction(..) , Interruptibility(..) , Forkedness(..) , cgetsockname , cgetsockopt , cclose , crecv , crecvfrom , cshutdown , negativeSliceLength , nonInternetSocketFamily , functionWithAccepted , functionWithConnection , functionWithListener , functionWithSocket , functionGracefulClose , socketAddressSize ) where import Control.Exception (Exception(..)) import Data.Kind (Type) import Foreign.C.Types (CInt) import qualified Data.List as L data Direction = Send | Receive data Interruptibility = Interruptible | Uninterruptible data Forkedness = Forked | Unforked -- | Represents any unexpected behaviors that a function working on a -- socket, connection, or listener can exhibit. data SocketException = SentMessageTruncated !Int -- ^ The datagram did not fit in the buffer. This can happen while -- sending. The field is the size of the number of bytes in the -- datagram that were successfully copied into the send buffer. | ReceivedMessageTruncated !Int -- ^ The datagram did not fit in the buffer. This can happen while -- receiving. The field is the original size of the datagram that -- was was truncated while copying it into the buffer. | SocketAddressSize -- ^ The socket address was not the expected size. This exception -- indicates a bug in this library or (less likely) in the -- operating system. | SocketAddressFamily !CInt -- ^ The socket address had an unexpected family. This exception -- indicates a bug in this library or (less likely) in the -- operating system. The int argument is the actual family -- found in the socket address. | OptionValueSize -- ^ The option value was not the expected size. This exception -- indicates a bug in this library or (less likely) in the -- operating system. | NegativeBytesRequested -- ^ The user requested a negative number of bytes in a call -- to a receive function. | ReceptionAbandoned -- ^ This happens when the @Unless@ variant of a function is -- used and the @STM@ action completes before the socket is -- ready for a read. | RemoteNotShutdown -- ^ The remote end sent more data when it was expected to send -- a shutdown. | RemoteShutdown -- ^ The remote end has shutdown its side of the full-duplex -- connection. This can happen @receive@ is called on a -- stream socket. This is not necessarily a bad thing. Many -- protocols use shutdown to indicate that no more data -- is available. These protocols can be contrasted with -- protocols that send a length representing a number of -- expected bytes. | ErrorCode !CInt -- ^ Any error code from the operating system that this library does -- not expect or recognize. Consult your operating system manual -- for details about the error code. deriving stock (Eq,Show) deriving anyclass (Exception) data SocketUnrecoverableException = SocketUnrecoverableException { modules :: String , function :: String , description :: [String] } deriving stock (Show,Eq) instance Exception SocketUnrecoverableException where displayException (SocketUnrecoverableException m f d) = m ++ "." ++ f ++ ": [" ++ L.intercalate "," d ++ "]" cgetsockname :: String cgetsockname = "getsockname" cgetsockopt :: String cgetsockopt = "getsockopt" cclose :: String cclose = "getsockname" crecv :: String crecv = "recv" crecvfrom :: String crecvfrom = "recvfrom" cshutdown :: String cshutdown = "shutdown" functionGracefulClose :: String functionGracefulClose = "gracefulClose" nonInternetSocketFamily :: String nonInternetSocketFamily = "non-internet socket family" negativeSliceLength :: String negativeSliceLength = "negative slice length" functionWithAccepted :: String functionWithAccepted = "withAccepted" functionWithConnection :: String functionWithConnection = "withConnection" functionWithListener :: String functionWithListener = "withListener" functionWithSocket :: String functionWithSocket = "withSocket" socketAddressSize :: String socketAddressSize = "socket address size"