+++ /dev/null
-{-
- - Copyright (C) 2015-2016 Ramakrishnan Muthukrishnan <ram@rkrishnan.org>
- -
- - This file is part of FuncTorrent.
- -
- - FuncTorrent is free software; you can redistribute it and/or modify
- - it under the terms of the GNU General Public License as published by
- - the Free Software Foundation; either version 3 of the License, or
- - (at your option) any later version.
- -
- - FuncTorrent is distributed in the hope that it will be useful,
- - but WITHOUT ANY WARRANTY; without even the implied warranty of
- - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- - GNU General Public License for more details.
- -
- - You should have received a copy of the GNU General Public License
- - along with FuncTorrent; if not, see <http://www.gnu.org/licenses/>
- -}
-
-{-# LANGUAGE OverloadedStrings #-}
-module FuncTorrent.Tracker
- (runTracker
- , getConnectedPeers
- , newTracker
- ) where
-
-import Control.Concurrent(forkIO)
-import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)
-import Control.Concurrent.MVar (newEmptyMVar, putMVar, readMVar)
-import Control.Monad.State (StateT, liftIO, get, runStateT)
-import Control.Monad (forever)
-import Data.ByteString.Char8 (ByteString)
-import Data.List (isPrefixOf)
-import Network (PortNumber)
-
-import qualified FuncTorrent.Tracker.Http as HT (trackerLoop)
-import qualified FuncTorrent.Tracker.Udp as UT (trackerLoop)
-import FuncTorrent.Tracker.Types (TState(..), TrackerEventState(..), TrackerProtocol(..), TrackerMsg(..))
-import qualified FuncTorrent.FileSystem as FS (MsgChannel)
-import FuncTorrent.PeerMsgs (Peer)
-
-type MsgChannel = Chan TrackerMsg
-
-newTracker :: IO MsgChannel
-newTracker = newChan
-
-runTracker :: MsgChannel -> FS.MsgChannel -> ByteString -> PortNumber
- -> String -> [String] -> Integer -> IO ()
-runTracker msgChannel fsChan infohash port peerId announceList sz = do
- let fn = getTrackerLoopFn turl
- ps <- newEmptyMVar
- _ <- forkIO $ fn turl port peerId infohash fsChan (initialTState ps)
- _ <- runStateT (msgHandler msgChannel) (initialTState ps)
- return ()
- where getTrackerLoopFn turl' =
- case getTrackerType turl' of
- Http -> HT.trackerLoop
- Udp -> UT.trackerLoop
- _ -> error "Tracker Protocol unimplemented"
- initialTState ps' = TState { currentState = None
- , connectedPeers = ps'
- , left = sz }
- turl = head announceList
-
-getTrackerType :: String -> TrackerProtocol
-getTrackerType url | "http://" `isPrefixOf` url = Http
- | "udp://" `isPrefixOf` url = Udp
- | otherwise = UnknownProtocol
-
-
-msgHandler :: MsgChannel -> StateT TState IO ()
-msgHandler c = forever $ do
- st <- get
- peers <- liftIO $ readMVar (connectedPeers st)
- msg <- liftIO recvMsg
- liftIO $ sendResponse msg peers
- where
- recvMsg = readChan c
- sendResponse msg peers =
- case msg of
- GetConnectedPeersMsg var ->
- putMVar var peers
- _ ->
- putStrLn "Unhandled Tracker Msg"
-
-getConnectedPeers :: MsgChannel -> IO [Peer]
-getConnectedPeers c = do
- v <- newEmptyMVar
- writeChan c (GetConnectedPeersMsg v)
- readMVar v