diff options
Diffstat (limited to 'src/Network/BitTorrent')
-rw-r--r-- | src/Network/BitTorrent/Tracker/UDP.hs | 67 |
1 files changed, 36 insertions, 31 deletions
diff --git a/src/Network/BitTorrent/Tracker/UDP.hs b/src/Network/BitTorrent/Tracker/UDP.hs index 23c6cacc..f6469a18 100644 --- a/src/Network/BitTorrent/Tracker/UDP.hs +++ b/src/Network/BitTorrent/Tracker/UDP.hs | |||
@@ -12,6 +12,7 @@ | |||
12 | {-# LANGUAGE RecordWildCards #-} | 12 | {-# LANGUAGE RecordWildCards #-} |
13 | {-# LANGUAGE FlexibleInstances #-} | 13 | {-# LANGUAGE FlexibleInstances #-} |
14 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} | 14 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} |
15 | {-# LANGUAGE TypeFamilies #-} | ||
15 | module Network.BitTorrent.Tracker.UDP | 16 | module Network.BitTorrent.Tracker.UDP |
16 | ( UDPTracker | 17 | ( UDPTracker |
17 | , initialTracker | 18 | , initialTracker |
@@ -94,13 +95,18 @@ data Response = Connected ConnId | |||
94 | | Failed Text | 95 | | Failed Text |
95 | deriving Show | 96 | deriving Show |
96 | 97 | ||
97 | -- TODO rename to message? | 98 | data family Transaction a |
98 | data Transaction a = Transaction | 99 | data instance Transaction Request = TransactionQ |
99 | { connId :: !ConnId | 100 | { connIdQ :: {-# UNPACK #-} !ConnId |
100 | , transId :: !TransId | 101 | , transIdQ :: {-# UNPACK #-} !TransId |
101 | , body :: !a | 102 | , request :: !Request |
102 | } deriving Show | 103 | } deriving Show |
104 | data instance Transaction Response = TransactionR | ||
105 | { transIdR :: {-# UNPACK #-} !TransId | ||
106 | , response :: !Response | ||
107 | } deriving Show | ||
103 | 108 | ||
109 | -- TODO newtype | ||
104 | type MessageId = Word32 | 110 | type MessageId = Word32 |
105 | 111 | ||
106 | connectId, announceId, scrapeId, errorId :: MessageId | 112 | connectId, announceId, scrapeId, errorId :: MessageId |
@@ -110,23 +116,23 @@ scrapeId = 2 | |||
110 | errorId = 3 | 116 | errorId = 3 |
111 | 117 | ||
112 | instance Serialize (Transaction Request) where | 118 | instance Serialize (Transaction Request) where |
113 | put Transaction {..} = do | 119 | put TransactionQ {..} = do |
114 | case body of | 120 | case request of |
115 | Connect -> do | 121 | Connect -> do |
116 | put initialConnectionId | 122 | put initialConnectionId |
117 | put connectId | 123 | put connectId |
118 | put transId | 124 | put transIdQ |
119 | 125 | ||
120 | Announce query -> do | 126 | Announce query -> do |
121 | put connId | 127 | put connIdQ |
122 | put announceId | 128 | put announceId |
123 | put transId | 129 | put transIdQ |
124 | put query | 130 | put query |
125 | 131 | ||
126 | Scrape hashes -> do | 132 | Scrape hashes -> do |
127 | put connId | 133 | put connIdQ |
128 | put scrapeId | 134 | put scrapeId |
129 | put transId | 135 | put transIdQ |
130 | forM_ hashes put | 136 | forM_ hashes put |
131 | 137 | ||
132 | get = do | 138 | get = do |
@@ -135,10 +141,10 @@ instance Serialize (Transaction Request) where | |||
135 | tid <- get | 141 | tid <- get |
136 | bod <- getBody mid | 142 | bod <- getBody mid |
137 | 143 | ||
138 | return $ Transaction { | 144 | return $ TransactionQ { |
139 | connId = cid | 145 | connIdQ = cid |
140 | , transId = tid | 146 | , transIdQ = tid |
141 | , body = bod | 147 | , request = bod |
142 | } | 148 | } |
143 | where | 149 | where |
144 | getBody :: MessageId -> Get Request | 150 | getBody :: MessageId -> Get Request |
@@ -149,26 +155,26 @@ instance Serialize (Transaction Request) where | |||
149 | | otherwise = fail "unknown message id" | 155 | | otherwise = fail "unknown message id" |
150 | 156 | ||
151 | instance Serialize (Transaction Response) where | 157 | instance Serialize (Transaction Response) where |
152 | put Transaction {..} = do | 158 | put TransactionR {..} = do |
153 | case body of | 159 | case response of |
154 | Connected conn -> do | 160 | Connected conn -> do |
155 | put connectId | 161 | put connectId |
156 | put transId | 162 | put transIdR |
157 | put conn | 163 | put conn |
158 | 164 | ||
159 | Announced info -> do | 165 | Announced info -> do |
160 | put announceId | 166 | put announceId |
161 | put transId | 167 | put transIdR |
162 | put info | 168 | put info |
163 | 169 | ||
164 | Scraped infos -> do | 170 | Scraped infos -> do |
165 | put scrapeId | 171 | put scrapeId |
166 | put transId | 172 | put transIdR |
167 | forM_ infos put | 173 | forM_ infos put |
168 | 174 | ||
169 | Failed info -> do | 175 | Failed info -> do |
170 | put errorId | 176 | put errorId |
171 | put transId | 177 | put transIdR |
172 | put (encodeUtf8 info) | 178 | put (encodeUtf8 info) |
173 | 179 | ||
174 | 180 | ||
@@ -178,10 +184,9 @@ instance Serialize (Transaction Response) where | |||
178 | tid <- get | 184 | tid <- get |
179 | bod <- getBody mid | 185 | bod <- getBody mid |
180 | 186 | ||
181 | return $ Transaction { | 187 | return $ TransactionR |
182 | connId = initialConnectionId -- TODO | 188 | { transIdR = tid |
183 | , transId = tid | 189 | , response = bod |
184 | , body = bod | ||
185 | } | 190 | } |
186 | where | 191 | where |
187 | getBody :: MessageId -> Get Response | 192 | getBody :: MessageId -> Get Response |
@@ -277,19 +282,19 @@ transaction :: UDPTracker -> Request -> IO (Transaction Response) | |||
277 | transaction tracker @ UDPTracker {..} request = do | 282 | transaction tracker @ UDPTracker {..} request = do |
278 | cid <- getConnectionId tracker | 283 | cid <- getConnectionId tracker |
279 | tid <- genTransactionId | 284 | tid <- genTransactionId |
280 | let trans = Transaction cid tid request | 285 | let trans = TransactionQ cid tid request |
281 | 286 | ||
282 | addr <- getTrackerAddr trackerURI | 287 | addr <- getTrackerAddr trackerURI |
283 | res <- call addr (encode trans) | 288 | res <- call addr (encode trans) |
284 | case decode res of | 289 | case decode res of |
285 | Right (response @ Transaction {..}) | 290 | Right (responseT @ TransactionR {..}) |
286 | | tid == transId -> return response | 291 | | tid == transIdR -> return responseT |
287 | | otherwise -> throwIO $ userError "transaction id mismatch" | 292 | | otherwise -> throwIO $ userError "transaction id mismatch" |
288 | Left msg -> throwIO $ userError msg | 293 | Left msg -> throwIO $ userError msg |
289 | 294 | ||
290 | connectUDP :: UDPTracker -> IO ConnId | 295 | connectUDP :: UDPTracker -> IO ConnId |
291 | connectUDP tracker = do | 296 | connectUDP tracker = do |
292 | Transaction _ tid resp <- transaction tracker Connect | 297 | TransactionR tid resp <- transaction tracker Connect |
293 | case resp of | 298 | case resp of |
294 | Connected cid -> return cid | 299 | Connected cid -> return cid |
295 | 300 | ||