summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Network/BitTorrent/Tracker/UDP.hs67
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 #-}
15module Network.BitTorrent.Tracker.UDP 16module 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? 98data family Transaction a
98data Transaction a = Transaction 99data 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
104data instance Transaction Response = TransactionR
105 { transIdR :: {-# UNPACK #-} !TransId
106 , response :: !Response
107 } deriving Show
103 108
109-- TODO newtype
104type MessageId = Word32 110type MessageId = Word32
105 111
106connectId, announceId, scrapeId, errorId :: MessageId 112connectId, announceId, scrapeId, errorId :: MessageId
@@ -110,23 +116,23 @@ scrapeId = 2
110errorId = 3 116errorId = 3
111 117
112instance Serialize (Transaction Request) where 118instance 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
151instance Serialize (Transaction Response) where 157instance 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)
277transaction tracker @ UDPTracker {..} request = do 282transaction 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
290connectUDP :: UDPTracker -> IO ConnId 295connectUDP :: UDPTracker -> IO ConnId
291connectUDP tracker = do 296connectUDP 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