implement tapserver BBA on all platforms
This expands the tapserver BBA interface to be available on all platforms. tapserver itself is still macOS-only, but newserv (the PSO server) is not, and it can directly accept local and remote tapserver connections as well. This makes the tapserver interface potentially useful on all platforms.
This commit is contained in:
parent
85dee300b5
commit
0c364cbb4c
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -133,6 +133,8 @@
|
|||
<string name="xlink_kai_guide_header">For setup instructions, <a href="https://www.teamxlink.co.uk/wiki/Dolphin">refer to this page.</a></string>
|
||||
<string name="xlink_kai_bba_ip">XLink Kai IP Address/hostname</string>
|
||||
<string name="xlink_kai_bba_ip_description">IP address or hostname of device running the XLink Kai client</string>
|
||||
<string name="bba_tapserver_destination">Tapserver destination</string>
|
||||
<string name="bba_tapserver_destination_description">Enter the socket path or netloc (address:port) of the tapserver instance</string>
|
||||
<string name="bba_builtin_dns">DNS Server</string>
|
||||
<string name="bba_builtin_dns_description">Use 8.8.8.8 for normal DNS, else enter your custom one</string>
|
||||
|
||||
|
|
|
@ -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()
|
||||
endif()
|
||||
|
|
|
@ -137,6 +137,8 @@ const Info<bool> MAIN_BBA_XLINK_CHAT_OSD{{System::Main, "Core", "BBA_XLINK_CHAT_
|
|||
// Schthack PSO Server - https://schtserv.com/
|
||||
const Info<std::string> MAIN_BBA_BUILTIN_DNS{{System::Main, "Core", "BBA_BUILTIN_DNS"},
|
||||
"3.18.217.27"};
|
||||
const Info<std::string> MAIN_BBA_TAPSERVER_DESTINATION{
|
||||
{System::Main, "Core", "BBA_TAPSERVER_DESTINATION"}, "/tmp/dolphin-tap"};
|
||||
const Info<std::string> MAIN_BBA_BUILTIN_IP{{System::Main, "Core", "BBA_BUILTIN_IP"}, ""};
|
||||
|
||||
const Info<SerialInterface::SIDevices>& GetInfoForSIDevice(int channel)
|
||||
|
|
|
@ -96,6 +96,7 @@ extern const Info<std::string> MAIN_BBA_XLINK_IP;
|
|||
extern const Info<bool> MAIN_BBA_XLINK_CHAT_OSD;
|
||||
extern const Info<std::string> MAIN_BBA_BUILTIN_DNS;
|
||||
extern const Info<std::string> MAIN_BBA_BUILTIN_IP;
|
||||
extern const Info<std::string> MAIN_BBA_TAPSERVER_DESTINATION;
|
||||
const Info<SerialInterface::SIDevices>& GetInfoForSIDevice(int channel);
|
||||
const Info<bool>& GetInfoForAdapterRumble(int channel);
|
||||
const Info<bool>& GetInfoForSimulateKonga(int channel);
|
||||
|
|
|
@ -3,10 +3,16 @@
|
|||
|
||||
#include "Core/HW/EXI/EXI_DeviceEthernet.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2ipdef.h>
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#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<struct sockaddr_in*>(&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<struct sockaddr_un*>(&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<sockaddr*>(&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<sockaddr*>(&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();
|
|
@ -137,11 +137,9 @@ std::unique_ptr<IEXIDevice> EXIDevice_Create(Core::System& system, const EXIDevi
|
|||
result = std::make_unique<CEXIETHERNET>(system, BBADeviceType::TAP);
|
||||
break;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
case EXIDeviceType::EthernetTapServer:
|
||||
result = std::make_unique<CEXIETHERNET>(system, BBADeviceType::TAPSERVER);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case EXIDeviceType::EthernetXLink:
|
||||
result = std::make_unique<CEXIETHERNET>(system, BBADeviceType::XLINK);
|
||||
|
|
|
@ -39,7 +39,6 @@ enum class EXIDeviceType : int
|
|||
MemoryCardFolder,
|
||||
AGP,
|
||||
EthernetXLink,
|
||||
// Only used on Apple devices.
|
||||
EthernetTapServer,
|
||||
EthernetBuiltIn,
|
||||
None = 0xFF
|
||||
|
|
|
@ -50,12 +50,11 @@ CEXIETHERNET::CEXIETHERNET(Core::System& system, BBADeviceType type) : IEXIDevic
|
|||
m_network_interface = std::make_unique<TAPNetworkInterface>(this);
|
||||
INFO_LOG_FMT(SP1, "Created TAP physical network interface.");
|
||||
break;
|
||||
#if defined(__APPLE__)
|
||||
case BBADeviceType::TAPSERVER:
|
||||
m_network_interface = std::make_unique<TAPServerNetworkInterface>(this);
|
||||
m_network_interface = std::make_unique<TAPServerNetworkInterface>(
|
||||
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<BuiltInBBAInterface>(
|
||||
this, Config::Get(Config::MAIN_BBA_BUILTIN_DNS), Config::Get(Config::MAIN_BBA_BUILTIN_IP));
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -15,6 +15,7 @@ public:
|
|||
{
|
||||
Ethernet,
|
||||
XLinkKai,
|
||||
TapServer,
|
||||
BuiltIn
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue