diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+0.1.0.19
+--------
+* Fix a memory leak
+
 0.1.0.18
 --------
 * Add complete command line arguments
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -187,7 +187,7 @@
       same "printed page" as the copyright notice for easier
       identification within third-party archives.
 
-   Copyright 2015 Jinjing Wang
+   Copyright [yyyy] [name of copyright owner]
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -63,6 +63,22 @@
 The original goal of MoeSocks is to provide extra configurability to standard
 shadowsocks, but it has been discarded since remote is too flaky. 
 
+License
+--------
+Copyright 2015 Jinjing Wang
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
 [shadowsocks]:https://github.com/shadowsocks/shadowsocks 
 [shadowsocks-go]:https://github.com/shadowsocks/shadowsocks-go
 [shadowsocks-haskell]:https://github.com/rnons/shadowsocks-haskell
diff --git a/moesocks.cabal b/moesocks.cabal
--- a/moesocks.cabal
+++ b/moesocks.cabal
@@ -1,6 +1,6 @@
 name:               moesocks
 category:           Network
-version:            0.1.0.18
+version:            0.1.0.19
 license:            Apache-2.0
 synopsis:           A functional firewall killer
 description:        A socks5 proxy using the client / server architecture.
@@ -24,7 +24,7 @@
 executable moesocks
   main-is:             Main.hs
   ghc-options:        -Wall -fno-warn-unused-do-bind -threaded 
-                      -rtsopts "-with-rtsopts=-N"
+                      -rtsopts "-with-rtsopts=-N -c"
   build-depends:       base > 4 && <= 5
                       , HsOpenSSL
                       , aeson
@@ -42,6 +42,7 @@
                       , random
                       , safe
                       , stm
+                      , strict
                       , text
                       , time
                       , transformers
diff --git a/src/Network/MoeSocks/App.hs b/src/Network/MoeSocks/App.hs
--- a/src/Network/MoeSocks/App.hs
+++ b/src/Network/MoeSocks/App.hs
@@ -17,8 +17,8 @@
 import Network.MoeSocks.Config
 import Network.MoeSocks.Constant
 import Network.MoeSocks.Helper
-import Network.MoeSocks.Type
 import Network.MoeSocks.TCP
+import Network.MoeSocks.Type
 import Network.MoeSocks.UDP
 import Network.Socket hiding (send, recv, recvFrom, sendTo)
 import Network.Socket.ByteString
@@ -37,23 +37,6 @@
 
 parseConfig :: MoeOptions -> MoeMonadT MoeConfig
 parseConfig aOption = do
-  let
-    formatConfig :: Value -> Value
-    formatConfig (Object _obj) =
-        Object -
-          _obj
-              & H.toList 
-              & over (mapped . _1) T.tail 
-              & H.fromList
-    formatConfig _ = Null
-
-    showConfig :: MoeConfig -> Text
-    showConfig =    view utf8 
-                  . toStrict 
-                  . encode 
-                  . formatConfig 
-                  . toJSON 
-
   let _maybeFilePath = aOption ^. configFile 
 
   _v <- case _maybeFilePath of
@@ -94,6 +77,21 @@
       fixConfig _ = Null
   
 
+      formatConfig :: Value -> Value
+      formatConfig (Object _obj) =
+          Object -
+            _obj
+                & H.toList 
+                & over (mapped . _1) T.tail 
+                & H.fromList
+      formatConfig _ = Null
+
+      showConfig :: MoeConfig -> Text
+      showConfig =    view utf8 
+                    . toStrict 
+                    . encode 
+                    . formatConfig 
+                    . toJSON 
 
       
 
diff --git a/src/Network/MoeSocks/Common.hs b/src/Network/MoeSocks/Common.hs
--- a/src/Network/MoeSocks/Common.hs
+++ b/src/Network/MoeSocks/Common.hs
@@ -4,15 +4,20 @@
 
 import Control.Lens
 import Control.Monad.Writer hiding (listen)
+import Data.ByteString (ByteString)
 import Data.Text (Text)
-import Data.Text.Strict.Lens (utf8)
 import Data.Text.Lens
+import Data.Text.Strict.Lens (utf8)
 import Network.MoeSocks.Helper
+import Network.MoeSocks.Internal.ShadowSocks.Encrypt as E
 import Network.MoeSocks.Type
 import Network.Socket hiding (send, recv, recvFrom, sendTo)
 import Prelude hiding ((-), take)
 import qualified Data.List as L
