hstorchat-0.1.0.0: src/Main.hs
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Concurrent
import Control.Exception
import Control.Monad
import qualified Data.Map as M
import Data.Text as T
import Graphics.QML
import Network.Socket
import System.IO
import System.Process
import Network.HSTorChat.Client
import Network.HSTorChat.Protocol
import Paths_hstorchat
gentorrc :: String -> IO ()
gentorrc dd = writeFile (dd ++ "/torrc") $ Prelude.unlines
[ "SocksPort " ++ socksport
-- we don't use the control port currently, so leave this alone
--, "ControlPort 11119"
-- INCOMING connections for the hidden service arrive at 11009
-- and will be forwarded to TorChat at 127.0.0.1:22009
, "HiddenServiceDir " ++ dd ++ "/hidden_service"
, "HiddenServicePort " ++ hsport ++ " 127.0.0.1:" ++ hstcport
-- where should tor store it's cache files
, "DataDirectory " ++ dd ++ " tor_data"
-- some tuning
, "AvoidDiskWrites 1"
, "LongLivedPorts " ++ hstcport
, "FetchDirInfoEarly 1"
, "CircuitBuildTimeout 30"
, "NumEntryGuards 6"
-- You can uncomment the lines below to log Tor's activity to the
-- console or to a log file. Use this only during debugging!
-- Turning off SaveLogging will leave sensitive information on your disk,
-- the built in default is save logging turned on (set to 1).
-- so don't remove the # from that line unless you need it
-- and remember to put it in again, after you are done.
--, "Log info File tor.log"
--, "Log info stdout"
--, "SafeLogging 0"
]
where hsport = show hstorchatHSPort
hstcport = show hstorchatLocalPort
socksport = show torSocksPort
-- | Wait until the hidden service hostname file
-- is ready
hiddenServiceName :: IO String
hiddenServiceName = catch (do dd <- getDataDir
readFile $ dd ++ "/hidden_service/hostname")
(\e -> print (e :: IOException)
>> threadDelay 5000
>> hiddenServiceName)
main :: IO ()
main = withSocketsDo $ do
dd <- getDataDir
gentorrc dd
_ <- createProcess $ proc "tor" ["-f", dd ++ "/torrc"]
onion <- hiddenServiceName
let myonion = T.take 16 $ T.pack onion
putStr $ "Hello " ++ onion
sock <- socket AF_INET Stream 0
setSocketOption sock ReuseAddr 1
li <- inet_addr hstorchatHost
bindSocket sock $ SockAddrInet hstorchatLocalPort li
listen sock 2
buddies <- newMVar M.empty
p <- newMVar []
tc <- newObjectDC $ TorChat myonion Available buddies p
_ <- forkIO $ forever $ do
(insock,_) <- accept sock
iHdl <- socketToHandle insock ReadWriteMode
hSetBuffering iHdl LineBuffering
forkIO $ newConnectionRequest tc iHdl
doc <- getDataFileName "qml/HSTorChat.qml"
runEngineLoop defaultEngineConfig {
initialDocument = fileDocument doc
, contextObject = Just $ anyObjRef tc
}