diff --git a/hamncheese/Scripts/edge.gd b/hamncheese/Scripts/edge.gd index 2241ef0..9d701d4 100644 --- a/hamncheese/Scripts/edge.gd +++ b/hamncheese/Scripts/edge.gd @@ -22,13 +22,16 @@ const MODE_READ := "r" const MODE_WRITE := "w" -var _edge_pid := -1 -var _udp := PacketPeerUDP.new() -var _sequence := 1 -var _password := "n2n" -var _data_buffer := {} -var _data_type := {} -var _timer : Timer +var _edge_pid := -1 +var _edge_running := false +var _udp := PacketPeerUDP.new() +var _sequence := 1 +var _password := "n2n" +var _data_buffer := {} +var _data_type := {} +var _timer : Timer +var _my_port := 0 +var _management_port := 0 signal data_recieved(type: String, data: Array) @@ -36,12 +39,18 @@ signal network_died func _on_timer_timeout(): - if !OS.is_process_running(_edge_pid): - stop_edge() - network_died.emit() - if _udp.is_socket_connected(): - _send("info") - _send("edges") + if _edge_running: + if _udp.is_socket_connected(): + _send("info") + _send("edges") + else: + _udp.bind(_my_port, "127.0.0.1") + _udp.connect_to_host("127.0.0.1", _management_port) + else: + if _edge_pid >= 0: + if OS.is_process_running(_edge_pid): + OS.kill(_edge_pid) + _edge_pid = -1 func _process(_delta): @@ -68,7 +77,47 @@ func _process(_delta): _data_buffer[received["_tag"]].append(received) -func _ready(): +func _send(what: String, mode: String = MODE_READ): + if _udp.is_socket_connected(): + var packet = mode + " " + str(_sequence) + ":1:" + _password + " " + what + _udp.put_packet(packet.to_ascii_buffer()) + _sequence += 1 + if _sequence > 999: + _sequence = 1 + + +func shutdown(): + if _edge_pid >= 0: + if OS.is_process_running(_edge_pid): + OS.kill(_edge_pid) + _edge_pid = -1 + _edge_running = false + + +func start_edge(community: String, key: String, supernode: String, port: int = 7777, my_port: int = 5643, management_port: int = 5644): + _my_port = my_port + _management_port = management_port + _timer = Timer.new() + _timer.wait_time = 3 + _timer.autostart = true + _timer.timeout.connect(_on_timer_timeout) + var binary = OS.get_user_data_dir() + "/edge" + var arguments = ["--management-password", _password, "-c", community, "-k", key, "-l", supernode + ":" + str(port)] + if OS.get_name() == "Windows": + binary = binary + ".exe" + else: + arguments.append("-f") + _password = Util.generate_password() + _edge_pid = await Process.elevate(binary, arguments) + if _edge_pid < 0: + await Dialog.alert("Error", "Unable to start network layer!") + return false + Engine.get_main_loop().current_scene.add_child(_timer) + _edge_running = true + return true + + +func startup(): # Extract the edge binary. var binary = OS.get_user_data_dir() + "/edge" if OS.get_name() == "Windows": @@ -81,42 +130,9 @@ func _ready(): OS.execute("chmod", ["+x", binary]) -func _send(what: String, mode: String = MODE_READ): - if _udp.is_socket_connected(): - var packet = mode + " " + str(_sequence) + ":1:" + _password + " " + what - _udp.put_packet(packet.to_ascii_buffer()) - _sequence += 1 - if _sequence > 999: - _sequence = 1 - - -func start_edge(community: String, key: String, supernode: String, port: int = 7777, my_port: int = 5643, management_port: int = 5644): - var binary = OS.get_user_data_dir() + "/edge" - var arguments = ["--management-password", _password, "-c", community, "-k", key, "-l", supernode + ":" + str(port)] - if OS.get_name() == "Windows": - binary = binary + ".exe" - _edge_pid = OS.create_process(binary, arguments, false) - else: - arguments.append("-f") - _password = Util.generate_password() - _edge_pid = await Process.elevate(binary, arguments) - if _edge_pid < 0: - await Dialog.alert("Error", "Unable to start network layer!") - return false - _udp.bind(my_port, "127.0.0.1") - _udp.connect_to_host("127.0.0.1", management_port) - _timer = Timer.new() - _timer.wait_time = 3 - _timer.autostart = true - _timer.timeout.connect(_on_timer_timeout) - Engine.get_main_loop().current_scene.add_child(_timer) - _timer.timeout.emit() - return true - - func stop_edge(): if _timer != null: _timer.queue_free() _send("stop", MODE_WRITE) _udp.close() - _edge_pid = -1 + _edge_running = false diff --git a/hamncheese/Scripts/main.gd b/hamncheese/Scripts/main.gd index 39bbcd8..649f41b 100644 --- a/hamncheese/Scripts/main.gd +++ b/hamncheese/Scripts/main.gd @@ -150,9 +150,20 @@ func _on_online_check_button_toggled(toggled_on): func _ready(): + Settings.startup() + Process.startup(PEER_BASE_PORT) + # If we're on Windows, be sure we're running as Administrator. + # This is going to bork up network shares later. + if OS.get_name() == "Windows": + if !Process.is_elevated(): + Process.elevate(OS.get_executable_path()) + Process.shutdown() + Engine.get_main_loop().quit() + Network.startup() + Peers.startup() + Edge.startup() Edge.data_recieved.connect(_data_recieved) Edge.network_died.connect(_network_died) - Process.startup(PEER_BASE_PORT) func _show_exit_dialog(): @@ -164,4 +175,5 @@ func _show_exit_dialog(): if online_check_button.button_pressed: _go_offline() Process.shutdown() + Edge.shutdown() Engine.get_main_loop().quit() diff --git a/hamncheese/Scripts/network.gd b/hamncheese/Scripts/network.gd index 5a68a9d..5ce261e 100644 --- a/hamncheese/Scripts/network.gd +++ b/hamncheese/Scripts/network.gd @@ -22,10 +22,6 @@ func _process(_delta): pass -func _ready(): - Peers.peer_received_packet.connect(_received_packet) - - func _received_packet(peer, verb, payload): match verb: "status": @@ -41,3 +37,7 @@ func _received_packet(peer, verb, payload): print(peer) print(payload) print() + + +func startup(): + Peers.peer_received_packet.connect(_received_packet) diff --git a/hamncheese/Scripts/peers.gd b/hamncheese/Scripts/peers.gd index 070e171..d85b64d 100644 --- a/hamncheese/Scripts/peers.gd +++ b/hamncheese/Scripts/peers.gd @@ -74,17 +74,6 @@ func _process(_delta): _tcp_server() -func _ready(): - _serverRunning = false - clear() - _timer = Timer.new() - _timer.wait_time = 1 - _timer.one_shot = false - _timer.timeout.connect(_on_timer_timeout) - Engine.get_main_loop().current_scene.add_child(_timer) - _timer.start() - - func _sort_by_ip(a, b): # Sort numerically. if Util.ip_string_to_int(a["ip"]) < Util.ip_string_to_int(b["ip"]): @@ -180,6 +169,17 @@ func start_server(address, portStart, user, uuid): _serverRunning = true +func startup(): + _serverRunning = false + clear() + _timer = Timer.new() + _timer.wait_time = 1 + _timer.one_shot = false + _timer.timeout.connect(_on_timer_timeout) + Engine.get_main_loop().current_scene.add_child(_timer) + _timer.start() + + func stop_server(): if _serverRunning: # Tear down network. diff --git a/hamncheese/Scripts/process.gd b/hamncheese/Scripts/process.gd index ac0397f..254e60c 100644 --- a/hamncheese/Scripts/process.gd +++ b/hamncheese/Scripts/process.gd @@ -44,9 +44,40 @@ func _elevate_unix(program: String, arguments: PackedStringArray): func _elevate_windows(program: String, arguments: PackedStringArray): - # powershell.exe -Command Start-Process edge.exe -ArgumentList 'stuff here' -Verb runAs - var options = ["-Command", "Start-Process", program, "-ArgumentList", "'" + " ".join(arguments) + "'", "-Verb", "runAs"] - var pid = OS.create_process("powershell.exe", options, true) + # powershell.exe -Command (Start-Process 'edge.exe' -ArgumentList 'stuff here' -Verb runAs -PassThru).Id + var pidFile := OS.get_user_data_dir() + "/elevate.pid" + var cmdFile := OS.get_user_data_dir() + "/elevate.cmd" + # Build the script to run. + var power := "@powershell.exe -Command (Start-Process '" + program + "'" + if arguments.size() > 0: + power += " -ArgumentList '" + " ".join(arguments) + "'" + power += " -Verb runAs -PassThru).Id > \"" + pidFile + "\"" + var handle = FileAccess.open(cmdFile, FileAccess.WRITE) + handle.store_line(power) + handle.close() + # Run it. + var cmdPid = OS.create_process(cmdFile, [], true) + # Wait for PID to be created. + var pid = -1 + var count := 5 + while !FileAccess.file_exists(pidFile) and count > 0: + OS.delay_msec(500) + count -= 1 + # We get a PID? + if count > 0: + # Read PID. + handle = FileAccess.open(pidFile, FileAccess.READ) + pid = int(handle.get_line()) + handle.close() + # Wait for batch to exit. + if cmdPid > 0: + while OS.is_process_running(cmdPid): + OS.delay_msec(500) + # Clean up. + if FileAccess.file_exists(cmdFile): + DirAccess.remove_absolute(cmdFile) + if FileAccess.file_exists(pidFile): + DirAccess.remove_absolute(pidFile) return pid @@ -64,17 +95,26 @@ func _process(_delta): peer.close() -func elevate(program: String, arguments: PackedStringArray): +func elevate(program: String, arguments: PackedStringArray = []): if OS.get_name() == "Windows": - return await _elevate_windows(program, arguments) + return _elevate_windows(program, arguments) else: return await _elevate_unix(program, arguments) +func is_elevated(): + if OS.get_name() == "Windows": + var result = OS.execute("net.exe", [ "sessions" ]) + return true if result == 0 else false + else: + return false # We don't support this on UNIX. + + func shutdown(): _udp.stop() - if FileAccess.file_exists(_ask_pass_script): - DirAccess.remove_absolute(_ask_pass_script) + if _ask_pass_script != "": + if FileAccess.file_exists(_ask_pass_script): + DirAccess.remove_absolute(_ask_pass_script) func startup(port: int = 19999): diff --git a/hamncheese/Scripts/settings.gd b/hamncheese/Scripts/settings.gd index 82a171b..f4fa79e 100644 --- a/hamncheese/Scripts/settings.gd +++ b/hamncheese/Scripts/settings.gd @@ -40,6 +40,36 @@ var uuid: String = "" var passwords := {} +func _init_crypto(): + _crypto = Crypto.new() + _key = CryptoKey.new() + if !FileAccess.file_exists("user://rsa.key") or !FileAccess.file_exists("user://rsa.crt"): + var cert = X509Certificate.new() + _key = _crypto.generate_rsa(4096) + cert = _crypto.generate_self_signed_certificate(_key, "CN=kangaroopunch.com,O=Kangaroo Punch Studios,C=US") + _key.save("user://rsa.key") + cert.save("user://rsa.crt") + else: + _key.load("user://rsa.key") + + +func _on_ip_check_button_toggled(_toggled_on): + ip_line_edit.editable = !ip_check_button.button_pressed + + +func _on_mac_check_button_toggled(_toggled_on): + mac_line_edit.editable = !mac_check_button.button_pressed + + +func _on_save_settings_button_pressed(): + save_settings() + settings_window.visible = false + + +func _on_settings_window_close_requested(): + settings_window.visible = false + + func load_settings(): # Do we have a configuration yet? passwords = {} @@ -125,37 +155,7 @@ func save_settings(): config.save("user://network.cfg") -func _init_crypto(): - _crypto = Crypto.new() - _key = CryptoKey.new() - if !FileAccess.file_exists("user://rsa.key") or !FileAccess.file_exists("user://rsa.crt"): - var cert = X509Certificate.new() - _key = _crypto.generate_rsa(4096) - cert = _crypto.generate_self_signed_certificate(_key, "CN=kangaroopunch.com,O=Kangaroo Punch Studios,C=US") - _key.save("user://rsa.key") - cert.save("user://rsa.crt") - else: - _key.load("user://rsa.key") - - -func _on_ip_check_button_toggled(_toggled_on): - ip_line_edit.editable = !ip_check_button.button_pressed - - -func _on_mac_check_button_toggled(_toggled_on): - mac_line_edit.editable = !mac_check_button.button_pressed - - -func _on_save_settings_button_pressed(): - save_settings() - settings_window.visible = false - - -func _on_settings_window_close_requested(): - settings_window.visible = false - - -func _ready(): +func startup(): _init_crypto() load_settings()