(TState(..),
initialTrackerState,
trackerLoop,
+ udpTrackerLoop
) where
import Prelude hiding (lookup, splitAt)
-import System.IO (Handle)
+
import Control.Applicative (liftA2)
import Control.Concurrent (threadDelay)
import Control.Concurrent.MVar (MVar, newEmptyMVar, newMVar, readMVar, putMVar)
+import Control.Exception (try)
import Data.Binary (Binary(..), encode, decode)
import Data.Binary.Put (putWord16be, putWord32be, putWord64be, putByteString)
import Data.Binary.Get (Get, isEmpty, getByteString, getWord16be, getWord32be)
import Data.Char (chr)
import Data.List (intercalate, isPrefixOf)
import Data.Map as M (lookup)
-import Network (PortNumber)
+import Network (connectTo, PortID(..), PortNumber, Socket)
+import Network.Socket (defaultProtocol, SocketType( Datagram ), Family( AF_INET ), SockAddr( SockAddrInet ), inet_addr, socket)
+import Network.Socket.ByteString (sendTo, recv)
import Network.HTTP.Base (urlEncode)
import qualified Data.ByteString.Base16 as B16 (encode)
import FuncTorrent.Peer (Peer(..))
import FuncTorrent.Utils (splitN)
-
data TrackerProtocol = Http
| Udp
| UnknownProtocol
trackerLoop port peerId m st
-- udp tracker
-getResponse :: Handle -> IO UDPResponse
-getResponse h = do
+getResponse :: Socket -> IO UDPResponse
+getResponse s = do
-- connect packet is 16 bytes long
-- announce packet is atleast 20 bytes long
- bs <- hGet h (16*1024)
+ bs <- recv s (16*1024)
return $ decode $ fromStrict bs
-sendRequest :: Handle -> UDPRequest -> IO ()
-sendRequest h req = hPut h bsReq
- where bsReq = toStrict $ encode req
+sendRequest :: Socket -> String -> PortNumber -> UDPRequest -> IO ()
+sendRequest s ip port req = do
+ hostaddr <- inet_addr ip
+ _ <- sendTo s bsReq $ SockAddrInet (fromIntegral port) hostaddr
+ return ()
+ where bsReq = toStrict $ encode req
getTrackerType :: String -> TrackerProtocol
getTrackerType url | isPrefixOf "http://" url = Http
| isPrefixOf "udp://" url = Udp
| otherwise = UnknownProtocol
+
+udpTrackerLoop :: PortNumber -> String -> Metainfo -> TState -> IO String
+udpTrackerLoop port peerId m st = do
+ -- h <- connectTo "exodus.desync.com" (PortNumber 6969)
+ s <- socket AF_INET Datagram defaultProtocol
+ hostAddr <- inet_addr "185.37.101.229"
+ putStrLn "connected to tracker"
+ _ <- sendTo s (toStrict $ encode (ConnectReq 42)) (SockAddrInet 2710 hostAddr)
+ putStrLn "--> sent ConnectReq to tracker"
+ resp <- recv s 16
+ putStrLn "<-- recv ConnectResp from tracker"
+ return $ show resp