diff --git a/Examples/ClientServer/Client.hs b/Examples/ClientServer/Client.hs
new file mode 100644
--- /dev/null
+++ b/Examples/ClientServer/Client.hs
@@ -0,0 +1,61 @@
+
+module Main(main) where
+
+import           Holumbus.Common.Debug
+import           Holumbus.Common.Logging
+import           Holumbus.Common.Utils
+import           Holumbus.Network.PortRegistry.PortRegistryPort
+import           Holumbus.Network.Communication
+
+version :: String
+version = "Holumbus-Communication Client 0.1"
+
+
+main :: IO ()
+main
+  = do
+    putStrLn version
+    handleAll (\e -> putStrLn $ "EXCEPTION: " ++ show e) $
+      do
+      initializeLogging []
+      p <- newPortRegistryFromXmlFile "/tmp/registry.xml"
+      setPortRegistry p
+      client <- initializeData
+      waitForInput client
+      deinitializeData client
+
+waitForInput :: Client -> IO ()
+waitForInput client
+  = do
+    line <- getLine
+    case line of
+      "exit"  -> 
+        return ()
+      "debug" -> 
+        do
+        printDebug client
+        waitForInput client
+      _ -> 
+        waitForInput client
+
+
+dispatch 
+  :: String 
+  -> IO (Maybe String)
+dispatch msg
+  = do
+    putStrLn $ "message arrived: " ++ msg
+    return Nothing
+
+
+initializeData :: IO (Client)
+initializeData 
+  = do
+    client <- newClient "server" Nothing dispatch
+    return client
+
+
+deinitializeData :: Client -> IO ()
+deinitializeData client
+  = do
+    closeClient client
diff --git a/Examples/ClientServer/Makefile b/Examples/ClientServer/Makefile
new file mode 100644
--- /dev/null
+++ b/Examples/ClientServer/Makefile
@@ -0,0 +1,31 @@
+# Making FileSystem-Standalone Programs
+
+HOME		= ../..
+
+SOURCE		= .
+
+GHC_FLAGS	= -Wall -threaded -O2 -hidir $(OUTPUT) -odir $(OUTPUT)
+GHC		= ghc $(GHC_FLAGS)
+
+RM_FLAGS	= -rf
+RM		= rm $(RM_FLAGS)
+
+PROG		= Client Server
+
+OUTPUT		= output
+
+all : $(PROG)
+
+#prof : $(PROG).hs
+#	[ -d $(OUTPUT) ] || mkdir -p $(OUTPUT)
+#	$(RM) $(OUTPUT)/*
+#	$(GHC) -prof -auto-all -ignore-package Holumbus -i../../source/ --make -o $(PROG)_p $(PROG).hs
+
+% : %.hs
+	[ -d $(OUTPUT) ] || mkdir -p $(OUTPUT)
+	$(RM) $(OUTPUT)/*
+	$(GHC) --make -o $@ $<
+
+clean :
+	$(RM) $(PROG) $(OUTPUT) *.port
+	
diff --git a/Examples/ClientServer/Server.hs b/Examples/ClientServer/Server.hs
new file mode 100644
--- /dev/null
+++ b/Examples/ClientServer/Server.hs
@@ -0,0 +1,75 @@
+
+module Main(main) where
+
+import           Holumbus.Common.Debug
+import           Holumbus.Common.Logging
+import           Holumbus.Common.Utils
+import           Holumbus.Network.PortRegistry.PortRegistryPort
+import           Holumbus.Network.Communication
+
+
+version :: String
+version = "Holumbus-Communication Server 0.1"
+
+
+main :: IO ()
+main
+  = do
+    putStrLn version
+    handleAll (\e -> putStrLn $ "EXCEPTION: " ++ show e) $
+      do
+      initializeLogging []
+      p <- newPortRegistryFromXmlFile "/tmp/registry.xml"
+      setPortRegistry p
+      server <- initializeData
+      waitForInput server
+      deinitializeData server
+
+
+waitForInput :: Server -> IO ()
+waitForInput server
+  = do
+    line <- getLine
+    case line of
+      "exit"  -> 
+        return ()
+      "debug" -> 
+        do
+        printDebug server
+        waitForInput server
+      _ -> 
+        waitForInput server
+
+
+dispatch 
+  :: String 
+  -> IO (Maybe String)
+dispatch msg
+  = do
+    putStrLn $ "message arrived: " ++ msg
+    return Nothing
+
+
+register :: IdType -> ClientPort -> IO ()
+register i cp
+  = do
+    putStrLn $ "register request: Id: " ++ show i ++ " -- Port: " ++ show cp
+
+
+unregister :: IdType -> ClientPort -> IO ()
+unregister i cp
+  = do
+    putStrLn $ "unregister request: Id: " ++ show i ++ " -- Port: " ++ show cp
+
+
+initializeData :: IO (Server)
+initializeData 
+  = do
+    server <- newServer "server" Nothing dispatch (Just register) (Just unregister)
+    return server
+
+
+deinitializeData :: Server -> IO ()
+deinitializeData server
+  = do
+    closeServer server
diff --git a/Examples/Makefile b/Examples/Makefile
new file mode 100644
--- /dev/null
+++ b/Examples/Makefile
@@ -0,0 +1,13 @@
+# Making all examples
+
+ALLEXAMPLES       = ClientServer Ports
+
+
+all :
+	$(foreach i,$(ALLEXAMPLES),$(MAKE) -C $i all ;)
+
+wc :
+	@wc -l `find . -wholename './_darcs/*' -prune -o -name "*.hs" -print`
+
+clean :
+	$(foreach i,$(ALLEXAMPLES),$(MAKE) -C $i $@ ;)
diff --git a/Examples/Ports/Makefile b/Examples/Ports/Makefile
new file mode 100644
--- /dev/null
+++ b/Examples/Ports/Makefile
@@ -0,0 +1,31 @@
+# Making FileSystem-Standalone Programs
+
+HOME		= ../..
+
+SOURCE		= .
+
+GHC_FLAGS	= -Wall -threaded -O2 -hidir $(OUTPUT) -odir $(OUTPUT)
+GHC		= ghc $(GHC_FLAGS)
+
+RM_FLAGS	= -rf
+RM		= rm $(RM_FLAGS)
+
+PROG		= Single Sender Receiver
+
+OUTPUT		= output
+
+all : $(PROG)
+
+#prof : $(PROG).hs
+#	[ -d $(OUTPUT) ] || mkdir -p $(OUTPUT)
+#	$(RM) $(OUTPUT)/*
+#	$(GHC) -prof -auto-all -ignore-package Holumbus -i../../source/ --make -o $(PROG)_p $(PROG).hs
+
+% : %.hs
+	[ -d $(OUTPUT) ] || mkdir -p $(OUTPUT)
+	$(RM) $(OUTPUT)/*
+	$(GHC) --make -o $@ $<
+
+clean :
+	$(RM) $(PROG) $(OUTPUT) p.port port.xml
+	
diff --git a/Examples/Ports/Receiver.hs b/Examples/Ports/Receiver.hs
new file mode 100644
--- /dev/null
+++ b/Examples/Ports/Receiver.hs
@@ -0,0 +1,98 @@
+-- ----------------------------------------------------------------------------
+{- |
+  Module     : 
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+
+-}
+-- ----------------------------------------------------------------------------
+
+module Main(main) where
+
+import           Control.Concurrent
+import qualified Data.ByteString.Lazy as B
+
+import           Holumbus.Common.Logging
+import           Holumbus.Common.Utils
+import           Holumbus.Network.Port
+import           Holumbus.Network.PortRegistry.PortRegistryPort
+import qualified Holumbus.Console.Console as Console
+
+
+type StringStream = Stream String
+type StringPort   = Port String
+
+
+newStringStream :: IO StringStream
+newStringStream = newLocalStream Nothing
+
+
+decodeStringPort :: Maybe B.ByteString -> Maybe StringPort
+decodeStringPort = decodeMaybe
+
+
+version :: String
+version = "Ports-Demo Receiver 0.1"
+
+
+main :: IO ()
+main
+  = do
+    initializeLogging []
+    putStrLn version    
+    putStrLn "Begin"
+    reg <- newPortRegistryFromXmlFile "/tmp/registry.xml"
+    setPortRegistry reg
+    printStreamController
+    putStrLn "initialising streams..."
+    s <- newStringStream
+    p <- newPortFromStream s
+    globalS <- newStream  STGlobal  (Just "global")  (Just 10002)
+    putStrLn "streams initialised"
+    writePortToFile p "p.port"
+    forkIO $ printMessages "global" globalS
+    Console.handleUserInput createConsole ()
+
+
+printMessages :: String -> StringStream -> IO ()
+printMessages info s
+  = do
+    msg <- readStreamMsg s
+    putStrLn $ "port: " ++ info
+    putStrLn "Incoming Message:"
+    putStrLn $ show msg
+    let replyPort = decodeStringPort $ getGenericData msg
+    let text      = getMessageData msg
+    case replyPort of
+        (Nothing) ->  
+          do
+          putStrLn "no reply port in message"
+        (Just p) ->
+          do
+          send p ("ECHO:" ++ text)
+    printMessages info s
+    
+    
+createConsole :: Console.ConsoleData ()
+createConsole =
+  Console.addConsoleCommand "debug" printDebug "prints internal state of the filesystem (DEBUG)" $ 
+  Console.addConsoleCommand "version" printVersion "prints the version" $ 
+  Console.initializeConsole
+
+ 
+printDebug :: () -> [String] -> IO ()
+printDebug _ _
+  = do
+    printStreamController
+  
+printVersion :: () -> [String] -> IO ()
+printVersion _ _
+  = do
+    putStrLn version
+
diff --git a/Examples/Ports/Sender.hs b/Examples/Ports/Sender.hs
new file mode 100644
--- /dev/null
+++ b/Examples/Ports/Sender.hs
@@ -0,0 +1,105 @@
+-- ----------------------------------------------------------------------------
+{- |
+  Module     : 
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+
+-}
+-- ----------------------------------------------------------------------------
+
+module Main(main) where
+    
+import           Data.List
+-- import           Data.Binary
+
+import           Holumbus.Common.Logging
+import           Holumbus.Network.Port
+import           Holumbus.Network.PortRegistry.PortRegistryPort
+import qualified Holumbus.Console.Console as Console
+
+
+version :: String
+version = "Ports-Demo Sender 0.1"
+
+
+main :: IO ()
+main
+  = do
+    initializeLogging []
+    putStrLn version
+    putStrLn "Begin"
+    printStreamController 
+    reg <- newPortRegistryFromXmlFile "/tmp/registry.xml"
+    setPortRegistry reg
+    p <- readPortFromFile "p.port"
+    Console.handleUserInput createConsole p
+
+        
+createConsole :: Console.ConsoleData (Port String)
+createConsole =
+  -- Console.addConsoleCommand "send" sendMsg "sends a message" $
+  -- Console.addConsoleCommand "sendP" sendPMsg "sends a message to the private port of the receiver" $
+  -- Console.addConsoleCommand "sendN" sendNMsg "sends a message to the named port of the receiver" $
+  Console.addConsoleCommand "sendG" sendGMsg "sends a message to the global port of the receiver" $
+  Console.addConsoleCommand "debug" printDebug "prints internal state of the filesystem (DEBUG)" $ 
+  Console.addConsoleCommand "version" printVersion "prints the version" $ 
+  Console.initializeConsole
+
+{-
+sendMsg :: StringPort -> [String] -> IO ()
+sendMsg p line
+  = do
+    respStream <- newStringStream
+    respPort <- newPortFromStream respStream
+    let msg = intercalate " " line
+    sendWithGeneric p msg (encode respPort)
+    response <- tryWaitReadStreamMsg respStream time10
+    case response of
+      -- if no response
+      Nothing -> putStrLn "no response in 10 seconds"          
+      -- handle the response
+      (Just r) -> putStrLn $ "ResponseMessage:\n" ++ show r
+    closeStream respStream
+    
+sendPMsg :: StringPort -> [String] -> IO ()
+sendPMsg _ line
+  = do
+    privPort <- (newPort "private" "localhost" 10000)::IO StringPort
+    let msg = intercalate " " line
+    send privPort msg
+ 
+ 
+sendNMsg :: StringPort -> [String] -> IO ()
+sendNMsg _ line
+  = do
+    namedPort <- (newPort "named" "localhost" 10001)::IO StringPort
+    let msg = intercalate " " line
+    send namedPort msg
+-}
+
+sendGMsg :: (Port String) -> [String] -> IO ()
+sendGMsg _ line
+  = do
+    globalPort <- (newGlobalPort "global")::IO (Port String)
+    let msg = intercalate " " line
+    send globalPort msg
+
+
+printDebug :: (Port String) -> [String] -> IO ()
+printDebug _ _
+  = do
+    printStreamController
+
+
+
+
+printVersion :: (Port String) -> [String] -> IO ()
+printVersion _ _
+  = do
+    putStrLn version
diff --git a/Examples/Ports/Single.hs b/Examples/Ports/Single.hs
new file mode 100644
--- /dev/null
+++ b/Examples/Ports/Single.hs
@@ -0,0 +1,108 @@
+-- ----------------------------------------------------------------------------
+{- |
+  Module     : 
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+
+-}
+-- ----------------------------------------------------------------------------
+
+module Main(main) where
+
+import           Data.Binary
+import qualified Data.ByteString.Lazy as B
+
+import           Holumbus.Common.Logging
+import           Holumbus.Network.Port
+
+
+version :: String
+version = "Holumbus-Ports Single-Demo 0.1"
+
+
+type StringStream = Stream String
+type StringPort   = Port String
+
+
+decodeMaybe :: (Binary a) => Maybe B.ByteString -> Maybe a
+decodeMaybe Nothing = Nothing
+decodeMaybe (Just b) = (Just $ decode b)
+
+
+decodeStringPort :: Maybe B.ByteString -> Maybe StringPort
+decodeStringPort = decodeMaybe
+
+
+
+main :: IO ()
+main
+  = do
+    initializeLogging []
+    putStrLn version
+    
+    putStrLn ""
+    putStrLn "opening private Streams and Ports"
+    
+    printStreamController
+    stream1 <- (newLocalStream (Just "stream1")):: IO StringStream
+    stream2 <- (newLocalStream (Just "stream2")):: IO StringStream
+    printStreamController
+    
+    testCase stream1 stream2 "Hello World"
+    
+    putStrLn ""
+    putStrLn "closing streams..."
+    closeStream stream1
+    closeStream stream2
+    printStreamController
+    
+    
+    
+testCase :: StringStream -> StringStream -> String -> IO ()
+testCase stream1 stream2 t
+  = do
+    putStrLn ""
+    putStrLn "Begin"
+
+    port1   <- newPortFromStream stream1
+    port2   <- newPortFromStream stream2
+    
+    putStrLn ""
+    putStrLn $ "Sending: " ++ t
+    sendWithGeneric port1 t (encode port2)
+    printStreamController
+
+    putStrLn ""
+    putStrLn "Reading result..."
+    msg1 <- readStreamMsg stream1
+    putStrLn "Result:"
+    putStrLn $ "Text: " ++ getMessageData msg1
+    putStrLn $ "Msg: " ++ show msg1
+    
+    putStrLn ""
+    putStrLn "echoing result..."
+    let replyPort = decodeStringPort $ getGenericData msg1
+    let text      = getMessageData msg1
+    case replyPort of    
+        (Nothing) ->
+          do
+          putStrLn "no reply port in message"
+        (Just p) ->
+          do
+          send p ("ECHO:" ++ text)
+    
+
+    putStrLn "Reading echo..."
+    msg2 <- readStreamMsg stream2
+    putStrLn "Result:"
+    putStrLn $ "Text: " ++ getMessageData msg2
+    putStrLn $ "Msg: " ++ show msg2
+        
+    putStrLn ""
+    putStrLn "End"
diff --git a/Holumbus-Distribution.cabal b/Holumbus-Distribution.cabal
new file mode 100644
--- /dev/null
+++ b/Holumbus-Distribution.cabal
@@ -0,0 +1,74 @@
+name:          Holumbus-Distribution
+version:       0.0.1
+license:       OtherLicense
+license-file:  LICENSE
+author:        Stefan Schmidt, Uwe Schmidt
+copyright:     Copyright (c) 2008 Stefan Schmidt, Uwe Schmidt
+maintainer:    Stefan Schmidt <sts@holumbus.org>
+stability:     experimental
+category:      Distributed Computing, Network
+synopsis:      intra- and inter-program communication
+homepage:      http://holumbus.fh-wedel.de
+description:   Holumbus-Distribution offers Erlang-Style mailboxes for an easy implementation
+               of distributed systems in Haskell. The mailboxes can be used to exchange messages
+               between threads inside a single program or between programs over the network.
+build-type:    Simple
+cabal-version: >=1.6
+
+extra-source-files:
+    README
+    Makefile
+    Programs/Makefile
+    Programs/PortRegistry/Makefile
+    Programs/PortRegistry/PortRegistry.hs
+    Examples/Makefile
+    Examples/ClientServer/Client.hs
+    Examples/ClientServer/Makefile
+    Examples/ClientServer/Server.hs
+    Examples/Ports/Makefile
+    Examples/Ports/Receiver.hs
+    Examples/Ports/Sender.hs
+    Examples/Ports/Single.hs
+
+library
+  build-depends:  base       >= 4
+                , binary     >= 0.4
+                , bytestring >= 0.9
+                , containers >= 0.1
+                , editline   >= 0.2
+                , haskell98  >= 1
+                , hslogger   >= 1.0
+                , hxt        >= 8.2
+                , network    >= 2.1
+                , time       >= 1.1
+                , unix       >= 2.3
+
+  hs-source-dirs: 
+                  source
+  exposed-modules: Holumbus.Data.AccuMap
+                 , Holumbus.Data.KeyMap
+                 , Holumbus.Data.MultiMap
+                 , Holumbus.Network.Communication
+                 , Holumbus.Network.Core
+                 , Holumbus.Network.Messages
+                 , Holumbus.Network.Port
+                 , Holumbus.Network.Site
+                 , Holumbus.Network.PortRegistry
+                 , Holumbus.Network.PortRegistry.Messages
+                 , Holumbus.Network.PortRegistry.PortRegistryData
+                 , Holumbus.Network.PortRegistry.PortRegistryPort
+                 , Holumbus.Console.Console
+                 , Holumbus.Common.Debug
+                 , Holumbus.Common.FileHandling
+                 , Holumbus.Common.Logging
+                 , Holumbus.Common.Threading
+                 , Holumbus.Common.Utils
+
+  ghc-options: -Wall -threaded
+  extensions: Arrows DeriveDataTypeable ExistentialQuantification
+
+executable PortRegistry
+  main-is: PortRegistry.hs
+  hs-source-dirs: Programs/PortRegistry source
+  ghc-options: -Wall -threaded
+  extensions: Arrows DeriveDataTypeable ExistentialQuantification
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2008 Stefan Schmidt
+
+Permission is hereby granted, free of charge, to any person obtaining 
+a copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
+sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
+THE SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,56 @@
+# Making all
+#
+# Building the library and generating documentation is done by cabal,
+# only the tests and the examples will be built using make.
+
+# TEST_BASE	= test
+EXAMPLES_BASE	= Examples
+PROGRAMS_BASE	= Programs
+
+all : configure build doc dist
+
+configure :
+	@runhaskell Setup.hs configure
+
+doc	: configure
+	@runhaskell Setup.hs haddock --hyperlink-source --hscolour-css=hscolour.css
+
+build	: configure
+	@runhaskell Setup.hs build
+
+install :
+	@runhaskell Setup.hs install --global
+
+dist	:
+	@runhaskell Setup.hs sdist
+
+prof	:
+	@runhaskell Setup.hs configure -p
+	@runhaskell Setup.hs build
+
+# alltests :
+#	$(MAKE) -C $(TEST_BASE) all
+
+examples :
+	$(MAKE) -C $(EXAMPLES_BASE) all
+
+programs :	
+	$(MAKE) -C $(PROGRAMS_BASE) all
+
+wc :
+	@wc -l `find ./source/Holumbus -wholename './_darcs/*' -prune -o -name "*.hs" -print`   
+	# $(MAKE) -C $(TEST_BASE) wc
+	$(MAKE) -C $(EXAMPLES_BASE) wc
+	$(MAKE) -C $(PROGRAMS_BASE) wc
+
+zip:	clean
+	@zip -r holumbus_mapreduce$$(date +%Y%m%d_%H%M).zip *
+
+clean :
+	@runhaskell Setup.hs clean
+	@rm -rf holumbus_mapreduce*.zip
+	# $(MAKE) -C $(TEST_BASE) clean
+	$(MAKE) -C $(EXAMPLES_BASE) clean
+	$(MAKE) -C $(PROGRAMS_BASE) clean
+
+.PHONY	: configure build doc dist clean zip wc examples programs
diff --git a/Programs/Makefile b/Programs/Makefile
new file mode 100644
--- /dev/null
+++ b/Programs/Makefile
@@ -0,0 +1,18 @@
+# Making all examples
+
+# COMMUNICATION     = Communication/ClientServer Communication/Ports
+PORTREGISTRY      = PortRegistry
+ALLPROGRAMS       = $(PORTREGISTRY)
+
+
+all :
+	$(foreach i,$(ALLPROGRAMS),$(MAKE) -C $i all ;)
+
+registry :
+	$(foreach i,$(PORTREGISTRY),$(MAKE) -C $i all ;)
+
+wc :
+	@wc -l `find . -wholename './_darcs/*' -prune -o -name "*.hs" -print`
+
+clean :
+	$(foreach i,$(ALLPROGRAMS),$(MAKE) -C $i $@ ;)
diff --git a/Programs/PortRegistry/Makefile b/Programs/PortRegistry/Makefile
new file mode 100644
--- /dev/null
+++ b/Programs/PortRegistry/Makefile
@@ -0,0 +1,30 @@
+
+HOME		= ../..
+
+SOURCE		= .
+
+GHC_FLAGS	= -Wall -threaded -O2 -hidir $(OUTPUT) -odir $(OUTPUT)
+GHC		= ghc $(GHC_FLAGS)
+
+RM_FLAGS	= -rf
+RM		= rm $(RM_FLAGS)
+
+PROG		= PortRegistry
+
+OUTPUT		= output
+
+all : $(PROG)
+
+#prof : $(PROG).hs
+#	[ -d $(OUTPUT) ] || mkdir -p $(OUTPUT)
+#	$(RM) $(OUTPUT)/*
+#	$(GHC) -prof -auto-all -ignore-package Holumbus -i../../source/ --make -o $(PROG)_p $(PROG).hs
+
+% : %.hs
+	[ -d $(OUTPUT) ] || mkdir -p $(OUTPUT)
+	$(RM) $(OUTPUT)/*
+	$(GHC) --make -o $@ $<
+
+clean :
+	$(RM) $(PROG) $(OUTPUT) registry.xml registry.port
+	
diff --git a/Programs/PortRegistry/PortRegistry.hs b/Programs/PortRegistry/PortRegistry.hs
new file mode 100644
--- /dev/null
+++ b/Programs/PortRegistry/PortRegistry.hs
@@ -0,0 +1,95 @@
+-- ----------------------------------------------------------------------------
+{- |
+  Module     : 
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+
+-}
+-- ----------------------------------------------------------------------------
+
+module Main(main) where
+
+import           Holumbus.Common.Logging
+import           Holumbus.Common.FileHandling
+import           Holumbus.Common.Utils
+import           Holumbus.Network.Port
+import           Holumbus.Network.PortRegistry
+import           Holumbus.Network.PortRegistry.PortRegistryData
+import qualified Holumbus.Console.Console as Console
+
+
+version :: String
+version = "Holumbus-PortRegistry 0.1"
+
+
+main :: IO ()
+main
+  = do
+    initializeLogging []
+    let sn = "portregistry"
+    let po = (Just 9000)
+    r <- newPortRegistryData sn po
+    p <- getPortRegistryRequestPort r
+    writePortToFile p "/tmp/registry.port"
+    saveToXmlFile "/tmp/registry.xml" p
+    Console.handleUserInput createConsole r 
+    putStrLn version
+
+    
+createConsole :: Console.ConsoleData PortRegistryData
+createConsole =
+  Console.addConsoleCommand "register" 	 hdlRegister   "registers a port manually" $
+  Console.addConsoleCommand "unregister" hdlUnregister "unregisters a port manually" $
+  Console.addConsoleCommand "lookup" 	 hdlLookup     "gets the socket id for a port" $
+  Console.addConsoleCommand "ports" 	 hdlGetPorts   "lists all ports" $ 
+  Console.addConsoleCommand "version"    hdlVersion    "prints the version" $
+  Console.initializeConsole
+
+
+hdlRegister :: PortRegistryData -> [String] -> IO ()
+hdlRegister prd opts
+  = do
+    handleAll (\_ -> putStrLn "usage: register <streamname> <hostname> <socketId>") $
+      do
+      let sn = head opts
+      let hn = head $ tail opts
+      let po = fromInteger $ read $ head $ tail $ tail opts
+      registerPort sn (SocketId hn po) prd
+
+
+hdlUnregister :: PortRegistryData -> [String] -> IO ()
+hdlUnregister prd opts
+  = handleAll (\_ -> putStrLn "usage: unregister <streamname>") $
+      do
+      let sn = head opts
+      unregisterPort sn prd
+
+
+hdlLookup :: PortRegistryData -> [String] -> IO ()
+hdlLookup prd opts
+  = handleAll (\_ -> putStrLn "usage: lookup <streamname>") $
+      do
+      let sn = head opts
+      soid <- lookupPort sn prd
+      putStrLn $ show soid
+
+
+hdlGetPorts :: PortRegistryData -> [String] -> IO ()
+hdlGetPorts prd _
+  = do
+    ls <- getPorts prd
+    putStrLn $ show ls
+
+
+hdlVersion :: PortRegistryData -> [String] -> IO ()
+hdlVersion _ _
+  = do
+    putStrLn version
+
+-- ------------------------------------------------------------
diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,156 @@
+This is the Holumbus-Distribution Library
+
+Version 0.0.1
+
+Stefan Schmidt sts@holumbus.org
+
+http://holumbus.fh-wedel.de
+
+
+About
+-----
+
+Holumbus is a set of Haskell libraries. This package contains the 
+Holumbus-Distribution library for building and running a distributed systems.
+One of the core elements of this library is an Erlang-like mailbox 
+system for interchanging messages between different threads or applications. 
+
+This library itself is independent from other Holumbus libraries.
+
+
+Documentation:
+------------------------------------------
+
+The "Chan" data type form Control.Concurrent.Chan is pretty useful.
+You can easily use it as a queue for the consumer-producer-problem. One
+thread writes into the channel, the other reads the data from it. But this
+only works, if the two threads are running in the same address space.
+That means the Chan data type cannot be used for the communication of
+distinct applications, but this scenario is a normal use case.
+
+Therefore it would be very useful to have a single framework for inter- 
+and intra-process communication. One thread can create a mailbox and other 
+threads can send messages to it, though it should make no difference, 
+if the threads are in the same address space or not.
+
+This libary offers a "Stream-Port" implementation, borrowed from the
+multi-paradigm programming language Mozart/Oz.
+
+A stream in this context is like a mailbox or a receiver. Other threads can send
+messages to it via a port. A port in this context has nothing to do with the
+port number of a unix-socket. Think of it as a sender.
+
+To address a stream over the network easily, you can give him a unique name.
+Then you can create a port, give him that stream name and the messages will
+be send directly to the stream. This requires you to start the PortRegistry.
+
+The PortRegistry keeps a log for all global communication streams in the
+network. It MUST be started BEFORE all other programs. In future versions this
+explicit execution sequence might not be necessary any more, but for now the
+FIRST thing you have to start is the PortRegistry. There is ONLY ONE one
+instance allowed in the whole communication network (this might also change).
+
+You can find the main parts for the communication in the module
+"Holumbus.Network.Port"
+
+This library also contains some parts which might be useful, e.g. some
+specialized maps (Holumbus.Data) and a commandline user interface
+(Holumbus.Console). They are used in other Holumbus libraries.
+
+
+Contents
+--------
+
+Examples  Some example applications
+Programs  The applications you need to run a distributed system.
+source    Source code of the Holumbus-Distribution library.
+
+
+Requirements
+------------
+
+So far, this library is only tested under Linux, please tell me, if you have 
+problems under Windows or other OS.
+The Holumbus-Distribution library requires at least GHC 6.10 and the 
+following packages (available via Hackage).
+
+  containers
+  hslogger
+  network 
+  unix
+  time
+  bytestring
+  binary
+  hxt
+
+
+Installation
+------------
+
+A Cabal file is provided, therefore Holumbus-Distribution can be installed using
+the standard Cabal way:
+
+$ runhaskell Setup.hs configure
+$ runhaskell Setup.hs build
+$ runhaskell Setup.hs install --global # with root privileges
+
+This will generate the library and the PortRegestry program.
+
+For those who prefer to build it the old way with make:
+
+$ make build
+$ make install # with root privileges
+
+If you want to run your own distributed system, you'll need to compile the
+PortRegistry, too. This can be done with
+
+$ make programs
+
+
+Steps to make a distributed system running
+--------------------------------
+
+Before you can use the mailboxes in your own programs, you need to start the
+PortRegistry BEFORE running any of you programs. If you have compiled the
+PortRegistry, you can start it with: 
+
+$ cd Programs/PortRegistry
+$ ./PortRegistry
+
+This will create a file "registry.xml" in your "/tmp" directory. This file
+contains all information for your programs to access the PortRegistry.
+It is wise to copy this file to every computer, on which you want to run a 
+program of your system.
+
+Before you can send/receive messages in your programs, you'll need to
+load the "registry.xml" file. This can be done by two simple lines in the
+IO-monad:
+
+p <- newPortRegistryFromXmlFile "/tmp/registry.xml"
+setPortRegistry p
+
+To create a simple Mailbox for receiving messages, you can look a the following
+demo-program:
+      
+main :: IO ()
+main
+  = do
+    reg <- newPortRegistryFromXmlFile "/tmp/registry.xml"
+    setPortRegistry reg
+    gS <- (newGlobalStream "global"):: IO (Stream String)
+    msg <- readStream gS
+    putStrLn msg
+
+This program will set up a mailbox and wait till the first message is received
+and print it out. Then is will terminate.
+And the following program will send a message to your mailbox:      
+      
+main :: IO ()
+main
+  = do
+    reg <- newPortRegistryFromXmlFile "/tmp/registry.xml"
+    setPortRegistry reg
+    gP <- (newGlobalPort "global")::IO (Port String)
+    send gP "Hello World"
+      
+This program just sends one message to your mailbox.      
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/source/Holumbus/Common/Debug.hs b/source/Holumbus/Common/Debug.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Common/Debug.hs
@@ -0,0 +1,24 @@
+-- ----------------------------------------------------------------------------
+{- |
+  Module     : Holumbus.Common.Debug
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+
+  A typeclass for printing debug output.
+
+-}
+-- ----------------------------------------------------------------------------
+
+module Holumbus.Common.Debug where
+
+
+class Debug m where
+
+  -- | Just print out some debug output.  
+  printDebug :: m -> IO ()
diff --git a/source/Holumbus/Common/FileHandling.hs b/source/Holumbus/Common/FileHandling.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Common/FileHandling.hs
@@ -0,0 +1,213 @@
+-- ----------------------------------------------------------------------------
+{- |
+  Module     : Holumbus.Common.FileHandling
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+
+  Some nice helper functions for strict file writing, appending and
+  reading. All read-functions are strict, in the sense that
+  the whole file is read at once and the content is stored into memory.
+  So you won't have any semi-closed handles which might bring you in trouble
+  from time to time. The files are immedialty closed after the reading.
+  This Module can handle four filetypes: XML-Files, List-Files,
+  Binary-Files and Text-Files.
+  
+  XML-Files:
+  Normal textfiles, but the content is stored as a xml-representation. For
+  the pickling, we use the HXT-Library 
+  (see http:\/\/www.fh-wedel.de\/~si\/HXmlToolbox\/)
+  
+  List-Files:
+  Binary-Files, which store a list of data-objects. The main difference
+  between Binary-Files and List-Files is, that you can append data to a
+  List-File which will be automatically concatenated to the existing list.
+  If you try this with a normal Binary-File, you'll get only the original
+  list and the appended data will be lost.
+  
+  Binary-Files:
+  Normal binary files, for the encoding and decoding, we use the Haskell
+  binary-package.
+  
+  Text-Files:
+  Normal text files.
+
+-}
+-- ----------------------------------------------------------------------------
+
+module Holumbus.Common.FileHandling
+    (
+      -- * xml files
+      loadFromXmlFile
+    , saveToXmlFile
+
+      -- * lists in binary files
+    , writeToListFile
+    , appendToListFile
+    , readFromListFile
+    , parseByteStringToList
+
+      -- * bytestring file handling
+    , writeToBinFile
+    , appendToBinFile
+    , readFromBinFile
+
+      -- * string file handling
+    , writeToTextFile
+    , appendToTextFile
+    , readFromTextFile
+    )
+where
+
+
+import           Control.Exception
+import           Data.Binary
+import qualified Data.ByteString.Lazy as B
+import           Data.Char
+import           Foreign
+import           System.IO
+import           System.IO.Unsafe
+
+import           Text.XML.HXT.Arrow
+
+-- ----------------------------------------------------------------------------
+-- xml files
+-- ----------------------------------------------------------------------------
+
+
+-- | Loads an XML-File and parses the content to a specified datatype.
+loadFromXmlFile :: (XmlPickler a) => FilePath -> IO a
+loadFromXmlFile f
+  = do
+    r <- runX (xunpickleDocument xpickle options f)
+    return $! head r
+    where
+    options = [ (a_validate,v_0), (a_remove_whitespace, v_1), (a_encoding, utf8), (a_validate, v_0) ]
+
+
+-- | Converts a dataset to XML and saves the XML-string into a file.
+saveToXmlFile :: (XmlPickler a) => FilePath -> a -> IO ()
+saveToXmlFile f i 
+  = do
+    runX (constA i >>> xpickleDocument xpickle options f)
+    return ()
+    where
+    options = [ (a_indent, v_1), (a_output_encoding, utf8), (a_validate, v_0) ]
+
+-- ----------------------------------------------------------------------------
+-- generic lists
+-- ----------------------------------------------------------------------------
+
+
+-- | Writes data to a list file.
+writeToListFile :: (Binary a) => FilePath -> [a] -> IO ()
+writeToListFile fp bs = writeToBinFile fp $ B.concat $ map encode bs
+
+
+-- | Appends data to a list file.
+appendToListFile :: (Binary a) => FilePath -> [a] -> IO ()
+appendToListFile fp bs = appendToBinFile fp $ B.concat $ map encode bs
+
+-- | reads from a list file.
+readFromListFile :: (Binary a) => FilePath -> IO [a]
+readFromListFile f
+   = do
+     b <- readFromBinFile f 
+     return $ parseByteStringToList b
+
+
+-- | You'll need this function, if you read the files a a normal binary file,
+--   but the content itself is a list. This function encodes the bytestring
+--   into a list of the specified datatype.
+parseByteStringToList :: (Binary a) => B.ByteString -> [a]
+parseByteStringToList b = reverse $ parse b []
+  where
+  parse :: (Binary a) => B.ByteString -> [a] -> [a]
+  parse bs accu
+    | (B.null bs) = accu
+    | otherwise   = parse (B.drop count bs) ([nextElem] ++ accu) 
+    where
+    nextElem = decode bs
+    count    = B.length (encode nextElem)
+     
+
+
+-- ----------------------------------------------------------------------------     
+-- strict functions, bytestrings only     
+-- ----------------------------------------------------------------------------
+
+-- | Write data to a binary file.
+writeToBinFile :: FilePath -> B.ByteString -> IO ()
+writeToBinFile = B.writeFile
+
+
+-- | Append data to a binary file, this doesn't mean, that the contents
+--   are really concatenated when you read the file.    
+appendToBinFile :: FilePath -> B.ByteString -> IO ()
+appendToBinFile = B.appendFile
+
+
+-- | Reads the data from a binary file as a bytestring.
+readFromBinFile :: FilePath -> IO B.ByteString
+readFromBinFile f  
+   = bracket (openBinaryFile f ReadMode) hClose $ 
+       \h -> do
+       s <- hFileSize h
+       c <- B.hGetNonBlocking h (fromInteger s)
+       return $! c    
+
+
+-- ----------------------------------------------------------------------------     
+-- strict functions, strings only     
+-- ----------------------------------------------------------------------------
+
+     
+-- | Writes a sting to a text file.
+writeToTextFile :: FilePath -> String -> IO ()
+writeToTextFile = writeFile
+
+-- | Appends a string to a text file.
+appendToTextFile :: FilePath -> String -> IO ()
+appendToTextFile = appendFile
+
+
+-- | Strict file reading by Simon Marlow.
+-- found on
+-- http:\/\/users.aber.ac.uk\/afc\/stricthaskell.html
+readFromTextFile :: FilePath -> IO String
+readFromTextFile f
+  = do
+    bracket (openFile f ReadMode) hClose $ 
+      \h -> do
+      s <- hFileSize h
+      fp <- mallocForeignPtrBytes (fromIntegral s)
+      len <- withForeignPtr fp $ \buf -> hGetBuf h buf (fromIntegral s)
+      lazySlurp fp 0 len
+
+
+buf_size :: Int
+buf_size = 4096
+
+
+lazySlurp :: ForeignPtr Word8 -> Int -> Int -> IO String
+lazySlurp fp ix len
+  | fp `seq` False = undefined
+  | ix >= len = return []
+  | otherwise = do
+      cs <- unsafeInterleaveIO (lazySlurp fp (ix + buf_size) len)
+      ws <- withForeignPtr fp $ \p -> loop' (min (len-ix) buf_size - 1) 
+          ((p :: Ptr Word8) `plusPtr` ix) cs
+      return ws
+  where
+  loop' :: Int -> Ptr Word8 -> String -> IO String
+  loop' len' p acc
+    | len' `seq` p `seq` False = undefined
+    | len' < 0 = return acc
+    | otherwise = do
+       w <- peekElemOff p len'
+       loop' (len'-1) p (chr (fromIntegral w):acc)
diff --git a/source/Holumbus/Common/Logging.hs b/source/Holumbus/Common/Logging.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Common/Logging.hs
@@ -0,0 +1,66 @@
+-- ----------------------------------------------------------------------------
+{- |
+  Module     : Holumbus.Common.Logging
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+
+  In this part of the Holumbus-Framework, we use hslogging. With this, we are
+  able to activate and deactivate some nice debugging-Output.
+  This is the global configuration for the logging-output. Of cource, if you
+  want to use this output, you have to invoke initializeLogging.
+
+-}
+-- ----------------------------------------------------------------------------
+
+module Holumbus.Common.Logging
+(
+-- * Configuration
+initializeLogging
+)
+where
+
+import System.IO
+
+import System.Log.Logger
+import System.Log.Handler.Simple
+-- import System.Log.Handler.Syslog
+
+
+
+
+-- ----------------------------------------------------------------------------
+-- Configuration
+-- ----------------------------------------------------------------------------
+
+
+-- | configures the logging-parameters for the Holumbus-Framework
+initializeLogging :: [(String, Priority)] -> IO ()
+initializeLogging ls = do
+
+    -- log all verbose	
+    v <- verboseStreamHandler stderr DEBUG
+    updateGlobalLogger rootLoggerName (setLevel DEBUG . setHandlers [v])
+
+    -- set all logLevels for all loggers
+    mapM_ (\(s,p) -> updateGlobalLogger s (setLevel p)) ls
+
+    -- log all to syslog
+    -- s <- openlog "SyslogStuff" [PID] USER DEBUG
+    -- updateGlobalLogger rootLoggerName (addHandler s)
+    
+    -- this will be removed in next versions
+    -- updateGlobalLogger "Holumbus" (setLevel DEBUG)
+    -- updateGlobalLogger "Holumbus.Network" (setLevel WARNING)
+    -- updateGlobalLogger "Holumbus.MapReduce.TaskProcessor.task" (setLevel WARNING)
+    -- updateGlobalLogger "Holumbus.FileSystem.Storage.FileStorage" (setLevel WARNING)
+    -- updateGlobalLogger "Holumbus.FileSystem.Node.NodeData" (setLevel INFO)
+    -- updateGlobalLogger "Holumbus.MapReduce.Types" (setLevel INFO)
+    -- updateGlobalLogger "Holumbus.Network.Communication" (setLevel DEBUG)
+    -- updateGlobalLogger "Holumbus.MapReduce.JobController.cycle" (setLevel WARNING)
+    
diff --git a/source/Holumbus/Common/Threading.hs b/source/Holumbus/Common/Threading.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Common/Threading.hs
@@ -0,0 +1,206 @@
+-- ----------------------------------------------------------------------------
+
+{- |
+  Module     : Holumbus.Common.Threading
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+  Operations to start and stop threads which will not be killed when a regular
+  exception occurs. In this case, the thread will continue working. Such a 
+  thread can only be killed by the stop-method. This whole thing is a wrapper
+  around the normal lightweight thread functions.
+  
+  The created threads execute a function in an infinite loop. This is the
+  normal usecase for message dispatcher threads.
+  
+-}
+
+-- ----------------------------------------------------------------------------
+
+module Holumbus.Common.Threading
+(
+  Thread
+, newThread
+, setThreadDelay
+, setThreadAction
+, setThreadErrorHandler
+
+, startThread
+, stopThread
+)
+where
+
+{- 6.8
+import qualified Control.Exception      as E
+import           Data.Typeable
+-}
+import           Control.Exception      ( AsyncException(..)
+                                        , catchJust
+                                        )
+import           Control.Concurrent
+
+import           Data.Maybe
+
+import           System.Log.Logger
+
+import           Holumbus.Common.Utils  ( handleAll )
+
+localLogger :: String
+localLogger = "Holumbus.Common.Threading"
+
+
+-- ----------------------------------------------------------------------------
+-- Thread-Control
+-- ----------------------------------------------------------------------------
+
+-- | Exception to stop a thread, so we can distinguish this request from
+--   "real" exceptions.
+
+{- 6.8
+data KillThreadException = KillThreadException ThreadId
+  deriving (Typeable, Show)
+-}
+
+-- | The data needed to access and control the thread. 
+data ThreadData = ThreadData {
+    thd_Id      :: Maybe ThreadId
+  , thd_Running :: Bool
+  , thd_Delay   :: Maybe Int
+  , thd_Action  :: (IO ())
+  , thd_Error   :: (IO ())
+  }
+  
+  
+-- | The thread datatype
+type Thread = MVar ThreadData 
+
+
+-- | Creates a new thread object. The thread will not be running.
+newThread :: IO Thread
+newThread
+  = do 
+    newMVar $ ThreadData Nothing False defaultDelay noAction noAction
+    where
+    noAction     = return ()
+    defaultDelay = Nothing
+
+
+-- | Sets the delay between two loop cycles. Default value: no delay.
+setThreadDelay :: Int -> Thread -> IO ()
+setThreadDelay d thread
+  = do
+    modifyMVar thread $ \thd -> return (thd {thd_Delay = Just d},())
+    
+    
+-- | Sets the action function, which will be executed in each cycle
+setThreadAction :: (IO ()) -> Thread -> IO ()
+setThreadAction f thread
+  = do
+    modifyMVar thread $ \thd -> return (thd {thd_Action = f},())
+
+
+-- | Sets the error handler. It is activated, when the action function
+--   will raise an exception.
+setThreadErrorHandler :: (IO ()) -> Thread -> IO ()
+setThreadErrorHandler e thread
+  = do
+    modifyMVar thread $ \thd -> return (thd {thd_Error = e},())
+
+
+-- | Starts the thread.
+startThread :: Thread -> IO ()
+startThread th
+  = modifyMVar th $
+      \thd ->
+      do
+      -- check, if thread is running (it has a threadId)
+      servId' <- case (thd_Id thd) of
+        i@(Just _) -> return i
+        (Nothing) ->
+          do
+          -- if not running, start the loop
+          i <- forkIO $ doAction th
+          return (Just i)
+      return (thd {thd_Id = servId', thd_Running = True},())
+    where    
+    -- the action loop
+    doAction thread
+      = do
+        thd <- readMVar thread
+        if (thd_Running thd)
+          -- if thread is still running 
+          then do
+            {- 6.8 E.handle -}
+            handleAll
+             ( \ e -> do
+                      -- if a normal exception occurs, the error handler should be excuted
+                      warningM localLogger $ show e
+                      thd_Error thd
+                      doAction thread
+             ) $
+              do
+              -- catch the exception which tells us to kill the dispatcher and kill it
+              {- 6.8 E.catchDyn -}
+              catchJust isThreadKilledException
+               ( do
+                 -- wait for next watch-cycle
+                 if (isJust (thd_Delay thd)) 
+                    then do threadDelay $ fromJust (thd_Delay thd)
+                    else do return ()
+                 -- do the action
+                 thd_Action thd
+                 -- and again
+                 doAction thread
+               )
+               killHandler
+          else do
+            debugM localLogger $ "thread normally closed by himself"
+            deleteThreadId thread
+	where
+        isThreadKilledException      		:: AsyncException -> Maybe ()
+        isThreadKilledException ThreadKilled    = Just ()
+        isThreadKilledException _               = Nothing
+
+        killHandler :: () -> IO ()
+        killHandler _
+          = do
+            debugM localLogger $ "thread normally closed by other thread "
+            deleteThreadId thread
+{- 6.8
+        killHandler :: KillThreadException -> IO ()
+        killHandler (KillThreadException i)
+          = do
+            debugM localLogger $ "thread normally closed by other thread " ++ show i
+            deleteThreadId thread
+-}
+        deleteThreadId :: Thread -> IO ()
+        deleteThreadId t
+          = modifyMVar t $ \thd -> return (thd {thd_Id = Nothing, thd_Running = False},())
+
+
+-- | Stops the thread. If the thread itself wants to stop from within the action
+--   function, the current cycle will be executed till the end. So statements
+--   after this function will still be executed.
+stopThread :: Thread -> IO ()
+stopThread thread
+  = do
+    me <- myThreadId
+    him <- withMVar thread $ \thd -> return $ thd_Id thd
+    if (isJust him) 
+      then do
+        let he = fromJust him
+        if (me == he) 
+          -- if stop is called from the thread, we want to finish our work
+          then do 
+            modifyMVar thread $ \thd -> return (thd {thd_Running = False},())
+            -- else we kill it the unfriendly way...
+          else do
+            {- 6.8: E.throwDynTo he (KillThreadException me) -}
+            killThread he
+      else do
+        return ()
diff --git a/source/Holumbus/Common/Utils.hs b/source/Holumbus/Common/Utils.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Common/Utils.hs
@@ -0,0 +1,134 @@
+-- ----------------------------------------------------------------------------
+
+{- |
+  Module     : Holumbus.Common.Utils
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+  Some nice functions, needed everywhere.
+
+-}
+
+-- ----------------------------------------------------------------------------
+
+module Holumbus.Common.Utils
+    ( 
+      decodeMaybe
+
+      -- , lookupList
+      -- , lookupMaybe
+
+      -- , cutMaybePair
+    , filterEmptyList
+    , setEmptyList
+      -- , filterBlanks
+
+    , prettyRecordLine
+      -- , prettyResultLine
+      -- , handleExitError
+
+    , handleAll		-- exception handling for all exceptions
+    )
+where
+
+import           Control.Exception	( SomeException
+					, handle
+					)
+import           Data.Binary
+import qualified Data.ByteString.Lazy as B
+
+-- import qualified Data.Map as Map
+
+import           Data.Maybe
+import           Data.Char
+
+-- import           System.Exit
+
+-- ------------------------------------------------------------
+--
+-- handle with type sinature
+
+{- 6.8
+handleAll	:: (Exception -> IO a) -> IO a -> IO a
+-}
+
+-- ghc 6.10 requires a type signature for handle
+
+handleAll	:: (SomeException -> IO a) -> IO a -> IO a
+handleAll	= handle
+
+-- ------------------------------------------------------------
+
+-- | parses something from a maybe bytestring, if Nothing, then Nothing
+decodeMaybe :: (Binary a) => Maybe B.ByteString -> Maybe a
+decodeMaybe Nothing = Nothing
+decodeMaybe (Just b) = (Just $ decode b)
+
+{-
+lookupMaybe :: (Ord k) => Map.Map k v -> Maybe k -> Maybe v
+lookupMaybe _ Nothing = Nothing
+lookupMaybe m (Just k) = Map.lookup k m
+-}
+{-
+lookupList :: (Ord k) => Map.Map k v -> [k] -> [v]
+lookupList m ks = mapMaybe (\k' -> lookupMaybe m $ Just k') ks
+-}    
+{-
+cutMaybePair :: Maybe (Maybe a, Maybe b) -> (Maybe a, Maybe b)
+cutMaybePair (Nothing) = (Nothing, Nothing)
+cutMaybePair (Just p)  = p
+-}
+
+filterEmptyList :: Maybe [k] -> [k]
+filterEmptyList (Nothing) = []
+filterEmptyList (Just ls) = ls
+
+
+setEmptyList :: [k] -> Maybe [k]
+setEmptyList [] = Nothing
+setEmptyList ls = Just ls 
+
+{-
+filterBlanks :: Maybe String -> Maybe String
+filterBlanks (Nothing) = Nothing
+filterBlanks (Just "") = Nothing
+filterBlanks (Just s)  = if s' == "" then Nothing else (Just s)
+  where
+  s' = filter isPrint s 
+-}
+
+
+-- | For the nice output of key-value-pairs 
+prettyRecordLine :: (Show b, Show a) => Int -> a -> b -> String
+prettyRecordLine n a b = stra ++ (replicate diff ' ') ++ show strb
+  where
+   stra = show a
+   strb = show b
+   diff = n - length stra
+  
+   
+{-
+prettyResultLine :: (Show e, Show a, Show d) => Int -> Either e d -> a -> String
+prettyResultLine n (Left e) _ = prettyRecordLine n "Error:" e
+prettyResultLine n (Right r) a = prettyRecordLine n a r
+-}
+
+{-
+handleExitError :: (Show e) => IO (Either e a) -> IO a
+handleExitError res
+  = do
+    res' <- res
+    case res' of
+      (Left e) ->
+        do
+        putStrLn $ "ERROR: " ++ show e
+        exitFailure
+      (Right a) -> return a
+-}   
+
+-- ----------------------------------------------------------------------------
diff --git a/source/Holumbus/Console/Console.hs b/source/Holumbus/Console/Console.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Console/Console.hs
@@ -0,0 +1,242 @@
+-- ----------------------------------------------------------------------------
+
+{- |
+  Module     : Holumbus.Console.Console
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+  This module provides a tiny and nice implementation of a little command 
+  shell. It can be feed with individual commands and provides a simple but
+  powerful way to interact with your program. The following functions are
+  implemented by default:
+    exit - exit the console loop
+    help - print a nice help
+
+  There was a little "bug" with the System.Console.Readline package. When
+  we use this option, we make a foreign call... and the Haskell library
+  documentation say this about concurrency and GHC:
+  
+  "If you don't use the -threaded option, then the runtime does not make 
+  use of multiple OS threads. Foreign calls will block all other running 
+  Haskell threads until the call returns.
+  The System.IO library still does multiplexing, so there can be multiple
+  threads doing IO, and this is handled internally by the runtime using 
+  select."
+   
+  We make a foreign call, which is not in the System.IO library, so we
+  have to work with -threaded when we want a fancy command history.
+
+-}
+
+-- ----------------------------------------------------------------------------
+
+
+module Holumbus.Console.Console
+    (
+     -- * Console datatype
+     ConsoleData
+    
+     -- * Operations
+    , nextOption
+    , parseOption
+    , initializeConsole
+    , addConsoleCommand
+    , handleUserInput
+    )
+where
+
+import           Control.Concurrent
+import           Control.Monad
+
+import           Data.Char
+import qualified Data.Map as Map
+
+import           System.IO
+import           System.Console.Editline.Readline
+
+import           Holumbus.Common.Utils	( handleAll )
+
+-- ----------------------------------------------------------------------------
+-- datatypes
+-- ----------------------------------------------------------------------------
+
+
+-- | Map which contains all commands that the user can execute
+type ConsoleData a = Map.Map String (ConsoleCommand a)
+
+
+-- | Console command, only a pair of a function which will be executed 
+--   and a description 
+type ConsoleCommand a = ( Maybe (ConsoleFunction a), String )
+
+
+-- | A console function. The string list represents the arguments
+type ConsoleFunction a = (a -> [String] -> IO())
+
+-- ----------------------------------------------------------------------------
+-- operations 
+-- ----------------------------------------------------------------------------
+
+
+-- | Creates a new console datatype
+initializeConsole :: ConsoleData a
+initializeConsole = Map.fromList [(exitString, exitCommand), (helpString, helpCommand)]
+
+
+-- | Adds a new console command to the function, an existing command with the
+--   same name will be overwritten
+addConsoleCommand 
+  :: String             -- ^ command string (the word the user has to enter when he wants to execute the command)
+  -> ConsoleFunction a  -- ^ the function which should be executed
+  -> String             -- ^ the function description
+  -> ConsoleData a      -- ^ the old console data
+  -> ConsoleData a
+addConsoleCommand c f d m = Map.insert c (Just f, d) m
+
+
+-- | The exit function string.
+exitString  :: String
+exitString = "exit"
+
+
+-- | A dummy exit function (Just to print the help description, the command 
+--   is handled in the main loop.
+exitCommand :: ConsoleCommand a
+exitCommand = ( Nothing, "exit the console")
+
+
+-- | The help function string.
+helpString :: String
+helpString = "help"
+
+
+-- | A dummy help function (Just to print the help description, the command 
+--   is handled in the main loop.
+helpCommand :: ConsoleCommand a
+helpCommand = (Nothing, "print this help")
+
+
+-- | The command-line prompt string.
+shellString :: String
+shellString = "command> "
+
+-- | gets the next option from the command line as string
+nextOption :: [String] -> IO (Maybe String, [String])
+nextOption o
+  = handleAll (\_ -> return (Nothing, o)) $
+      do
+      if ( null o ) then
+          return (Nothing, o)
+        else 
+          return (Just $ head o, tail o) 
+
+-- | Simple "parser" for the commandline...
+parseOption :: Read a => [String] -> IO (Maybe a, [String])
+parseOption o
+  = handleAll (\_ -> return (Nothing, o)) $
+      do
+      if ( null o ) then
+          return (Nothing, o)
+        else 
+          return (Just $ read $ head o, tail o) 
+
+
+-- | Reads the input from the stdin.
+getCommandLine :: IO (String)
+getCommandLine 
+-- no commandline history
+{-  = do
+    putStr shellString
+    hFlush stdout
+    maybeLine <- getLine --readline shellString
+    return maybeLine
+-}
+-- with commandline history, please use -threaded option
+  = do
+    maybeLine <- readline shellString
+    yield
+    case maybeLine of
+      Nothing   -> return exitString -- EOF / control-d
+      Just line -> 
+        do 
+          if (not $ null line) then do addHistory line else return ()
+          return line
+          
+
+-- | The main loop. You know... read stdin, parse the input, execute command.
+--   You can quit it by the exit-command.
+handleUserInput :: ConsoleData a -> a -> IO ()
+handleUserInput cdata conf
+  = do
+    line  <- getCommandLine
+    input <- return (words line)
+    cmd   <- return (command input)
+    args  <- return (arguments input)
+    if (cmd == exitString) 
+      then do
+        return ()
+      else do
+        if (not $ null cmd) then do handleCommand cdata conf cmd args else return ()
+        handleUserInput cdata conf
+    where
+      command s = if (not $ null s) then head s else ""
+      arguments s = tail s
+
+
+-- | Picks the command an execute the command function.
+handleCommand :: ConsoleData a -> a -> String -> [String] -> IO ()
+handleCommand cdata conf cmd args
+  = do
+    if (cmd == helpString)
+      then do
+        printHelp cdata
+      else do
+        handleCommand' (Map.lookup cmd cdata)
+    where
+        handleCommand' Nothing              = do printError
+        handleCommand' (Just (Nothing, _ )) = do printNoHandler
+        handleCommand' (Just (Just f, _ ))  = do f conf args
+
+
+-- | Is executed when the function has no handler
+printNoHandler :: IO ()
+printNoHandler 
+  = do
+    putStrLn "no function handler found"
+
+
+-- | Prints the "command-not-found" message.
+printError :: IO ()
+printError
+  = do
+    putStrLn "unknown command, try help for a list of available commands"
+
+
+-- | Prints the help text.
+printHelp :: ConsoleData a -> IO ()
+printHelp cdata
+  = do
+    putStrLn "available Commands:"
+    printCommands (Map.toAscList cdata)
+    where
+      printCommands [] = do return ()
+      printCommands (x:xs) = do
+                             printCommand x
+                             printCommands xs
+      printCommand (c, (_, t)) = do
+                                 putStrLn ((prettyCommandName 15 c) ++ " -  " ++ t) 
+
+
+-- | Does some pretty printing for the function descriptions
+prettyCommandName :: Int -> String -> String 
+prettyCommandName n s
+  | n <= 0 = s
+  | (n > 0) && (null s) = ' ' : prettyCommandName (n-1) s
+  | otherwise           = x : prettyCommandName (n-1) xs
+    where
+      (x:xs) = s
diff --git a/source/Holumbus/Data/AccuMap.hs b/source/Holumbus/Data/AccuMap.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Data/AccuMap.hs
@@ -0,0 +1,122 @@
+-- ----------------------------------------------------------------------------
+{- |
+  Module     : Holumbus.Data.AccuMap
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+  A map of key-value-pairs. The values are hold in a list, so adding the same
+  key-value-pair twice to the map, will result in storing the value twice.
+  Even the sequence of adding the values will be saved.
+  
+  The name AccuMap is from accumulation map. You can use this map to easily
+  storing all you key-value-pairs. After that you can all values-lists by
+  key. Unlike the MultiMap, you don't lose the information of identical values
+  and their order of adding.
+  
+  Most functions are inspired by the Data.Map type. 
+-}
+-- ----------------------------------------------------------------------------
+
+module Holumbus.Data.AccuMap
+(
+  AccuMap
+, empty
+, null
+, insert
+, insertList
+, lookup
+, member
+, deleteKey
+, union
+, fromList
+, fromTupleList
+, toList
+)
+where
+
+import           Prelude hiding (null, lookup)
+
+import qualified Data.Map as Map
+
+
+-- | the AccuMap datatype
+data AccuMap k a = AM (Map.Map k [a])
+  deriving (Eq, Ord)
+
+
+instance (Show k, Show a) => Show (AccuMap k a) where
+  show (AM m) = msShow
+    where
+    ms = Map.toList m
+    msShow = concat $ map (\(k,s) -> (show k) ++ "\n" ++ (showL s)) ms
+    showL ls = concat $ map (\s -> show s ++ "\n") ls 
+
+
+-- | Creates an empty AccuMap.
+empty :: (Ord k) => AccuMap k a
+empty = AM Map.empty
+
+
+-- | Test, if AccuMap is empty.
+null :: (Ord k) => AccuMap k a -> Bool
+null (AM m) = Map.null m
+
+
+-- | Insert a key-value-pair to the AccuMap.
+insert :: (Ord k) => k -> a -> AccuMap k a -> AccuMap k a
+insert k a (AM m) = AM $ Map.alter altering k m
+  where
+    altering Nothing = Just $ [a]
+    altering (Just s) = Just $ a:s
+
+
+-- | Insert a key and a list of values to the AccuMap.
+--   Faster than adding all pair one by one.
+insertList :: (Ord k) => k -> [a] -> AccuMap k a -> AccuMap k a
+insertList _ [] m      = m
+insertList k as (AM m) = AM $ Map.alter altering k m
+  where
+    altering Nothing = Just $ as
+    altering (Just s) = Just $ as ++ s
+
+
+-- | Get the list of values for one key. If the key doesn't exists,
+--   an empty list is returned.
+lookup :: (Ord k) => k -> AccuMap k a -> [a]
+lookup k (AM m) = maybe [] (id) (Map.lookup k m)
+
+
+-- | Test, if the key is in the AccuMap.
+member :: (Ord k, Eq a) => k -> AccuMap k a -> Bool
+member k m = [] /= lookup k m
+
+
+-- | Deletes a key and all its values from the AccuMap.
+deleteKey :: (Ord k) => k -> AccuMap k a -> AccuMap k a
+deleteKey k (AM m) = AM $ Map.delete k m
+
+
+-- | Combines two AccuMaps, the ordering of the two maps is
+--   significant for the order of the values-elements.
+union :: (Ord k) => AccuMap k a -> AccuMap k a -> AccuMap k a
+union (AM m1) (AM m2) = AM $ Map.unionWith (\l1 l2 -> l1 ++ l2) m1 m2 
+
+
+-- | Creates an AccuMap from a list.
+fromList :: (Ord k) => [(k,[a])] -> AccuMap k a
+fromList ks = foldl (\m (k,as) -> insertList k as m) empty ks
+
+
+-- | Creates an AccuMap from a tuple list.
+fromTupleList :: (Ord k) => [(k,a)] -> AccuMap k a
+fromTupleList ts = fromList $ map (\(k,a) -> (k,[a])) ts
+
+
+-- | Transforms an AccuMap to a list.
+toList :: (Ord k) => AccuMap k a -> [(k,[a])]
+toList (AM m) = Map.toList m
diff --git a/source/Holumbus/Data/KeyMap.hs b/source/Holumbus/Data/KeyMap.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Data/KeyMap.hs
@@ -0,0 +1,127 @@
+-- ----------------------------------------------------------------------------
+{- |
+  Module     : Holumbus.Data.KeyMap
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+  The KeyMap is derived from the Data.Map type. The keys of the Map are
+  strings and the values can be arbitrary data objects. But you don't have to
+  specify the keys because every value-object is able to create it's own
+  key via the "Key" typeclass.
+  
+  From the functionality, the KeyMap stands between a set and a Map. If you
+  want to insert an element to the map, it behaves like a set. You don't need 
+  an additionnal key and it makes no different if you insert an object multiple
+  times. If you want to access the objects in the KeyMap, you can lookup them
+  via the key, so in this case this container behaves like an ordinary map.
+
+  The functions for this container are named after the standard Map and Set
+  functions.
+-}
+-- ----------------------------------------------------------------------------
+
+module Holumbus.Data.KeyMap
+    (
+      KeyMap
+    , Key(..)
+    , empty
+    , null
+    , insert
+    , lookup
+    , keys
+    , elems
+    , memberKey
+    , memberElem
+    , deleteKey
+    , deleteElem
+    , fromList
+    , toList
+    , toAscList
+    )
+where
+
+import           Prelude hiding (null, lookup)
+import           Data.Maybe
+import qualified Data.Map as Map
+
+-- | Every element of this map has to implement a key-function. which
+--   gives us the key of the element
+class Key n where
+  getKey :: n -> String
+
+
+-- | The KeyMap datatype.
+data KeyMap a = NM (Map.Map String a)
+  deriving (Show, Eq, Ord)
+
+
+-- | The empty KeyMap.
+empty :: KeyMap a
+empty = NM Map.empty
+
+
+-- | Test, if the MultiMap is empty.
+null :: (Key a) => KeyMap a -> Bool
+null (NM m) = Map.null m
+
+
+-- | Inserts an element in the KeyMap.
+insert :: (Key a) => a -> KeyMap a -> KeyMap a
+insert a (NM m) = NM $ Map.insert (getKey a) a m
+  
+
+-- | Gets all different elements for one key or an empty set.
+lookup :: (Key a, Monad m) => String -> KeyMap a -> m a
+lookup k (NM mm)
+    = do
+      let Just r = Map.lookup k mm
+      return r
+
+-- | Get all different keys from the map.
+keys :: (Key a) => KeyMap a -> [String]
+keys (NM m) = Map.keys m
+
+
+-- | Get all different values in the map without regarding their keys.
+elems :: (Key a) => KeyMap a -> [a]
+elems (NM m) = Map.elems m
+
+
+-- | Test, if a key is in the KeyMap.
+memberKey :: (Key a) => String -> KeyMap a -> Bool
+memberKey k (NM m) = Map.member k m
+
+
+-- | Test, if a data object is in the KeyMap.
+memberElem :: (Key a) => a -> KeyMap a -> Bool
+memberElem a (NM m) = Map.member (getKey a) m
+
+
+-- | Deletes a whole key from the KeyMap.
+deleteKey :: (Key a) => String -> KeyMap a -> KeyMap a
+deleteKey k (NM m) = NM $ Map.delete k m
+
+
+-- | Deletes a single elemet from the KeyMap.
+deleteElem :: (Key a) => a -> KeyMap a -> KeyMap a
+deleteElem a (NM m) = NM $ Map.delete (getKey a) m
+
+
+-- | Creates a KeyMap from a list of keys.
+fromList :: (Key a) => [a] -> KeyMap a
+fromList as = foldl (\m a -> insert a m) empty as
+
+
+-- | Transforms a KeyMap to a list of keys.
+toList :: (Key a) => KeyMap a -> [a]
+toList (NM m) = map (snd) $ Map.toList m
+
+
+-- | The same as toList, but the keys are in ascending order.
+toAscList :: (Key a) => KeyMap a -> [a]
+toAscList (NM m) = map (snd) $ Map.toAscList m
diff --git a/source/Holumbus/Data/MultiMap.hs b/source/Holumbus/Data/MultiMap.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Data/MultiMap.hs
@@ -0,0 +1,178 @@
+-- ----------------------------------------------------------------------------
+{- |
+  Module     : Holumbus.Data.MultiMap
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+  This module provides a MultiMap, that means a Map, which can hold
+  multiple values for one key, but every distinct value is only stores once.
+  So adding the same key-value-pair twice will only create one new entry in
+  the map.
+  
+  This Map is helpfull to examine how many different key-values-pairs you
+  have in your application.
+  
+  Most of the functions are borrowed from Data.Map 
+-}
+-- ----------------------------------------------------------------------------
+
+module Holumbus.Data.MultiMap
+(
+  MultiMap
+, empty
+, null
+, insert
+, insertSet
+, insertKeys
+, lookup
+, keys
+, elems
+, filterElements
+, member
+, delete
+, deleteKey
+, deleteElem
+, deleteAllElems
+, fromList
+, fromTupleList
+, toList
+, toAscList
+)
+where
+
+import           Prelude hiding (null, lookup)
+
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+
+
+-- | A MultiMap, it can hold more (different!!!) Elements for one key.
+data MultiMap k a = MM (Map.Map k (Set.Set a))
+  deriving (Show, Eq, Ord)
+
+{-
+instance (Show k, Show a) => Show (MultiMap k a) where
+  show (MM m) = msShow
+    where
+    ms = map (\(k,s) -> (k, Set.toList s)) (Map.toList m)
+    msShow = concat $ map (\(k,s) -> (show k) ++ "\n" ++ (showL s)) ms
+    showL ls = concat $ map (\s -> show s ++ "\n") ls 
+-}
+
+-- | The empty MultiMap.
+empty :: (Ord k, Ord a) => MultiMap k a
+empty = MM Map.empty
+
+
+-- | Test, if the MultiMap is empty.
+null :: (Ord k, Ord a) => MultiMap k a -> Bool
+null (MM m) = Map.null m
+
+
+-- | Inserts an element in the MultiMap.
+insert :: (Ord k, Ord a) => k -> a -> MultiMap k a -> MultiMap k a
+insert k a (MM m) = MM $ Map.alter altering k m
+  where
+  altering Nothing = Just $ Set.singleton a
+  altering (Just s) = Just $ Set.insert a s
+  
+
+-- | Inserts multiple elements in a set to the MultiMap.
+insertSet :: (Ord k, Ord a) => k -> Set.Set a -> MultiMap k a -> MultiMap k a
+insertSet k newSet mm@(MM m) = 
+  if (Set.null newSet) then mm else MM $ Map.alter altering k m
+  where
+  altering Nothing = Just newSet
+  altering (Just s) = Just $ Set.union newSet s
+
+
+-- | Inserts multiple keys with the same values.
+insertKeys :: (Ord k, Ord a) => [k] -> Set.Set a -> MultiMap k a -> MultiMap k a
+insertKeys ks a m = foldl (\m' k -> insertSet k a m') m ks 
+
+
+-- | Gets all different elements for one key or an empty set.
+lookup :: (Ord k, Ord a) => k -> MultiMap k a -> Set.Set a
+lookup k (MM m) = maybe (Set.empty) (id) (Map.lookup k m)
+
+
+-- | Get all different elements from a list of keys.
+lookupKeys :: (Ord k, Ord a) => [k] -> MultiMap k a -> Set.Set a
+lookupKeys ks m = Set.unions $ map (\k -> lookup k m) ks
+
+
+-- | Get all different keys from the map.
+keys :: (Ord k, Ord a) => MultiMap k a -> Set.Set k
+keys (MM m) = Set.fromList $ Map.keys m
+
+
+-- | Get all different values in the map without regarding their keys.
+elems :: (Ord k, Ord a) => MultiMap k a -> Set.Set a
+elems (MM m) = Set.unions $ Map.elems m
+
+
+-- | Like lookup keys, but an empty input list will give all elements back,
+--   not the empty set.
+filterElements :: (Ord k, Ord a) => [k] -> MultiMap k a -> Set.Set a
+filterElements [] m = elems m  -- get all
+filterElements ks m = lookupKeys ks m
+
+
+-- | Test, if a key is in the Map.
+member :: (Ord k, Ord a) => k -> MultiMap k a -> Bool
+member k m = Set.empty /= lookup k m
+
+
+-- | Deletes an Element from the Map, if the data in Nothing, the whole key is
+--   deleted.
+delete :: (Ord k, Ord a) => k -> Maybe a -> MultiMap k a -> MultiMap k a
+delete k Nothing m = deleteKey k m
+delete k (Just a) m = deleteElem k a m
+
+
+-- | Deletes a whole key from the map.
+deleteKey :: (Ord k, Ord a) => k -> MultiMap k a -> MultiMap k a
+deleteKey k (MM m) = MM $ Map.delete k m
+
+
+-- | Deletes a single Element from the map.
+deleteElem :: (Ord k, Ord a) => k -> a -> MultiMap k a -> MultiMap k a
+deleteElem k a (MM m) = MM $ Map.alter delSet k m
+  where
+  delSet Nothing = Nothing
+  delSet (Just set) = filterEmpty $ Set.delete a set
+  filterEmpty set
+    | set == Set.empty = Nothing
+    | otherwise = Just set
+
+
+-- | Deletes all Elements (*,a) (slow!!!).
+deleteAllElems :: (Ord k, Ord a) => a -> MultiMap k a -> MultiMap k a
+deleteAllElems a m = foldl (\m'' k -> deleteElem k a m'') m ks
+  where
+  ks = Set.toList $ keys m
+
+
+-- | Creates a MultiMap from a list of pairs (key,set value).
+fromList :: (Ord k, Ord a) => [(k,Set.Set a)] -> MultiMap k a
+fromList ks = foldl (\m (k,as) -> insertSet k as m) empty ks
+
+
+-- | Creates a MultiMap from a list of tuples.
+fromTupleList :: (Ord k, Ord a) => [(k,a)] -> MultiMap k a
+fromTupleList ks = foldl (\m (k,a) -> insert k a m) empty ks
+
+
+-- | Transforms a MultiMap to a list of pairs (key,set value).
+toList :: (Ord k, Ord a) => MultiMap k a -> [(k,Set.Set a)]
+toList (MM m) = Map.toList m
+
+
+-- | The same as toList, but the keys are in ascending order.
+toAscList :: (Ord k, Ord a) => MultiMap k a -> [(k,Set.Set a)]
+toAscList (MM m) = Map.toAscList m
diff --git a/source/Holumbus/Network/Communication.hs b/source/Holumbus/Network/Communication.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Network/Communication.hs
@@ -0,0 +1,959 @@
+-- ----------------------------------------------------------------------------
+
+{- |
+  Module     : Holumbus.Network.Communication
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+
+  This module implements an abstract client server model. The clients register
+  at the server and check from time to time if the server still exists. If not,
+  the client searches for a new server.
+  The server on the other hand, keeps a list with all clients and checks, if
+  each client is reachable. If not, the client is deleted from the list.
+  
+  This abstract network model helps us to implement a basic distrubuted system
+  with a central server and many attached clients which get little tasks from
+  the server. Because this model alone would be very unfunctional, the user is
+  able to define his own functions which will be handled by the server or the
+  client. 
+-}
+
+-- ----------------------------------------------------------------------------
+
+{-# OPTIONS -fglasgow-exts #-}
+module Holumbus.Network.Communication
+(
+  StreamName       -- (reexport)
+, SocketId         -- (reexport)
+, PortNumber       -- (reexport)
+
+-- time constants
+, time30           -- (reexport)
+, timeIndefinitely -- (reexport)
+
+, IdType
+
+, ClientInfo(..)
+
+-- * server operations
+, Server
+, newServer
+, closeServer
+, ServerPort
+, newServerPort
+, sendRequestToServer
+
+, getClientInfo
+, getAllClientInfos
+
+-- * client operations
+, ClientClass(..)
+, Client
+, newClient
+, closeClient
+, ClientPort
+, sendRequestToClient 
+)
+where
+
+import           Control.Concurrent
+import           Data.Binary
+import qualified Data.ByteString.Lazy as B
+import qualified Data.Map as Map
+import           Data.Maybe
+import           Network
+import           System.Log.Logger
+
+import           Holumbus.Common.Debug
+import           Holumbus.Common.Threading
+import qualified Holumbus.Data.MultiMap as MMap
+import           Holumbus.Network.Messages
+import           Holumbus.Network.Port
+import           Holumbus.Network.Site
+
+
+
+localLogger :: String
+localLogger = "Holumbus.Network.Communication"
+
+
+-- ----------------------------------------------------------------------------
+-- General Datatypes
+-- ----------------------------------------------------------------------------
+
+-- | The type of the client id.
+type IdType = Int
+
+
+
+-- ----------------------------------------------------------------------------
+-- Server-Messages
+-- ----------------------------------------------------------------------------
+
+-- | The requests, the server can handle.
+data ServerRequestMessage
+  = SReqRegisterClient SiteId (Port ClientRequestMessage)
+  | SReqUnregisterClient IdType
+  | SReqPing IdType
+  | SReqServerAction B.ByteString
+  | SReqUnknown
+  deriving (Show)
+
+instance Binary (ServerRequestMessage) where
+  put (SReqRegisterClient sid po) = putWord8 1 >> put sid >> put po
+  put (SReqUnregisterClient i)    = putWord8 2 >> put i
+  put (SReqPing i)                = putWord8 3 >> put i
+  put (SReqServerAction b)        = putWord8 4 >> put b
+  put (SReqUnknown)               = putWord8 0
+  get
+    = do
+      t <- getWord8
+      case t of
+        1 -> get >>= \sid -> get >>= \po -> return (SReqRegisterClient sid po)
+        2 -> get >>= \i -> return (SReqUnregisterClient i)
+        3 -> get >>= \i -> return (SReqPing i)
+        4 -> get >>= \b -> return (SReqServerAction b)
+        _ -> return (SReqUnknown)
+
+
+-- | The responses the server gives.
+data ServerResponseMessage
+  = SRspSuccess
+  | SRspRegisterClient IdType
+  | SRspUnregisterClient
+  | SRspPing Bool
+  | SRspServerAction B.ByteString
+  | SRspError String
+  | SRspUnknown
+  deriving (Show)
+
+instance Binary (ServerResponseMessage) where
+  put (SRspSuccess)          = putWord8 1
+  put (SRspRegisterClient i) = putWord8 2 >> put i
+  put (SRspUnregisterClient) = putWord8 3
+  put (SRspPing b)           = putWord8 4 >> put b
+  put (SRspServerAction b)   = putWord8 5 >> put b
+  put (SRspError e)          = putWord8 6 >> put e
+  put (SRspUnknown)          = putWord8 0
+  get
+    = do
+      t <- getWord8
+      case t of
+        1 -> return (SRspSuccess)
+        2 -> get >>= \i -> return (SRspRegisterClient i)
+        3 -> return (SRspUnregisterClient)
+        4 -> get >>= \b -> return (SRspPing b)
+        5 -> get >>= \b -> return (SRspServerAction b)
+        6 -> get >>= \e -> return (SRspError e)
+        _ -> return (SRspUnknown)
+  
+instance RspMsg (ServerResponseMessage) where
+  isError (SRspError _) = True
+  isError _ = False
+  
+  getErrorMsg (SRspError e) = e
+  getErrorMsg _ = ""
+  
+  isUnknown (SRspUnknown) = True
+  isUnknown _ = False
+  
+  mkErrorMsg e = SRspError e
+  
+
+
+
+-- ----------------------------------------------------------------------------
+-- Server-TypeClass
+-- ----------------------------------------------------------------------------
+
+-- | The request-functions a server has to implement.
+class ServerClass s where
+
+  -- | Register a new client in the server database.
+  registerClient :: SiteId -> Port ClientRequestMessage -> s -> IO IdType
+  
+  -- | Delete a client from the server database.
+  unregisterClient :: IdType -> s -> IO ()
+  
+  -- | Check, if server is responding.
+  pingServer :: IdType-> s -> IO Bool
+
+
+
+-- ----------------------------------------------------------------------------
+-- Server-Data
+-- ----------------------------------------------------------------------------
+  
+-- | The type of the functions which will be executed by registration and
+--   unregistration.
+type RegistrationAction = (IdType -> ClientPort -> IO ())
+  
+  
+-- The information of the client known by the server.
+data ClientInfo = ClientInfo {
+    ci_Id           :: Int
+  , ci_Site         :: SiteId                -- ^ SiteId (Hostname,PID) of the client process
+  , ci_Port         :: ClientPort            -- ^ the port of the client
+  , ci_PingThreadId :: Thread                -- ^ the threadId of the ping-Process (needed to stop it)
+  , ci_LifeValue    :: Int
+  }
+  
+instance Show ClientInfo where
+  show (ClientInfo n s p _ i) = "{Id: " ++ show n ++ 
+                                 " - Site: " ++ show s ++ 
+                                 " - Port: " ++ show p ++ 
+                                 " - LifeValue: " ++ show i ++ "}"
+
+
+-- | The data of the server needed to organise the clients.
+data ServerData = ServerData {
+    sd_ServerThreadId  :: Thread                        -- ^ threadId of the streamDispatcher
+  , sd_OwnStream       :: Stream (ServerRequestMessage) -- ^ the stream the requestDispatcher reads from
+  , sd_OwnPort         :: Port (ServerRequestMessage)   -- ^ the port the clients send messages to
+  , sd_ClientMap       :: Map.Map IdType ClientInfo     -- ^ infomation of the the clients
+  , sd_SiteToClientMap :: MMap.MultiMap SiteId IdType   -- ^ needed to get the closest client
+  , sd_SiteMap         :: SiteMap                       -- ^ needed to get the closest site
+  , sd_Register        :: RegistrationAction
+  , sd_Unregister      :: RegistrationAction
+  , sd_NextId          :: IdType
+  }
+  
+  
+-- | The server.
+data Server = Server (MVar ServerData)
+  
+  
+maxLifeValue :: Int
+maxLifeValue = 3
+
+
+-- | Creates a new server.
+newServer
+  :: (Binary a, Binary b)
+  => StreamName -> Maybe PortNumber
+  -> (a -> IO (Maybe b))             -- ^ handling own request
+  -> Maybe RegistrationAction        -- ^ for registration
+  -> Maybe RegistrationAction        -- ^ for unregistration 
+  -> IO Server
+newServer sn pn dispatch register unregister
+  = do
+    -- create a new server
+    st    <- (newStream STGlobal (Just sn) pn::IO (Stream ServerRequestMessage))
+    po    <- newPortFromStream st
+    tid   <- newThread
+    let reg   = maybe (\_ _ -> return ()) id register
+    let unreg = maybe (\_ _ -> return ()) id unregister
+    let sd = ServerData tid st po Map.empty MMap.empty Map.empty reg unreg 1
+    s <- newMVar sd
+    let server =  Server s
+    -- start the requestDispatcher to handle requests
+    startRequestDispatcher tid st (dispatchServerRequest server dispatch)
+    return server
+
+
+-- | Closes the server.
+closeServer :: Server -> IO ()
+closeServer s@(Server server)
+  = do
+    debugM localLogger "closeServer: start"
+    (allIds,thread,stream) <- withMVar server $
+      \sd ->
+      do
+      -- getAll ClientIds
+      let allIds = Map.keys (sd_ClientMap sd)
+      return (allIds, sd_ServerThreadId sd, sd_OwnStream sd)          
+    debugM localLogger "closeServer: stopRequestDispatcher"
+    -- shutdown the server thread
+    stopRequestDispatcher thread
+    -- close the stream
+    debugM localLogger "closeServer: closeStream"
+    closeStream stream
+    debugM localLogger "closeServer: unregister clients"
+    mapM (\i -> do unregisterClient i s) allIds
+    debugM localLogger "closeServer: end"
+    return ()
+
+
+-- | Handles the requests from the client.
+dispatchServerRequest
+  :: (Binary a, Binary b)
+  => Server
+  -> (a -> IO (Maybe b))
+  -> ServerRequestMessage
+  -> Port (ServerResponseMessage)
+  -> IO ()
+dispatchServerRequest server action msg replyPort
+  = do
+    debugM localLogger $ "dispatchServerRequest: " ++ show msg
+    case msg of
+      (SReqRegisterClient s po) ->
+        do
+        handleRequest replyPort (registerClient s po server) (\i -> SRspRegisterClient i)
+        return ()
+      (SReqUnregisterClient n) ->
+        do
+        handleRequest replyPort (unregisterClient n server) (\_ -> SRspUnregisterClient)
+        return ()
+      (SReqPing i) ->
+        do
+        handleRequest replyPort (pingServer i server) (\b -> SRspPing b)
+        return ()
+      (SReqServerAction b) ->
+        do
+        handleRequest replyPort
+          (action $ decode b) 
+          (\res -> maybe (SRspUnknown) (\r -> SRspServerAction $ encode r) res)
+      _ -> 
+        handleRequest replyPort (return ()) (\_ -> SRspUnknown)
+
+
+-- | Creates a new client id and updates the serverdata.
+getNextId :: ServerData -> (IdType, ServerData)
+getNextId sd 
+  = (i, sd { sd_NextId = nid })
+  where
+    i   = sd_NextId sd
+    nid = i + 1
+
+
+-- | Adds a new client to the server datastructures,
+--   the ping-thread will not be started.
+addClientToServer
+  :: IdType -> SiteId -> ClientPort -> Thread
+  -> ServerData -> ServerData
+addClientToServer i sid cp tid sd
+  = sd { sd_ClientMap = nsm', sd_SiteToClientMap = snm', sd_SiteMap = sm' }
+  where
+    --update the ClientMap
+    nsm = sd_ClientMap sd
+    nsm' = Map.insert i (ClientInfo i sid cp tid maxLifeValue) nsm
+    --update the SiteToClientMap
+    snm = sd_SiteToClientMap sd
+    snm' = MMap.insert sid i snm
+    -- update the SiteMap
+    sm = sd_SiteMap sd
+    sm' = addIdToMap sid sm
+    
+
+-- | Deletes a new client from the server datastructures,
+--   the ping-thread will not be closed.
+deleteClientFromServer :: IdType -> ServerData -> ServerData
+deleteClientFromServer i sd 
+  = sd { sd_ClientMap = nsm', sd_SiteToClientMap = snm', sd_SiteMap = sm' }
+  where
+    --update the ClientMap
+    nsm = sd_ClientMap sd
+    nsm' = Map.delete i nsm
+    --update the SiteToClientMap and the SiteIdMap
+    info = lookupClientInfo i sd
+    snm = sd_SiteToClientMap sd
+    sm = sd_SiteMap sd
+    (snm', sm') = deleteSiteId info
+    deleteSiteId Nothing = (snm, sm)
+    deleteSiteId (Just info') = (MMap.deleteElem sid i snm , deleteIdFromMap sid sm)
+      where
+      sid = ci_Site info'
+
+
+-- | Gets the ClientPort from a ClientId (on the ServerData).
+lookupClientInfo :: IdType -> ServerData -> Maybe ClientInfo
+lookupClientInfo i sd = Map.lookup i (sd_ClientMap sd)
+
+
+-- | Gets a list with all registered clients (on the ServerData).
+lookupAllClientInfos :: ServerData -> [ClientInfo]
+lookupAllClientInfos sd = Map.elems (sd_ClientMap sd)
+
+
+-- | Gets the ClientPort from a ClientId (on the Server).
+getClientInfo :: IdType -> Server -> IO (Maybe ClientInfo)
+getClientInfo i (Server server)
+  = withMVar server $ \sd -> return $ lookupClientInfo i sd 
+
+
+-- | Gets a list with all registered clients (on the Server).
+getAllClientInfos :: Server -> IO [ClientInfo]
+getAllClientInfos (Server server)
+  = withMVar server $ \sd -> return $ lookupAllClientInfos sd
+
+-- | Sets the life value of a specific client.
+setClientLife :: Int -> IdType -> Server -> IO ()
+setClientLife v i (Server server)
+  = modifyMVar server $
+      \sd -> do
+        let mbCi = lookupClientInfo i sd
+        sd' <- case mbCi of
+          (Just ci) -> do
+            let ci'  = ci {ci_LifeValue = v}
+                nsm  = sd_ClientMap sd
+                nsm' = Map.insert i ci' nsm
+                sd'  = sd {sd_ClientMap = nsm'}
+            return sd'
+          (Nothing) -> return sd
+        return (sd', ())
+
+-- | Gets the life value of a specific client.
+getClientLife :: IdType -> Server -> IO (Int)
+getClientLife i (Server server)
+  = withMVar server $
+      \sd -> do
+        let mbCi = lookupClientInfo i sd
+        case mbCi of
+          (Just ci) -> return $ ci_LifeValue ci
+          (Nothing) -> return 0
+
+
+instance ServerClass Server where
+  registerClient sid po s@(Server server)
+    = do
+      let cp = newClientPort po
+      -- register the client at the server
+      (ptid,i,register) <- modifyMVar server $
+        \sd ->
+        do
+        -- create a new Id and a new Port
+        let (i, sd') = getNextId sd
+        let register = sd_Register sd
+        -- add node to controller
+        ptid <- newThread
+        let sd'' = addClientToServer i sid cp ptid sd'
+        return (sd'', (ptid, i, register))
+      -- do general registration action
+      register i cp
+      -- startPingProcess for Client
+      setThreadDelay 5000000 ptid
+      setThreadAction (checkClient i cp s ptid) ptid
+      setThreadErrorHandler (handleCheckClientError i s ptid) ptid
+      startThread ptid
+      return i
+     
+  unregisterClient i (Server server)
+    = do
+      debugM localLogger "unregisterClient: start"
+      (mbInfo, unregister) <- modifyMVar server $
+        \sd ->
+        do
+        let unregister = sd_Unregister sd
+        let mbInfo = lookupClientInfo i sd 
+        let sd' = deleteClientFromServer i sd
+        return (sd', (mbInfo,unregister))
+      debugM localLogger "unregisterClient: client deleted"
+      case mbInfo of
+        (Just info) -> 
+          do
+          debugM localLogger "unregisterClient: killing the ping thread"
+          -- kill the ping-thread
+          stopThread (ci_PingThreadId info)
+          debugM localLogger "unregisterClient: ping thread killed"
+          debugM localLogger "unregisterClient: executing unregister-function"
+          -- execute the unregister function
+          unregister i (ci_Port info)
+          debugM localLogger "unregisterClient: unregister-function executed"
+        (Nothing)   ->
+          do
+          debugM localLogger "unregisterClient: no client info found"
+          return ()
+      debugM localLogger "unregisterClient: end"
+        
+  pingServer i (Server server)
+    = withMVar server $
+        \sd -> return $ isJust $ lookupClientInfo i sd
+        
+
+
+instance Debug Server where
+  printDebug (Server server)
+    = withMVar server $
+        \sd ->
+        do
+        putStrLn "printServer"
+        putStrLn $ "OwnStream:       " ++ show (sd_OwnStream sd)
+        putStrLn $ "OwnPort:         " ++ show (sd_OwnPort sd)
+        putStrLn $ "ClientMap:       " ++ show (sd_ClientMap sd)
+        putStrLn $ "SiteToClientMap: " ++ show (sd_SiteToClientMap sd)
+        putStrLn $ "SiteMap:         " ++ show (sd_SiteMap sd)
+        putStrLn $ "NextId:          " ++ show (sd_NextId sd)
+  
+
+
+-- ----------------------------------------------------------------------------
+-- Server-Port
+-- ----------------------------------------------------------------------------
+
+-- | The ServerPort is only a wrapper for a Port-Datatype.  
+data ServerPort = ServerPort (Port ServerRequestMessage)
+  deriving (Show)
+
+instance Binary ServerPort where
+  put (ServerPort p) = put p
+  get
+    = do
+      p <- get
+      return (ServerPort p)
+      
+
+-- | Creates a new ServerPort.
+newServerPort :: StreamName -> Maybe SocketId -> IO ServerPort
+newServerPort sn soid
+  = do
+    p <- newPort sn soid
+    return (ServerPort p)
+
+ 
+instance ServerClass ServerPort where
+  registerClient sid po (ServerPort p) 
+    = do
+      withStream $
+        \s -> performPortAction p s time30 (SReqRegisterClient sid po) $
+          \rsp ->
+          do
+          case rsp of
+            (SRspRegisterClient n) -> return (Just n)
+            _ -> return Nothing
+  
+  unregisterClient i (ServerPort p)
+    = do
+      withStream $
+        \s -> performPortAction p s time30 (SReqUnregisterClient i) $
+          \rsp ->
+          do
+          case rsp of
+            (SRspUnregisterClient) -> return (Just ())
+            _ -> return Nothing
+  
+  pingServer i (ServerPort p)
+    = do
+      withStream $
+        \s -> performPortAction p s time30 (SReqPing i) $
+          \rsp ->
+          do
+          case rsp of
+            (SRspPing b) -> return (Just b)
+            _ -> return Nothing 
+  
+  
+
+
+-- ----------------------------------------------------------------------------
+-- Client-Messages
+-- ----------------------------------------------------------------------------
+  
+-- | Requests datatype, which is send to a filesystem node.
+data ClientRequestMessage
+  = CReqPing IdType
+  | CReqClientAction B.ByteString
+  | CReqClientId
+  | CReqServerPort
+  | CReqUnknown
+  deriving (Show)
+
+instance Binary ClientRequestMessage where
+  put (CReqPing i)         = putWord8 1 >> put i
+  put (CReqClientAction b) = putWord8 2 >> put b
+  put (CReqClientId)       = putWord8 3
+  put (CReqServerPort)     = putWord8 4
+  put (CReqUnknown)        = putWord8 0
+  get
+    = do
+      t <- getWord8
+      case t of
+        1 -> get >>= \i -> return (CReqPing i)
+        2 -> get >>= \b -> return (CReqClientAction b)
+        3 -> return (CReqClientId)
+        4 -> return (CReqServerPort)
+        _ -> return (CReqUnknown)
+
+
+-- | Response datatype from a filesystem node.
+data ClientResponseMessage
+  = CRspPing Bool
+  | CRspClientAction B.ByteString
+  | CRspClientId (Maybe IdType)
+  | CRspServerPort ServerPort
+  | CRspError String
+  | CRspUnknown
+  deriving (Show)      
+
+instance Binary ClientResponseMessage where
+  put (CRspPing b)         = putWord8 1 >> put b
+  put (CRspClientAction b) = putWord8 2 >> put b
+  put (CRspClientId i)     = putWord8 3 >> put i
+  put (CRspServerPort p)   = putWord8 4 >> put p
+  put (CRspError e)        = putWord8 5 >> put e
+  put (CRspUnknown)        = putWord8 0
+  get
+    = do
+      t <- getWord8
+      case t of
+        1 -> get >>= \b -> return (CRspPing b)
+        2 -> get >>= \b -> return (CRspClientAction b)
+        3 -> get >>= \i -> return (CRspClientId i)
+        4 -> get >>= \p -> return (CRspServerPort p)
+        5 -> get >>= \e -> return (CRspError e)
+        _ -> return (CRspUnknown)
+
+instance RspMsg ClientResponseMessage where
+  isError (CRspError _) = True
+  isError _ = False
+  
+  getErrorMsg (CRspError e) = e
+  getErrorMsg _ = ""
+  
+  isUnknown (CRspUnknown) = True
+  isUnknown _ = False
+  
+  mkErrorMsg e = CRspError e
+
+
+
+-- ----------------------------------------------------------------------------
+-- Client-TypeClass
+-- ----------------------------------------------------------------------------
+
+-- | The request-functions a client has to implement.
+class ClientClass c where
+
+  -- | Check, if the client is responding.
+  pingClient :: IdType-> c -> IO Bool
+  
+  -- | Get the ID of the client.
+  getClientId :: c -> IO (Maybe IdType)
+  
+  -- | Gets the server port the client wants to connect to.
+  getServerPort :: c -> IO (ServerPort)
+        
+
+
+  
+-- ----------------------------------------------------------------------------
+-- Client-Data
+-- ----------------------------------------------------------------------------
+
+  
+-- | Client datatype.
+data ClientData = ClientData {
+    cd_ServerThreadId  :: Thread
+  , cd_PingThreadId    :: Thread
+  , cd_Id              :: Maybe IdType
+  , cd_LifeValue       :: Int
+  , cd_SiteId          :: SiteId
+  , cd_OwnStream       :: Stream ClientRequestMessage
+  , cd_OwnPort         :: Port ClientRequestMessage
+  , cd_ServerPort      :: ServerPort
+  }
+
+  
+-- | Only a wrapper around an MVar.
+data Client = Client (MVar ClientData)
+
+
+-- | Creates a new client, it needs the StreamName and optional 
+--   the SocketId of the server.
+newClient
+  :: (Binary a, Binary b)
+  => StreamName -> Maybe SocketId
+  -> (a -> IO (Maybe b))  -- ^ the individual request dispatcher for the client
+  -> IO Client
+newClient sn soid action
+  = do  
+    sp <- newServerPort sn soid
+    -- initialize values
+    sid     <- getSiteId
+    stid    <- newThread  
+    st      <- (newLocalStream Nothing::IO (Stream ClientRequestMessage))
+    po      <- newPortFromStream st
+    ptid    <- newThread
+    let cd = (ClientData stid ptid Nothing maxLifeValue sid st po sp)
+    c <- newMVar cd
+    let client = Client c 
+    -- first, we start the server, because we can't handle requests without it
+    startRequestDispatcher stid st (dispatchClientRequest client action)
+    -- then we try to register a the server
+    setThreadDelay 5000000 ptid
+    setThreadAction (checkServer sp sid po client) ptid
+    setThreadErrorHandler (handleCheckServerError client) ptid
+    startThread ptid
+    return client
+
+
+-- | Closes the client.
+closeClient :: Client -> IO ()
+closeClient (Client client)
+  = modifyMVar client $
+      \cd ->
+      do
+      case (cd_Id cd) of
+        (Just i)  -> unregisterClient i (cd_ServerPort cd)
+        (Nothing) -> return ()
+      stopRequestDispatcher (cd_ServerThreadId cd)
+      closeStream (cd_OwnStream cd)
+      stopThread (cd_PingThreadId cd)
+      return (cd, ())
+
+
+-- | Handles the requests from the server.
+dispatchClientRequest
+  :: (Binary a, Binary b)
+  => Client
+  -> (a -> IO (Maybe b))
+  -> ClientRequestMessage 
+  -> Port ClientResponseMessage
+  -> IO ()
+dispatchClientRequest client action msg replyPort
+  = do
+    debugM localLogger $ "dispatchClientRequest: " ++ show msg
+    case msg of
+      (CReqPing i) ->
+        do
+        handleRequest replyPort (pingClient i client) (\b -> CRspPing b)
+        return ()
+      (CReqClientAction b) ->
+        do
+        -- now, we have a specific client request
+        handleRequest replyPort 
+          (action $ decode b) 
+          (\res -> maybe (CRspUnknown) (\r -> CRspClientAction $ encode r) res)
+      _ -> 
+        handleRequest replyPort (return ()) (\_ -> CRspUnknown)
+
+
+-- | Test, if the client is registered by a server. 
+isClientRegistered :: Client -> IO (Bool, Maybe IdType)
+isClientRegistered (Client client)
+  = withMVar client $ \cd -> return $ (isJust (cd_Id cd), (cd_Id cd))
+
+
+-- | Deletes the internal clientId, the client will then be in an 
+--   unregisterd state.
+unsetClientId :: Client -> IO ()
+unsetClientId (Client client)
+  = modifyMVar client $ \cd -> return ( cd {cd_Id = Nothing}, ())
+
+-- | Sets the life value of the server port.
+setLifeValue :: Int -> Client -> IO ()
+setLifeValue v (Client client)
+  = modifyMVar client $ \cd -> return (cd {cd_LifeValue = v}, ())
+
+-- | Gets the life value of the server port.
+getLifeValue :: Client -> IO (Int)
+getLifeValue (Client client)
+  = withMVar client $ \cd -> return (cd_LifeValue cd)
+
+-- | Assigns a new clientId to the client.
+setClientId :: IdType -> Client -> IO ()
+setClientId i (Client client)
+      = modifyMVar client $ \cd -> return ( cd {cd_Id = Just i}, ())  
+
+
+instance ClientClass Client where
+  pingClient i (Client client)
+    = withMVar client $
+        \cd -> return $ (cd_Id cd) == (Just i)
+        
+  getClientId (Client client)
+    = withMVar client $
+        \cd -> return $ (cd_Id cd)
+    
+  getServerPort (Client client)
+    = withMVar client $
+        \cd -> return $ (cd_ServerPort cd)
+
+
+instance Debug Client where
+  printDebug (Client client)
+    = withMVar client $
+        \cd ->
+        do
+        putStrLn "printClient"
+        putStrLn $ "Id:         " ++ show (cd_Id cd)
+        putStrLn $ "LifeValue   " ++ show (cd_LifeValue cd)
+        putStrLn $ "Site:       " ++ show (cd_SiteId cd)
+        putStrLn $ "OwnStream:  " ++ show (cd_OwnStream cd)
+        putStrLn $ "OwnPort:    " ++ show (cd_OwnPort cd)
+        putStrLn $ "ServerPort: " ++ show (cd_ServerPort cd)
+
+
+
+
+-- ----------------------------------------------------------------------------
+-- Client-Port
+-- ----------------------------------------------------------------------------
+
+-- | Just a wrapper around a port.
+data ClientPort = ClientPort (Port ClientRequestMessage)
+  deriving (Show)
+
+instance Binary ClientPort where
+  put (ClientPort p) = put p
+  get
+    = do
+      p <- get
+      return (ClientPort p)
+
+
+-- | Creates a new ClientPort.
+newClientPort :: Port ClientRequestMessage -> ClientPort
+newClientPort po = ClientPort po
+
+
+
+instance ClientClass ClientPort where
+  pingClient i (ClientPort p)
+    = do
+      withStream $
+        \s -> performPortAction p s time30 (CReqPing i) $
+          \rsp ->
+          do
+          case rsp of
+            (CRspPing b) -> return (Just b)
+            _ -> return Nothing
+
+  getClientId (ClientPort p)
+    = do
+      withStream $
+        \s -> performPortAction p s time30 (CReqClientId) $
+          \rsp ->
+          do
+          case rsp of
+            (CRspClientId i) -> return (Just i)
+            _ -> return Nothing
+    
+  getServerPort (ClientPort p)
+    = do
+      withStream $
+        \s -> performPortAction p s time30 (CReqServerPort) $
+          \rsp ->
+          do
+          case rsp of
+            (CRspServerPort sp) -> return (Just sp)
+            _ -> return Nothing
+
+
+
+
+-- ----------------------------------------------------------------------------
+-- Communication-Functions
+-- ----------------------------------------------------------------------------
+
+-- | Sends a request from the server to the client an handles the response or
+--   invokes a user-defined handler.
+sendRequestToClient 
+  :: (Show a, Binary a, Binary b)
+  => ClientPort -> Int
+  -> a
+  -> (b -> IO (Maybe c))  -- ^ response handler
+  -> IO c
+sendRequestToClient (ClientPort p) timeout a handler
+  = do
+    debugM localLogger $ "sending request to Client: " ++ show a
+    withStream $
+      \s -> performPortAction p s timeout (CReqClientAction (encode a)) $
+        \rsp ->
+        do
+        case rsp of
+          (CRspClientAction b) -> 
+            do
+            handler (decode b)
+          _ -> return Nothing
+
+
+-- | Sends a request from the client to the server an handles the response or
+--   invokes a user-defined handler.
+sendRequestToServer 
+  :: (Show a, Binary a, Binary b)
+  => ServerPort -> Int
+  -> a
+  -> (b -> IO (Maybe c))  -- ^ response handler
+  -> IO c
+sendRequestToServer (ServerPort p) timeout a handler
+  = do
+    debugM localLogger $ "sending message to Server: " ++ show a
+    withStream $
+      \s -> performPortAction p s timeout (SReqServerAction (encode a)) $
+        \rsp ->
+        do
+        case rsp of
+          (SRspServerAction b) -> 
+            do
+            handler (decode b)
+          _ -> return Nothing
+
+          
+-- ----------------------------------------------------------------------------
+-- Ping-Functions
+-- ----------------------------------------------------------------------------
+
+-- | Checks, if a client is still reachable, otherwise it will be deleted
+--   from the server.
+checkClient :: IdType -> ClientPort -> Server -> Thread -> IO ()
+checkClient i po server thread
+  = do
+    debugM localLogger "pingClient"
+    b <- pingClient i po
+    case b of
+      False -> 
+        do
+        warningM localLogger "pingCient: client is not reachable... delete him"
+        handleCheckClientError i server thread
+      True  -> 
+        do
+        debugM localLogger "pingCient: client is ok"
+        setClientLife maxLifeValue i server
+        return ()
+    
+
+-- | If a client does not respond to a ping, this function is invoked.
+--   It deleted the client from the server and stops the ping thread.
+handleCheckClientError :: IdType -> Server -> Thread -> IO ()
+handleCheckClientError i server thread
+   = do
+     v <- getClientLife i server
+     if (v > 0)
+       then do
+         setClientLife (v-1) i server
+       else do
+         unregisterClient i server
+         stopThread thread
+     return ()
+
+
+-- | Checks, if a server is still reachable, otherwise it will be 
+--  deleted from the client.
+checkServer :: ServerPort -> SiteId -> Port ClientRequestMessage -> Client -> IO ()
+checkServer sepo sid clpo c
+  = do
+    debugM localLogger "pingServer"
+    (reg,i) <- isClientRegistered c
+    if (reg)
+      then do
+        debugM localLogger "pingServer: client is registered, testing server" 
+        b <- pingServer (fromJust i) sepo
+        if (b)
+          then do
+            debugM localLogger "pingServer: server is ok"
+            setLifeValue maxLifeValue c
+            return ()              
+          else do
+            warningM localLogger "pingServer: server is down" 
+            handleCheckServerError c
+      else do 
+        debugM localLogger "pingServer: trying to register client"
+        i' <- registerClient sid clpo sepo
+        setClientId i' c    
+
+
+-- | If the server does not respond to a ping, this function is invoked.
+--   It sets the server to an unregistered state, so it will reconnect again.
+handleCheckServerError :: Client -> IO ()
+handleCheckServerError c
+  = do
+    v <- getLifeValue c
+    if (v > 0)
+      then do setLifeValue (v-1) c
+      else do unsetClientId c
diff --git a/source/Holumbus/Network/Core.hs b/source/Holumbus/Network/Core.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Network/Core.hs
@@ -0,0 +1,266 @@
+-- ----------------------------------------------------------------------------
+
+{- |
+  Module     : Holumbus.Network.Core
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+  The Server-Module for the Holumbus framework.
+  
+  It contains the lowlevel functions, like the socket handling (opening, 
+  reading, writing, ...).
+  
+-}
+
+-- ----------------------------------------------------------------------------
+
+{-# OPTIONS -fglasgow-exts #-}
+module Holumbus.Network.Core
+    (
+      -- * Socket-Descriptor
+      SocketId(..)
+
+      -- * Server-Operations
+    , startSocket
+
+      -- * Client-Operations
+    , sendRequest
+
+      -- * Handle-Operations
+    , putMessage
+    , getMessage
+
+    , ThreadIdException(..)
+    )
+where
+
+import           Prelude hiding         ( catch )
+
+import           Control.Concurrent
+import           Control.Exception      ( Exception
+					, bracket
+					, catch
+					)
+import           Control.Monad
+
+import           Data.Binary
+import qualified Data.ByteString.Lazy   as B
+import           Data.Typeable
+
+import           Network
+import qualified Network.Socket         as Socket
+
+import           System.Log.Logger
+import           System.CPUTime
+import           System.IO
+import           System.Posix
+
+import           Text.Printf
+import           Text.XML.HXT.Arrow
+
+import           Holumbus.Common.Utils  ( handleAll )
+
+-- | Logger
+localLogger :: String
+localLogger = "Holumbus.Network.Core"
+
+
+type ServerDispatcher = SocketId -> Handle -> HostName -> PortNumber -> IO ()
+
+-- ------------------------------------------------------------
+--
+-- exception stuff
+
+data ThreadIdException  = ThreadIdException ThreadId
+                          deriving (Typeable, Show)
+
+instance Exception ThreadIdException where
+
+-- ----------------------------------------------------------------------------
+-- Socket Descriptor
+-- ----------------------------------------------------------------------------
+
+-- | All data, that is needed to address a socket.
+--   Contains the hostname and the portNumber.
+data SocketId = SocketId HostName PortNumber 
+  deriving (Show, Eq)
+
+instance Binary (SocketId) where
+  put (SocketId hn po)
+    = put hn >> (put . toInteger) po
+  get
+    = do
+      hn <- get
+      poInt <- get
+      return (SocketId hn (fromInteger poInt))
+
+instance XmlPickler SocketId where
+  xpickle = xpSocketId
+
+xpSocketId :: PU SocketId
+xpSocketId
+  = xpElem "socket" $
+    xpWrap(\(hn, po) -> SocketId hn (fromInteger po), \(SocketId hn po) -> (hn, (toInteger po))) $
+    xpPair (xpAttr "hostname" xpText) (xpAttr "port" xpickle)
+
+
+-- ----------------------------------------------------------------------------
+-- Server-Operations
+-- ----------------------------------------------------------------------------
+
+-- | Creates a new (unix-)socket and starts the listener in its own thread.
+--   You'll get the threadId of the listener Thread, so you can kill it.
+--   It is also possible to give a range of PortNumbers on which the socket
+--   will be opened. The first portnumber available will be taken.
+startSocket 
+  :: ServerDispatcher -- ^ dispatcher function
+  -> PortNumber       -- ^ start port number
+  -> PortNumber       -- ^ end port number
+  -> IO (Maybe (ThreadId, HostName, PortNumber))
+startSocket f actPo maxPo
+  = do
+    s <- (getFirstSocket actPo maxPo)
+    case s of
+      Nothing -> 
+        return Nothing
+      (Just (so, po)) ->
+        do
+        hn <- getHostName
+        tid <- forkIO $ 
+          do
+          handleAll
+            (\e ->
+              do
+              putStrLn $ "ERROR - socket closed with exception: " ++ show e 
+              sClose so
+            ) $
+            do
+            {- 6.8
+            catchDyn (waitForRequests f so (SocketId hn po)) (handler so)
+            -}
+            catch
+              (waitForRequests f so (SocketId hn po))
+              (handler so)
+        return (Just (tid, hn, po))
+    where
+    handler :: Socket -> ThreadIdException -> IO ()
+    handler so (ThreadIdException i)
+        = do
+          sClose so
+          putStrLn $ "socket normally closed by thread " ++ show i 
+
+
+-- | Gets the hostname of the computer of just "localhost".
+getHostName :: IO (HostName)
+getHostName
+  = do
+    (hn, _) <- Socket.getNameInfo [] True False (Socket.SockAddrUnix "localhost")
+    return (maybe "localhost" id hn)
+
+
+-- | Gets the first free port number and creates of new socket on it.
+getFirstSocket :: PortNumber -> PortNumber -> IO (Maybe (Socket, PortNumber))
+getFirstSocket actPo maxPo
+  | actPo > maxPo = return Nothing
+  | otherwise 
+    = do
+      handleAll (return (getFirstSocket (actPo+1) maxPo)) $
+        do
+        socket <- getSocket (PortNumber actPo)
+        return (Just (socket, actPo))     
+
+
+-- | Opens a socket on a port number.
+getSocket :: PortID -> IO (Socket)
+getSocket po =
+  -- for MS-Windows Systems
+  withSocketsDo $ do
+  -- Don't let the server be terminated by sockets closed unexpectedly by the client.
+  installHandler sigPIPE Ignore Nothing
+  socket <- listenOn po
+  return socket
+
+
+-- | Listens to a socket and opens a new dispatcher thread for every incomming
+--   data.
+waitForRequests :: ServerDispatcher -> Socket -> SocketId -> IO ()
+waitForRequests f socket soid = 
+  do
+  client <- accept socket
+  forkIO $ processRequest f soid client   -- Spawn new thread to answer the current request.
+  waitForRequests f socket soid       -- Wait for more requests.
+
+
+-- | A wrapper around the user defined dispatcher function.
+--   Mesures the time and catches unhandled exceptions.
+processRequest :: ServerDispatcher -> SocketId -> (Handle, HostName, PortNumber) -> IO ()
+processRequest f soid client = 
+  bracket (return client) (\(hdl, _, _) -> hClose hdl) (\cl -> processRequest' cl)
+    where
+    processRequest' (hdl, hst, prt) = 
+      do
+      hSetBuffering hdl NoBuffering
+      -- Dispatch the request and measure the processing time.
+      t1 <- getCPUTime
+      debugM localLogger "starting to dispatch request"
+      handleAll (\e -> errorM localLogger $ "UnknownError: " ++ show e) $ do
+        f soid hdl hst prt
+      t2 <- getCPUTime
+      d <- return ((fromIntegral (t2 - t1) / 1000000000000) :: Float)
+      ds <- return (printf "%.4f" d)
+      infoM localLogger ("request processed in " ++ ds ++ " sec")
+
+
+-- ----------------------------------------------------------------------------
+-- Client-Operations
+-- ----------------------------------------------------------------------------
+
+    
+-- | Send the query to a server and merge the result with the global result.
+sendRequest :: (Handle -> IO a) -> HostName -> PortID -> IO a
+sendRequest f n p = 
+  withSocketsDo $ do 
+    installHandler sigPIPE Ignore Nothing
+    
+    --TODO exception handling
+    --handle (\e -> do putStrLn $ show e return False) $
+    bracket (connectTo n p) (hClose) (send)
+    where    
+    send hdl 
+      = do
+        hSetBuffering hdl NoBuffering
+        f hdl
+
+
+-- ----------------------------------------------------------------------------
+-- Handle-Operations
+-- ----------------------------------------------------------------------------
+
+-- | Puts a bytestring to a handle. But to make the reading easier, we write
+--   the length of the data as a message-header to the handle, too. 
+putMessage :: B.ByteString -> Handle -> IO ()
+putMessage msg hdl
+  = do
+    handleAll (\e -> do
+      errorM localLogger $ "putMessage: " ++ show e
+      errorM localLogger $ "message: " ++ show msg 
+     ) $ do
+      hPutStrLn hdl ((show $ B.length msg) ++ " ")
+      B.hPut hdl msg
+
+
+-- | Reads data from a stream. We define, that the first line of the message
+--   is the message header which tells us how much bytes we have to read.
+getMessage :: Handle -> IO (B.ByteString)
+getMessage hdl
+  = do
+    line <- hGetLine hdl
+    let pkg = words line
+    raw <- B.hGet hdl (read $ head pkg)
+    return raw
+  
diff --git a/source/Holumbus/Network/Messages.hs b/source/Holumbus/Network/Messages.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Network/Messages.hs
@@ -0,0 +1,264 @@
+-- ----------------------------------------------------------------------------
+
+{- |
+  Module     : Holumbus.Network.Messages
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+  
+  General functions for the transmission of messages over the Holumbus-Ports.
+  You don't need these functions, but they make your life much easier.
+  
+  The mailbox concept doesn't deal with the request and response scheme
+  very well, but with this module, all the boring stuff is solved. The function
+  performPortAction will do everything for you. If you find it boring to write
+  a seperate listener-thread for every mailbox you want to read from, you
+  might look at the startRequestDispatcher and stopRequestDispatcher functions. 
+
+-}
+
+-- ----------------------------------------------------------------------------
+
+{-# OPTIONS -fglasgow-exts #-}
+module Holumbus.Network.Messages
+(
+-- * Message-Class
+  RspMsg(..)
+
+-- * Port-Handling
+, performPortAction
+
+-- * Stream-Handling
+, startRequestDispatcher
+, stopRequestDispatcher
+, handleRequest
+)
+where
+
+import           Control.Concurrent
+import		 Control.Exception	( Exception
+					, throw
+					)
+{- 6.8
+import qualified Control.Exception as E
+-}
+
+import           Data.Binary
+import           Data.Maybe
+import           Data.Typeable
+
+import           System.Log.Logger
+
+import           Holumbus.Common.Threading
+import           Holumbus.Common.Utils
+import qualified Holumbus.Network.Port as P
+
+
+localLogger :: String
+localLogger = "Holumbus.Network.Messages"
+
+
+
+-- ----------------------------------------------------------------------------
+-- Message-Class
+-- ----------------------------------------------------------------------------
+
+-- | The typeclass for the response messages. We want to react if an error
+--   message is received an this interface helps us to detect and create such
+--   a message. The unknown message will be send back, if the server doesn't
+--   understand our request.
+class RspMsg m where
+  isError :: m -> Bool  
+  getErrorMsg :: m -> String
+  isUnknown :: m -> Bool
+  mkErrorMsg :: String -> m
+
+
+
+-- ----------------------------------------------------------------------------
+-- Port-Handling
+-- ----------------------------------------------------------------------------
+
+-- | Every request might raise an exception
+data MessageException
+    = TimeoutException     	-- ^ if the server takes too long to respond
+    | UnknownRequest       	-- ^ if the server doesn't understand our request
+    | FalseResponse String 	-- ^ when the server response doesn't match our definition
+    | ErrorResponse String	-- ^ if an error in the server occurred and he informs us about the error
+      deriving (Show, Typeable)
+
+instance Exception MessageException
+
+-- | Sends a repest to the server  (stream) and waits for a response.
+--   If the response can't be received in a certain time, a TimeoutException
+--   will be raised. If a response is received, an individual response handler
+--   is executed.
+talkWithServer
+  :: (Show a, Binary a, Show b, Binary b, RspMsg b)
+  => P.Port a          -- ^ port to which the message will be send
+  -> P.Stream b        -- ^ the stream from which the response is read
+  -> Int               -- ^ timeout for the response in nanoseconds (1000000 = 1 sec) (0 = wait for ever)
+  -> a                 -- ^ message to be send
+  -> (b -> IO c)       -- ^ handler function for the response 
+  -> IO c
+talkWithServer p respStream timeout m hdlFct
+  = do
+    respPort <- P.newPortFromStream respStream
+    -- send the request to the node
+    debugM localLogger $ "sending: " ++ show m
+    P.sendWithGeneric p m (encode respPort)
+    --wait for the response
+    debugM localLogger $ "waiting for response for: " ++ show m 
+    response <- P.tryWaitReadStream respStream timeout
+    -- r' <- P.readStream respStream
+    -- let response = Just r'
+    debugM localLogger "response Message..."
+    debugM localLogger $ show response
+    res <- case response of
+      -- if no response
+      Nothing -> do
+        warningM localLogger "talkWithServer: timeout"
+        {- E.throwDyn TimeoutException -}
+	throw TimeoutException
+      -- handle the response
+      (Just r) ->
+        hdlFct r
+    return res
+       
+
+-- | A wrapper around the user defined response handler.
+--   All error and unkown response will be catched, so you don't have to
+--   deal with them. But you can't also throw an error in your response 
+--   function, if you want.
+basicResponseHandler
+  :: (Show b, Binary b, RspMsg b) 
+  => (b -> IO (Maybe c)) 
+  -> b 
+  -> IO c
+basicResponseHandler hdlFct rsp
+  = do
+    -- look for right message
+    res <- hdlFct rsp
+    case res of
+      -- if right type... return result
+      (Just r) -> 
+        return r
+      -- else handle error types
+      Nothing ->
+        handleError
+    where
+      handleError
+        | (isError rsp)   = do
+			    warningM localLogger $ "basicResponseHandler: error: " ++ show rsp
+			    {- 6.8 E.throwDyn $ ErrorResponse $ getErrorMsg rsp -}
+			    throw $ ErrorResponse $ getErrorMsg rsp
+        | (isUnknown rsp) = do
+			    warningM localLogger $ "basicResponseHandler: unknown: " ++ show rsp
+			    {- 6.8 E.throwDyn UnknownRequest -}
+			    throw UnknownRequest
+        | otherwise       = do
+			    warningM localLogger $ "basicResponseHandler: false: " ++ show rsp
+			    {- E.throwDyn $ FalseResponse $ show rsp -}
+			    throw $ FalseResponse $ show rsp
+        
+                    
+-- | Sends a request to the server (stream) and handles the response and all
+--   error cases. Very helpful when simulating a request response scheme
+--   with the mailboxes.                    
+performPortAction
+  :: (Show a, Binary a, Show b, Binary b, RspMsg b) 
+  => P.Port a             -- ^ request port
+  -> P.Stream b           -- ^ response Stream 
+  -> Int                  -- ^ timeout for the response in mikroseconds (1000000 = 1 sec) (0 = wait for ever)
+  -> a                    -- ^ request message
+  -> (b -> IO (Maybe c))  -- ^ response handler
+  -> IO c
+performPortAction reqPo resStr timeout reqMsg rspHdl
+  = do
+    talkWithServer reqPo resStr timeout reqMsg $
+      basicResponseHandler rspHdl
+  
+
+-- ----------------------------------------------------------------------------
+-- Stream-Handling
+-- ----------------------------------------------------------------------------
+
+-- | The server-side request dispatcher handles all incomming responses.
+--   The dispatcher runs in its own thread and should not be killed by
+--   any exceptions which will be raised in the handling process.
+startRequestDispatcher
+  :: (Binary a, Show a, Show b, Binary b, RspMsg b) 
+  => Thread                                     -- ^ threadId, to be filled
+  -> P.Stream a                                 -- ^ request-Stream (this is where the messages come in)
+  -> (a -> P.Port b -> IO ())                   -- ^ the dispatcher (create a reply message)
+  -> IO ()
+startRequestDispatcher thread reqS dispatcher
+  = do
+    setThreadAction (requestDispatcher reqS dispatcher) thread
+    startThread thread
+
+
+-- | Stops the request dispatcher.
+stopRequestDispatcher :: Thread -> IO ()
+stopRequestDispatcher thread
+  = do
+    stopThread thread 
+
+
+-- | Wrapper around the user-defined dispatching function. For every incomming
+--   request a new thread will be created to be able to handle the next request. 
+requestDispatcher 
+  :: (Binary a, Show a, Show b, Binary b, RspMsg b)
+  => P.Stream a 
+  -> (a -> P.Port b -> IO ())
+  -> IO ()
+requestDispatcher reqS dispatcher
+  = do
+    -- read the next message from the stream (block, if no message arrived)
+    msg <- P.readStreamMsg reqS
+    -- extract the data
+    let dat = P.getMessageData msg
+    debugM localLogger "dispatching new Message... "
+    debugM localLogger $ show dat
+    -- extract the (possible replyport)
+    let responsePort = decodeMaybe $ P.getGenericData msg
+    if (isNothing responsePort)
+      then do
+        warningM localLogger "no reply port in message"
+        -- yield
+      else do
+        -- do the dispatching in a new process...
+        _ <- forkIO $ dispatcher dat $ (fromJust responsePort)
+        return ()
+
+
+-- | Execute a function and send its result to the specified port.
+handleRequest
+  :: (Show b, Binary b, RspMsg b)
+  => P.Port b    -- ^ the reply port (where the messages will be send to)
+  -> IO c        -- ^ the action which will generate the data to be send
+  -> (c -> b)    -- ^ create an output from the data
+  -> IO ()
+handleRequest po fhdl fres
+  = do
+    -- in case, we can't send the error...
+    handleAll (\e -> do
+        errorM localLogger $ "handleRequest: exeption raised and could not be send to controller" 
+        errorM localLogger $ show e) $ do
+      do
+      -- in case our operation fails, we send a failure-response
+      handleAll ( \e -> do
+		        errorM localLogger $ "handleRequest: exeption raised and reporting to controller" 
+		        errorM localLogger $ show e
+                        P.send po (mkErrorMsg $ show e)
+		) $
+                do
+		-- our action, might raise an exception
+		r <- fhdl
+		-- send the response
+		P.send po $ fres r
diff --git a/source/Holumbus/Network/Port.hs b/source/Holumbus/Network/Port.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Network/Port.hs
@@ -0,0 +1,982 @@
+-- ----------------------------------------------------------------------------
+
+{- |
+  Module     : Holumbus.Network.Port
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+  Stream and Port datatype for internal an external process communication.
+  Useful for communikation of distributed systems.
+  
+-}
+
+-- ----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -fno-warn-unused-binds #-}	-- for unused record field selectors
+
+module Holumbus.Network.Port
+(
+-- * Constants
+  time1
+, time10
+, time30
+, time60
+, time120
+, timeIndefinitely
+
+-- * Datatypes
+, SocketId(..) -- reexport from core
+, MessageType
+, Message
+, StreamName
+, StreamType(..)
+, Stream
+, Port
+
+-- * Message-Operations
+, getMessageType
+, getMessageData
+, getGenericData
+
+-- * Global-Operations
+, setPortRegistry
+
+-- * Stream-Operations
+, newGlobalStream
+, newLocalStream
+, newPrivateStream
+, newStream
+, closeStream
+
+, isEmptyStream
+, readStream
+, readStreamMsg
+, tryReadStream
+, tryReadStreamMsg
+, tryWaitReadStream
+, tryWaitReadStreamMsg
+, withStream
+
+-- * Port-Operations
+, newPortFromStream
+, newPort
+, newGlobalPort
+
+, isPortLocal
+, send
+, sendWithGeneric
+, sendWithMaybeGeneric 
+
+, writePortToFile
+, readPortFromFile
+
+-- * Debug
+, printStreamController
+)
+where
+
+import           Control.Concurrent
+import           Control.Exception
+import           Control.Monad
+
+import           Data.Binary
+import qualified Data.ByteString.Lazy as B
+import           Data.Char
+import qualified Data.Map as Map
+import           Data.Maybe
+import qualified Data.Set as Set
+import           Data.Time
+import           Network
+
+import           System.IO
+import           System.IO.Unsafe
+import           System.Log.Logger
+import           System.Timeout
+
+import           Text.XML.HXT.Arrow
+
+import           Holumbus.Common.Utils		( handleAll )
+import           Holumbus.Network.Site
+import           Holumbus.Network.Core
+import           Holumbus.Network.PortRegistry
+import qualified Holumbus.Data.MultiMap as MMap
+
+
+localLogger :: String
+localLogger = "Holumbus.Network.Port"
+
+
+
+-- -----------------------------------------------------------------------------
+-- Constants
+-- -----------------------------------------------------------------------------
+
+
+-- | One second
+time1 :: Int
+time1 = 1000000
+
+-- | 10 seconds
+time10 :: Int
+time10 = 10000000
+
+-- | 30 seconds
+time30 :: Int
+time30 = 30000000
+
+
+-- | 60 seconds
+time60 :: Int
+time60 = 60000000
+
+
+-- | 120 seconds
+time120 :: Int
+time120 = 120000000
+
+
+-- | Wait how long it takes
+timeIndefinitely :: Int
+timeIndefinitely = -1
+
+
+-- | The default starting port number 
+defaultPort :: PortNumber
+defaultPort = 9000
+
+
+-- | The default maximal port number
+maxPort :: PortNumber
+maxPort = 40000
+
+
+
+
+-- ----------------------------------------------------------------------------
+-- Message-Datatype
+-- ----------------------------------------------------------------------------
+
+-- | Message Type
+--   Is it an internal Message or does it come from an external Node?
+data MessageType = MTInternal | MTExternal 
+  deriving (Show)
+
+instance Binary MessageType where
+  put MTInternal = putWord8 1
+  put MTExternal = putWord8 2
+  get
+    = do
+      t <- getWord8
+      case t of
+        1 -> return MTInternal
+        _ -> return MTExternal      
+
+
+-- | Message Datatype.
+--   We are sending additional information, to do debugging
+data (Show a, Binary a) => Message a = Message {
+    msg_Type           :: ! MessageType          -- ^ the message-type
+  , msg_Receiver       :: ! StreamName           -- ^ the name of the destination stream
+  , msg_Data           :: ! a                    -- ^ the data  
+  , msg_Generic        :: ! (Maybe B.ByteString) -- ^ some generic data -- could be another port
+  , msg_ReceiverSocket :: ! (Maybe SocketId)     -- ^ socket to which the message is send (DEBUG)
+  , msg_SenderSocket   :: ! (Maybe SocketId)     -- ^ socket from which the message was send (DEBUG)
+  , msg_Send_time      :: ! UTCTime              -- ^ timestamp from the sender (DEBUG)
+  , msg_Receive_time   :: ! UTCTime              -- ^ timestamp from the receiver (DEBUG)
+  } deriving (Show)
+
+instance (Show a, Binary a) => Binary (Message a) where
+  put (Message t r d g rs ss t1 t2)
+    = do
+      put t
+      put r
+      put d
+      put g
+      put rs
+      put ss
+      put $ show t1
+      put $ show t2
+  get
+    = do
+      t     <- get
+      r     <- get
+      d     <- get
+      g     <- get
+      rs    <- get
+      ss    <- get
+      t1Str <- get
+      t2Str <- get
+      return $ (Message t r d g rs ss (read t1Str) (read t2Str))
+
+
+-- ----------------------------------------------------------------------------
+-- Port-Datatype
+-- ----------------------------------------------------------------------------
+
+-- | The port datatype.
+data Port a = Port { p_StreamName :: StreamName      -- ^ the name of the destination stream
+		   , p_SocketId   :: Maybe SocketId
+		   }
+	      deriving (Show)
+
+instance (Show a, Binary a) => Binary (Port a) where
+  put (Port sn soid)	= put sn >> put soid
+  get			= do
+			  sn   <- get
+			  soid <- get
+			  return (Port sn soid)
+
+instance (Show a, Binary a) => XmlPickler (Port a) where
+  xpickle = xpPort
+  
+xpPort :: PU (Port a)
+xpPort = 
+    xpElem "port" $
+    xpWrap(\(sn, soid) -> Port sn soid, \(Port sn soid) -> (sn, soid)) $
+    xpPair (xpAttr "name" xpText) (xpOption $ xpickle)
+
+
+
+
+-- ----------------------------------------------------------------------------
+-- Stream-Datatype
+-- ----------------------------------------------------------------------------
+
+-- | The name of a stream.
+type StreamName = String
+
+
+-- | The stream type, determines the accessibility of a stream
+data StreamType = STGlobal | STLocal | STPrivate
+  deriving (Show, Eq, Ord)
+
+-- | The stream datatype
+data Stream a
+   = Stream {
+      s_StreamName :: StreamName
+    , s_SocketId   :: SocketId
+    , s_Type       :: StreamType
+    , s_Channel    :: BinaryChannel
+    }
+
+instance (Show a, Binary a) => Show (Stream a) where
+  show (Stream sn soid st _)
+    = "(Stream" ++
+      " - Name: " ++ show sn ++
+      " - SocketId: " ++ show soid ++
+      " - Type: " ++ show st ++
+      " )"
+
+
+  
+-- ----------------------------------------------------------------------------
+-- StreamController-Datatype
+-- ----------------------------------------------------------------------------
+
+-- | A chan datatype for binary messages
+type BinaryChannel = (Chan (Message B.ByteString))
+
+
+-- | The stream controller datatype.
+--   We need this to keep a log of all used streams in the program and to
+--   use multiple streams per unix-socket. The access information for the
+--   PortRegistry is also placed here. There should only be one stream
+--   controller per program. To ensure this, we use a global reference to this
+--   data object.
+data StreamControllerData = StreamControllerData
+    (Maybe SocketId)
+    (Maybe GenericRegistry)
+    Int
+    (Map.Map StreamName (BinaryChannel, PortNumber, StreamType))
+    (Map.Map PortNumber (ThreadId, HostName))
+    (MMap.MultiMap PortNumber StreamName) 
+  
+instance Show StreamControllerData where
+  show (StreamControllerData ds _ si stm sem pom)
+    =  "StreamControllerData:\n"
+    ++ "  DefaultSocket:\t" ++ show ds
+    ++ "  lastStreamId:\t" ++ show si
+    ++ "  Streams:\t" ++ show (Map.keys stm)
+    ++ "  ServerMap:\t" ++ show sem
+    ++ "  PortMap:\t" ++ show pom
+
+
+-- | The stream controller.
+type StreamController = MVar StreamControllerData
+
+
+
+
+-- ----------------------------------------------------------------------------
+-- StreamController-Operations
+-- ----------------------------------------------------------------------------
+
+-- | A direct access to the program stream controller.
+{-# NOINLINE streamController #-}
+streamController :: StreamController
+streamController
+  = do
+    unsafePerformIO $ newMVar emptyStreamControllerData
+    where
+      emptyStreamControllerData
+        = StreamControllerData
+            Nothing
+            Nothing
+            0
+            Map.empty
+            Map.empty 
+            MMap.empty 
+
+
+-- | Sets the link to the PortRegistry in the stream controller 
+setPortRegistry :: (PortRegistry r) => r -> IO ()
+setPortRegistry r
+  = modifyMVar streamController $
+      \(StreamControllerData s _ i sm pm pmm) ->
+      return ((StreamControllerData s (Just $ mkGenericRegistry r) i sm pm pmm),())
+
+
+-- | Gets the next generated and program unique stream name.
+getNextStreamName :: IO (StreamName)
+getNextStreamName 
+  = modifyMVar streamController $
+      \(StreamControllerData s r i sm pm pmm) ->
+      do
+      let i'   = i + 1
+      let n    = "$" ++ show i'
+      let scd' = StreamControllerData s r i' sm pm pmm
+      return (scd',n)
+      
+
+-- | Test, if a user defined stream name is valid.
+--   A stream name may only contain numbers and characters.
+isValidStreamName :: StreamName -> Bool
+isValidStreamName [] = False
+isValidStreamName sn = null $ filter isForbiddenChar sn 
+  where
+  isForbiddenChar c = not $ isAlphaNum c
+
+
+-- | Test, if the stream name is valid and if it is not already used in the
+--   program.
+validateStreamName :: Maybe StreamName -> IO (StreamName)
+validateStreamName (Nothing) = getNextStreamName
+validateStreamName (Just sn)
+  | isValidStreamName sn 
+      = do
+        taken <- withMVar streamController $
+          \(StreamControllerData _ _ _ sm _ _) -> 
+          return $ Map.member sn sm 
+        if (taken) 
+          then do error "stream name already exists"
+          else do return sn 
+  | otherwise 
+      = error "invalid stream name"
+
+
+-- | Opens a unix-socket on the given port number. If no port number is 
+--   specified, the default port number will be used. It is not problem that 
+--   two ports share the same unix-socket. The stream controller will handle
+--   the incomming messages to the right stream.
+openSocket :: Maybe PortNumber -> IO (SocketId)
+-- get/start the default socket
+openSocket (Nothing)
+  = modifyMVar streamController $
+      \scd@(StreamControllerData s r i sm pm pmm) ->
+      do
+      case s of
+        (Nothing) ->
+          do
+          res <- startStreamServer defaultPort maxPort
+          case res of
+            (Nothing) -> 
+              error "Port: getDefaultPort: unable to open defaultsocket"
+            (Just (soid@(SocketId hn pn), tid)) ->
+              do
+              let pm'  = Map.insert pn (tid,hn) pm
+              let s'   = Just soid
+              let scd' = StreamControllerData s' r i sm pm' pmm
+              return (scd',soid)
+        (Just soid) -> 
+          return (scd,soid)
+-- get/start the new socket
+openSocket (Just pn)
+  = modifyMVar streamController $
+      \scd@(StreamControllerData s r i sm pm pmm) ->
+      do
+      let mp = Map.lookup pn pm
+      case mp of
+        (Nothing) ->
+          do
+          res <- startStreamServer pn pn
+          case res of
+            (Nothing) -> 
+              error "Port: getDefaultPort: unable to open socket"
+            (Just (soid@(SocketId hn _), tid)) ->
+              do
+              let pm'  = Map.insert pn (tid,hn) pm
+              let scd' = StreamControllerData s r i sm pm' pmm
+              return (scd',soid)
+        (Just (_,hn)) ->
+          return (scd,SocketId hn pn)
+         
+
+-- | Closes a socket, only possible, if the unix-socket was used by only one
+--   stream.
+closeSocket :: SocketId -> IO ()
+closeSocket soid@(SocketId _ pn)
+  = modifyMVar streamController $
+      \scd@(StreamControllerData s r i sm pm pmm) ->
+      do
+      if (isNothing s || soid == fromJust s)
+        -- don't delete the defaultSocket
+        then do
+          return (scd,())
+        else do
+          if (MMap.member pn pmm)
+            -- if the port is still used by other streams, keep it
+            then do
+              return (scd,())
+            -- close the socket and delete it from the controller
+            else do
+              let (tid, _) = fromJust $ Map.lookup pn pm
+              stopStreamServer tid
+              let pm'  = Map.delete pn pm
+              let scd' = StreamControllerData s r i sm pm' pmm
+              return (scd',())
+      
+
+-- | Registers a stream at the stream controller.
+registerStream :: Stream a ->  IO ()
+registerStream st
+  = modifyMVar streamController $
+      \(StreamControllerData s r i sm pm pmm) ->
+      do
+      let sm'  = Map.insert sn (ch,pn,ty) sm
+      let pmm'  = MMap.insert pn sn pmm 
+      return ((StreamControllerData s r i sm' pm pmm'), ())
+    where      
+    (SocketId _ pn) = s_SocketId st
+    ch = s_Channel st
+    sn = s_StreamName st
+    ty = s_Type st
+
+
+-- | Deletes a stream from the stream controller. 
+unregisterStream :: Stream a -> IO ()
+unregisterStream st
+  = modifyMVar streamController $
+      \(StreamControllerData s r i sm pm pmm) ->
+      do
+      let sm'  = Map.delete sn sm
+      let pmm' = MMap.deleteElem pn sn pmm
+      return ((StreamControllerData s r i sm' pm pmm'), ()) 
+    where      
+    (SocketId _ pn) = s_SocketId st
+    sn = s_StreamName st
+
+
+-- | Registers a stream at the global PortRegistry.
+registerGlobalPort :: Stream a -> IO ()
+registerGlobalPort (Stream sn soid STGlobal _)
+  = do
+    r <- withMVar streamController $
+      \(StreamControllerData _ r' _ _ _ _) -> return r'
+    case r of
+      (Just r') -> registerPort sn soid r'
+      (Nothing) -> errorM localLogger $ "registerGlobalPort: no portregistry while handling port " ++ sn
+registerGlobalPort _ = return ()
+
+
+-- | Deletes a stream from the global PortRegistry.
+unregisterGlobalPort :: Stream a -> IO ()
+unregisterGlobalPort (Stream sn _ STGlobal _)
+  = do
+    r <- withMVar streamController $
+      \(StreamControllerData _ r' _ _ _ _) -> return r'
+    case r of
+      (Just r') -> unregisterPort sn r'
+      (Nothing) -> errorM localLogger $ "unregisterGlobalPort: no portregistry while handling port " ++ sn
+unregisterGlobalPort _ = return ()
+
+
+-- | Get the unix-socket of a stream to create a global port.
+getGlobalPort :: StreamName -> IO (Maybe SocketId)
+getGlobalPort sn
+  = do
+    r <- withMVar streamController $
+      \(StreamControllerData _ r' _ _ _ _) -> return r'
+    case r of
+      (Just rp) -> 
+        do
+        handleAll (\e -> do
+          errorM localLogger $ "getGlobalPort: error while getting port: " ++ sn ++ " exception: " ++ show e
+          return Nothing
+         ) $ do
+         lookupPort sn rp             
+      (Nothing) -> do 
+        errorM localLogger $ "getGlobalPort: no portregistry found while getting port: " ++ sn
+        return Nothing
+
+
+-- | Gets the names of all stream from a specified port number.
+getStreamNamesForPort :: PortNumber -> IO (Set.Set StreamName)
+getStreamNamesForPort pn
+  = withMVar streamController $
+      \(StreamControllerData _ _ _ _ _ pmm) ->
+      return $ MMap.lookup pn pmm
+
+
+-- | Gets the data of a stream from the stream controller.
+getStreamData :: StreamName -> IO (Maybe (BinaryChannel, PortNumber, StreamType))
+getStreamData sn
+  = withMVar streamController $
+      \(StreamControllerData _ _ _ sm _ _) ->
+      return $ Map.lookup sn sm
+
+
+
+-- -----------------------------------------------------------------------------
+-- Message-Operations
+-- -----------------------------------------------------------------------------
+
+-- | Encodes a message into a bytestring.
+encodeMessage :: (Show a, Binary a) => Message a -> Message B.ByteString
+encodeMessage (Message t n d g r s t1 t2) = (Message t n (encode d) g r s t1 t2)
+
+
+-- | Decodes a message from a bytestring.
+decodeMessage :: (Show a, Binary a) => Message B.ByteString -> Message a
+decodeMessage (Message t n d g r s t1 t2) = (Message t n (decode d) g r s t1 t2)
+
+
+-- | Creates a new message with the current time.
+newMessage :: (Show a, Binary a) => MessageType -> StreamName -> a -> Maybe B.ByteString -> IO (Message a)
+newMessage t n d g
+  = do
+    time <- getCurrentTime
+    return (Message t n d g Nothing Nothing time time)
+
+
+-- | Gets the type of a message.
+getMessageType :: (Show a, Binary a) => Message a -> MessageType
+getMessageType = msg_Type
+
+
+-- | Gets the data of a message.
+getMessageData :: (Show a, Binary a) => Message a -> a
+getMessageData = msg_Data
+
+
+-- | Gets the generic data (usually the return port) of a message.
+getGenericData :: (Show a, Binary a) => Message a -> (Maybe B.ByteString)
+getGenericData = msg_Generic
+
+
+-- | Gets the distination stream name of the message.
+getMessageReceiver :: (Show a, Binary a) => Message a -> StreamName
+getMessageReceiver = msg_Receiver
+
+
+-- | Sets the receive time of a message.
+updateReceiveTime :: (Show a, Binary a) => Message a -> IO (Message a)
+updateReceiveTime msg 
+  = do
+    time <- getCurrentTime
+    return (msg {msg_Receive_time = time})
+
+-- | Sets the receiver unix-socket of the message.
+updateReceiverSocket :: (Show a, Binary a) => Message a -> SocketId -> Message a
+updateReceiverSocket msg soId = msg { msg_ReceiverSocket = Just soId }
+
+
+-- | Sets the sender unix-socket of the message.
+updateSenderSocket :: (Show a, Binary a) => Message a -> SocketId -> Message a
+updateSenderSocket msg soId = msg { msg_SenderSocket = Just soId } 
+
+
+
+
+-- ----------------------------------------------------------------------------
+-- Stream-Operations
+-- ----------------------------------------------------------------------------
+
+
+-- | Creates a new global stream.
+newGlobalStream :: (Show a, Binary a) => StreamName -> IO (Stream a)
+newGlobalStream n = newStream STGlobal (Just n) Nothing
+
+
+-- | Creates a new local stream.
+newLocalStream :: (Show a, Binary a) => Maybe StreamName -> IO (Stream a)
+newLocalStream sn = newStream STLocal sn Nothing
+
+
+-- | Creates a new private stream.
+newPrivateStream :: (Show a, Binary a) => Maybe StreamName -> IO (Stream a)
+newPrivateStream sn = newStream STPrivate sn Nothing
+
+
+-- | General function for creating a new stream.
+newStream 
+  :: (Show a, Binary a) 
+  => StreamType -> Maybe StreamName -> Maybe PortNumber 
+  -> IO (Stream a)
+newStream STGlobal Nothing _ = error "newStream: global ports always need a name"
+newStream st n pn
+  = do
+    ch <- newChan
+    sn <- validateStreamName n
+    infoM localLogger $ "opening socket for " ++ sn
+    soid <- openSocket pn
+    let s = Stream sn soid st ch
+    infoM localLogger $ "registering " ++ show sn ++ " at controller"
+    registerStream s
+    infoM localLogger $ "registering " ++ show sn ++ " at registry"
+    registerGlobalPort s
+    return s
+
+
+-- | Closes a stream.
+closeStream :: (Show a, Binary a) => Stream a -> IO ()
+closeStream s
+  = do
+    infoM localLogger $ "unregistering " ++ show sn ++ " at registry"
+    unregisterGlobalPort s
+    infoM localLogger $ "unregistering " ++ show sn ++ " at controller"
+    unregisterStream s
+    infoM localLogger $ "closing socket for " ++ sn
+    closeSocket (s_SocketId s)
+    where
+    sn = s_StreamName s
+
+
+-- | Writes a message to the channel of the stream.
+--   This function is not public, so you have to write to a stream throug its
+--   port
+writeChannel :: Chan (Message B.ByteString) -> Message B.ByteString -> IO ()
+writeChannel ch msg
+  = do
+    newMsg <- updateReceiveTime msg
+    writeChan ch newMsg
+
+
+-- | Test, if the stream contains new messages.
+isEmptyStream :: Stream a -> IO Bool
+isEmptyStream s
+  = do
+    isEmptyChan (s_Channel s)
+
+
+-- | Reads the data packet of the next message from a stream.
+--   If stream is empty, this function will block until a new message arrives.
+readStream :: (Show a, Binary a) => Stream a -> IO a
+readStream s
+  = do
+    msg <- readStreamMsg s
+    return (msg_Data msg)
+
+
+-- | Reads the next message from a stream (data packet + message header).
+--   If stream is empty, this function will block until a new message arrives.
+readStreamMsg :: (Show a, Binary a) => Stream a -> IO (Message a)
+readStreamMsg s
+  = do
+    debugM localLogger "PORT: readStreamMsg 1"
+    res <- readChan (s_Channel s)
+    debugM localLogger "PORT: readStreamMsg 2"
+    return $ decodeMessage res
+
+
+--TODO is there a better way for non-blocking?
+-- | Helper function for doing a non blocking stream action.
+tryStreamAction :: Stream a -> (Stream a -> IO (b)) -> IO (Maybe b)
+tryStreamAction s f
+  = do
+    empty <- isEmptyStream s
+    if (not empty) 
+      then do timeout 1000 (f s)
+      else do return Nothing
+
+
+-- | Helper function for doing a timed stream action.
+tryWaitStreamAction :: Stream a -> (Stream a -> IO (b)) -> Int -> IO (Maybe b)
+tryWaitStreamAction s f t
+  = do
+    debugM localLogger "tryWaitStreamAction: waiting..."
+    r <- timeout t (f s)
+    debugM localLogger "tryWaitStreamAction: ...finished"
+    let debugResult = maybe "nothing received" (\_ -> "value found") r
+    debugM localLogger $ "tryWaitStreamAction: " ++ debugResult
+    return r
+    
+
+-- | Reads the data packet of the next message from a stream.
+--   If stream is empty, this function will immediately return with Nothing.
+tryReadStream :: (Show a, Binary a) => Stream a -> IO (Maybe a)
+tryReadStream s
+  = do
+    tryStreamAction s readStream
+
+
+-- | Reads the next message from a stream (data packet + message header).
+--   If stream is empty, this function will immediately return with Nothing.
+tryReadStreamMsg :: (Show a, Binary a) => Stream a -> IO (Maybe (Message a))
+tryReadStreamMsg s
+  = do
+    tryStreamAction s readStreamMsg
+
+
+-- | Reads the data packet of the next message from a stream.
+--   If stream is empty, this function will wait for new messages until the 
+--   time is up and if no message has arrived, return with Nothing.
+tryWaitReadStream :: (Show a, Binary a) => Stream a -> Int -> IO (Maybe a)
+tryWaitReadStream s t 
+  = do
+    tryWaitStreamAction s readStream t
+
+
+-- | Reads the next message from a stream (data packet + message header).
+--   If stream is empty, this function will wait for new messages until the 
+--   time is up and if no message has arrived, return with Nothing.
+tryWaitReadStreamMsg :: (Show a, Binary a) => Stream a -> Int -> IO (Maybe (Message a))
+tryWaitReadStreamMsg s t
+  = do
+    tryWaitStreamAction s readStreamMsg t
+
+
+-- | Encapsulates a stream.
+--   A new stream is created, then some user-action is done an after that the
+--   stream is closed. 
+withStream :: (Show a, Binary a) => (Stream a -> IO b) -> IO b
+withStream f
+  = do
+    debugM localLogger "withStream: creating new stream"
+    s <- newStream STLocal Nothing Nothing
+    debugM localLogger "withStream: new stream created"
+    res <- f s
+    closeStream s
+    return res
+
+
+
+
+-- ----------------------------------------------------------------------------
+-- StreamServer-Operations
+-- ----------------------------------------------------------------------------
+
+-- | Starts a new thread which will listen on a unix-socket for new messages
+--   and delegate them to their streams.
+startStreamServer :: PortNumber -> PortNumber -> IO (Maybe (SocketId, ThreadId))
+startStreamServer actPo maxPo
+  = do
+    res <- startSocket (streamDispatcher) actPo maxPo
+    case res of
+      Nothing ->
+        return Nothing
+      (Just (tid, hn, po)) ->
+        return (Just (SocketId hn po, tid))
+    
+
+-- | Stops a thread listening to a unix-socket.
+stopStreamServer :: ThreadId -> IO ()
+stopStreamServer sId 
+  = do
+    me <- myThreadId
+    debugM localLogger $ "stopping server... with threadId: " ++ show sId ++ " - form threadId: " ++ show me
+    {- 6.8 throwDynTo sId me -}
+    throwTo sId (ThreadIdException me)
+    yield
+
+
+-- | Delegates new incomming messages on a unix-socket to their streams.
+streamDispatcher :: SocketId -> Handle -> HostName -> PortNumber -> IO ()
+streamDispatcher (SocketId _ ownPo) hdl hn po
+  = do
+    debugM localLogger "streamDispatcher: getting message from handle"
+    raw <- getMessage hdl
+    let msg = (decode raw)::Message B.ByteString
+    debugM localLogger $ "streamDispatcher: Message: " ++ show msg
+    let sn = getMessageReceiver msg
+    sns <- getStreamNamesForPort ownPo
+    sd <- getStreamData sn
+    if (Set.member sn sns)
+      -- if the socket knows the stream 
+      then do
+        case sd of
+          (Just (_,_,STPrivate)) ->
+            warningM localLogger $ "streamDispatcher: received msg for private stream " ++ sn
+          (Just (ch,_,_)) ->
+            do
+            debugM localLogger "streamDispatcher: writing message to channel"
+            writeChannel ch $ updateSenderSocket msg (SocketId hn po)
+            debugM localLogger "streamDispatcher: message written to channel"
+          (Nothing) ->
+            do
+            errorM localLogger $ "streamDispatcher: no channel for stream " ++ sn
+      -- if the stream is unknown, log this as error
+      else do
+        warningM localLogger $ "streamDispatcher: received msg for unknown stream " ++ sn
+
+
+
+
+-- -----------------------------------------------------------------------------
+-- Port Operations  
+-- -----------------------------------------------------------------------------
+
+
+-- | Creates a new Port, which is bound to a stream.
+newPortFromStream :: Stream a -> IO (Port a)
+newPortFromStream s
+  = do
+    let sn = s_StreamName s
+    let soid = s_SocketId s
+    return $ Port sn (Just soid)
+
+
+-- | Creates a new port from a streamname and its socketId.
+newPort :: StreamName -> Maybe SocketId -> IO (Port a)
+newPort sn soid = return $ Port sn soid
+
+
+-- | Creates a new port to a global stream, only its name is needed.
+newGlobalPort :: StreamName -> IO (Port a)
+newGlobalPort sn = return $ Port sn Nothing
+
+
+-- | Test, if a port is local.
+isPortLocal :: Port a -> IO Bool
+isPortLocal (Port sn mbSoid)
+  = do
+    sd <- getStreamData sn
+    case sd of
+      (Just (_,po,_)) ->
+        do
+        case mbSoid of
+          (Just s1) ->
+             do
+             sid <- getSiteId
+             let hn = getSiteHost sid
+             let s2 = SocketId hn po 
+             return (s1 == s2)
+          (Nothing) ->
+             do
+             return False
+      (Nothing) ->
+        return False
+  
+    
+-- | Send data to the stream of the port.
+--   The data is send via network, if the stream is located on an external
+--   processor
+send :: (Show a, Binary a) => Port a -> a -> IO ()
+send p d = sendWithMaybeGeneric p d Nothing
+
+
+-- | Like "send", but here we can give some generic data (e.g. a port for reply 
+--   messages).
+sendWithGeneric :: (Show a, Binary a) => Port a -> a -> B.ByteString -> IO ()
+sendWithGeneric p d rp = sendWithMaybeGeneric p d (Just rp) 
+
+
+-- | Like "sendWithGeneric", but the generic data is optional
+sendWithMaybeGeneric :: (Show a, Binary a) => Port a -> a -> Maybe B.ByteString -> IO ()
+sendWithMaybeGeneric p@(Port sn mbsoid) d rp
+  = do
+    local <- isPortLocal p
+    if local
+      -- we have a local stream
+      then do
+        msg <- newMessage MTInternal sn d rp
+        sd <- getStreamData sn
+        case sd of
+          (Just (ch,_,_)) ->
+            do
+            writeChannel ch $ encodeMessage msg
+          _ ->
+            do
+            errorM localLogger $ "sendWithMaybeGeneric: no channel found for stream " ++ sn
+      else do
+        -- we have an external stream
+        case mbsoid of
+          -- we know it's port
+          (Just so@(SocketId hn po)) ->
+            do
+            msg <- newMessage MTExternal sn d rp
+            let raw = encode $ encodeMessage $ updateReceiverSocket msg so
+            sendRequest (putMessage raw) hn (PortNumber po)
+            return ()
+          -- we don't know it's port
+          (Nothing) ->
+            do
+            extsoid <- getGlobalPort sn
+            case extsoid of
+              (Just so@(SocketId hn po)) ->
+                do
+                msg <- newMessage MTExternal sn d rp
+                let raw = encode $ encodeMessage $ updateReceiverSocket msg so
+                sendRequest (putMessage raw) hn (PortNumber po)
+                return ()
+              (Nothing) ->
+                do
+                errorM localLogger errorMsg
+                error errorMsg
+                where
+                errorMsg = "sendWithMaybeGeneric: global port not found for stream " ++ sn
+
+
+-- | Writes a port-description to a file.
+--   Quite useful fpr sharing ports between programs
+writePortToFile :: (Show a, Binary a) => Port a -> FilePath -> IO ()
+writePortToFile p fp
+  = do
+    bracket 
+      (openFile fp WriteMode)
+      (hClose) 
+      (\hdl ->
+        do 
+        enc <- return (encode $ p)
+        hPutStrLn hdl ((show $ B.length enc) ++ " ")
+        B.hPut hdl enc
+      )
+
+
+-- | Reads a port-description from a file.
+--   Quite useful fpr sharing ports between programs
+readPortFromFile :: (Show a, Binary a) => FilePath -> IO (Port a)
+readPortFromFile fp
+  =  do
+     bracket
+        (openFile fp ReadMode)
+        (hClose)
+        (\hdl -> 
+          do
+          pkg <- liftM words $ hGetLine hdl
+          raw <- B.hGet hdl (read $ head pkg)
+          p <- return (decode raw)
+          return p
+        )
+
+
+
+
+-- ----------------------------------------------------------------------------
+-- Debugging
+-- ----------------------------------------------------------------------------
+
+-- | Prints the internal data of the stream controller to stdout,
+--   useful for debugging.
+printStreamController :: IO ()
+printStreamController
+  = withMVar streamController $
+      \scd ->
+      do
+      putStrLn "StreamController:"
+      putStrLn $ show scd
+
diff --git a/source/Holumbus/Network/PortRegistry.hs b/source/Holumbus/Network/PortRegistry.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Network/PortRegistry.hs
@@ -0,0 +1,81 @@
+-- ----------------------------------------------------------------------------
+{- |
+  Module     : Holumbus.Network.PortRegistry
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+
+  The typeclass for the PortRegistry. Contains all PortRegistry functions which
+  can accessed remotely by the clients.
+  
+-}
+-- ----------------------------------------------------------------------------
+
+{-# OPTIONS -fglasgow-exts #-}
+module Holumbus.Network.PortRegistry
+    (
+      -- * Type-Classes
+      PortRegistry(..)
+
+      -- * GenericRegistry
+    , GenericRegistry
+    , mkGenericRegistry
+    )
+where
+
+import Holumbus.Network.Core
+
+-- ----------------------------------------------------------------------------
+-- Type-Class
+-- ----------------------------------------------------------------------------
+
+-- | The Interface of the PortRegistry.
+class PortRegistry pr where
+
+  -- | Creates a new port entry in the registry.
+  registerPort :: String -> SocketId -> pr -> IO ()
+
+  -- | Deletes an entry from the registry.
+  unregisterPort :: String -> pr -> IO ()
+
+  -- | Get the socket of the port by its name.
+  lookupPort :: String -> pr -> IO (Maybe SocketId)
+
+  -- | Get a list of all registered ports.
+  getPorts :: pr -> IO [(String, SocketId)]
+  
+
+
+
+-- ----------------------------------------------------------------------------
+-- GenericRegistry
+-- ----------------------------------------------------------------------------
+  
+-- | The generic registry object.
+--   This is a wrapper around an PortRegistryData or PortRegistryPort object.
+--   With this additional indirection, we eliminate the distinction between
+--   the port or the data object in the datatypes using the PortRegistry.
+--   Therefore it is easier to get access to the registry and the code gets 
+--   more readable.
+--   This might be a good example of hiding network-access. To the caller it
+--   makes no difference, if the PortRegistry is in the same address space of
+--   on another computer in the network.
+
+data GenericRegistry = forall r. (PortRegistry r) => GenericRegistry r
+
+
+-- | Creates a new generic PortRegistry.
+mkGenericRegistry :: (PortRegistry r) => r -> GenericRegistry
+mkGenericRegistry = GenericRegistry
+
+
+instance PortRegistry GenericRegistry where
+  registerPort sn soid (GenericRegistry r) = registerPort sn soid r
+  unregisterPort sn (GenericRegistry r) = unregisterPort sn r
+  lookupPort sn (GenericRegistry r) = lookupPort sn r
+  getPorts (GenericRegistry r) = getPorts r
diff --git a/source/Holumbus/Network/PortRegistry/Messages.hs b/source/Holumbus/Network/PortRegistry/Messages.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Network/PortRegistry/Messages.hs
@@ -0,0 +1,121 @@
+-- ----------------------------------------------------------------------------
+{- |
+  Module     : Holumbus.Network.PortRegistry.Messages
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+
+  This modules defines the messages from and to the PortRegistry.
+
+-}
+-- ----------------------------------------------------------------------------
+
+module Holumbus.Network.PortRegistry.Messages
+(
+  PortRegistryRequestStream
+, PortRegistryRequestPort
+
+, PortRegistryResponseStream
+, PortRegistryResponsePort
+
+, PortRegistryRequestMessage(..)
+, PortRegistryResponseMessage(..)
+)
+where
+
+import           Data.Binary
+
+import           Holumbus.Network.Port
+import           Holumbus.Network.Core
+import           Holumbus.Network.Messages
+
+
+-- ----------------------------------------------------------------------------
+-- Ports
+-- ----------------------------------------------------------------------------
+
+-- | The Stream for the messages TO the PortRegistry.
+type PortRegistryRequestStream  = Stream PortRegistryRequestMessage
+
+-- | The Port for the messages TO the PortRegistry.
+type PortRegistryRequestPort    = Port PortRegistryRequestMessage
+
+-- | The Stream for the messages FROM the PortRegistry.
+type PortRegistryResponseStream = Stream PortRegistryResponseMessage
+
+-- | The Port for the messages FROM the PortRegistry.
+type PortRegistryResponsePort   = Port PortRegistryResponseMessage
+
+
+
+-- ----------------------------------------------------------------------------
+-- Messages
+-- ----------------------------------------------------------------------------
+
+-- | The messages TO the PortRegistry.
+data PortRegistryRequestMessage
+  = PRReqRegister StreamName SocketId
+  | PRReqUnregister StreamName
+  | PRReqLookup StreamName
+  | PRReqGetPorts
+  | PRReqUnknown
+  deriving (Show)
+
+instance Binary PortRegistryRequestMessage where
+  put (PRReqRegister sn soid) = putWord8 1 >> put sn >> put soid
+  put (PRReqUnregister sn)    = putWord8 2 >> put sn
+  put (PRReqLookup sn)        = putWord8 3 >> put sn
+  put (PRReqGetPorts)         = putWord8 4
+  put (PRReqUnknown)          = putWord8 0
+  get
+    = do
+      t <- getWord8
+      case t of
+        1 -> get >>= \sn -> get >>= \soid -> return (PRReqRegister sn soid)
+        2 -> get >>= \sn -> return (PRReqUnregister sn)
+        3 -> get >>= \sn -> return (PRReqLookup sn)
+        4 -> return (PRReqGetPorts)
+        _ -> return (PRReqUnknown)
+
+
+-- | The messages FROM the PortRegistry.
+data PortRegistryResponseMessage
+  = PRRspSuccess
+  | PRRspLookup (Maybe SocketId)
+  | PRRspGetPorts [(String,SocketId)]
+  | PRRspError String
+  | PRRspUnknown
+  deriving (Show)
+
+instance Binary PortRegistryResponseMessage where
+  put (PRRspSuccess)     = putWord8 1
+  put (PRRspLookup soid) = putWord8 2 >> put soid
+  put (PRRspGetPorts ls) = putWord8 3 >> put ls
+  put (PRRspError e)     = putWord8 4 >> put e
+  put (PRRspUnknown)     = putWord8 0
+  get
+    = do
+      t <- getWord8
+      case t of
+        1 -> return (PRRspSuccess)
+        2 -> get >>= \soid -> return (PRRspLookup soid)
+        3 -> get >>= \ls -> return (PRRspGetPorts ls)
+        4 -> get >>= \e -> return (PRRspError e)
+        _ -> return (PRRspUnknown)
+
+instance RspMsg PortRegistryResponseMessage where
+  isError (PRRspError _) = True
+  isError _ = False
+  
+  getErrorMsg (PRRspError e) = e
+  getErrorMsg _ = ""
+  
+  isUnknown (PRRspUnknown) = True
+  isUnknown _ = False  
+    
+  mkErrorMsg e = PRRspError e
diff --git a/source/Holumbus/Network/PortRegistry/PortRegistryData.hs b/source/Holumbus/Network/PortRegistry/PortRegistryData.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Network/PortRegistry/PortRegistryData.hs
@@ -0,0 +1,163 @@
+-- ----------------------------------------------------------------------------
+{- |
+  Module     : Holumbus.Network.PortRegistry.PortRegistryData
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+
+  This module contains the main datatype for the PortRegistry.
+  
+-}
+-- ----------------------------------------------------------------------------
+
+module Holumbus.Network.PortRegistry.PortRegistryData
+(
+-- * Datatypes
+  PortRegistryData
+
+-- * Creation and Destruction
+, newPortRegistryData
+, closePortRegistryData
+
+, getPortRegistryRequestPort
+
+-- * reexport
+, setPortRegistry 
+)
+where
+
+
+import           Control.Concurrent
+import qualified Data.Map as Map
+import           Network
+import           System.Log.Logger
+
+import           Holumbus.Common.Threading
+import           Holumbus.Network.Port
+import           Holumbus.Network.Messages
+import           Holumbus.Network.PortRegistry
+import           Holumbus.Network.PortRegistry.Messages
+
+
+localLogger :: String
+localLogger = "Holumbus.Network.PortRegistry.PortRegistryData"
+
+
+
+-- ----------------------------------------------------------------------------
+-- Datatypes
+-- ----------------------------------------------------------------------------
+
+-- | The data needed by the PortRegistry
+data PortRegistryData = PortRegistryData {
+    prd_ServerThreadId :: Thread                             -- ^ The thread-data of the message-dispatcher thread.
+  , prd_OwnStream      :: PortRegistryRequestStream          -- ^ The Stream for all incomming messages.
+  , prd_SocketMap      :: MVar (Map.Map StreamName SocketId) -- ^ The map storing the port-data (the real registry).
+  }
+
+
+-- ----------------------------------------------------------------------------
+-- Creation and Destruction
+-- ----------------------------------------------------------------------------
+
+
+-- | Creates a new PortRegistry.
+newPortRegistryData :: StreamName -> Maybe PortNumber -> IO PortRegistryData
+newPortRegistryData sn pn
+  = do
+    st      <- (newStream STLocal (Just sn) pn)::IO PortRegistryRequestStream
+    mMVar   <- newMVar Map.empty
+    sMVar   <- newThread            
+    let prd = PortRegistryData sMVar st mMVar
+    startRequestDispatcher sMVar st (dispatch prd)
+    return prd
+
+
+-- | Closes the PortRegistry with its streams and threads.
+closePortRegistryData :: PortRegistryData -> IO ()
+closePortRegistryData prd
+  = do
+    stopRequestDispatcher (prd_ServerThreadId prd)
+    closeStream (prd_OwnStream prd)
+    return ()
+
+
+-- | Get the RequestPort of the PortRegistry.
+--   It can be used to give access to the PortRegistry, eg. you can serialize
+--   this information and transfer it over the network to grant access to the
+--   clients.
+getPortRegistryRequestPort :: PortRegistryData -> IO PortRegistryRequestPort
+getPortRegistryRequestPort prd = newPortFromStream (prd_OwnStream prd)
+
+
+-- | The main dispatch-function. It handles the incomming messages and reacts.
+dispatch 
+  :: PortRegistryData 
+  -> PortRegistryRequestMessage 
+  -> PortRegistryResponsePort
+  -> IO ()
+dispatch prd msg replyPort
+  = do
+    case msg of
+      (PRReqRegister sn soid) ->
+        do
+        handleRequest replyPort (registerPort sn soid prd) (\_ -> PRRspSuccess)
+        return ()
+      (PRReqUnregister sn) ->      
+        do
+        handleRequest replyPort (unregisterPort sn prd) (\_ -> PRRspSuccess)
+        return ()
+      (PRReqLookup sn) ->
+        do
+        handleRequest replyPort (lookupPort sn prd) (\soid -> PRRspLookup soid)
+        return ()
+      (PRReqGetPorts) ->
+        do
+        handleRequest replyPort (getPorts prd) (\ls -> PRRspGetPorts ls)
+        return ()
+      _ -> 
+        do
+        infoM localLogger $ "dispatch: unknown request " ++ show msg
+        handleRequest replyPort (return ()) (\_ -> PRRspUnknown)
+
+
+
+-- ----------------------------------------------------------------------------
+-- Typeclass instanciation (PortRegistry)
+-- ----------------------------------------------------------------------------
+
+
+-- The PortRegistry-typeclass instanciation for the PortRegistryData.
+instance PortRegistry PortRegistryData where
+  
+  registerPort sn soid prd
+    = do
+      infoM localLogger $ "register: " ++ sn ++ " - at: " ++ show soid 
+      modifyMVar (prd_SocketMap prd) $
+        \sm -> return (Map.insert sn soid sm, ())
+
+  unregisterPort sn prd
+    = do
+      infoM localLogger $ "unregister: " ++ sn
+      modifyMVar (prd_SocketMap prd) $
+        \sm -> return (Map.delete sn sm, ())
+  
+  lookupPort sn prd
+    = do
+      infoM localLogger $ "looking up: " ++ sn
+      soid <- withMVar (prd_SocketMap prd) $
+        \sm -> return (Map.lookup sn sm)
+      infoM localLogger $ "result for: " ++ sn ++ " -> " ++ show soid
+      return soid
+  
+  getPorts prd
+    = do
+      infoM localLogger $ "getting all ports"
+      withMVar (prd_SocketMap prd) $
+        \sm -> return (Map.toList sm)
+      
diff --git a/source/Holumbus/Network/PortRegistry/PortRegistryPort.hs b/source/Holumbus/Network/PortRegistry/PortRegistryPort.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Network/PortRegistry/PortRegistryPort.hs
@@ -0,0 +1,144 @@
+-- ----------------------------------------------------------------------------
+{- |
+  Module     : Holumbus.Network.PortRegistry.PortRegistryPort
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+  
+  This module contains the Interface for external access to the PortRegistry.
+  
+-}
+-- ----------------------------------------------------------------------------
+
+module Holumbus.Network.PortRegistry.PortRegistryPort
+(
+-- * Datatypes
+  PortRegistryPort
+  
+-- * Creation
+, newPortRegistryPort
+, newPortRegistryFromData
+, newPortRegistryFromXmlFile 
+
+-- * reexport
+, setPortRegistry 
+)
+where
+
+import System.Log.Logger
+
+import Holumbus.Common.FileHandling
+import Holumbus.Network.Port
+import Holumbus.Network.Messages
+import Holumbus.Network.PortRegistry
+import Holumbus.Network.PortRegistry.Messages
+
+
+localLogger :: String
+localLogger = "Holumbus.Network.PortRegistry.PortRegistryPort"
+
+
+-- ----------------------------------------------------------------------------
+-- Datatypes
+-- ----------------------------------------------------------------------------
+ 
+-- | The datatype for the PortRegistry remote interface. 
+data PortRegistryPort = PortRegistryPort PortRegistryRequestPort
+  deriving (Show)
+
+
+
+
+-- ----------------------------------------------------------------------------
+--  Creation
+-- ----------------------------------------------------------------------------
+
+
+-- | Creates a new PortRegistryPort from a port-object.
+newPortRegistryPort :: PortRegistryRequestPort -> PortRegistryPort
+newPortRegistryPort p = PortRegistryPort p
+
+
+-- | Creates a new PortRegistryPort from the StreamName and SocketId.
+newPortRegistryFromData :: StreamName -> SocketId -> IO PortRegistryPort
+newPortRegistryFromData sn soid
+  = do
+    p <- newPort sn (Just soid)
+    return $ newPortRegistryPort p
+
+
+-- | Creates a new PortRegistryPort from a XML-File.
+newPortRegistryFromXmlFile :: FilePath -> IO PortRegistryPort
+newPortRegistryFromXmlFile fp
+  = do
+    p <- loadFromXmlFile fp
+    return $ newPortRegistryPort p
+
+
+
+-- ----------------------------------------------------------------------------
+-- Typeclass instanciation for PortRegistryPort
+-- ----------------------------------------------------------------------------
+
+-- PortRegistry-typeclass instanciation for the PortRegistryPort.
+instance PortRegistry PortRegistryPort where
+    
+  registerPort sn soid (PortRegistryPort p)
+    = do
+      debugM localLogger "registerPort start"
+      r <- withStream $
+        \s -> performPortAction p s time30 (PRReqRegister sn soid) $
+          \rsp ->
+          do
+          case rsp of
+            (PRRspSuccess) -> return (Just $ ())
+            _ -> return Nothing
+      debugM localLogger "registerPort end"
+      return r
+
+
+  unregisterPort sn (PortRegistryPort p)
+    = do
+      debugM localLogger "unregisterPort start"
+      r <- withStream $
+        \s -> performPortAction p s time30 (PRReqUnregister sn) $
+          \rsp ->
+          do
+          case rsp of
+            (PRRspSuccess) -> return (Just $ ())
+            _ -> return Nothing
+      debugM localLogger "unregisterPort end"
+      return r
+  
+  lookupPort sn (PortRegistryPort p)
+    = do
+      debugM localLogger "lookupPort start"
+      r <- withStream $
+        \s -> performPortAction p s time30 (PRReqLookup sn) $
+          \rsp ->
+          do
+          case rsp of
+            (PRRspLookup soid) -> return (Just $ soid)
+            _ -> return Nothing
+      debugM localLogger "lookupPort end"
+      return r
+  
+
+  getPorts (PortRegistryPort p)
+    = do
+      debugM localLogger "getPorts start"
+      r <- withStream $
+        \s -> performPortAction p s time30 (PRReqGetPorts) $
+          \rsp ->
+          do
+          case rsp of
+            (PRRspGetPorts ls) -> return (Just $ ls)
+            _ -> return Nothing
+      debugM localLogger "getPorts end"
+      return r
+  
diff --git a/source/Holumbus/Network/Site.hs b/source/Holumbus/Network/Site.hs
new file mode 100644
--- /dev/null
+++ b/source/Holumbus/Network/Site.hs
@@ -0,0 +1,219 @@
+-- ----------------------------------------------------------------------------
+
+{- |
+  Module     : Holumbus.Network.Site
+  Copyright  : Copyright (C) 2008 Stefan Schmidt
+  License    : MIT
+
+  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
+  Stability  : experimental
+  Portability: portable
+  Version    : 0.1
+
+  Just a little Id to help us to decide if two thread are running in the
+  same program or just on the same machine or on differen machines. 
+
+-}
+
+-- ----------------------------------------------------------------------------
+
+module Holumbus.Network.Site
+(
+-- * Datatypes
+  SiteId
+, SiteMap
+  
+-- * Operations on the SiteId
+, getSiteId
+, getSiteHost
+, getSiteProcess
+, isSameHost
+, isSameProcess
+, nearestId
+
+-- * Operations on the SiteMap
+, emptySiteMap
+, addIdToMap
+, deleteIdFromMap
+, deleteHostFromMap
+, isSiteIdMember
+, getNeighbourSiteIds
+)
+where
+
+import           Data.Binary
+import qualified Data.List as List
+import           Network.Socket
+import           System.Posix
+
+import           Text.XML.HXT.Arrow
+
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+
+
+
+
+-- ----------------------------------------------------------------------------
+-- Datatypes
+-- ----------------------------------------------------------------------------
+
+
+-- | The datatype of the SiteId, it contains the hostname and a processid,
+--   so it is possible to decide if two site ids belong to the same process
+--   or the the same computer or are on distinct computers.
+data SiteId = SiteId HostName ProcessID deriving (Show, Eq, Ord)
+
+instance Binary SiteId where
+  put (SiteId hn pid) = put hn >> put (toInteger pid)
+  get
+    = do
+      hn <- get
+      pid <- get
+      return (SiteId hn (fromInteger pid)) 
+
+instance XmlPickler SiteId where
+  xpickle = xpSiteId
+  
+xpSiteId :: PU SiteId
+xpSiteId = 
+  xpElem "siteId" $
+      xpWrap (\(hn, pid) -> SiteId hn (fromInteger pid), \(SiteId hn pid) -> (hn, toInteger pid)) xpSite
+      where
+      xpSite =
+        xpPair
+          (xpElem "hostname" xpText)
+          (xpElem "pid" xpickle)
+
+
+-- | Just a little Map to hold the SiteIds an to get the neighbout Ids.
+type SiteMap = Map.Map HostName (Set.Set SiteId)
+
+
+
+
+-- ----------------------------------------------------------------------------
+-- Operations on the SiteId
+-- ----------------------------------------------------------------------------
+
+
+-- | Little helper function.
+getHostName :: IO (HostName)
+getHostName
+  = do
+    (hn, _) <- getNameInfo [] True False (SockAddrUnix "localhost")
+    return (maybe "localhost" id hn)
+    
+
+-- | Gets the SiteId for the calling program. 
+getSiteId :: IO (SiteId)
+getSiteId
+  = do
+    hn <- getHostName
+    pid <- getProcessID
+    return (SiteId hn pid)
+
+       
+-- | Extracts the Hostname from the SiteId.
+getSiteHost :: SiteId -> HostName
+getSiteHost (SiteId hn _) = hn
+
+
+-- | Extracts the ProcessID from the SiteId.
+getSiteProcess :: SiteId -> ProcessID
+getSiteProcess (SiteId _ pid) = pid
+
+
+-- | Test, if the two Ids are located on the same host.
+isSameHost :: SiteId -> SiteId -> Bool
+isSameHost (SiteId hn1 _) (SiteId hn2 _) = hn1 == hn2
+
+
+-- | Test, if the two Ids are located on the same host an in the same process.
+isSameProcess :: SiteId -> SiteId -> Bool
+isSameProcess = (==)
+
+
+-- | The filtering function.
+--   Splits the given Id-list into three sublists:
+--   the Ids from the same process,
+--   the Ids from the same computer,
+--   all other Ids.
+--   This is some sort of distance function, a simple one, but for now it
+--   should do its work.
+filterSiteIds :: SiteId -> [SiteId] -> ([SiteId],[SiteId],[SiteId])
+filterSiteIds _ [] = ([],[],[])
+filterSiteIds i ls
+  = (same, local, other)
+  where
+    (same, temp) = List.partition (\s -> isSameProcess i s) ls
+    (local, other) = List.partition (\s -> isSameHost i s) temp
+
+
+-- | Gets the nearest item from an Id-list compared to a given Id.
+nearestId :: SiteId -> [SiteId] -> Maybe SiteId
+nearestId s l = nearestId' $ filterSiteIds s l
+  where
+  nearestId' ([],  [],  [])  = Nothing
+  nearestId' ([],  [],  x:_) = Just x
+  nearestId' ([],  x:_, _)   = Just x
+  nearestId' (x:_, _,   _)   = Just x
+  
+  
+  
+  
+-- ----------------------------------------------------------------------------
+-- Operations on the SiteMap
+-- ----------------------------------------------------------------------------
+
+-- | Empty SiteId-Map.
+emptySiteMap :: SiteMap
+emptySiteMap = Map.empty
+
+
+-- | Adds an id to the map.
+addIdToMap :: SiteId -> SiteMap -> SiteMap
+addIdToMap i m 
+  = Map.alter f hn m
+    where
+      hn = getSiteHost i
+      f Nothing = (Just $ Set.singleton i)
+      f (Just s) = (Just $ Set.insert i s)
+
+
+-- | Deletes an id from the map.
+deleteIdFromMap :: SiteId -> SiteMap -> SiteMap
+deleteIdFromMap i m
+  = Map.alter f hn m
+    where
+      hn = getSiteHost i
+      f Nothing = Nothing
+      f (Just s) = filterEmpty $ Set.delete i s
+      filterEmpty s
+        | s == Set.empty = Nothing
+        | otherwise = Just s
+
+
+-- | Delete a hostname an all its ids from the map.
+deleteHostFromMap :: HostName -> SiteMap -> SiteMap
+deleteHostFromMap hn m
+  = Map.alter f hn m
+    where
+      f _ = Nothing
+
+
+-- | Test, if the site id is already in the list.
+isSiteIdMember :: SiteId -> SiteMap -> Bool 
+isSiteIdMember i m
+  = maybe False (\s -> Set.member i s) (Map.lookup hn m) 
+    where
+      hn = getSiteHost i
+
+
+-- | Gets all ids which are on the same host, but not
+--   the original siteid itself.
+getNeighbourSiteIds :: SiteId -> SiteMap -> Set.Set SiteId
+getNeighbourSiteIds i m
+  = maybe (Set.empty) (\s -> Set.delete i s) (Map.lookup hn m) 
+    where
+      hn = getSiteHost i
