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'.