diff options
-rw-r--r-- | Presence/ServerC.hs | 7 | ||||
-rw-r--r-- | Presence/XMPP.hs | 36 | ||||
-rw-r--r-- | Presence/XMPPServer.hs | 69 | ||||
-rw-r--r-- | Presence/XMPPTypes.hs | 84 | ||||
-rw-r--r-- | Presence/main.hs | 4 |
5 files changed, 133 insertions, 67 deletions
diff --git a/Presence/ServerC.hs b/Presence/ServerC.hs index 3933c812..36e2d7bf 100644 --- a/Presence/ServerC.hs +++ b/Presence/ServerC.hs | |||
@@ -7,6 +7,7 @@ module ServerC | |||
7 | , ConnId(..) | 7 | , ConnId(..) |
8 | , ServerHandle | 8 | , ServerHandle |
9 | , quitListening | 9 | , quitListening |
10 | , dummyServerHandle | ||
10 | ) where | 11 | ) where |
11 | 12 | ||
12 | import Network.Socket as Socket | 13 | import Network.Socket as Socket |
@@ -39,6 +40,7 @@ import Control.Monad.Trans.Class (lift) | |||
39 | import Control.Monad.IO.Class (MonadIO (liftIO)) | 40 | import Control.Monad.IO.Class (MonadIO (liftIO)) |
40 | import qualified Data.ByteString as S (ByteString) | 41 | import qualified Data.ByteString as S (ByteString) |
41 | import System.IO (Handle) | 42 | import System.IO (Handle) |
43 | import Control.Concurrent.MVar (newMVar) | ||
42 | 44 | ||
43 | import ByteStringOperators | 45 | import ByteStringOperators |
44 | import SocketLike | 46 | import SocketLike |
@@ -50,6 +52,11 @@ newtype ConnId = ConnId Int | |||
50 | 52 | ||
51 | newtype ServerHandle = ServerHandle Socket | 53 | newtype ServerHandle = ServerHandle Socket |
52 | 54 | ||
55 | dummyServerHandle = do | ||
56 | mvar <- newMVar Closed | ||
57 | let sock = MkSocket 0 AF_UNSPEC NoSocketType 0 mvar | ||
58 | return (ServerHandle sock) | ||
59 | |||
53 | quitListening :: ServerHandle -> IO () | 60 | quitListening :: ServerHandle -> IO () |
54 | quitListening (ServerHandle socket) = sClose socket | 61 | quitListening (ServerHandle socket) = sClose socket |
55 | 62 | ||
diff --git a/Presence/XMPP.hs b/Presence/XMPP.hs new file mode 100644 index 00000000..f361641e --- /dev/null +++ b/Presence/XMPP.hs | |||
@@ -0,0 +1,36 @@ | |||
1 | {-# LANGUAGE FlexibleContexts #-} | ||
2 | module XMPP | ||
3 | ( module XMPP | ||
4 | , module XMPPTypes | ||
5 | , quitListening | ||
6 | ) where | ||
7 | |||
8 | import ServerC | ||
9 | import XMPPTypes | ||
10 | |||
11 | import Data.HList | ||
12 | import Network.Socket (Family) | ||
13 | import Network.BSD (PortNumber) | ||
14 | import Control.Concurrent.STM | ||
15 | |||
16 | listenForXmppClients | ||
17 | :: (HList t1, HExtend e l (HCons PortNumber t1), XMPPSession t) => | ||
18 | Family -> XMPPClass t -> e -> l -> IO ServerHandle | ||
19 | listenForXmppClients addr_family session_factory port st = do | ||
20 | putStrLn "unimplemented: listenForXmppClients" | ||
21 | dummyServerHandle | ||
22 | -- TODO | ||
23 | |||
24 | listenForRemotePeers | ||
25 | :: (HList t1, HExtend e l (HCons PortNumber t1), XMPPSession t) => | ||
26 | Family -> XMPPClass t -> e -> l -> IO ServerHandle | ||
27 | listenForRemotePeers addrfamily session_factory port st = do | ||
28 | putStrLn "unimplemented: listenForRemotePeers" | ||
29 | dummyServerHandle | ||
30 | -- TODO | ||
31 | |||
32 | seekRemotePeers :: XMPPConfig config => | ||
33 | config -> TChan Presence -> IO () | ||
34 | seekRemotePeers config chan = do | ||
35 | putStrLn "unimplemented: seekRemotePeers" | ||
36 | return () | ||
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs index e8ab5490..813c7c7b 100644 --- a/Presence/XMPPServer.hs +++ b/Presence/XMPPServer.hs | |||
@@ -6,6 +6,7 @@ | |||
6 | -- {-# LANGUAGE GADTs #-} | 6 | -- {-# LANGUAGE GADTs #-} |
7 | module XMPPServer | 7 | module XMPPServer |
8 | ( module XMPPServer | 8 | ( module XMPPServer |
9 | , module XMPPTypes | ||
9 | , quitListening | 10 | , quitListening |
10 | ) where | 11 | ) where |
11 | 12 | ||
@@ -58,39 +59,13 @@ import Control.Concurrent.STM | |||
58 | import Control.Concurrent | 59 | import Control.Concurrent |
59 | import Control.Exception as Exception | 60 | import Control.Exception as Exception |
60 | import Text.Show.ByteString as L | 61 | import Text.Show.ByteString as L |
61 | import Data.Binary.Builder as B | ||
62 | import Data.Binary.Put | ||
63 | import qualified Data.Map as Map | 62 | import qualified Data.Map as Map |
64 | import GHC.Conc | 63 | import GHC.Conc |
65 | import Network.BSD hiding (getHostByAddr) | 64 | import Network.BSD hiding (getHostByAddr) |
66 | import Control.Concurrent.Async | 65 | import Control.Concurrent.Async |
67 | import qualified Data.Set as Set | 66 | import qualified Data.Set as Set |
68 | import GetHostByAddr | 67 | import GetHostByAddr |
69 | 68 | import XMPPTypes | |
70 | data Peer = LocalHost | RemotePeer SockAddr | ||
71 | deriving (Eq,Prelude.Show) | ||
72 | |||
73 | instance Ord Peer where | ||
74 | LocalHost <= _ | ||
75 | = True | ||
76 | RemotePeer (SockAddrUnix a) <= RemotePeer (SockAddrUnix b) | ||
77 | = a <= b | ||
78 | RemotePeer (SockAddrUnix _) <= _ | ||
79 | = True | ||
80 | RemotePeer (SockAddrInet aport a) <= RemotePeer (SockAddrInet bport b) | ||
81 | = (a,aport) <= (b,bport) | ||
82 | RemotePeer (SockAddrInet aport a) <= _ | ||
83 | = True | ||
84 | RemotePeer (SockAddrInet6 aport aflow a ascope) <= RemotePeer (SockAddrInet6 bport bflow b bscope) | ||
85 | = (a,aport,ascope,aflow) <= (b,bport,bscope,bflow) | ||
86 | a <= b = False | ||
87 | |||
88 | -- | Jabber ID (JID) datatype | ||
89 | data JID = JID { name :: Maybe ByteString | ||
90 | , peer :: Peer | ||
91 | , resource :: Maybe ByteString | ||
92 | } | ||
93 | deriving (Eq,Ord) | ||
94 | 69 | ||
95 | is_remote (RemotePeer _) = True | 70 | is_remote (RemotePeer _) = True |
96 | is_remote _ = False | 71 | is_remote _ = False |
@@ -110,37 +85,10 @@ getNamesForPeer peer@(RemotePeer addr) = do | |||
110 | return . map pack $ names | 85 | return . map pack $ names |
111 | 86 | ||
112 | 87 | ||
113 | showPeer :: Peer -> ByteString | ||
114 | showPeer LocalHost = "localhost" | ||
115 | showPeer (RemotePeer addr@(SockAddrInet _ _)) = pack $ stripColon (Prelude.show addr) | ||
116 | where stripColon s = pre where (pre,port) = break (==':') s | ||
117 | showPeer (RemotePeer addr@(SockAddrInet6 _ _ _ _)) = pack $ stripColon (Prelude.show addr) | ||
118 | where stripColon s = if null bracket then pre else pre ++ "]" | ||
119 | where | ||
120 | (pre,bracket) = break (==']') s | ||
121 | |||
122 | peerAddr :: Peer -> SockAddr | 88 | peerAddr :: Peer -> SockAddr |
123 | peerAddr (RemotePeer addr) = addr | 89 | peerAddr (RemotePeer addr) = addr |
124 | -- peerAddr LocalHost = throw exception | 90 | -- peerAddr LocalHost = throw exception |
125 | 91 | ||
126 | instance L.Show JID where | ||
127 | showp (JID n s r ) = putBuilder . B.fromLazyByteString $ n <$++> "@" <?++> showPeer s <++?> "/" <++$> r | ||
128 | |||
129 | instance Prelude.Show JID where | ||
130 | show jid = L.unpack $ L.show jid | ||
131 | |||
132 | instance NFData JID where | ||
133 | rnf v@(JID n s r) = n `seq` s `seq` r `seq` () | ||
134 | |||
135 | jid user host rsrc = JID (Just user) host (Just rsrc) | ||
136 | |||
137 | data JabberShow = Offline | ||
138 | | Away | ||
139 | | Available | ||
140 | deriving (Prelude.Show,Enum,Ord,Eq,Read) | ||
141 | |||
142 | data Presence = Presence JID JabberShow | ||
143 | deriving Prelude.Show | ||
144 | 92 | ||
145 | xmlifyPresenceForPeer sock (Presence jid stat) = do | 93 | xmlifyPresenceForPeer sock (Presence jid stat) = do |
146 | -- TODO: accept socket argument and determine local ip address | 94 | -- TODO: accept socket argument and determine local ip address |
@@ -184,19 +132,6 @@ instance NFData Presence where | |||
184 | rnf (Presence jid stat) = rnf jid `seq` stat `seq` () | 132 | rnf (Presence jid stat) = rnf jid `seq` stat `seq` () |
185 | 133 | ||
186 | 134 | ||
187 | class XMPPSession session where | ||
188 | data XMPPClass session | ||
189 | newSession :: XMPPClass session -> Socket -> Handle -> IO session | ||
190 | setResource :: session -> ByteString -> IO () | ||
191 | getJID :: session -> IO JID | ||
192 | closeSession :: session -> IO () | ||
193 | subscribe :: session -> Maybe JID -> IO (TChan Presence) | ||
194 | announcePresence :: session -> Presence -> IO () | ||
195 | |||
196 | class XMPPConfig config where | ||
197 | getBuddies :: config -> ByteString -> IO [ByteString] | ||
198 | getSubscribers :: config -> ByteString -> IO [ByteString] | ||
199 | |||
200 | greet host = L.unlines | 135 | greet host = L.unlines |
201 | [ "<?xml version='1.0'?>" | 136 | [ "<?xml version='1.0'?>" |
202 | , "<stream:stream" | 137 | , "<stream:stream" |
diff --git a/Presence/XMPPTypes.hs b/Presence/XMPPTypes.hs new file mode 100644 index 00000000..eb5d349e --- /dev/null +++ b/Presence/XMPPTypes.hs | |||
@@ -0,0 +1,84 @@ | |||
1 | {-# LANGUAGE OverloadedStrings #-} | ||
2 | {-# LANGUAGE TypeFamilies #-} | ||
3 | module XMPPTypes where | ||
4 | |||
5 | import Network.Socket (Socket,SockAddr(..)) | ||
6 | import System.IO (Handle) | ||
7 | import Control.Concurrent.STM (TChan) | ||
8 | import Data.ByteString.Lazy.Char8 as L (ByteString,unpack,pack) | ||
9 | import Text.Show.ByteString as L | ||
10 | import Data.Binary.Builder as B | ||
11 | import Data.Binary.Put | ||
12 | import Control.DeepSeq | ||
13 | import ByteStringOperators | ||
14 | |||
15 | class XMPPSession session where | ||
16 | data XMPPClass session | ||
17 | newSession :: XMPPClass session -> Socket -> Handle -> IO session | ||
18 | setResource :: session -> ByteString -> IO () | ||
19 | getJID :: session -> IO JID | ||
20 | closeSession :: session -> IO () | ||
21 | subscribe :: session -> Maybe JID -> IO (TChan Presence) | ||
22 | announcePresence :: session -> Presence -> IO () | ||
23 | |||
24 | class XMPPConfig config where | ||
25 | getBuddies :: config -> ByteString -> IO [ByteString] | ||
26 | getSubscribers :: config -> ByteString -> IO [ByteString] | ||
27 | |||
28 | -- | Jabber ID (JID) datatype | ||
29 | data JID = JID { name :: Maybe ByteString | ||
30 | , peer :: Peer | ||
31 | , resource :: Maybe ByteString | ||
32 | } | ||
33 | deriving (Eq,Ord) | ||
34 | |||
35 | data JabberShow = Offline | ||
36 | | Away | ||
37 | | Available | ||
38 | deriving (Prelude.Show,Enum,Ord,Eq,Read) | ||
39 | |||
40 | data Presence = Presence JID JabberShow | ||
41 | deriving Prelude.Show | ||
42 | |||
43 | data Peer = LocalHost | RemotePeer SockAddr | ||
44 | deriving (Eq,Prelude.Show) | ||
45 | |||
46 | |||
47 | |||
48 | instance Ord Peer where | ||
49 | LocalHost <= _ | ||
50 | = True | ||
51 | RemotePeer (SockAddrUnix a) <= RemotePeer (SockAddrUnix b) | ||
52 | = a <= b | ||
53 | RemotePeer (SockAddrUnix _) <= _ | ||
54 | = True | ||
55 | RemotePeer (SockAddrInet aport a) <= RemotePeer (SockAddrInet bport b) | ||
56 | = (a,aport) <= (b,bport) | ||
57 | RemotePeer (SockAddrInet aport a) <= _ | ||
58 | = True | ||
59 | RemotePeer (SockAddrInet6 aport aflow a ascope) <= RemotePeer (SockAddrInet6 bport bflow b bscope) | ||
60 | = (a,aport,ascope,aflow) <= (b,bport,bscope,bflow) | ||
61 | a <= b = False | ||
62 | |||
63 | instance L.Show JID where | ||
64 | showp (JID n s r ) = putBuilder . B.fromLazyByteString $ n <$++> "@" <?++> showPeer s <++?> "/" <++$> r | ||
65 | |||
66 | instance Prelude.Show JID where | ||
67 | show jid = L.unpack $ L.show jid | ||
68 | |||
69 | instance NFData JID where | ||
70 | rnf v@(JID n s r) = n `seq` s `seq` r `seq` () | ||
71 | |||
72 | jid user host rsrc = JID (Just user) host (Just rsrc) | ||
73 | |||
74 | |||
75 | showPeer :: Peer -> ByteString | ||
76 | showPeer LocalHost = "localhost" | ||
77 | showPeer (RemotePeer addr@(SockAddrInet _ _)) = pack $ stripColon (Prelude.show addr) | ||
78 | where stripColon s = pre where (pre,port) = break (==':') s | ||
79 | showPeer (RemotePeer addr@(SockAddrInet6 _ _ _ _)) = pack $ stripColon (Prelude.show addr) | ||
80 | where stripColon s = if null bracket then pre else pre ++ "]" | ||
81 | where | ||
82 | (pre,bracket) = break (==']') s | ||
83 | |||
84 | |||
diff --git a/Presence/main.hs b/Presence/main.hs index a0a80569..403a6ac7 100644 --- a/Presence/main.hs +++ b/Presence/main.hs | |||
@@ -25,7 +25,11 @@ import UTmp | |||
25 | -- | 25 | -- |
26 | #endif | 26 | #endif |
27 | import FGConsole | 27 | import FGConsole |
28 | #ifdef HAXML | ||
28 | import XMPPServer | 29 | import XMPPServer |
30 | #else | ||
31 | import XMPP | ||
32 | #endif | ||
29 | import Data.HList | 33 | import Data.HList |
30 | import Control.Exception | 34 | import Control.Exception |
31 | import LocalPeerCred | 35 | import LocalPeerCred |