diff options
-rw-r--r-- | src/Crypto/Tox.hs | 21 | ||||
-rw-r--r-- | src/Data/PacketQueue.hs | 93 | ||||
-rw-r--r-- | src/Network/Tox/Crypto/Handlers.hs | 73 | ||||
-rw-r--r-- | src/Network/Tox/Crypto/Transport.hs | 16 |
4 files changed, 195 insertions, 8 deletions
diff --git a/src/Crypto/Tox.hs b/src/Crypto/Tox.hs index 18cdb5d2..624da233 100644 --- a/src/Crypto/Tox.hs +++ b/src/Crypto/Tox.hs | |||
@@ -34,11 +34,13 @@ module Crypto.Tox | |||
34 | , decodePlain | 34 | , decodePlain |
35 | -- , computeSharedSecret | 35 | -- , computeSharedSecret |
36 | , lookupSharedSecret | 36 | , lookupSharedSecret |
37 | , lookupNonceFunction | ||
37 | , encrypt | 38 | , encrypt |
38 | , decrypt | 39 | , decrypt |
39 | , Nonce8(..) | 40 | , Nonce8(..) |
40 | , Nonce24(..) | 41 | , Nonce24(..) |
41 | , incrementNonce24 | 42 | , incrementNonce24 |
43 | , nonce24ToWord16 | ||
42 | , addtoNonce24 | 44 | , addtoNonce24 |
43 | , Nonce32(..) | 45 | , Nonce32(..) |
44 | , getRemainingEncrypted | 46 | , getRemainingEncrypted |
@@ -300,10 +302,19 @@ lookupSharedSecret :: TransportCrypto -> SecretKey -> PublicKey -> Nonce24 -> IO | |||
300 | lookupSharedSecret crypto sk recipient nonce | 302 | lookupSharedSecret crypto sk recipient nonce |
301 | = ($ nonce) <$> lookupNonceFunction crypto sk recipient | 303 | = ($ nonce) <$> lookupNonceFunction crypto sk recipient |
302 | 304 | ||
305 | {-# INLINE lookupNonceFunction #-} | ||
303 | lookupNonceFunction :: TransportCrypto -> SecretKey -> PublicKey -> IO (Nonce24 -> State) | 306 | lookupNonceFunction :: TransportCrypto -> SecretKey -> PublicKey -> IO (Nonce24 -> State) |
304 | lookupNonceFunction TransportCrypto{secretsCache} sk recipient = do | 307 | lookupNonceFunction c@(TransportCrypto{secretsCache}) sk recipient = do |
305 | now <- getPOSIXTime | 308 | now <- getPOSIXTime |
306 | atomically $ do | 309 | atomically $ lookupNonceFunctionSTM now c sk recipient |
310 | |||
311 | {-# INLINE lookupNonceFunctionSTM #-} | ||
312 | -- | This version of 'lookupNonceFunction' is STM instead of IO, this means if some later part of | ||
313 | -- of the transaction fails, we may end up forgoing a computation that could have been cached. | ||
314 | -- Use with care. In most circumstances you probably want 'lookupNonceFunction'. It also commits | ||
315 | -- us to using TVars to store the cache. | ||
316 | lookupNonceFunctionSTM :: POSIXTime -> TransportCrypto -> SecretKey -> PublicKey -> STM (Nonce24 -> State) | ||
317 | lookupNonceFunctionSTM now TransportCrypto{secretsCache} sk recipient = do | ||
307 | mm <- readTVar $ sharedSecret secretsCache | 318 | mm <- readTVar $ sharedSecret secretsCache |
308 | case MM.lookup' recipient mm of | 319 | case MM.lookup' recipient mm of |
309 | Nothing -> do | 320 | Nothing -> do |
@@ -332,7 +343,10 @@ hsalsa20 k n = BA.append a b | |||
332 | 343 | ||
333 | 344 | ||
334 | newtype Nonce24 = Nonce24 ByteString | 345 | newtype Nonce24 = Nonce24 ByteString |
335 | deriving (Eq, Ord, ByteArrayAccess,Data) | 346 | deriving (Eq, Ord, ByteArrayAccess, Data) |
347 | |||
348 | nonce24ToWord16 :: Nonce24 -> Word16 | ||
349 | nonce24ToWord16 (Nonce24 n24) = fromIntegral (B.index n24 23) + 256 * fromIntegral (B.index n24 22) | ||
336 | 350 | ||
337 | addtoNonce24 :: Nonce24 -> Word -> IO Nonce24 | 351 | addtoNonce24 :: Nonce24 -> Word -> IO Nonce24 |
338 | addtoNonce24 (Nonce24 n24) n = Nonce24 <$> BA.copy n24 init | 352 | addtoNonce24 (Nonce24 n24) n = Nonce24 <$> BA.copy n24 init |
@@ -376,6 +390,7 @@ addtoNonce24 (Nonce24 n24) n = Nonce24 <$> BA.copy n24 init | |||
376 | pokeElemOff ptr 5 $ tBE32 (W# sum_) | 390 | pokeElemOff ptr 5 $ tBE32 (W# sum_) |
377 | init _ = error "incrementNonce24: I only support 64 and 32 bits" | 391 | init _ = error "incrementNonce24: I only support 64 and 32 bits" |
378 | 392 | ||
393 | {-# INLINE incrementNonce24 #-} | ||
379 | incrementNonce24 :: Nonce24 -> IO Nonce24 | 394 | incrementNonce24 :: Nonce24 -> IO Nonce24 |
380 | incrementNonce24 nonce24 = addtoNonce24 nonce24 1 | 395 | incrementNonce24 nonce24 = addtoNonce24 nonce24 1 |
381 | 396 | ||
diff --git a/src/Data/PacketQueue.hs b/src/Data/PacketQueue.hs index b349bf4b..927d6c53 100644 --- a/src/Data/PacketQueue.hs +++ b/src/Data/PacketQueue.hs | |||
@@ -3,12 +3,19 @@ | |||
3 | -- be stored out of order, but from which they are extracted in the proper | 3 | -- be stored out of order, but from which they are extracted in the proper |
4 | -- sequence. | 4 | -- sequence. |
5 | {-# LANGUAGE NamedFieldPuns #-} | 5 | {-# LANGUAGE NamedFieldPuns #-} |
6 | {-# LANGUAGE FlexibleContexts #-} | ||
6 | module Data.PacketQueue | 7 | module Data.PacketQueue |
7 | ( PacketQueue | 8 | ( PacketQueue |
8 | , new | 9 | , new |
9 | , dequeue | 10 | , dequeue |
10 | , enqueue | 11 | , enqueue |
11 | , observeOutOfBand | 12 | , observeOutOfBand |
13 | , PacketOutQueue | ||
14 | , newOutGoing | ||
15 | , tryAppendQueueOutgoing | ||
16 | , dequeueOutgoing | ||
17 | , mapOutGoing | ||
18 | , OutGoingResult(..) | ||
12 | ) where | 19 | ) where |
13 | 20 | ||
14 | import Control.Concurrent.STM | 21 | import Control.Concurrent.STM |
@@ -21,7 +28,7 @@ data PacketQueue a = PacketQueue | |||
21 | { pktq :: TArray Word32 (Maybe a) | 28 | { pktq :: TArray Word32 (Maybe a) |
22 | , seqno :: TVar Word32 | 29 | , seqno :: TVar Word32 |
23 | , qsize :: Word32 | 30 | , qsize :: Word32 |
24 | , buffend :: TVar Word32 | 31 | , buffend :: TVar Word32 -- on incoming, highest packet number handled + 1 |
25 | } | 32 | } |
26 | 33 | ||
27 | -- | Create a new PacketQueue. | 34 | -- | Create a new PacketQueue. |
@@ -77,3 +84,87 @@ enqueue PacketQueue{ pktq, seqno, qsize, buffend } no x = do | |||
77 | 84 | ||
78 | -- lookup :: PacketQueue a -> Word32 -> STM (Maybe a) | 85 | -- lookup :: PacketQueue a -> Word32 -> STM (Maybe a) |
79 | -- lookup PacketQueue{ pktq, seqno, qsize } no = _todo | 86 | -- lookup PacketQueue{ pktq, seqno, qsize } no = _todo |
87 | |||
88 | ----------------------------------------------------- | ||
89 | -- * PacketOutQueue | ||
90 | -- | ||
91 | |||
92 | data PacketOutQueue extra msg toWire fromWire = PacketOutQueue | ||
93 | { pktoInPQ :: PacketQueue fromWire -- ^ reference to the incoming 'PacketQueue' | ||
94 | , pktoOutPQ :: PacketQueue (Word32,toWire) | ||
95 | , pktoPacketNo :: TVar Word32 | ||
96 | , pktoToWireIO :: IO (STM extra) | ||
97 | , pktoToWire :: STM extra | ||
98 | -> Word32{-packet number we expect to recieve-} | ||
99 | -> Word32{- buffer_end -} | ||
100 | -> Word32{- packet number -} | ||
101 | -> msg | ||
102 | -> STM (Maybe (toWire,Word32{-next packet no-})) | ||
103 | } | ||
104 | |||
105 | mapOutGoing :: ((Word32,towire) -> Maybe (Word32,towire)) -> PacketOutQueue extra msg towire fromwire -> STM () | ||
106 | mapOutGoing f q@(PacketOutQueue { pktoOutPQ=PacketQueue{ pktq } }) = do | ||
107 | (z,n) <- getBounds pktq | ||
108 | let ff i = do | ||
109 | e <- readArray pktq i | ||
110 | writeArray pktq i (e>>=f) | ||
111 | mapM_ ff [z .. n] | ||
112 | |||
113 | newOutGoing :: PacketQueue fromwire | ||
114 | -- ^ Incoming queue | ||
115 | -> (STM io -> Word32 {-packet number we expect to recieve-} -> Word32{-buffer_end-} -> Word32{-packet number-} -> msg -> STM (Maybe (wire,Word32{-next packet no-}))) | ||
116 | -- ^ toWire callback | ||
117 | -> IO (STM io) | ||
118 | -- ^ io action to get extra parameter | ||
119 | -> Word32 -- ^ packet number of first outgoing packet | ||
120 | -> Word32 -- ^ Capacity of queue. | ||
121 | -> Word32 -- ^ Initial sequence number. | ||
122 | -> STM (PacketOutQueue io msg wire fromwire) | ||
123 | newOutGoing inq towire toWireIO num capacity seqstart = do | ||
124 | outq <- new capacity seqstart | ||
125 | numVar <- newTVar num | ||
126 | return $ PacketOutQueue | ||
127 | { pktoInPQ = inq | ||
128 | , pktoOutPQ = outq | ||
129 | , pktoPacketNo = numVar | ||
130 | , pktoToWireIO = toWireIO | ||
131 | , pktoToWire = towire | ||
132 | } | ||
133 | |||
134 | data OutGoingResult = OGSuccess | OGFull | OGEncodeFail | ||
135 | deriving (Eq,Show) | ||
136 | |||
137 | -- | Convert a message to packet format and append it to the front of a queue | ||
138 | -- used for outgoing messages. (Note that ‘front‛ usually means the higher | ||
139 | -- index in this implementation.) | ||
140 | tryAppendQueueOutgoing :: STM extra -> PacketOutQueue extra msg wire fromwire -> msg -> STM OutGoingResult | ||
141 | tryAppendQueueOutgoing getExtra q@(PacketOutQueue { pktoInPQ, pktoOutPQ, pktoPacketNo, pktoToWireIO, pktoToWire }) msg = do | ||
142 | be <- readTVar (buffend pktoOutPQ) | ||
143 | let i = be `mod` (qsize pktoOutPQ) | ||
144 | mbPkt <- readArray (pktq pktoOutPQ) i | ||
145 | pktno <- readTVar pktoPacketNo | ||
146 | nextno <- readTVar (seqno pktoInPQ) | ||
147 | mbWire <- pktoToWire getExtra nextno be pktno msg | ||
148 | case mbWire of | ||
149 | Just (pkt,pktno') | ||
150 | -> case mbPkt of | ||
151 | -- slot is free, insert element | ||
152 | Nothing -> do | ||
153 | modifyTVar' (buffend pktoOutPQ) (+1) | ||
154 | writeTVar pktoPacketNo $! pktno' | ||
155 | writeArray (pktq pktoOutPQ) i (Just (pktno,pkt)) | ||
156 | return OGSuccess | ||
157 | -- queue is full, block until its not | ||
158 | _ -> return OGFull | ||
159 | -- don't know how to send this message | ||
160 | Nothing -> return OGEncodeFail | ||
161 | |||
162 | dequeueOutgoing :: PacketOutQueue extra msg wire fromwire -> STM (Word32,wire) | ||
163 | dequeueOutgoing (PacketOutQueue {pktoOutPQ=PacketQueue { pktq, seqno, qsize }}) = do | ||
164 | i0 <- readTVar seqno | ||
165 | let i = i0 `mod` qsize | ||
166 | x <- maybe retry return =<< readArray pktq i | ||
167 | -- writeArray pktq i Nothing -- not cleaning | ||
168 | modifyTVar' seqno succ | ||
169 | return x | ||
170 | |||
diff --git a/src/Network/Tox/Crypto/Handlers.hs b/src/Network/Tox/Crypto/Handlers.hs index edfcb260..6a79da1b 100644 --- a/src/Network/Tox/Crypto/Handlers.hs +++ b/src/Network/Tox/Crypto/Handlers.hs | |||
@@ -1,5 +1,6 @@ | |||
1 | {-# LANGUAGE NamedFieldPuns #-} | 1 | {-# LANGUAGE NamedFieldPuns #-} |
2 | {-# LANGUAGE TupleSections #-} | 2 | {-# LANGUAGE TupleSections #-} |
3 | {-# LANGUAGE TypeOperators #-} | ||
3 | module Network.Tox.Crypto.Handlers where | 4 | module Network.Tox.Crypto.Handlers where |
4 | 5 | ||
5 | import Network.Tox.NodeId | 6 | import Network.Tox.NodeId |
@@ -22,6 +23,7 @@ import qualified Data.PacketQueue as PQ | |||
22 | ;import Data.PacketQueue (PacketQueue) | 23 | ;import Data.PacketQueue (PacketQueue) |
23 | import Data.Serialize as S | 24 | import Data.Serialize as S |
24 | import Data.Word | 25 | import Data.Word |
26 | import qualified Data.Word64Map as W64 | ||
25 | import GHC.Conc (unsafeIOToSTM) | 27 | import GHC.Conc (unsafeIOToSTM) |
26 | import qualified Data.Set as Set | 28 | import qualified Data.Set as Set |
27 | import qualified Data.Array.Unboxed as A | 29 | import qualified Data.Array.Unboxed as A |
@@ -32,6 +34,7 @@ import System.Environment | |||
32 | import System.Directory | 34 | import System.Directory |
33 | import Control.Concurrent | 35 | import Control.Concurrent |
34 | import GHC.Conc (labelThread) | 36 | import GHC.Conc (labelThread) |
37 | import System.IO.Unsafe(unsafeDupablePerformIO {- unsafeIOToSTM -}) | ||
35 | 38 | ||
36 | -- util, todo: move to another module | 39 | -- util, todo: move to another module |
37 | maybeToEither :: Maybe b -> Either String b | 40 | maybeToEither :: Maybe b -> Either String b |
@@ -45,7 +48,10 @@ data NetCryptoSessionStatus = Unaccepted | Accepted | Confirmed | |||
45 | type IOHook addr x = addr -> x -> IO (Maybe (x -> x)) | 48 | type IOHook addr x = addr -> x -> IO (Maybe (x -> x)) |
46 | type NetCryptoHook = IOHook NetCryptoSession CryptoData | 49 | type NetCryptoHook = IOHook NetCryptoSession CryptoData |
47 | type MsgTypeArray = A.UArray Word8 Word16 | 50 | type MsgTypeArray = A.UArray Word8 Word16 |
48 | 51 | type MsgOutMap = W64.Word64Map Word8 | |
52 | -- type MsgOutMap = A.UArray Word64 Word8 -- if above is too slow, switch to this, but use reasonable bounds | ||
53 | msgOutMapLookup :: Word64 -> MsgOutMap -> Maybe Word8 | ||
54 | msgOutMapLookup = W64.lookup | ||
49 | 55 | ||
50 | -- | Information, that may be made visible in multiple sessions, as well | 56 | -- | Information, that may be made visible in multiple sessions, as well |
51 | -- as displayed in some way to the user via mutiple views. | 57 | -- as displayed in some way to the user via mutiple views. |
@@ -86,7 +92,7 @@ data NetCryptoSession = NCrypto { ncState :: TVar NetCryptoSessionStatu | |||
86 | -- may not be in ncHooks yet, but they should appear | 92 | -- may not be in ncHooks yet, but they should appear |
87 | -- here if ncUnrecognizedHook will add them to ncHooks | 93 | -- here if ncUnrecognizedHook will add them to ncHooks |
88 | -- on an as-need basis. | 94 | -- on an as-need basis. |
89 | , ncOutgoingTypeArray :: TVar MsgTypeArray | 95 | , ncOutgoingIdMap :: TVar MsgOutMap |
90 | , ncAllSessions :: NetCryptoSessions -- ^ may be needed if one net-crypto session | 96 | , ncAllSessions :: NetCryptoSessions -- ^ may be needed if one net-crypto session |
91 | -- needs to possibly start another, as is | 97 | -- needs to possibly start another, as is |
92 | -- the case in group chats | 98 | -- the case in group chats |
@@ -94,6 +100,7 @@ data NetCryptoSession = NCrypto { ncState :: TVar NetCryptoSessionStatu | |||
94 | , ncPacketQueue :: PacketQueue CryptoData | 100 | , ncPacketQueue :: PacketQueue CryptoData |
95 | , ncBufferStart :: TVar Word32 | 101 | , ncBufferStart :: TVar Word32 |
96 | , ncDequeueThread :: Maybe ThreadId | 102 | , ncDequeueThread :: Maybe ThreadId |
103 | , ncOutgoingQueue :: PQ.PacketOutQueue (State,Nonce24,TVar MsgOutMap) CryptoMessage (CryptoPacket Encrypted) CryptoData | ||
97 | } | 104 | } |
98 | 105 | ||
99 | data NetCryptoSessions = NCSessions { netCryptoSessions :: TVar (Map.Map SockAddr NetCryptoSession) | 106 | data NetCryptoSessions = NCSessions { netCryptoSessions :: TVar (Map.Map SockAddr NetCryptoSession) |
@@ -104,6 +111,7 @@ data NetCryptoSessions = NCSessions { netCryptoSessions :: TVar (Map.Map SockAdd | |||
104 | , sessionView :: SessionView | 111 | , sessionView :: SessionView |
105 | , msgTypeArray :: MsgTypeArray | 112 | , msgTypeArray :: MsgTypeArray |
106 | , inboundQueueCapacity :: Word32 | 113 | , inboundQueueCapacity :: Word32 |
114 | , outboundQueueCapacity :: Word32 | ||
107 | , nextSessionId :: TVar SessionID | 115 | , nextSessionId :: TVar SessionID |
108 | } | 116 | } |
109 | 117 | ||
@@ -168,6 +176,7 @@ newSessionsState crypto unrechook hooks = do | |||
168 | } | 176 | } |
169 | , msgTypeArray = allMsgTypes -- todo make this a parameter | 177 | , msgTypeArray = allMsgTypes -- todo make this a parameter |
170 | , inboundQueueCapacity = 200 | 178 | , inboundQueueCapacity = 200 |
179 | , outboundQueueCapacity = 400 | ||
171 | , nextSessionId = nextSessionId0 | 180 | , nextSessionId = nextSessionId0 |
172 | } | 181 | } |
173 | 182 | ||
@@ -208,6 +217,53 @@ newHandShakeData crypto basenonce (HParam {hpOtherCookie,hpMySecretKey,hpCookieR | |||
208 | , otherCookie = freshCookie' | 217 | , otherCookie = freshCookie' |
209 | }) freshCookie | 218 | }) freshCookie |
210 | 219 | ||
220 | type XMessage = CryptoMessage -- todo | ||
221 | |||
222 | ncToWire :: STM (State,Nonce24,TVar MsgOutMap) | ||
223 | -> Word32{- packet number we expect to recieve -} | ||
224 | -> Word32{- buffer_end -} | ||
225 | -> Word32{- packet number -} | ||
226 | -> XMessage | ||
227 | -> STM (Maybe (CryptoPacket Encrypted,Word32{-next packet no-})) | ||
228 | ncToWire getState seqno bufend pktno msg = do | ||
229 | let typ = getMessageType msg | ||
230 | typ64 = toWord64 typ | ||
231 | let lsness msg = | ||
232 | case typ of | ||
233 | Msg mid -> lossyness mid | ||
234 | GrpMsg KnownLossy _ -> Lossy | ||
235 | GrpMsg KnownLossless _ -> Lossless | ||
236 | (state,n24,msgOutMapVar) <- getState | ||
237 | msgOutMap <- readTVar msgOutMapVar | ||
238 | case msgOutMapLookup typ64 msgOutMap of | ||
239 | Just outid -> do | ||
240 | let setMessageId (OneByte _) mid = OneByte (toEnum8 mid) | ||
241 | setMessageId (TwoByte _ x) mid = TwoByte (toEnum8 mid) x | ||
242 | setMessageId (UpToN _ x) mid = UpToN (toEnum8 mid) x | ||
243 | msg' = setMessageId msg outid | ||
244 | in case lsness msg of | ||
245 | UnknownLossyness -> return Nothing | ||
246 | Lossy -> let cd = | ||
247 | CryptoData | ||
248 | { bufferStart = seqno | ||
249 | , bufferEnd = bufend | ||
250 | , bufferData = msg' | ||
251 | } | ||
252 | plain = encodePlain cd | ||
253 | encrypted = encrypt state plain | ||
254 | pkt = CryptoPacket { pktNonce = nonce24ToWord16 n24, pktData = encrypted } | ||
255 | in return (Just (pkt, pktno)) | ||
256 | Lossless -> let cd = | ||
257 | CryptoData | ||
258 | { bufferStart = seqno | ||
259 | , bufferEnd = pktno | ||
260 | , bufferData = msg' | ||
261 | } | ||
262 | plain = encodePlain cd | ||
263 | encrypted = encrypt state plain | ||
264 | pkt = CryptoPacket { pktNonce = nonce24ToWord16 n24, pktData = encrypted } | ||
265 | in return (Just (pkt, pktno+1)) | ||
266 | |||
211 | -- | called when we recieve a crypto handshake with valid cookie | 267 | -- | called when we recieve a crypto handshake with valid cookie |
212 | -- TODO set priority on contact addr to 0 if it is older than ForgetPeriod, | 268 | -- TODO set priority on contact addr to 0 if it is older than ForgetPeriod, |
213 | -- then increment it regardless. (Keep addr in MinMaxPSQ in Roster.Contact) | 269 | -- then increment it regardless. (Keep addr in MinMaxPSQ in Roster.Contact) |
@@ -250,10 +306,18 @@ freshCryptoSession sessions | |||
250 | ncHooks0 <- atomically $ newTVar (defaultHooks sessions) | 306 | ncHooks0 <- atomically $ newTVar (defaultHooks sessions) |
251 | ncUnrecognizedHook0 <- atomically $ newTVar (defaultUnrecognizedHook sessions) | 307 | ncUnrecognizedHook0 <- atomically $ newTVar (defaultUnrecognizedHook sessions) |
252 | ncIncomingTypeArray0 <- atomically $ newTVar (msgTypeArray sessions) | 308 | ncIncomingTypeArray0 <- atomically $ newTVar (msgTypeArray sessions) |
253 | ncOutgoingTypeArray0 <- atomically $ newTVar allMsgTypes | 309 | ncOutgoingIdMap0 <- atomically $ newTVar W64.empty |
254 | ncView0 <- atomically $ newTVar (sessionView sessions) | 310 | ncView0 <- atomically $ newTVar (sessionView sessions) |
255 | pktq <- atomically $ PQ.new (inboundQueueCapacity sessions) 0 | 311 | pktq <- atomically $ PQ.new (inboundQueueCapacity sessions) 0 |
256 | bufstart <- atomically $ newTVar 0 | 312 | bufstart <- atomically $ newTVar 0 |
313 | let toWireIO = do | ||
314 | f <- lookupNonceFunction crypto newsession theirSessionKey | ||
315 | atomically $ do | ||
316 | n24 <- readTVar ncMyPacketNonce0 | ||
317 | let n24plus1 = unsafeDupablePerformIO (incrementNonce24 n24) | ||
318 | writeTVar ncMyPacketNonce0 n24plus1 | ||
319 | return (return (f n24, n24, ncOutgoingIdMap0)) | ||
320 | pktoq <- atomically $ PQ.newOutGoing pktq ncToWire toWireIO 0 (outboundQueueCapacity sessions) 0 | ||
257 | let netCryptoSession0 = | 321 | let netCryptoSession0 = |
258 | NCrypto { ncState = ncState0 | 322 | NCrypto { ncState = ncState0 |
259 | , ncSessionId = sessionId | 323 | , ncSessionId = sessionId |
@@ -270,11 +334,12 @@ freshCryptoSession sessions | |||
270 | , ncUnrecognizedHook = ncUnrecognizedHook0 | 334 | , ncUnrecognizedHook = ncUnrecognizedHook0 |
271 | , ncAllSessions = sessions | 335 | , ncAllSessions = sessions |
272 | , ncIncomingTypeArray = ncIncomingTypeArray0 | 336 | , ncIncomingTypeArray = ncIncomingTypeArray0 |
273 | , ncOutgoingTypeArray = ncOutgoingTypeArray0 | 337 | , ncOutgoingIdMap = ncOutgoingIdMap0 |
274 | , ncView = ncView0 | 338 | , ncView = ncView0 |
275 | , ncPacketQueue = pktq | 339 | , ncPacketQueue = pktq |
276 | , ncBufferStart = bufstart | 340 | , ncBufferStart = bufstart |
277 | , ncDequeueThread = Nothing -- error "you want the NetCrypto-Dequeue thread id, but is it started?" | 341 | , ncDequeueThread = Nothing -- error "you want the NetCrypto-Dequeue thread id, but is it started?" |
342 | , ncOutgoingQueue = pktoq | ||
278 | } | 343 | } |
279 | threadid <- forkIO $ do | 344 | threadid <- forkIO $ do |
280 | tid <- myThreadId | 345 | tid <- myThreadId |
diff --git a/src/Network/Tox/Crypto/Transport.hs b/src/Network/Tox/Crypto/Transport.hs index 386c2766..b89bde46 100644 --- a/src/Network/Tox/Crypto/Transport.hs +++ b/src/Network/Tox/Crypto/Transport.hs | |||
@@ -23,6 +23,7 @@ module Network.Tox.Crypto.Transport | |||
23 | , MessageType(..) | 23 | , MessageType(..) |
24 | , KnownLossyness(..) | 24 | , KnownLossyness(..) |
25 | , AsWord16(..) | 25 | , AsWord16(..) |
26 | , AsWord64(..) | ||
26 | -- feild name classes | 27 | -- feild name classes |
27 | , HasGroupChatID(..) | 28 | , HasGroupChatID(..) |
28 | , HasGroupNumber(..) | 29 | , HasGroupNumber(..) |
@@ -420,6 +421,11 @@ class AsWord16 a where | |||
420 | toWord16 :: a -> Word16 | 421 | toWord16 :: a -> Word16 |
421 | fromWord16 :: Word16 -> a | 422 | fromWord16 :: Word16 -> a |
422 | 423 | ||
424 | class AsWord64 a where | ||
425 | toWord64 :: a -> Word64 | ||
426 | fromWord64 :: Word64 -> a | ||
427 | |||
428 | |||
423 | toEnum8 :: (Enum a, Integral word8) => word8 -> a | 429 | toEnum8 :: (Enum a, Integral word8) => word8 -> a |
424 | toEnum8 = toEnum . fromIntegral | 430 | toEnum8 = toEnum . fromIntegral |
425 | fromEnum8 :: Enum a => a -> Word8 | 431 | fromEnum8 :: Enum a => a -> Word8 |
@@ -428,6 +434,9 @@ fromEnum8 = fromIntegral . fromEnum | |||
428 | fromEnum16 :: Enum a => a -> Word16 | 434 | fromEnum16 :: Enum a => a -> Word16 |
429 | fromEnum16 = fromIntegral . fromEnum | 435 | fromEnum16 = fromIntegral . fromEnum |
430 | 436 | ||
437 | fromEnum64 :: Enum a => a -> Word64 | ||
438 | fromEnum64 = fromIntegral . fromEnum | ||
439 | |||
431 | 440 | ||
432 | -- MessageType, for our client keep it inside 16 bits | 441 | -- MessageType, for our client keep it inside 16 bits |
433 | -- but we should extend it to 32 or even 64 on the wire. | 442 | -- but we should extend it to 32 or even 64 on the wire. |
@@ -440,6 +449,13 @@ instance AsWord16 MessageType where | |||
440 | fromWord16 x | x < 1024, x .|. 0x0200 == 0x0200 = GrpMsg (toEnum8 ((x - 512) `div` 256)) (toEnum8 x) | 449 | fromWord16 x | x < 1024, x .|. 0x0200 == 0x0200 = GrpMsg (toEnum8 ((x - 512) `div` 256)) (toEnum8 x) |
441 | fromWord16 x = error "Not clear how to convert Word16 to MessageType" | 450 | fromWord16 x = error "Not clear how to convert Word16 to MessageType" |
442 | 451 | ||
452 | instance AsWord64 MessageType where | ||
453 | toWord64 (Msg msgID) = fromIntegral (fromIntegral (fromEnum16 msgID) :: Word8) | ||
454 | toWord64 (GrpMsg lsy msgName) = 512 + 256 * (fromEnum64 lsy) + fromIntegral (fromEnum8 msgName) | ||
455 | fromWord64 x | x < 256 = Msg (toEnum $ fromIntegral x) | ||
456 | fromWord64 x | x < 1024, x .|. 0x0200 == 0x0200 = GrpMsg (toEnum8 ((x - 512) `div` 256)) (toEnum8 x) | ||
457 | fromWord64 x = error "Not clear how to convert Word64 to MessageType" | ||
458 | |||
443 | word16 :: (Functor f, AsWord16 x) => (Word16 -> f Word16) -> (x -> f x) | 459 | word16 :: (Functor f, AsWord16 x) => (Word16 -> f Word16) -> (x -> f x) |
444 | word16 = lens toWord16 (\_ x -> fromWord16 x) | 460 | word16 = lens toWord16 (\_ x -> fromWord16 x) |
445 | 461 | ||