# 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)