diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,10 @@
 # Revision history for Z-IO
 
+## 0.1.1.2  -- 2020-09-25
+
+* Fix macOS build problem caused by missing zconf.h.
+* Add more tests(TCP, IPC).
+
 ## 0.1.1.0  -- 2020-09-19
 
 * Add stream utilities to `Z.IO.Buffered`.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -4,7 +4,9 @@
 
 ## Z-IO
 
-[![Linux Build Status](https://img.shields.io/travis/haskell-z/z-io/master.svg?label=Linux%20build)](https://travis-ci.org/haskell-z/z-io)
+[![Linux Build Status](https://github.com/haskell-Z/z-io/workflows/ubuntu-ci/badge.svg)](https://github.com/haskell-Z/z-io/actions)
+
+[![MacOS Build Status](https://github.com/haskell-Z/z-io/workflows/oxs-ci/badge.svg)](https://github.com/haskell-Z/z-io/actions)
 
 This package provides basic IO operations:
 
diff --git a/Z-IO.cabal b/Z-IO.cabal
--- a/Z-IO.cabal
+++ b/Z-IO.cabal
@@ -1,5 +1,5 @@
 name:                       Z-IO
-version:                    0.1.1.1
+version:                    0.1.1.2
 synopsis:                   Simple and high performance IO toolkit for Haskell
 description:                Simple and high performance IO toolkit for Haskell, including
                             file system, network, ipc and more!
@@ -19,13 +19,6 @@
                             README.md
                             LICENSE
 
-                            include/hs_uv.h
-                            cbits/hs_uv_base.c
-                            cbits/hs_uv_stream.c
-                            cbits/hs_uv_udp.c
-                            cbits/hs_uv_file.c
-                            cbits/hs_uv_dns.c
-
                             -- zlib C sources
                             third_party/zlib/crc32.h
                             third_party/zlib/inffast.h 
@@ -103,13 +96,6 @@
     default: False
     manual: True
 
-flag integer-simple
-    description:
-        Use the [simple integer library](http://hackage.haskell.org/package/integer-simple)
-        instead of [integer-gmp](http://hackage.haskell.org/package/integer-gmp)
-    default: False
-    manual: False
-
 library
     exposed-modules:        Z.IO.FileSystem
                             Z.IO.FileSystem.Threaded
@@ -141,27 +127,23 @@
                           , time                    >= 1.8 && < 2.0
                           , stm                     == 2.5.*
 
-    if flag(integer-simple)
-        cpp-options:        -DINTEGER_SIMPLE
-        build-depends:      integer-simple >= 0.1 && < 0.5
-    else
-        cpp-options:        -DINTEGER_GMP
-        build-depends:      integer-gmp >= 0.2 && < 1.1
-
     include-dirs:           include
                             third_party/zlib
 
     includes:               hs_uv.h
+                            zlib.h
+                            zconf.h
 
     install-includes:       hs_uv.h 
                             zlib.h
+                            zconf.h
 
     cc-options:             -march=native
     c-sources:              cbits/hs_uv_base.c
+                            cbits/hs_uv_dns.c
+                            cbits/hs_uv_file.c
                             cbits/hs_uv_stream.c
                             cbits/hs_uv_udp.c
-                            cbits/hs_uv_file.c
-                            cbits/hs_uv_dns.c
                             cbits/hs_zlib.c
 
                             third_party/zlib/adler32.c
@@ -237,7 +219,7 @@
         if flag(no-pkg-config)
             extra-libraries:    uv
         else
-            pkgconfig-depends:  libuv >= 1.14
+            pkgconfig-depends:  libuv >= 1.32
 
     default-language:       Haskell2010
     build-tools:            hsc2hs, hspec-discover
@@ -261,19 +243,14 @@
                           , zlib
                           , bytestring
 
-    other-modules:          Z.IO.FileSystemSpec
+    other-modules:          Z.Compression.ZlibSpec
                             Z.IO.FileSystem.ThreadedSpec
+                            Z.IO.FileSystemSpec
+                            Z.IO.Network.UDPSpec
+                            Z.IO.Network.TCPSpec
+                            -- Z.IO.Network.IPCSpec
                             Z.IO.LowResTimerSpec
                             Z.IO.ResourceSpec
-                            Z.IO.UDPSpec
 
     ghc-options:            -threaded
     default-language:       Haskell2010
-
-    if flag(integer-simple)
-        cpp-options: -DINTEGER_SIMPLE
-        build-depends: integer-simple >= 0.1 && < 0.5
-    else
-        cpp-options: -DINTEGER_GMP
-        build-depends: integer-gmp >= 0.2 && < 1.1
-
diff --git a/Z/Compression/Zlib.hsc b/Z/Compression/Zlib.hsc
--- a/Z/Compression/Zlib.hsc
+++ b/Z/Compression/Zlib.hsc
@@ -167,7 +167,7 @@
             zflush zs bufRef
 
 -- | Compress some bytes.
-compress :: CompressConfig -> V.Bytes -> V.Bytes
+compress :: HasCallStack => CompressConfig -> V.Bytes -> V.Bytes
 compress conf input = unsafePerformIO $ do
     ref <- newIORef []
     (write, flush) <- compressSink conf (\ x -> modifyIORef' ref (x:), return ())
@@ -266,7 +266,7 @@
 
     
 -- | Decompress some bytes.
-decompress :: DecompressConfig -> V.Bytes -> V.Bytes
+decompress :: HasCallStack => DecompressConfig -> V.Bytes -> V.Bytes
 decompress conf input = V.concat . unsafePerformIO $ do
      collectSource =<< decompressSource conf =<< sourceFromList [input]
 
diff --git a/Z/IO/Network/IPC.hs b/Z/IO/Network/IPC.hs
--- a/Z/IO/Network/IPC.hs
+++ b/Z/IO/Network/IPC.hs
@@ -68,12 +68,13 @@
     uvm <- liftIO getUVManager
     client <- initIPCStream uvm
     let hdl = uvsHandle client
-    liftIO . withCBytes tname $ \ tname_p -> do
+    liftIO $ do
         forM_ cname $ \ cname' ->
             withCBytes cname' $ \ cname_p ->
                 -- bind is safe without withUVManager
                 throwUVIfMinus_ (uv_pipe_bind hdl cname_p)
-        void . withUVRequest uvm $ \ _ -> hs_uv_pipe_connect hdl tname_p
+        withCBytes tname $ \ tname_p -> do
+            void . withUVRequest uvm $ \ _ -> hs_uv_pipe_connect hdl tname_p
     return client
 
 --------------------------------------------------------------------------------
@@ -105,11 +106,14 @@
 startIPCServer IPCServerConfig{..} = do
     let backLog = max ipcListenBacklog 128
     serverUVManager <- getUVManager
-    withResource (initIPCStream serverUVManager) $ \ (UVStream serverHandle serverSlot _ _) ->
+    withResource (initIPCStream serverUVManager) $ \ (UVStream serverHandle serverSlot _ _) -> do
+        withCBytes ipcListenName $ \ name_p -> do
+            throwUVIfMinus_ (uv_pipe_bind serverHandle name_p)
         bracket
             (throwOOMIfNull $ hs_uv_accept_check_alloc serverHandle)
             hs_uv_accept_check_close $
             \ check -> do
+
 -- The buffer passing of accept is a litte complicated here, to get maximum performance,
 -- we do batch accepting. i.e. recv multiple client inside libuv's event loop:
 --
@@ -127,51 +131,51 @@
 -- we allocate a new uv_check_t for given uv_stream_t, with predefined checking callback
 -- see hs_accept_check_cb in hs_uv_stream.c
                 throwUVIfMinus_ $ hs_uv_accept_check_init check
-                withCBytes ipcListenName $ \ name_p -> do
-                    m <- getBlockMVar serverUVManager serverSlot
-                    acceptBuf <- newPinnedPrimArray backLog
-                    let acceptBufPtr = coerce (mutablePrimArrayContents acceptBuf :: Ptr UVFD)
+                m <- getBlockMVar serverUVManager serverSlot
 -- Step 2.
 -- we allocate a buffer to hold accepted FDs, pass it just like a normal reading buffer.
-                    withUVManager' serverUVManager $ do
-                        -- We use buffersize as accepted fd counter, so we write 0 here
-                        pokeBufferTable serverUVManager serverSlot acceptBufPtr (backLog-1)
-                        throwUVIfMinus_ (uv_pipe_bind serverHandle name_p)
-                        throwUVIfMinus_ (hs_uv_listen serverHandle (max 4 (fromIntegral backLog)))
+-- then we can start listening.
+                acceptBuf <- newPinnedPrimArray backLog
+                let acceptBufPtr = coerce (mutablePrimArrayContents acceptBuf :: Ptr UVFD)
 
-                    forever $ do
-                        -- wait until accept some FDs
-                        !acceptCountDown <- takeMVar m
+                withUVManager' serverUVManager $ do
+                    -- We use buffersize as accepted fd counter, so we write 0 here
+                    pokeBufferTable serverUVManager serverSlot acceptBufPtr (backLog-1)
+                    throwUVIfMinus_ (hs_uv_listen serverHandle (max 4 (fromIntegral backLog)))
+
+                forever $ do
+                    -- wait until accept some FDs
+                    !acceptCountDown <- takeMVar m
 -- Step 3.
--- Copy buffer, fetch accepted FDs and fork worker threads.
+-- After uv loop finishes, if we got some FDs, copy the FD buffer, fetch accepted FDs and fork worker threads.
 
-                        -- we lock uv manager here in case of next uv_run overwrite current accept buffer
-                        acceptBufCopy <- withUVManager' serverUVManager $ do
-                            _ <- tryTakeMVar m
-                            pokeBufferTable serverUVManager serverSlot acceptBufPtr (backLog-1)
+                    -- we lock uv manager here in case of next uv_run overwrite current accept buffer
+                    acceptBufCopy <- withUVManager' serverUVManager $ do
+                        _ <- tryTakeMVar m
+                        pokeBufferTable serverUVManager serverSlot acceptBufPtr (backLog-1)
 
-                            -- if acceptCountDown count to -1, we should resume on haskell side
-                            when (acceptCountDown == -1) (hs_uv_listen_resume serverHandle)
+                        -- if acceptCountDown count to -1, we should resume on haskell side
+                        when (acceptCountDown == -1) (hs_uv_listen_resume serverHandle)
 
-                            -- copy accepted FDs
-                            let acceptCount = backLog - 1 - acceptCountDown
-                            acceptBuf' <- newPrimArray acceptCount
-                            copyMutablePrimArray acceptBuf' 0 acceptBuf (acceptCountDown+1) acceptCount
-                            unsafeFreezePrimArray acceptBuf'
+                        -- copy accepted FDs
+                        let acceptCount = backLog - 1 - acceptCountDown
+                        acceptBuf' <- newPrimArray acceptCount
+                        copyMutablePrimArray acceptBuf' 0 acceptBuf (acceptCountDown+1) acceptCount
+                        unsafeFreezePrimArray acceptBuf'
 
-                        -- fork worker thread
-                        forM_ [0..sizeofPrimArray acceptBufCopy-1] $ \ i -> do
-                            let fd = indexPrimArray acceptBufCopy i
-                            if fd < 0
-                            -- minus fd indicate a server error and we should close server
-                            then throwUVIfMinus_ (return fd)
-                            -- It's important to use the worker thread's mananger instead of server's one!
-                            else void . forkBa $ do
-                                uvm <- getUVManager
-                                withResource (initUVStream (\ loop hdl -> do
-                                    throwUVIfMinus_ (uv_pipe_init loop hdl 0)
-                                    throwUVIfMinus_ (hs_uv_pipe_open hdl fd)) uvm) $ \ uvs -> do
-                                    ipcServerWorker uvs
+                    -- fork worker thread
+                    forM_ [0..sizeofPrimArray acceptBufCopy-1] $ \ i -> do
+                        let fd = indexPrimArray acceptBufCopy i
+                        if fd < 0
+                        -- minus fd indicate a server error and we should close server
+                        then throwUVIfMinus_ (return fd)
+                        -- It's important to use the worker thread's mananger instead of server's one!
+                        else void . forkBa $ do
+                            uvm <- getUVManager
+                            withResource (initUVStream (\ loop hdl -> do
+                                throwUVIfMinus_ (uv_pipe_init loop hdl 0)
+                                throwUVIfMinus_ (hs_uv_pipe_open hdl fd)) uvm) $ \ uvs -> do
+                                ipcServerWorker uvs
 
 --------------------------------------------------------------------------------
 
diff --git a/Z/IO/Network/SocketAddr.hsc b/Z/IO/Network/SocketAddr.hsc
--- a/Z/IO/Network/SocketAddr.hsc
+++ b/Z/IO/Network/SocketAddr.hsc
@@ -47,8 +47,8 @@
   , inet6Loopback
   , inet6AddrToTuple
   , tupleToInet6Addr
-  , FlowInfo(..)
-  , ScopeID(..)
+  , FlowInfo
+  , ScopeID
   -- * port numbber
   , PortNumber(..)
   , portAny
@@ -82,7 +82,6 @@
 
 import           Data.Bits
 import qualified Data.List                as List
-import           Data.Ratio
 import           Data.Typeable
 import           Foreign
 import           Foreign.C
@@ -330,6 +329,13 @@
 instance UnalignedAccess Inet6Addr where
     unalignedSize   = UnalignedSize (#size struct in6_addr)
 
+    indexBA p off = 
+        let a = indexBA p (off + s6_addr_offset + 0)
+            b = indexBA p  (off + s6_addr_offset + 4)
+            c = indexBA p  (off + s6_addr_offset + 8)
+            d = indexBA p  (off + s6_addr_offset + 12)
+        in Inet6Addr (getBE a) (getBE b) (getBE c) (getBE d)
+
     peekMBA p off = do
         a <- peekMBA p (off + s6_addr_offset + 0)
         b <- peekMBA p  (off + s6_addr_offset + 4)
@@ -520,6 +526,7 @@
 
 instance UnalignedAccess PortNumber where
    unalignedSize = UnalignedSize 2
+   indexBA p off = PortNumber . ntohs $ indexBA p off
    pokeMBA p off (PortNumber po) = pokeMBA p off (htons po)
    peekMBA p off = PortNumber . ntohs <$> peekMBA p off
     
diff --git a/Z/IO/Network/TCP.hs b/Z/IO/Network/TCP.hs
--- a/Z/IO/Network/TCP.hs
+++ b/Z/IO/Network/TCP.hs
@@ -29,6 +29,10 @@
   , defaultTCPServerConfig
   , startTCPServer
   , getTCPPeerName
+  -- * Internal helper
+  , setTCPNoDelay
+  , setTCPKeepAlive
+  , initTCPStream
   ) where
 
 import           Control.Concurrent.MVar
@@ -70,16 +74,17 @@
     uvm <- liftIO getUVManager
     client <- initTCPStream uvm
     let hdl = uvsHandle client
-    liftIO . withSocketAddr tcpRemoteAddr $ \ targetPtr -> do
+    liftIO $ do
         forM_ tcpClientAddr $ \ tcpClientAddr' ->
-            withSocketAddr tcpClientAddr' $ \ localPtr ->
+            withSocketAddrUnsafe tcpClientAddr' $ \ localPtr ->
                 -- bind is safe without withUVManager
                 throwUVIfMinus_ (uv_tcp_bind hdl localPtr 0)
         -- nodelay is safe without withUVManager
         when tcpClientNoDelay . throwUVIfMinus_ $ uv_tcp_nodelay hdl 1
         when (tcpClientKeepAlive > 0) . throwUVIfMinus_ $
             uv_tcp_keepalive hdl 1 tcpClientKeepAlive
-        void . withUVRequest uvm $ \ _ -> hs_uv_tcp_connect hdl targetPtr
+        withSocketAddrUnsafe tcpRemoteAddr $ \ targetPtr -> do
+            void . withUVRequest uvm $ \ _ -> hs_uv_tcp_connect hdl targetPtr
     return client
 
 --------------------------------------------------------------------------------
@@ -115,7 +120,10 @@
 startTCPServer TCPServerConfig{..} = do
     let backLog = max tcpListenBacklog 128
     serverUVManager <- getUVManager
-    withResource (initTCPStream serverUVManager) $ \ (UVStream serverHandle serverSlot _ _) ->
+    withResource (initTCPStream serverUVManager) $ \ (UVStream serverHandle serverSlot _ _) -> do
+        -- bind is safe without withUVManager
+        withSocketAddrUnsafe tcpListenAddr $ \ addrPtr -> do
+            throwUVIfMinus_ (uv_tcp_bind serverHandle addrPtr 0)
         bracket
             (throwOOMIfNull $ hs_uv_accept_check_alloc serverHandle)
             hs_uv_accept_check_close $
@@ -137,56 +145,55 @@
 -- we allocate a new uv_check_t for given uv_stream_t, with predefined checking callback
 -- see hs_accept_check_cb in hs_uv_stream.c
                 throwUVIfMinus_ $ hs_uv_accept_check_init check
-                withSocketAddr tcpListenAddr $ \ addrPtr -> do
-                    m <- getBlockMVar serverUVManager serverSlot
-                    acceptBuf <- newPinnedPrimArray backLog
-                    let acceptBufPtr = coerce (mutablePrimArrayContents acceptBuf :: Ptr UVFD)
+                m <- getBlockMVar serverUVManager serverSlot
 -- Step 2.
 -- we allocate a buffer to hold accepted FDs, pass it just like a normal reading buffer.
-                    withUVManager' serverUVManager $ do
-                        -- We use buffersize as accepted fd count(count backwards)
-                        pokeBufferTable serverUVManager serverSlot acceptBufPtr (backLog-1)
-                        throwUVIfMinus_ (uv_tcp_bind serverHandle addrPtr 0)
-                        throwUVIfMinus_ (hs_uv_listen serverHandle (max 4 (fromIntegral backLog)))
+-- then we can start listening.
+                acceptBuf <- newPinnedPrimArray backLog
+                let acceptBufPtr = coerce (mutablePrimArrayContents acceptBuf :: Ptr UVFD)
+                withUVManager' serverUVManager $ do
+                    -- We use buffersize as accepted fd count(count backwards)
+                    pokeBufferTable serverUVManager serverSlot acceptBufPtr (backLog-1)
+                    throwUVIfMinus_ (hs_uv_listen serverHandle (max 4 (fromIntegral backLog)))
 
-                    forever $ do
-                        -- wait until accept some FDs
-                        !acceptCountDown <- takeMVar m
+                forever $ do
+                    -- wait until accept some FDs
+                    !acceptCountDown <- takeMVar m
 -- Step 3.
--- Copy buffer, fetch accepted FDs and fork worker threads.
+-- After uv loop finishes, if we got some FDs, copy the FD buffer, fetch accepted FDs and fork worker threads.
 
-                        -- we lock uv manager here in case of next uv_run overwrite current accept buffer
-                        acceptBufCopy <- withUVManager' serverUVManager $ do
-                            _ <- tryTakeMVar m
-                            pokeBufferTable serverUVManager serverSlot acceptBufPtr (backLog-1)
+                    -- we lock uv manager here in case of next uv_run overwrite current accept buffer
+                    acceptBufCopy <- withUVManager' serverUVManager $ do
+                        _ <- tryTakeMVar m
+                        pokeBufferTable serverUVManager serverSlot acceptBufPtr (backLog-1)
 
-                            -- if acceptCountDown count to -1, we should resume on haskell side
-                            when (acceptCountDown == -1) (hs_uv_listen_resume serverHandle)
+                        -- if acceptCountDown count to -1, we should resume on haskell side
+                        when (acceptCountDown == -1) (hs_uv_listen_resume serverHandle)
 
-                            -- copy accepted FDs
-                            let acceptCount = backLog - 1 - acceptCountDown
-                            acceptBuf' <- newPrimArray acceptCount
-                            copyMutablePrimArray acceptBuf' 0 acceptBuf (acceptCountDown+1) acceptCount
-                            unsafeFreezePrimArray acceptBuf'
+                        -- copy accepted FDs
+                        let acceptCount = backLog - 1 - acceptCountDown
+                        acceptBuf' <- newPrimArray acceptCount
+                        copyMutablePrimArray acceptBuf' 0 acceptBuf (acceptCountDown+1) acceptCount
+                        unsafeFreezePrimArray acceptBuf'
 
-                        -- fork worker thread
-                        forM_ [0..sizeofPrimArray acceptBufCopy-1] $ \ i -> do
-                            let fd = indexPrimArray acceptBufCopy i
-                            if fd < 0
-                            -- minus fd indicate a server error and we should close server
-                            then throwUVIfMinus_ (return fd)
-                            -- It's important to use the worker thread's mananger instead of server's one!
-                            else void . forkBa $ do
-                                uvm <- getUVManager
-                                withResource (initUVStream (\ loop hdl -> do
-                                    throwUVIfMinus_ (uv_tcp_init loop hdl)
-                                    throwUVIfMinus_ (hs_uv_tcp_open hdl fd)) uvm) $ \ uvs -> do
-                                    when tcpServerWorkerNoDelay . throwUVIfMinus_ $
-                                        -- safe without withUVManager
-                                        uv_tcp_nodelay (uvsHandle uvs) 1
-                                    when (tcpServerWorkerKeepAlive > 0) . throwUVIfMinus_ $
-                                        uv_tcp_keepalive (uvsHandle uvs) 1 tcpServerWorkerKeepAlive
-                                    tcpServerWorker uvs
+                    -- fork worker thread
+                    forM_ [0..sizeofPrimArray acceptBufCopy-1] $ \ i -> do
+                        let fd = indexPrimArray acceptBufCopy i
+                        if fd < 0
+                        -- minus fd indicate a server error and we should close server
+                        then throwUVIfMinus_ (return fd)
+                        -- It's important to use the worker thread's mananger instead of server's one!
+                        else void . forkBa $ do
+                            uvm <- getUVManager
+                            withResource (initUVStream (\ loop hdl -> do
+                                throwUVIfMinus_ (uv_tcp_init loop hdl)
+                                throwUVIfMinus_ (hs_uv_tcp_open hdl fd)) uvm) $ \ uvs -> do
+                                when tcpServerWorkerNoDelay . throwUVIfMinus_ $
+                                    -- safe without withUVManager
+                                    uv_tcp_nodelay (uvsHandle uvs) 1
+                                when (tcpServerWorkerKeepAlive > 0) . throwUVIfMinus_ $
+                                    uv_tcp_keepalive (uvsHandle uvs) 1 tcpServerWorkerKeepAlive
+                                tcpServerWorker uvs
 
 --------------------------------------------------------------------------------
 
@@ -211,13 +218,13 @@
 -- | Get the current address to which the handle is bound.
 getTCPSockName :: HasCallStack => UVStream -> IO SocketAddr
 getTCPSockName uvs = do
-    withSocketAddrStorage $ \ paddr ->
+    withSocketAddrStorageUnsafe $ \ paddr ->
         void $ withPrimUnsafe (fromIntegral sizeOfSocketAddrStorage :: CInt) $ \ plen ->
-            throwUVIfMinus_ (uv_udp_getsockname (uvsHandle uvs) paddr plen)
+            throwUVIfMinus_ (uv_tcp_getsockname (uvsHandle uvs) paddr plen)
 
 -- | Get the address of the peer connected to the handle.
 getTCPPeerName :: HasCallStack => UVStream -> IO SocketAddr
 getTCPPeerName uvs = do
-    withSocketAddrStorage $ \ paddr ->
+    withSocketAddrStorageUnsafe $ \ paddr ->
         void $ withPrimUnsafe (fromIntegral sizeOfSocketAddrStorage :: CInt) $ \ plen ->
-            throwUVIfMinus_ (uv_udp_getpeername (uvsHandle uvs) paddr plen)
+            throwUVIfMinus_ (uv_tcp_getpeername (uvsHandle uvs) paddr plen)
diff --git a/Z/IO/Network/UDP.hs b/Z/IO/Network/UDP.hs
--- a/Z/IO/Network/UDP.hs
+++ b/Z/IO/Network/UDP.hs
@@ -130,13 +130,15 @@
 
             -- init uv struct
             (do throwUVIfMinus_ (uv_udp_init loop hdl)
-                -- bind the socket if address is available
-                forM_ maddr $ \ (addr, flag) ->
-                    withSocketAddr addr $ \ p ->
-                        throwUVIfMinus_ (uv_udp_bind hdl p flag)
                 ) `onException` hs_uv_handle_free hdl
             return (hdl, slot)
 
+        -- bind the socket if address is available
+        -- This is safe without lock UV manager
+        forM_ maddr $ \ (addr, flag) ->
+            withSocketAddrUnsafe addr $ \ p ->
+                throwUVIfMinus_ (uv_udp_bind hdl p flag)
+
         sbuf <- A.newPinnedPrimArray (max 0 sbsiz)
         closed <- newIORef False
         return (UDP hdl slot uvm sbuf closed))
@@ -154,7 +156,7 @@
 getSockName :: HasCallStack => UDP -> IO SocketAddr
 getSockName udp@(UDP hdl _ _ _ _) = do
     checkUDPClosed udp
-    withSocketAddrStorage $ \ paddr ->
+    withSocketAddrStorageUnsafe $ \ paddr ->
         void $ withPrimUnsafe (fromIntegral sizeOfSocketAddrStorage :: CInt) $ \ plen ->
             throwUVIfMinus_ (uv_udp_getsockname hdl paddr plen)
 
@@ -166,7 +168,7 @@
 connectUDP :: HasCallStack => UDP -> SocketAddr -> IO ConnectedUDP
 connectUDP udp@(UDP hdl _ _ _ _) addr = do
     checkUDPClosed udp
-    withSocketAddr addr $ \ paddr ->
+    withSocketAddrUnsafe addr $ \ paddr ->
         throwUVIfMinus_ (uv_udp_connect hdl paddr)
     return (ConnectedUDP udp)
 
@@ -174,14 +176,14 @@
 disconnectUDP :: HasCallStack => ConnectedUDP -> IO UDP
 disconnectUDP (ConnectedUDP udp@(UDP hdl _ _ _ _)) = do
     checkUDPClosed udp
-    throwUVIfMinus_ (uv_udp_connect hdl nullPtr)
+    throwUVIfMinus_ (uv_udp_disconnect hdl nullPtr)
     return udp
 
 -- | Get the remote IP and port on 'ConnectedUDP'.
 getPeerName :: HasCallStack => ConnectedUDP -> IO SocketAddr
 getPeerName (ConnectedUDP udp@(UDP hdl _ _ _ _)) = do
     checkUDPClosed udp
-    withSocketAddrStorage $ \ paddr ->
+    withSocketAddrStorageUnsafe $ \ paddr ->
         void $ withPrimUnsafe (fromIntegral sizeOfSocketAddrStorage :: CInt) $ \ plen ->
             throwUVIfMinus_ (uv_udp_getpeername hdl paddr plen)
 
@@ -198,8 +200,9 @@
     copyPrimArray sbuf 0 ba s la
     withMutablePrimArrayContents sbuf $ \ pbuf -> do
         m <- withUVManager' uvm $ do
-            reqSlot <- getUVSlot uvm (hs_uv_udp_send hdl nullPtr pbuf la)
+            reqSlot <- getUVSlot uvm (hs_uv_udp_send_connected hdl pbuf la)
             reqMVar <- getBlockMVar uvm reqSlot
+            -- since we locked uv manager here, it won't affect next event
             _ <- tryTakeMVar reqMVar
             return reqMVar
         -- we can't cancel uv_udp_send_t in current libuv
@@ -221,20 +224,21 @@
     lb <- getSizeofMutablePrimArray sbuf
     when (la > lb) (throwUVIfMinus_ (return UV_EMSGSIZE))
     copyPrimArray sbuf 0 ba s la
-    withSocketAddr addr $ \ paddr ->
-        withMutablePrimArrayContents sbuf $ \ pbuf -> do
-            m <- withUVManager' uvm $ do
-                reqSlot <- getUVSlot uvm (hs_uv_udp_send hdl paddr pbuf la)
-                reqMVar <- getBlockMVar uvm reqSlot
-                _ <- tryTakeMVar reqMVar
-                return reqMVar
-            -- we can't cancel uv_udp_send_t in current libuv
-            -- and disaster will happen if buffer got collected.
-            -- so we have to turn to uninterruptibleMask_'s help.
-            -- i.e. sendUDP is an uninterruptible operation.
-            -- OS will guarantee writing a socket will not
-            -- hang forever anyway.
-            throwUVIfMinus_  (uninterruptibleMask_ $ takeMVar m)
+    withMutablePrimArrayContents sbuf $ \ pbuf -> do
+        m <- withUVManager' uvm $ do
+            reqSlot <- withSocketAddrUnsafe addr $ \ paddr ->
+                getUVSlot uvm (hs_uv_udp_send hdl paddr pbuf la)
+            reqMVar <- getBlockMVar uvm reqSlot
+            -- since we locked uv manager here, it won't affect next event
+            _ <- tryTakeMVar reqMVar
+            return reqMVar
+        -- we can't cancel uv_udp_send_t in current libuv
+        -- and disaster will happen if buffer got collected.
+        -- so we have to turn to uninterruptibleMask_'s help.
+        -- i.e. sendUDP is an uninterruptible operation.
+        -- OS will guarantee writing a socket will not
+        -- hang forever anyway.
+        throwUVIfMinus_  (uninterruptibleMask_ $ takeMVar m)
 
 -- | Set IP multicast loop flag. Makes multicast packets loop back to local sockets.
 setMulticastLoop :: HasCallStack => UDP -> Bool -> IO ()
diff --git a/Z/IO/UV/FFI.hsc b/Z/IO/UV/FFI.hsc
--- a/Z/IO/UV/FFI.hsc
+++ b/Z/IO/UV/FFI.hsc
@@ -149,14 +149,14 @@
 foreign import ccall unsafe uv_tcp_init_ex :: Ptr UVLoop -> Ptr UVHandle -> CUInt -> IO CInt
 foreign import ccall unsafe uv_tcp_nodelay :: Ptr UVHandle -> CInt -> IO CInt
 foreign import ccall unsafe uv_tcp_keepalive :: Ptr UVHandle -> CInt -> CUInt -> IO CInt
-foreign import ccall unsafe uv_tcp_getsockname :: Ptr UVHandle -> Ptr SocketAddr -> CInt -> IO CInt
-foreign import ccall unsafe uv_tcp_getpeername :: Ptr UVHandle -> Ptr SocketAddr -> CInt -> IO CInt
+foreign import ccall unsafe uv_tcp_getsockname :: Ptr UVHandle -> MBA## SocketAddr -> MBA## CInt -> IO CInt
+foreign import ccall unsafe uv_tcp_getpeername :: Ptr UVHandle -> MBA## SocketAddr -> MBA## CInt -> IO CInt
 
 uV_TCP_IPV6ONLY :: CUInt
 uV_TCP_IPV6ONLY = #{const UV_TCP_IPV6ONLY}
 
-foreign import ccall unsafe uv_tcp_bind :: Ptr UVHandle -> Ptr SocketAddr -> CUInt -> IO CInt
-foreign import ccall unsafe hs_uv_tcp_connect :: Ptr UVHandle -> Ptr SocketAddr -> IO UVSlotUnSafe
+foreign import ccall unsafe uv_tcp_bind :: Ptr UVHandle -> MBA## SocketAddr -> CUInt -> IO CInt
+foreign import ccall unsafe hs_uv_tcp_connect :: Ptr UVHandle -> MBA## SocketAddr -> IO UVSlotUnSafe
 foreign import ccall unsafe hs_set_socket_reuse :: Ptr UVHandle -> IO CInt
 
 foreign import ccall unsafe hs_uv_pipe_open :: Ptr UVHandle -> UVFD -> IO CInt
@@ -169,7 +169,7 @@
 foreign import ccall unsafe uv_udp_init :: Ptr UVLoop -> Ptr UVHandle -> IO CInt
 foreign import ccall unsafe uv_udp_init_ex :: Ptr UVLoop -> Ptr UVHandle -> CUInt -> IO CInt
 foreign import ccall unsafe uv_udp_open :: Ptr UVHandle -> UVFD -> IO CInt
-foreign import ccall unsafe uv_udp_bind :: Ptr UVHandle -> Ptr SocketAddr -> UVUDPFlag -> IO CInt
+foreign import ccall unsafe uv_udp_bind :: Ptr UVHandle -> MBA## SocketAddr -> UVUDPFlag -> IO CInt
 
 newtype UVMembership = UVMembership CInt deriving (Show, Eq, Ord)
 
@@ -191,6 +191,9 @@
 pattern UV_UDP_PARTIAL = #{const UV_UDP_PARTIAL}
 
 foreign import ccall unsafe uv_udp_connect
+    :: Ptr UVHandle -> MBA## SocketAddr -> IO CInt
+-- | Just pass null pointer as SocketAddr to disconnect
+foreign import ccall unsafe "uv_udp_connect" uv_udp_disconnect
     :: Ptr UVHandle -> Ptr SocketAddr -> IO CInt
 
 foreign import ccall unsafe uv_udp_set_membership ::
@@ -207,11 +210,13 @@
 foreign import ccall unsafe hs_uv_udp_recv_start :: Ptr UVHandle -> IO CInt
 foreign import ccall unsafe uv_udp_recv_stop :: Ptr UVHandle -> IO CInt
 foreign import ccall unsafe hs_uv_udp_send 
-    :: Ptr UVHandle -> Ptr SocketAddr -> Ptr Word8 -> Int -> IO UVSlotUnSafe
+    :: Ptr UVHandle -> MBA## SocketAddr -> Ptr Word8 -> Int -> IO UVSlotUnSafe
+foreign import ccall unsafe hs_uv_udp_send_connected
+    :: Ptr UVHandle -> Ptr Word8 -> Int -> IO UVSlotUnSafe
 foreign import ccall unsafe uv_udp_getsockname 
-    :: Ptr UVHandle -> Ptr SocketAddr -> MBA## CInt -> IO CInt
+    :: Ptr UVHandle -> MBA## SocketAddr -> MBA## CInt -> IO CInt
 foreign import ccall unsafe uv_udp_getpeername
-    :: Ptr UVHandle -> Ptr SocketAddr -> MBA## CInt -> IO CInt
+    :: Ptr UVHandle -> MBA## SocketAddr -> MBA## CInt -> IO CInt
 
 
 --------------------------------------------------------------------------------
diff --git a/Z/IO/UV/Manager.hs b/Z/IO/UV/Manager.hs
--- a/Z/IO/UV/Manager.hs
+++ b/Z/IO/UV/Manager.hs
@@ -330,6 +330,7 @@
     (slot, m) <- withUVManager uvm $ \ loop -> mask_ $ do
         slot <- getUVSlot uvm (f loop)
         m <- getBlockMVar uvm slot
+        -- since we locked uv manager here, it won't affect next event
         _ <- tryTakeMVar m
         return (slot, m)
     g =<< (takeMVar m `onException` cancelUVReq uvm slot no_extra_cleanup)
diff --git a/cbits/hs_uv_udp.c b/cbits/hs_uv_udp.c
--- a/cbits/hs_uv_udp.c
+++ b/cbits/hs_uv_udp.c
@@ -126,3 +126,8 @@
     } else return slot;
 
 }
+
+HsInt hs_uv_udp_send_connected(uv_udp_t* handle, char* buf, HsInt buf_siz){
+    return hs_uv_udp_send(handle, NULL, buf, buf_siz);
+}
+
diff --git a/include/hs_uv.h b/include/hs_uv.h
--- a/include/hs_uv.h
+++ b/include/hs_uv.h
@@ -294,6 +294,7 @@
 // udp
 
 int hs_uv_udp_recv_start(uv_udp_t* handle);
+HsInt hs_uv_udp_send_connected(uv_udp_t* handle, char* buf, HsInt buf_siz);
 HsInt hs_uv_upd_send(uv_udp_t* handle, const struct sockaddr* addr, char* buf, HsInt buf_siz);
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/test/Z/Compression/ZlibSpec.hs b/test/Z/Compression/ZlibSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Z/Compression/ZlibSpec.hs
@@ -0,0 +1,77 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Z.Compression.ZlibSpec where
+
+import           Control.Monad
+import           Data.IORef
+import           Data.ByteString       as B
+import           Data.ByteString.Lazy  as BL
+import           Z.Data.Vector         as V
+import           Z.Compression.Zlib
+import qualified Codec.Compression.Zlib as TheZlib
+import           Z.IO.Buffered
+import           Test.QuickCheck
+import           Test.QuickCheck.Function
+import           Test.QuickCheck.Property
+import           Test.Hspec
+import           Test.Hspec.QuickCheck
+import           Test.HUnit
+
+
+spec :: Spec
+spec = describe "zlib" $ do
+
+    describe "decompress . compress === id" . modifyMaxSize (*50) $ do
+        prop "decompress . compress === id" $ \ xs  -> do
+            decompress defaultDecompressConfig
+                (compress defaultCompressConfig (V.pack xs)) === V.pack xs
+
+        prop "decompress . compress === id(with dict)" $ \ xs  -> do
+            let dict = "aabbccdd"
+            decompress defaultDecompressConfig{decompressDictionary = dict}
+                (compress defaultCompressConfig{compressDictionary = dict} (V.pack xs))
+                    === V.pack xs
+
+        prop "compress === TheZlib.compress" $ \ xs  -> do
+            V.unpack (compress defaultCompressConfig (V.pack xs)) ===
+                BL.unpack (TheZlib.compressWith TheZlib.defaultCompressParams (BL.pack xs))
+
+        prop "compress === TheZlib.compress(with dict)" $ \ xs  -> do
+            V.unpack (compress defaultCompressConfig{compressDictionary = "aabbccdd"} (V.pack xs)) ===
+                BL.unpack (TheZlib.compressWith
+                    TheZlib.defaultCompressParams{TheZlib.compressDictionary = Just "aabbccdd" }
+                        (BL.pack xs))
+
+        prop "decompressSink . compressSource === id" $ \ xss -> do
+            ref <- newIORef []
+            (write, flush) <- compressSink defaultCompressConfig
+                (\ x -> modifyIORef' ref (x:), return ())
+
+            let vs = Prelude.map V.pack xss
+
+            forM_ vs write
+            flush
+
+            source <- sourceFromList . Prelude.reverse =<< readIORef ref
+            vs' <- collectSource =<< decompressSource defaultDecompressConfig source
+
+            V.concat vs @=? V.concat vs'
+
+        prop "decompressSink . compressSource === id(with dict)" $ \ xss -> do
+            let dict = "aabbccdd"
+            ref <- newIORef []
+            (write, flush) <- compressSink defaultCompressConfig{compressDictionary = dict}
+
+                (\ x -> modifyIORef' ref (x:), return ())
+
+            let vs = Prelude.map V.pack xss
+
+            forM_ vs write
+            flush
+
+            source <- sourceFromList . Prelude.reverse =<< readIORef ref
+            vs' <- collectSource =<< decompressSource
+                defaultDecompressConfig{decompressDictionary = dict} source
+
+            V.concat vs @=? V.concat vs'
+
diff --git a/test/Z/IO/Network/TCPSpec.hs b/test/Z/IO/Network/TCPSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Z/IO/Network/TCPSpec.hs
@@ -0,0 +1,52 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Z.IO.Network.TCPSpec where
+
+import           Control.Concurrent
+import           Control.Monad
+import           Data.Bits
+import           Z.Data.Vector         as V
+import           Z.Data.Vector.Base    as V
+import           Data.List               as List
+import           Foreign.Marshal.Array
+import           Foreign.Ptr
+import           Z.IO.Exception
+import           Z.IO.Resource
+import           Z.IO.Buffered
+import           Z.IO.Network
+import           Test.Hspec
+import           Test.HUnit
+
+spec :: Spec
+spec = describe "TCP operations" $ do
+    it "roundtrip test" $ do
+        let testMsg = V.cycleN 256 "abc"
+            longMsg = V.cycleN 2048 "abcdefg"
+            addr = SocketAddrInet 12345 inetLoopback
+
+        serverThread <- forkIO $ startTCPServer defaultTCPServerConfig{
+                tcpListenAddr = addr
+            ,   tcpServerWorker = \ tcp -> do
+                    i <- newBufferedInput defaultChunkSize tcp
+                    o <- newBufferedOutput defaultChunkSize tcp
+                    forever $ readBuffer i >>= writeBuffer o >> flushBuffer o
+            }
+
+        threadDelay 100000
+
+        replicateM_ 1000 . forkIO $
+            withResource (initTCPClient defaultTCPClientConfig{tcpRemoteAddr = addr}) $ \ tcp -> do
+                i <- newBufferedInput defaultChunkSize tcp
+                o <- newBufferedOutput defaultChunkSize tcp
+
+                replicateM_ 1000 . forkIO $ do
+                    writeBuffer o testMsg >> flushBuffer o
+                    testMsg' <- readAll' i
+                    testMsg' @=? testMsg
+
+                replicateM_ 1000 . forkIO $ do
+                    writeBuffer o longMsg >> flushBuffer o
+                    longMsg' <- readAll' i
+                    longMsg' @=? longMsg
+
+        killThread serverThread
diff --git a/test/Z/IO/Network/UDPSpec.hs b/test/Z/IO/Network/UDPSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Z/IO/Network/UDPSpec.hs
@@ -0,0 +1,53 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Z.IO.Network.UDPSpec where
+
+import           Control.Concurrent
+import           Control.Monad
+import           Data.Bits
+import           Z.Data.Vector         as V
+import           Z.Data.Vector.Base    as V
+import           Data.List               as List
+import           Foreign.Marshal.Array
+import           Foreign.Ptr
+import           Z.IO.Exception
+import           Z.IO.Resource
+import           Z.IO.Network
+import           Test.Hspec
+import           Test.HUnit
+
+spec :: Spec
+spec = describe "UDP operations" $ do
+    it "roundtrip test" $ do
+        let testMsg = V.replicate 256 48
+            longMsg = V.replicate 2048 48
+            addr = SocketAddrInet 12345 inetLoopback
+        withResource (initUDP defaultUDPConfig{udpSendMsgSize = 2048}) $ \ c ->
+            withResource (initUDP defaultUDPConfig{udpLocalAddr = Just (addr,UV_UDP_DEFAULT)}) $ \ s -> do
+                forkIO $ sendUDP c addr testMsg
+                [(_, partial, rcvMsg)]<- recvUDP defaultUDPRecvConfig s
+                partial @=? False
+                rcvMsg @=? testMsg
+
+                threadDelay 100000
+
+                forkIO $ sendUDP c addr longMsg
+                [(_, partial, rcvMsg)]<- recvUDP defaultUDPRecvConfig s
+                partial @=? True
+
+    it "UDP sending addr test" $ do
+        let testMsg = V.replicate 256 48
+            addr = SocketAddrInet 12346 inetLoopback
+            addr' = SocketAddrInet 12347 inetLoopback
+        withResource (initUDP defaultUDPConfig{udpLocalAddr = Just (addr,UV_UDP_DEFAULT)}) $ \ c ->
+            withResource (initUDP defaultUDPConfig{udpLocalAddr = Just (addr',UV_UDP_DEFAULT)}) $ \ s -> do
+                forkIO $ sendUDP c addr' testMsg
+                [(rcvAddr, _, _)]<- recvUDP defaultUDPRecvConfig s
+                Just addr @=? rcvAddr
+
+    it "overlong message exception" $ do
+        let testMsg = V.replicate 4096 48
+            addr = SocketAddrInet 12348 inetLoopback
+        withResource (initUDP defaultUDPConfig) $ \ c ->
+            withResource (initUDP defaultUDPConfig) $ \ s -> do
+                sendUDP c addr testMsg `shouldThrow` anyException
diff --git a/test/Z/IO/UDPSpec.hs b/test/Z/IO/UDPSpec.hs
deleted file mode 100644
--- a/test/Z/IO/UDPSpec.hs
+++ /dev/null
@@ -1,54 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-
-module Z.IO.UDPSpec where
-
-import           Control.Concurrent
-import           Control.Monad
-import           Data.Bits
-import           Z.Data.Vector         as V
-import           Z.Data.Vector.Base    as V
-import           Data.List               as List
-import           Foreign.Marshal.Array
-import           Foreign.Ptr
-import           Z.IO.Exception
-import           Z.IO.Resource
-import           Z.IO.Network.SocketAddr
-import           Z.IO.Network.UDP
-import           Test.Hspec
-import           Test.HUnit
-
-spec :: Spec
-spec = describe "UDP operations" $ do
-    it "roundtrip test" $ do
-        let testMsg = V.replicate 256 48
-            longMsg = V.replicate 2048 48
-            addr = SocketAddrInet 12345 inetLoopback
-        withResource (initUDP defaultUDPConfig{udpSendMsgSize = 2048}) $ \ c ->
-            withResource (initUDP defaultUDPConfig{udpLocalAddr = Just (addr,UV_UDP_DEFAULT)}) $ \ s -> do
-                forkIO $ sendUDP c addr testMsg
-                [(_, partial, rcvMsg)]<- recvUDP defaultUDPRecvConfig s
-                partial @=? False
-                rcvMsg @=? testMsg
-
-                threadDelay 100000
-
-                forkIO $ sendUDP c addr longMsg
-                [(_, partial, rcvMsg)]<- recvUDP defaultUDPRecvConfig s
-                partial @=? True
-
-    it "UDP sending addr test" $ do
-        let testMsg = V.replicate 256 48
-            addr = SocketAddrInet 12346 inetLoopback
-            addr' = SocketAddrInet 12347 inetLoopback
-        withResource (initUDP defaultUDPConfig{udpLocalAddr = Just (addr,UV_UDP_DEFAULT)}) $ \ c ->
-            withResource (initUDP defaultUDPConfig{udpLocalAddr = Just (addr',UV_UDP_DEFAULT)}) $ \ s -> do
-                forkIO $ sendUDP c addr' testMsg
-                [(rcvAddr, _, _)]<- recvUDP defaultUDPRecvConfig s
-                Just addr @=? rcvAddr
-
-    it "overlong message exception" $ do
-        let testMsg = V.replicate 4096 48
-            addr = SocketAddrInet 12348 inetLoopback
-        withResource (initUDP defaultUDPConfig) $ \ c ->
-            withResource (initUDP defaultUDPConfig) $ \ s -> do
-                sendUDP c addr testMsg `shouldThrow` anyException
diff --git a/third_party/zlib/zconf.h b/third_party/zlib/zconf.h
new file mode 100644
--- /dev/null
+++ b/third_party/zlib/zconf.h
@@ -0,0 +1,534 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */
+#  define Z_PREFIX_SET
+
+/* all linked symbols and init macros */
+#  define _dist_code            z__dist_code
+#  define _length_code          z__length_code
+#  define _tr_align             z__tr_align
+#  define _tr_flush_bits        z__tr_flush_bits
+#  define _tr_flush_block       z__tr_flush_block
+#  define _tr_init              z__tr_init
+#  define _tr_stored_block      z__tr_stored_block
+#  define _tr_tally             z__tr_tally
+#  define adler32               z_adler32
+#  define adler32_combine       z_adler32_combine
+#  define adler32_combine64     z_adler32_combine64
+#  define adler32_z             z_adler32_z
+#  ifndef Z_SOLO
+#    define compress              z_compress
+#    define compress2             z_compress2
+#    define compressBound         z_compressBound
+#  endif
+#  define crc32                 z_crc32
+#  define crc32_combine         z_crc32_combine
+#  define crc32_combine64       z_crc32_combine64
+#  define crc32_z               z_crc32_z
+#  define deflate               z_deflate
+#  define deflateBound          z_deflateBound
+#  define deflateCopy           z_deflateCopy
+#  define deflateEnd            z_deflateEnd
+#  define deflateGetDictionary  z_deflateGetDictionary
+#  define deflateInit           z_deflateInit
+#  define deflateInit2          z_deflateInit2
+#  define deflateInit2_         z_deflateInit2_
+#  define deflateInit_          z_deflateInit_
+#  define deflateParams         z_deflateParams
+#  define deflatePending        z_deflatePending
+#  define deflatePrime          z_deflatePrime
+#  define deflateReset          z_deflateReset
+#  define deflateResetKeep      z_deflateResetKeep
+#  define deflateSetDictionary  z_deflateSetDictionary
+#  define deflateSetHeader      z_deflateSetHeader
+#  define deflateTune           z_deflateTune
+#  define deflate_copyright     z_deflate_copyright
+#  define get_crc_table         z_get_crc_table
+#  ifndef Z_SOLO
+#    define gz_error              z_gz_error
+#    define gz_intmax             z_gz_intmax
+#    define gz_strwinerror        z_gz_strwinerror
+#    define gzbuffer              z_gzbuffer
+#    define gzclearerr            z_gzclearerr
+#    define gzclose               z_gzclose
+#    define gzclose_r             z_gzclose_r
+#    define gzclose_w             z_gzclose_w
+#    define gzdirect              z_gzdirect
+#    define gzdopen               z_gzdopen
+#    define gzeof                 z_gzeof
+#    define gzerror               z_gzerror
+#    define gzflush               z_gzflush
+#    define gzfread               z_gzfread
+#    define gzfwrite              z_gzfwrite
+#    define gzgetc                z_gzgetc
+#    define gzgetc_               z_gzgetc_
+#    define gzgets                z_gzgets
+#    define gzoffset              z_gzoffset
+#    define gzoffset64            z_gzoffset64
+#    define gzopen                z_gzopen
+#    define gzopen64              z_gzopen64
+#    ifdef _WIN32
+#      define gzopen_w              z_gzopen_w
+#    endif
+#    define gzprintf              z_gzprintf
+#    define gzputc                z_gzputc
+#    define gzputs                z_gzputs
+#    define gzread                z_gzread
+#    define gzrewind              z_gzrewind
+#    define gzseek                z_gzseek
+#    define gzseek64              z_gzseek64
+#    define gzsetparams           z_gzsetparams
+#    define gztell                z_gztell
+#    define gztell64              z_gztell64
+#    define gzungetc              z_gzungetc
+#    define gzvprintf             z_gzvprintf
+#    define gzwrite               z_gzwrite
+#  endif
+#  define inflate               z_inflate
+#  define inflateBack           z_inflateBack
+#  define inflateBackEnd        z_inflateBackEnd
+#  define inflateBackInit       z_inflateBackInit
+#  define inflateBackInit_      z_inflateBackInit_
+#  define inflateCodesUsed      z_inflateCodesUsed
+#  define inflateCopy           z_inflateCopy
+#  define inflateEnd            z_inflateEnd
+#  define inflateGetDictionary  z_inflateGetDictionary
+#  define inflateGetHeader      z_inflateGetHeader
+#  define inflateInit           z_inflateInit
+#  define inflateInit2          z_inflateInit2
+#  define inflateInit2_         z_inflateInit2_
+#  define inflateInit_          z_inflateInit_
+#  define inflateMark           z_inflateMark
+#  define inflatePrime          z_inflatePrime
+#  define inflateReset          z_inflateReset
+#  define inflateReset2         z_inflateReset2
+#  define inflateResetKeep      z_inflateResetKeep
+#  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateSync           z_inflateSync
+#  define inflateSyncPoint      z_inflateSyncPoint
+#  define inflateUndermine      z_inflateUndermine
+#  define inflateValidate       z_inflateValidate
+#  define inflate_copyright     z_inflate_copyright
+#  define inflate_fast          z_inflate_fast
+#  define inflate_table         z_inflate_table
+#  ifndef Z_SOLO
+#    define uncompress            z_uncompress
+#    define uncompress2           z_uncompress2
+#  endif
+#  define zError                z_zError
+#  ifndef Z_SOLO
+#    define zcalloc               z_zcalloc
+#    define zcfree                z_zcfree
+#  endif
+#  define zlibCompileFlags      z_zlibCompileFlags
+#  define zlibVersion           z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+#  define Byte                  z_Byte
+#  define Bytef                 z_Bytef
+#  define alloc_func            z_alloc_func
+#  define charf                 z_charf
+#  define free_func             z_free_func
+#  ifndef Z_SOLO
+#    define gzFile                z_gzFile
+#  endif
+#  define gz_header             z_gz_header
+#  define gz_headerp            z_gz_headerp
+#  define in_func               z_in_func
+#  define intf                  z_intf
+#  define out_func              z_out_func
+#  define uInt                  z_uInt
+#  define uIntf                 z_uIntf
+#  define uLong                 z_uLong
+#  define uLongf                z_uLongf
+#  define voidp                 z_voidp
+#  define voidpc                z_voidpc
+#  define voidpf                z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+#  define gz_header_s           z_gz_header_s
+#  define internal_state        z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+#  define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+#  define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#  ifndef WIN32
+#    define WIN32
+#  endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+#    ifndef SYS16BIT
+#      define SYS16BIT
+#    endif
+#  endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+#  ifndef STDC
+#    define STDC
+#  endif
+#  if __STDC_VERSION__ >= 199901L
+#    ifndef STDC99
+#      define STDC99
+#    endif
+#  endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+#  define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
+#  define STDC
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const       /* note: need a more gentle solution here */
+#  endif
+#endif
+
+#if defined(ZLIB_CONST) && !defined(z_const)
+#  define z_const const
+#else
+#  define z_const
+#endif
+
+#ifdef Z_SOLO
+   typedef unsigned long z_size_t;
+#else
+#  define z_longlong long long
+#  if defined(NO_SIZE_T)
+     typedef unsigned NO_SIZE_T z_size_t;
+#  elif defined(STDC)
+#    include <stddef.h>
+     typedef size_t z_size_t;
+#  else
+     typedef unsigned long z_size_t;
+#  endif
+#  undef z_longlong
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+#ifndef Z_ARG /* function prototypes for stdarg */
+#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#    define Z_ARG(args)  args
+#  else
+#    define Z_ARG(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+#  if defined(M_I86SM) || defined(M_I86MM)
+     /* MSC small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef _MSC_VER
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#  if (defined(__SMALL__) || defined(__MEDIUM__))
+     /* Turbo C small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef __BORLANDC__
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+   /* If building or using zlib as a DLL, define ZLIB_DLL.
+    * This is not mandatory, but it offers a little performance increase.
+    */
+#  ifdef ZLIB_DLL
+#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+#      ifdef ZLIB_INTERNAL
+#        define ZEXTERN extern __declspec(dllexport)
+#      else
+#        define ZEXTERN extern __declspec(dllimport)
+#      endif
+#    endif
+#  endif  /* ZLIB_DLL */
+   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+    * define ZLIB_WINAPI.
+    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+    */
+#  ifdef ZLIB_WINAPI
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+     /* No need for _export, use ZLIB.DEF instead. */
+     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+#    define ZEXPORT WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA WINAPIV
+#    else
+#      define ZEXPORTVA FAR CDECL
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  ifdef ZLIB_DLL
+#    ifdef ZLIB_INTERNAL
+#      define ZEXPORT   __declspec(dllexport)
+#      define ZEXPORTVA __declspec(dllexport)
+#    else
+#      define ZEXPORT   __declspec(dllimport)
+#      define ZEXPORTVA __declspec(dllimport)
+#    endif
+#  endif
+#endif
+
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void const *voidpc;
+   typedef void FAR   *voidpf;
+   typedef void       *voidp;
+#else
+   typedef Byte const *voidpc;
+   typedef Byte FAR   *voidpf;
+   typedef Byte       *voidp;
+#endif
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+#  include <limits.h>
+#  if (UINT_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned
+#  elif (ULONG_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned long
+#  elif (USHRT_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned short
+#  endif
+#endif
+
+#ifdef Z_U4
+   typedef Z_U4 z_crc_t;
+#else
+   typedef unsigned long z_crc_t;
+#endif
+
+#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */
+#  define Z_HAVE_UNISTD_H
+#endif
+
+#ifdef HAVE_STDARG_H    /* may be set to #if 1 by ./configure */
+#  define Z_HAVE_STDARG_H
+#endif
+
+#ifdef STDC
+#  ifndef Z_SOLO
+#    include <sys/types.h>      /* for off_t */
+#  endif
+#endif
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#  ifndef Z_SOLO
+#    include <stdarg.h>         /* for va_list */
+#  endif
+#endif
+
+#ifdef _WIN32
+#  ifndef Z_SOLO
+#    include <stddef.h>         /* for wchar_t */
+#  endif
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+#  undef _LARGEFILE64_SOURCE
+#endif
+
+#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
+#  define Z_HAVE_UNISTD_H
+#endif
+#ifndef Z_SOLO
+#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
+#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+#    ifdef VMS
+#      include <unixio.h>       /* for off_t */
+#    endif
+#    ifndef z_off_t
+#      define z_off_t off_t
+#    endif
+#  endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+#  define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+#  define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+#  define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+#  define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+#  define z_off64_t off64_t
+#else
+#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+#    define z_off64_t __int64
+#  else
+#    define z_off64_t z_off_t
+#  endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+  #pragma map(deflateInit_,"DEIN")
+  #pragma map(deflateInit2_,"DEIN2")
+  #pragma map(deflateEnd,"DEEND")
+  #pragma map(deflateBound,"DEBND")
+  #pragma map(inflateInit_,"ININ")
+  #pragma map(inflateInit2_,"ININ2")
+  #pragma map(inflateEnd,"INEND")
+  #pragma map(inflateSync,"INSY")
+  #pragma map(inflateSetDictionary,"INSEDI")
+  #pragma map(compressBound,"CMBND")
+  #pragma map(inflate_table,"INTABL")
+  #pragma map(inflate_fast,"INFA")
+  #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
