diff --git a/Readme.md b/Readme.md
--- a/Readme.md
+++ b/Readme.md
@@ -15,19 +15,19 @@
 Implementation
 ==============
 
-* `n` is randomly generated for each packet.
-* `n` is bounded by a maximum `r`, configurable by the `--randomness` argument.
-* To reduce overhead, `n` is set to 0 whenever `m` is greater then a 
-  threshold `b`, configurable by the `--bound` argument.
+* `n` is deduced from a randomly generated `i = n + m` for each packet.
+* When a random `i` is less then `m`, payload is split to `p1` and `p2` to satisfy the constrain, where the length of `p1` is equal to `i` and `p1 + p2 = payload`. `p2` will be sent in the next iteration by the same algorithm.
+* `i` is bounded by a maximum `r`, configurable by the `--randomnessInBytes` argument.
+* To reduce overhead, `n` is set to `0` whenever `m` is greater then `r`.
 
 Usage
 =====
 * local:
 
-        need-obfs --localHost TEXT --localPort INTEGER --remoteHost TEXT --remotePort INTEGER
+        neko-obfs --localHost TEXT --localPort INTEGER --remoteHost TEXT --remotePort INTEGER
 * remote: 
 
-        neko-obfs --remote --remoteHost TEXT --remotePort INTEGER --forwardHost TEXT --forwardPort INTEGER
+        neko-obfs --role remote --remoteHost TEXT --remotePort INTEGER --forwardHost TEXT --forwardPort INTEGER
 * This tunnel should be used inside an encrypted tunnel.
 * For example:
 
diff --git a/neko-obfs.cabal b/neko-obfs.cabal
--- a/neko-obfs.cabal
+++ b/neko-obfs.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                neko-obfs
-version:             0.1.0.1
+version:             0.1.0.2
 synopsis:            a TCP tunnel with packet length obfuscation
 description:         Just another tool that helps accessing the internet
 license:             Apache-2.0
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -4,10 +4,11 @@
 
 import           Helper ((-), log)
 import           Prelude hiding ((-), log)
+import qualified Prelude as Prelude
 
 import           Control.Concurrent.Async (async, waitAnyCatchCancel, waitEitherCancel)
 import           Control.Lens
-import           Control.Monad (replicateM_, join)
+import           Control.Monad (replicateM_, join, when)
 import           Control.Monad.IO.Class (MonadIO(..))
 import           Control.Monad.Trans.State.Strict (runStateT)
 import           Data.Attoparsec.ByteString (parse, maybeResult)
@@ -28,29 +29,69 @@
 import           Pipes.Safe
 import           System.Random (randomIO)
 import           Options.Generic
+import System.IO (hSetBuffering, stdin, stdout, BufferMode(LineBuffering))
 
 import           Options (toConfig)
 import           Parser
 import           Type
 
 
-obfsEncode :: (MonadIO m) => Integer -> Integer -> Pipe ByteString ByteString m a
-obfsEncode bound randomness = do
+obfsEncode :: (MonadIO m) => Bool -> Integer -> Pipe ByteString ByteString m a
+obfsEncode debug randomness = do
   for cat - \x -> do
     let payloadLen = (fromIntegral - B.length x)
+    if (payloadLen >= fromIntegral randomness)
+      then do
+        let paddingLen = 0
+        let chunk =
+              view strict - Builder.toLazyByteString -
+                Builder.word32BE paddingLen
+                <> Builder.byteString
+                      (BC.replicate (fromIntegral paddingLen) - '.')
+                <> Builder.word32BE payloadLen
+                <> Builder.byteString x
 
