Merge pull request #9117 from fuzziqersoftware/add-tapserver-bba
Add tapserver network interface for macOS since TunTap is now unmaintained
This commit is contained in:
commit
2feb5f204a
|
@ -623,6 +623,7 @@ if(WIN32)
|
|||
elseif(APPLE)
|
||||
target_sources(core PRIVATE
|
||||
HW/EXI/BBA/TAP_Apple.cpp
|
||||
HW/EXI/BBA/TAPServer_Apple.cpp
|
||||
HW/EXI/BBA/XLINK_KAI_BBA.cpp
|
||||
HW/WiimoteReal/IOdarwin.h
|
||||
HW/WiimoteReal/IOdarwin_private.h
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
// Copyright 2020 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Core/HW/EXI/EXI_Device.h"
|
||||
#include "Core/HW/EXI/EXI_DeviceEthernet.h"
|
||||
|
||||
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";
|
||||
|
||||
bool CEXIETHERNET::TAPServerNetworkInterface::Activate()
|
||||
{
|
||||
if (IsActivated())
|
||||
return true;
|
||||
|
||||
sockaddr_un sun = {};
|
||||
if (sizeof(socket_path) > sizeof(sun.sun_path))
|
||||
{
|
||||
ERROR_LOG(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(SP1, "Couldn't create socket, unable to init BBA");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (connect(fd, reinterpret_cast<sockaddr*>(&sun), sizeof(sun)) == -1)
|
||||
{
|
||||
ERROR_LOG(SP1, "Couldn't connect socket (%d), unable to init BBA", errno);
|
||||
close(fd);
|
||||
fd = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO_LOG(SP1, "BBA initialized.\n");
|
||||
return RecvInit();
|
||||
}
|
||||
|
||||
bool CEXIETHERNET::TAPServerNetworkInterface::SendFrame(const u8* frame, u32 size)
|
||||
{
|
||||
{
|
||||
const std::string s = ArrayToString(frame, size, 0x10);
|
||||
INFO_LOG(SP1, "SendFrame %x\n%s\n", size, s.c_str());
|
||||
}
|
||||
|
||||
auto size16 = u16(size);
|
||||
if (write(fd, &size16, 2) != 2)
|
||||
{
|
||||
ERROR_LOG(SP1, "SendFrame(): could not write size field\n");
|
||||
return false;
|
||||
}
|
||||
int written_bytes = write(fd, frame, size);
|
||||
if (u32(written_bytes) != size)
|
||||
{
|
||||
ERROR_LOG(SP1, "SendFrame(): expected to write %d bytes, instead wrote %d", size,
|
||||
written_bytes);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_eth_ref->SendComplete();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void CEXIETHERNET::TAPServerNetworkInterface::ReadThreadHandler()
|
||||
{
|
||||
while (!readThreadShutdown.IsSet())
|
||||
{
|
||||
fd_set rfds;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(fd, &rfds);
|
||||
|
||||
timeval timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 50000;
|
||||
if (select(fd + 1, &rfds, nullptr, nullptr, &timeout) <= 0)
|
||||
continue;
|
||||
|
||||
u16 size;
|
||||
if (read(fd, &size, 2) != 2)
|
||||
{
|
||||
ERROR_LOG(SP1, "Failed to read size field from BBA, err=%d", errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
int read_bytes = read(fd, m_eth_ref->mRecvBuffer.get(), size);
|
||||
if (read_bytes < 0)
|
||||
{
|
||||
ERROR_LOG(SP1, "Failed to read packet data from BBA, err=%d", errno);
|
||||
}
|
||||
else if (readEnabled.IsSet())
|
||||
{
|
||||
std::string data_string = ArrayToString(m_eth_ref->mRecvBuffer.get(), read_bytes, 0x10);
|
||||
INFO_LOG(SP1, "Read data: %s", data_string.c_str());
|
||||
m_eth_ref->mRecvBufferLength = read_bytes;
|
||||
m_eth_ref->RecvHandlePacket();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CEXIETHERNET::TAPServerNetworkInterface::RecvInit()
|
||||
{
|
||||
readThread = std::thread(&CEXIETHERNET::TAPServerNetworkInterface::ReadThreadHandler, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ExpansionInterface
|
|
@ -136,6 +136,12 @@ std::unique_ptr<IEXIDevice> EXIDevice_Create(const TEXIDevices device_type, cons
|
|||
result = std::make_unique<CEXIETHERNET>(BBADeviceType::TAP);
|
||||
break;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
case EXIDEVICE_ETHTAPSERVER:
|
||||
result = std::make_unique<CEXIETHERNET>(BBADeviceType::TAPSERVER);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case EXIDEVICE_ETHXLINK:
|
||||
result = std::make_unique<CEXIETHERNET>(BBADeviceType::XLINK);
|
||||
break;
|
||||
|
|
|
@ -33,6 +33,9 @@ enum TEXIDevices : int
|
|||
EXIDEVICE_MEMORYCARDFOLDER,
|
||||
EXIDEVICE_AGP,
|
||||
EXIDEVICE_ETHXLINK,
|
||||
#if defined(__APPLE__)
|
||||
EXIDEVICE_ETHTAPSERVER,
|
||||
#endif
|
||||
EXIDEVICE_NONE = 0xFF
|
||||
};
|
||||
|
||||
|
|
|
@ -48,6 +48,12 @@ CEXIETHERNET::CEXIETHERNET(BBADeviceType type)
|
|||
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);
|
||||
INFO_LOG(SP1, "Created tapserver physical network interface.");
|
||||
break;
|
||||
#endif
|
||||
case BBADeviceType::XLINK:
|
||||
// TODO start BBA with network link down, bring it up after "connected" response from XLink
|
||||
|
||||
|
|
|
@ -202,6 +202,9 @@ enum class BBADeviceType
|
|||
{
|
||||
TAP,
|
||||
XLINK,
|
||||
#if defined(__APPLE__)
|
||||
TAPSERVER,
|
||||
#endif
|
||||
};
|
||||
|
||||
class CEXIETHERNET : public IEXIDevice
|
||||
|
@ -337,7 +340,7 @@ private:
|
|||
void RecvStart() override;
|
||||
void RecvStop() override;
|
||||
|
||||
private:
|
||||
protected:
|
||||
#if defined(WIN32) || defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
|
||||
defined(__OpenBSD__)
|
||||
std::thread readThread;
|
||||
|
@ -356,6 +359,22 @@ private:
|
|||
#endif
|
||||
};
|
||||
|
||||
#if defined(__APPLE__)
|
||||
class TAPServerNetworkInterface : public TAPNetworkInterface
|
||||
{
|
||||
public:
|
||||
explicit TAPServerNetworkInterface(CEXIETHERNET* eth_ref) : TAPNetworkInterface(eth_ref) {}
|
||||
|
||||
public:
|
||||
bool Activate() override;
|
||||
bool SendFrame(const u8* frame, u32 size) override;
|
||||
bool RecvInit() override;
|
||||
|
||||
private:
|
||||
void ReadThreadHandler();
|
||||
};
|
||||
#endif
|
||||
|
||||
class XLinkNetworkInterface : public NetworkInterface
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -100,12 +100,16 @@ void GameCubePane::CreateWidgets()
|
|||
|
||||
// Add SP1 devices
|
||||
|
||||
for (const auto& entry :
|
||||
{std::make_pair(tr("<Nothing>"), ExpansionInterface::EXIDEVICE_NONE),
|
||||
std::make_pair(tr("Dummy"), ExpansionInterface::EXIDEVICE_DUMMY),
|
||||
std::make_pair(tr("Broadband Adapter (TAP)"), ExpansionInterface::EXIDEVICE_ETH),
|
||||
std::make_pair(tr("Broadband Adapter (XLink Kai)"),
|
||||
ExpansionInterface::EXIDEVICE_ETHXLINK)})
|
||||
std::vector<std::pair<QString, ExpansionInterface::TEXIDevices>> sp1Entries{
|
||||
std::make_pair(tr("<Nothing>"), ExpansionInterface::EXIDEVICE_NONE),
|
||||
std::make_pair(tr("Dummy"), ExpansionInterface::EXIDEVICE_DUMMY),
|
||||
std::make_pair(tr("Broadband Adapter (TAP)"), ExpansionInterface::EXIDEVICE_ETH),
|
||||
std::make_pair(tr("Broadband Adapter (XLink Kai)"), ExpansionInterface::EXIDEVICE_ETHXLINK)};
|
||||
#if defined(__APPLE__)
|
||||
sp1Entries.emplace_back(std::make_pair(tr("Broadband Adapter (tapserver)"),
|
||||
ExpansionInterface::EXIDEVICE_ETHTAPSERVER));
|
||||
#endif
|
||||
for (const auto& entry : sp1Entries)
|
||||
{
|
||||
m_slot_combos[2]->addItem(entry.first, entry.second);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue