diff options
-rw-r--r-- | src/Network/Tox/Crypto/Handlers.hs | 101 | ||||
-rw-r--r-- | src/Network/Tox/Crypto/Transport.hs | 1 |
2 files changed, 97 insertions, 5 deletions
diff --git a/src/Network/Tox/Crypto/Handlers.hs b/src/Network/Tox/Crypto/Handlers.hs index 602b14cc..fe620757 100644 --- a/src/Network/Tox/Crypto/Handlers.hs +++ b/src/Network/Tox/Crypto/Handlers.hs | |||
@@ -25,6 +25,7 @@ import qualified Data.PacketQueue as PQ | |||
25 | ;import Data.PacketQueue (PacketQueue) | 25 | ;import Data.PacketQueue (PacketQueue) |
26 | import Data.Serialize as S | 26 | import Data.Serialize as S |
27 | import Data.Word | 27 | import Data.Word |
28 | import Data.Maybe | ||
28 | import qualified Data.Word64Map as W64 | 29 | import qualified Data.Word64Map as W64 |
29 | import Data.Word64RangeMap | 30 | import Data.Word64RangeMap |
30 | import qualified Data.Set as Set | 31 | import qualified Data.Set as Set |
@@ -66,6 +67,9 @@ data SessionView = SessionView | |||
66 | { svNick :: TVar ByteString | 67 | { svNick :: TVar ByteString |
67 | , svStatus :: TVar UserStatus | 68 | , svStatus :: TVar UserStatus |
68 | , svStatusMsg :: TVar ByteString | 69 | , svStatusMsg :: TVar ByteString |
70 | , svTheirNick :: TVar ByteString | ||
71 | , svTheirStatus :: TVar UserStatus | ||
72 | , svTheirStatusMsg :: TVar ByteString | ||
69 | , svNoSpam :: TVar (Maybe NoSpam) | 73 | , svNoSpam :: TVar (Maybe NoSpam) |
70 | , svGroups :: TVar (Map.Map GroupChatId (Set.Set SockAddr)) | 74 | , svGroups :: TVar (Map.Map GroupChatId (Set.Set SockAddr)) |
71 | 75 | ||
@@ -193,6 +197,9 @@ newSessionsState crypto unrechook hooks = do | |||
193 | nick <- atomically $ newTVar B.empty | 197 | nick <- atomically $ newTVar B.empty |
194 | status <- atomically $ newTVar Online | 198 | status <- atomically $ newTVar Online |
195 | statusmsg <- atomically $ newTVar B.empty | 199 | statusmsg <- atomically $ newTVar B.empty |
200 | theirnick <- atomically $ newTVar B.empty | ||
201 | theirstatus <- atomically $ newTVar Online | ||
202 | theirstatusmsg <- atomically $ newTVar B.empty | ||
196 | nospam <- atomically $ newTVar Nothing | 203 | nospam <- atomically $ newTVar Nothing |
197 | grps <- atomically $ newTVar Map.empty | 204 | grps <- atomically $ newTVar Map.empty |
198 | pname <- getProgName | 205 | pname <- getProgName |
@@ -214,6 +221,9 @@ newSessionsState crypto unrechook hooks = do | |||
214 | { svNick = nick | 221 | { svNick = nick |
215 | , svStatus = status | 222 | , svStatus = status |
216 | , svStatusMsg = statusmsg | 223 | , svStatusMsg = statusmsg |
224 | , svTheirNick = theirnick | ||
225 | , svTheirStatus = theirstatus | ||
226 | , svTheirStatusMsg = theirstatusmsg | ||
217 | , svNoSpam = nospam | 227 | , svNoSpam = nospam |
218 | , svGroups = grps | 228 | , svGroups = grps |
219 | , svCacheDir = cachedir | 229 | , svCacheDir = cachedir |
@@ -652,28 +662,109 @@ allMsgTypes fDefault = A.listArray (minBound,maxBound) (0:knownMsgs) | |||
652 | , map (const 0) [ 200 .. 255 ] -- All lossy, exept the last | 662 | , map (const 0) [ 200 .. 255 ] -- All lossy, exept the last |
653 | ] | 663 | ] |
654 | 664 | ||
655 | -- | handles nothing | 665 | setNick :: TransportCrypto -> NetCryptoSession -> ByteString -> IO (Either String ()) |
666 | setNick crypto session nick = do | ||
667 | let Just (_,maxlen) = msgSizeParam NICKNAME | ||
668 | if B.length nick > maxlen | ||
669 | then return (Left $ "nickname must not exceed " ++ show maxlen ++ " bytes.") | ||
670 | else do | ||
671 | let viewVar = ncView session | ||
672 | atomically $ do | ||
673 | view <- readTVar viewVar | ||
674 | writeTVar (svNick view) nick | ||
675 | let nickPacket = error "todo" | ||
676 | return (Left "TODO: sendMessage crypto (NetCrypto nickPacket)") | ||
677 | -- return (Right ()) | ||
678 | |||
679 | setStatus :: TransportCrypto -> NetCryptoSession -> UserStatus -> IO (Either String ()) | ||
680 | setStatus crypto session status = do | ||
681 | let viewVar = ncView session | ||
682 | atomically $ do | ||
683 | view <- readTVar viewVar | ||
684 | writeTVar (svStatus view) status | ||
685 | let statusPacket = error "todo" | ||
686 | return (Left "TODO: sendMessage crypto (NetCrypto statusPacket)") | ||
687 | |||
688 | setStatusMsg :: TransportCrypto -> NetCryptoSession -> ByteString -> IO (Either String ()) | ||
689 | setStatusMsg crypto session msg = do | ||
690 | let Just (_,maxlen) = msgSizeParam STATUSMESSAGE | ||
691 | if B.length msg > maxlen | ||
692 | then return (Left $ "status message must not exceed " ++ show maxlen ++ " bytes.") | ||
693 | else do | ||
694 | let viewVar = ncView session | ||
695 | atomically $ do | ||
696 | view <- readTVar viewVar | ||
697 | writeTVar (svStatusMsg view) msg | ||
698 | let statusMsgPacket = error "todo" | ||
699 | return (Left "TODO: sendMessage crypto (NetCrypto statusMsgPacket)") | ||
700 | |||
701 | -- | handles nothings | ||
656 | defaultCryptoDataHooks :: Map.Map MessageType [NetCryptoHook] | 702 | defaultCryptoDataHooks :: Map.Map MessageType [NetCryptoHook] |
657 | defaultCryptoDataHooks = Map.empty | 703 | defaultCryptoDataHooks |
704 | = Map.fromList | ||
705 | [ (Msg USERSTATUS,[defaultUserStatusHook]) | ||
706 | , (Msg NICKNAME, [defaultNicknameHook]) | ||
707 | , (Msg STATUSMESSAGE, [defaultStatusMsgHook]) | ||
708 | ] | ||
709 | |||
710 | defaultUserStatusHook :: NetCryptoSession -> CryptoMessage -> IO (Maybe (CryptoMessage -> CryptoMessage)) | ||
711 | defaultUserStatusHook session cm@(TwoByte {msgID=USERSTATUS, msgByte=statusByte}) = do | ||
712 | let status = toEnum8 statusByte | ||
713 | viewVar = ncView session | ||
714 | atomically $ do | ||
715 | view <- readTVar viewVar | ||
716 | writeTVar (svTheirStatus view) status | ||
717 | hookHelper True (Msg USERSTATUS) session cm | ||
718 | |||
719 | defaultNicknameHook :: NetCryptoSession -> CryptoMessage -> IO (Maybe (CryptoMessage -> CryptoMessage)) | ||
720 | defaultNicknameHook session cm@(UpToN {msgID=NICKNAME, msgBytes=nick}) = do | ||
721 | let viewVar = ncView session | ||
722 | atomically $ do | ||
723 | view <- readTVar viewVar | ||
724 | writeTVar (svTheirNick view) nick | ||
725 | hookHelper True (Msg NICKNAME) session cm | ||
726 | |||
727 | defaultStatusMsgHook :: NetCryptoSession -> CryptoMessage -> IO (Maybe (CryptoMessage -> CryptoMessage)) | ||
728 | defaultStatusMsgHook session cm@(UpToN {msgID=STATUSMESSAGE, msgBytes=msg}) = do | ||
729 | let viewVar = ncView session | ||
730 | atomically $ do | ||
731 | view <- readTVar viewVar | ||
732 | writeTVar (svTheirStatusMsg view) msg | ||
733 | hookHelper True (Msg STATUSMESSAGE) session cm | ||
658 | 734 | ||
659 | -- | updates ncLastNMsgs, and sends message to type-0 listeners | 735 | -- | updates ncLastNMsgs, and sends message to type-0 listeners |
660 | defaultUnRecHook :: MessageType -> NetCryptoHook | 736 | defaultUnRecHook :: MessageType -> NetCryptoHook |
661 | defaultUnRecHook typ session cm | any ($ typ) [isKillPacket, isOFFLINE] = atomically $ do | 737 | defaultUnRecHook = hookHelper False |
738 | |||
739 | hookHelper :: Bool -> MessageType -> NetCryptoHook | ||
740 | hookHelper _ typ session cm | any ($ typ) [isKillPacket, isOFFLINE] = atomically $ do | ||
662 | tmchans <- map snd . IntMap.elems <$> readTVar (ncListeners session) | 741 | tmchans <- map snd . IntMap.elems <$> readTVar (ncListeners session) |
663 | forM_ tmchans $ \chan -> closeTMChan chan | 742 | forM_ tmchans $ \chan -> closeTMChan chan |
664 | return Nothing | 743 | return Nothing |
665 | 744 | ||
666 | defaultUnRecHook typ session cm = do | 745 | hookHelper handledFlg typ session cm = do |
667 | let msgQ = ncLastNMsgs session | 746 | let msgQ = ncLastNMsgs session |
668 | msgNumVar = ncMsgNumVar session | 747 | msgNumVar = ncMsgNumVar session |
669 | dropCntVar = ncDropCntVar session | 748 | dropCntVar = ncDropCntVar session |
670 | atomically $ do | 749 | atomically $ do |
671 | num <- readTVar msgNumVar | 750 | num <- readTVar msgNumVar |
672 | (wraps,offset) <- PQ.enqueue msgQ num (False,cm) | 751 | (wraps,offset) <- PQ.enqueue msgQ num (handledFlg,cm) |
673 | capacity <- PQ.getCapacity msgQ | 752 | capacity <- PQ.getCapacity msgQ |
674 | let dropped = wraps * capacity + offset | 753 | let dropped = wraps * capacity + offset |
675 | modifyTVar' msgNumVar (+1) | 754 | modifyTVar' msgNumVar (+1) |
676 | writeTVar dropCntVar dropped | 755 | writeTVar dropCntVar dropped |
756 | atomically $ do | ||
757 | idtmchans <- IntMap.assocs <$> readTVar (ncListeners session) | ||
758 | mbChans | ||
759 | <- forM idtmchans $ \(id,(typ,chan)) -> do | ||
760 | bClosed <- isClosedTMChan chan | ||
761 | if bClosed | ||
762 | then do | ||
763 | modifyTVar' (ncListeners session) (IntMap.delete id) | ||
764 | return Nothing | ||
765 | else return (if typ==0 then Just chan else Nothing) | ||
766 | forM_ (catMaybes mbChans) $ \chan -> do | ||
767 | writeTMChan chan cm | ||
677 | return Nothing | 768 | return Nothing |
678 | 769 | ||
679 | -- | use to add a single hook to a specific session. | 770 | -- | use to add a single hook to a specific session. |
diff --git a/src/Network/Tox/Crypto/Transport.hs b/src/Network/Tox/Crypto/Transport.hs index 70405a3e..40288502 100644 --- a/src/Network/Tox/Crypto/Transport.hs +++ b/src/Network/Tox/Crypto/Transport.hs | |||
@@ -53,6 +53,7 @@ module Network.Tox.Crypto.Transport | |||
53 | , fromEnum8 | 53 | , fromEnum8 |
54 | , fromEnum16 | 54 | , fromEnum16 |
55 | , toEnum8 | 55 | , toEnum8 |
56 | , msgSizeParam | ||
56 | ) where | 57 | ) where |
57 | 58 | ||
58 | import Crypto.Tox | 59 | import Crypto.Tox |