-import Network.MoeSocks.Internal.ShadowSocks.Encrypt
+import qualified Data.Strict as S
+
+plainCipher :: (S.Maybe ByteString) -> IO ByteString
+plainCipher = E.plainCipher
 
 getCipher :: Text -> Text -> IO (Cipher, Cipher)
 getCipher aMethod aPassword =
diff --git a/src/Network/MoeSocks/Helper.hs b/src/Network/MoeSocks/Helper.hs
--- a/src/Network/MoeSocks/Helper.hs
+++ b/src/Network/MoeSocks/Helper.hs
@@ -29,7 +29,9 @@
 import qualified Data.ByteString as S
 import qualified Data.ByteString.Builder as B
 import qualified Data.ByteString.Lazy as LB
+import qualified Data.Strict as S
 
+
 -- BEGIN backports
 
 infixr 0 -
@@ -39,6 +41,9 @@
 -- END backports
 
 
+type HCipher = S.Maybe ByteString -> IO ByteString 
+type HQueue = TBQueue (S.Maybe ByteString)
+
 io :: (MonadIO m) => IO a -> m a
 io = liftIO
 
@@ -95,6 +100,7 @@
   puts - "Closing socket " <> aID
   close aSocket 
 
+
 logSocketWithAddress :: String -> IO (Socket, SockAddr) -> 
                         ((Socket, SockAddr) -> IO a) -> IO a
 logSocketWithAddress aID _init f = do
@@ -172,6 +178,7 @@
   pure ()
 
 connectTunnel :: (Maybe String, IO ()) -> (Maybe String, IO ()) -> IO ()
+-- connectTunnel x y = finally (waitBothDebug x y) performGC
 connectTunnel = waitBothDebug
 
 {-connectTunnel :: (Maybe String, IO ()) -> (Maybe String, IO ()) -> IO ()-}
@@ -247,15 +254,16 @@
 send_ :: Socket -> ByteString -> IO ()
 send_ = sendAll
 
-sendBuilder :: TBQueue (Maybe ByteString) -> B.Builder -> IO ()
+sendBuilder :: HQueue -> B.Builder -> IO ()
 sendBuilder _queue = 
-  atomically . writeTBQueue _queue . Just . builder_To_ByteString
+  atomically . writeTBQueue _queue . S.Just . builder_To_ByteString
 
-sendBuilderEncrypted ::  TBQueue (Maybe ByteString) -> 
-                          (ByteString -> IO ByteString) -> B.Builder -> IO ()
+sendBuilderEncrypted ::  HQueue -> 
+                          HCipher -> 
+                          B.Builder -> IO ()
 sendBuilderEncrypted _queue _encrypt x = 
-  atomically . writeTBQueue _queue . Just =<< 
-                                      _encrypt (builder_To_ByteString x)
+  atomically . writeTBQueue _queue . S.Just =<< 
+                                      _encrypt (S.Just - builder_To_ByteString x)
 
 -- | An exception raised when parsing fails.
 data ParseException = ParseException String
@@ -265,7 +273,7 @@
 
 instance Exception ParseException
 
-parseSocket :: String -> ByteString -> (ByteString -> IO ByteString) ->
+parseSocket :: String -> ByteString -> HCipher ->
                   Parser a -> Socket -> IO (ByteString, a)
 parseSocket aID _partial _decrypt aParser = parseSocketWith aID - parse aParser
   where
@@ -274,7 +282,7 @@
     parseSocketWith _id _parser _socket = do
       _rawBytes <- recv_ _socket
       {-puts - "rawBytes: " <> show _rawBytes-}
-      _bytes <- _decrypt _rawBytes
+      _bytes <- _decrypt (S.Just _rawBytes)
 
       case _parser - _partial <> _bytes of
         Done i _r -> pure (i, _r)
@@ -292,8 +300,8 @@
 
 -- throttle speed in kilobytes per second
 produceLoop :: String -> Timeout -> Maybe Double ->
-              Socket -> TBQueue (Maybe ByteString) -> 
-              (ByteString -> IO ByteString) -> IO ()
+              Socket -> HQueue -> 
+              HCipher -> IO ()
 produceLoop aID aTimeout aThrottle aSocket aTBQueue f = do
   _startTime <- getCurrentTime
 
@@ -302,7 +310,7 @@
                     {-tryIO aID - close aSocket-}
                   
       _produce :: Int -> IO ()
