diff options
-rw-r--r-- | Tox.hs | 57 |
1 files changed, 43 insertions, 14 deletions
@@ -11,6 +11,7 @@ | |||
11 | module Tox where | 11 | module Tox where |
12 | 12 | ||
13 | import Control.Arrow | 13 | import Control.Arrow |
14 | import Control.Concurrent (MVar) | ||
14 | import Control.Concurrent.STM | 15 | import Control.Concurrent.STM |
15 | import qualified Crypto.Cipher.Salsa as Salsa | 16 | import qualified Crypto.Cipher.Salsa as Salsa |
16 | import qualified Crypto.Cipher.XSalsa as XSalsa | 17 | import qualified Crypto.Cipher.XSalsa as XSalsa |
@@ -368,8 +369,9 @@ data Routing = Routing | |||
368 | , committee6 :: TriadCommittee NodeId SockAddr | 369 | , committee6 :: TriadCommittee NodeId SockAddr |
369 | } | 370 | } |
370 | 371 | ||
372 | type ToxClient = Client String Method TransactionId NodeInfo (Message ByteString) | ||
371 | 373 | ||
372 | newClient :: SockAddr -> IO (Client String Method TransactionId NodeInfo (Message ByteString)) | 374 | newClient :: SockAddr -> IO (ToxClient, Routing) |
373 | newClient addr = do | 375 | newClient addr = do |
374 | udp <- udpTransport addr | 376 | udp <- udpTransport addr |
375 | secret <- generateSecretKey | 377 | secret <- generateSecretKey |
@@ -402,9 +404,31 @@ newClient addr = do | |||
402 | sched4 <- newTVar Int.empty | 404 | sched4 <- newTVar Int.empty |
403 | sched6 <- newTVar Int.empty | 405 | sched6 <- newTVar Int.empty |
404 | return $ Routing tentative_info sched4 tbl4 committee4 sched6 tbl6 committee6 | 406 | return $ Routing tentative_info sched4 tbl4 committee4 sched6 tbl6 committee6 |
405 | let net = layerTransport (parsePacket secret cache) | 407 | |
406 | (encodePacket secret cache) | 408 | -- If we have 8-byte keys for IntMap, then use it for transaction lookups. |
407 | udp | 409 | -- Otherwise, use ordinary Map. The details of which will be hidden by an |
410 | -- existential closure (see mkclient below). | ||
411 | tblvar <- | ||
412 | if fitsInInt (Proxy :: Proxy Word64) | ||
413 | then do | ||
414 | let intmapT = transactionMethods (contramapT intKey intMapMethods) gen | ||
415 | intmap_var <- atomically $ newTVar (drg, mempty) | ||
416 | return $ Right (intmapT,intmap_var) | ||
417 | else do | ||
418 | let mapT = transactionMethods (contramapT nonceKey mapMethods) gen | ||
419 | map_var <- atomically $ newTVar (drg, mempty) | ||
420 | return $ Left (mapT,map_var) | ||
421 | let net = onInbound (updateRouting outgoingClient routing) | ||
422 | $ layerTransport (parsePacket secret cache) | ||
423 | (encodePacket secret cache) | ||
424 | $ udp | ||
425 | |||
426 | -- Paranoid: It's safe to define /net/ and /client/ to be mutually | ||
427 | -- recursive since 'updateRouting' does not invoke 'awaitMessage' which | ||
428 | -- which was modified by 'onInbound'. However, I'm going to avoid the | ||
429 | -- mutual reference just to be safe. | ||
430 | outgoingClient = client { clientNet = net { awaitMessage = return Nothing } } | ||
431 | |||
408 | dispatch tbl = DispatchMethods | 432 | dispatch tbl = DispatchMethods |
409 | { classifyInbound = classify | 433 | { classifyInbound = classify |
410 | , lookupHandler = handlers | 434 | , lookupHandler = handlers |
@@ -421,7 +445,16 @@ newClient addr = do | |||
421 | let (bs, g') = randomBytesGenerate 24 g | 445 | let (bs, g') = randomBytesGenerate 24 g |
422 | writeTVar var (g',pending) | 446 | writeTVar var (g',pending) |
423 | return $ TransactionId nonce8 (Nonce24 bs) | 447 | return $ TransactionId nonce8 (Nonce24 bs) |
424 | client tbl var = Client | 448 | |
449 | client = either mkclient mkclient tblvar | ||
450 | |||
451 | mkclient :: DRG g => | ||
452 | ( TransactionMethods (g,t (MVar (Message ByteString))) | ||
453 | TransactionId | ||
454 | (Message ByteString) | ||
455 | , TVar (g, t (MVar (Message ByteString))) | ||
456 | ) -> ToxClient | ||
457 | mkclient (tbl,var) = Client | ||
425 | { clientNet = net | 458 | { clientNet = net |
426 | , clientDispatcher = dispatch tbl | 459 | , clientDispatcher = dispatch tbl |
427 | , clientErrorReporter = printErrors stderr | 460 | , clientErrorReporter = printErrors stderr |
@@ -433,15 +466,8 @@ newClient addr = do | |||
433 | R.thisNode <$> readTVar var | 466 | R.thisNode <$> readTVar var |
434 | , clientResponseId = genNonce24 var | 467 | , clientResponseId = genNonce24 var |
435 | } | 468 | } |
436 | if fitsInInt (Proxy :: Proxy Word64) | 469 | |
437 | then do | 470 | return (client, routing) |
438 | let intmapT = transactionMethods (contramapT intKey intMapMethods) gen | ||
439 | intmap_var <- atomically $ newTVar (drg, mempty) | ||
440 | return (client intmapT intmap_var) | ||
441 | else do | ||
442 | let mapT = transactionMethods (contramapT nonceKey mapMethods) gen | ||
443 | map_var <- atomically $ newTVar (drg, mempty) | ||
444 | return (client mapT map_var) | ||
445 | 471 | ||
446 | last8 :: ByteString -> Nonce8 | 472 | last8 :: ByteString -> Nonce8 |
447 | last8 bs | 473 | last8 bs |
@@ -482,6 +508,9 @@ type Handler = MethodHandler String TransactionId NodeInfo (Message ByteString) | |||
482 | 508 | ||
483 | handler typ f = Just $ MethodHandler decodePayload (encodePayload typ) f | 509 | handler typ f = Just $ MethodHandler decodePayload (encodePayload typ) f |
484 | 510 | ||
511 | updateRouting :: ToxClient -> Routing -> NodeInfo -> Message ByteString -> IO () | ||
512 | updateRouting = error "todo updateRouting" | ||
513 | |||
485 | data Ping = Ping deriving Show | 514 | data Ping = Ping deriving Show |
486 | data Pong = Pong deriving Show | 515 | data Pong = Pong deriving Show |
487 | 516 | ||