packages feed

tcp-streams 0.2.1.0 → 0.2.2.0

raw patch · 5 files changed

+58/−31 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- System.IO.Streams.OpenSSL: CertificateVerifyFail :: CertificateVerifyFail
- System.IO.Streams.OpenSSL: data CertificateVerifyFail
- System.IO.Streams.OpenSSL: instance GHC.Classes.Eq System.IO.Streams.OpenSSL.CertificateVerifyFail
- System.IO.Streams.OpenSSL: instance GHC.Exception.Exception System.IO.Streams.OpenSSL.CertificateVerifyFail
- System.IO.Streams.OpenSSL: instance GHC.Show.Show System.IO.Streams.OpenSSL.CertificateVerifyFail

Files

ChangeLog.md view
@@ -1,5 +1,9 @@ # Revision history for tcp-simple +## 0.2.2.0++* Clean and document exception behavior.+ ## 0.2.1.0  * Fix broken document.
System/IO/Streams/OpenSSL.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE DeriveDataTypeable #-}  -- | This module provides convenience functions for interfacing @io-streams@ -- with @HsOpenSSL@. @ssl/SSL@ here stand for @HsOpenSSL@ library, not the@@ -7,7 +6,8 @@ -- sending is unbuffered, anything write into 'OutputStream' will be immediately -- send to underlying socket. ----- You should handle 'IOError' when you read/write these streams for safety.+-- The same exceptions rule which applied to TCP apply here, with addtional+-- 'SSL.SomeSSLException` to be watched out. -- -- Be sure to use 'withOpenSSL' wrap your operation before using any functions here. -- otherwise a segmentation fault will happen.@@ -22,11 +22,10 @@   , withOpenSSL   , sslToStreams   , closeSSL-  , CertificateVerifyFail(..)   ) where  import qualified Control.Exception     as E-import           Control.Monad         (void, unless)+import           Control.Monad         (unless, void) import           Data.ByteString.Char8 (ByteString) import qualified Data.ByteString.Char8 as S import           Network.Socket        (HostName, PortNumber, Socket)@@ -38,7 +37,6 @@ import           System.IO.Streams     (InputStream, OutputStream) import qualified System.IO.Streams     as Streams import qualified System.IO.Streams.TCP as TCP-import           Data.Typeable         (Typeable)  bUFSIZ :: Int bUFSIZ = 32752@@ -57,6 +55,7 @@     input = do         s <- SSL.read ssl bUFSIZ         return $! if S.null s then Nothing else Just s+        `E.onException` return Nothing      output Nothing  = return ()     output (Just s) = SSL.write ssl s@@ -70,8 +69,7 @@ -- @('HostName', 'PortNumber')@ combination. -- -- this function will try to verify server's identity,--- a 'CertificateVerifyFail' will be thrown if fail.--- it may throw 'SSL.SomeSSLException' too.+-- a 'SSL.ProtocolError' will be thrown if fail. -- connect :: SSLContext           -- ^ SSL context. See the @HsOpenSSL@                                 -- documentation for information on creating@@ -92,16 +90,17 @@             verified = case subname of                 Just subname' -> maybe False (== subname') cnname                 Nothing       -> maybe False (matchDomain host) cnname-        unless (trusted && verified) (E.throwIO CertificateVerifyFail)+        unless (trusted && verified) (E.throwIO $ SSL.ProtocolError "fail to verify certificate")         (is, os) <- sslToStreams ssl         return (is, os, ssl)    where     matchDomain :: String -> String -> Bool     matchDomain n1 n2 =-        let n1' = (take 2 . reverse) (splitDot n1)-            n2' = (take 2 . reverse) (splitDot n2)-        in n1' == n2'+        let n1' = reverse (splitDot n1)+            n2' = reverse (splitDot n2)+            cmp src target = src == "*" || src == target+        in and (zipWith cmp n1' n2')     splitDot :: String -> [String]     splitDot "" = [""]     splitDot x  =@@ -146,9 +145,7 @@     E.bracketOnError (SSL.connection ctx sock') closeSSL $ \ ssl -> do         SSL.accept ssl         trusted <- SSL.getVerifyResult ssl-        unless trusted (E.throwIO CertificateVerifyFail)+        unless trusted (E.throwIO $ SSL.ProtocolError "fail to verify certificate")         (is, os) <- sslToStreams ssl         return (is, os, ssl, sockAddr) -data CertificateVerifyFail = CertificateVerifyFail deriving (Show, Eq, Typeable)-instance E.Exception CertificateVerifyFail
System/IO/Streams/TCP.hs view
@@ -4,8 +4,15 @@ -- with raw tcp. the default receive buffer size is 4096. sending is unbuffered, -- anything write into 'OutputStream' will be immediately send to underlying socket. ----- You should handle 'IOError' when you read/write these streams for safety.--- Note, `TCP_NODELAY` are enabled by default. you can use 'N.setSocketOption' to adjust.+-- Reading 'InputStream' will block until message comming, for example+-- `System.IO.Streams.ByteString.readExactly 1024` will block until 1024 bytes are available.+--+-- When socket is closed, the 'InputStream' will be closed too(further reading 'Nothing'),+-- no exception will be thrown. You still should handle 'IOError' when you write to  'OutputStream' for safety,+-- but no exception doesn't essentially mean a successful write, especially under bad network+-- environment(broken wire for example).+--+-- `TCP_NODELAY` are enabled by default. you can use 'N.setSocketOption' to adjust.  module System.IO.Streams.TCP (     -- * tcp client@@ -18,22 +25,23 @@   , accept   ) where +import           Control.Concurrent.MVar   (withMVar) import qualified Control.Exception         as E-import           Control.Monad             (void)-import           Data.ByteString.Char8     (ByteString)-import           Network.Socket            (HostName, PortNumber, Socket)+import           Control.Monad             (unless, void)+import           Data.ByteString           (ByteString)+import qualified Data.ByteString           as B+import           Network.Socket            (HostName, PortNumber, Socket (..)) import qualified Network.Socket            as N+import qualified Network.Socket.ByteString as NB import           System.IO.Streams         (InputStream, OutputStream) import qualified System.IO.Streams         as Stream-import           System.IO.Streams.Network (socketToStreamsWithBufferSize) - bUFSIZ :: Int bUFSIZ = 4096  -- | resolve a 'HostName'/'PortNumber' combination. ----- This function throws an IO exception when resolve fail.+-- This function throws an 'IOError' when resolve fail. -- resolveAddrInfo :: HostName -> PortNumber -> IO (N.Family, N.SocketType, N.ProtocolNumber, N.SockAddr) resolveAddrInfo host port = do@@ -74,7 +82,6 @@                      )  - -- | connect to remote tcp server. -- -- You may need to use 'E.bracket' pattern to enusre 'N.Socket' 's safety.@@ -82,11 +89,7 @@ connect :: HostName             -- ^ hostname to connect to         -> PortNumber           -- ^ port number to connect to         -> IO (InputStream ByteString, OutputStream ByteString, Socket)-connect host port = do-    sock <- connectSocket host port-    (is, os) <- socketToStreamsWithBufferSize bUFSIZ sock-    return (is, os, sock)-+connect host port = connectWithBufferSize host port bUFSIZ  -- | connect to remote tcp server with a receive buffer size. --@@ -143,10 +146,31 @@ -- | accept a new connection from remote client, return a 'InputStream' / 'OutputStream' pair, -- a new underlying 'Socket', and remote 'N.SockAddr',you should call 'bindAndListen' first. ----- This function will block current thread if there's no connection comming.+-- This function will block if there's no connection comming. -- accept :: Socket -> IO (InputStream ByteString, OutputStream ByteString, N.Socket, N.SockAddr) accept sock = do     (sock', sockAddr) <- N.accept sock     (is, os) <- socketToStreamsWithBufferSize bUFSIZ sock'     return (is, os, sock', sockAddr)++socketToStreamsWithBufferSize+    :: Int                      -- ^ how large the receive buffer should be+    -> Socket                   -- ^ network socket+    -> IO (InputStream ByteString, OutputStream ByteString)+socketToStreamsWithBufferSize bufsiz sock@(MkSocket _ _ _ _ statusMVar) = do+    is <- Stream.makeInputStream input+    os <- Stream.makeOutputStream output+    return (is, os)++  where+    input = withMVar statusMVar $ \ status ->+        case status of+            N.Connected -> do+                s <- NB.recv sock bufsiz+                return $! if B.null s then Nothing else Just s+                `E.onException` return Nothing+            _ -> return Nothing++    output Nothing  = return ()+    output (Just s) = unless (B.null s) (NB.sendAll sock s)
System/IO/Streams/TLS.hs view
@@ -5,7 +5,8 @@ -- sending is unbuffered, anything write into 'OutputStream' will be -- immediately send to underlying socket. ----- You should handle 'IOError' when you read/write these streams for safety.+-- The same exceptions rule which applied to TCP apply here, with addtional+-- 'TLS.TLSException' to be watched out. -- module System.IO.Streams.TLS (     -- * client@@ -46,6 +47,7 @@     input = do         s <- TLS.recvData ctx         return $! if B.null s then Nothing else Just s+        `E.onException` return Nothing      output Nothing  = return ()     output (Just s) = TLS.sendData ctx (fromStrict s)
tcp-streams.cabal view
@@ -1,5 +1,5 @@ name:                tcp-streams-version:             0.2.1.0+version:             0.2.2.0 synopsis:            One stop solution for tcp client and server with tls support. description:         One stop solution for tcp client and server with tls support. license:             BSD3