diff options
Diffstat (limited to 'Presence/XMPPServer.hs')
-rw-r--r-- | Presence/XMPPServer.hs | 111 |
1 files changed, 102 insertions, 9 deletions
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs index e44ae37b..d26e8c03 100644 --- a/Presence/XMPPServer.hs +++ b/Presence/XMPPServer.hs | |||
@@ -1364,6 +1364,28 @@ monitor sv params xmpp = do | |||
1364 | , EventEndElement "{http://jabber.org/protocol/muc#user}x" | 1364 | , EventEndElement "{http://jabber.org/protocol/muc#user}x" |
1365 | ] | 1365 | ] |
1366 | ioWriteChan replyto stanza | 1366 | ioWriteChan replyto stanza |
1367 | Part -> do | ||
1368 | stanza <- makePresenceStanzaEx "jabber:client" (Just $ roomjid muckey me rkey cnick) Offline | ||
1369 | $ [ EventBeginElement "{http://jabber.org/protocol/muc#user}x" [] ] | ||
1370 | ++ (do guard mine | ||
1371 | [ EventBeginElement "{http://jabber.org/protocol/muc#user}status" | ||
1372 | [ ("code",[ContentText "110"]) -- self-presence code. | ||
1373 | ] | ||
1374 | , EventEndElement "{http://jabber.org/protocol/muc#user}status" ]) | ||
1375 | ++ [ EventEndElement "{http://jabber.org/protocol/muc#user}x" ] | ||
1376 | ioWriteChan replyto stanza | ||
1377 | when mine $ atomically $ do | ||
1378 | jrs <- readTVar joined_rooms | ||
1379 | let m = Map.findWithDefault Map.empty k jrs | ||
1380 | m' = Map.delete (rkey,muckey) m | ||
1381 | jrs' = if Map.null m' then Map.delete k jrs | ||
1382 | else Map.insert k m' jrs | ||
1383 | writeTVar joined_rooms jrs' | ||
1384 | Talk talk -> do | ||
1385 | them <- xmppTellClientHisName xmpp k | ||
1386 | stanza <- makeMessageEx "jabber:client" (roomjid muckey me rkey cnick) them GroupChatMsg talk | ||
1387 | ioWriteChan replyto stanza | ||
1388 | return () | ||
1367 | _ -> return () | 1389 | _ -> return () |
1368 | ] | 1390 | ] |
1369 | action | 1391 | action |
@@ -1409,7 +1431,7 @@ data ServiceMatch a | |||
1409 | | TopLevelService -- ^ This server's exact hostname. | 1431 | | TopLevelService -- ^ This server's exact hostname. |
1410 | 1432 | ||
1411 | 1433 | ||
1412 | lookupService :: Text -> Map.Map Text a -> Text -> (ServiceMatch a) | 1434 | lookupService :: Text {- ^ hostname -} -> Map.Map Text a {- ^ service map -} -> Text {- ^ JID -} -> (ServiceMatch a) |
1413 | lookupService me mucs to = case Text.toLower to of | 1435 | lookupService me mucs to = case Text.toLower to of |
1414 | nm | nm == Text.toLower me | 1436 | nm | nm == Text.toLower me |
1415 | -> TopLevelService | 1437 | -> TopLevelService |
@@ -1432,7 +1454,9 @@ applyStanza :: Server PeerAddress ConnectionData releaseKey Event | |||
1432 | -> StanzaWrap (LockedChan Event) | 1454 | -> StanzaWrap (LockedChan Event) |
1433 | -> IO () | 1455 | -> IO () |
1434 | 1456 | ||
1435 | applyStanza sv joined_rooms quitVar xmpp stanza = case stanzaOrigin stanza of | 1457 | applyStanza sv joined_rooms quitVar xmpp stanza = do |
1458 | dput XJabber $ "applyStanza: " ++ show (stanzaType stanza) | ||
1459 | case stanzaOrigin stanza of | ||
1436 | ClientOrigin k replyto -> | 1460 | ClientOrigin k replyto -> |
1437 | case stanzaType stanza of | 1461 | case stanzaType stanza of |
1438 | RequestResource clientsNameForMe wanted -> do | 1462 | RequestResource clientsNameForMe wanted -> do |
@@ -1479,8 +1503,7 @@ applyStanza sv joined_rooms quitVar xmpp stanza = case stanzaOrigin stanza of | |||
1479 | PresenceStatus {} -> do | 1503 | PresenceStatus {} -> do |
1480 | let mucs = xmppGroupChat xmpp | 1504 | let mucs = xmppGroupChat xmpp |
1481 | me <- xmppTellMyNameToClient xmpp k | 1505 | me <- xmppTellMyNameToClient xmpp k |
1482 | if | Available <- presenceShow (stanzaType stanza) | 1506 | if | Just to <- stanzaTo stanza |
1483 | , Just to <- stanzaTo stanza | ||
1484 | , (Just room,h,mnick) <- splitJID to | 1507 | , (Just room,h,mnick) <- splitJID to |
1485 | , let roomjid = unsplitJID ((Just room,h,Nothing)) | 1508 | , let roomjid = unsplitJID ((Just room,h,Nothing)) |
1486 | , Service (Just _) mucname muc <- lookupService me mucs roomjid | 1509 | , Service (Just _) mucname muc <- lookupService me mucs roomjid |
@@ -1490,13 +1513,34 @@ applyStanza sv joined_rooms quitVar xmpp stanza = case stanzaOrigin stanza of | |||
1490 | reply <- makeErrorStanza' stanza JidMalformed | 1513 | reply <- makeErrorStanza' stanza JidMalformed |
1491 | [ ("by", [ContentText roomjid]) ] | 1514 | [ ("by", [ContentText roomjid]) ] |
1492 | sendReply quitVar (Error JidMalformed (head reply)) reply replyto | 1515 | sendReply quitVar (Error JidMalformed (head reply)) reply replyto |
1493 | Just nick -> do | 1516 | Just nick -> case presenceShow (stanzaType stanza) of |
1494 | jid <- xmppTellClientHisName xmpp k | 1517 | Available -> do |
1495 | r <- mucJoinRoom muc jid nick room k -- stanza | 1518 | jid <- xmppTellClientHisName xmpp k |
1496 | atomically $ do | 1519 | join $ atomically $ do |
1497 | jrs <- readTVar joined_rooms | 1520 | jrs <- readTVar joined_rooms |
1498 | let m = Map.findWithDefault Map.empty k jrs | 1521 | let m = Map.findWithDefault Map.empty k jrs |
1499 | writeTVar joined_rooms $ Map.insert k (Map.insert (room,mucname) (replyto,r) m) jrs | 1522 | case Map.lookup (room,mucname) m of |
1523 | Nothing -> do r <- mucJoinRoom muc jid nick room k -- stanza | ||
1524 | jrs <- readTVar joined_rooms | ||
1525 | let m = Map.findWithDefault Map.empty k jrs | ||
1526 | writeTVar joined_rooms $ Map.insert k (Map.insert (room,mucname) (replyto,r) m) jrs | ||
1527 | return $ return () | ||
1528 | Just r -> return $ dput XJabber "MUC: already joined." | ||
1529 | Offline -> do | ||
1530 | jid <- xmppTellClientHisName xmpp k | ||
1531 | atomically $ do | ||
1532 | jrs <- readTVar joined_rooms | ||
1533 | let m = Map.findWithDefault Map.empty k jrs | ||
1534 | case Map.lookup (room,mucname) m of | ||
1535 | Just (_,r) -> do | ||
1536 | partRoom r (Just jid) -- joinedNick r == nick | ||
1537 | {- | ||
1538 | let m' = Map.delete (room,mucname) m | ||
1539 | jrs' = if Map.null m' then Map.delete k jrs | ||
1540 | else Map.insert k m' jrs | ||
1541 | writeTVar joined_rooms jrs' | ||
1542 | -} | ||
1543 | _ -> return () | ||
1500 | | otherwise -> do | 1544 | | otherwise -> do |
1501 | -- Handle presence stanza that is not a chatroom join. | 1545 | -- Handle presence stanza that is not a chatroom join. |
1502 | xmppInformClientPresence xmpp k stanza | 1546 | xmppInformClientPresence xmpp k stanza |
@@ -1541,6 +1585,24 @@ applyStanza sv joined_rooms quitVar xmpp stanza = case stanzaOrigin stanza of | |||
1541 | let reply = makeNodeInfo (stanzaId stanza) "x-roomuser-item" (room <> "@" <> a <> "." <> me) | 1585 | let reply = makeNodeInfo (stanzaId stanza) "x-roomuser-item" (room <> "@" <> a <> "." <> me) |
1542 | (stanzaFrom stanza) n | 1586 | (stanzaFrom stanza) n |
1543 | return (Info, reply) | 1587 | return (Info, reply) |
1588 | (Service (Just room) a muc) | Just "http://jabber.org/protocol/muc#traffic" <- mnode | ||
1589 | -> do | ||
1590 | dput XJabber $ "TODO: 18.1.1 Allowable Traffic" | ||
1591 | reply <- makeErrorStanza' stanza FeatureNotImplemented | ||
1592 | [ ("by", [ContentText (room <> "@" <> a <> "." <> me)]) ] | ||
1593 | return (Error FeatureNotImplemented (head reply), reply) | ||
1594 | (Service (Just room) a muc) | Just "http://jabber.org/protocol/muc#rooms" <- mnode | ||
1595 | -> do | ||
1596 | dput XJabber $ "TODO: 6.7 Discovering Client Support for MUC" | ||
1597 | reply <- makeErrorStanza' stanza FeatureNotImplemented | ||
1598 | [ ("by", [ContentText (room <> "@" <> a <> "." <> me)]) ] | ||
1599 | return (Error FeatureNotImplemented (head reply), reply) | ||
1600 | (Service (Just room) a muc) | Just nodename <- mnode | ||
1601 | -> do | ||
1602 | dput XJabber $ "Uknown info node: " ++ Text.unpack nodename | ||
1603 | reply <- makeErrorStanza' stanza FeatureNotImplemented | ||
1604 | [ ("by", [ContentText (room <> "@" <> a <> "." <> me)]) ] | ||
1605 | return (Error FeatureNotImplemented (head reply), reply) | ||
1544 | TopLevelService | 1606 | TopLevelService |
1545 | -> case mnode of | 1607 | -> case mnode of |
1546 | Just _ -> unavail | 1608 | Just _ -> unavail |
@@ -1579,6 +1641,36 @@ applyStanza sv joined_rooms quitVar xmpp stanza = case stanzaOrigin stanza of | |||
1579 | me <- xmppTellMyNameToClient xmpp k | 1641 | me <- xmppTellMyNameToClient xmpp k |
1580 | let reply = iq_service_unavailable (stanzaId stanza) me query | 1642 | let reply = iq_service_unavailable (stanzaId stanza) me query |
1581 | sendReply quitVar (Error ServiceUnavailable (head reply)) reply replyto | 1643 | sendReply quitVar (Error ServiceUnavailable (head reply)) reply replyto |
1644 | Message { msgType = GroupChatMsg } -> do | ||
1645 | let mucs = xmppGroupChat xmpp | ||
1646 | me <- xmppTellMyNameToClient xmpp k | ||
1647 | if | Just to <- stanzaTo stanza | ||
1648 | , (Just room,h,mnick) <- splitJID to | ||
1649 | , let roomjid = unsplitJID ((Just room,h,Nothing)) | ||
1650 | , Service (Just _) mucname muc <- lookupService me mucs roomjid | ||
1651 | -> case mnick of | ||
1652 | Nothing -> do | ||
1653 | -- Send message. | ||
1654 | jid <- xmppTellClientHisName xmpp k -- This should match stanzaFrom | ||
1655 | join $ atomically $ do | ||
1656 | jrs <- readTVar joined_rooms | ||
1657 | let m = Map.findWithDefault Map.empty k jrs | ||
1658 | case Map.lookup (room,mucname) m of | ||
1659 | Just (_,r) -> do | ||
1660 | let RH v = roomHandle r | ||
1661 | oldt <- readTVar v | ||
1662 | expected <- readTVar (roomFutureSeqNo $ joinedRoom r) | ||
1663 | b <- sendChat r (Just jid) $ do | ||
1664 | (_,msg) <- msgLangMap (stanzaType stanza) | ||
1665 | talk <- maybeToList $ msgBody msg | ||
1666 | [ Talk talk ] | ||
1667 | return $ dput XJabber $ "sendChat: " ++ show (b,expected,oldt,msgLangMap (stanzaType stanza)) | ||
1668 | _ -> return $ dput XJabber $ "uknown room" ++ show (room,mucname) | ||
1669 | Just nick -> do | ||
1670 | -- Private message. TODO | ||
1671 | dput XJabber $ "TODO: Private messasge. " ++ show nick | ||
1672 | |||
1673 | | otherwise -> dput XJabber $ "Failed groupchat parse. to=" ++ show (stanzaTo stanza) | ||
1582 | Message {} -> do | 1674 | Message {} -> do |
1583 | -- wlog $ "LANGMAP "++show (stanzaId stanza, msgLangMap (stanzaType stanza)) | 1675 | -- wlog $ "LANGMAP "++show (stanzaId stanza, msgLangMap (stanzaType stanza)) |
1584 | maybe (return ()) (flip cacheMessageId replyto) $ do | 1676 | maybe (return ()) (flip cacheMessageId replyto) $ do |
@@ -1615,6 +1707,7 @@ forwardStanza quitVar xmpp stanza = do | |||
1615 | -- let newStream = greet'' "jabber:client" "blackbird" | 1707 | -- let newStream = greet'' "jabber:client" "blackbird" |
1616 | -- sendReply quitVar Error newStream replyto | 1708 | -- sendReply quitVar Error newStream replyto |
1617 | case stanzaType stanza of | 1709 | case stanzaType stanza of |
1710 | Message { msgType = GroupChatMsg } -> return () -- Group chat handled elsewhere. | ||
1618 | Message {} -> do | 1711 | Message {} -> do |
1619 | case stanzaOrigin stanza of | 1712 | case stanzaOrigin stanza of |
1620 | LocalPeer {} -> return () | 1713 | LocalPeer {} -> return () |