packages feed

sshtun-1.0.0: src/Sshtun/Tunnel.hs

-- Copyright: 2012 Dino Morelli
-- License: BSD3 (see LICENSE)
-- Author: Dino Morelli <dino@ui3.info>

module Sshtun.Tunnel
   ( tunnelStart
   )
   where

import Control.Concurrent.STM
import System.Process
import Text.Printf

import Sshtun.Common
import Sshtun.Conf
import Sshtun.Log


{- This is an ugly hack to delay things until after switchWatcher 
   reads the flag status
-}
tunnelStart :: Conf -> TVar Shared -> IO ()
tunnelStart c s = sleep 5 >> tunnelManager c s


{- This is the tunnel managing loop, tries to keep it running,
   if desired
-}
tunnelManager :: Conf -> TVar Shared -> IO ()
tunnelManager conf shared = do
   state <- atomically . readTVar $ shared

   case state of
      (Stopped, Run) -> do
         -- Tunnel is stopped, but we'd like it to be started

         logM INFO "Tunnel manager starting tunnel"
         ph <- runCommand $ printf "ssh -p %d -N -R %d:localhost:%d %s %s@%s"
            (sshPort conf) (remotePort conf) (localPort conf)
            (addlSshArgs conf) (remoteUser conf) (remoteHost conf)
         atomically $ writeTVar shared (Running ph, Run)

         -- Then, we wait. Possibly for a long time
         _ <- waitForProcess ph

         -- Tunnel has (possibly unexpectedly) stopped, make a note of this
         logM INFO "Tunnel manager unblocked"
         -- Read this again, may have changed during long wait
         (_, dst) <- atomically . readTVar $ shared
         atomically $ writeTVar shared (Stopped, dst)
      _ -> return ()

   sleep $ tunnelRetryDelay conf
   tunnelManager conf shared