]> git.rkrishnan.org Git - functorrent.git/blob - src/FuncTorrent/Utils.hs
more hlint fixes
[functorrent.git] / src / FuncTorrent / Utils.hs
1 {-
2  - Copyright (C) 2015-2016 Ramakrishnan Muthukrishnan <ram@rkrishnan.org>
3  -
4  - This file is part of FuncTorrent.
5  -
6  - FuncTorrent is free software; you can redistribute it and/or modify
7  - it under the terms of the GNU General Public License as published by
8  - the Free Software Foundation; either version 3 of the License, or
9  - (at your option) any later version.
10  -
11  - FuncTorrent is distributed in the hope that it will be useful,
12  - but WITHOUT ANY WARRANTY; without even the implied warranty of
13  - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  - GNU General Public License for more details.
15  -
16  - You should have received a copy of the GNU General Public License
17  - along with FuncTorrent; if not,  see <http://www.gnu.org/licenses/>
18  -}
19
20 module FuncTorrent.Utils
21        ( createDummyFile
22        , writeFileAtOffset
23        , readFileAtOffset
24        , splitNum
25        , splitN
26        , verifyHash
27        , IP
28        , Port
29        , toIP
30        , toPort
31        , getHostname
32        , getPort
33        )
34        where
35
36 import Prelude hiding (writeFile, take)
37
38 import qualified Crypto.Hash.SHA1 as SHA1 (hash)
39 import Control.Exception.Base (IOException, try)
40 import Data.ByteString (ByteString, writeFile, hPut, hGet, take)
41 import qualified Data.ByteString.Base16 as B16 (encode)
42 import qualified Data.ByteString.Char8 as BC
43 import Data.List (intercalate)
44 import System.IO (Handle, hSeek, SeekMode(..))
45 import System.Directory (doesFileExist)
46
47 type IP = String
48 type Port = Integer
49
50 splitN :: Int -> BC.ByteString -> [BC.ByteString]
51 splitN n bs | BC.null bs = []
52             | otherwise = BC.take n bs : splitN n (BC.drop n bs)
53
54 splitNum :: Integer -> Integer -> [Integer]
55 splitNum n d | n == 0 = []
56              | n < d = [n]
57              | otherwise = d : splitNum (n - d) d
58
59 createDummyFile :: FilePath -> Int -> IO (Either IOException ())
60 createDummyFile path size = do
61   dfe <- doesFileExist path
62   if not dfe
63     then
64     try $ writeFile path (BC.replicate size '\0')
65     else
66     return $ Right ()
67
68 -- write into a file at a specific offet
69 writeFileAtOffset :: Handle -> Integer -> ByteString -> IO ()
70 writeFileAtOffset h offset block = do
71   hSeek h AbsoluteSeek offset
72   hPut h block
73
74 readFileAtOffset :: Handle -> Integer -> Integer -> IO ByteString
75 readFileAtOffset h offset len = do
76   hSeek h AbsoluteSeek offset
77   hGet h (fromInteger len)
78
79 verifyHash :: ByteString -> ByteString -> Bool
80 verifyHash bs pieceHash =
81   take 20 (SHA1.hash bs) == pieceHash
82
83 toPort :: ByteString -> Port
84 toPort = read . ("0x" ++) . BC.unpack . B16.encode
85
86 toIP :: ByteString -> IP
87 toIP = Data.List.intercalate "." .
88        map (show . toInt . ("0x" ++) . BC.unpack) .
89        splitN 2 . B16.encode
90
91 toInt :: String -> Integer
92 toInt = read
93
94 getHostname :: String -> String
95 getHostname url = takeWhile (/= ':') $ drop 2 $ dropWhile (/= '/') url
96
97 getPort :: String -> Port
98 getPort url = read $ takeWhile (/= '/') $ drop 1 $ dropWhile (/= ':') $ drop 2 $ dropWhile (/= '/') url