-    randomLen <-
-      if (payloadLen > fromIntegral bound)
-        then pure 0
-        else liftIO - randomIO <&> (`mod` fromIntegral randomness)
+        when debug - log - "E: " <> (T.pack - show - B.length chunk)
+        yield chunk
+      else
+        randomLenCheckLoop x
+  where
+    randomLenCheckLoop payload = do
+      let payloadLen = (fromIntegral - B.length payload)
+      randomLen <- liftIO - randomIO <&> (`mod` fromIntegral randomness)
+      if (payloadLen <= randomLen)
+        then
+          do
+            let paddingLen = randomLen Prelude.- payloadLen
+            let chunk =
+                  view strict - Builder.toLazyByteString -
+                    Builder.word32BE paddingLen
+                    <> Builder.byteString
+                        (BC.replicate (fromIntegral paddingLen) - '.')
+                    <> Builder.word32BE payloadLen
+                    <> Builder.byteString payload
 
-    yield - view strict - Builder.toLazyByteString -
-      Builder.word32BE randomLen
-      <> Builder.byteString (BC.replicate (fromIntegral randomLen) - 'a')
-      <> Builder.word32BE payloadLen
-      <> Builder.byteString x
+            when debug - log - "E: " <> (T.pack - show - B.length chunk)
+            yield chunk
+        else
+          do
+            let paddingLen = 0
+                (now, next) = B.splitAt (fromIntegral randomLen) payload
 
+            let chunk =
+                  view strict - Builder.toLazyByteString -
+                    Builder.word32BE paddingLen
+                    <> Builder.byteString
+                        (BC.replicate (fromIntegral paddingLen) - '.')
+                    <> Builder.word32BE (fromIntegral - B.length now)
+                    <> Builder.byteString now
 
+            when debug - log - "E: " <> (T.pack - show - B.length chunk)
+            yield chunk
+
+            randomLenCheckLoop next
+
+
 obfsDecode :: (MonadIO m) => Producer ByteString m a -> (ByteString -> m ()) -> m ()
 obfsDecode pull sink = loop pull
   where
@@ -65,12 +106,15 @@
 
 main :: IO ()
 main = do
+  hSetBuffering stdin LineBuffering
+  hSetBuffering stdout LineBuffering
+
   config <- getRecord "a TCP tunnel with packet length obfuscation" <&> toConfig
 
   log - T.pack - show config
 
-  let mtu = 4096
-      timeout = fromIntegral - config ^. timeoutInSeconds * 1000000
+  let _mtu = fromIntegral - config ^. mtu + (-8) -- 2 word32be
+      _timeout = fromIntegral - config ^. timeoutInSeconds * 1000000
 
   let _localHost = config ^. localHost . re packed
       _localPort = show - config ^. localPort
@@ -78,9 +122,11 @@
       _remoteHost = config ^. remoteHost . re packed
       _remotePort = show - config ^. remotePort
 
-      _fromSocket = fromSocketTimeout timeout
-      _toSocket = toSocketTimeout timeout
+      _fromSocket = fromSocketTimeout _timeout
+      _toSocket = toSocketTimeout _timeout
 
+      _debug = config ^. debug
+
   localThread <- pure -
     runSafeT . runEffect - serve (Host _localHost) _localPort - \(localSock, localSockAddr) -> do
       log - "local accepted: " <> view packed (show localSockAddr)
@@ -91,14 +137,14 @@
           liftIO - NS.setSocketOption remoteSock NS.NoDelay 1
 
           let
-              localPull = _fromSocket localSock mtu
+              localPull = _fromSocket localSock _mtu
 
-              remotePull = _fromSocket remoteSock mtu
+              remotePull = _fromSocket remoteSock _mtu
               remotePush = _toSocket remoteSock
 
 
           sendThread <- liftIO - async - runEffect - do
-            localPull >-> obfsEncode (config ^. bound) (config ^. randomness)
+            localPull >-> obfsEncode _debug (config ^. randomnessInBytes)
                       >-> remotePush
             liftIO - NS.shutdown remoteSock NS.ShutdownSend
 
@@ -123,17 +169,17 @@
           liftIO - NS.setSocketOption forwardSock NS.NoDelay 1
 
           let
-              remotePull = _fromSocket remoteSock mtu
+              remotePull = _fromSocket remoteSock _mtu
               remotePush = _toSocket remoteSock
 
