summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules')
-rw-r--r--src/osd/modules/lib/osdobj_common.cpp30
-rw-r--r--src/osd/modules/lib/osdobj_common.h14
-rw-r--r--src/osd/modules/netdev/netdev_common.cpp39
-rw-r--r--src/osd/modules/netdev/netdev_common.h36
-rw-r--r--src/osd/modules/netdev/netdev_module.h9
-rw-r--r--src/osd/modules/netdev/none.cpp19
-rw-r--r--src/osd/modules/netdev/pcap.cpp216
-rw-r--r--src/osd/modules/netdev/taptun.cpp105
8 files changed, 303 insertions, 165 deletions
diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp
index e3c8d63b0d6..eed73f3097b 100644
--- a/src/osd/modules/lib/osdobj_common.cpp
+++ b/src/osd/modules/lib/osdobj_common.cpp
@@ -15,12 +15,12 @@
#include "modules/font/font_module.h"
#include "modules/input/input_module.h"
#include "modules/midi/midi_module.h"
+#include "modules/netdev/netdev_module.h"
#include "modules/monitor/monitor_module.h"
#include "modules/netdev/netdev_module.h"
#include "modules/render/render_module.h"
#include "modules/sound/sound_module.h"
-#include "osdnet.h"
#include "watchdog.h"
#include "emu.h"
@@ -208,6 +208,7 @@ osd_common_t::osd_common_t(osd_options &options)
, m_sound(nullptr)
, m_debugger(nullptr)
, m_midi(nullptr)
+ , m_network(nullptr)
, m_keyboard_input(nullptr)
, m_mouse_input(nullptr)
, m_lightgun_input(nullptr)
@@ -615,8 +616,8 @@ bool osd_common_t::execute_command(const char *command)
{
if (strcmp(command, OSDCOMMAND_LIST_NETWORK_ADAPTERS) == 0)
{
- osd_module &om = select_module_options<osd_module>(OSD_NETDEV_PROVIDER);
- auto const &interfaces = get_netdev_list();
+ auto &om = select_module_options<netdev_module>(OSD_NETDEV_PROVIDER);
+ auto const interfaces = om.list_devices();
if (interfaces.empty())
{
printf("No supported network interfaces were found\n");
@@ -626,17 +627,17 @@ bool osd_common_t::execute_command(const char *command)
printf("Available network interfaces:\n");
for (auto &entry : interfaces)
{
- printf(" %s\n", entry->description);
+ printf(" %.*s\n", int(entry.description.length()), entry.description.data());
}
}
- om.exit();
+ dynamic_cast<osd_module &>(om).exit();
return true;
}
else if (strcmp(command, OSDCOMMAND_LIST_MIDI_DEVICES) == 0)
{
- osd_module &om = select_module_options<osd_module>(OSD_MIDI_PROVIDER);
- auto const ports = dynamic_cast<midi_module &>(om).list_midi_ports();
+ auto &om = select_module_options<midi_module>(OSD_MIDI_PROVIDER);
+ auto const ports = om.list_midi_ports();
if (ports.empty())
{
printf("No MIDI ports were found\n");
@@ -657,7 +658,7 @@ bool osd_common_t::execute_command(const char *command)
printf(port.default_output ? "%s (default)\n" : "%s\n", port.name.c_str());
}
}
- om.exit();
+ dynamic_cast<osd_module &>(om).exit();
return true;
}
@@ -697,10 +698,10 @@ void osd_common_t::init_subsystems()
m_debugger = &select_module_options<debug_module>(OSD_DEBUG_PROVIDER);
- select_module_options<netdev_module>(OSD_NETDEV_PROVIDER);
-
m_midi = &select_module_options<midi_module>(OSD_MIDI_PROVIDER);
+ m_network = &select_module_options<netdev_module>(OSD_NETDEV_PROVIDER);
+
m_output = &select_module_options<output_module>(OSD_OUTPUT_PROVIDER);
machine().output().set_global_notifier(output_notifier_callback, this);
@@ -788,3 +789,12 @@ std::vector<osd::midi_port_info> osd_common_t::list_midi_ports()
return m_midi->list_midi_ports();
}
+std::unique_ptr<osd::network_device> osd_common_t::open_network_device(int id, osd::network_handler &handler)
+{
+ return m_network->open_device(id, handler);
+}
+
+std::vector<osd::network_device_info> osd_common_t::list_network_devices()
+{
+ return m_network->list_devices();
+}
diff --git a/src/osd/modules/lib/osdobj_common.h b/src/osd/modules/lib/osdobj_common.h
index 820fe3edf21..991ebacfdce 100644
--- a/src/osd/modules/lib/osdobj_common.h
+++ b/src/osd/modules/lib/osdobj_common.h
@@ -197,6 +197,7 @@ class font_module;
class input_module;
class midi_module;
class monitor_module;
+class netdev_module;
class osd_watchdog;
class osd_window;
class output_module;
@@ -234,16 +235,22 @@ public:
virtual void add_audio_to_recording(const int16_t *buffer, int samples_this_frame) override;
virtual std::vector<ui::menu_item> get_slider_list() override;
- // command option overrides
- virtual bool execute_command(const char *command) override;
-
+ // font interface
virtual osd_font::ptr font_alloc() override;
virtual bool get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) override;
+ // command option overrides
+ virtual bool execute_command(const char *command) override;
+
+ // MIDI interface
virtual std::unique_ptr<osd::midi_input_port> create_midi_input(std::string_view name) override;
virtual std::unique_ptr<osd::midi_output_port> create_midi_output(std::string_view name) override;
virtual std::vector<osd::midi_port_info> list_midi_ports() override;
+ // network interface
+ virtual std::unique_ptr<osd::network_device> open_network_device(int id, osd::network_handler &handler) override;
+ virtual std::vector<osd::network_device_info> list_network_devices() override;
+
// FIXME: everything below seems to be osd specific and not part of
// this INTERFACE but part of the osd IMPLEMENTATION
@@ -317,6 +324,7 @@ protected:
sound_module* m_sound;
debug_module* m_debugger;
midi_module* m_midi;
+ netdev_module* m_network;
input_module* m_keyboard_input;
input_module* m_mouse_input;
input_module* m_lightgun_input;
diff --git a/src/osd/modules/netdev/netdev_common.cpp b/src/osd/modules/netdev/netdev_common.cpp
new file mode 100644
index 00000000000..b6a2328c7a6
--- /dev/null
+++ b/src/osd/modules/netdev/netdev_common.cpp
@@ -0,0 +1,39 @@
+// license:BSD-3-Clause
+// copyright-holders:Carl
+
+#include "netdev_common.h"
+
+
+namespace osd {
+
+network_device_base::network_device_base(network_handler &handler)
+ : m_handler(handler)
+ , m_stopped(true)
+{
+}
+
+network_device_base::~network_device_base()
+{
+}
+
+void network_device_base::start()
+{
+ m_stopped = false;
+}
+
+void network_device_base::stop()
+{
+ m_stopped = true;
+}
+
+void network_device_base::poll()
+{
+ uint8_t *buf;
+ int len;
+ while (!m_stopped && (len = recv_dev(&buf)))
+ {
+ m_handler.recv_cb(buf, len);
+ }
+}
+
+} // namespace osd
diff --git a/src/osd/modules/netdev/netdev_common.h b/src/osd/modules/netdev/netdev_common.h
new file mode 100644
index 00000000000..95d961a438a
--- /dev/null
+++ b/src/osd/modules/netdev/netdev_common.h
@@ -0,0 +1,36 @@
+// license:BSD-3-Clause
+// copyright-holders:Carl
+#ifndef MAME_OSD_NETDEV_NETDEV_COMMON_H
+#define MAME_OSD_NETDEV_NETDEV_COMMON_H
+
+#pragma once
+
+#include "interface/nethandler.h"
+
+#include <cstdint>
+
+
+namespace osd {
+
+class network_device_base : public network_device
+{
+public:
+ virtual ~network_device_base();
+
+ virtual void start() override;
+ virtual void stop() override;
+ virtual void poll() override;
+
+protected:
+ network_device_base(network_handler &handler);
+
+ virtual int recv_dev(uint8_t **buf) = 0;
+
+private:
+ network_handler &m_handler;
+ bool m_stopped;
+};
+
+} // namespace osd
+
+#endif // MAME_OSD_NETDEV_NETDEV_COMMON_H
diff --git a/src/osd/modules/netdev/netdev_module.h b/src/osd/modules/netdev/netdev_module.h
index b102e56fbb8..3636c3a23cb 100644
--- a/src/osd/modules/netdev/netdev_module.h
+++ b/src/osd/modules/netdev/netdev_module.h
@@ -9,6 +9,11 @@
#pragma once
+#include "interface/nethandler.h"
+
+#include <memory>
+#include <vector>
+
//============================================================
// CONSTANTS
@@ -20,7 +25,9 @@ class netdev_module
{
public:
virtual ~netdev_module() = default;
- // no specific routines below ... may change
+
+ virtual std::unique_ptr<osd::network_device> open_device(int id, osd::network_handler &handler) = 0;
+ virtual std::vector<osd::network_device_info> list_devices() = 0;
};
#endif // MAME_OSD_NETDEV_NETDEV_MODULE_H
diff --git a/src/osd/modules/netdev/none.cpp b/src/osd/modules/netdev/none.cpp
index 8441c002802..284ff51a962 100644
--- a/src/osd/modules/netdev/none.cpp
+++ b/src/osd/modules/netdev/none.cpp
@@ -8,6 +8,9 @@
#include "modules/osdmodule.h"
+#include <memory>
+#include <vector>
+
namespace osd {
@@ -21,7 +24,21 @@ public:
}
virtual ~netdev_none() { }
- virtual int init(osd_interface &osd, const osd_options &options) override { return 0; }
+
+ virtual int init(osd_interface &osd, const osd_options &options) override
+ {
+ return 0;
+ }
+
+ virtual std::unique_ptr<network_device> open_device(int id, network_handler &handler) override
+ {
+ return std::unique_ptr<network_device>();
+ }
+
+ virtual std::vector<network_device_info> list_devices() override
+ {
+ return std::vector<network_device_info>();
+ }
};
} // anonymous namespace
diff --git a/src/osd/modules/netdev/pcap.cpp b/src/osd/modules/netdev/pcap.cpp
index 77ca557f1de..8ad62773d58 100644
--- a/src/osd/modules/netdev/pcap.cpp
+++ b/src/osd/modules/netdev/pcap.cpp
@@ -7,20 +7,25 @@
#if defined(OSD_NET_USE_PCAP)
+#include "netdev_common.h"
+
#include "modules/lib/osdlib.h"
-#include "osdnet.h"
+
#include "osdcore.h" // osd_printf_*
#include "util/strformat.h" // string_format
+#include <memory>
+#include <vector>
+
#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS)
#include <windows.h>
#undef interface
#define LIB_NAME "wpcap.dll"
#elif defined(SDLMAME_MACOSX)
+#include <atomic>
#include <pthread.h>
-#include <libkern/OSAtomic.h>
#define LIB_NAME "libpcap.dylib"
#else
@@ -47,10 +52,10 @@ typedef int (*pcap_dispatch_fn)(pcap_t *, int, pcap_handler, u_char *);
class pcap_module : public osd_module, public netdev_module
{
public:
- pcap_module()
- : osd_module(OSD_NETDEV_PROVIDER, "pcap"), netdev_module(),
- pcap_findalldevs_dl(nullptr), pcap_open_live_dl(nullptr), pcap_next_ex_dl(nullptr), pcap_compile_dl(nullptr),
- pcap_close_dl(nullptr), pcap_setfilter_dl(nullptr), pcap_sendpacket_dl(nullptr), pcap_set_datalink_dl(nullptr), pcap_dispatch_dl(nullptr)
+ pcap_module() :
+ osd_module(OSD_NETDEV_PROVIDER, "pcap"), netdev_module(),
+ pcap_findalldevs_dl(nullptr), pcap_open_live_dl(nullptr), pcap_next_ex_dl(nullptr), pcap_compile_dl(nullptr),
+ pcap_close_dl(nullptr), pcap_setfilter_dl(nullptr), pcap_sendpacket_dl(nullptr), pcap_set_datalink_dl(nullptr), pcap_dispatch_dl(nullptr)
{
}
@@ -84,6 +89,20 @@ public:
return true;
}
+ virtual std::unique_ptr<network_device> open_device(int id, network_handler &handler) override;
+ virtual std::vector<network_device_info> list_devices() override;
+
+private:
+ struct device_info
+ {
+ std::string name;
+ std::string description;
+ };
+
+ class netdev_pcap;
+
+ std::vector<device_info> m_devices;
+
osd::dynamic_module::ptr pcap_dll;
pcap_findalldevs_fn pcap_findalldevs_dl;
@@ -97,195 +116,161 @@ public:
pcap_dispatch_fn pcap_dispatch_dl;
};
-// FIXME: bridge between pcap_module and netdev_pcap
-static pcap_module *module = nullptr;
-
-#ifdef SDLMAME_MACOSX
-struct netdev_pcap_context
-{
- uint8_t *pkt;
- int len;
- pcap_t *p;
-
- uint8_t packets[32][1600];
- int packetlens[32];
- int head;
- int tail;
-};
-#endif
-
-class netdev_pcap : public osd_network_device
+class pcap_module::netdev_pcap : public network_device_base
{
public:
- netdev_pcap(const char *name, network_handler &ifdev);
+ netdev_pcap(pcap_module &module, const char *name, network_handler &handler);
~netdev_pcap();
- virtual int send(uint8_t *buf, int len) override;
- virtual void set_mac(const uint8_t *mac) override;
+ virtual int send(void const *buf, int len) override;
protected:
virtual int recv_dev(uint8_t **buf) override;
private:
+ pcap_module &m_module;
pcap_t *m_p;
#ifdef SDLMAME_MACOSX
- struct netdev_pcap_context m_ctx;
pthread_t m_thread;
+ uint8_t *pkt;
+ int len;
+ pcap_t *p;
+ uint8_t m_pktbuf[2048];
+
+ uint8_t m_packets[32][1600];
+ int m_packetlens[32];
+ std::atomic<int> m_head;
+ std::atomic<int> m_tail;
+
+ static void pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes);
+ static void *pcap_blocker(void *arg);
#endif
};
#ifdef SDLMAME_MACOSX
-static void netdev_pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
+void pcap_module::netdev_pcap::pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
{
- struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)user;
+ netdev_pcap *const ctx = reinterpret_cast<netdev_pcap *>(user);
- if(!ctx->p) return;
+ if (!ctx->p)
+ return;
- if(OSAtomicCompareAndSwapInt((ctx->head+1) & 0x1F, ctx->tail, &ctx->tail)) {
+ int const curr = ctx->m_head.load(std::memory_order_relaxed);
+ int const next = (curr + 1) & 0x1f;
+ if (ctx->m_tail.load(std::memory_order_acquire) == next)
+ {
printf("buffer full, dropping packet\n");
return;
}
- memcpy(ctx->packets[ctx->head], bytes, h->len);
- ctx->packetlens[ctx->head] = h->len;
- OSAtomicCompareAndSwapInt(ctx->head, (ctx->head+1) & 0x1F, &ctx->head);
+ memcpy(ctx->m_packets[curr], bytes, h->len);
+ ctx->m_packetlens[curr] = h->len;
+ ctx->m_head.store(next, std::memory_order_release);
}
-static void *netdev_pcap_blocker(void *arg) {
- struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)arg;
+void *pcap_module::netdev_pcap::pcap_blocker(void *arg)
+{
+ netdev_pcap *const ctx = reinterpret_cast<netdev_pcap *>(arg);
- while(ctx && ctx->p) {
- (*module->pcap_dispatch_dl)(ctx->p, 1, netdev_pcap_handler, (u_char*)ctx);
- }
+ while (ctx && ctx->p)
+ (*ctx->m_module.pcap_dispatch_dl)(ctx->p, 1, &netdev_pcap::pcap_handler, reinterpret_cast<u_char *>(ctx));
- return 0;
+ return nullptr;
}
#endif
-netdev_pcap::netdev_pcap(const char *name, network_handler &ifdev)
- : osd_network_device(ifdev)
+pcap_module::netdev_pcap::netdev_pcap(pcap_module &module, const char *name, network_handler &handler) :
+ network_device_base(handler),
+ m_module(module),
+ m_p(nullptr)
{
char errbuf[PCAP_ERRBUF_SIZE];
#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS)
- m_p = (*module->pcap_open_live_dl)(name, 65535, 1, -1, errbuf);
+ m_p = (*m_module.pcap_open_live_dl)(name, 65535, 1, -1, errbuf);
#else
- m_p = (*module->pcap_open_live_dl)(name, 65535, 1, 1, errbuf);
+ m_p = (*m_module.pcap_open_live_dl)(name, 65535, 1, 1, errbuf);
#endif
if(!m_p)
{
osd_printf_error("Unable to open %s: %s\n", name, errbuf);
return;
}
- if ((*module->pcap_set_datalink_dl)(m_p, DLT_EN10MB) == -1)
+ if ((*m_module.pcap_set_datalink_dl)(m_p, DLT_EN10MB) == -1)
{
osd_printf_error("Unable to set %s to ethernet", name);
- (*module->pcap_close_dl)(m_p);
+ (*m_module.pcap_close_dl)(m_p);
m_p = nullptr;
return;
}
- netdev_pcap::set_mac(&get_mac()[0]);
#ifdef SDLMAME_MACOSX
- m_ctx.head = 0;
- m_ctx.tail = 0;
- m_ctx.p = m_p;
- pthread_create(&m_thread, nullptr, netdev_pcap_blocker, &m_ctx);
-#endif
-}
-
-void netdev_pcap::set_mac(const uint8_t *mac)
-{
- struct bpf_program fp;
- if(!m_p) return;
-#ifdef SDLMAME_MACOSX
- auto filter = util::string_format("not ether src %02X:%02X:%02X:%02X:%02X:%02X and (ether dst %02X:%02X:%02X:%02X:%02X:%02X or ether multicast or ether broadcast or ether dst 09:00:07:ff:ff:ff)", (unsigned char)mac[0], (unsigned char)mac[1], (unsigned char)mac[2],(unsigned char)mac[3], (unsigned char)mac[4], (unsigned char)mac[5], (unsigned char)mac[0], (unsigned char)mac[1], (unsigned char)mac[2],(unsigned char)mac[3], (unsigned char)mac[4], (unsigned char)mac[5]);
-#else
- auto filter = util::string_format("ether dst %02X:%02X:%02X:%02X:%02X:%02X or ether multicast or ether broadcast", (unsigned char)mac[0], (unsigned char)mac[1], (unsigned char)mac[2],(unsigned char)mac[3], (unsigned char)mac[4], (unsigned char)mac[5]);
+ m_head = 0;
+ m_tail = 0;
+ p = m_p;
+ pthread_create(&m_thread, nullptr, &netdev_pcap::pcap_blocker, this);
#endif
- if ((*module->pcap_compile_dl)(m_p, &fp, filter.c_str(), 1, 0) == -1) {
- osd_printf_error("Error with pcap_compile\n");
- }
- if ((*module->pcap_setfilter_dl)(m_p, &fp) == -1) {
- osd_printf_error("Error with pcap_setfilter\n");
- }
}
-int netdev_pcap::send(uint8_t *buf, int len)
+int pcap_module::netdev_pcap::send(void const *buf, int len)
{
- int ret;
- if(!m_p) {
+ if (!m_p)
+ {
printf("send invoked, but no pcap context\n");
return 0;
}
- ret = (*module->pcap_sendpacket_dl)(m_p, buf, len);
+ int ret = (*m_module.pcap_sendpacket_dl)(m_p, reinterpret_cast<const u_char *>(buf), len);
printf("sent packet length %d, returned %d\n", len, ret);
return ret ? len : 0;
- //return (!pcap_sendpacket_dl(m_p, buf, len))?len:0;
+ //return (!pcap_sendpacket_dl(m_p, reinterpret_cast<const u_char *>(buf), len)) ? len : 0;
}
-int netdev_pcap::recv_dev(uint8_t **buf)
+int pcap_module::netdev_pcap::recv_dev(uint8_t **buf)
{
-#ifdef SDLMAME_MACOSX
- uint8_t pktbuf[2048];
- int ret;
-
// no device open?
- if(!m_p) return 0;
+ if (!m_p)
+ return 0;
+#ifdef SDLMAME_MACOSX
// Empty
- if(OSAtomicCompareAndSwapInt(m_ctx.head, m_ctx.tail, &m_ctx.tail)) {
+ int const curr = m_tail.load(std::memory_order_relaxed);
+ if (m_head.load(std::memory_order_acquire) == curr)
return 0;
- }
- memcpy(pktbuf, m_ctx.packets[m_ctx.tail], m_ctx.packetlens[m_ctx.tail]);
- ret = m_ctx.packetlens[m_ctx.tail];
- OSAtomicCompareAndSwapInt(m_ctx.tail, (m_ctx.tail+1) & 0x1F, &m_ctx.tail);
- *buf = pktbuf;
+ memcpy(m_pktbuf, m_packets[curr], m_packetlens[curr]);
+ int ret = m_packetlens[curr];
+ m_tail.store((curr + 1) & 0x1f, std::memory_order_release);
+ *buf = m_pktbuf;
return ret;
#else
struct pcap_pkthdr *header;
- if(!m_p) return 0;
- return ((*module->pcap_next_ex_dl)(m_p, &header, (const u_char **)buf) == 1)?header->len:0;
+ return ((*m_module.pcap_next_ex_dl)(m_p, &header, (const u_char **)buf) == 1)?header->len:0;
#endif
}
-netdev_pcap::~netdev_pcap()
+pcap_module::netdev_pcap::~netdev_pcap()
{
#ifdef SDLMAME_MACOSX
- m_ctx.p = nullptr;
+ p = nullptr;
pthread_cancel(m_thread);
pthread_join(m_thread, nullptr);
#endif
- if(m_p) (*module->pcap_close_dl)(m_p);
+ if(m_p) (*m_module.pcap_close_dl)(m_p);
m_p = nullptr;
}
-static CREATE_NETDEV(create_pcap)
-{
- auto *dev = new netdev_pcap(ifname, ifdev);
- return dynamic_cast<osd_network_device *>(dev);
-}
-
int pcap_module::init(osd_interface &osd, const osd_options &options)
{
pcap_if_t *devs;
char errbuf[PCAP_ERRBUF_SIZE];
- // FIXME: bridge between pcap_module and netdev_pcap
- module = this;
-
if ((*pcap_findalldevs_dl)(&devs, errbuf) == -1)
{
osd_printf_error("Unable to get network devices: %s\n", errbuf);
return 1;
}
- while(devs)
+ while (devs)
{
- if(devs->description) {
- add_netdev(devs->name, devs->description, create_pcap);
- } else {
- add_netdev(devs->name, devs->name, create_pcap);
- }
+ m_devices.emplace_back(device_info{ devs->name, devs->description ? devs->description : devs->name });
devs = devs->next;
}
return 0;
@@ -293,7 +278,24 @@ int pcap_module::init(osd_interface &osd, const osd_options &options)
void pcap_module::exit()
{
- clear_netdev();
+ m_devices.clear();
+}
+
+std::unique_ptr<network_device> pcap_module::open_device(int id, network_handler &handler)
+{
+ if ((0 > id) || (m_devices.size() <= id))
+ return nullptr;
+
+ return std::make_unique<netdev_pcap>(*this, m_devices[id].name.c_str(), handler);
+}
+
+std::vector<network_device_info> pcap_module::list_devices()
+{
+ std::vector<network_device_info> result;
+ result.reserve(m_devices.size());
+ for (int id = 0; m_devices.size() > id; ++id)
+ result.emplace_back(network_device_info{ id, m_devices[id].description });
+ return result;
}
} // anonymous namespace
diff --git a/src/osd/modules/netdev/taptun.cpp b/src/osd/modules/netdev/taptun.cpp
index c78ec9471e1..b765a667ae7 100644
--- a/src/osd/modules/netdev/taptun.cpp
+++ b/src/osd/modules/netdev/taptun.cpp
@@ -6,6 +6,17 @@
#if defined(OSD_NET_USE_TAPTUN)
+#include "netdev_common.h"
+
+#include "osdcore.h" // osd_printf_verbose
+#include "osdfile.h" // PATH_SEPARATOR
+
+#include "util/hashing.h" // crc32_creator
+#include "util/unicode.h"
+
+#include <memory>
+#include <vector>
+
#if defined(_WIN32)
#include <windows.h>
#include <winioctl.h>
@@ -17,13 +28,6 @@
#include <cerrno>
#endif
-#include "osdcore.h" // osd_printf_verbose
-#include "osdfile.h" // PATH_SEPARATOR
-#include "osdnet.h"
-#include "unicode.h"
-
-#include "util/hashing.h" // crc32_creator
-
#ifdef __linux__
#define IFF_TAP 0x0002
#define IFF_NO_PI 0x1000
@@ -52,22 +56,33 @@ public:
}
virtual ~taptun_module() { }
- virtual int init(osd_interface &osd, const osd_options &options);
- virtual void exit();
+ virtual int init(osd_interface &osd, const osd_options &options) override;
+ virtual void exit() override;
+
+ virtual bool probe() override { return true; }
+
+ virtual std::unique_ptr<network_device> open_device(int id, network_handler &handler) override;
+ virtual std::vector<network_device_info> list_devices() override;
- virtual bool probe() { return true; }
+private:
+ struct device_info
+ {
+ std::string name;
+ std::string description;
+ };
+
+ std::vector<device_info> m_devices;
};
-class netdev_tap : public osd_network_device
+class netdev_tap : public network_device_base
{
public:
- netdev_tap(const char *name, network_handler &ifdev);
+ netdev_tap(const char *name, network_handler &handler);
~netdev_tap();
- int send(uint8_t *buf, int len) override;
- void set_mac(const uint8_t *mac) override;
+ int send(void const *buf, int len) override;
protected:
int recv_dev(uint8_t **buf) override;
@@ -81,12 +96,11 @@ private:
int m_fd = -1;
char m_ifname[10];
#endif
- char m_mac[6];
uint8_t m_buf[2048];
};
-netdev_tap::netdev_tap(const char *name, network_handler &ifdev)
- : osd_network_device(ifdev)
+netdev_tap::netdev_tap(const char *name, network_handler &handler)
+ : network_device_base(handler)
{
#if defined(__linux__)
m_fd = -1;
@@ -144,11 +158,6 @@ netdev_tap::~netdev_tap()
#endif
}
-void netdev_tap::set_mac(const uint8_t *mac)
-{
- memcpy(m_mac, mac, 6);
-}
-
static u32 finalise_frame(u8 buf[], u32 length)
{
/*
@@ -180,7 +189,7 @@ static u32 finalise_frame(u8 buf[], u32 length)
}
#if defined(_WIN32)
-int netdev_tap::send(uint8_t *buf, int len)
+int netdev_tap::send(void const *buf, int len)
{
OVERLAPPED overlapped = {};
@@ -244,7 +253,7 @@ static std::wstring safe_string(WCHAR value[], int length)
}
// find the friendly name for an adapter in the registry
-static std::wstring get_connection_name(std::wstring &id)
+static std::wstring get_connection_name(std::wstring const &id)
{
std::wstring result;
@@ -326,7 +335,7 @@ static std::vector<std::wstring> get_tap_adapters()
return result;
}
#else
-int netdev_tap::send(uint8_t *buf, int len)
+int netdev_tap::send(void const *buf, int len)
{
if(m_fd == -1) return 0;
len = write(m_fd, buf, len);
@@ -335,42 +344,52 @@ int netdev_tap::send(uint8_t *buf, int len)
int netdev_tap::recv_dev(uint8_t **buf)
{
- int len;
- if(m_fd == -1) return 0;
- // exit if we didn't receive anything, got an error, got a broadcast or multicast packet,
- // are in promiscuous mode or got a packet with our mac.
- do {
- len = read(m_fd, m_buf, sizeof(m_buf));
- } while((len > 0) && memcmp(&get_mac()[0], m_buf, 6) && !get_promisc() && !(m_buf[0] & 1));
+ if (0 > m_fd)
+ return 0;
+
+ int len = read(m_fd, m_buf, sizeof(m_buf));
if (len > 0)
len = finalise_frame(m_buf, len);
*buf = m_buf;
- return (len == -1)?0:len;
+ return (len == -1) ? 0 : len;
}
#endif
-static CREATE_NETDEV(create_tap)
-{
- auto *dev = new netdev_tap(ifname, ifdev);
- return dynamic_cast<osd_network_device *>(dev);
-}
-
int taptun_module::init(osd_interface &osd, const osd_options &options)
{
#if defined(_WIN32)
- for (std::wstring &id : get_tap_adapters())
- add_netdev(utf8_from_wstring(id).c_str(), utf8_from_wstring(get_connection_name(id)).c_str(), create_tap);
+ auto const adapters = get_tap_adapters();
+ m_devices.reserve(adapters.size());
+ for (std::wstring const &id : adapters)
+ m_devices.emplace_back(device_info{ utf8_from_wstring(id), utf8_from_wstring(get_connection_name(id)) });
#else
- add_netdev("tap", "TAP/TUN Device", create_tap);
+ m_devices.emplace_back(device_info{ "tap", "TUN/TAP Device" });
#endif
return 0;
}
void taptun_module::exit()
{
- clear_netdev();
+ m_devices.clear();
+}
+
+std::unique_ptr<network_device> taptun_module::open_device(int id, network_handler &handler)
+{
+ if ((0 > id) || (m_devices.size() <= id))
+ return nullptr;
+
+ return std::make_unique<netdev_tap>(m_devices[id].name.c_str(), handler);
+}
+
+std::vector<network_device_info> taptun_module::list_devices()
+{
+ std::vector<network_device_info> result;
+ result.reserve(m_devices.size());
+ for (int id = 0; m_devices.size() > id; ++id)
+ result.emplace_back(network_device_info{ id, m_devices[id].description });
+ return result;
}
} // anonymous namespace