diff options
-rw-r--r-- | Presence/XMPP.hs | 101 | ||||
-rw-r--r-- | Presence/XMPPServer.hs | 4 | ||||
-rw-r--r-- | Presence/XMPPTypes.hs | 3 | ||||
-rw-r--r-- | Presence/main.hs | 2 |
4 files changed, 99 insertions, 11 deletions
diff --git a/Presence/XMPP.hs b/Presence/XMPP.hs index e158eea2..248d1ffb 100644 --- a/Presence/XMPP.hs +++ b/Presence/XMPP.hs | |||
@@ -1,4 +1,5 @@ | |||
1 | {-# LANGUAGE FlexibleContexts #-} | 1 | {-# LANGUAGE OverloadedStrings #-} |
2 | {-# LANGUAGE FlexibleContexts #-} | ||
2 | module XMPP | 3 | module XMPP |
3 | ( module XMPPTypes | 4 | ( module XMPPTypes |
4 | , listenForXmppClients | 5 | , listenForXmppClients |
@@ -9,19 +10,105 @@ module XMPP | |||
9 | 10 | ||
10 | import ServerC | 11 | import ServerC |
11 | import XMPPTypes | 12 | import XMPPTypes |
13 | import SocketLike | ||
14 | import ByteStringOperators | ||
12 | 15 | ||
13 | import Data.HList | 16 | import Data.HList |
14 | import Network.Socket (Family) | 17 | import Network.Socket (Family) |
15 | import Network.BSD (PortNumber) | 18 | import Network.BSD (PortNumber) |
16 | import Control.Concurrent.STM | 19 | import Control.Concurrent.STM |
20 | import Data.Conduit | ||
21 | import qualified Data.Conduit.List as CL | ||
22 | import Data.ByteString (ByteString) | ||
23 | import qualified Data.ByteString.Lazy.Char8 as L | ||
24 | ( putStrLn | ||
25 | ) | ||
26 | import Control.Concurrent (forkIO,killThread) | ||
27 | import Control.Exception (handle,SomeException(..),finally) | ||
28 | import Control.Monad.IO.Class | ||
29 | import Control.Monad.Trans.Maybe | ||
30 | import Todo | ||
31 | import Control.Monad as Monad | ||
32 | import Text.XML.Stream.Parse | ||
17 | 33 | ||
18 | listenForXmppClients | 34 | data Commands x = Send [x] | QuitThread |
19 | :: (HList t1, HExtend e l (HCons PortNumber t1), XMPPSession t) => | 35 | deriving Prelude.Show |
20 | Family -> XMPPClass t -> e -> l -> IO ServerHandle | 36 | |
37 | xmlifyPresenceForClient :: Presence -> IO [x] | ||
38 | xmlifyPresenceForClient presence = todo | ||
39 | |||
40 | handleClient | ||
41 | :: (SocketLike sock, HHead l (XMPPClass session), | ||
42 | XMPPSession session) => | ||
43 | HCons sock (HCons t l) -> Source IO ByteString -> Sink ByteString IO () -> IO () | ||
44 | handleClient st src snk = do | ||
45 | let HCons sock (HCons _ st') = st | ||
46 | session_factory = hHead st' | ||
47 | pname <- getPeerName sock | ||
48 | session <- newSession session_factory sock | ||
49 | Prelude.putStrLn $ "PEER NAME: "++Prelude.show pname | ||
50 | pchan <- subscribe session Nothing | ||
51 | cmdChan <- atomically newTChan | ||
52 | |||
53 | |||
54 | {- | ||
55 | reader <- forkIO $ do | ||
56 | flip ($$) snk $ | ||
57 | handle (\(SomeException e) -> liftIO (L.putStrLn $ "quit reader via exception: "<++>bshow e) >> return ()) $ | ||
58 | fix $ \loop -> do | ||
59 | event <- liftIO . atomically $ | ||
60 | (fmap Left $ readTChan pchan) | ||
61 | `orElse` | ||
62 | (fmap Right $ readTChan cmdChan) | ||
63 | case event of | ||
64 | Left presence -> do | ||
65 | liftIO (L.putStrLn $ "PRESENCE: " <++> bshow presence) | ||
66 | -- TODO: it violates spec to send presence information before | ||
67 | -- a resource is bound. | ||
68 | -- r <- xmlifyPresenceForClient presence | ||
69 | -- yield r | ||
70 | -- -- hPutStrLn h r | ||
71 | -- liftIO (L.putStrLn $ "\nOUT client:\n" <++> r) | ||
72 | Right (Send r) -> | ||
73 | mapM_ yield r | ||
74 | -- yield r | ||
75 | -- -- hPutStrLn h r | ||
76 | loop | ||
77 | -} | ||
78 | let outgoing = do | ||
79 | event <- liftIO . atomically $ | ||
80 | (fmap Left $ readTChan pchan) | ||
81 | `orElse` | ||
82 | (fmap Right $ readTChan cmdChan) | ||
83 | case event of | ||
84 | Right QuitThread -> return () | ||
85 | Left presence -> do | ||
86 | xs <- liftIO $ xmlifyPresenceForClient presence | ||
87 | Monad.mapM_ yield xs | ||
88 | outgoing | ||
89 | |||
90 | incomming = do | ||
91 | mb <- await | ||
92 | maybe (return ()) | ||
93 | (\packet -> do | ||
94 | liftIO (L.putStrLn $ "client-in: " <++> bshow packet) | ||
95 | incomming) | ||
96 | mb | ||
97 | |||
98 | sendingThread <- forkIO (outgoing $$ snk) | ||
99 | let quit = do | ||
100 | atomically $ writeTChan cmdChan QuitThread | ||
101 | closeSession session | ||
102 | -- killThread sendingThread | ||
103 | finally ( src $= parseBytes def $$ incomming ) | ||
104 | quit | ||
105 | |||
106 | listenForXmppClients :: | ||
107 | (HList l, HHead l (XMPPClass session), HExtend e1 l2 l1, | ||
108 | HExtend e l1 (HCons PortNumber l), XMPPSession session) => | ||
109 | Family -> e1 -> e -> l2 -> IO ServerHandle | ||
21 | listenForXmppClients addr_family session_factory port st = do | 110 | listenForXmppClients addr_family session_factory port st = do |
22 | putStrLn "unimplemented: listenForXmppClients" | 111 | doServer (addr_family .*. port .*. session_factory .*. st) handleClient |
23 | dummyServerHandle | ||
24 | -- TODO | ||
25 | 112 | ||
26 | listenForRemotePeers | 113 | listenForRemotePeers |
27 | :: (HList t1, HExtend e l (HCons PortNumber t1), XMPPSession t) => | 114 | :: (HList t1, HExtend e l (HCons PortNumber t1), XMPPSession t) => |
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs index 813c7c7b..f607989d 100644 --- a/Presence/XMPPServer.hs +++ b/Presence/XMPPServer.hs | |||
@@ -160,7 +160,7 @@ startCon session_factory sock st = do | |||
160 | -- cred <- getLocalPeerCred sock | 160 | -- cred <- getLocalPeerCred sock |
161 | -- Prelude.putStrLn $ "PEER CRED: "++Prelude.show cred | 161 | -- Prelude.putStrLn $ "PEER CRED: "++Prelude.show cred |
162 | pname <- getPeerName sock | 162 | pname <- getPeerName sock |
163 | session <- newSession session_factory sock h | 163 | session <- newSession session_factory sock |
164 | Prelude.putStrLn $ "PEER NAME: "++Prelude.show pname | 164 | Prelude.putStrLn $ "PEER NAME: "++Prelude.show pname |
165 | pchan <- subscribe session Nothing | 165 | pchan <- subscribe session Nothing |
166 | cmdChan <- atomically newTChan | 166 | cmdChan <- atomically newTChan |
@@ -418,7 +418,7 @@ startPeer session_factory sock st = do | |||
418 | name <- fmap bshow $ getPeerName sock | 418 | name <- fmap bshow $ getPeerName sock |
419 | L.putStrLn $ "IN peer: connected " <++> name | 419 | L.putStrLn $ "IN peer: connected " <++> name |
420 | jids <- newTVarIO Set.empty | 420 | jids <- newTVarIO Set.empty |
421 | session <- newSession session_factory sock h | 421 | session <- newSession session_factory sock |
422 | let quit = do | 422 | let quit = do |
423 | L.putStrLn $ "IN peer: disconnected " <++> name | 423 | L.putStrLn $ "IN peer: disconnected " <++> name |
424 | js <- fmap Set.toList (readTVarIO jids) | 424 | js <- fmap Set.toList (readTVarIO jids) |
diff --git a/Presence/XMPPTypes.hs b/Presence/XMPPTypes.hs index eb5d349e..e3bbfd16 100644 --- a/Presence/XMPPTypes.hs +++ b/Presence/XMPPTypes.hs | |||
@@ -11,10 +11,11 @@ import Data.Binary.Builder as B | |||
11 | import Data.Binary.Put | 11 | import Data.Binary.Put |
12 | import Control.DeepSeq | 12 | import Control.DeepSeq |
13 | import ByteStringOperators | 13 | import ByteStringOperators |
14 | import SocketLike | ||
14 | 15 | ||
15 | class XMPPSession session where | 16 | class XMPPSession session where |
16 | data XMPPClass session | 17 | data XMPPClass session |
17 | newSession :: XMPPClass session -> Socket -> Handle -> IO session | 18 | newSession :: SocketLike sock => XMPPClass session -> sock -> IO session |
18 | setResource :: session -> ByteString -> IO () | 19 | setResource :: session -> ByteString -> IO () |
19 | getJID :: session -> IO JID | 20 | getJID :: session -> IO JID |
20 | closeSession :: session -> IO () | 21 | closeSession :: session -> IO () |
diff --git a/Presence/main.hs b/Presence/main.hs index 403a6ac7..9a09b855 100644 --- a/Presence/main.hs +++ b/Presence/main.hs | |||
@@ -63,7 +63,7 @@ data UnixSession = UnixSession { | |||
63 | 63 | ||
64 | instance XMPPSession UnixSession where | 64 | instance XMPPSession UnixSession where |
65 | data XMPPClass UnixSession = UnixSessions PresenceState | 65 | data XMPPClass UnixSession = UnixSessions PresenceState |
66 | newSession (UnixSessions state) sock handle = do | 66 | newSession (UnixSessions state) sock = do |
67 | muid <- getLocalPeerCred sock | 67 | muid <- getLocalPeerCred sock |
68 | L.putStrLn $ "SESSION: open " <++> bshow muid | 68 | L.putStrLn $ "SESSION: open " <++> bshow muid |
69 | uid_ref <- newIORef muid | 69 | uid_ref <- newIORef muid |