diff options
-rw-r--r-- | xmppServer.hs | 63 |
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) | |||
27 | import Data.Monoid ( (<>) ) | 27 | import Data.Monoid ( (<>) ) |
28 | import Data.Text (Text) | 28 | import Data.Text (Text) |
29 | import qualified Data.Text as Text (pack) | 29 | import qualified Data.Text as Text (pack) |
30 | import qualified Data.Map as Map | ||
30 | 31 | ||
31 | import qualified Control.Concurrent.STM.UpdateStream as Slotted | 32 | import qualified Control.Concurrent.STM.UpdateStream as Slotted |
32 | import ControlMaybe | 33 | import ControlMaybe |
33 | import Nesting | 34 | import Nesting |
34 | import EventUtil | 35 | import EventUtil |
35 | import Server | 36 | import Server |
37 | import Data.Time.Clock (UTCTime,getCurrentTime) | ||
36 | 38 | ||
37 | addrToText :: SockAddr -> Text | 39 | addrToText :: SockAddr -> Text |
38 | addrToText (addr@(SockAddrInet _ _)) = Text.pack $ stripColon (show addr) | 40 | addrToText (addr@(SockAddrInet _ _)) = Text.pack $ stripColon (show addr) |
@@ -289,21 +291,63 @@ forkConnection k pingflag src snk stanzas = do | |||
289 | monitor sv params = do | 291 | monitor 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 | ||
371 | data Peer = Peer | ||
372 | { peerWanted :: TVar Bool -- ^ False when this peer is on a you-call-me basis | ||
373 | , peerState :: TVar PeerState | ||
374 | } | ||
375 | data PeerState | ||
376 | = PeerPendingConnect UTCTime | ||
377 | | PeerPendingAccept UTCTime | ||
378 | | PeerConnected (TChan Stanza) | ||
379 | |||
327 | peerKey (sock,addr) = do | 380 | peerKey (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) |