summaryrefslogtreecommitdiff
path: root/dht/src/Network/Tox/Transport.hs
blob: 0ca9b75863f09f00aed0b3e35c98671a58632d25 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
{-# LANGUAGE DataKinds                  #-}
{-# LANGUAGE GADTs                      #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE KindSignatures             #-}
{-# LANGUAGE LambdaCase                 #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE TupleSections              #-}
{-# LANGUAGE TypeOperators              #-}
module Network.Tox.Transport (toxTransport, RouteId) where

import Network.QueryResponse
import Crypto.Tox
import Data.Tox.Relay as TCP
import qualified Data.Tox.DHT.Multi as Multi
import Network.Tox.DHT.Transport as UDP
import Network.Tox.TCP (ViaRelay)
import Network.Tox.Onion.Transport
import Network.Tox.Crypto.Transport
import Network.Tox.Onion.Routes

import Control.Concurrent.STM
import qualified Data.ByteString    as B
import qualified Data.Dependent.Map as DMap
import Data.Dependent.Sum
import Data.Functor.Identity
import Network.Socket

pendingCookiesUDP :: TransportCrypto -> STM [(SockAddr, (Int, PublicKey))]
pendingCookiesUDP crypto = readTVar $ pendingCookies crypto

pendingCookiesTCP :: TransportCrypto -> STM [(ViaRelay, (Int, PublicKey))]
pendingCookiesTCP crypto = return [] -- TODO

toxTransport ::
      TransportCrypto
          -> OnionRouter
          -> (PublicKey -> IO (Maybe UDP.NodeInfo))
          -> SockAddr -- ^ UDP bind-address
          -> UDPTransport
          -> Transport String ViaRelay B.ByteString
          -> (TCP.NodeInfo -> RelayPacket -> IO ())   -- ^ TCP server-bound callback.
          -> (Int -> OnionMessage Encrypted -> IO ()) -- ^ TCP client-bound callback.
          -> IO ( Transport String Multi.SessionAddress (CryptoPacket Encrypted)
                , Transport String Multi.NodeInfo (DHTMessage Encrypted8)
                , Transport String (OnionDestination RouteId) (OnionMessage Encrypted)
                , Transport String AnnouncedRendezvous (PublicKey,OnionData)
                , Transport String Multi.SessionAddress (Handshake Encrypted))
toxTransport crypto orouter closeLookup addr udp relaynet tcp2server tcp2client = do
    (netcrypto, udp0) <- partitionTransport parseCrypto encodeCrypto udp
    (dhtUDP,udp1) <- partitionTransportM (parseDHTAddr (pendingCookiesUDP crypto) nodeInfo)
                                      (fmap Just . encodeDHTAddr nodeAddr)
                                    $ forwardOnions crypto addr udp0 tcp2client
    -- rlynet0 = layerTransportM (DHT.decrypt crypto Multi.relayNodeId) (DHT.encrypt crypto Multi.relayNodeId) relaynet
    (dhtTCP,relaynet0) <- partitionTransportM
                            (parseDHTAddr (pendingCookiesTCP crypto) (\nid viarelay -> Right viarelay))
                            (fmap Just . encodeDHTAddr id)
                            relaynet
    let _ = dhtTCP :: Transport String ViaRelay (DHTMessage Encrypted8)
    dht <- mergeTransports $ DMap.fromList
        [ Multi.UDP :=> ByAddress dhtUDP
        , Multi.TCP :=> ByAddress dhtTCP
        ]
    (onion1,udp2) <- partitionAndForkTransport tcp2server
                             (parseOnionAddr $ lookupSender orouter)
                             (encodeOnionAddr crypto $ lookupRoute orouter)
                             udp1
    (dta,onion) <- partitionTransportM (parseDataToRoute crypto) (encodeDataToRoute crypto) onion1
    let handshakes = layerTransport parseHandshakes encodeHandshakes udp2
        promoteUDP :: TransportA err SockAddr x y -> TransportA err Multi.SessionAddress x y
        promoteUDP net = layerTransport (\msg saddr -> Right (msg,Multi.SessionUDP ==> saddr))
                                        (\msg (Multi.SessionUDP :=> Identity saddr) -> (msg,saddr))
                                        net
        -- TODO: Enable sessions over TCP
        multi_netcrypto = promoteUDP netcrypto
        multi_handshakes = promoteUDP handshakes
    return ( multi_netcrypto
           , forwardDHTRequests crypto (fmap (fmap (Multi.UDP ==>)) . closeLookup) dht
           , onion
           , dta
           , multi_handshakes
           )


-- instance (Sized a, Sized b) => Sized (a,b) where size = _todo


--   Byte value   Packet Kind           Return address
-- :----------- :--------------------
--   `0x00`       Ping Request          DHTNode
--   `0x01`       Ping Response         -
--   `0x02`       Nodes Request         DHTNode
--   `0x04`       Nodes Response        -
--   `0x18`       Cookie Request        DHTNode, but without sending pubkey in response
--   `0x19`       Cookie Response       - (no pubkey)
--
--   `0x21`       LAN Discovery         DHTNode (No reply, port 33445, trigger Nodes Request/Response)
--
--   `0x20`       DHT Request           DHTNode/-forward
--
--   `0x1a`       Crypto Handshake      CookieAddress
--
--   `0x1b`       Crypto Data           SessionAddress
--
--   `0x83`       Announce Request      OnionToOwner
--   `0x84`       Announce Response     -
--   `0x85`       Onion Data Request    OnionToOwner
--   `0x86`       Onion Data Response   -
--
--   `0xf0`       Bootstrap Info        SockAddr?
--
--   `0x80`       Onion Request 0       -forward
--   `0x81`       Onion Request 1       -forward
--   `0x82`       Onion Request 2       -forward
--   `0x8c`       Onion Response 3      -return
--   `0x8d`       Onion Response 2      -return
--   `0x8e`       Onion Response 1      -return