aboutsummaryrefslogtreecommitdiffstats
path: root/src/Network/WireGuard/Daemon.hs
blob: 5b3f2259a622cdfb2e0d9ff913efca03a6e7e4f0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
module Network.WireGuard.Daemon
  ( runDaemon
  ) where

import           Control.Concurrent.Async               (async, cancel)
import           Control.Concurrent.STM                 (atomically)
import           Control.Monad                          (void)
import           GHC.Conc.IO                            (closeFdWith)
import           System.Directory                       (removeFile)
import           System.Posix.IO                        (closeFd)
import           System.Posix.Types                     (Fd)

import           Control.Concurrent.MVar
import           System.Posix.Signals

import           Network.WireGuard.Core                 (runCore)
import           Network.WireGuard.Internal.State       (createDevice)
import           Network.WireGuard.RPC                  (runRPC)
import           Network.WireGuard.TunListener          (runTunListener)
import           Network.WireGuard.UdpListener          (runUdpListener)

import           Network.WireGuard.Internal.Constant
import           Network.WireGuard.Internal.PacketQueue
import           Network.WireGuard.Internal.Util

runDaemon :: String -> FilePath -> [Fd] -> IO ()
runDaemon intfName sockPath tunFds = do
    device <- atomically $ createDevice intfName

    rpcThread <- async $ runRPC sockPath device

    readTunChan <- atomically $ newPacketQueue maxQueuedTunPackets
    writeTunChan <- atomically $ newPacketQueue maxQueuedTunPackets
    tunListenerThread <- async $ runTunListener tunFds readTunChan writeTunChan

    -- TODO: Support per-host packet queue
    -- TODO: Add timestamp and discard really ancient UDP packets
    readUdpChan <- atomically $ newPacketQueue maxQueuedUdpPackets
    writeUdpChan <- atomically $ newPacketQueue maxQueuedUdpPackets
    udpListenerThread <- async $ runUdpListener device readUdpChan writeUdpChan

    coreThread <- async $ runCore device readTunChan writeTunChan readUdpChan writeUdpChan

    died <- newEmptyMVar

    let dieGracefully = do
            mapM_ cancel [rpcThread, tunListenerThread, udpListenerThread, coreThread]
            mapM_ (closeFdWith closeFd) tunFds
            catchIOExceptionAnd (return ()) (removeFile sockPath)
            putMVar died ()

    void $ installHandler sigTERM (Catch dieGracefully) Nothing
    void $ installHandler sigINT (Catch dieGracefully) Nothing

    takeMVar died