-              forwardPull = _fromSocket forwardSock mtu
+              forwardPull = _fromSocket forwardSock _mtu
 
           sendThread <- liftIO - async - do
             obfsDecode remotePull - send forwardSock
             liftIO - NS.shutdown forwardSock NS.ShutdownSend
 
           recvThread <- liftIO - async - runEffect - do
-            forwardPull >-> obfsEncode (config ^. bound) (config ^. randomness)
+            forwardPull >-> obfsEncode _debug (config ^. randomnessInBytes)
                         >-> remotePush
             liftIO - NS.shutdown remoteSock NS.ShutdownSend
 
@@ -143,11 +189,12 @@
 
 
   case config ^. role of
-    Local -> do
-      _ <- localThread
-      pure ()
-    Remote -> do
-      _ <- remoteThread
+    Local -> join localThread
+    Remote -> join remoteThread
+    Both -> do
+      local <- async - join localThread
+      remote <- async - join remoteThread
+      waitEitherCancel local remote
       pure ()
 
   pure ()
diff --git a/src/Options.hs b/src/Options.hs
--- a/src/Options.hs
+++ b/src/Options.hs
@@ -1,6 +1,5 @@
--- |
-
 {-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
 
 module Options where
 
@@ -11,16 +10,17 @@
 
 data TunnelOptions = TunnelOptions
   {
-    localHost :: Maybe Text
+    role :: Maybe Text
+  , localHost :: Maybe Text
   , localPort :: Maybe Integer
   , remoteHost :: Text
   , remotePort :: Integer
   , forwardHost :: Maybe Text
   , forwardPort :: Maybe Integer
-  , remote :: Bool
-  , bound :: Maybe Integer
-  , randomness :: Maybe Integer
+  , randomnessInBytes :: Maybe Integer
   , timeoutInSeconds :: Maybe Integer
+  , mtu :: Maybe Integer
+  , debug :: Bool
   }
   deriving (Generic, Show, Eq)
 
@@ -30,6 +30,12 @@
 toConfig :: TunnelOptions -> Config
 toConfig o =
   let c = defaultConfig
+      _role =
+        case role o of
+          Just "remote" -> Remote
+          Just "local" -> Local
+          Just "both" -> Both
+          _ -> Local
   in
   Config
     {
@@ -39,8 +45,9 @@
     , _remotePort = remotePort o
     , _forwardHost = fromMaybe (_forwardHost c) (forwardHost o)
     , _forwardPort = fromMaybe (_forwardPort c) (forwardPort o)
-    , _role = if remote o then Remote else Local
-    , _bound = fromMaybe (_bound c) (bound o)
-    , _randomness = fromMaybe (_randomness c) (randomness o)
+    , _role = _role
+    , _randomnessInBytes = fromMaybe (_randomnessInBytes c) (randomnessInBytes o)
     , _timeoutInSeconds = fromMaybe (_timeoutInSeconds c) (timeoutInSeconds o)
+    , _mtu = fromMaybe (_mtu c) (mtu o)
+    , _debug = debug o
     }
diff --git a/src/Type.hs b/src/Type.hs
--- a/src/Type.hs
+++ b/src/Type.hs
@@ -7,7 +7,7 @@
 import Control.Lens
 import Data.Text (Text)
 
-data Role = Local | Remote
+data Role = Local | Remote | Both
   deriving (Show, Eq)
 
 data Config = Config
@@ -19,9 +19,10 @@
   , _forwardHost :: Text
   , _forwardPort :: Integer
   , _role :: Role
-  , _bound :: Integer
-  , _randomness :: Integer
+  , _randomnessInBytes :: Integer
   , _timeoutInSeconds :: Integer
+  , _debug :: Bool
+  , _mtu :: Integer
   }
   deriving (Show, Eq)
 
@@ -37,7 +38,8 @@
   , _forwardHost = "127.0.0.1"
   , _forwardPort = 1080
   , _role = Local
-  , _bound = 1024
-  , _randomness = 300
+  , _randomnessInBytes = 256
   , _timeoutInSeconds = 3600
+  , _debug = False
+  , _mtu = 4096
   }
