packages feed

network-3.2.10.0: Network/Socket.hs

{-# LANGUAGE CPP #-}

#include "HsNetDef.h"

-----------------------------------------------------------------------------

-----------------------------------------------------------------------------

-- In order to process this file, you need to have CALLCONV defined.

-- |
-- Module      :  Network.Socket
-- Copyright   :  (c) The University of Glasgow 2001
-- License     :  BSD-style (see the file libraries/network/LICENSE)
--
-- Maintainer  :  libraries@haskell.org
-- Stability   :  provisional
-- Portability :  portable
--
-- This is the main module of the network package supposed to be
-- used with either "Network.Socket.ByteString" or
-- "Network.Socket.ByteString.Lazy" for sending/receiving.
--
-- Here are two minimal example programs using the TCP/IP protocol:
--
-- * a server that echoes all data that it receives back
-- * a client using it
--
-- > -- Echo server program
-- > module Main (main) where
-- >
-- > import Control.Concurrent (forkFinally)
-- > import qualified Control.Exception as E
-- > import Control.Monad (unless, forever, void)
-- > import qualified Data.ByteString as S
-- > import qualified Data.List.NonEmpty as NE
-- > import Network.Socket
-- > import Network.Socket.ByteString (recv, sendAll)
-- >
-- > main :: IO ()
-- > main = runTCPServer Nothing "3000" talk
-- >   where
-- >     talk s = do
-- >         msg <- recv s 1024
-- >         unless (S.null msg) $ do
-- >           sendAll s msg
-- >           talk s
-- >
-- > -- from the "network-run" package.
-- > runTCPServer :: Maybe HostName -> ServiceName -> (Socket -> IO a) -> IO a
-- > runTCPServer mhost port server = do
-- >     addr <- resolve
-- >     E.bracket (open addr) close loop
-- >   where
-- >     resolve = do
-- >         let hints = defaultHints {
-- >                 addrFlags = [AI_PASSIVE]
-- >               , addrSocketType = Stream
-- >               }
-- >         NE.head <$> getAddrInfo (Just hints) mhost (Just port)
-- >     open addr = E.bracketOnError (openSocket addr) close $ \sock -> do
-- >         setSocketOption sock ReuseAddr 1
-- >         withFdSocket sock setCloseOnExecIfNeeded
-- >         bind sock $ addrAddress addr
-- >         listen sock 1024
-- >         return sock
-- >     loop sock = forever $ E.bracketOnError (accept sock) (close . fst)
-- >         $ \(conn, _peer) -> void $
-- >             -- 'forkFinally' alone is unlikely to fail thus leaking @conn@,
-- >             -- but 'E.bracketOnError' above will be necessary if some
-- >             -- non-atomic setups (e.g. spawning a subprocess to handle
-- >             -- @conn@) before proper cleanup of @conn@ is your case
-- >             forkFinally (server conn) (const $ gracefulClose conn 5000)
--
-- > {-# LANGUAGE OverloadedStrings #-}
-- > -- Echo client program
-- > module Main (main) where
-- >
-- > import qualified Control.Exception as E
-- > import qualified Data.ByteString.Char8 as C
-- > import qualified Data.List.NonEmpty as NE
-- > import Network.Socket
-- > import Network.Socket.ByteString (recv, sendAll)
-- >
-- > main :: IO ()
-- > main = runTCPClient "127.0.0.1" "3000" $ \s -> do
-- >     sendAll s "Hello, world!"
-- >     msg <- recv s 1024
-- >     putStr "Received: "
-- >     C.putStrLn msg
-- >
-- > -- from the "network-run" package.
-- > runTCPClient :: HostName -> ServiceName -> (Socket -> IO a) -> IO a
-- > runTCPClient host port client = do
-- >     addr <- resolve
-- >     E.bracket (open addr) close client
-- >   where
-- >     resolve = do
-- >         let hints = defaultHints { addrSocketType = Stream }
-- >         NE.head <$> getAddrInfo (Just hints) (Just host) (Just port)
-- >     open addr = E.bracketOnError (openSocket addr) close $ \sock -> do
-- >         connect sock $ addrAddress addr
-- >         return sock
--
-- The proper programming model is that one 'Socket' is handled by
-- a single thread. If multiple threads use one 'Socket' concurrently,
-- unexpected things would happen. There is one exception for multiple
-- threads vs a single 'Socket': one thread reads data from a 'Socket'
-- only and the other thread writes data to the 'Socket' only.
module Network.Socket (
    -- * Address information
    getAddrInfo,

    -- ** Types
    ServiceName,
    AddrInfo (..),
    defaultHints,

    -- ** Flags
    AddrInfoFlag (..),
    addrInfoFlagImplemented,

    -- * Socket operations
    connect,
    bind,
    listen,
    accept,

    -- ** Closing
    close,
    close',
    gracefulClose,
    shutdown,
    ShutdownCmd (..),

    -- * Socket options
    SocketOption (
        SockOpt,
        UnsupportedSocketOption,
        Debug,
        ReuseAddr,
        SoDomain,
        Type,
        SoProtocol,
        SoError,
        DontRoute,
        Broadcast,
        SendBuffer,
        RecvBuffer,
        KeepAlive,
        KeepInit,
        OOBInline,
        TimeToLive,
        MaxSegment,
        NoDelay,
        Cork,
        Linger,
        ReusePort,
        RecvLowWater,
        SendLowWater,
        RecvTimeOut,
        SendTimeOut,
        UseLoopBack,
        UserTimeout,
        IPv6Only,
        RecvIPv4TTL,
        RecvIPv4TOS,
        RecvIPv4PktInfo,
        DontFragment,
        RecvIPv6HopLimit,
        RecvIPv6TClass,
        RecvIPv6PktInfo,
        MulticastIF,
        MulticastTTL,
        MulticastLoop,
        AddMembership,
        DropMembership
    ),
    isSupportedSocketOption,
    whenSupported,
    getSocketOption,
    setSocketOption,

    -- ** General socket options
    StructLinger (..),
    SocketTimeout (..),
    getSockOpt,
    setSockOpt,

    -- ** Integrated socket options
    SockOptValue (..),
    setSockOptValue,

    -- * Socket
    Socket,
    socket,
    openSocket,
    withFdSocket,
    unsafeFdSocket,
    touchSocket,
    socketToFd,
    fdSocket,
    mkSocket,
    socketToHandle,

    -- ** Types of Socket
    SocketType (
        GeneralSocketType,
        UnsupportedSocketType,
        NoSocketType,
        Stream,
        Datagram,
        Raw,
        RDM,
        SeqPacket
    ),
    isSupportedSocketType,
    getSocketType,

    -- ** Family
    Family (
        GeneralFamily,
        UnsupportedFamily,
        AF_UNSPEC,
        AF_UNIX,
        AF_INET,
        AF_INET6,
        AF_IMPLINK,
        AF_PUP,
        AF_CHAOS,
        AF_NS,
        AF_NBS,
        AF_ECMA,
        AF_DATAKIT,
        AF_CCITT,
        AF_SNA,
        AF_DECnet,
        AF_DLI,
        AF_LAT,
        AF_HYLINK,
        AF_APPLETALK,
        AF_ROUTE,
        AF_NETBIOS,
        AF_NIT,
        AF_802,
        AF_ISO,
        AF_OSI,
        AF_NETMAN,
        AF_X25,
        AF_AX25,
        AF_OSINET,
        AF_GOSSIP,
        AF_IPX,
        Pseudo_AF_XTP,
        AF_CTF,
        AF_WAN,
        AF_SDL,
        AF_NETWARE,
        AF_NDD,
        AF_INTF,
        AF_COIP,
        AF_CNT,
        Pseudo_AF_RTIP,
        Pseudo_AF_PIP,
        AF_SIP,
        AF_ISDN,
        Pseudo_AF_KEY,
        AF_NATM,
        AF_ARP,
        Pseudo_AF_HDRCMPLT,
        AF_ENCAP,
        AF_LINK,
        AF_RAW,
        AF_RIF,
        AF_NETROM,
        AF_BRIDGE,
        AF_ATMPVC,
        AF_ROSE,
        AF_NETBEUI,
        AF_SECURITY,
        AF_PACKET,
        AF_ASH,
        AF_ECONET,
        AF_ATMSVC,
        AF_IRDA,
        AF_PPPOX,
        AF_WANPIPE,
        AF_BLUETOOTH,
        AF_CAN
    ),
    isSupportedFamily,
    packFamily,
    unpackFamily,

    -- ** Protocol number
    ProtocolNumber,
    defaultProtocol,

    -- * Basic socket address type
    SockAddr (..),
    isSupportedSockAddr,
    getPeerName,
    getSocketName,

    -- ** Host address
    HostAddress,
    hostAddressToTuple,
    tupleToHostAddress,

    -- ** Host address6
    HostAddress6,
    hostAddress6ToTuple,
    tupleToHostAddress6,

    -- ** Flow Info
    FlowInfo,

    -- ** Scope ID
    ScopeID,
    ifNameToIndex,
    ifIndexToName,

    -- ** Port number
    PortNumber,
    defaultPort,
    socketPortSafe,
    socketPort,

    -- * UNIX-domain socket
    isUnixDomainSocketAvailable,
    socketPair,
    sendFd,
    recvFd,
    getPeerCredential,

    -- * Name information
    getNameInfo,
    NameInfoFlag (..),

    -- * Host name information
    getHostName,
    HostName,

    -- * Low level

    -- ** socket operations
    setCloseOnExecIfNeeded,
    getCloseOnExec,
    setNonBlockIfNeeded,
    getNonBlock,

    -- ** Sending and receiving data
    sendBuf,
    recvBuf,
    recvBufNoWait,
    sendBufTo,
    recvBufFrom,

    -- ** Advanced IO
    sendBufMsg,
    recvBufMsg,
    MsgFlag (
        MSG_OOB,
        MSG_DONTROUTE,
        MSG_PEEK,
        MSG_EOR,
        MSG_TRUNC,
        MSG_CTRUNC,
        MSG_WAITALL
    ),

    -- ** Control message (ancillary data)
    Cmsg (..),
    CmsgId (
        CmsgId,
        CmsgIdIPv4TTL,
        CmsgIdIPv6HopLimit,
        CmsgIdIPv4TOS,
        CmsgIdIPv6TClass,
        CmsgIdIPv4PktInfo,
        CmsgIdIPv6PktInfo,
        CmsgIdFds,
        UnsupportedCmsgId
    ),

    -- ** APIs for control message
    lookupCmsg,
    filterCmsg,

    -- ** Class and types for control message
    ControlMessage (..),
    IPv4TTL (..),
    IPv6HopLimit (..),
    IPv4TOS (..),
    IPv6TClass (..),
    IPv4PktInfo (..),
    IPv6PktInfo (..),

    -- * Special constants
    maxListenQueue,

    -- * Event polling
    -- $eventpolling

    -- ** Giving up on a blocked operation
    withReadable,
    acceptWith,
    recvBufWith,
    recvBufFromWith,

    -- ** What a given-up operation can fail with
    isClosedSocketError,
    isTransientAcceptError,

    -- ** Waiting for readiness (POSIX only)
    waitReadSocketSTM,
    waitAndCancelReadSocketSTM,
    waitWriteSocketSTM,
    waitAndCancelWriteSocketSTM,

    -- * Deprecated
    withSocketsDo,

    -- * Multicast Group
    MulticastGroup (..),
)
where

import Network.Socket.Buffer hiding (
    recvBufFrom,
    recvBufMsg,
    sendBufMsg,
    sendBufTo,
 )
import Network.Socket.Cbits
import Network.Socket.Fcntl
import Network.Socket.Flag
import Network.Socket.Handle
import Network.Socket.If
import Network.Socket.Info
#if !defined(mingw32_HOST_OS)
import Network.Socket.Posix.HostName(getHostName)
#else
import Network.Socket.Win32.HostName(getHostName)
#endif
import Network.Socket.Internal
import Network.Socket.Name hiding (getPeerName, getSocketName)
import Network.Socket.Options
import Network.Socket.STM
import Network.Socket.Shutdown
import Network.Socket.SockAddr
import Network.Socket.Syscall hiding (accept, bind, connect)
import Network.Socket.Types
import Network.Socket.Unix
import Network.Socket.Wait (
    recvBufFromWith,
    isClosedSocketError,
    isTransientAcceptError,
    recvBufWith,
    withReadable,
 )
#if !defined(mingw32_HOST_OS)
import Network.Socket.Posix.Cmsg
#else
import Network.Socket.Win32.Cmsg
#endif

-- $eventpolling
--
-- A thread blocked on a socket is stopped here by being told, not by
-- having the socket closed under it and not by an asynchronous exception
-- thrown into it.  Each of 'withReadable', 'acceptWith', 'recvBufWith'
-- and 'recvBufFromWith' takes an 'Control.Concurrent.STM.STM' action
-- beside the operation; whichever settles first decides, 'Left' when the
-- caller gave up and 'Right' when the operation completed, and an
-- operation which has completed wins a tie.  They are for one reader at
-- a time, and 'withReadable' says what else they ask of the caller.
--
-- The other two ways are going away or gone.  A close ends a wait only
-- because the event manager tells the waiter so, which 'GHC.Conc.closeFdWith'
-- is to stop doing, and a descriptor number is reused; an asynchronous
-- exception does not reach a thread blocked in a socket call on Windows
-- at all.
--
-- A server loop which is told to stop, rather than having its listening
-- socket closed under it:
--
-- > stopping <- newTVarIO False
-- > -- the shutdown handler runs: atomically $ writeTVar stopping True
-- > let loop = acceptWith sock (check =<< readTVar stopping) >>= \case
-- >         Left () -> return ()
-- >         Right (conn, _) -> forkIO (serve conn) >> loop
--
-- A receive which gives up on a deadline, where 'System.Timeout.timeout'
-- cannot cut one short:
--
-- > late <- registerDelay (milliseconds * 1000)
-- > r <- recvBufWith s buf size (check =<< readTVar late)
--
-- The 'Control.Concurrent.STM.STM' action is run more than once, so it
-- has to be a test rather than something which takes what it reads.
--
-- Readiness, which these are built from on POSIX, is not available on
-- Windows: completion ports report that an operation finished, not that
-- one could be started.  The four readiness functions say so rather than
-- blocking for good, and what runs there instead is the operation itself,
-- on a thread of its own, cancelled with @CancelIoEx@ when the caller
-- gives up.  "Network.Socket.ByteString" has @recvWith@ and
-- @recvFromWith@ for 'Data.ByteString.ByteString'.