{-# OPTIONS_GHC -fno-warn-orphans #-}------------------------------------------------------------------------------- |-- Module : Network.StreamSocket-- Copyright : See LICENSE file-- License : BSD---- Maintainer : Ganesh Sittampalam <ganesh@earth.li>-- Stability : experimental-- Portability : non-portable (not tested)---- Socket Stream instance. Originally part of Gray's\/Bringert's HTTP module.---- * Changes by Robin Bate Boerop <robin@bateboerop.name>:-- - Made dependencies explicit in import statements.-- - Removed false dependencies in import statements.-- - Created separate module for instance Stream Socket.---- * Changes by Simon Foster:-- - Split module up into to separate Network.[Stream,TCP,HTTP] modules-------------------------------------------------------------------------------moduleNetwork.StreamSocket(handleSocketError ,myrecv )whereimportNetwork.Stream (Stream (..),ConnError (ErrorReset ,ErrorMisc ),Result )importNetwork.Socket(Socket,getSocketOption,shutdown,ShutdownCmd(ShutdownBoth),SocketOption(SoError))importNetwork.Socket.ByteString(send,recv)importqualifiedNetwork.Socket(close)importNetwork.HTTP.Base (catchIO )importNetwork.HTTP.Utils (fromUTF8BS ,toUTF8BS )importControl.Monad(liftM)importControl.ExceptionasException(IOException)importSystem.IO.Error(isEOFError)-- | Exception handler for socket operations.handleSocketError ::Socket->IOException->IO(Result a )handleSocketError :: Socket -> IOException -> IO (Result a)
handleSocketError Socket
sk IOException
e =doInt
se <-Socket -> SocketOption -> IO Int
getSocketOptionSocket
sk SocketOption
SoErrorcaseInt
se ofInt
0->IOException -> IO (Result a)
forall a. IOException -> IO a
ioErrorIOException
e Int
10054->Result a -> IO (Result a)
forall (m :: * -> *) a. Monad m => a -> m a
return(Result a -> IO (Result a)) -> Result a -> IO (Result a)
forall a b. (a -> b) -> a -> b
$ConnError -> Result a
forall a b. a -> Either a b
LeftConnError
ErrorReset -- resetInt
_->Result a -> IO (Result a)
forall (m :: * -> *) a. Monad m => a -> m a
return(Result a -> IO (Result a)) -> Result a -> IO (Result a)
forall a b. (a -> b) -> a -> b
$ConnError -> Result a
forall a b. a -> Either a b
Left(ConnError -> Result a) -> ConnError -> Result a
forall a b. (a -> b) -> a -> b
$String -> ConnError
ErrorMisc (String -> ConnError) -> String -> ConnError
forall a b. (a -> b) -> a -> b
$Int -> String
forall a. Show a => a -> String
showInt
se myrecv ::Socket->Int->IOStringmyrecv :: Socket -> Int -> IO String
myrecv Socket
sock Int
len =lethandler :: IOException -> IO [a]
handler IOException
e =ifIOException -> Bool
isEOFErrorIOException
e then[a] -> IO [a]
forall (m :: * -> *) a. Monad m => a -> m a
return[]elseIOException -> IO [a]
forall a. IOException -> IO a
ioErrorIOException
e inIO String -> (IOException -> IO String) -> IO String
forall a. IO a -> (IOException -> IO a) -> IO a
catchIO ((ByteString -> String) -> IO ByteString -> IO String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmapByteString -> String
fromUTF8BS (Socket -> Int -> IO ByteString
recvSocket
sock Int
len ))IOException -> IO String
forall a. IOException -> IO [a]
handler instanceStream SocketwherereadBlock :: Socket -> Int -> IO (Result String)
readBlock Socket
sk Int
n =Socket -> Int -> IO (Result String)
readBlockSocket Socket
sk Int
n readLine :: Socket -> IO (Result String)
readLine Socket
sk =Socket -> IO (Result String)
readLineSocket Socket
sk writeBlock :: Socket -> String -> IO (Result ())
writeBlock Socket
sk String
str =Socket -> String -> IO (Result ())
writeBlockSocket Socket
sk String
str close :: Socket -> IO ()
close Socket
sk =do-- This slams closed the connection (which is considered rude for TCP\/IP)Socket -> ShutdownCmd -> IO ()
shutdownSocket
sk ShutdownCmd
ShutdownBothSocket -> IO ()
Network.Socket.closeSocket
sk closeOnEnd :: Socket -> Bool -> IO ()
closeOnEnd Socket
_sk Bool
_=() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return()-- can't really deal with this, so do run the risk of leaking sockets here.readBlockSocket ::Socket->Int->IO(Result String)readBlockSocket :: Socket -> Int -> IO (Result String)
readBlockSocket Socket
sk Int
n =((String -> Result String) -> IO String -> IO (Result String)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftMString -> Result String
forall a b. b -> Either a b
Right(IO String -> IO (Result String))
-> IO String -> IO (Result String)
forall a b. (a -> b) -> a -> b
$Int -> IO String
fn Int
n )IO (Result String)
-> (IOException -> IO (Result String)) -> IO (Result String)
forall a. IO a -> (IOException -> IO a) -> IO a
`catchIO` (Socket -> IOException -> IO (Result String)
forall a. Socket -> IOException -> IO (Result a)
handleSocketError Socket
sk )wherefn :: Int -> IO String
fn Int
x =do{String
str <-Socket -> Int -> IO String
myrecv Socket
sk Int
x ;letlen :: Int
len =String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
lengthString
str ;ifInt
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<Int
x then(Int -> IO String
fn (Int
x Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
len )IO String -> (String -> IO String) -> IO String
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=\String
more ->String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return(String
str String -> String -> String
forall a. [a] -> [a] -> [a]
++String
more ))elseString -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
returnString
str }-- Use of the following function is discouraged.-- The function reads in one character at a time,-- which causes many calls to the kernel recv()-- hence causes many context switches.readLineSocket ::Socket->IO(Result String)readLineSocket :: Socket -> IO (Result String)
readLineSocket Socket
sk =((String -> Result String) -> IO String -> IO (Result String)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftMString -> Result String
forall a b. b -> Either a b
Right(IO String -> IO (Result String))
-> IO String -> IO (Result String)
forall a b. (a -> b) -> a -> b
$String -> IO String
fn String
"")IO (Result String)
-> (IOException -> IO (Result String)) -> IO (Result String)
forall a. IO a -> (IOException -> IO a) -> IO a
`catchIO` (Socket -> IOException -> IO (Result String)
forall a. Socket -> IOException -> IO (Result a)
handleSocketError Socket
sk )wherefn :: String -> IO String
fn String
str =doString
c <-Socket -> Int -> IO String
myrecv Socket
sk Int
1-- like eating through a straw.ifString -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
nullString
c Bool -> Bool -> Bool
||String
c String -> String -> Bool
forall a. Eq a => a -> a -> Bool
==String
"\n"thenString -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return(String -> String
forall a. [a] -> [a]
reverseString
str String -> String -> String
forall a. [a] -> [a] -> [a]
++String
c )elseString -> IO String
fn (String -> Char
forall a. [a] -> a
headString
c Char -> String -> String
forall a. a -> [a] -> [a]
:String
str )writeBlockSocket ::Socket->String->IO(Result ())writeBlockSocket :: Socket -> String -> IO (Result ())
writeBlockSocket Socket
sk String
str =((() -> Result ()) -> IO () -> IO (Result ())
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM() -> Result ()
forall a b. b -> Either a b
Right(IO () -> IO (Result ())) -> IO () -> IO (Result ())
forall a b. (a -> b) -> a -> b
$String -> IO ()
fn String
str )IO (Result ()) -> (IOException -> IO (Result ())) -> IO (Result ())
forall a. IO a -> (IOException -> IO a) -> IO a
`catchIO` (Socket -> IOException -> IO (Result ())
forall a. Socket -> IOException -> IO (Result a)
handleSocketError Socket
sk )wherefn :: String -> IO ()
fn []=() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return()fn String
x =Socket -> ByteString -> IO Int
sendSocket
sk (String -> ByteString
toUTF8BS String
x )IO Int -> (Int -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=\Int
i ->String -> IO ()
fn (Int -> String -> String
forall a. Int -> [a] -> [a]
dropInt
i String
x )

AltStyle によって変換されたページ (->オリジナル) /