{-# LINE1"Network/Socket/ByteString/IO.hsc"#-}{-# LANGUAGE RecordWildCards #-}{-# LANGUAGE OverloadedStrings #-}-- |-- Module : Network.Socket.ByteString-- Copyright : (c) Johan Tibell 2007-2010-- License : BSD-style---- Maintainer : johan.tibell@gmail.com-- Stability : stable-- Portability : portable---- This module provides access to the BSD /socket/ interface. This-- module is generally more efficient than the 'String' based network-- functions in 'Network.Socket'. For detailed documentation, consult-- your favorite POSIX socket reference. All functions communicate-- failures by converting the error number to 'System.IO.IOError'.---- This module is made to be imported with 'Network.Socket' like so:---- > import Network.Socket hiding (send, sendTo, recv, recvFrom)-- > import Network.Socket.ByteString--moduleNetwork.Socket.ByteString.IO(-- * Send data to a socketsend,sendAll,sendTo,sendAllTo-- ** Vectored I/O-- $vectored,sendMany,sendManyTo-- * Receive data from a socket,recv,recvFrom,waitWhen0)whereimportControl.Concurrent(threadWaitWrite,rtsSupportsBoundThreads)importData.ByteString(ByteString)importqualifiedData.ByteStringasBimportData.ByteString.Internal(createAndTrim)importData.ByteString.Unsafe(unsafeUseAsCStringLen)importForeign.Marshal.Alloc(allocaBytes)importForeign.Ptr(castPtr)importNetwork.Socket.BufferimportNetwork.Socket.ByteString.InternalimportNetwork.Socket.ImportsimportNetwork.Socket.Types{-# LINE59"Network/Socket/ByteString/IO.hsc"#-}importControl.Monad(zipWithM_)importForeign.Marshal.Array(allocaArray)importForeign.Marshal.Utils(with)importForeign.Ptr(Ptr,plusPtr)importForeign.Storable(Storable(..))importNetwork.Socket.InternalimportNetwork.Socket.ByteString.IOVec(IOVec(..))importNetwork.Socket.ByteString.MsgHdr(MsgHdr(..)){-# LINE69"Network/Socket/ByteString/IO.hsc"#-}-- ------------------------------------------------------------------------------ Sending-- | Send data to the socket. The socket must be connected to a-- remote socket. Returns the number of bytes sent. Applications are-- responsible for ensuring that all data has been sent.send::Socket-- ^ Connected socket->ByteString-- ^ Data to send->IOInt-- ^ Number of bytes sentsendsxs=unsafeUseAsCStringLenxs$\(str,len)->sendBufs(castPtrstr)lenwaitWhen0::Int->Socket->IO()waitWhen00s=whenrtsSupportsBoundThreads$withFdSockets$\fd->threadWaitWrite$fromIntegralfdwaitWhen0__=return()-- | Send data to the socket. The socket must be connected to a-- remote socket. Unlike 'send', this function continues to send data-- until either all data has been sent or an error occurs. On error,-- an exception is raised, and there is no way to determine how much-- data, if any, was successfully sent.sendAll::Socket-- ^ Connected socket->ByteString-- ^ Data to send->IO()sendAll_""=return()sendAllsbs=dosent<-sendsbswaitWhen0sentswhen(sent>=0)$sendAlls$B.dropsentbs-- | Send data to the socket. The recipient can be specified-- explicitly, so the socket need not be in a connected state.-- Returns the number of bytes sent. Applications are responsible for-- ensuring that all data has been sent.sendTo::SocketAddresssa=>Socket-- ^ Socket->ByteString-- ^ Data to send->sa-- ^ Recipient address->IOInt-- ^ Number of bytes sentsendTosxssa=unsafeUseAsCStringLenxs$\(str,len)->sendBufTosstrlensa-- | Send data to the socket. The recipient can be specified-- explicitly, so the socket need not be in a connected state. Unlike-- 'sendTo', this function continues to send data until either all-- data has been sent or an error occurs. On error, an exception is-- raised, and there is no way to determine how much data, if any, was-- successfully sent.sendAllTo::SocketAddresssa=>Socket-- ^ Socket->ByteString-- ^ Data to send->sa-- ^ Recipient address->IO()sendAllTo_""_=return()sendAllTosxssa=dosent<-sendTosxssawaitWhen0sentswhen(sent>=0)$sendAllTos(B.dropsentxs)sa-- | Send data to the socket. The socket must be in a connected-- state. The data is sent as if the parts have been concatenated.-- This function continues to send data until either all data has been-- sent or an error occurs. On error, an exception is raised, and-- there is no way to determine how much data, if any, was-- successfully sent.sendMany::Socket-- ^ Connected socket->[ByteString]-- ^ Data to send->IO(){-# LINE140"Network/Socket/ByteString/IO.hsc"#-}sendMany_[]=return()sendManyscs=dosent<-sendManyInnerwaitWhen0sentswhen(sent>=0)$sendManys$remainingChunkssentcswheresendManyInner=fmapfromIntegral.withIOVeccs$\(iovsPtr,iovsLen)->withFdSockets$\fd->doletlen=fromIntegral$miniovsLen(1024){-# LINE150"Network/Socket/ByteString/IO.hsc"#-}throwSocketErrorWaitWrites"Network.Socket.ByteString.sendMany"$c_writevfdiovsPtrlen{-# LINE155"Network/Socket/ByteString/IO.hsc"#-}-- | Send data to the socket. The recipient can be specified-- explicitly, so the socket need not be in a connected state. The-- data is sent as if the parts have been concatenated. This function-- continues to send data until either all data has been sent or an-- error occurs. On error, an exception is raised, and there is no-- way to determine how much data, if any, was successfully sent.sendManyTo::Socket-- ^ Socket->[ByteString]-- ^ Data to send->SockAddr-- ^ Recipient address->IO(){-# LINE167"Network/Socket/ByteString/IO.hsc"#-}sendManyTo_[]_=return()sendManyToscsaddr=dosent<-fromIntegral<$>sendManyToInnerwaitWhen0sentswhen(sent>=0)$sendManyTos(remainingChunkssentcs)addrwheresendManyToInner=withSockAddraddr$\addrPtraddrSize->withIOVeccs$\(iovsPtr,iovsLen)->doletmsgHdr=MsgHdraddrPtr(fromIntegraladdrSize)iovsPtr(fromIntegraliovsLen)withFdSockets$\fd->withmsgHdr$\msgHdrPtr->throwSocketErrorWaitWrites"Network.Socket.ByteString.sendManyTo"$c_sendmsgfdmsgHdrPtr0{-# LINE186"Network/Socket/ByteString/IO.hsc"#-}-- ------------------------------------------------------------------------------ Receiving-- | Receive data from the socket. The socket must be in a connected-- state. This function may return fewer bytes than specified. If-- the message is longer than the specified length, it may be-- discarded depending on the type of socket. This function may block-- until a message arrives.---- Considering hardware and network realities, the maximum number of bytes to-- receive should be a small power of 2, e.g., 4096.---- For TCP sockets, a zero length return value means the peer has-- closed its half side of the connection.recv::Socket-- ^ Connected socket->Int-- ^ Maximum number of bytes to receive->IOByteString-- ^ Data receivedrecvsnbytes|nbytes<0=ioError(mkInvalidRecvArgError"Network.Socket.ByteString.recv")|otherwise=createAndTrimnbytes$\ptr->recvBufsptrnbytes-- | Receive data from the socket. The socket need not be in a-- connected state. Returns @(bytes, address)@ where @bytes@ is a-- 'ByteString' representing the data received and @address@ is a-- 'SockAddr' representing the address of the sending socket.---- If the first return value is zero, it means EOF.recvFrom::SocketAddresssa=>Socket-- ^ Socket->Int-- ^ Maximum number of bytes to receive->IO(ByteString,sa)-- ^ Data received and sender addressrecvFromsocknbytes=allocaBytesnbytes$\ptr->do(len,sockaddr)<-recvBufFromsockptrnbytesstr<-B.packCStringLen(ptr,len)return(str,sockaddr)-- ------------------------------------------------------------------------------ Not exported{-# LINE228"Network/Socket/ByteString/IO.hsc"#-}-- | Suppose we try to transmit a list of chunks @cs@ via a gathering write-- operation and find that @n@ bytes were sent. Then @remainingChunks n cs@ is-- list of chunks remaining to be sent.remainingChunks::Int->[ByteString]->[ByteString]remainingChunks_[]=[]remainingChunksi(x:xs)|i<len=B.dropix:xs|otherwise=leti'=i-lenini'`seq`remainingChunksi'xswherelen=B.lengthx-- | @withIOVec cs f@ executes the computation @f@, passing as argument a pair-- consisting of a pointer to a temporarily allocated array of pointers to-- IOVec made from @cs@ and the number of pointers (@length cs@).-- /Unix only/.withIOVec::[ByteString]->((PtrIOVec,Int)->IOa)->IOawithIOVeccsf=allocaArraycsLen$\aPtr->dozipWithM_pokeIov(ptrsaPtr)csf(aPtr,csLen)wherecsLen=lengthcsptrs=iterate(`plusPtr`sizeOf(undefined::IOVec))pokeIovptrs=unsafeUseAsCStringLens$\(sPtr,sLen)->pokeptr$IOVecsPtr(fromIntegralsLen){-# LINE255"Network/Socket/ByteString/IO.hsc"#-}