diff options
Diffstat (limited to 'src/osd')
-rw-r--r-- | src/osd/interface/nethandler.cpp | 1 | ||||
-rw-r--r-- | src/osd/interface/nethandler.h | 27 | ||||
-rw-r--r-- | src/osd/modules/lib/osdobj_common.cpp | 30 | ||||
-rw-r--r-- | src/osd/modules/lib/osdobj_common.h | 14 | ||||
-rw-r--r-- | src/osd/modules/netdev/netdev_common.cpp | 39 | ||||
-rw-r--r-- | src/osd/modules/netdev/netdev_common.h | 36 | ||||
-rw-r--r-- | src/osd/modules/netdev/netdev_module.h | 9 | ||||
-rw-r--r-- | src/osd/modules/netdev/none.cpp | 19 | ||||
-rw-r--r-- | src/osd/modules/netdev/pcap.cpp | 201 | ||||
-rw-r--r-- | src/osd/modules/netdev/taptun.cpp | 105 | ||||
-rw-r--r-- | src/osd/osdepend.h | 5 | ||||
-rw-r--r-- | src/osd/osdnet.cpp | 110 | ||||
-rw-r--r-- | src/osd/osdnet.h | 66 |
13 files changed, 327 insertions, 335 deletions
diff --git a/src/osd/interface/nethandler.cpp b/src/osd/interface/nethandler.cpp index 79823c2d7fd..f3715df9b12 100644 --- a/src/osd/interface/nethandler.cpp +++ b/src/osd/interface/nethandler.cpp @@ -16,7 +16,6 @@ namespace osd { network_handler::network_handler() noexcept - : m_promisc(false) { std::fill(std::begin(m_mac), std::end(m_mac), 0); } diff --git a/src/osd/interface/nethandler.h b/src/osd/interface/nethandler.h index 3a9a47ebd8b..9513b158d99 100644 --- a/src/osd/interface/nethandler.h +++ b/src/osd/interface/nethandler.h @@ -15,6 +15,7 @@ #include "osdcomm.h" #include <array> +#include <string_view> namespace osd { @@ -23,6 +24,7 @@ namespace osd { // TYPE DEFINITIONS //************************************************************************** + // base for virtual network interface handler class network_handler @@ -33,15 +35,36 @@ public: virtual void recv_cb(u8 *buf, int len) = 0; std::array<u8, 6> const &get_mac() noexcept { return m_mac; } - bool get_promisc() noexcept { return m_promisc; } protected: ~network_handler() = default; - bool m_promisc; std::array<u8, 6> m_mac; }; + +// interface to network device + +class network_device +{ +public: + virtual ~network_device() = default; + + virtual void start() = 0; + virtual void stop() = 0; + virtual void poll() = 0; + virtual int send(const void *buf, int len) = 0; +}; + + +// description of an available network device + +struct network_device_info +{ + int id; + std::string_view description; +}; + } // namespace osd #endif // MAME_OSD_INTERFACE_NETHANDLER_H 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..8b5e20077fc 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,132 +116,113 @@ 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 packets[32][1600]; + int packetlens[32]; + std::atomic<int> head; + std::atomic<int> 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->head; + int const next = (curr + 1) & 0x1f; + if (ctx->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->packets[curr], bytes, h->len); + ctx->packetlens[curr] = h->len; + ctx->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]); + head = 0; + 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) { printf("send invoked, but no pcap context\n"); return 0; } - ret = (*module->pcap_sendpacket_dl)(m_p, buf, len); + 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]; @@ -232,60 +232,48 @@ int netdev_pcap::recv_dev(uint8_t **buf) if(!m_p) return 0; // Empty - if(OSAtomicCompareAndSwapInt(m_ctx.head, m_ctx.tail, &m_ctx.tail)) { + + int const curr = tail; + if (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); + memcpy(pktbuf, packets[curr], packetlens[curr]); + ret = packetlens[curr]; + tail.store((curr + 1) & 0x1f, std::memory_order_release); *buf = 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 +281,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 diff --git a/src/osd/osdepend.h b/src/osd/osdepend.h index 8e9a4be6d7a..ebad7883bbe 100644 --- a/src/osd/osdepend.h +++ b/src/osd/osdepend.h @@ -17,6 +17,7 @@ #include "bitmap.h" #include "interface/midiport.h" +#include "interface/nethandler.h" #include <cstdint> #include <memory> @@ -100,6 +101,10 @@ public: virtual std::unique_ptr<osd::midi_output_port> create_midi_output(std::string_view name) = 0; virtual std::vector<osd::midi_port_info> list_midi_ports() = 0; + // network interface + virtual std::unique_ptr<osd::network_device> open_network_device(int id, osd::network_handler &handler) = 0; + virtual std::vector<osd::network_device_info> list_network_devices() = 0; + protected: virtual ~osd_interface() { } }; diff --git a/src/osd/osdnet.cpp b/src/osd/osdnet.cpp deleted file mode 100644 index 7fe2f7b2eb7..00000000000 --- a/src/osd/osdnet.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Carl - -#include "osdnet.h" - -#include "interface/nethandler.h" - - -static std::vector<std::unique_ptr<osd_network_device::entry_t>> netdev_list; - -void add_netdev(const char *name, const char *description, create_netdev func) -{ - auto entry = std::make_unique<osd_network_device::entry_t>(); - entry->id = netdev_list.size(); - strncpy(entry->name, name, 255); - entry->name[255] = '\0'; - strncpy(entry->description, (description != nullptr) ? description : "(no name)", 255); - entry->description[255] = '\0'; - entry->func = func; - netdev_list.push_back(std::move(entry)); -} - -void clear_netdev() -{ - netdev_list.clear(); -} - -const std::vector<std::unique_ptr<osd_network_device::entry_t>>& get_netdev_list() -{ - return netdev_list; -} - -osd_network_device *open_netdev(int id, osd::network_handler &ifdev) -{ - for(auto &entry : netdev_list) - if(entry->id==id) - return entry->func(entry->name, ifdev); - return nullptr; -} - -osd_network_device::osd_network_device(osd::network_handler &ifdev) - : m_dev(ifdev) - , m_stopped(true) -{ -} - -osd_network_device::~osd_network_device() -{ -} - -void osd_network_device::start() -{ - m_stopped = false; -} - -void osd_network_device::stop() -{ - m_stopped = true; -} - -void osd_network_device::poll() -{ - uint8_t *buf; - int len; - //const char atalkmac[] = { 0x09, 0x00, 0x07, 0xff, 0xff, 0xff }; - while(!m_stopped && (len = recv_dev(&buf))) - { -#if 0 - if(buf[0] & 1) - { - if(memcmp("\xff\xff\xff\xff\xff\xff", buf, 6) && memcmp(atalkmac, buf, 6) && !m_dev.mcast_chk(buf, len)) continue; - } - else { - //const unsigned char *ourmac = (const unsigned char *)get_mac(); - //printf("our mac: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X dst mac: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", ourmac[0], ourmac[1], ourmac[2], ourmac[3], ourmac[4], ourmac[5], buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); - if(memcmp(get_mac(), buf, 6) && !get_promisc()) continue; - } -#endif - - m_dev.recv_cb(buf, len); - } -} - -int osd_network_device::send(uint8_t *buf, int len) -{ - return 0; -} - -int osd_network_device::recv_dev(uint8_t **buf) -{ - return 0; -} - -void osd_network_device::set_mac(const uint8_t *mac) -{ -} - -void osd_network_device::set_promisc(bool promisc) -{ -} - -bool osd_network_device::get_promisc() -{ - return m_dev.get_promisc(); -} - -const std::array<uint8_t, 6> &osd_network_device::get_mac() -{ - return m_dev.get_mac(); -} diff --git a/src/osd/osdnet.h b/src/osd/osdnet.h deleted file mode 100644 index 8b21c38d395..00000000000 --- a/src/osd/osdnet.h +++ /dev/null @@ -1,66 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Carl -#ifndef MAME_OSD_OSDNET_H -#define MAME_OSD_OSDNET_H - -#pragma once - -#include "osdcomm.h" - -#include <algorithm> -#include <array> -#include <memory> -#include <vector> - - -namespace osd { class network_handler; } -class osd_network_device; - -#define CREATE_NETDEV(name) osd_network_device *name(const char *ifname, osd::network_handler &ifdev) -typedef osd_network_device *(*create_netdev)(const char *ifname, osd::network_handler &ifdev); - -class osd_network_device -{ -public: - struct entry_t - { - entry_t() - { - std::fill(std::begin(name), std::end(name), 0); - std::fill(std::begin(description), std::end(description), 0); - } - - int id = 0; - char name[256]; - char description[256]; - create_netdev func = nullptr; - }; - - osd_network_device(osd::network_handler &ifdev); - virtual ~osd_network_device(); - - void start(); - void stop(); - void poll(); - - virtual int send(uint8_t *buf, int len); - virtual void set_mac(const uint8_t *mac); - virtual void set_promisc(bool promisc); - - const std::array<uint8_t, 6> &get_mac(); - bool get_promisc(); - -protected: - virtual int recv_dev(uint8_t **buf); - -private: - osd::network_handler &m_dev; - bool m_stopped; -}; - -osd_network_device *open_netdev(int id, osd::network_handler &ifdev); -void add_netdev(const char *name, const char *description, create_netdev func); -void clear_netdev(); -const std::vector<std::unique_ptr<osd_network_device::entry_t>>& get_netdev_list(); - -#endif // MAME_OSD_OSDNET_H |