diff options
author | joe <joe@jerkface.net> | 2014-02-17 09:53:04 -0500 |
---|---|---|
committer | joe <joe@jerkface.net> | 2014-02-17 09:53:04 -0500 |
commit | 24f0f7a50653223ea72c846a56817760a0bd63b9 (patch) | |
tree | fc23e2e6447aaace62f47fe977021e0017c01db3 /xmppServer.hs | |
parent | b17536990b17f646d800be2b014d917c0cd78c26 (diff) |
Get username and tty for jid
Diffstat (limited to 'xmppServer.hs')
-rw-r--r-- | xmppServer.hs | 102 |
1 files changed, 96 insertions, 6 deletions
diff --git a/xmppServer.hs b/xmppServer.hs index 3a16aca5..ec3a618d 100644 --- a/xmppServer.hs +++ b/xmppServer.hs | |||
@@ -13,21 +13,111 @@ import Network.Socket | |||
13 | import Data.Monoid ( (<>) ) | 13 | import Data.Monoid ( (<>) ) |
14 | import qualified Data.Text as Text | 14 | import qualified Data.Text as Text |
15 | import qualified Data.Text.IO as Text | 15 | import qualified Data.Text.IO as Text |
16 | import qualified Data.Text.Encoding as Text | ||
16 | import Control.Monad | 17 | import Control.Monad |
17 | import qualified Network.BSD as BSD | 18 | import qualified Network.BSD as BSD |
19 | import qualified Data.Text as Text | ||
20 | import Data.Text (Text) | ||
21 | import qualified Data.Map as Map | ||
22 | import Data.Map (Map) | ||
23 | import Control.Exception ({-evaluate,-}handle,SomeException(..),bracketOnError,ErrorCall(..)) | ||
24 | import System.Posix.User (getUserEntryForID,userName) | ||
25 | import qualified Data.ByteString.Lazy.Char8 as L | ||
18 | 26 | ||
19 | 27 | import UTmp (ProcessID,users) | |
28 | import LocalPeerCred | ||
20 | import XMPPServer | 29 | import XMPPServer |
21 | import Server | 30 | import Server |
22 | 31 | ||
32 | textHostName = fmap Text.pack BSD.getHostName | ||
33 | |||
34 | localJID user resource = do | ||
35 | hostname <- textHostName | ||
36 | return $ user <> "@" <> hostname <> "/" <> resource | ||
37 | |||
38 | data ClientState = ClientState | ||
39 | { clientResource :: Text | ||
40 | , clientUser :: Text | ||
41 | , clientPid :: Maybe ProcessID | ||
42 | } | ||
43 | |||
44 | data PresenceState = PresenceState | ||
45 | { clients :: TVar (Map ConnectionKey ClientState) | ||
46 | } | ||
47 | |||
48 | getConsolePids :: PresenceState -> IO [(Text,ProcessID)] | ||
49 | getConsolePids state = do -- return [("tty7", 23)] -- todo | ||
50 | us <- UTmp.users | ||
51 | return $ map (\(_,tty,pid)->(lazyByteStringToText tty,pid)) us | ||
52 | |||
53 | lazyByteStringToText = (foldr1 (<>) . map Text.decodeUtf8 . L.toChunks) | ||
54 | |||
55 | identifyTTY' ttypids uid inode = ttypid | ||
56 | where ttypids' = map (\(tty,pid)->(L.fromChunks [Text.encodeUtf8 tty], pid)) ttypids | ||
57 | ttypid = fmap textify $ identifyTTY ttypids' uid inode | ||
58 | textify (tty,pid) = (fmap lazyByteStringToText tty, pid) | ||
59 | |||
60 | chooseResourceName state k addr desired = do | ||
61 | muid <- getLocalPeerCred' addr | ||
62 | (mtty,pid) <- getTTYandPID muid | ||
63 | user <- getJabberUserForId muid | ||
64 | let client = ClientState { clientResource = maybe "fallback" id mtty | ||
65 | , clientUser = user | ||
66 | , clientPid = pid } | ||
67 | |||
68 | atomically $ | ||
69 | modifyTVar' (clients state) $ Map.insert k client | ||
70 | localJID (clientUser client) (clientResource client) | ||
71 | |||
72 | where | ||
73 | getTTYandPID muid = do | ||
74 | -- us <- fmap (map (second fst) . Map.toList) . readTVarIO $ activeUsers state | ||
75 | ttypids <- getConsolePids state | ||
76 | -- let tailOf3 ((_,a),b) = (a,b) | ||
77 | (t,pid) <- case muid of | ||
78 | Just (uid,inode) -> identifyTTY' ttypids uid inode | ||
79 | Nothing -> return (Nothing,Nothing) | ||
80 | let rsc = t `mplus` fmap ( ("pid."<>) . Text.pack . show ) pid | ||
81 | return (rsc,pid) | ||
82 | |||
83 | getJabberUserForId muid = | ||
84 | maybe (return "nobody") | ||
85 | (\(uid,_) -> | ||
86 | handle (\(SomeException _) -> | ||
87 | return . (<> "uid.") . Text.pack . show $ uid) | ||
88 | $ do | ||
89 | user <- fmap userName $ getUserEntryForID uid | ||
90 | return (Text.pack user) | ||
91 | ) | ||
92 | muid | ||
93 | |||
94 | forClient state k fallback f = do | ||
95 | mclient <- atomically $ do | ||
96 | cs <- readTVar (clients state) | ||
97 | return $ Map.lookup k cs | ||
98 | maybe (fallback k) (flip f k) mclient | ||
99 | |||
100 | tellClientHisName state k = forClient state k fallback go | ||
101 | where | ||
102 | fallback k = localJID "nobody" "fallback" | ||
103 | go client k = localJID (clientUser client) (clientResource client) | ||
104 | |||
105 | |||
23 | main = runResourceT $ do | 106 | main = runResourceT $ do |
24 | hostname <- fmap Text.pack $ liftIO BSD.getHostName | 107 | -- us <- liftIO UTmp.users |
108 | -- liftIO $ putStrLn (show us) | ||
109 | hostname <- liftIO textHostName | ||
110 | state <- do | ||
111 | clients <- liftIO . atomically $ newTVar Map.empty | ||
112 | return PresenceState | ||
113 | { clients = clients | ||
114 | } | ||
25 | sv <- xmppServer | 115 | sv <- xmppServer |
26 | XMPPServerParameters | 116 | XMPPServerParameters |
27 | { xmppChooseResourceName = \k sock desired -> return $ "nobody@" <> hostname <> "/tty666" | 117 | { xmppChooseResourceName = chooseResourceName state |
28 | , xmppTellMyNameToClient = return hostname | 118 | , xmppTellClientHisName = tellClientHisName state |
119 | , xmppTellMyNameToClient = textHostName | ||
29 | , xmppTellMyNameToPeer = \addr -> return $ addrToText addr | 120 | , xmppTellMyNameToPeer = \addr -> return $ addrToText addr |
30 | , xmppTellClientHisName = \k -> return $ "nobody@" <> hostname <> "/tty666" | ||
31 | , xmppTellPeerHisName = return . peerKeyToText | 121 | , xmppTellPeerHisName = return . peerKeyToText |
32 | , xmppNewConnection = \k outchan -> return () | 122 | , xmppNewConnection = \k outchan -> return () |
33 | , xmppEOF = \k -> return () | 123 | , xmppEOF = \k -> return () |
@@ -37,7 +127,7 @@ main = runResourceT $ do | |||
37 | , xmppRosterOthers = \k -> return [] | 127 | , xmppRosterOthers = \k -> return [] |
38 | , xmppSubscribeToRoster = \k -> return () | 128 | , xmppSubscribeToRoster = \k -> return () |
39 | , xmppLookupPeerName = \k -> return "localhost" | 129 | , xmppLookupPeerName = \k -> return "localhost" |
40 | , xmppLookupClientJID = \k -> return $ "nobody@" <> hostname <> "/tty666" | 130 | -- , xmppLookupClientJID = \k -> return $ "nobody@" <> hostname <> "/tty666" |
41 | , xmppDeliverMessage = \fail msg -> do | 131 | , xmppDeliverMessage = \fail msg -> do |
42 | let msgs = msgLangMap (stanzaType msg) | 132 | let msgs = msgLangMap (stanzaType msg) |
43 | body = fmap (maybe "" id . msgBody . snd) $ take 1 msgs | 133 | body = fmap (maybe "" id . msgBody . snd) $ take 1 msgs |