-      _produce _bytesReceived = do
+      _produce _bytesReceived = flip onException (f S.Nothing) - do
         _r <- timeoutFor aID aTimeout - recv_ aSocket
         {-pute - "Get chunk: " <> (show - S.length _r) -- <> " " <> aID-}
         if (_r & isn't _Empty) 
@@ -326,12 +334,13 @@
                         <> " miliseconds."
                 threadDelay - floor - _sleepTime
               
-            f _r >>= atomically . writeTBQueue aTBQueue . Just
+            f (S.Just _r) >>= atomically . writeTBQueue aTBQueue . S.Just
             yield
             _produce (_bytesReceived + S.length _r)
           else do
             puts -  "Half closed: " <> aID 
-            atomically - writeTBQueue aTBQueue Nothing
+            f S.Nothing >>= atomically . writeTBQueue aTBQueue . S.Just
+            atomically - writeTBQueue aTBQueue S.Nothing
 
   _produce 0 `onException` _shutdown
   pure ()
@@ -339,7 +348,7 @@
   
 
 consumeLoop :: String -> Timeout -> Maybe Double ->
-                Socket -> TBQueue (Maybe ByteString) -> IO ()
+                Socket -> HQueue -> IO ()
 consumeLoop aID aTimeout aThrottle aSocket aTBQueue = do
   _startTime <- getCurrentTime
   
@@ -374,8 +383,8 @@
         _newPacket <- atomically - readTBQueue aTBQueue
 
         case _newPacket of
-          Nothing -> () <$ _shutdown
-          Just _data -> do
+          S.Nothing -> () <$ _shutdown
+          S.Just _data -> do
                           timeoutFor aID aTimeout - 
                                           sendAll aSocket _data
                           yield
diff --git a/src/Network/MoeSocks/Internal/ShadowSocks/Encrypt.hs b/src/Network/MoeSocks/Internal/ShadowSocks/Encrypt.hs
--- a/src/Network/MoeSocks/Internal/ShadowSocks/Encrypt.hs
+++ b/src/Network/MoeSocks/Internal/ShadowSocks/Encrypt.hs
@@ -2,7 +2,7 @@
  - https://hackage.haskell.org/package/shadowsocks
  - Copyright: rnons
  - Licence: MIT
- - Slightly modified to work better with moesocks
+ - Heavily modified here
  -}
 
 
