{-# LINE 1 "Network/Sendfile/Linux.hsc" #-}{-# LANGUAGE ForeignFunctionInterface #-}{-# LINE 2 "Network/Sendfile/Linux.hsc" #-}moduleNetwork.Sendfile.Linux(sendfile,sendfileFd,sendfileWithHeader,sendfileFdWithHeader)whereimportControl.ApplicativeimportControl.ExceptionimportControl.MonadimportData.ByteStringasBimportData.ByteString.UnsafeimportData.IntimportForeign.C.Error(eAGAIN,getErrno,throwErrno)importForeign.C.TypesimportForeign.Marshal(alloca)importForeign.Ptr(Ptr)importForeign.Storable(poke)importGHC.Conc(threadWaitWrite)importNetwork.Sendfile.TypesimportNetwork.SocketimportNetwork.Socket.Internal(throwSocketErrorIfMinus1RetryMayBlock)importSystem.Posix.FilesimportSystem.Posix.IOimportSystem.Posix.Types{-# LINE 30 "Network/Sendfile/Linux.hsc" #-}{-# LINE 31 "Network/Sendfile/Linux.hsc" #-}------------------------------------------------------------------ |-- Simple binding for sendfile() of Linux.-- Used system calls:---- - EntireFile -- open(), stat(), sendfile(), and close()---- - PartOfFile -- open(), sendfile(), and close()---- If the size of the file is unknown when sending the entire file,-- specifying PartOfFile is much faster.---- The fourth action argument is called when a file is sent as chunks.-- Chucking is inevitable if the socket is non-blocking (this is the-- default) and the file is large. The action is called after a chunk-- is sent and bofore waiting the socket to be ready for writing.sendfile::Socket->FilePath->FileRange->IO()->IO()sendfilesockpathrangehook=bracketsetupteardown$\fd->sendfileFdsockfdrangehookwheresetup=openFdpathReadOnlyNothingdefaultFileFlagsteardown=closeFd-- |-- Simple binding for sendfile() of Linux.-- Used system calls:---- - EntireFile -- stat() and sendfile()---- - PartOfFile -- sendfile()---- If the size of the file is unknown when sending the entire file,-- specifying PartOfFile is much faster.---- The fourth action argument is called when a file is sent as chunks.-- Chucking is inevitable if the socket is non-blocking (this is the-- default) and the file is large. The action is called after a chunk-- is sent and bofore waiting the socket to be ready for writing.sendfileFd::Socket->Fd->FileRange->IO()->IO()sendfileFdsockfdrangehook=alloca$\offp->caserangeofEntireFile->dopokeoffp0-- System call is very slow. Use PartOfFile instead.len<-fileSize<$>getFdStatusfdletlen'=fromIntegrallensendloopdstfdoffplen'hookPartOfFileofflen->dopokeoffp(fromIntegraloff)letlen'=fromIntegrallensendloopdstfdoffplen'hookwheredst=Fd$fdSocketsocksendloop::Fd->Fd->PtrCOff->CSize->IO()->IO()sendloopdstsrcoffplenhook=dobytes<-c_sendfiledstsrcoffplencasebytesof-1->doerrno<-getErrnoiferrno==eAGAINthenlooplenelsethrowErrno"Network.SendFile.Linux.sendloop"0->return()-- the file is truncated_->loop(len-fromIntegralbytes)whereloop0=return()loopleft=dohook-- Parallel IO manager use edge-trigger mode.-- So, calling threadWaitWrite only when errnor is eAGAIN.errno<-getErrnowhen(errno==eAGAIN)$threadWaitWritedstsendloopdstsrcoffplefthook-- Dst Src in order. take careforeignimportccallunsafe"sendfile"c_sendfile::Fd->Fd->PtrCOff->CSize->IO(Int32){-# LINE 114 "Network/Sendfile/Linux.hsc" #-}------------------------------------------------------------------ |-- Simple binding for send() and sendfile() of Linux.-- Used system calls:---- - EntireFile -- send(), open(), stat(), sendfile(), and close()---- - PartOfFile -- send(), open(), sendfile(), and close()---- The fifth header is sent with send() + the MSG_MORE flag. If the-- file is small enough, the header and the file is send in a single-- TCP packet.---- If the size of the file is unknown when sending the entire file,-- specifying PartOfFile is much faster.---- The fourth action argument is called when a file is sent as chunks.-- Chucking is inevitable if the socket is non-blocking (this is the-- default) and the file is large. The action is called after a chunk-- is sent and bofore waiting the socket to be ready for writing.sendfileWithHeader::Socket->FilePath->FileRange->IO()->[ByteString]->IO()sendfileWithHeadersockpathrangehookhdr=do-- Copying is much faster than syscall.sendAllMsgMoresock$B.concathdrsendfilesockpathrangehook-- |-- Simple binding for send() and sendfile() of Linux.-- Used system calls:---- - EntireFile -- send(), stat() and sendfile()---- - PartOfFile -- send() and sendfile()---- The fifth header is sent with send() + the MSG_MORE flag. If the-- file is small enough, the header and the file is send in a single-- TCP packet.---- If the size of the file is unknown when sending the entire file,-- specifying PartOfFile is much faster.---- The fourth action argument is called when a file is sent as chunks.-- Chucking is inevitable if the socket is non-blocking (this is the-- default) and the file is large. The action is called after a chunk-- is sent and bofore waiting the socket to be ready for writing.sendfileFdWithHeader::Socket->Fd->FileRange->IO()->[ByteString]->IO()sendfileFdWithHeadersockfdrangehookhdr=do-- Copying is much faster than syscall.sendAllMsgMoresock$B.concathdrsendfileFdsockfdrangehooksendAllMsgMore::Socket->ByteString->IO()sendAllMsgMoresockbs=dosent<-sendMsgMoresockbswhen(sent<B.lengthbs)$sendAllMsgMoresock(B.dropsentbs)sendMsgMore::Socket->ByteString->IOIntsendMsgMore(MkSockets____)xs=unsafeUseAsCStringLenxs$\(str,len)->fromIntegral<$>throwSocketErrorIfMinus1RetryMayBlock"sendMsgMore"(threadWaitWrite(fromIntegrals))(c_sendsstr(fromIntegrallen)(32768)){-# LINE 181 "Network/Sendfile/Linux.hsc" #-}foreignimportccallunsafe"send"c_send::CInt->PtrCChar->CSize->CInt->IO(Int32){-# LINE 184 "Network/Sendfile/Linux.hsc" #-}