diff --git a/ui/xemu-hud.cc b/ui/xemu-hud.cc index d8846d8922..74879529ca 100644 --- a/ui/xemu-hud.cc +++ b/ui/xemu-hud.cc @@ -823,6 +823,7 @@ class NetworkWindow { public: bool is_open; + int backend; char remote_addr[64]; char local_addr[64]; @@ -851,45 +852,56 @@ public: strncpy(remote_addr, tmp, sizeof(remote_addr)-1); xemu_settings_get_string(XEMU_SETTINGS_NETWORK_LOCAL_ADDR, &tmp); strncpy(local_addr, tmp, sizeof(local_addr)-1); + xemu_settings_get_enum(XEMU_SETTINGS_NETWORK_BACKEND, &backend); } - ImGui::TextWrapped( - "xemu socket networking works by sending and receiving packets over " - "UDP which encapsulate the network traffic that the machine would " - "send or receive when connected to a Local Area Network (LAN)." - ); - - ImGui::Dummy(ImVec2(0.0f, ImGui::GetStyle().WindowPadding.y)); - ImGui::Separator(); - ImGui::Dummy(ImVec2(0.0f, ImGui::GetStyle().WindowPadding.y)); - - ImGui::Columns(2, "", false); - ImGui::SetColumnWidth(0, ImGui::GetWindowWidth()*0.33); - ImGuiInputTextFlags flg = 0; bool is_enabled = xemu_net_is_enabled(); if (is_enabled) { flg |= ImGuiInputTextFlags_ReadOnly; } - ImGui::Text("Remote Host"); - ImGui::SameLine(); HelpMarker("The remote : to forward packets to (e.g. 1.2.3.4:9368)"); + ImGui::Columns(2, "", false); + ImGui::SetColumnWidth(0, ImGui::GetWindowWidth()*0.33); + + ImGui::Text("Attached To"); + ImGui::SameLine(); HelpMarker("The network backend which the emulated NIC interacts with"); ImGui::NextColumn(); - float w = ImGui::GetColumnWidth()-10*g_ui_scale; - ImGui::SetNextItemWidth(w); if (is_enabled) ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.6f); - ImGui::InputText("###remote_host", remote_addr, sizeof(remote_addr), flg); + int temp_backend = backend; // Temporary to make backend combo read-only (FIXME: surely there's a nicer way) + if (ImGui::Combo("##backend", is_enabled ? &temp_backend : &backend, "User (NAT)\0Socket\0") && !is_enabled) { + xemu_settings_set_enum(XEMU_SETTINGS_NETWORK_BACKEND, backend); + xemu_settings_save(); + } if (is_enabled) ImGui::PopStyleVar(); + ImGui::SameLine(); + if (backend == XEMU_NET_BACKEND_USER) { + HelpMarker("User-mode TCP/IP stack with a NAT'd network"); + } else if (backend == XEMU_NET_BACKEND_SOCKET_UDP) { + HelpMarker("Encapsulates link-layer traffic in UDP packets"); + } ImGui::NextColumn(); - ImGui::Text("Local Host"); - ImGui::SameLine(); HelpMarker("The local : to receive packets on (e.g. 0.0.0.0:9368)"); - ImGui::NextColumn(); - ImGui::SetNextItemWidth(w); - if (is_enabled) ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.6f); - ImGui::InputText("###local_host", local_addr, sizeof(local_addr), flg); - if (is_enabled) ImGui::PopStyleVar(); - ImGui::NextColumn(); + if (backend == XEMU_NET_BACKEND_SOCKET_UDP) { + ImGui::Text("Remote Host"); + ImGui::SameLine(); HelpMarker("The remote : to forward packets to (e.g. 1.2.3.4:9368)"); + ImGui::NextColumn(); + float w = ImGui::GetColumnWidth()-10*g_ui_scale; + ImGui::SetNextItemWidth(w); + if (is_enabled) ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.6f); + ImGui::InputText("###remote_host", remote_addr, sizeof(remote_addr), flg); + if (is_enabled) ImGui::PopStyleVar(); + ImGui::NextColumn(); + + ImGui::Text("Local Host"); + ImGui::SameLine(); HelpMarker("The local : to receive packets on (e.g. 0.0.0.0:9368)"); + ImGui::NextColumn(); + ImGui::SetNextItemWidth(w); + if (is_enabled) ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.6f); + ImGui::InputText("###local_host", local_addr, sizeof(local_addr), flg); + if (is_enabled) ImGui::PopStyleVar(); + ImGui::NextColumn(); + } ImGui::Columns(1); diff --git a/ui/xemu-net.c b/ui/xemu-net.c index 3432603eef..72acc822e0 100644 --- a/ui/xemu-net.c +++ b/ui/xemu-net.c @@ -46,16 +46,29 @@ void xemu_net_enable(void) return; } + int backend; const char *local_addr, *remote_addr; + xemu_settings_get_enum(XEMU_SETTINGS_NETWORK_BACKEND, &backend); xemu_settings_get_string(XEMU_SETTINGS_NETWORK_REMOTE_ADDR, &remote_addr); xemu_settings_get_string(XEMU_SETTINGS_NETWORK_LOCAL_ADDR, &local_addr); - // Create the UDP netdev - QDict *qdict = qdict_new(); - qdict_put_str(qdict, "id", id); - qdict_put_str(qdict, "type", "socket"); - qdict_put_str(qdict, "udp", remote_addr); - qdict_put_str(qdict, "localaddr", local_addr); + // Create the netdev + QDict *qdict; + if (backend == XEMU_NET_BACKEND_USER) { + qdict = qdict_new(); + qdict_put_str(qdict, "id", id); + qdict_put_str(qdict, "type", "user"); + } else if (backend == XEMU_NET_BACKEND_SOCKET_UDP) { + qdict = qdict_new(); + qdict_put_str(qdict, "id", id); + qdict_put_str(qdict, "type", "socket"); + qdict_put_str(qdict, "udp", remote_addr); + qdict_put_str(qdict, "localaddr", local_addr); + } else { + // Unsupported backend type + return; + } + QemuOpts *opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &error_abort); qobject_unref(qdict); netdev_add(opts, &local_err); diff --git a/ui/xemu-settings.c b/ui/xemu-settings.c index 267600b24d..14804872ba 100644 --- a/ui/xemu-settings.c +++ b/ui/xemu-settings.c @@ -56,6 +56,7 @@ struct xemu_settings { // [network] int net_enabled; // Boolean + int net_backend; char *net_local_addr; char *net_remote_addr; }; @@ -72,6 +73,12 @@ static const struct enum_str_map display_scale_map[DISPLAY_SCALE__COUNT+1] = { { 0, NULL }, }; +static const struct enum_str_map net_backend_map[XEMU_NET_BACKEND__COUNT+1] = { + { XEMU_NET_BACKEND_USER, "user" }, + { XEMU_NET_BACKEND_SOCKET_UDP, "udp" }, + { 0, NULL }, +}; + struct config_offset_table { enum config_types type; const char *section; @@ -102,6 +109,7 @@ struct config_offset_table { [XEMU_SETTINGS_INPUT_CONTROLLER_4_GUID] = { CONFIG_TYPE_STRING, "input", "controller_4_guid", offsetof(struct xemu_settings, controller_4_guid), { .default_str = "" } }, [XEMU_SETTINGS_NETWORK_ENABLED] = { CONFIG_TYPE_BOOL, "network", "enabled", offsetof(struct xemu_settings, net_enabled), { .default_bool = 0 } }, + [XEMU_SETTINGS_NETWORK_BACKEND] = { CONFIG_TYPE_ENUM, "network", "backend", offsetof(struct xemu_settings, net_backend), { .default_int = XEMU_NET_BACKEND_USER }, net_backend_map }, [XEMU_SETTINGS_NETWORK_LOCAL_ADDR] = { CONFIG_TYPE_STRING, "network", "local_addr", offsetof(struct xemu_settings, net_local_addr), { .default_str = "0.0.0.0:9368" } }, [XEMU_SETTINGS_NETWORK_REMOTE_ADDR] = { CONFIG_TYPE_STRING, "network", "remote_addr", offsetof(struct xemu_settings, net_remote_addr), { .default_str = "1.2.3.4:9368" } }, }; diff --git a/ui/xemu-settings.h b/ui/xemu-settings.h index e92ca66ea7..c7c26a6f64 100644 --- a/ui/xemu-settings.h +++ b/ui/xemu-settings.h @@ -43,6 +43,7 @@ enum xemu_settings_keys { XEMU_SETTINGS_INPUT_CONTROLLER_3_GUID, XEMU_SETTINGS_INPUT_CONTROLLER_4_GUID, XEMU_SETTINGS_NETWORK_ENABLED, + XEMU_SETTINGS_NETWORK_BACKEND, XEMU_SETTINGS_NETWORK_LOCAL_ADDR, XEMU_SETTINGS_NETWORK_REMOTE_ADDR, XEMU_SETTINGS__COUNT, @@ -58,6 +59,13 @@ enum DISPLAY_SCALE DISPLAY_SCALE_INVALID = -1 }; +enum xemu_net_backend { + XEMU_NET_BACKEND_USER, + XEMU_NET_BACKEND_SOCKET_UDP, + XEMU_NET_BACKEND__COUNT, + XEMU_NET_BACKEND_INVALID = -1 +}; + // Determine whether settings were loaded or not int xemu_settings_did_fail_to_load(void);