diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt
index ea685b817d..8dc9e619c5 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt
@@ -23,6 +23,12 @@ enum class StringSetting(
"BBA_BUILTIN_DNS",
"3.18.217.27"
),
+ MAIN_BBA_TAPSERVER_DESTINATION(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "BBA_TAPSERVER_DESTINATION",
+ "/tmp/dolphin-tap"
+ ),
MAIN_CUSTOM_RTC_VALUE(
Settings.FILE_DOLPHIN,
Settings.SECTION_INI_CORE,
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt
index 44e2b2b915..ef395ed6a4 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt
@@ -1101,6 +1101,17 @@ class SettingsFragmentPresenter(
R.string.xlink_kai_bba_ip_description
)
)
+ } else if (serialPort1Type == 11) {
+ // Broadband Adapter (tapserver)
+ sl.add(
+ InputStringSetting(
+ context,
+ StringSetting.MAIN_BBA_TAPSERVER_DESTINATION,
+ R.string.bba_tapserver_destination,
+ R.string.bba_tapserver_destination_description
+ )
+ )
+ }
} else if (serialPort1Type == 12) {
// Broadband Adapter (Built In)
sl.add(
diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml
index 251886b98a..2e8fc6856e 100644
--- a/Source/Android/app/src/main/res/values/strings.xml
+++ b/Source/Android/app/src/main/res/values/strings.xml
@@ -133,6 +133,8 @@
For setup instructions, refer to this page.
XLink Kai IP Address/hostname
IP address or hostname of device running the XLink Kai client
+ Tapserver destination
+ Enter the socket path or netloc (address:port) of the tapserver instance
DNS Server
Use 8.8.8.8 for normal DNS, else enter your custom one
diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt
index 290947e722..945c57760d 100644
--- a/Source/Core/Core/CMakeLists.txt
+++ b/Source/Core/Core/CMakeLists.txt
@@ -696,6 +696,7 @@ if(WIN32)
target_sources(core PRIVATE
HW/EXI/BBA/TAP_Win32.cpp
HW/EXI/BBA/TAP_Win32.h
+ HW/EXI/BBA/TAPServer.cpp
HW/EXI/BBA/XLINK_KAI_BBA.cpp
HW/EXI/BBA/BuiltIn.cpp
HW/EXI/BBA/BuiltIn.h
@@ -712,7 +713,7 @@ if(WIN32)
elseif(APPLE)
target_sources(core PRIVATE
HW/EXI/BBA/TAP_Apple.cpp
- HW/EXI/BBA/TAPServer_Apple.cpp
+ HW/EXI/BBA/TAPServer.cpp
HW/EXI/BBA/XLINK_KAI_BBA.cpp
HW/EXI/BBA/BuiltIn.cpp
HW/EXI/BBA/BuiltIn.h
@@ -721,6 +722,7 @@ elseif(APPLE)
elseif(UNIX)
target_sources(core PRIVATE
HW/EXI/BBA/TAP_Unix.cpp
+ HW/EXI/BBA/TAPServer.cpp
HW/EXI/BBA/XLINK_KAI_BBA.cpp
HW/EXI/BBA/BuiltIn.cpp
HW/EXI/BBA/BuiltIn.h
@@ -778,4 +780,4 @@ endif()
if(USE_RETRO_ACHIEVEMENTS)
target_link_libraries(core PRIVATE rcheevos)
target_compile_definitions(core PRIVATE -DUSE_RETRO_ACHIEVEMENTS)
-endif()
\ No newline at end of file
+endif()
diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp
index 21c453b6c7..cdd852c260 100644
--- a/Source/Core/Core/Config/MainSettings.cpp
+++ b/Source/Core/Core/Config/MainSettings.cpp
@@ -137,6 +137,8 @@ const Info MAIN_BBA_XLINK_CHAT_OSD{{System::Main, "Core", "BBA_XLINK_CHAT_
// Schthack PSO Server - https://schtserv.com/
const Info MAIN_BBA_BUILTIN_DNS{{System::Main, "Core", "BBA_BUILTIN_DNS"},
"3.18.217.27"};
+const Info MAIN_BBA_TAPSERVER_DESTINATION{
+ {System::Main, "Core", "BBA_TAPSERVER_DESTINATION"}, "/tmp/dolphin-tap"};
const Info MAIN_BBA_BUILTIN_IP{{System::Main, "Core", "BBA_BUILTIN_IP"}, ""};
const Info& GetInfoForSIDevice(int channel)
diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h
index dddda8ae7a..b13615df5d 100644
--- a/Source/Core/Core/Config/MainSettings.h
+++ b/Source/Core/Core/Config/MainSettings.h
@@ -96,6 +96,7 @@ extern const Info MAIN_BBA_XLINK_IP;
extern const Info MAIN_BBA_XLINK_CHAT_OSD;
extern const Info MAIN_BBA_BUILTIN_DNS;
extern const Info MAIN_BBA_BUILTIN_IP;
+extern const Info MAIN_BBA_TAPSERVER_DESTINATION;
const Info& GetInfoForSIDevice(int channel);
const Info& GetInfoForAdapterRumble(int channel);
const Info& GetInfoForSimulateKonga(int channel);
diff --git a/Source/Core/Core/HW/EXI/BBA/TAPServer_Apple.cpp b/Source/Core/Core/HW/EXI/BBA/TAPServer.cpp
similarity index 54%
rename from Source/Core/Core/HW/EXI/BBA/TAPServer_Apple.cpp
rename to Source/Core/Core/HW/EXI/BBA/TAPServer.cpp
index de71067c1b..3e0644a41b 100644
--- a/Source/Core/Core/HW/EXI/BBA/TAPServer_Apple.cpp
+++ b/Source/Core/Core/HW/EXI/BBA/TAPServer.cpp
@@ -3,10 +3,16 @@
#include "Core/HW/EXI/EXI_DeviceEthernet.h"
+#ifdef _WIN32
+#include
+#include
+#else
#include
#include
+#include
#include
#include
+#endif
#include "Common/CommonFuncs.h"
#include "Common/Logging/Log.h"
@@ -15,42 +21,84 @@
namespace ExpansionInterface
{
-// This interface is only implemented on macOS, since macOS needs a replacement
-// for TunTap when the kernel extension is no longer supported. This interface
-// only appears in the menu on macOS, so on other platforms, it does nothing and
-// refuses to activate.
-constexpr char socket_path[] = "/tmp/dolphin-tap";
+static int ConnectToDestination(const std::string& destination)
+{
+ if (destination.empty())
+ {
+ INFO_LOG_FMT(SP1, "Cannot connect: destination is empty\n");
+ return -1;
+ }
+
+ size_t ss_size;
+ struct sockaddr_storage ss;
+ memset(&ss, 0, sizeof(ss));
+ if (destination[0] != '/')
+ { // IP address or hostname
+ size_t colon_offset = destination.find(':');
+ if (colon_offset == std::string::npos)
+ {
+ INFO_LOG_FMT(SP1, "Destination IP address does not include port\n");
+ return -1;
+ }
+
+ struct sockaddr_in* sin = reinterpret_cast(&ss);
+ sin->sin_addr.s_addr = htonl(sf::IpAddress(destination.substr(0, colon_offset)).toInteger());
+ sin->sin_family = AF_INET;
+ sin->sin_port = htons(stoul(destination.substr(colon_offset + 1)));
+ ss_size = sizeof(*sin);
+#ifndef _WIN32
+ }
+ else
+ { // UNIX socket
+ struct sockaddr_un* sun = reinterpret_cast(&ss);
+ if (destination.size() + 1 > sizeof(sun->sun_path))
+ {
+ INFO_LOG_FMT(SP1, "Socket path is too long, unable to init BBA\n");
+ return -1;
+ }
+ sun->sun_family = AF_UNIX;
+ strcpy(sun->sun_path, destination.c_str());
+ ss_size = sizeof(*sun);
+#else
+ }
+ else
+ {
+ INFO_LOG_FMT(SP1, "UNIX sockets are not supported on Windows\n");
+ return -1;
+#endif
+ }
+
+ int fd = socket(ss.ss_family, SOCK_STREAM, (ss.ss_family == AF_INET) ? IPPROTO_TCP : 0);
+ if (fd == -1)
+ {
+ INFO_LOG_FMT(SP1, "Couldn't create socket; unable to init BBA\n");
+ return -1;
+ }
+
+#ifdef __APPLE__
+ int opt_no_sigpipe = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &opt_no_sigpipe, sizeof(opt_no_sigpipe)) < 0)
+ INFO_LOG_FMT(SP1, "Failed to set SO_NOSIGPIPE on socket\n");
+#endif
+
+ if (connect(fd, reinterpret_cast(&ss), ss_size) == -1)
+ {
+ std::string s = Common::LastStrerrorString();
+ INFO_LOG_FMT(SP1, "Couldn't connect socket ({}), unable to init BBA\n", s.c_str());
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
bool CEXIETHERNET::TAPServerNetworkInterface::Activate()
{
if (IsActivated())
return true;
- sockaddr_un sun = {};
- if (sizeof(socket_path) > sizeof(sun.sun_path))
- {
- ERROR_LOG_FMT(SP1, "Socket path is too long, unable to init BBA");
- return false;
- }
- sun.sun_family = AF_UNIX;
- strcpy(sun.sun_path, socket_path);
-
- fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd == -1)
- {
- ERROR_LOG_FMT(SP1, "Couldn't create socket, unable to init BBA");
- return false;
- }
-
- if (connect(fd, reinterpret_cast(&sun), sizeof(sun)) == -1)
- {
- ERROR_LOG_FMT(SP1, "Couldn't connect socket ({}), unable to init BBA",
- Common::LastStrerrorString());
- close(fd);
- fd = -1;
- return false;
- }
+ fd = ConnectToDestination(m_destination);
INFO_LOG_FMT(SP1, "BBA initialized.");
return RecvInit();
diff --git a/Source/Core/Core/HW/EXI/EXI_Device.cpp b/Source/Core/Core/HW/EXI/EXI_Device.cpp
index 425ce9dbb2..ad25a94522 100644
--- a/Source/Core/Core/HW/EXI/EXI_Device.cpp
+++ b/Source/Core/Core/HW/EXI/EXI_Device.cpp
@@ -137,11 +137,9 @@ std::unique_ptr EXIDevice_Create(Core::System& system, const EXIDevi
result = std::make_unique(system, BBADeviceType::TAP);
break;
-#if defined(__APPLE__)
case EXIDeviceType::EthernetTapServer:
result = std::make_unique(system, BBADeviceType::TAPSERVER);
break;
-#endif
case EXIDeviceType::EthernetXLink:
result = std::make_unique(system, BBADeviceType::XLINK);
diff --git a/Source/Core/Core/HW/EXI/EXI_Device.h b/Source/Core/Core/HW/EXI/EXI_Device.h
index 2c90d772f9..c927a255d3 100644
--- a/Source/Core/Core/HW/EXI/EXI_Device.h
+++ b/Source/Core/Core/HW/EXI/EXI_Device.h
@@ -39,7 +39,6 @@ enum class EXIDeviceType : int
MemoryCardFolder,
AGP,
EthernetXLink,
- // Only used on Apple devices.
EthernetTapServer,
EthernetBuiltIn,
None = 0xFF
diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp
index 549ace3a6e..fb2660ed04 100644
--- a/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp
+++ b/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp
@@ -50,12 +50,11 @@ CEXIETHERNET::CEXIETHERNET(Core::System& system, BBADeviceType type) : IEXIDevic
m_network_interface = std::make_unique(this);
INFO_LOG_FMT(SP1, "Created TAP physical network interface.");
break;
-#if defined(__APPLE__)
case BBADeviceType::TAPSERVER:
- m_network_interface = std::make_unique(this);
+ m_network_interface = std::make_unique(
+ this, Config::Get(Config::MAIN_BBA_TAPSERVER_DESTINATION));
INFO_LOG_FMT(SP1, "Created tapserver physical network interface.");
break;
-#endif
case BBADeviceType::BuiltIn:
m_network_interface = std::make_unique(
this, Config::Get(Config::MAIN_BBA_BUILTIN_DNS), Config::Get(Config::MAIN_BBA_BUILTIN_IP));
diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.h b/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.h
index cdbf645aee..301420fbea 100644
--- a/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.h
+++ b/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.h
@@ -205,9 +205,7 @@ enum class BBADeviceType
{
TAP,
XLINK,
-#if defined(__APPLE__)
TAPSERVER,
-#endif
BuiltIn,
};
@@ -364,11 +362,13 @@ private:
#endif
};
-#if defined(__APPLE__)
class TAPServerNetworkInterface : public TAPNetworkInterface
{
public:
- explicit TAPServerNetworkInterface(CEXIETHERNET* eth_ref) : TAPNetworkInterface(eth_ref) {}
+ explicit TAPServerNetworkInterface(CEXIETHERNET* eth_ref, const std::string& destination)
+ : TAPNetworkInterface(eth_ref), m_destination(destination)
+ {
+ }
public:
bool Activate() override;
@@ -376,9 +376,10 @@ private:
bool RecvInit() override;
private:
+ std::string m_destination;
+
void ReadThreadHandler();
};
-#endif
class XLinkNetworkInterface : public NetworkInterface
{
diff --git a/Source/Core/DolphinQt/Settings/BroadbandAdapterSettingsDialog.cpp b/Source/Core/DolphinQt/Settings/BroadbandAdapterSettingsDialog.cpp
index 91aeae8a22..f8abbc77ab 100644
--- a/Source/Core/DolphinQt/Settings/BroadbandAdapterSettingsDialog.cpp
+++ b/Source/Core/DolphinQt/Settings/BroadbandAdapterSettingsDialog.cpp
@@ -48,6 +48,17 @@ void BroadbandAdapterSettingsDialog::InitControls()
window_title = tr("Broadband Adapter MAC Address");
break;
+ case Type::TapServer:
+ address_label = new QLabel(tr("UNIX socket path or netloc (address:port):"));
+ address_placeholder = QStringLiteral("/tmp/dolphin-tap");
+ current_address = QString::fromStdString(Config::Get(Config::MAIN_BBA_TAPSERVER_DESTINATION));
+ description =
+ new QLabel(tr("On macOS and Linux, the default value \"/tmp/dolphin-tap\" will work with "
+ "tapserver and newserv. On Windows, you must enter an IP address and port."));
+
+ window_title = tr("BBA destination address");
+ break;
+
case Type::BuiltIn:
address_label = new QLabel(tr("Enter the DNS server to use:"));
address_placeholder = QStringLiteral("8.8.8.8");
@@ -114,6 +125,9 @@ void BroadbandAdapterSettingsDialog::SaveAddress()
Config::SetBaseOrCurrent(Config::MAIN_BBA_MAC, bba_new_address);
break;
}
+ case Type::TapServer:
+ Config::SetBaseOrCurrent(Config::MAIN_BBA_TAPSERVER_DESTINATION, bba_new_address);
+ break;
case Type::BuiltIn:
Config::SetBaseOrCurrent(Config::MAIN_BBA_BUILTIN_DNS, bba_new_address);
break;
diff --git a/Source/Core/DolphinQt/Settings/BroadbandAdapterSettingsDialog.h b/Source/Core/DolphinQt/Settings/BroadbandAdapterSettingsDialog.h
index ca8d813cbe..53863f1d15 100644
--- a/Source/Core/DolphinQt/Settings/BroadbandAdapterSettingsDialog.h
+++ b/Source/Core/DolphinQt/Settings/BroadbandAdapterSettingsDialog.h
@@ -15,6 +15,7 @@ public:
{
Ethernet,
XLinkKai,
+ TapServer,
BuiltIn
};
diff --git a/Source/Core/DolphinQt/Settings/GameCubePane.cpp b/Source/Core/DolphinQt/Settings/GameCubePane.cpp
index 8c89badf00..944efa7a9f 100644
--- a/Source/Core/DolphinQt/Settings/GameCubePane.cpp
+++ b/Source/Core/DolphinQt/Settings/GameCubePane.cpp
@@ -149,9 +149,7 @@ void GameCubePane::CreateWidgets()
EXIDeviceType::Dummy,
EXIDeviceType::Ethernet,
EXIDeviceType::EthernetXLink,
-#ifdef __APPLE__
EXIDeviceType::EthernetTapServer,
-#endif
EXIDeviceType::EthernetBuiltIn,
})
{
@@ -355,6 +353,7 @@ void GameCubePane::UpdateButton(ExpansionInterface::Slot slot)
case ExpansionInterface::Slot::SP1:
has_config = (device == ExpansionInterface::EXIDeviceType::Ethernet ||
device == ExpansionInterface::EXIDeviceType::EthernetXLink ||
+ device == ExpansionInterface::EXIDeviceType::EthernetTapServer ||
device == ExpansionInterface::EXIDeviceType::EthernetBuiltIn);
break;
}
@@ -400,6 +399,13 @@ void GameCubePane::OnConfigPressed(ExpansionInterface::Slot slot)
dialog.exec();
return;
}
+ case ExpansionInterface::EXIDeviceType::EthernetTapServer:
+ {
+ BroadbandAdapterSettingsDialog dialog(this, BroadbandAdapterSettingsDialog::Type::TapServer);
+ SetQWidgetWindowDecorations(&dialog);
+ dialog.exec();
+ return;
+ }
case ExpansionInterface::EXIDeviceType::EthernetBuiltIn:
{
BroadbandAdapterSettingsDialog dialog(this, BroadbandAdapterSettingsDialog::Type::BuiltIn);