packages feed

haskell-tor-0.1.0.0: exe/Main.hs

{-# LANGUAGE CPP              #-}
{-# LANGUAGE RecordWildCards  #-}
import Data.ByteString.Char8(ByteString,pack)
import qualified Data.ByteString.Lazy as L
import Tor
import Tor.Flags
import Tor.NetworkStack

#ifdef HaLVM_HOST_OS
import Hans.Device.Xen
import Hans.DhcpClient
import Hans.NetworkStack hiding (listen, accept)
import Hypervisor.Console
import Hypervisor.XenStore
import Tor.NetworkStack.Hans
import XenDevice.NIC
#else
import Hans.Device.Tap
import Hans.DhcpClient
import Hans.NetworkStack hiding (listen, accept)
import System.IO
import Tor.NetworkStack.Hans
import Tor.NetworkStack.System
#endif

import qualified Data.ByteString as S
import Tor.Link
import Tor.Circuit
import Tor.State.Credentials
import Control.Concurrent
import Crypto.Random
import Tor.RouterDesc
import Tor.DataFormat.Helpers
import Tor.State.Directories
import Tor.State.Routers

--main :: IO ()
--main = runDefaultMain $ \ flags ->
--  do rngMV <- newMVar =<< drgNew
--     addrsMV <- newMVar []
--     (MkNS ns, logger) <- initializeSystem flags
----      dirdb <- newDirectoryDatabase ns logger
----      db <- newRouterDatabase ns dirdb logger
--     creds <- newCredentials logger
--     [_,printAscii] <- words `fmap` readFile "/Users/awick/.tor/fingerprint"
--     keyfile <- S.readFile "/Users/awick/.tor/keys/secret_onion_key_ntor"
--     let target = blankRouterDesc { routerIPv4Address  = "10.0.1.27"
--                                  , routerORPort       = 9001
--                                  , routerFingerprint  = readHex printAscii
--                                  , routerNTorOnionKey = Just (S.drop 64 keyfile)
--                                  }
----     second <- modifyMVar rngMV (getRouter db [])
----     third <- modifyMVar rngMV (getRouter db [])
--     link <- initLink ns creds rngMV addrsMV logger target
--     circId <- modifyMVar rngMV (linkNewCircuitId link)
--     circ <- createCircuit rngMV logger link target circId
----     extendCircuit circ second
----     putStrLn "Done."
----     extendCircuit circ third
----     putStrLn "Done."
--     foo <- resolveName circ "galois.com"
--     putStrLn ("Foo: " ++ show foo)

main :: IO ()
main = runDefaultMain $ \ flags ->
  do (MkNS ns, logger)  <- initializeSystem flags
     let options   = defaultTorOptions{
                       torLog = logger
                     , torRelayOptions = Just defaultTorRelayOptions {
                            torOnionPort = getOnionPort flags
                          , torNickname  = getNickname flags
                          , torContact   = getContactInfo flags
                          }
                     }
     tor <- startTor ns options
     addrs <- torResolveName tor "www.whatismypublicip.com"
     case addrs of
       [] ->
         putStrLn ("Could not resolve www.whatismypublicip.com!")
       ((addr, _ttl) : _) ->
         do sock <- torConnect tor addr 80
            torWrite sock (buildGet "/")
            resp <- readLoop sock
            torClose sock ReasonDone

buildGet :: String -> ByteString
buildGet str = result
 where
  result      = pack (requestLine ++ userAgent ++ crlf)
  requestLine = "GET " ++ str ++ " HTTP/1.0\r\n"
  userAgent   = "User-Agent: CERN-LineMode/2.15 libwww/2.17b3\r\n"
  crlf        = "\r\n"

readLoop :: TorSocket -> IO L.ByteString
readLoop sock =
  do next <- torRead sock 256
     if L.length next < 256
        then return next
        else do rest <- readLoop sock
                return (next `L.append` rest)

-- -----------------------------------------------------------------------------

initializeSystem :: [Flag] ->
                    IO (SomeNetworkStack, String -> IO ())
#ifdef HaLVM_HOST_OS
initializeSystem _ =
  do con    <- initXenConsole
     xs     <- initXenStore
     ns     <- newNetworkStack
     macstr <- findNIC xs
     nic    <- openNIC xs macstr
     let mac = read macstr
     addDevice ns mac (xenSend nic) (xenReceiveLoop nic)
     deviceUp ns mac
     ipaddr <- dhcpDiscover ns mac
     return (MkNS (hansNetworkStack ns), makeLogger (\ x -> writeConsole con (x ++ "\n")))
 where
  findNIC xs =
    do nics <- listNICs xs
       case nics of
         []    -> threadDelay 1000000 >> findNIC xs
         (x:_) -> return x
#else
initializeSystem flags =
  case getTapDevice flags of
    Nothing ->
      do logger <- generateLogger flags
         return (MkNS systemNetworkStack, logger)
    Just tapName ->
      do mfd <- openTapDevice tapName
         case mfd of
           Nothing ->
             fail ("Couldn't open tap device " ++ tapName)
           Just fd ->
             do ns <- newNetworkStack
                logger <- generateLogger flags
                let mac = read "52:54:00:12:34:56"
                addDevice ns mac (tapSend fd) (tapReceiveLoop fd)
                deviceUp ns mac
                ipaddr <- dhcpDiscover ns mac
                logger ("Node has IP Address " ++ show ipaddr)
                return (MkNS (hansNetworkStack ns), logger)

generateLogger :: [Flag] -> IO (String -> IO ())
generateLogger []                 = return (makeLogger (hPutStrLn stdout))
generateLogger ((OutputLog fp):_) = do h <- openFile fp AppendMode
                                       return (makeLogger (hPutStrLn h))
generateLogger (_:rest)           = generateLogger rest
#endif