@@ -33,9 +33,12 @@
 
 
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE LambdaCase #-}
+
 module Network.MoeSocks.Internal.ShadowSocks.Encrypt
   ( getEncDec
   , iv_len
+  , plainCipher
   ) where
 
 import           Control.Concurrent.MVar ( newEmptyMVar, isEmptyMVar
@@ -48,11 +51,13 @@
 import           Data.Monoid ((<>))
 import           OpenSSL (withOpenSSL)
 import           OpenSSL.EVP.Cipher (getCipherByName, CryptoMode(..))
-import           OpenSSL.EVP.Internal (cipherInitBS, cipherUpdateBS)
+import           OpenSSL.EVP.Internal (cipherInitBS, cipherUpdateBS,
+                                        cipherFinalBS)
 import           OpenSSL.Random (randBytes)
 import           Data.Text (Text)
 import           Control.Lens
 import           Data.Text.Lens
+import qualified Data.Strict as S
 
 
 method_supported :: HM.HashMap Text (Int, Int)
@@ -92,7 +97,8 @@
         | otherwise = m
 
 getSSLEncDec :: Text -> ByteString
-             -> IO (ByteString -> IO ByteString, ByteString -> IO ByteString)
+             -> IO (S.Maybe ByteString -> IO ByteString
+                    , S.Maybe ByteString -> IO ByteString)
 getSSLEncDec method password = do
     let (m0, m1) = fromJust $ HM.lookup method method_supported
     random_iv <- withOpenSSL $ randBytes 32
@@ -105,46 +111,56 @@
                                         method ^. _Text
     ctx <- withOpenSSL $ cipherInitBS cipherMethod key cipher_iv Encrypt
     let
-        encrypt buf = 
-          if S.null buf
-            then return $! S.empty
-            else do
-              empty <- isEmptyMVar cipherCtx
-              if empty
-                  then do
-                      putMVar cipherCtx $! ()
-                      ciphered <- withOpenSSL $ cipherUpdateBS ctx buf
-                      return $! cipher_iv <> ciphered
-                  else do
-                      r <- withOpenSSL $ cipherUpdateBS ctx buf
-                      return $! r
+        encrypt :: (S.Maybe ByteString) -> IO ByteString
+        encrypt = \case
+          S.Nothing -> cipherFinalBS ctx
+          S.Just buf -> do
+            if S.null buf
+              then return $! mempty
+              else do
+                empty <- isEmptyMVar cipherCtx
+                if empty
+                    then do
+                        putMVar cipherCtx $! ()
+                        ciphered <- withOpenSSL $ cipherUpdateBS ctx buf
+                        return $! cipher_iv <> ciphered
+                    else do
+                        r <- withOpenSSL $ cipherUpdateBS ctx buf
+                        return $! r
 
-        decrypt buf =
-          if S.null buf
-            then return $! S.empty
-            else do
-              empty <- isEmptyMVar decipherCtx
-              if empty
-                  then do
-                      let decipher_iv = S.take m1 buf
-                      dctx <- withOpenSSL $ 
-                              cipherInitBS cipherMethod key decipher_iv Decrypt
-                      putMVar decipherCtx $! dctx
-                      if S.null (S.drop m1 buf)
-                          then return ""
-                          else do
-                              r <- withOpenSSL $
-                                      cipherUpdateBS dctx (S.drop m1 buf)
-                              return $! r
-                  else do
-                      dctx <- readMVar decipherCtx
-                      r <- withOpenSSL $ cipherUpdateBS dctx buf
-                      return $! r
+        decrypt :: (S.Maybe ByteString) -> IO ByteString
+        decrypt = \case
+          S.Nothing -> cipherFinalBS ctx
+          S.Just buf -> do 
+            if S.null buf
+              then return $! S.empty
+              else do
+                empty <- isEmptyMVar decipherCtx
+                if empty
+                    then do
+                        let decipher_iv = S.take m1 buf
+                        dctx <- withOpenSSL $ 
+                                cipherInitBS cipherMethod key decipher_iv Decrypt
+                        putMVar decipherCtx $! dctx
+                        if S.null (S.drop m1 buf)
+                            then return ""
+                            else do
+                                r <- withOpenSSL $
+                                        cipherUpdateBS dctx (S.drop m1 buf)
+                                return $! r
+                    else do
+                        dctx <- readMVar decipherCtx
+                        r <- withOpenSSL $ cipherUpdateBS dctx buf
+                        return $! r
 
     return (encrypt, decrypt)
 
+plainCipher :: (S.Maybe ByteString -> IO ByteString)
+plainCipher = pure . S.fromMaybe mempty
+
 getEncDec :: Text -> ByteString  
-          -> IO (ByteString -> IO ByteString, ByteString -> IO ByteString)
+          -> IO (S.Maybe ByteString -> IO ByteString
+                , S.Maybe ByteString -> IO ByteString)
 getEncDec t
-  | t == "none" = const $ pure (pure, pure)
+  | t == "none" = const $ pure (plainCipher, plainCipher)
   | otherwise = getSSLEncDec t
diff --git a/src/Network/MoeSocks/TCP.hs b/src/Network/MoeSocks/TCP.hs
--- a/src/Network/MoeSocks/TCP.hs
+++ b/src/Network/MoeSocks/TCP.hs
@@ -15,12 +15,14 @@
 import Network.MoeSocks.Type
 import Network.Socket hiding (send, recv, recvFrom, sendTo)
 import Prelude hiding ((-), take)
+import qualified Data.Strict as S
 
 local_Socks5_RequestHandler :: MoeConfig -> ByteString -> (Socket, SockAddr) 
                                                                     -> IO ()
 local_Socks5_RequestHandler aConfig _ (aSocket,_) = do
   (_partialBytesAfterGreeting, _r) <- 
-      parseSocket "clientGreeting" mempty pure greetingParser aSocket
+      parseSocket "clientGreeting" mempty plainCipher
+        greetingParser aSocket
 
   when (not - _No_authentication `elem` (_r ^. authenticationMethods)) - 
     throwIO - ParseException
@@ -31,7 +33,7 @@
   _parsedRequest <- parseSocket 
                                 "clientRequest" 
                                 _partialBytesAfterGreeting
-                                pure
+                                plainCipher
                                 connectionParser
                                 aSocket
 
@@ -105,8 +107,8 @@
                   sendChannel _encrypt _header
 
                 when (_partialBytesAfterClientRequest & isn't _Empty) -
-                  atomically . writeTBQueue sendChannel . Just =<< 
-                    _encrypt _partialBytesAfterClientRequest
+                  atomically . writeTBQueue sendChannel . S.Just =<< 
+                    _encrypt (S.Just _partialBytesAfterClientRequest)
 
 
                 let _produce = do
@@ -203,7 +205,7 @@
 
           let sendThread = do
                 when (_leftOverBytes & isn't _Empty) -
-                  atomically - writeTBQueue sendChannel - Just _leftOverBytes
+                  atomically - writeTBQueue sendChannel - S.Just _leftOverBytes
 
                 let _produce = do
                                   produceLoop (_logId "R --> + Loop")
diff --git a/src/Network/MoeSocks/Type.hs b/src/Network/MoeSocks/Type.hs
--- a/src/Network/MoeSocks/Type.hs
+++ b/src/Network/MoeSocks/Type.hs
@@ -3,6 +3,7 @@
 
 module Network.MoeSocks.Type where
 
+import Control.Concurrent.STM
 import Control.Lens
 import Control.Monad.Except
 import Control.Monad.Reader
@@ -12,6 +13,7 @@
 import Data.Word
 import GHC.Generics
 import System.Log.Logger
+import qualified Data.Strict as S
 
 data ClientGreeting = ClientGreeting
   {
@@ -106,7 +108,7 @@
 
 makeLenses ''Env
 
-type Cipher = ByteString -> IO ByteString 
-
+type Cipher = S.Maybe ByteString -> IO ByteString 
+type Queue = TBQueue (Maybe ByteString) 
 
 type MoeMonadT = ReaderT MoeOptions (ExceptT String IO)
diff --git a/src/Network/MoeSocks/UDP.hs b/src/Network/MoeSocks/UDP.hs
--- a/src/Network/MoeSocks/UDP.hs
+++ b/src/Network/MoeSocks/UDP.hs
@@ -2,19 +2,20 @@
 
 module Network.MoeSocks.UDP where
 
+import Control.Exception
 import Control.Lens
 import Control.Monad
-import Data.Attoparsec.ByteString
 import Control.Monad.Writer hiding (listen)
-import Control.Exception
+import Data.Attoparsec.ByteString
 import Data.ByteString (ByteString)
-import Network.MoeSocks.Helper
 import Network.MoeSocks.BuilderAndParser
 import Network.MoeSocks.Common
+import Network.MoeSocks.Helper
 import Network.MoeSocks.Type
 import Network.Socket hiding (send, recv, recvFrom, sendTo)
 import Network.Socket.ByteString
 import Prelude hiding ((-), take)
+import qualified Data.Strict as S
 
 
 buildShadowSocksRequest :: ClientRequest -> ByteString -> ByteString
@@ -31,6 +32,10 @@
             "R Failed to parse UDP request"
 
 
+processAll :: Cipher -> ByteString -> IO ByteString
+processAll f x = 
+  (<>) <$> f (S.Just x) <*> f S.Nothing
+
 local_UDP_ForwardRequestHandler :: MoeConfig -> Forward -> 
                                   ByteString -> (Socket,SockAddr) -> IO ()
 local_UDP_ForwardRequestHandler aConfig aForwarding aMessage 
@@ -65,9 +70,10 @@
       let _msg = show aSockAddr <> " -> " <> showRequest _clientRequest
       _log - "L U: " <> _msg
       
-      send_ _remoteSocket =<< _encrypt _bytes
+      send_ _remoteSocket =<< _encrypt (S.Just _bytes)
 
-      (_r, _) <- recv_ _remoteSocket >>= _decrypt >>= parseShadowSocksRequest
+      (_r, _) <- recv_ _remoteSocket >>= processAll _decrypt 
+                                      >>= parseShadowSocksRequest
 
       {-puts - "L UDP <--: " <> show _r-}
       when (_r & isn't _Empty) - do
@@ -84,7 +90,7 @@
 
   {-let (_encrypt, _decrypt) = (pure, pure)-}
   
-  _msg <- _decrypt aMessage
+  _msg <- processAll _decrypt aMessage
 
   (_decryptedMessage, _clientRequest) <- parseShadowSocksRequest _msg
   
@@ -108,5 +114,5 @@
     {-puts - "R UDP <--: " <> show _r-}
 
     when (_r & isn't _Empty) - do
-      _encryptedMessage <- _encrypt _r
+      _encryptedMessage <- processAll _encrypt _r
       sendAllTo aSocket _encryptedMessage aSockAddr
