diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,165 @@
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions. 
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version. 
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/Network/YAML.hs b/Network/YAML.hs
new file mode 100644
--- /dev/null
+++ b/Network/YAML.hs
@@ -0,0 +1,20 @@
+
+module Network.YAML 
+  (
+   module Network.YAML.Caller,
+   module Network.YAML.Instances,
+   module Network.YAML.Derive,
+   module Network.YAML.Dispatcher,
+   module Network.YAML.Balancer,
+   module Network.YAML.WrapMethods,
+   forkA
+  ) where
+
+import Network.YAML.Caller
+import Network.YAML.Instances
+import Network.YAML.Derive
+import Network.YAML.Dispatcher
+import Network.YAML.Balancer
+import Network.YAML.WrapMethods 
+import Network.YAML.Server (forkA)
+
diff --git a/Network/YAML/Balancer.hs b/Network/YAML/Balancer.hs
new file mode 100644
--- /dev/null
+++ b/Network/YAML/Balancer.hs
@@ -0,0 +1,19 @@
+
+module Network.YAML.Balancer where
+
+import System.Random
+import qualified Data.ByteString.Char8 as BS
+
+type Server = (BS.ByteString, Int)
+
+-- | Select random server
+selectRandom :: [(BS.ByteString, Server, Int)]   -- ^ [(Service name, (hostname, port number), priority)]
+             -> BS.ByteString                    -- ^ Service name
+             -> IO Server
+selectRandom lst service = do
+  let lst' = concatMap (\(name,srv,p) -> replicate p (name, srv)) lst
+      lst'' = map snd $ filter (\(name,srv) -> name==service) lst'
+      n = length lst''
+  k <- randomRIO (0, n-1)
+  return $ lst'' !! k
+
diff --git a/Network/YAML/Base.hs b/Network/YAML/Base.hs
new file mode 100644
--- /dev/null
+++ b/Network/YAML/Base.hs
@@ -0,0 +1,78 @@
+{-# LANGUAGE FlexibleInstances, FlexibleContexts, TypeSynonymInstances, MultiParamTypeClasses, OverloadedStrings #-}
+
+module Network.YAML.Base where
+
+import Control.Monad
+import Data.Maybe
+import Data.Default
+import Data.Object
+import Data.Object.Yaml
+import qualified Data.ByteString.Char8 as BS
+import Text.Libyaml hiding (encode, decode)
+
+class (ConvertSuccess YamlObject a, ConvertSuccess a YamlObject, Default a) => IsYamlObject a where
+
+getAttr :: BS.ByteString -> YamlObject -> Maybe YamlObject
+getAttr key (Mapping pairs) = lookup (toYamlScalar key) pairs
+getAttr key (Sequence lst) =
+  case catMaybes $ map (getAttr key) lst of
+    [x] -> Just x
+    _   -> Nothing
+getAttr key (Scalar sc) = Nothing
+
+getScalar :: (IsYamlScalar a) => YamlObject -> Maybe a 
+getScalar (Scalar x) = Just (fromYamlScalar x)
+getScalar _          = Nothing
+
+getList :: YamlObject -> [YamlObject]
+getList (Sequence lst) = lst
+getList _              = []
+
+getScalarAttr :: (IsYamlScalar a) => BS.ByteString -> YamlObject -> Maybe a
+getScalarAttr key obj = getScalar =<< getAttr key obj
+
+getSubKey :: (IsYamlScalar a) => BS.ByteString -> BS.ByteString -> YamlObject -> Maybe a
+getSubKey key subkey obj = do
+  attr <- getAttr key obj
+  r <- getAttr subkey attr
+  getScalar r
+
+getItem :: BS.ByteString -> Int -> YamlObject -> YamlObject
+getItem key k obj = 
+  case getListAttr key obj of
+    [] ->  Sequence []
+    lst -> lst !! k
+
+getListAttr :: BS.ByteString -> YamlObject -> [YamlObject]
+getListAttr key obj = 
+  case getAttr key obj of
+    Just x -> getList x
+    Nothing -> []
+
+getFirstKey :: YamlObject -> BS.ByteString
+getFirstKey (Mapping pairs) = fromYamlScalar $ fst $ head pairs
+
+instance IsYamlScalar Double where
+  fromYamlScalar (YamlScalar v _ _) = read $ BS.unpack v
+  toYamlScalar x = YamlScalar (BS.pack $ show x) NoTag Any
+
+instance IsYamlScalar Int where
+  fromYamlScalar (YamlScalar v _ _) = read $ BS.unpack v
+  toYamlScalar x = YamlScalar (BS.pack $ show x) NoTag Any
+
+instance IsYamlScalar Integer where
+  fromYamlScalar (YamlScalar v _ _) = read $ BS.unpack v
+  toYamlScalar x = YamlScalar (BS.pack $ show x) NoTag Any
+
+serialize :: IsYamlObject a => a -> BS.ByteString
+serialize x = 
+  let c :: YamlObject
+      c = cs x
+  in  encode c
+
+unserialize :: IsYamlObject a => BS.ByteString -> Maybe a
+unserialize x =
+  let d :: Maybe YamlObject
+      d = decode x
+  in  cs `fmap` d
+
diff --git a/Network/YAML/Caller.hs b/Network/YAML/Caller.hs
new file mode 100644
--- /dev/null
+++ b/Network/YAML/Caller.hs
@@ -0,0 +1,82 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Network.YAML.Caller where
+
+import qualified Data.Map as M
+import Data.Object.Yaml
+import Data.Convertible.Base
+import qualified Data.ByteString.Char8 as BS
+import Network
+import System.IO
+import Control.Monad
+import Control.Concurrent
+
+import Network.YAML.Base
+import Network.YAML.Instances
+import Network.YAML.Server
+
+-- | Send any YAML text and return an answer
+sendYAML :: (BS.ByteString, Int)      -- ^ (Hostname, port)
+         -> BS.ByteString             -- ^ YAML text
+         -> IO BS.ByteString          -- ^ Answer
+sendYAML (host,port) yaml =  withSocketsDo $ do
+  h <- connectTo (BS.unpack host) (PortNumber $ fromIntegral port)
+  hSetBuffering h NoBuffering
+  BS.hPutStrLn h yaml
+  lns <- readHandle h []
+  hClose h
+  let text = BS.unlines lns
+  return text
+
+-- | Call remote method
+call :: (IsYamlObject a, IsYamlObject b)
+     => (BS.ByteString, Int)            -- ^ (Host name, port number)
+     -> BS.ByteString                   -- ^ Name of method
+     -> a                               -- ^ Argument for method
+     -> IO b
+call (host,port) name args = do
+  let c = mkCall name (cs args)
+      s = serialize c
+  text <- sendYAML (host,port) s
+  case unserialize text of
+    Nothing -> fail "No answer"
+    Just x -> return x
+
+-- | Similar, but select server on each call
+callDynamic :: (IsYamlObject a, IsYamlObject b)
+            => (BS.ByteString -> IO (BS.ByteString,Int)) -- ^ Get (Host name, port number) from service name
+            -> BS.ByteString                             -- ^ Name of the service
+            -> BS.ByteString                             -- ^ Name of method
+            -> a                                         -- ^ Argument for method
+            -> IO b
+callDynamic getServer service name args = do
+  srv <- getServer service
+  call srv name args
+
+-- | Call a method and put it's result into MVar
+callF :: (IsYamlObject a, IsYamlObject b)
+      => (BS.ByteString -> IO (BS.ByteString, Int))           -- ^ Get (Host, port) from service name
+      -> BS.ByteString                                        -- ^ Service name
+      -> BS.ByteString                                        -- ^ Method name
+      -> (a, MVar b)                                          -- ^ (Argument, MVar for result)
+      -> IO ()
+callF getServer service name (args, var) = do
+  srv <- getServer service
+--   putStrLn $ "Calling to " ++ show srv
+  r <- call srv name args
+  putMVar var r
+
+-- | Call a method for each argument in the list in parallel
+-- (it can run method for each argument on another server)
+callP :: (IsYamlObject a, IsYamlObject b)
+      => (BS.ByteString -> IO (BS.ByteString, Int))      -- ^ Get (Host, port) from service name
+      -> BS.ByteString                                   -- ^ Service name
+      -> BS.ByteString                                   -- ^ Method name
+      -> [a]                                             -- ^ List of arguments
+      -> IO [b]
+callP getServer service name args = do
+  let n = length args
+  vars <- replicateM n newEmptyMVar
+  mapM (forkIO . callF getServer service name) $ zip args vars
+  mapM takeMVar vars
+
diff --git a/Network/YAML/Derive.hs b/Network/YAML/Derive.hs
new file mode 100644
--- /dev/null
+++ b/Network/YAML/Derive.hs
@@ -0,0 +1,127 @@
+{-# LANGUAGE TemplateHaskell, TypeSynonymInstances, MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+module Network.YAML.Derive
+  (deriveDefault, deriveIsYamlObject,
+   stringOfName)
+  where
+
+import Language.Haskell.TH
+import Control.Monad
+import Data.Maybe
+import Data.Default
+import Data.Object
+import Data.Object.Yaml
+import qualified Data.ByteString.Char8 as BS
+
+import Network.YAML.Base
+
+mkList :: [Name] -> ExpQ
+mkList []       = [| [] |]
+mkList (v:vars) = [| (toYamlScalar $(stringOfName v), Scalar $ toYamlScalar $(varE v)): $(mkList vars) |]
+
+mkSeq :: [Name] -> ExpQ
+mkSeq []       = [| [] |]
+mkSeq (v:vars) = [| cs $(varE v): $(mkSeq vars) |]
+
+getNameBase :: Name -> Name
+getNameBase name = mkName $ nameBase name
+
+stringOfName :: Name -> ExpQ
+stringOfName n = sigE (stringE $ nameBase n) [t| BS.ByteString |]
+
+nameE :: Name -> ExpQ
+nameE name = varE $ getNameBase name
+
+consClause :: Con -> ClauseQ
+consClause (NormalC name fields) =  do
+    -- Name of constructor, i.e. "A". Will become string literal in generated code
+    let constructorName = nameBase name
+
+    -- Get variables for left and right side of function definition
+    (pats,vars) <- genPE (length fields)
+
+    clause [conP name pats]                                 -- (A x1 x2)
+           (normalB [| Mapping [(toYamlScalar (BS.pack constructorName), Sequence $(mkSeq vars))] |]) []
+
+consClause (RecC name fields) = do
+    -- Name of constructor, i.e. "A". Will become string literal in generated code
+    let constructorName = nameBase name
+        names = [getNameBase name | (name, _, _) <- fields]
+        pats = map varP names
+    clause [conP name pats]                                 -- (A x1 x2)
+           (normalB [| Mapping [(toYamlScalar (BS.pack constructorName), Mapping $(mkList names))] |]) []
+
+consClause x = report True (show x) >> return undefined
+
+genFromClause cName names= do
+    obj <- newName "obj"
+    let guard = [| getFirstKey $(varE obj) == (BS.pack cName) |]
+        body = foldl appE (conE $ mkName cName) $ map (getAttr' cName obj) $ map getNameBase names
+    clause [varP obj] (guardedB [normalGE guard body]) []
+  where
+    getAttr' c obj n = [| fromMaybe def $ getSubKey (BS.pack c) $(stringOfName n) $(varE obj) |]
+
+fromClause :: Con -> ClauseQ
+fromClause (RecC name fields) = do
+    let constructorName = nameBase name
+        names = [getNameBase name | (name, _, _) <- fields]
+    genFromClause constructorName names
+
+fromClause (NormalC name fields) = do
+    let cName = nameBase name
+    (_,names) <- genPE (length fields)
+    obj <- newName "obj"
+    let guard = [| getFirstKey $(varE obj) == (BS.pack cName) |]
+        body = foldl appE (conE $ mkName cName) $ map (getAttr' cName obj) $ map fst (zip [0..] names)
+    clause [varP obj] (guardedB [normalGE guard body]) []
+  where
+    getAttr' c obj k = [| cs $ getItem (BS.pack c) k $(varE obj) |]
+    getName (n,x) = (n, getNameBase x)
+    
+
+-- | Derive `instance ConvertSuccess t YamlObject ...'
+deriveToYamlObject :: Name -> Q [Dec]
+deriveToYamlObject t = do
+  -- Get list of constructors for type t
+  TyConI (DataD _ _ _ constructors _)  <-  reify t
+  convbody <- mapM consClause constructors
+  return [InstanceD [] (ConT ''ConvertSuccess `AppT` ConT t `AppT` ConT ''YamlObject) [FunD 'convertSuccess convbody]]
+
+-- | Derive `instance ConvertSuccess YamlObject t ...'
+deriveFromYamlObject :: Name -> Q [Dec]
+deriveFromYamlObject t = do
+  TyConI (DataD _ _ _ constructors _)  <-  reify t
+  body <- mapM fromClause constructors
+  return [InstanceD [] (ConT ''ConvertSuccess `AppT` ConT ''YamlObject `AppT` ConT t) [FunD 'convertSuccess body]]
+
+-- | Derive `instance IsYamlObject t where ...'
+deriveIsYamlObject :: Name -> Q [Dec]
+deriveIsYamlObject t = do
+  [i1] <- deriveToYamlObject t
+  [i2] <- deriveFromYamlObject t
+  let i3 = InstanceD [] (ConT ''IsYamlObject `AppT` ConT t) []
+  return [i1,i2,i3]
+
+defaultClause :: Con -> ClauseQ
+defaultClause (RecC name fields) = do
+  let defs = replicate (length fields) (varE $ mkName "def")
+      body = foldl appE (conE name) defs
+  clause [] (normalB body) []
+defaultClause (NormalC name fields) = do
+  let defs = replicate (length fields) (varE $ mkName "def")
+      body = foldl appE (conE name) defs
+  clause [] (normalB body) []
+
+-- | Derive `instance Default t where def = ...'
+deriveDefault :: Name -> Q [Dec]
+deriveDefault t = do
+  TyConI (DataD _ _ _ constructors _)  <-  reify t
+  body <- defaultClause (head constructors)
+  return [InstanceD [] (ConT ''Default `AppT` ConT t) [FunD 'def [body]]]
+
+-- | Generate n unique variables and return them in form of patterns and expressions
+genPE ::  Int -> Q ([PatQ], [Name])
+genPE n = do
+  ids <- replicateM n (newName "x")
+  return (map varP ids, ids)
+
diff --git a/Network/YAML/Dispatcher.hs b/Network/YAML/Dispatcher.hs
new file mode 100644
--- /dev/null
+++ b/Network/YAML/Dispatcher.hs
@@ -0,0 +1,31 @@
+
+module Network.YAML.Dispatcher where
+
+import qualified Data.Map as M
+import Data.Object.Yaml
+import Data.Convertible.Base
+import qualified Data.ByteString.Char8 as BS
+
+import Network.YAML.Base
+import Network.YAML.Instances
+import Network.YAML.Server
+
+type Worker = YamlObject -> IO YamlObject
+type Rules = M.Map BS.ByteString Worker
+
+-- | Build dispatching rules
+mkRules :: [(BS.ByteString,Worker)] -> Rules
+mkRules pairs = M.fromList pairs
+
+-- | Select worker from dispatching rules
+dispatch :: Rules -> Worker
+dispatch rules = \obj -> 
+  let call :: Call
+      call = cs obj
+  in case M.lookup (methodName call) rules of
+      Nothing -> fail $ "Unknown method: " ++ (BS.unpack $ methodName call)
+      Just fn -> fn (args call)
+
+-- | Listens given port and dispatches requests
+dispatcher :: Int -> Rules -> IO ()
+dispatcher port rules = server port (dispatch rules)
diff --git a/Network/YAML/Instances.hs b/Network/YAML/Instances.hs
new file mode 100644
--- /dev/null
+++ b/Network/YAML/Instances.hs
@@ -0,0 +1,145 @@
+{-# LANGUAGE TypeSynonymInstances, MultiParamTypeClasses, OverloadedStrings, FlexibleInstances, IncoherentInstances #-}
+
+module Network.YAML.Instances where
+  
+import Data.Maybe
+import Data.Default
+import Data.Object
+import Data.Object.Yaml
+import qualified Data.ByteString.Char8 as BS
+
+import Network.YAML.Base
+
+-- | Build YamlObject from (key,value) pairs
+object :: [(BS.ByteString, YamlScalar)] -> YamlObject
+object pairs = Mapping [(toYamlScalar name, Scalar val) | (name,val) <- pairs]
+
+-- | Build YamlObject with single field
+field :: (IsYamlScalar a) => BS.ByteString -> a -> YamlObject
+field name val = Mapping [(toYamlScalar name, Scalar $ toYamlScalar val)]
+
+instance Default BS.ByteString where
+  def = BS.empty
+
+instance (IsYamlObject a) => ConvertSuccess [a] YamlObject where
+  convertSuccess lst = Sequence $ map cs lst
+
+instance (IsYamlObject a) => ConvertSuccess YamlObject [a] where
+  convertSuccess (Mapping pairs) = map cs $ map snd pairs
+  convertSuccess (Sequence lst) = map cs lst
+  convertSuccess s@(Scalar _) = [cs s]
+
+instance (IsYamlObject a) => IsYamlObject [a] where
+
+tryGet lst k = 
+  if k >= length lst
+    then def
+    else lst !! k
+
+instance (IsYamlObject a, IsYamlObject b) => ConvertSuccess (a,b) YamlObject where
+  convertSuccess (x,y) = Sequence [cs x, cs y]
+
+instance (IsYamlObject a, IsYamlObject b) => ConvertSuccess YamlObject (a,b) where
+  convertSuccess obj = (cs x, cs y) 
+    where
+      list = getList obj
+      x = tryGet list 0
+      y = tryGet list 1
+
+instance (IsYamlObject a, IsYamlObject b) => IsYamlObject (a,b) where
+
+instance (IsYamlObject a, IsYamlObject b, IsYamlObject c) => ConvertSuccess (a,b,c) YamlObject where
+  convertSuccess (x,y,z) = Sequence [cs x, cs y, cs z]
+
+instance (IsYamlObject a, IsYamlObject b, IsYamlObject c) => ConvertSuccess YamlObject (a,b,c) where
+  convertSuccess obj = (cs x, cs y, cs z) 
+    where
+      list = getList obj
+      x = tryGet list 0
+      y = tryGet list 1
+      z = tryGet list 2
+
+instance (IsYamlObject a, IsYamlObject b, IsYamlObject c) => IsYamlObject (a,b,c) where
+
+instance (Default a, Default b) => Default (a,b) where
+  def = (def, def)
+
+instance (Default a, Default b, Default c) => Default (a,b,c) where
+  def = (def, def, def)
+
+instance Default YamlObject where
+  def = Sequence []
+
+instance IsYamlObject YamlObject where
+
+instance ConvertSuccess YamlObject Double where
+  convertSuccess x = fromMaybe def $ getScalar x
+
+instance ConvertSuccess Double YamlObject where
+  convertSuccess x = Scalar $ toYamlScalar x
+
+instance IsYamlObject Double where
+
+instance ConvertSuccess YamlObject Int where
+  convertSuccess x = fromMaybe def $ getScalar x
+
+instance ConvertSuccess Int YamlObject where
+  convertSuccess x = Scalar $ toYamlScalar x
+
+instance IsYamlObject Int where
+
+instance ConvertSuccess YamlObject Integer where
+  convertSuccess x = fromMaybe def $ getScalar x
+
+instance ConvertSuccess Integer YamlObject where
+  convertSuccess x = Scalar $ toYamlScalar x
+
+instance IsYamlObject Integer where
+
+instance ConvertSuccess YamlObject BS.ByteString where
+  convertSuccess x = fromMaybe def $ getScalar x
+
+instance ConvertSuccess BS.ByteString YamlObject where
+  convertSuccess x = Scalar $ toYamlScalar x
+
+instance IsYamlObject BS.ByteString where
+
+instance ConvertSuccess YamlObject String where
+  convertSuccess x = fromMaybe def $ getScalar x
+
+instance ConvertSuccess String YamlObject where
+  convertSuccess x = Scalar $ toYamlScalar x
+
+instance IsYamlObject String where
+
+data Call = Call { methodName :: BS.ByteString, args :: YamlObject }
+  deriving (Show)
+
+mkCall :: BS.ByteString -> YamlObject -> YamlObject
+mkCall name args = cs $ Call name args
+
+stringScalar :: String -> YamlScalar
+stringScalar = toYamlScalar
+
+instance ConvertSuccess Call YamlObject where
+  convertSuccess (Call name args) = Mapping [(stringScalar "call", Scalar $ toYamlScalar name), 
+                                             (stringScalar "args", args)]
+
+instance ConvertSuccess YamlObject Call where
+  convertSuccess obj = Call name args
+    where
+      name = fromMaybe "defaultMethod" $ getScalarAttr "call" obj
+      args = fromMaybe (Sequence []) $ getAttr "args" obj
+
+instance Default Call where
+  def = Call "defaultMethod" def
+
+instance IsYamlObject Call where
+
+-- | Convert any (a -> IO b) action to YAML RPC method
+yamlMethod :: (IsYamlObject a, IsYamlObject b) => (a -> IO b) -> YamlObject -> IO YamlObject
+yamlMethod fn = \obj -> do
+  let x = cs obj
+  y <- fn x
+  return $ cs y
+
diff --git a/Network/YAML/Server.hs b/Network/YAML/Server.hs
new file mode 100644
--- /dev/null
+++ b/Network/YAML/Server.hs
@@ -0,0 +1,69 @@
+
+module Network.YAML.Server where
+
+import Control.Monad 
+import Control.Monad.State
+import Control.Concurrent
+import Control.Exception
+import Network
+import System.IO
+import qualified Data.ByteString.Char8 as BS
+import Data.Object.Yaml
+
+import Network.YAML.Base
+import Network.YAML.Instances
+
+-- | Run each IO action in separate thread and return all results
+forkA :: [IO a] -> IO [a]
+forkA lst = do
+    let n = length lst
+    vars <- replicateM n newEmptyMVar
+    mapM (forkIO . run) $ zip lst vars
+    mapM takeMVar vars
+  where
+    run (x,v) = do
+      r <- x
+      putMVar v r
+
+-- | Read lines from Handle
+readHandle :: Handle
+           -> [BS.ByteString]       -- ^ Already read lines
+           -> IO [BS.ByteString]
+readHandle h acc = do
+    line <- BS.hGetLine h
+    let line' = if BS.null line
+                  then line
+                  else if (BS.last line)=='\r'
+                          then BS.init line
+                          else line
+--           print $ "read line:"++line'
+    if BS.null line'
+      then return acc
+      else readHandle h (acc ++ [line'])
+
+-- | Start server and wait for connections
+server ::
+      Int                              -- ^ Port number
+   -> (YamlObject -> IO YamlObject)    -- ^ Worker
+   -> IO ()
+server port callOut = do
+--        installHandler sigPIPE Ignore Nothing    
+      sock  <- listenOn (PortNumber $ fromIntegral port)
+      (forever $ loop sock) `finally` sClose sock
+  where
+    loop :: Socket -> IO ThreadId
+    loop sock =
+         do (h,_nm,_port) <- accept sock
+            forkIO
+              (do 
+                hSetBuffering h NoBuffering
+                lns <- readHandle h []
+                let text = BS.unlines lns
+                case unserialize text of
+                  Nothing -> hClose h
+                  Just ob -> do
+--                     print ob
+                    res <- callOut ob
+                    BS.hPutStrLn h $ serialize res
+                    hClose h)
+
diff --git a/Network/YAML/WrapMethods.hs b/Network/YAML/WrapMethods.hs
new file mode 100644
--- /dev/null
+++ b/Network/YAML/WrapMethods.hs
@@ -0,0 +1,51 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+module Network.YAML.WrapMethods
+  (remote, declareRules)
+  where
+
+import Language.Haskell.TH
+import Control.Monad
+import Data.Char (toUpper)
+import Data.Object.Yaml
+import qualified Data.ByteString.Char8 as BS
+
+import Network.YAML.Base
+import Network.YAML.Caller
+import Network.YAML.Derive
+import Network.YAML.Instances
+import Network.YAML.Dispatcher
+
+-- | Declare given function as remote method. 
+-- This creates a function with same name as given (so qualified name must be
+-- used as argument), and almost same behaivour. Difference is that newly
+-- declared function takes pair (host name, port number) as first argument.
+remote :: Name -> Q [Dec]
+remote name = do
+  srv <- newName "srv"
+  let c = clause [varP srv] (normalB [| call $(varE srv) $(stringOfName name) |]) []
+      cName = mkName $ nameBase name
+  (VarI _ tp _ _) <- reify name
+  let AppT (AppT ArrowT a) ioB = tp
+  sequence [
+    sigD cName [t| (BS.ByteString, Int) -> $(return a) -> $(return ioB) |],
+    funD cName [c]]
+
+rulePair :: Name -> ExpQ
+rulePair name = [| ($(stringOfName name), yamlMethod $(varE name)) |]
+
+mkList :: [Exp] -> ExpQ
+mkList [] = [| [] |]
+mkList (e:es) = [| $(return e): $(mkList es) |]
+
+-- | Declare dispatching rules for given list of functions. 
+-- Map with rules will be called dispatchingRules.
+-- For each given function RPC method with same name will be declared.
+declareRules :: [Name] -> Q [Dec]
+declareRules names = do
+  pairs <- mapM rulePair names
+  let body = [| mkRules $(mkList pairs) |]
+      c = clause [] (normalB body) []
+  sequence [
+    funD (mkName "dispatchingRules") [c]]
+
diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,20 @@
+YAML-RPC README
+===============
+Ilya V. Portnov <portnov84@rambler.ru>
+
+The yaml-rpc package contains a small library to organize remote procedure call
+(RPC) over TCP/IP network, using YAML as data serialization format.
+
+RPC server should supply a set of "RPC methods", which are simply functions ::
+a -> IO b, `a' and 'b' should be of class IsYamlObject. This class guarantees
+that values of given type can be serialized to YAML and de-serialized.
+Network.YAML.Instances module provides some instances declaration for this
+typeclass. Moreover, Network.YAML.Derive module contains (TemplateHaskell)
+function deriveIsYamlObject, which will help you to declare `instance
+IsYamlObject ...' for almost any ADT.
+
+You can see examples of usage in files Test.hs and TestCall.hs. Haddock
+documentation is here: http://iportnov.ru/files/yaml-rpc/html/index.html.
+
+Depends: ghc >= 6.10, network, data-object, data-object-yaml, yaml,
+data-default, convertible-text.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/Test.hs b/Test.hs
new file mode 100644
--- /dev/null
+++ b/Test.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE OverloadedStrings, TemplateHaskell #-}
+-- | Test server
+module Main where
+
+import Data.Object.Yaml
+import Data.Convertible.Base
+import qualified Data.Map as M
+
+import Network.YAML
+
+import TestTypes
+import Methods
+
+-- Declare dispatchingRules for given functions
+$(declareRules ['double, 'mySum, 'counter, 'ls])
+
+main = do
+  putStrLn "Listening..."
+  -- Start 3 listeners on 3 ports
+  forkA [dispatcher 5000 dispatchingRules,
+         dispatcher 5001 dispatchingRules,
+         dispatcher 5002 dispatchingRules]
+  return ()
diff --git a/TestCall.hs b/TestCall.hs
new file mode 100644
--- /dev/null
+++ b/TestCall.hs
@@ -0,0 +1,47 @@
+{-# LANGUAGE OverloadedStrings, TemplateHaskell #-}
+-- | Test client
+module Main where
+
+import Data.Object.Yaml
+import Data.Convertible.Base
+
+import Network.YAML
+
+import TestTypes
+import qualified Methods
+
+-- declare `double', `mySum' and `ls' as RPC methods
+$(remote 'Methods.double)
+$(remote 'Methods.mySum)
+$(remote 'Methods.ls)
+-- For example, `ls' is defined in Methods.hs as
+-- ls :: String -> IO [String]
+-- Now `ls' is defined here as
+-- ls :: (ByteString,Int) -> String -> IO [String]
+
+rules = [("test", ("127.0.0.1", 5000), 1),
+         ("test", ("127.0.0.1", 5001), 1),
+         ("test", ("127.0.0.1", 5002), 1)]
+
+getService = selectRandom rules
+
+p = Point 2.0 3.0
+
+ps = [Point 3.0 5.0, Point 1.0 2.1, Point 0.1 0.2]
+
+main = do
+  test <- getService "test"
+
+  -- call remote functions
+  r <- double test p
+  print r
+  s <- mySum test [3.5, 5.5, 1.0]
+  print s
+  lst <- ls test "/tmp"
+  print lst
+
+  -- call remote functions for many arguments, for each argument on different server maybe
+  rs <- callP getService "test" "double" ps
+  print (rs :: [Point])
+  cs <- callP getService "test" "counter" $ zip ([3,4,5,6] :: [Int]) ([1..] :: [Int])
+  print (cs :: [Int])
diff --git a/yaml-rpc.cabal b/yaml-rpc.cabal
new file mode 100644
--- /dev/null
+++ b/yaml-rpc.cabal
@@ -0,0 +1,68 @@
+Name:                yaml-rpc
+
+-- The package version. See the Haskell package versioning policy
+-- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for
+-- standards guiding when and how versions should be incremented.
+Version:             0.1
+
+-- A short (one-line) description of the package.
+Synopsis:            Simple library for network (TCP/IP) YAML RPC
+
+-- A longer description of the package.
+Description:         This library aimed to organize remote procedure call (RPC) 
+                     over TCP/IP network, using YAML as data serialization format.
+
+-- URL for the project homepage or repository.
+Homepage:            http://iportnov.ru/en/projects/yaml-rpc-0/
+
+-- The license under which the package is released.
+License:             LGPL-3
+
+-- The file containing the license text.
+License-file:        LICENSE
+
+-- The package author(s).
+Author:              Ilya V. Portnov
+
+-- An email address to which users can send suggestions, bug reports,
+-- and patches.
+Maintainer:          portnov84@rambler.ru
+
+-- A copyright notice.
+-- Copyright:           
+
+Category:            Network
+
+Build-type:          Simple
+
+-- Extra files to be distributed with the package, such as examples or
+-- a README.
+Extra-source-files:  README Test.hs TestCall.hs
+
+-- Constraint on the version of Cabal needed to build this package.
+Cabal-version:       >=1.4
+
+
+Library
+  -- Modules exported by the library.
+  Exposed-modules:     Network.YAML.Derive,
+                       Network.YAML.Server,
+                       Network.YAML.Caller,
+                       Network.YAML.Dispatcher,
+                       Network.YAML.Instances,
+                       Network.YAML.Base,
+                       Network.YAML.WrapMethods,
+                       Network.YAML.Balancer,
+                       Network.YAML
+  
+  -- Packages needed in order to build this package.
+  Build-depends:       yaml, data-object-yaml, network, template-haskell, bytestring,
+                       data-object, data-default, base >= 3 && <= 5, mtl, convertible-text,
+                       containers, random
+  
+  -- Modules not exported by this package.
+  -- Other-modules:       
+  
+  -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.
+  -- Build-tools:         
+  
