summaryrefslogtreecommitdiff
path: root/helper/bitmask_helper.nim
blob: 64333ee5b525c83684f9426d2932f382580c1970 (plain)
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# Bitmask Helper
# A privileged helper that should run as a service in windows.

import asyncdispatch, asyncnet
import strutils
import protocol
import osproc

type
  Client = ref object
    socket: AsyncSocket
    netAddr: string
    id: int
    connected: bool

  Server = ref object
    socket: AsyncSocket
    clients: seq[Client]
    openvpnProc: seq[Process]

proc newServer(): Server = Server(socket: newAsyncSocket(), clients: @[])
proc `$`(client: Client): string =
  $client.id & "(" & client.netAddr & ")"

#
# OpenVPN commands
# 

proc startOpenVPN(line: string, server: Server) =
  let parsed = parseMessage(line)
  echo(">>> start OpenVPN. \n  args:", parsed.args)
  if server.openvpnProc.len == 0:
    server.openvpnProc = @[]
  if server.openvpnProc.len > 0 and running(server.openvpnProc[0]):
    echo(">>> need to stop process first (len: ", server.openvpnProc.len, ")")
    return

  try:
    # TODO sanitize args
    let p = startProcess("c:/Program Files/OpenVPN/bin/openvpn.exe", args=split(parsed.args))
    echo "LEN: ", len(server.openvpnProc)
    if server.openvpnProc.len == 0:
      server.openvpnProc.add(p)
    else:
      server.openvpnProc[0] = p
  except OsError:
    echo("error while launching process!")


proc stopOpenVPN(line: string, server: Server) =
  echo(">>> stop OpenVPN, \n  args:", parseMessage(line).args)
  terminate(server.openvpnProc[0])


proc doStatus(line: string, server: Server) =
  if len(server.openvpnProc) == 1:
    echo "running: ", running(server.openvpnProc[0])
  else:
    echo "no proc created"

#
# processing commands loop
#

proc processCommands(server: Server, client: Client) {.async.} =
  while true:
    let line = await client.socket.recvLine()
    if line.len == 0:
      echo(client, " disconnected!")
      client.connected = false
      client.socket.close()
      return

    echo("debug: ", client, " received: ", line)

    try:
      let parsed = parseMessage(line)
      let cmd = parsed.cmd
      case cmd
      of "openvpn_start":
        startOpenVPN(line, server)
      of "openvpn_stop":
        stopOpenVPN(line, server)
      of "status":
        doStatus(line, server)
      of "ping":
        ping(line, server)
      else:
        echo("Invalid command: ", cmd)
   
    except MessageParsingError:
      echo("Invalid message:", line)


proc loop(server: Server, port = 7171) {.async.} =
  server.socket.bindAddr(port.Port, address = "127.0.0.1")
  server.socket.listen()

  while true:
    let (netAddr, clientSocket) = await server.socket.acceptAddr()
    echo("Accepted connection from ", netAddr)
    let client = Client(
      socket: clientSocket,
      netAddr: netAddr,
      id: server.clients.len,
      connected: true
    )
    server.clients.add(client)
    asyncCheck processCommands(server, client)

var server = newServer()
waitFor loop(server)