websockets 0.5.1.1 → 0.5.2.0
raw patch · 2 files changed
+71/−1 lines, 2 files
Files
+ src/Network/WebSockets/Util/PubSub.hs view
@@ -0,0 +1,69 @@+-- | This is a simple utility module to implement a publish-subscribe pattern.+-- Note that this only allows communication in a single direction: pusing data+-- from the server to connected clients (browsers).+--+-- Usage:+--+-- * Create a new 'PubSub' handle using 'newPubSub'+--+-- * Subscribe your clients using the 'subscribe' call+--+-- * Push new updates from the server using the 'publish' call+--+{-# LANGUAGE Rank2Types #-}+module Network.WebSockets.Util.PubSub+ ( PubSub+ , newPubSub+ , publish+ , subscribe+ ) where++import Control.Applicative ((<$>))+import Control.Monad (forM_, forever)+import Control.Monad.Trans (liftIO)+import Data.IntMap (IntMap)+import qualified Control.Concurrent.MVar as MV++import qualified Data.IntMap as IM++import Network.WebSockets++data PubSub_ p = PubSub_+ { pubSubNextId :: Int+ , pubSubSinks :: IntMap (Sink p)+ }++addClient :: Sink p -> PubSub_ p -> (PubSub_ p, Int)+addClient sink (PubSub_ nid sinks) =+ (PubSub_ (nid + 1) (IM.insert nid sink sinks), nid)++removeClient :: Int -> PubSub_ p -> PubSub_ p+removeClient ref ps = ps {pubSubSinks = IM.delete ref (pubSubSinks ps)}++-- | A handle which keeps track of subscribed clients+newtype PubSub p = PubSub (MV.MVar (PubSub_ p))++-- | Create a new 'PubSub' handle, with no clients initally connected+newPubSub :: IO (PubSub p)+newPubSub = PubSub <$> MV.newMVar PubSub_+ { pubSubNextId = 0+ , pubSubSinks = IM.empty+ }++-- | Broadcast a message to all connected clients+publish :: PubSub p -> Message p -> IO ()+publish (PubSub mvar) msg = do+ sinks <- pubSubSinks <$> MV.readMVar mvar + forM_ (IM.toList sinks) $ \(_, s) -> sendSink s msg++-- | Blocks forever+subscribe :: Protocol p => PubSub p -> WebSockets p ()+subscribe (PubSub mvar) = do+ sink <- getSink+ ref <- liftIO $ MV.modifyMVar mvar $ return . addClient sink+ catchWsError loop $ const $ liftIO $+ MV.modifyMVar_ mvar $ return . removeClient ref+ where+ loop = forever $ do+ _ <- receiveDataMessage+ return ()
websockets.cabal view
@@ -1,5 +1,5 @@ Name: websockets-Version: 0.5.1.1+Version: 0.5.2.0 Synopsis: A sensible and clean way to write WebSocket-capable servers in Haskell.@@ -46,6 +46,7 @@ Exposed-modules: Network.WebSockets Network.WebSockets.Internal+ Network.WebSockets.Util.PubSub Other-modules: Network.WebSockets.Handshake