packages feed

Scurry-0.0.1: src/scurry.hs

module Main where

import System.Console.GetOpt
import System.Environment
import System.IO
import System.Exit

import Network.Socket (withSocketsDo)
import Network.BSD

import Scurry.Peer
import Scurry.Comm
-- import Scurry.Management.Config
-- import Scurry.Management.Tracker
import Scurry.State
import Scurry.Util(inet_addr)
import Scurry.Network
import Scurry.Types.Network
import Data.Word
import Data.Maybe

data ScurryOpts = ScurryOpts {
    vpnAddr  :: Maybe ScurryAddress,
    vpnMask  :: Maybe ScurryMask,
    bindAddr :: ScurryAddress,
    bindPort :: ScurryPort,
    peers    :: [EndPoint]
} deriving (Show)

data ScurryOpt = SOVAddr ScurryAddress
               | SOVMask ScurryMask
               | SOBAddr ScurryAddress
               | SOBPort ScurryPort
    deriving (Show)

defaultPort :: ScurryPort
defaultPort = ScurryPort 24999

readPort :: String -> ScurryPort
readPort [] = error "I need some numbers!"
readPort s = let w = read s :: Word16
             in (ScurryPort . fromIntegral) w

lookupName :: String -> IO EndPoint
lookupName ep = do
    let name = takeWhile (/=':') ep
        port = case drop 1 $ dropWhile (/=':') ep of
                    [] -> defaultPort
                    x  -> readPort x

    HostEntry { hostAddresses = as } <- getHostByName name

    return $ EndPoint (ScurryAddress (as !! 0)) port
          
parseScurryOpts :: [String] -> IO (Either String ScurryOpts)
parseScurryOpts args = let def_opt = ScurryOpts { vpnAddr = Nothing
                                                , vpnMask = Nothing
                                                , bindAddr = ScurryAddress 0
                                                , bindPort = ScurryPort 24999
                                                , peers = [] }
                           va_t = SOVAddr . fromJust . inet_addr
                           vm_t = SOVMask . fromJust . inet_addr
                           ba_t = SOBAddr . fromJust . inet_addr
                           bp_t = SOBPort . readPort
                           options = [ Option "a" ["vpn-addr"]  (ReqArg va_t "VPN_ADDRESS")  "The IP address to use for the VPN."
                                     , Option "m" ["vpn-mask"]  (ReqArg vm_t "VPN_NETMASK")  "The network mask the for the VPN."
                                     , Option "b" ["bind-addr"] (ReqArg ba_t "BIND_ADDRESS") "The network interface on which listen for connections."
                                     , Option "p" ["bind-port"] (ReqArg bp_t "BIND_PORT")    "The port on which to listen for connections." ]
                           (m,o,_) = getOpt RequireOrder options args -- ignore errors for now
                           u = Left (usageInfo "How to use scurry." options)
                           opt' = foldr rplcOpts def_opt m
                       in case args of
                               ["-h"]     -> return u
                               ["--help"] -> return u
                               _          -> do ps <- mapM lookupName o
                                                return $ Right (opt' { peers = ps })

    where rplcOpts (SOVAddr a) sos = sos { vpnAddr  = Just a }
          rplcOpts (SOVMask m) sos = sos { vpnMask  = Just m }
          rplcOpts (SOBAddr a) sos = sos { bindAddr = a }
          rplcOpts (SOBPort p) sos = sos { bindPort = p }

main :: IO ()
main = withSocketsDo $ do 
    args <- getArgs

    opts_ <- parseScurryOpts args
    -- let (configPath:trackerPath:_) = args

    opts <- case opts_ of
                 (Left msg) -> putStrLn msg >> exitFailure
                 (Right p)  -> return p

    -- (Just config)  <- load_scurry_config_file configPath
    -- (Just tracker) <- load_tracker_file trackerPath

    -- let (Scurry (VpnConfig tapIp tapMask) (NetworkConfig mySockAddr)) = config
    --     trackerEndPoints = filter (/= mySockAddr) $ map tToS tracker

    let initState = ScurryState {
            scurryPeers = [],
            scurryEndPoint = EndPoint (bindAddr opts) (bindPort opts),
            scurryNetwork = ScurryNetwork {
                scurryMask = vpnMask opts
            },
            scurryMyRecord = PeerRecord {
                peerMAC = Nothing,
                peerEndPoint = EndPoint (ScurryAddress 0) (ScurryPort 0),
                peerVPNAddr = vpnAddr opts,
                peerLocalPort = bindPort opts -- (\(EndPoint _ p) -> p) mySockAddr
            }
        }
        tapNet = (vpnAddr opts, vpnMask opts)

    local <- prepEndPoint (scurryEndPoint initState) -- mySockAddr

    startCom tapNet local initState (peers opts)

    {-
    where
        tToS (ScurryPeer ip port) = EndPoint ip port 
    -}


{-
getAddress :: Socket -> [EndPoint] -> IO (ScurryAddress, ScurryMask)
getAddress sock (t:trackers) = do
    let msg = SAddrRequest
        cmd = sendToAddr sock msg
    
    putStrLn "Requesting address..."
    cmd t

    where
        delayRead = do
            threadDelay (sToMs 1.5)
-}