summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/Tracker/Message.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/BitTorrent/Tracker/Message.hs')
-rw-r--r--src/Network/BitTorrent/Tracker/Message.hs108
1 files changed, 66 insertions, 42 deletions
diff --git a/src/Network/BitTorrent/Tracker/Message.hs b/src/Network/BitTorrent/Tracker/Message.hs
index 3447a367..59ef2027 100644
--- a/src/Network/BitTorrent/Tracker/Message.hs
+++ b/src/Network/BitTorrent/Tracker/Message.hs
@@ -52,6 +52,8 @@ import Data.Aeson (ToJSON(..), FromJSON(..))
52import Data.Aeson.TH 52import Data.Aeson.TH
53import Data.BEncode as BE 53import Data.BEncode as BE
54import Data.BEncode.BDict as BE 54import Data.BEncode.BDict as BE
55import Data.ByteString as BS
56import Data.ByteString.Char8 as BC
55import Data.Char as Char 57import Data.Char as Char
56import Data.List as L 58import Data.List as L
57import Data.Map as M 59import Data.Map as M
@@ -64,8 +66,10 @@ import Data.Typeable
64import Data.URLEncoded as URL 66import Data.URLEncoded as URL
65import Data.Word 67import Data.Word
66import Network 68import Network
67import Network.URI 69import Network.HTTP.Types.URI hiding (urlEncode)
68import Network.Socket 70import Network.Socket
71import Network.URI
72import Text.Read (readMaybe)
69 73
70import Data.Torrent.InfoHash 74import Data.Torrent.InfoHash
71import Data.Torrent.Progress 75import Data.Torrent.Progress
@@ -226,63 +230,83 @@ data QueryParam
226 = ParamInfoHash 230 = ParamInfoHash
227 | ParamPeerId 231 | ParamPeerId
228 | ParamPort 232 | ParamPort
229 | ParamProgress 233 | ParamUploaded
234 | ParamLeft
235 | ParamDownloaded
230 | ParamIP 236 | ParamIP
231 | ParamNumWant 237 | ParamNumWant
232 | ParamEvent 238 | ParamEvent
233 deriving (Show, Eq, Ord, Enum) 239 deriving (Show, Eq, Ord, Enum)
234 240
235data ParamParseFailure 241data ParamParseFailure
236 = Missing QueryParam -- ^ param not found in query string; 242 = Missing QueryParam -- ^ param not found in query string;
237 | Invalid QueryParam Text -- ^ param present but not valid. 243 | Invalid QueryParam ByteString -- ^ param present but not valid.
238 deriving (Show, Eq) 244 deriving (Show, Eq)
239 245
240type ParamResult = Either ParamParseFailure 246paramName :: QueryParam -> ByteString
247paramName ParamInfoHash = "info_hash"
248paramName ParamPeerId = "peer_id"
249paramName ParamPort = "port"
250paramName ParamUploaded = "uploaded"
251paramName ParamLeft = "left"
252paramName ParamDownloaded = "downloaded"
253paramName ParamIP = "ip"
254paramName ParamNumWant = "numwant"
255paramName ParamEvent = "event"
256
257class FromParam a where
258 fromParam :: BS.ByteString -> Maybe a
259
260instance FromParam InfoHash where
261 fromParam = byteStringToInfoHash
262
263instance FromParam PeerId where
264 fromParam = byteStringToPeerId
265
266instance FromParam Word32 where
267 fromParam = readMaybe . BC.unpack
268
269instance FromParam Word64 where
270 fromParam = readMaybe . BC.unpack
271
272instance FromParam Int where
273 fromParam = readMaybe . BC.unpack
241 274
242textToPeerId :: Text -> Maybe PeerId 275instance FromParam PortNumber where
243textToPeerId = undefined 276 fromParam bs = fromIntegral <$> (fromParam bs :: Maybe Word32)
244 277
245textToPortNumber :: Text -> Maybe PortNumber 278instance FromParam Event where
246textToPortNumber = undefined 279 fromParam bs = case BC.uncons bs of
280 Nothing -> Nothing
281 Just (x, xs) -> readMaybe $ BC.unpack $ BC.cons (Char.toUpper x) xs
247 282
248textToHostAddress :: Text -> Maybe HostAddress 283withError e = maybe (Left e) Right
249textToHostAddress = undefined
250 284
251textToNumWant :: Text -> Maybe Int 285reqParam param xs = do
252textToNumWant = undefined 286 val <- withError (Missing param) $ L.lookup (paramName param) xs
287 withError (Invalid param val) (fromParam val)
253 288
254textToEvent :: Text -> Maybe Event 289optParam param ps
255textToEvent = undefined 290 | Just x <- L.lookup (paramName param) ps
291 = pure <$> withError (Invalid param x) (fromParam x)
292 | otherwise = pure Nothing
256 293
257paramName :: QueryParam -> Text 294parseProgress :: SimpleQuery -> Either ParamParseFailure Progress
258paramName ParamInfoHash = "info_hash" 295parseProgress params = Progress
259paramName ParamPeerId = "peer_id" 296 <$> reqParam ParamDownloaded params
260paramName ParamPort = "port" 297 <*> reqParam ParamLeft params
298 <*> reqParam ParamUploaded params
261 299
262-- | Parse announce request from a decoded query string. 300-- | Parse announce request from a query string.
263parseAnnounceQuery :: [(Text, Text)] -> Either ParamParseFailure AnnounceQuery 301parseAnnounceQuery :: SimpleQuery -> Either ParamParseFailure AnnounceQuery
264parseAnnounceQuery params = AnnounceQuery 302parseAnnounceQuery params = AnnounceQuery
265 <$> reqParam ParamInfoHash textToInfoHash params 303 <$> reqParam ParamInfoHash params
266 <*> reqParam ParamPeerId textToPeerId params 304 <*> reqParam ParamPeerId params
267 <*> reqParam ParamPort textToPortNumber params 305 <*> reqParam ParamPort params
268 <*> progress params 306 <*> parseProgress params
269 <*> optParam ParamIP textToHostAddress params 307 <*> optParam ParamIP params
270 <*> optParam ParamNumWant textToNumWant params 308 <*> optParam ParamNumWant params
271 <*> optParam ParamEvent textToEvent params 309 <*> optParam ParamEvent params
272 where
273 withError e = maybe (Left e) Right
274 reqParam param p = withError (Missing param) . L.lookup (paramName param)
275 >=> \x -> withError (Invalid param x) (p x)
276
277 optParam param p ps
278 | Just x <- L.lookup (paramName param) ps
279 = pure <$> withError (Invalid param x) (p x)
280 | otherwise = pure Nothing
281
282 progress = undefined
283 ip = undefined
284 numwant = undefined
285 event = undefined
286 310
287-- TODO add extension datatype 311-- TODO add extension datatype
288 312