packages feed

Scurry-0.0.2: src/Scurry/Util.hs

module Scurry.Util(
    catch_to_maybe,
    inet_addr,
    inet_ntoa,
    sToMs,
    networkLowAddress,
    networkHighAddress,
    enumAllInMask,
    genRandAddr,
    isInMask,
) where

import qualified Network.Socket as INET (inet_addr,inet_ntoa)

import Data.Time
import Control.Monad
import System.Random
import System.IO.Unsafe (unsafePerformIO)

import Scurry.Types.Network
import Data.Bits

import Network.Util

{- I really don't like that inet_addr/inet_ntoa need to
 - run in IO. I also don't like how they throw errors
 - around instead of Nothing. I've fixed both problems! -}
catch_to_maybe :: (t -> IO a) -> t -> IO (Maybe a)
catch_to_maybe f a = catch (liftM Just (f a)) (\_ -> return Nothing)

inet_addr :: String -> Maybe ScurryAddress
inet_addr = unsafePerformIO .
              catch_to_maybe (\v -> liftM ScurryAddress (INET.inet_addr v))

inet_ntoa :: ScurryAddress -> Maybe String
inet_ntoa (ScurryAddress a) = unsafePerformIO $ catch_to_maybe INET.inet_ntoa a

-- | Seconds to milliseconds
sToMs :: Int -> Int
sToMs = (* 1000000)

genRandAddr :: [ScurryAddress] -> ScurryAddress -> ScurryAddress -> IO ScurryAddress
genRandAddr without mask net = do
    ct <- getCurrentTime

    let seed = 1000000000 * diffUTCTime ct (UTCTime (ModifiedJulianDay 0) 0)
        gen = mkStdGen $ round seed

    let (r,_) = randomR (0,100) gen
        a = (!! r) $ filter (not . flip elem without) $ enumAllInMask mask net

    return a
    

-- | Network utility functions

isInMask :: ScurryMask -> ScurryAddress -> ScurryAddress -> Bool
isInMask mask net addr = let m = scurryAddr mask
                             n = m .&. scurryAddr net
                             a = scurryAddr addr
                         in n == a
enumAllInMask :: ScurryMask -> ScurryAddress -> [ScurryAddress]
enumAllInMask mask net = let l = networkLowAddress mask net
                             h = networkHighAddress mask net
                         in eh l h
    where eh l' h' = if l' == h'
                        then h' : []
                        else l' : (eh (incrementAddress l') h')

incrementAddress :: ScurryAddress -> ScurryAddress
incrementAddress a = let a' = (ntohl . scurryAddr) a
                     in ScurryAddress $ htonl (a' + 1)

networkLowAddress :: ScurryMask -> ScurryAddress -> ScurryAddress
networkLowAddress mask addr = let a = (ntohl . scurryAddr) addr
                                  m = (ntohl . scurryAddr) mask
                                  n = a .&. m
                              in ScurryAddress $ htonl (n + 1)

networkHighAddress :: ScurryMask -> ScurryAddress -> ScurryAddress
networkHighAddress mask addr = let m = (ntohl . scurryAddr) mask
                                   a = (ntohl . scurryAddr) addr
                                   c = complement m
                                   n = (m .&. a) + c
                               in ScurryAddress $ htonl (n - 1) -- Highest address is broadcast