diff options
-rw-r--r-- | dht-client.cabal | 6 | ||||
-rw-r--r-- | examples/dhtd.hs | 114 | ||||
-rw-r--r-- | src/Data/Word64RangeMap.hs | 6 | ||||
-rw-r--r-- | src/Network/Tox/Crypto/Handlers.hs | 139 |
4 files changed, 211 insertions, 54 deletions
diff --git a/dht-client.cabal b/dht-client.cabal index 7382eb76..aa2ab6cc 100644 --- a/dht-client.cabal +++ b/dht-client.cabal | |||
@@ -92,6 +92,7 @@ library | |||
92 | Data.CyclicBuffer | 92 | Data.CyclicBuffer |
93 | Data.Word64Map | 93 | Data.Word64Map |
94 | Data.Word64RangeMap | 94 | Data.Word64RangeMap |
95 | Data.Word64RangeMap.Unboxed | ||
95 | OnionRouter | 96 | OnionRouter |
96 | Network.Tox | 97 | Network.Tox |
97 | Network.Tox.Transport | 98 | Network.Tox.Transport |
@@ -273,6 +274,7 @@ executable dhtd | |||
273 | default-language: Haskell2010 | 274 | default-language: Haskell2010 |
274 | build-depends: base, network, bytestring, hashable, deepseq | 275 | build-depends: base, network, bytestring, hashable, deepseq |
275 | , aeson | 276 | , aeson |
277 | , array | ||
276 | , pretty | 278 | , pretty |
277 | , dht-client | 279 | , dht-client |
278 | , unix | 280 | , unix |
@@ -288,7 +290,11 @@ executable dhtd | |||
288 | , monad-control | 290 | , monad-control |
289 | , xml-types | 291 | , xml-types |
290 | , conduit | 292 | , conduit |
293 | , conduit-extra | ||
291 | , transformers | 294 | , transformers |
295 | , filepath | ||
296 | , process | ||
297 | , cereal-conduit >= 0.7.3 | ||
292 | 298 | ||
293 | if flag(thread-debug) | 299 | if flag(thread-debug) |
294 | build-depends: time | 300 | build-depends: time |
diff --git a/examples/dhtd.hs b/examples/dhtd.hs index 1821cb1c..8e34d4fe 100644 --- a/examples/dhtd.hs +++ b/examples/dhtd.hs | |||
@@ -62,7 +62,9 @@ import qualified Data.HashMap.Strict as HashMap | |||
62 | import qualified Data.Text as T | 62 | import qualified Data.Text as T |
63 | import qualified Data.Text.Encoding as T | 63 | import qualified Data.Text.Encoding as T |
64 | import System.Posix.Signals | 64 | import System.Posix.Signals |
65 | 65 | import qualified Data.Array | |
66 | import qualified Data.Array.Unboxed as U | ||
67 | import qualified Data.Conduit as Conduit | ||
66 | 68 | ||
67 | import Announcer | 69 | import Announcer |
68 | import Announcer.Tox | 70 | import Announcer.Tox |
@@ -103,6 +105,13 @@ import OnionRouter | |||
103 | import PingMachine | 105 | import PingMachine |
104 | import Data.PacketQueue | 106 | import Data.PacketQueue |
105 | import qualified Data.Word64Map as W64 | 107 | import qualified Data.Word64Map as W64 |
108 | import System.FilePath | ||
109 | import System.Process | ||
110 | import System.Posix.IO | ||
111 | import Data.Word64RangeMap | ||
112 | import Network.Tox.Crypto.Transport | ||
113 | import Data.Conduit.Cereal | ||
114 | import qualified Data.Conduit.Binary as Conduit | ||
106 | 115 | ||
107 | -- Presence imports. | 116 | -- Presence imports. |
108 | import ConsoleWriter | 117 | import ConsoleWriter |
@@ -932,7 +941,9 @@ clientSession s@Session{..} sock cnum h = do | |||
932 | 941 | ||
933 | -- necrypto <FRIEND-TOXID> | 942 | -- necrypto <FRIEND-TOXID> |
934 | -- establish a netcrypto session with specified person | 943 | -- establish a netcrypto session with specified person |
935 | ("netcrypto", s) -> cmd0 $ netcrypto (Map.lookup netname dhts) selectedKey h roster mbTox (strp s) | 944 | ("netcrypto", s) -> cmd0 $ do |
945 | let exes = Map.fromList [("atox",("/usr/bin/tmux -c","atox"))] | ||
946 | netcrypto (Map.lookup netname dhts) selectedKey h roster mbTox exes (strp s) | ||
936 | ("g", s) | Just DHT{..} <- Map.lookup netname dhts | 947 | ("g", s) | Just DHT{..} <- Map.lookup netname dhts |
937 | -> cmd0 $ do | 948 | -> cmd0 $ do |
938 | -- arguments: method | 949 | -- arguments: method |
@@ -1282,11 +1293,12 @@ netcrypto | |||
1282 | -> ClientHandle | 1293 | -> ClientHandle |
1283 | -> ContactInfo extra1 | 1294 | -> ContactInfo extra1 |
1284 | -> Maybe (Tox.Tox extra2) | 1295 | -> Maybe (Tox.Tox extra2) |
1296 | -> Map.Map String (String,String) -- profile name to (multiplexer,exe name) for supported child executables | ||
1285 | -> String | 1297 | -> String |
1286 | -> IO () | 1298 | -> IO () |
1287 | netcrypto _ _ h _ Nothing _ = hPutClient h "Requires Tox enabled." | 1299 | netcrypto _ _ h _ Nothing _ _ = hPutClient h "Requires Tox enabled." |
1288 | netcrypto _ Nothing h _ _ _ = hPutClient h "No key is selected, see k command." | 1300 | netcrypto _ Nothing h _ _ _ _ = hPutClient h "No key is selected, see k command." |
1289 | netcrypto (Just (DHT {..})) (Just mypubkey) h roster (Just tox) keystr = | 1301 | netcrypto (Just (DHT {..})) (Just mypubkey) h roster (Just tox) exes paramStr = |
1290 | either | 1302 | either |
1291 | (const $ | 1303 | (const $ |
1292 | either | 1304 | either |
@@ -1297,6 +1309,25 @@ netcrypto (Just (DHT {..})) (Just mypubkey) h roster (Just tox) keystr = | |||
1297 | (goPubkey . Tox.id2key) $ | 1309 | (goPubkey . Tox.id2key) $ |
1298 | readEither keystr -- attempt read as NodeId type | 1310 | readEither keystr -- attempt read as NodeId type |
1299 | where | 1311 | where |
1312 | params = words paramStr | ||
1313 | keystr = bool (head params) "" (null params) | ||
1314 | -- TODO: | ||
1315 | -- execProfiles: | ||
1316 | -- atox@24-25,48-51,64-45 gnome-tox-notifier@24-25,49,50 | ||
1317 | -- ^-- word64 type values that should be forwarded to this process | ||
1318 | execParams=drop 1 params | ||
1319 | parseExecParam :: String -> (String,[(Maybe Word64,Maybe Word64)]) | ||
1320 | parseExecParam param = let (name,drop 1 -> rangesCombined) = span (/='@') param | ||
1321 | wordsBy x str = groupBy (const (/=x)) str | ||
1322 | rangesUnparsed = wordsBy ',' rangesCombined | ||
1323 | parseRange :: String -> (Maybe Word64,Maybe Word64) | ||
1324 | parseRange "all" = (Nothing,Nothing) | ||
1325 | parseRange x = let (low,drop 1 -> high) = break (==',') x | ||
1326 | in (readMaybe low,readMaybe high) | ||
1327 | in (name,map parseRange rangesUnparsed) | ||
1328 | execs = map parseExecParam execParams | ||
1329 | |||
1330 | |||
1300 | goNodeInfo userkey_nodeinfo = do | 1331 | goNodeInfo userkey_nodeinfo = do |
1301 | msec <- | 1332 | msec <- |
1302 | atomically $ do | 1333 | atomically $ do |
@@ -1314,7 +1345,78 @@ netcrypto (Just (DHT {..})) (Just mypubkey) h roster (Just tox) keystr = | |||
1314 | Just account -> do | 1345 | Just account -> do |
1315 | now <- getPOSIXTime | 1346 | now <- getPOSIXTime |
1316 | atomically $ setContactAddr now their_pub their_addr account | 1347 | atomically $ setContactAddr now their_pub their_addr account |
1317 | Tox.netCrypto tox sec their_pub | 1348 | sessions <- Tox.netCrypto tox sec their_pub |
1349 | exeDir <- takeDirectory <$> getExecutablePath | ||
1350 | forM_ sessions $ \session -> do | ||
1351 | forM_ execs $ \(exekey,ranges) -> do | ||
1352 | case Map.lookup exekey exes of | ||
1353 | Nothing -> return () | ||
1354 | Just (multiplexer,exename) -> do | ||
1355 | let exepath = exeDir </> exename | ||
1356 | (myReadFd,myWriteFd) <- System.Posix.IO.createPipe | ||
1357 | myRead <- fdToHandle myReadFd | ||
1358 | myWrite <- fdToHandle myWriteFd | ||
1359 | whoAmI <- atomically $ newTVar mypubkey | ||
1360 | whoAreThey <- atomically $ newTVar their_pub | ||
1361 | let fdArgs = [show myWriteFd,show myReadFd] | ||
1362 | if null multiplexer | ||
1363 | then callProcess exepath fdArgs | ||
1364 | else do | ||
1365 | let (multiplexer_exe,multiplexer_args) = splitAt 1 (words multiplexer) | ||
1366 | callProcess multiplexer (multiplexer_args ++ [intercalate " " (exepath:fdArgs)]) | ||
1367 | -- tell subprocess who is talking to who | ||
1368 | B.hPutStr myWrite ("\NUL\NUL" `B.append` S.encode (Tox.key2id mypubkey)) | ||
1369 | B.hPutStr myWrite ("\NUL\SOH" `B.append` S.encode (Tox.key2id their_pub)) | ||
1370 | -- add hooks so subprocess is updated on incoming | ||
1371 | let makeHook session typ | ||
1372 | = \session msg | ||
1373 | -> do -- if (getMessageType msg == typ) | ||
1374 | me <- atomically $ readTVar whoAmI | ||
1375 | when (me /= mypubkey) $ do | ||
1376 | atomically $ writeTVar whoAmI mypubkey | ||
1377 | B.hPutStr myWrite ("\NUL\NUL" `B.append` S.encode (Tox.key2id mypubkey)) | ||
1378 | them <- atomically $ readTVar whoAreThey | ||
1379 | when (them /= their_pub) $ do | ||
1380 | atomically $ writeTVar whoAreThey their_pub | ||
1381 | B.hPutStr myWrite ("\NUL\SOH" `B.append` S.encode (Tox.key2id their_pub)) | ||
1382 | B.hPutStr myWrite (S.encode msg) | ||
1383 | return (Just id) | ||
1384 | addHooks currentHooks typs = forM_ typs $ \typ -> modifyTVar (Tox.ncHooks session) (Map.insert typ (currentHooks typ ++ [makeHook session typ])) | ||
1385 | case ranges of | ||
1386 | [(Nothing,Nothing)] -> atomically $ do | ||
1387 | typs <- map fromWord64 . filter (/=0) . U.elems <$> readTVar (Tox.ncIncomingTypeArray session) | ||
1388 | addHooks (const []) typs | ||
1389 | _ -> atomically . forM_ ranges $ \range -> do | ||
1390 | case range of | ||
1391 | (Just first,Just last) -> do | ||
1392 | let typs = map fromWord64 [first .. last] | ||
1393 | hooks <- readTVar (Tox.ncHooks session) | ||
1394 | let currentHooks typ = fromMaybe [] (Map.lookup typ hooks) | ||
1395 | addHooks currentHooks typs | ||
1396 | -- forward messages from subprocess | ||
1397 | forwardThread <- forkIO $ do | ||
1398 | tid <- myThreadId | ||
1399 | let sidStr = printf "(%x)" (Tox.ncSessionId session) | ||
1400 | labelThread tid (exekey ++ ".forward" ++ sidStr) | ||
1401 | let myconduit = Conduit.sourceHandle myRead .| conduitGet2 S.get -- :: ConduitT i CryptoMessage IO () | ||
1402 | Conduit.runConduit (myconduit .| awaitForever (\msg -> do | ||
1403 | let typ = toWord64 (getMessageType msg) | ||
1404 | mbSendIt <- liftIO $ atomically (lookupInRangeMap typ (Tox.ncOutHooks session)) | ||
1405 | case mbSendIt of | ||
1406 | Just sendit -> liftIO . void $ sendit (Tox.toxCryptoKeys tox) session msg | ||
1407 | Nothing -> return () -- do | ||
1408 | -- uncomment to let unhooked pass thru: | ||
1409 | -- if lossyness (msgId msg) == Lossless | ||
1410 | -- then sendLossless (Tox.toxCryptoKeys tox) session msg | ||
1411 | -- else sendLossy (Tox.toxCryptoKeys tox) session msg | ||
1412 | )) | ||
1413 | -- add hook to killThread on kill packet | ||
1414 | atomically $ do | ||
1415 | hooks <- readTVar (Tox.ncHooks session) | ||
1416 | let currentHooks = fromMaybe [] $ Map.lookup (Msg KillPacket) hooks | ||
1417 | let myhook :: Tox.NetCryptoSession -> CryptoMessage -> IO (Maybe (CryptoMessage -> CryptoMessage)) | ||
1418 | myhook _ _ = killThread forwardThread >> return (Just id) | ||
1419 | modifyTVar' (Tox.ncHooks session) (Map.insert (Msg KillPacket) (currentHooks ++ [myhook])) | ||
1318 | hPutClient h "Handshake sent" | 1420 | hPutClient h "Handshake sent" |
1319 | goPubkey their_pub = do | 1421 | goPubkey their_pub = do |
1320 | msec <- | 1422 | msec <- |
diff --git a/src/Data/Word64RangeMap.hs b/src/Data/Word64RangeMap.hs index f4736d59..2e4cc8b7 100644 --- a/src/Data/Word64RangeMap.hs +++ b/src/Data/Word64RangeMap.hs | |||
@@ -20,14 +20,14 @@ import Data.IORef | |||
20 | 20 | ||
21 | type OuterIndex = Int | 21 | type OuterIndex = Int |
22 | type Index = Word64 | 22 | type Index = Word64 |
23 | type InnerArray b = UArray Index b | 23 | type InnerArray b = Array Index b |
24 | 24 | ||
25 | -- | Although this type includes a parameter for index, the code assumes bounds start at 0 | 25 | -- | Although this type includes a parameter for index, the code assumes bounds start at 0 |
26 | -- and the index has 'Integral', and 'Num' instances. | 26 | -- and the index has 'Integral', and 'Num' instances. |
27 | newtype RefArray r ma i e = RefArray (r (ma i e)) | 27 | newtype RefArray r ma i e = RefArray (r (ma i e)) |
28 | 28 | ||
29 | -- convenient contraint kind | 29 | -- convenient contraint kind |
30 | type RangeArray rangeArray m b ref = (IArray UArray b, MArray rangeArray (InnerArray b) m, Reference ref m) | 30 | type RangeArray rangeArray m b ref = (MArray rangeArray (InnerArray b) m, Reference ref m) |
31 | -- The RangeMap type, to be used with the above constraint | 31 | -- The RangeMap type, to be used with the above constraint |
32 | type RangeMap rangeArray b ref = RefArray ref rangeArray OuterIndex (InnerArray b) | 32 | type RangeMap rangeArray b ref = RefArray ref rangeArray OuterIndex (InnerArray b) |
33 | 33 | ||
@@ -64,7 +64,7 @@ instance (Reference r m, MArray ma e m) => MArray (RefArray r ma) e m where | |||
64 | unsafeWrite (RefArray r) i e = modifyRef r (\x -> Base.unsafeWrite x i e >> return (x,())) | 64 | unsafeWrite (RefArray r) i e = modifyRef r (\x -> Base.unsafeWrite x i e >> return (x,())) |
65 | -} | 65 | -} |
66 | 66 | ||
67 | emptySTMRangeMap :: STM (RangeMap TArray Word8 TVar) | 67 | emptySTMRangeMap :: STM (RangeMap TArray a TVar) |
68 | emptySTMRangeMap = RefArray <$> | 68 | emptySTMRangeMap = RefArray <$> |
69 | (newTVar =<< | 69 | (newTVar =<< |
70 | newListArray (0,-1) []) | 70 | newListArray (0,-1) []) |
diff --git a/src/Network/Tox/Crypto/Handlers.hs b/src/Network/Tox/Crypto/Handlers.hs index d5a49816..fabbf21d 100644 --- a/src/Network/Tox/Crypto/Handlers.hs +++ b/src/Network/Tox/Crypto/Handlers.hs | |||
@@ -32,7 +32,9 @@ import Data.Maybe | |||
32 | import qualified Data.Word64Map as W64 | 32 | import qualified Data.Word64Map as W64 |
33 | import Data.Word64RangeMap | 33 | import Data.Word64RangeMap |
34 | import qualified Data.Set as Set | 34 | import qualified Data.Set as Set |
35 | import qualified Data.Array.Unboxed as A | 35 | import qualified Data.Word64RangeMap.Unboxed as U |
36 | import qualified Data.Array.Unboxed as U | ||
37 | import qualified Data.Array as A | ||
36 | import SensibleDir | 38 | import SensibleDir |
37 | import System.FilePath | 39 | import System.FilePath |
38 | import System.Environment | 40 | import System.Environment |
@@ -189,7 +191,7 @@ type NetCryptoHook = IOHook NetCryptoSession CryptoMessage | |||
189 | -- | Convert an id byte to it's type (in Word64 format) | 191 | -- | Convert an id byte to it's type (in Word64 format) |
190 | -- Although the type doesn't enforce it, MsgTypeArray | 192 | -- Although the type doesn't enforce it, MsgTypeArray |
191 | -- should always have 256 entries. | 193 | -- should always have 256 entries. |
192 | type MsgTypeArray = A.UArray Word8 Word64 | 194 | type MsgTypeArray = U.UArray Word8 Word64 |
193 | 195 | ||
194 | -- | Information, that may be made visible in multiple sessions, as well | 196 | -- | Information, that may be made visible in multiple sessions, as well |
195 | -- as displayed in some way to the user via mutiple views. | 197 | -- as displayed in some way to the user via mutiple views. |
@@ -302,6 +304,9 @@ data NetCryptoSession = NCrypto | |||
302 | -- The remaining fields correspond to implementation specific state -- | 304 | -- The remaining fields correspond to implementation specific state -- |
303 | -- where as the prior fields will be used in any implementation -- | 305 | -- where as the prior fields will be used in any implementation -- |
304 | , ncHooks :: TVar (Map.Map MessageType [NetCryptoHook]) | 306 | , ncHooks :: TVar (Map.Map MessageType [NetCryptoHook]) |
307 | , ncOutHooks :: RangeMap TArray | ||
308 | (TransportCrypto -> NetCryptoSession -> CryptoMessage -> IO (Either String (CryptoPacket Encrypted))) | ||
309 | TVar | ||
305 | , ncUnrecognizedHook :: TVar (MessageType -> NetCryptoHook) | 310 | , ncUnrecognizedHook :: TVar (MessageType -> NetCryptoHook) |
306 | , ncIdleEventHooks :: TVar [(Int,NetCryptoSession -> IO ())] | 311 | , ncIdleEventHooks :: TVar [(Int,NetCryptoSession -> IO ())] |
307 | , ncIncomingTypeArray :: TVar MsgTypeArray | 312 | , ncIncomingTypeArray :: TVar MsgTypeArray |
@@ -315,7 +320,7 @@ data NetCryptoSession = NCrypto | |||
315 | -- always escapes. | 320 | -- always escapes. |
316 | -- | 321 | -- |
317 | -- Currently, the values at these indices are ignored. | 322 | -- Currently, the values at these indices are ignored. |
318 | , ncOutgoingIdMap :: RangeMap TArray Word8 TVar | 323 | , ncOutgoingIdMap :: U.RangeMap TArray Word8 TVar |
319 | -- ^ used to lookup the outgoing id for a type when sending an outoing message | 324 | -- ^ used to lookup the outgoing id for a type when sending an outoing message |
320 | , ncOutgoingIdMapEscapedLossy :: TVar (A.Array Word8 Word8) | 325 | , ncOutgoingIdMapEscapedLossy :: TVar (A.Array Word8 Word8) |
321 | -- ^ mapping of secondary id, when primary id is 0xC7 | 326 | -- ^ mapping of secondary id, when primary id is 0xC7 |
@@ -363,7 +368,7 @@ data NetCryptoSession = NCrypto | |||
363 | , ncOutgoingQueue :: TVar | 368 | , ncOutgoingQueue :: TVar |
364 | (UponHandshake | 369 | (UponHandshake |
365 | (PQ.PacketOutQueue | 370 | (PQ.PacketOutQueue |
366 | (State,Nonce24,RangeMap TArray Word8 TVar) | 371 | (State,Nonce24,U.RangeMap TArray Word8 TVar) |
367 | CryptoMessage | 372 | CryptoMessage |
368 | (CryptoPacket Encrypted) | 373 | (CryptoPacket Encrypted) |
369 | CryptoData)) | 374 | CryptoData)) |
@@ -495,7 +500,7 @@ type XMessage = CryptoMessage -- todo | |||
495 | -- rangemap <- readTVar (ncOutgoingIdMap session) | 500 | -- rangemap <- readTVar (ncOutgoingIdMap session) |
496 | -- return (state,n24,rangemap) | 501 | -- return (state,n24,rangemap) |
497 | 502 | ||
498 | ncToWire :: STM (State,Nonce24,RangeMap TArray Word8 TVar) | 503 | ncToWire :: STM (State,Nonce24,U.RangeMap TArray Word8 TVar) |
499 | -> Word32{- packet number we expect to recieve -} | 504 | -> Word32{- packet number we expect to recieve -} |
500 | -> Word32{- buffer_end -} | 505 | -> Word32{- buffer_end -} |
501 | -> Word32{- packet number -} | 506 | -> Word32{- packet number -} |
@@ -512,7 +517,7 @@ ncToWire getState seqno bufend pktno msg = do | |||
512 | (state,n24,msgOutMapVar) <- getState | 517 | (state,n24,msgOutMapVar) <- getState |
513 | -- msgOutMap <- readTVar msgOutMapVar | 518 | -- msgOutMap <- readTVar msgOutMapVar |
514 | result1 <- dtrace XNetCrypto ("lookupInRangeMap typ64=" ++ show typ64 ++ " " ++ show typ ++ show msg) | 519 | result1 <- dtrace XNetCrypto ("lookupInRangeMap typ64=" ++ show typ64 ++ " " ++ show typ ++ show msg) |
515 | $ lookupInRangeMap typ64 msgOutMapVar | 520 | $ U.lookupInRangeMap typ64 msgOutMapVar |
516 | case result1 of -- msgOutMapLookup typ64 msgOutMap of | 521 | case result1 of -- msgOutMapLookup typ64 msgOutMap of |
517 | Nothing -> dtrace XNetCrypto "lookupInRangeMap gave Nothing!" $ return Nothing | 522 | Nothing -> dtrace XNetCrypto "lookupInRangeMap gave Nothing!" $ return Nothing |
518 | Just outid -> dtrace XNetCrypto ("encrypting packet with Nonce: " ++ show n24) $ do | 523 | Just outid -> dtrace XNetCrypto ("encrypting packet with Nonce: " ++ show n24) $ do |
@@ -589,18 +594,26 @@ freshCryptoSession sessions | |||
589 | ncIdleEventHooks0 <- newTVar (defaultIdleEventHooks sessions) | 594 | ncIdleEventHooks0 <- newTVar (defaultIdleEventHooks sessions) |
590 | ncIncomingTypeArray0 <- newTVar (msgTypeArray sessions) | 595 | ncIncomingTypeArray0 <- newTVar (msgTypeArray sessions) |
591 | let idMap = foldl (\mp (x,y) -> W64.insert x y mp) W64.empty (zip [0..255] [0..255]) | 596 | let idMap = foldl (\mp (x,y) -> W64.insert x y mp) W64.empty (zip [0..255] [0..255]) |
592 | (ncOutgoingIdMap0,lossyEscapeIdMap,losslessEscapeIdMap) <- do | 597 | (ncOutgoingIdMap0,lossyEscapeIdMap,losslessEscapeIdMap,ncOutHooks0) <- do |
593 | idmap <- emptySTMRangeMap | 598 | idmap <- U.emptySTMRangeMap |
594 | insertArrayAt idmap 0 (A.listArray (0,255) [0 .. 255]) | 599 | U.insertArrayAt idmap 0 (U.listArray (0,255) [0 .. 255]) |
595 | -- the 2 escape ranges are adjacent, so put them in one array: | 600 | -- the 2 escape ranges are adjacent, so put them in one array: |
596 | insertArrayAt idmap 512 (A.listArray (512,1023) ( replicate 256 0xC7 -- lossy escaped | 601 | U.insertArrayAt idmap 512 (U.listArray (512,1023) ( replicate 256 0xC7 -- lossy escaped |
597 | ++ replicate 256 0x63 -- lossless escapped | 602 | ++ replicate 256 0x63 -- lossless escapped |
598 | )) | 603 | )) |
599 | -- lossless as separate range could have been done: | 604 | -- lossless as separate range could have been done: |
600 | -- > insertArrayAt idmap 768 (A.listArray (768,1023) (replicate 256 0x63)) | 605 | -- > insertArrayAt idmap 768 (A.listArray (768,1023) (replicate 256 0x63)) |
601 | lossyEsc <- newTVar $ A.listArray (0,255) [0 .. 255] | 606 | lossyEsc <- newTVar $ U.listArray (0,255) [0 .. 255] |
602 | losslessEsc <- newTVar $ A.listArray (0,255) [0 .. 255] | 607 | losslessEsc <- newTVar $ U.listArray (0,255) [0 .. 255] |
603 | return (idmap,lossyEsc,losslessEsc) | 608 | outHooks <- emptySTMRangeMap |
609 | mapM_ ($ outHooks) -- TODO: combine into larger ranges for faster lookup | ||
610 | [ insertWhereItGoes (A.listArray (2,2) [sendKillHook]) | ||
611 | , insertWhereItGoes (A.listArray (16,16) [sendLossless{-Ping-}]) | ||
612 | , insertWhereItGoes (A.listArray (24,25) [sendOnlineHook,sendLossless{-Offline-}]) | ||
613 | , insertWhereItGoes (A.listArray (48,51) [sendNickHook,sendStatusMsgHook,sendStatusHook,sendTypingHook]) | ||
614 | , insertWhereItGoes (A.listArray (63,64) [sendMessageHook, sendMessageHook]) | ||
615 | ] | ||
616 | return (idmap,lossyEsc,losslessEsc,outHooks) | ||
604 | ncView0 <- newTVar (sessionView sessions) | 617 | ncView0 <- newTVar (sessionView sessions) |
605 | pktq <- PQ.new (inboundQueueCapacity sessions) 0 | 618 | pktq <- PQ.new (inboundQueueCapacity sessions) 0 |
606 | bufstart <- newTVar 0 | 619 | bufstart <- newTVar 0 |
@@ -645,6 +658,7 @@ freshCryptoSession sessions | |||
645 | , ncSessionSecret = newsession | 658 | , ncSessionSecret = newsession |
646 | , ncSockAddr = HaveDHTKey addr | 659 | , ncSockAddr = HaveDHTKey addr |
647 | , ncHooks = ncHooks0 | 660 | , ncHooks = ncHooks0 |
661 | , ncOutHooks = ncOutHooks0 | ||
648 | , ncUnrecognizedHook = ncUnrecognizedHook0 | 662 | , ncUnrecognizedHook = ncUnrecognizedHook0 |
649 | , ncIdleEventHooks = ncIdleEventHooks0 | 663 | , ncIdleEventHooks = ncIdleEventHooks0 |
650 | , ncAllSessions = sessions | 664 | , ncAllSessions = sessions |
@@ -677,13 +691,13 @@ freshCryptoSession sessions | |||
677 | HaveHandshake pktoq -> return (runUponHandshake netCryptoSession0 addr pktoq) | 691 | HaveHandshake pktoq -> return (runUponHandshake netCryptoSession0 addr pktoq) |
678 | return (myhandshake,maybeLaunchMissles) | 692 | return (myhandshake,maybeLaunchMissles) |
679 | 693 | ||
680 | type NetCryptoOutQueue = PQ.PacketOutQueue (State,Nonce24,RangeMap TArray Word8 TVar) | 694 | type NetCryptoOutQueue = PQ.PacketOutQueue (State,Nonce24,U.RangeMap TArray Word8 TVar) |
681 | CryptoMessage | 695 | CryptoMessage |
682 | (CryptoPacket Encrypted) | 696 | (CryptoPacket Encrypted) |
683 | CryptoData | 697 | CryptoData |
684 | 698 | ||
685 | createNetCryptoOutQueue :: NetCryptoSessions -> SecretKey -> PublicKey -> PacketQueue CryptoData | 699 | createNetCryptoOutQueue :: NetCryptoSessions -> SecretKey -> PublicKey -> PacketQueue CryptoData |
686 | -> TVar Nonce24 -> RangeMap TArray Word8 TVar -> STM (UponHandshake NetCryptoOutQueue) | 700 | -> TVar Nonce24 -> U.RangeMap TArray Word8 TVar -> STM (UponHandshake NetCryptoOutQueue) |
687 | createNetCryptoOutQueue sessions newsession theirSessionKey pktq ncMyPacketNonce0 ncOutgoingIdMap0 = do | 701 | createNetCryptoOutQueue sessions newsession theirSessionKey pktq ncMyPacketNonce0 ncOutgoingIdMap0 = do |
688 | let crypto = transportCrypto sessions | 702 | let crypto = transportCrypto sessions |
689 | let toWireIO = do | 703 | let toWireIO = do |
@@ -1084,7 +1098,7 @@ sessionPacketH sessions addrRaw (CryptoPacket nonce16 encrypted) = do | |||
1084 | Nothing -> return () | 1098 | Nothing -> return () |
1085 | msgTypes <- atomically $ readTVar ncIncomingTypeArray | 1099 | msgTypes <- atomically $ readTVar ncIncomingTypeArray |
1086 | let msgTyp = cd ^. messageType | 1100 | let msgTyp = cd ^. messageType |
1087 | msgTypMapped64 = msgTypes A.! fromEnum8 (msgID cm) | 1101 | msgTypMapped64 = msgTypes U.! fromEnum8 (msgID cm) |
1088 | msgTypMapped = fromWord64 $ msgTypMapped64 | 1102 | msgTypMapped = fromWord64 $ msgTypMapped64 |
1089 | isLossy (GrpMsg KnownLossy _) = True | 1103 | isLossy (GrpMsg KnownLossy _) = True |
1090 | isLossy (Msg mid) | lossyness mid == Lossy = True | 1104 | isLossy (Msg mid) | lossyness mid == Lossy = True |
@@ -1116,7 +1130,7 @@ runCryptoHook session@(NCrypto {ncState, ncHooks,ncSessionSecret,ncTheirSessionP | |||
1116 | flip fix (cm,hookmap) $ \lookupAgain (cm,hookmap) -> do | 1130 | flip fix (cm,hookmap) $ \lookupAgain (cm,hookmap) -> do |
1117 | msgTypes <- atomically $ readTVar ncIncomingTypeArray | 1131 | msgTypes <- atomically $ readTVar ncIncomingTypeArray |
1118 | let msgTyp = cm ^. messageType | 1132 | let msgTyp = cm ^. messageType |
1119 | msgTypMapped64 = msgTypes A.! fromEnum8 (msgID cm) | 1133 | msgTypMapped64 = msgTypes U.! fromEnum8 (msgID cm) |
1120 | msgTypMapped = fromWord64 $ msgTypMapped64 | 1134 | msgTypMapped = fromWord64 $ msgTypMapped64 |
1121 | if msgTypMapped64 == 0 | 1135 | if msgTypMapped64 == 0 |
1122 | then return Nothing | 1136 | then return Nothing |
@@ -1147,8 +1161,8 @@ runCryptoHook session@(NCrypto {ncState, ncHooks,ncSessionSecret,ncTheirSessionP | |||
1147 | -- | construct a 'MsgTypeArray' for specified types, using their known common positions | 1161 | -- | construct a 'MsgTypeArray' for specified types, using their known common positions |
1148 | -- in the MessageId space if they have such a thing. | 1162 | -- in the MessageId space if they have such a thing. |
1149 | mkMsgTypes :: [MessageType] -> MsgTypeArray | 1163 | mkMsgTypes :: [MessageType] -> MsgTypeArray |
1150 | mkMsgTypes msgs = let zeros = A.listArray (0,255) (replicate 256 0) | 1164 | mkMsgTypes msgs = let zeros = U.listArray (0,255) (replicate 256 0) |
1151 | in zeros A.// map (\x -> (toIndex x,toWord64 x)) msgs | 1165 | in zeros U.// map (\x -> (toIndex x,toWord64 x)) msgs |
1152 | where | 1166 | where |
1153 | toIndex (Msg mid) = fromIntegral . fromEnum $ mid | 1167 | toIndex (Msg mid) = fromIntegral . fromEnum $ mid |
1154 | toIndex (GrpMsg KnownLossless nam) = 0x63 -- fromEnum MESSAGE_GROUPCHAT | 1168 | toIndex (GrpMsg KnownLossless nam) = 0x63 -- fromEnum MESSAGE_GROUPCHAT |
@@ -1189,10 +1203,10 @@ pattern PACKET_ID_LOSSY_RANGE_SIZE = 63 | |||
1189 | -- The first parameter is a function which is applied to get the values | 1203 | -- The first parameter is a function which is applied to get the values |
1190 | -- for keys of unknown nature. Could be either 'id' or 'const 0' | 1204 | -- for keys of unknown nature. Could be either 'id' or 'const 0' |
1191 | allMsgTypes :: (Word64 -> Word64) -> MsgTypeArray | 1205 | allMsgTypes :: (Word64 -> Word64) -> MsgTypeArray |
1192 | allMsgTypes fDefault = A.listArray (minBound,maxBound) (0:knownMsgs) | 1206 | allMsgTypes fDefault = U.listArray (minBound,maxBound) (0:knownMsgs) |
1193 | where | 1207 | |
1194 | knownMsgs :: [Word64] | 1208 | knownMsgs :: [Word64] |
1195 | knownMsgs = | 1209 | knownMsgs = |
1196 | concat [ map (fromIntegral . fromEnum) [ PacketRequest .. KillPacket ] | 1210 | concat [ map (fromIntegral . fromEnum) [ PacketRequest .. KillPacket ] |
1197 | , map (const 0) [ 3 .. 15 ] -- UnspecifiedPacket | 1211 | , map (const 0) [ 3 .. 15 ] -- UnspecifiedPacket |
1198 | , map (const 0) [ 16 .. 23 ] -- MessengerLoseless | 1212 | , map (const 0) [ 16 .. 23 ] -- MessengerLoseless |
@@ -1236,6 +1250,10 @@ sendPing crypto session = do | |||
1236 | sendOnline :: TransportCrypto -> NetCryptoSession -> IO (Either String (CryptoPacket Encrypted)) | 1250 | sendOnline :: TransportCrypto -> NetCryptoSession -> IO (Either String (CryptoPacket Encrypted)) |
1237 | sendOnline crypto session = do | 1251 | sendOnline crypto session = do |
1238 | let cm=OneByte ONLINE | 1252 | let cm=OneByte ONLINE |
1253 | sendOnlineHook crypto session cm | ||
1254 | |||
1255 | sendOnlineHook :: TransportCrypto -> NetCryptoSession -> CryptoMessage -> IO (Either String (CryptoPacket Encrypted)) | ||
1256 | sendOnlineHook crypto session cm = do | ||
1239 | addMsgToLastN False (cm ^. messageType) session (Out cm) | 1257 | addMsgToLastN False (cm ^. messageType) session (Out cm) |
1240 | result <- sendCrypto crypto session (return ()) (OneByte ONLINE) | 1258 | result <- sendCrypto crypto session (return ()) (OneByte ONLINE) |
1241 | -- double this packet | 1259 | -- double this packet |
@@ -1252,49 +1270,61 @@ sendOnline crypto session = do | |||
1252 | sendOffline :: TransportCrypto -> NetCryptoSession -> IO (Either String (CryptoPacket Encrypted)) | 1270 | sendOffline :: TransportCrypto -> NetCryptoSession -> IO (Either String (CryptoPacket Encrypted)) |
1253 | sendOffline crypto session = do | 1271 | sendOffline crypto session = do |
1254 | let cm=OneByte OFFLINE | 1272 | let cm=OneByte OFFLINE |
1273 | sendLossless crypto session cm | ||
1274 | |||
1275 | sendLossless :: TransportCrypto -> NetCryptoSession -> CryptoMessage -> IO (Either String (CryptoPacket Encrypted)) | ||
1276 | sendLossless crypto session cm = do | ||
1255 | addMsgToLastN False (cm ^. messageType) session (Out cm) | 1277 | addMsgToLastN False (cm ^. messageType) session (Out cm) |
1256 | sendCrypto crypto session (return ()) (OneByte OFFLINE) | 1278 | sendCrypto crypto session (return ()) (OneByte OFFLINE) |
1257 | 1279 | ||
1280 | sendLossy :: TransportCrypto -> NetCryptoSession -> CryptoMessage -> IO (Either String (CryptoPacket Encrypted)) | ||
1281 | sendLossy crypto session cm = sendCryptoLossy crypto session (return ()) cm | ||
1258 | 1282 | ||
1259 | sendKill :: TransportCrypto -> NetCryptoSession -> IO (Either String (CryptoPacket Encrypted)) | 1283 | sendKill :: TransportCrypto -> NetCryptoSession -> IO (Either String (CryptoPacket Encrypted)) |
1260 | sendKill crypto session = do | 1284 | sendKill crypto session = do |
1261 | let cm=OneByte KillPacket | 1285 | let cm=OneByte KillPacket |
1286 | sendKillHook crypto session cm | ||
1287 | |||
1288 | sendKillHook :: TransportCrypto -> NetCryptoSession -> CryptoMessage -> IO (Either String (CryptoPacket Encrypted)) | ||
1289 | sendKillHook crypto session cm = sendCryptoLossy crypto session (destroySession session) cm | ||
1290 | |||
1291 | sendCryptoLossy :: TransportCrypto -> NetCryptoSession -> (IO ()) -> CryptoMessage -> IO (Either String (CryptoPacket Encrypted)) | ||
1292 | sendCryptoLossy crypto session updateLocal cm = do | ||
1262 | mbOutQ <- atomically $ readTVar (ncOutgoingQueue session) | 1293 | mbOutQ <- atomically $ readTVar (ncOutgoingQueue session) |
1263 | case mbOutQ of | 1294 | case mbOutQ of |
1264 | NeedHandshake -> do | 1295 | NeedHandshake -> do |
1265 | let errmsg="NetCrypto NOT SENDING Kill packet (sessionid: " ++ show (ncSessionId session) ++ ") since no handshake yet" | 1296 | let errmsg = "Error sending lossy packet! (sessionid: " ++ show (ncSessionId session) ++ ") Need the Handshake first!" |
1266 | dput XNetCrypto errmsg | 1297 | updateLocal |
1267 | dput XNetCrypto $ "Destroying session anyway" | ||
1268 | destroySession session | ||
1269 | return (Left errmsg) | 1298 | return (Left errmsg) |
1270 | HaveHandshake outq -> do | 1299 | HaveHandshake outq -> do |
1271 | dput XNetCrypto $ "NetCrypto sending Kill packet (sessionid: " ++ show (ncSessionId session) ++ ")" | ||
1272 | getOutGoingParam <- PQ.readyOutGoing outq | 1300 | getOutGoingParam <- PQ.readyOutGoing outq |
1273 | mbPkt <- atomically $ PQ.peekPacket getOutGoingParam outq cm | 1301 | mbPkt <- atomically $ PQ.peekPacket getOutGoingParam outq cm |
1274 | case mbPkt of | 1302 | case mbPkt of |
1275 | Nothing -> do | 1303 | Nothing -> do |
1276 | let errmsg = "Error sending kill packet! (sessionid: " ++ show (ncSessionId session) ++ ")" | 1304 | let errmsg = "Error sending lossy packet! (sessionid: " ++ show (ncSessionId session) ++ ") " ++ show cm |
1277 | dput XNetCrypto errmsg | 1305 | updateLocal |
1278 | dput XNetCrypto $ "Destroying session anyway" | ||
1279 | Right <$> destroySession session | ||
1280 | return (Left errmsg) | 1306 | return (Left errmsg) |
1281 | Just (pkt,seqno) -> do | 1307 | Just (pkt,seqno) -> do |
1282 | case (ncSockAddr session) of | 1308 | case (ncSockAddr session) of |
1283 | NeedDHTKey -> do | 1309 | NeedDHTKey -> do |
1284 | let errmsg= "NetCrypto NOT SENDING Kill packet (sessionid: " ++ show (ncSessionId session) ++ ") since no DHTkey(sockaddr) yet" | 1310 | let errmsg= "NetCrypto NOT SENDING Lossy packet (sessionid: " ++ show (ncSessionId session) ++ ") since no DHTkey(sockaddr) yet" |
1285 | dput XNetCrypto errmsg | 1311 | updateLocal |
1286 | dput XNetCrypto $ "Destroying session anyway" | ||
1287 | Right <$> destroySession session | ||
1288 | return (Left errmsg) | 1312 | return (Left errmsg) |
1289 | HaveDHTKey saddr -> do | 1313 | HaveDHTKey saddr -> do |
1290 | sendSessionPacket (ncAllSessions session) saddr pkt | 1314 | sendSessionPacket (ncAllSessions session) saddr pkt |
1291 | dput XNetCrypto $ "sent kill packet (sessionid: " ++ show (ncSessionId session) ++ ")... now destroying session..." | 1315 | dput XNetCrypto $ "sent lossy packet (sessionid: " ++ show (ncSessionId session) ++ ") " ++ take 40 (show cm) ++ "..." |
1292 | destroySession session | 1316 | updateLocal |
1293 | return (Right pkt) | 1317 | return (Right pkt) |
1294 | 1318 | ||
1295 | setNick :: TransportCrypto -> NetCryptoSession -> ByteString -> IO (Either String (CryptoPacket Encrypted)) | 1319 | setNick :: TransportCrypto -> NetCryptoSession -> ByteString -> IO (Either String (CryptoPacket Encrypted)) |
1296 | setNick crypto session nick = do | 1320 | setNick crypto session nick = do |
1321 | let cm = UpToN NICKNAME nick | ||
1322 | sendNickHook crypto session cm | ||
1323 | |||
1324 | sendNickHook :: TransportCrypto -> NetCryptoSession -> CryptoMessage -> IO (Either String (CryptoPacket Encrypted)) | ||
1325 | sendNickHook crypto session cm = do | ||
1297 | let Just (_,maxlen) = msgSizeParam NICKNAME | 1326 | let Just (_,maxlen) = msgSizeParam NICKNAME |
1327 | let nick = msgBytes cm | ||
1298 | if B.length nick > maxlen | 1328 | if B.length nick > maxlen |
1299 | then return (Left $ "nickname must not exceed " ++ show maxlen ++ " bytes.") | 1329 | then return (Left $ "nickname must not exceed " ++ show maxlen ++ " bytes.") |
1300 | else do | 1330 | else do |
@@ -1302,16 +1332,20 @@ setNick crypto session nick = do | |||
1302 | let viewVar = ncView session | 1332 | let viewVar = ncView session |
1303 | view <- readTVar viewVar | 1333 | view <- readTVar viewVar |
1304 | writeTVar (svNick view) nick | 1334 | writeTVar (svNick view) nick |
1305 | let cm = UpToN NICKNAME nick | ||
1306 | addMsgToLastN False (cm ^. messageType) session (Out cm) | 1335 | addMsgToLastN False (cm ^. messageType) session (Out cm) |
1307 | sendCrypto crypto session updateLocal cm | 1336 | sendCrypto crypto session updateLocal cm |
1308 | 1337 | ||
1309 | setTyping :: TransportCrypto -> NetCryptoSession -> TypingStatus -> IO (Either String (CryptoPacket Encrypted)) | 1338 | setTyping :: TransportCrypto -> NetCryptoSession -> TypingStatus -> IO (Either String (CryptoPacket Encrypted)) |
1310 | setTyping crypto session status = do | 1339 | setTyping crypto session status = do |
1340 | let cm = TwoByte TYPING (fromEnum8 status) | ||
1341 | sendTypingHook crypto session cm | ||
1342 | |||
1343 | sendTypingHook:: TransportCrypto -> NetCryptoSession -> CryptoMessage -> IO (Either String (CryptoPacket Encrypted)) | ||
1344 | sendTypingHook crypto session cm = do | ||
1345 | let status = toEnum8 (msgByte cm) | ||
1311 | let updateLocal = do | 1346 | let updateLocal = do |
1312 | view <- readTVar (ncView session) | 1347 | view <- readTVar (ncView session) |
1313 | writeTVar (svTyping view) status | 1348 | writeTVar (svTyping view) status |
1314 | let cm = TwoByte TYPING (fromEnum8 status) | ||
1315 | addMsgToLastN False (cm ^. messageType) session (Out cm) | 1349 | addMsgToLastN False (cm ^. messageType) session (Out cm) |
1316 | sendCrypto crypto session updateLocal cm | 1350 | sendCrypto crypto session updateLocal cm |
1317 | 1351 | ||
@@ -1325,36 +1359,51 @@ setNoSpam crypto session mbnospam = do | |||
1325 | 1359 | ||
1326 | setStatus :: TransportCrypto -> NetCryptoSession -> UserStatus -> IO (Either String (CryptoPacket Encrypted)) | 1360 | setStatus :: TransportCrypto -> NetCryptoSession -> UserStatus -> IO (Either String (CryptoPacket Encrypted)) |
1327 | setStatus crypto session status = do | 1361 | setStatus crypto session status = do |
1362 | let cm = TwoByte USERSTATUS (fromEnum8 status) | ||
1363 | sendStatusHook crypto session cm | ||
1364 | |||
1365 | sendStatusHook :: TransportCrypto -> NetCryptoSession -> CryptoMessage -> IO (Either String (CryptoPacket Encrypted)) | ||
1366 | sendStatusHook crypto session cm = do | ||
1367 | let status = toEnum8 (msgByte cm) | ||
1328 | let updateLocal = do | 1368 | let updateLocal = do |
1329 | view <- readTVar (ncView session) | 1369 | view <- readTVar (ncView session) |
1330 | writeTVar (svStatus view) status | 1370 | writeTVar (svStatus view) status |
1331 | let cm = TwoByte USERSTATUS (fromEnum8 status) | ||
1332 | addMsgToLastN False (cm ^. messageType) session (Out cm) | 1371 | addMsgToLastN False (cm ^. messageType) session (Out cm) |
1333 | sendCrypto crypto session updateLocal cm | 1372 | sendCrypto crypto session updateLocal cm |
1334 | 1373 | ||
1335 | setStatusMsg :: TransportCrypto -> NetCryptoSession -> ByteString -> IO (Either String (CryptoPacket Encrypted)) | 1374 | setStatusMsg :: TransportCrypto -> NetCryptoSession -> ByteString -> IO (Either String (CryptoPacket Encrypted)) |
1336 | setStatusMsg crypto session msg = do | 1375 | setStatusMsg crypto session msg = do |
1376 | let cm = UpToN STATUSMESSAGE msg | ||
1377 | sendStatusMsgHook crypto session cm | ||
1378 | |||
1379 | sendStatusMsgHook :: TransportCrypto -> NetCryptoSession -> CryptoMessage -> IO (Either String (CryptoPacket Encrypted)) | ||
1380 | sendStatusMsgHook crypto session cm = do | ||
1337 | let Just (_,maxlen) = msgSizeParam STATUSMESSAGE | 1381 | let Just (_,maxlen) = msgSizeParam STATUSMESSAGE |
1382 | let msg = msgBytes cm | ||
1338 | if B.length msg > maxlen | 1383 | if B.length msg > maxlen |
1339 | then return (Left $ "status message must not exceed " ++ show maxlen ++ " bytes.") | 1384 | then return (Left $ "status message must not exceed " ++ show maxlen ++ " bytes.") |
1340 | else do | 1385 | else do |
1341 | let updateLocal = do | 1386 | let updateLocal = do |
1342 | view <- readTVar (ncView session) | 1387 | view <- readTVar (ncView session) |
1343 | writeTVar (svStatusMsg view) msg | 1388 | writeTVar (svStatusMsg view) msg |
1344 | let cm = UpToN STATUSMESSAGE msg | ||
1345 | addMsgToLastN False (cm ^. messageType) session (Out cm) | 1389 | addMsgToLastN False (cm ^. messageType) session (Out cm) |
1346 | sendCrypto crypto session updateLocal cm | 1390 | sendCrypto crypto session updateLocal cm |
1347 | 1391 | ||
1348 | sendChatMsg :: TransportCrypto -> NetCryptoSession -> ByteString -> IO (Either String (CryptoPacket Encrypted)) | 1392 | sendChatMsg :: TransportCrypto -> NetCryptoSession -> ByteString -> IO (Either String (CryptoPacket Encrypted)) |
1349 | sendChatMsg crypto session msg = do | 1393 | sendChatMsg crypto session msg = do |
1394 | let cm = UpToN MESSAGE msg | ||
1395 | sendMessageHook crypto session cm | ||
1396 | |||
1397 | sendMessageHook :: TransportCrypto -> NetCryptoSession -> CryptoMessage -> IO (Either String (CryptoPacket Encrypted)) | ||
1398 | sendMessageHook crypto session cm = do | ||
1350 | let Just (_,maxlen) = msgSizeParam MESSAGE | 1399 | let Just (_,maxlen) = msgSizeParam MESSAGE |
1400 | let msg = msgBytes cm | ||
1351 | if B.length msg > maxlen | 1401 | if B.length msg > maxlen |
1352 | then return (Left $ "status message must not exceed " ++ show maxlen ++ " bytes.") | 1402 | then return (Left $ "status message must not exceed " ++ show maxlen ++ " bytes.") |
1353 | else do | 1403 | else do |
1354 | let updateLocal = do | 1404 | let updateLocal = do |
1355 | view <- readTVar (ncView session) | 1405 | view <- readTVar (ncView session) |
1356 | writeTVar (svStatusMsg view) msg | 1406 | writeTVar (svStatusMsg view) msg |
1357 | let cm = UpToN MESSAGE msg | ||
1358 | addMsgToLastN False (cm ^. messageType) session (Out cm) | 1407 | addMsgToLastN False (cm ^. messageType) session (Out cm) |
1359 | sendCrypto crypto session updateLocal cm | 1408 | sendCrypto crypto session updateLocal cm |
1360 | 1409 | ||