+{-
+ - 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/>
+ -}
+
module FuncTorrent.Utils
- (createDummyFile,
- writeFileAtOffset,
- readFileAtOffset,
- splitNum,
- splitN,
- verifyHash
+ ( createDummyFile
+ , writeFileAtOffset
+ , readFileAtOffset
+ , splitNum
+ , splitN
+ , verifyHash
+ , IP
+ , Port
+ , toIP
+ , toPort
+ , getHostname
+ , getPort
)
where
import qualified Crypto.Hash.SHA1 as SHA1 (hash)
import Control.Exception.Base (IOException, try)
import Data.ByteString (ByteString, writeFile, hPut, hGet, take)
+import qualified Data.ByteString.Base16 as B16 (encode)
import qualified Data.ByteString.Char8 as BC
-import System.IO (withFile, hSeek, IOMode(..), SeekMode(..))
+import Data.List (intercalate)
+import System.IO (Handle, hSeek, SeekMode(..))
import System.Directory (doesFileExist)
+type IP = String
+type Port = Integer
+
splitN :: Int -> BC.ByteString -> [BC.ByteString]
splitN n bs | BC.null bs = []
| otherwise = BC.take n bs : splitN n (BC.drop n bs)
createDummyFile path size = do
dfe <- doesFileExist path
if not dfe
- then do
+ then
try $ writeFile path (BC.replicate size '\0')
else
return $ Right ()
-- write into a file at a specific offet
-writeFileAtOffset :: FilePath -> Integer -> ByteString -> IO ()
-writeFileAtOffset path offset block =
- withFile path ReadWriteMode (\h -> do
- hSeek h AbsoluteSeek offset
- hPut h block)
-readFileAtOffset :: FilePath -> Integer -> Integer -> IO ByteString
-readFileAtOffset path offset len =
- withFile path ReadWriteMode (\h -> do
- hSeek h AbsoluteSeek offset
- hGet h (fromInteger len))
+writeFileAtOffset :: Handle -> Integer -> ByteString -> IO ()
+writeFileAtOffset h offset block = do
+ hSeek h AbsoluteSeek offset
+ hPut h block
+
+readFileAtOffset :: Handle -> Integer -> Integer -> IO ByteString
+readFileAtOffset h offset len = do
+ hSeek h AbsoluteSeek offset
+ hGet h (fromInteger len)
verifyHash :: ByteString -> ByteString -> Bool
verifyHash bs pieceHash =
take 20 (SHA1.hash bs) == pieceHash
+
+toPort :: ByteString -> Port
+toPort = read . ("0x" ++) . BC.unpack . B16.encode
+
+toIP :: ByteString -> IP
+toIP = Data.List.intercalate "." .
+ map (show . toInt . ("0x" ++) . BC.unpack) .
+ splitN 2 . B16.encode
+
+toInt :: String -> Integer
+toInt = read
+
+getHostname :: String -> String
+getHostname url = takeWhile (/= ':') $ drop 2 $ dropWhile (/= '/') url
+
+getPort :: String -> Port
+getPort url = read $ takeWhile (/= '/') $ drop 1 $ dropWhile (/= ':') $ drop 2 $ dropWhile (/= '/') url