diff options
Diffstat (limited to 'dht/src/Network/BitTorrent/Tracker/Transport.hs')
-rw-r--r-- | dht/src/Network/BitTorrent/Tracker/Transport.hs | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/dht/src/Network/BitTorrent/Tracker/Transport.hs b/dht/src/Network/BitTorrent/Tracker/Transport.hs new file mode 100644 index 00000000..60cb832d --- /dev/null +++ b/dht/src/Network/BitTorrent/Tracker/Transport.hs | |||
@@ -0,0 +1,76 @@ | |||
1 | {-# LANGUAGE TupleSections #-} | ||
2 | module Network.BitTorrent.Tracker.Transport where | ||
3 | |||
4 | import Control.Concurrent.STM | ||
5 | import Crypto.Random | ||
6 | import Data.ByteString (ByteString) | ||
7 | import Data.Functor.Contravariant | ||
8 | import Data.IntMap.Strict (IntMap) | ||
9 | import qualified Data.Serialize as S | ||
10 | import Network.Socket | ||
11 | |||
12 | import Data.QueryResponse.Table | ||
13 | import Data.TableMethods | ||
14 | import Network.Address | ||
15 | import Network.BitTorrent.Tracker.Message | ||
16 | import Network.QueryResponse as QR | ||
17 | |||
18 | parseTracker :: ByteString -> SockAddr -> Either String (Transaction Request, SockAddr) | ||
19 | parseTracker bs saddr = fmap (, saddr) $ S.decode bs | ||
20 | |||
21 | encodeTracker :: Transaction Response -> SockAddr -> (ByteString, SockAddr) | ||
22 | encodeTracker resp saddr = (S.encode resp,saddr) | ||
23 | |||
24 | type Handler = MethodHandlerA String TransactionId SockAddr (Transaction Request) (Transaction Response) | ||
25 | |||
26 | type Client = QR.ClientA String MessageId TransactionId SockAddr (Transaction Request) (Transaction Response) | ||
27 | |||
28 | handlers :: MessageId -> Maybe Handler | ||
29 | handlers ConnectId = Nothing | ||
30 | handlers AnnounceId = Nothing | ||
31 | handlers ScrapeId = Nothing | ||
32 | handlers ErrorId = Nothing | ||
33 | handlers _ = Nothing | ||
34 | |||
35 | methodOfRequest :: Request -> MessageId | ||
36 | methodOfRequest Connect {} = ConnectId | ||
37 | methodOfRequest Announce {} = AnnounceId | ||
38 | methodOfRequest Scrape {} = ScrapeId | ||
39 | |||
40 | classify :: Transaction Request -> MessageClass String MessageId TransactionId SockAddr (Transaction Request) | ||
41 | classify qry = IsQuery (methodOfRequest $ request qry) (transIdQ qry) | ||
42 | |||
43 | dispatch :: DRG g => | ||
44 | DispatchMethodsA | ||
45 | (g, IntMap (Maybe (Transaction Response) -> IO ())) | ||
46 | String | ||
47 | MessageId | ||
48 | TransactionId | ||
49 | SockAddr | ||
50 | (Transaction Request) | ||
51 | (Transaction Response) | ||
52 | dispatch = DispatchMethods | ||
53 | { classifyInbound = classify | ||
54 | , lookupHandler = handlers | ||
55 | , tableMethods = transactionMethods (contramap fromEnum intMapMethods) genTransactionId | ||
56 | } | ||
57 | |||
58 | newClient :: ErrorReporter SockAddr (Transaction Request) MessageId TransactionId String | ||
59 | -> TransportA String SockAddr (Transaction Request) (Transaction Response) | ||
60 | -> IO (ClientA String | ||
61 | MessageId | ||
62 | TransactionId | ||
63 | SockAddr | ||
64 | (Transaction Request) | ||
65 | (Transaction Response)) | ||
66 | newClient err net = do | ||
67 | drg <- drgNew | ||
68 | state <- newTVarIO (drg, mempty) | ||
69 | return QR.Client | ||
70 | { clientNet = net | ||
71 | , clientDispatcher = dispatch | ||
72 | , clientErrorReporter = err | ||
73 | , clientPending = state | ||
74 | , clientAddress = const $ return localhost4 | ||
75 | , clientResponseId = return | ||
76 | } | ||