summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xmppServer.hs63
1 files changed, 58 insertions, 5 deletions
diff --git a/xmppServer.hs b/xmppServer.hs
index 40c423aa..4fbb775b 100644
--- a/xmppServer.hs
+++ b/xmppServer.hs
@@ -27,12 +27,14 @@ import Data.Maybe (catMaybes,fromJust)
27import Data.Monoid ( (<>) ) 27import Data.Monoid ( (<>) )
28import Data.Text (Text) 28import Data.Text (Text)
29import qualified Data.Text as Text (pack) 29import qualified Data.Text as Text (pack)
30import qualified Data.Map as Map
30 31
31import qualified Control.Concurrent.STM.UpdateStream as Slotted 32import qualified Control.Concurrent.STM.UpdateStream as Slotted
32import ControlMaybe 33import ControlMaybe
33import Nesting 34import Nesting
34import EventUtil 35import EventUtil
35import Server 36import Server
37import Data.Time.Clock (UTCTime,getCurrentTime)
36 38
37addrToText :: SockAddr -> Text 39addrToText :: SockAddr -> Text
38addrToText (addr@(SockAddrInet _ _)) = Text.pack $ stripColon (show addr) 40addrToText (addr@(SockAddrInet _ _)) = Text.pack $ stripColon (show addr)
@@ -289,21 +291,63 @@ forkConnection k pingflag src snk stanzas = do
289monitor sv params = do 291monitor sv params = do
290 chan <- return $ serverEvent sv 292 chan <- return $ serverEvent sv
291 stanzas <- atomically newTChan 293 stanzas <- atomically newTChan
294 peersVar <- atomically $ newTVar Map.empty
295 let doConnect utc k = do
296 peers <- readTVar peersVar
297 let mb = Map.lookup k peers
298 maybe (do false <- newTVar False
299 pending <- newTVar (PeerPendingConnect utc)
300 let v = Peer { peerWanted = false
301 , peerState = pending }
302 writeTVar (peersVar) $ Map.insert k v peers)
303 (\peer ->
304 writeTVar (peerState peer)
305 $ PeerPendingConnect utc)
306 mb
292 fix $ \loop -> do 307 fix $ \loop -> do
293 action <- atomically $ foldr1 orElse 308 action <- atomically $ foldr1 orElse
294 [ readTChan chan >>= \(k,e) -> return $ do 309 [ readTChan chan >>= \(k,e) -> return $ do
295 case e of 310 case e of
296 Connection pingflag conread conwrite -> do 311 Connection pingflag conread conwrite -> do
297 wlog $ tomsg k "Connection" 312 wlog $ tomsg k "Connection"
298 let (xsrc,xsnk) = xmlStream conread conwrite 313 let (xsrc,xsnk) = xmlStream conread conwrite
299 forkConnection k pingflag xsrc xsnk stanzas 314 outs <- forkConnection k pingflag xsrc xsnk stanzas
300 return () 315 atomically $ do
316 peers <- readTVar peersVar
317 let mb = Map.lookup k peers
318 maybe (do false <- newTVar True -- False -- TODO: should be False
319 connected <- newTVar (PeerConnected outs)
320 let v = Peer { peerWanted = false
321 , peerState = connected }
322 writeTVar (peersVar) $ Map.insert k v peers)
323 (\peer -> do
324 writeTVar (peerWanted peer) True -- TODO REMOVE
325 writeTVar (peerState peer)
326 $ PeerConnected outs)
327 mb
328 return ()
301 ConnectFailure addr -> do 329 ConnectFailure addr -> do
302 wlog $ tomsg k "ConnectFailure" 330 wlog $ tomsg k "ConnectFailure"
331 action <- atomically $ do
332 peers <- readTVar peersVar
333 let mb = Map.lookup k peers
334 maybe (return $ return ())
335 (\peer -> do
336 wanted <- readTVar (peerWanted peer)
337 if wanted then return $ do
338 utc <- getCurrentTime
339 control sv (Connect addr params)
340 wlog $ tomsg k "Retry"
341 atomically $ doConnect utc k
342 else return $ return ())
343 mb
344 action
303 EOF -> wlog $ tomsg k "EOF" 345 EOF -> wlog $ tomsg k "EOF"
304 HalfConnection In -> do 346 HalfConnection In -> do
305 wlog $ tomsg k "ReadOnly" 347 wlog $ tomsg k "ReadOnly"
348 utc <- getCurrentTime
306 control sv (Connect (callBackAddress k) params) 349 control sv (Connect (callBackAddress k) params)
350 atomically $ doConnect utc k
307 HalfConnection Out -> wlog $ tomsg k "WriteOnly" 351 HalfConnection Out -> wlog $ tomsg k "WriteOnly"
308 RequiresPing -> wlog $ tomsg k "RequiresPing" 352 RequiresPing -> wlog $ tomsg k "RequiresPing"
309 _ -> return () 353 _ -> return ()
@@ -324,9 +368,18 @@ data ConnectionKey
324 | ClientKey { localAddress :: SockAddr } 368 | ClientKey { localAddress :: SockAddr }
325 deriving (Show, Ord, Eq) 369 deriving (Show, Ord, Eq)
326 370
371data Peer = Peer
372 { peerWanted :: TVar Bool -- ^ False when this peer is on a you-call-me basis
373 , peerState :: TVar PeerState
374 }
375data PeerState
376 = PeerPendingConnect UTCTime
377 | PeerPendingAccept UTCTime
378 | PeerConnected (TChan Stanza)
379
327peerKey (sock,addr) = do 380peerKey (sock,addr) = do
328 peer <- 381 peer <-
329 sIsBound sock >>= \c -> 382 sIsConnected sock >>= \c ->
330 if c then getPeerName sock -- addr is normally socketName 383 if c then getPeerName sock -- addr is normally socketName
331 else return addr -- Weird hack: addr is would-be peer name 384 else return addr -- Weird hack: addr is would-be peer name
332 return $ PeerKey (peer `withPort` fromIntegral peerport) 385 return $ PeerKey (peer `withPort` fromIntegral peerport)