Converted pcap and taptun network code into modules. (nw)

This commit is contained in:
couriersud 2015-01-30 21:10:32 +01:00
parent 723823ce11
commit ae4dddb9c1
22 changed files with 409 additions and 622 deletions

View File

@ -1,7 +1,7 @@
#ifndef __DINETWORK_H__
#define __DINETWORK_H__
class netdev;
class osd_netdev;
class device_network_interface : public device_interface
{
@ -24,7 +24,7 @@ protected:
bool m_promisc;
char m_mac[6];
float m_bandwidth;
auto_pointer<class netdev> m_dev;
auto_pointer<class osd_netdev> m_dev;
int m_intf;
};

View File

@ -159,7 +159,7 @@ void ui_menu_network_devices::populate()
{
int curr = network->get_interface();
const char *title = NULL;
const netdev_entry_t *entry = netdev_first();
const osd_netdev::entry_t *entry = netdev_first();
while(entry) {
if(entry->id==curr) {
title = entry->description;

View File

@ -1048,7 +1048,7 @@ void video_manager::recompute_speed(const attotime &emutime)
if (filerr == FILERR_NONE)
save_snapshot(machine().first_screen(), file);
}
//printf("Scheduled exit at %f\n", emutime.as_double());
// schedule our demise
machine().schedule_exit();
}

View File

@ -128,6 +128,10 @@ void osd_common_t::register_options()
REGISTER_MODULE(m_mod_man, DEBUG_INTERNAL);
REGISTER_MODULE(m_mod_man, DEBUG_NONE);
REGISTER_MODULE(m_mod_man, NETDEV_TAPTUN);
REGISTER_MODULE(m_mod_man, NETDEV_PCAP);
// after initialization we know which modules are supported
const char *names[20];
@ -399,9 +403,15 @@ bool osd_common_t::execute_command(const char *command)
{
if (strcmp(command, OSDCOMMAND_LIST_NETWORK_ADAPTERS) == 0)
{
network_init();
osd_list_network_adapters();
network_exit();
osd_module *om = select_module_options(options(), OSD_NETDEV_PROVIDER);
if (om->probe())
{
om->init();
osd_list_network_adapters();
om->exit();
}
return true;
}
else if (strcmp(command, OSDCOMMAND_LIST_MIDI_DEVICES) == 0)
@ -431,9 +441,6 @@ void osd_common_t::init_subsystems()
machine().add_notifier(MACHINE_NOTIFY_RESUME, machine_notify_delegate(FUNC(osd_common_t::input_resume), this));
output_init();
#ifdef USE_NETWORK
network_init();
#endif
midi_init();
m_font_module = select_module_options<font_module *>(options(), OSD_FONT_PROVIDER);
@ -444,6 +451,8 @@ void osd_common_t::init_subsystems()
m_debugger = select_module_options<debug_module *>(options(), OSD_DEBUG_PROVIDER);
select_module_options<netdev_module *>(options(), OSD_NETDEV_PROVIDER);
m_mod_man.init();
}
@ -485,19 +494,11 @@ bool osd_common_t::output_init()
return true;
}
bool osd_common_t::network_init()
{
return true;
}
void osd_common_t::exit_subsystems()
{
video_exit();
input_exit();
output_exit();
#ifdef USE_NETWORK
network_exit();
#endif
midi_exit();
}
@ -517,10 +518,6 @@ void osd_common_t::output_exit()
{
}
void osd_common_t::network_exit()
{
}
void osd_common_t::osd_exit()
{
m_mod_man.exit();

View File

@ -18,6 +18,7 @@
#include "modules/font/font_module.h"
#include "modules/sound/sound_module.h"
#include "modules/debugger/debug_module.h"
#include "modules/netdev/netdev_module.h"
#include "cliopts.h"
//============================================================
@ -164,7 +165,6 @@ public:
virtual void input_resume();
virtual bool output_init();
virtual bool network_init();
virtual bool midi_init();
virtual void exit_subsystems();
@ -172,7 +172,6 @@ public:
virtual void window_exit();
virtual void input_exit();
virtual void output_exit();
virtual void network_exit();
virtual void midi_exit();
virtual void osd_exit();

View File

@ -0,0 +1,303 @@
#ifdef SDLMAME_NET_PCAP
#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include <pcap.h>
#include "emu.h"
#include "osdnet.h"
#include "netdev_module.h"
#include "modules/osdmodule.h"
#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS)
#define LIB_NAME L"wpcap.dll"
#define LIB_ERROR_STR "Unable to load winpcap: %lx\n"
typedef DWORD except_type;
#else
#include <dlfcn.h>
#ifdef SDLMAME_MACOSX
#include <pthread.h>
#include <libkern/OSAtomic.h>
#endif
#ifdef SDLMAME_MACOSX
#define LIB_NAME "libpcap.dylib"
#else
#define LIB_NAME "libpcap.so"
#endif
#define LIB_ERROR_STR "Unable to load pcap: %s\n"
typedef void *HMODULE;
typedef const char *except_type;
#define FreeLibrary(x) dlclose(x)
#define GetLastError() dlerror()
#define GetProcAddress(x, y) dlsym(x, y)
#define LoadLibrary(x) dlopen(x, RTLD_LAZY)
#endif
class pcap_module : public osd_module, public netdev_module
{
public:
pcap_module()
: osd_module(OSD_NETDEV_PROVIDER, "pcap"), netdev_module(), handle(NULL)
{
}
virtual ~pcap_module() { }
virtual int init();
virtual void exit();
virtual bool probe();
HMODULE handle;
};
static int (*pcap_compile_dl)(pcap_t *, struct bpf_program *, char *, int, bpf_u_int32) = NULL;
static int (*pcap_findalldevs_dl)(pcap_if_t **, char *) = NULL;
static pcap_t *(*pcap_open_live_dl)(const char *name, int, int, int, char *) = NULL;
static int (*pcap_next_ex_dl)(pcap_t *, struct pcap_pkthdr **, const u_char **) = NULL;
static void (*pcap_close_dl)(pcap_t *) = NULL;
static int (*pcap_setfilter_dl)(pcap_t *, struct bpf_program *) = NULL;
static int (*pcap_sendpacket_dl)(pcap_t *, u_char *, int) = NULL;
static int (*pcap_set_datalink_dl)(pcap_t *, int) = NULL;
static int (*pcap_dispatch_dl)(pcap_t *, int, pcap_handler callback, u_char *) = NULL;
#if 0
#define pcap_compile_dl pcap_compile
#define pcap_findalldevs_dl pcap_findalldevs
#define pcap_open_live_dl pcap_open_live
#define pcap_next_ex_dl pcap_next_ex
#define pcap_close_dl pcap_close
#define pcap_setfilter_dl pcap_setfilter
#define pcap_sendpacket_dl pcap_sendpacket
#define pcap_set_datalink_dl pcap_set_datalink
#endif
#ifdef SDLMAME_MACOSX
struct netdev_pcap_context {
UINT8 *pkt;
int len;
pcap_t *p;
UINT8 packets[32][1600];
int packetlens[32];
int head;
int tail;
};
#endif
class netdev_pcap : public osd_netdev
{
public:
netdev_pcap(const char *name, class device_network_interface *ifdev, int rate);
~netdev_pcap();
int send(UINT8 *buf, int len);
void set_mac(const char *mac);
protected:
int recv_dev(UINT8 **buf);
private:
pcap_t *m_p;
#ifdef SDLMAME_MACOSX
struct netdev_pcap_context m_ctx;
pthread_t m_thread;
#endif
};
#ifdef SDLMAME_MACOSX
static void netdev_pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) {
struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)user;
if(OSAtomicCompareAndSwapInt((ctx->head+1) & 0x1F, ctx->tail, &ctx->tail)) {
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);
}
static void *netdev_pcap_blocker(void *arg) {
struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)arg;
while(1) {
pcap_dispatch_dl(ctx->p, 1, netdev_pcap_handler, (u_char*)ctx);
}
return 0;
}
#endif
netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev, int rate)
: osd_netdev(ifdev, rate)
{
char errbuf[PCAP_ERRBUF_SIZE];
#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS)
m_p = pcap_open_live_dl(name, 65535, 1, -1, errbuf);
#else
m_p = pcap_open_live_dl(name, 65535, 1, 1, errbuf);
#endif
if(!m_p)
{
logerror("Unable to open %s: %s\n", name, errbuf);
return;
}
if(pcap_set_datalink_dl(m_p, DLT_EN10MB) == -1)
{
logerror("Unable to set %s to ethernet", name);
pcap_close_dl(m_p);
m_p = NULL;
return;
}
set_mac(get_mac());
#ifdef SDLMAME_MACOSX
m_ctx.head = 0;
m_ctx.tail = 0;
m_ctx.p = m_p;
pthread_create(&m_thread, NULL, netdev_pcap_blocker, &m_ctx);
#endif
}
void netdev_pcap::set_mac(const char *mac)
{
char filter[256];
struct bpf_program fp;
if(!m_p) return;
#ifdef SDLMAME_MACOSX
sprintf(filter, "not ether src %.2X:%.2X:%.2X:%.2X:%.2X:%.2X and (ether dst %.2X:%.2X:%.2X:%.2X:%.2X:%.2X 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
sprintf(filter, "ether dst %.2X:%.2X:%.2X:%.2X:%.2X:%.2X 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]);
#endif
if(pcap_compile_dl(m_p, &fp, filter, 1, 0) == -1) {
logerror("Error with pcap_compile\n");
}
if(pcap_setfilter_dl(m_p, &fp) == -1) {
logerror("Error with pcap_setfilter\n");
}
}
int netdev_pcap::send(UINT8 *buf, int len)
{
if(!m_p) return 0;
return (!pcap_sendpacket_dl(m_p, buf, len))?len:0;
}
int netdev_pcap::recv_dev(UINT8 **buf)
{
#ifdef SDLMAME_MACOSX
UINT8 pktbuf[2048];
int ret;
// Empty
if(OSAtomicCompareAndSwapInt(m_ctx.head, m_ctx.tail, &m_ctx.tail)) {
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;
return ret;
#else
struct pcap_pkthdr *header;
if(!m_p) return 0;
return (pcap_next_ex_dl(m_p, &header, (const u_char **)buf) == 1)?header->len:0;
#endif
}
netdev_pcap::~netdev_pcap()
{
if(m_p) pcap_close_dl(m_p);
}
static CREATE_NETDEV(create_pcap)
{
class netdev_pcap *dev = global_alloc(netdev_pcap(ifname, ifdev, rate));
return dynamic_cast<osd_netdev *>(dev);
}
bool pcap_module::probe()
{
if (handle == NULL)
{
handle = LoadLibrary(LIB_NAME);
return (handle != NULL);
}
return true;
}
int pcap_module::init()
{
pcap_if_t *devs;
char errbuf[PCAP_ERRBUF_SIZE];
try
{
if(!(pcap_findalldevs_dl = (int (*)(pcap_if_t **, char *))GetProcAddress(handle, "pcap_findalldevs")))
throw GetLastError();
if(!(pcap_open_live_dl = (pcap_t* (*)(const char *, int, int, int, char *))GetProcAddress(handle, "pcap_open_live")))
throw GetLastError();
if(!(pcap_next_ex_dl = (int (*)(pcap_t *, struct pcap_pkthdr **, const u_char **))GetProcAddress(handle, "pcap_next_ex")))
throw GetLastError();
if(!(pcap_compile_dl = (int (*)(pcap_t *, struct bpf_program *, char *, int, bpf_u_int32))GetProcAddress(handle, "pcap_compile")))
throw GetLastError();
if(!(pcap_close_dl = (void (*)(pcap_t *))GetProcAddress(handle, "pcap_close")))
throw GetLastError();
if(!(pcap_setfilter_dl = (int (*)(pcap_t *, struct bpf_program *))GetProcAddress(handle, "pcap_setfilter")))
throw GetLastError();
if(!(pcap_sendpacket_dl = (int (*)(pcap_t *, u_char *, int))GetProcAddress(handle, "pcap_sendpacket")))
throw GetLastError();
if(!(pcap_set_datalink_dl = (int (*)(pcap_t *, int))GetProcAddress(handle, "pcap_set_datalink")))
throw GetLastError();
if(!(pcap_dispatch_dl = (int (*)(pcap_t *, int, pcap_handler callback, u_char *))GetProcAddress(handle, "pcap_dispatch")))
throw GetLastError();
}
catch (except_type e)
{
FreeLibrary(handle);
logerror(LIB_ERROR_STR, e);
return 1;
}
if(pcap_findalldevs_dl(&devs, errbuf) == -1)
{
FreeLibrary(handle);
logerror("Unable to get network devices: %s\n", errbuf);
return 1;
}
while(devs)
{
add_netdev(devs->name, devs->description, create_pcap);
devs = devs->next;
}
return 0;
}
void pcap_module::exit()
{
clear_netdev();
FreeLibrary(handle);
handle = NULL;
}
#else
#include "modules/osdmodule.h"
#include "netdev_module.h"
MODULE_NOT_SUPPORTED(pcap_module, OSD_NETDEV_PROVIDER, "pcap")
#endif
MODULE_DEFINITION(NETDEV_PCAP, pcap_module)

View File

@ -1,3 +1,5 @@
#if defined(SDLMAME_NET_TAPTUN)
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
@ -6,6 +8,8 @@
#include "emu.h"
#include "osdnet.h"
#include "modules/osdmodule.h"
#include "netdev_module.h"
#ifdef __linux__
#define IFF_TAP 0x0002
@ -13,7 +17,25 @@
#define TUNSETIFF _IOW('T', 202, int)
#endif
class netdev_tap : public netdev
class taptun_module : public osd_module, public netdev_module
{
public:
taptun_module()
: osd_module(OSD_NETDEV_PROVIDER, "taptun"), netdev_module()
{
}
virtual ~taptun_module() { }
virtual int init();
virtual void exit();
virtual bool probe() { return true; }
};
class netdev_tap : public osd_netdev
{
public:
netdev_tap(const char *name, class device_network_interface *ifdev, int rate);
@ -31,7 +53,7 @@ private:
};
netdev_tap::netdev_tap(const char *name, class device_network_interface *ifdev, int rate)
: netdev(ifdev, rate)
: osd_netdev(ifdev, rate)
{
#ifdef __linux__
struct ifreq ifr;
@ -93,15 +115,27 @@ int netdev_tap::recv_dev(UINT8 **buf)
static CREATE_NETDEV(create_tap)
{
class netdev_tap *dev = global_alloc(netdev_tap(ifname, ifdev, rate));
return dynamic_cast<netdev *>(dev);
return dynamic_cast<osd_netdev *>(dev);
}
void init_tap()
int taptun_module::init()
{
add_netdev("tap", "TAP/TUN Device", create_tap);
return 0;
}
void deinit_tap()
void taptun_module::exit()
{
clear_netdev();
}
#else
#include "modules/osdmodule.h"
#include "netdev_module.h"
MODULE_NOT_SUPPORTED(taptun_module, OSD_NETDEV_PROVIDER, "taptun")
#endif
MODULE_DEFINITION(NETDEV_TAPTUN, taptun_module)

View File

@ -34,7 +34,7 @@ public:
const char * name() const { return m_name; }
const char * type() const { return m_type; }
virtual bool probe() const { return true; }
virtual bool probe() { return true; }
virtual int init() { return 0; }
virtual void exit() { }
@ -100,7 +100,7 @@ private:
public: \
_mod () \
: osd_module(_type, _name) {} \
bool probe() const { return false; } \
bool probe() { return false; } \
};
#endif /* __OSDMODULE_H__ */

View File

@ -1,11 +1,11 @@
#include "emu.h"
#include "osdnet.h"
static class simple_list<netdev_entry_t> netdev_list;
static class simple_list<osd_netdev::entry_t> netdev_list;
void add_netdev(const char *name, const char *description, create_netdev func)
{
netdev_entry_t *entry = global_alloc_clear(netdev_entry_t);
osd_netdev::entry_t *entry = global_alloc_clear(osd_netdev::entry_t);
entry->id = netdev_list.count();
strncpy(entry->name, name, 255);
entry->name[255] = '\0';
@ -20,13 +20,13 @@ void clear_netdev()
netdev_list.reset();
}
const netdev_entry_t *netdev_first() {
const osd_netdev::entry_t *netdev_first() {
return netdev_list.first();
}
class netdev *open_netdev(int id, class device_network_interface *ifdev, int rate)
class osd_netdev *open_netdev(int id, class device_network_interface *ifdev, int rate)
{
netdev_entry_t *entry = netdev_list.first();
osd_netdev::entry_t *entry = netdev_list.first();
while(entry) {
if(entry->id==id)
return entry->func(entry->name, ifdev, rate);
@ -36,22 +36,22 @@ class netdev *open_netdev(int id, class device_network_interface *ifdev, int rat
return NULL;
}
netdev::netdev(class device_network_interface *ifdev, int rate)
osd_netdev::osd_netdev(class device_network_interface *ifdev, int rate)
{
m_dev = ifdev;
ifdev->device().machine().scheduler().timer_pulse(attotime::from_hz(rate), timer_expired_delegate(FUNC(netdev::recv), this));
ifdev->device().machine().scheduler().timer_pulse(attotime::from_hz(rate), timer_expired_delegate(FUNC(osd_netdev::recv), this));
}
netdev::~netdev()
osd_netdev::~osd_netdev()
{
}
int netdev::send(UINT8 *buf, int len)
int osd_netdev::send(UINT8 *buf, int len)
{
return 0;
}
void netdev::recv(void *ptr, int param)
void osd_netdev::recv(void *ptr, int param)
{
UINT8 *buf;
int len;
@ -74,27 +74,27 @@ void netdev::recv(void *ptr, int param)
}
}
int netdev::recv_dev(UINT8 **buf)
int osd_netdev::recv_dev(UINT8 **buf)
{
return 0;
}
void netdev::set_mac(const char *mac)
void osd_netdev::set_mac(const char *mac)
{
}
void netdev::set_promisc(bool promisc)
void osd_netdev::set_promisc(bool promisc)
{
}
bool netdev::get_promisc()
bool osd_netdev::get_promisc()
{
if(m_dev)
return m_dev->get_promisc();
return false;
}
const char *netdev::get_mac()
const char *osd_netdev::get_mac()
{
if(m_dev)
return m_dev->get_mac();
@ -118,7 +118,7 @@ void osd_list_network_adapters(void)
}
printf("Available network adapters:\n");
const netdev_entry_t *entry = netdev_first();
const osd_netdev::entry_t *entry = netdev_first();
while(entry) {
printf(" %s\n", entry->description);
entry = entry->m_next;

View File

@ -3,25 +3,24 @@
#ifndef __OSDNET_H__
#define __OSDNET_H__
class netdev;
class osd_netdev;
#define CREATE_NETDEV(name) class netdev *name(const char *ifname, class device_network_interface *ifdev, int rate)
typedef class netdev *(*create_netdev)(const char *ifname, class device_network_interface *ifdev, int rate);
#define CREATE_NETDEV(name) class osd_netdev *name(const char *ifname, class device_network_interface *ifdev, int rate)
typedef class osd_netdev *(*create_netdev)(const char *ifname, class device_network_interface *ifdev, int rate);
struct netdev_entry_t
{
int id;
char name[256];
char description[256];
create_netdev func;
netdev_entry_t *m_next;
};
class netdev
class osd_netdev
{
public:
netdev(class device_network_interface *ifdev, int rate);
virtual ~netdev();
struct entry_t
{
int id;
char name[256];
char description[256];
create_netdev func;
entry_t *m_next;
};
osd_netdev(class device_network_interface *ifdev, int rate);
virtual ~osd_netdev();
virtual int send(UINT8 *buf, int len);
virtual void set_mac(const char *mac);
@ -39,9 +38,9 @@ private:
class device_network_interface *m_dev;
};
class netdev *open_netdev(int id, class device_network_interface *ifdev, int rate);
class osd_netdev *open_netdev(int id, class device_network_interface *ifdev, int rate);
void add_netdev(const char *name, const char *description, create_netdev func);
void clear_netdev();
const netdev_entry_t *netdev_first();
const osd_netdev::entry_t *netdev_first();
int netdev_count();
#endif

View File

@ -1,25 +0,0 @@
#include "emu.h"
#include "netdev_tap.h"
#include "netdev_pcap.h"
#include "osdsdl.h"
bool sdl_osd_interface::network_init()
{
#ifdef SDLMAME_NET_TAPTUN
init_tap();
#endif
#ifdef SDLMAME_NET_PCAP
init_pcap();
#endif
return true;
}
void sdl_osd_interface::network_exit()
{
#ifdef SDLMAME_NET_TAPTUN
deinit_tap();
#endif
#ifdef SDLMAME_NET_PCAP
deinit_pcap();
#endif
}

View File

@ -1,148 +0,0 @@
#ifdef SDLMAME_WIN32
#include "../windows/netdev_pcap.c"
#else
#include <pcap.h>
static int (*pcap_compile_dl)(pcap_t *, struct bpf_program *, char *, int, bpf_u_int32) = NULL;
static int (*pcap_findalldevs_dl)(pcap_if_t **, char *) = NULL;
static pcap_t *(*pcap_open_live_dl)(const char *name, int, int, int, char *) = NULL;
static int (*pcap_next_ex_dl)(pcap_t *, struct pcap_pkthdr **, const u_char **) = NULL;
static void (*pcap_close_dl)(pcap_t *) = NULL;
static int (*pcap_setfilter_dl)(pcap_t *, struct bpf_program *) = NULL;
static int (*pcap_sendpacket_dl)(pcap_t *, u_char *, int) = NULL;
static int (*pcap_set_datalink_dl)(pcap_t *, int) = NULL;
#include <dlfcn.h>
#include "emu.h"
#include "osdnet.h"
static void *handle = NULL;
class netdev_pcap : public netdev
{
public:
netdev_pcap(const char *name, class device_network_interface *ifdev, int rate);
~netdev_pcap();
int send(UINT8 *buf, int len);
void set_mac(const char *mac);
protected:
int recv_dev(UINT8 **buf);
private:
pcap_t *m_p;
};
netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev, int rate)
: netdev(ifdev, rate)
{
char errbuf[PCAP_ERRBUF_SIZE];
m_p = pcap_open_live_dl(name, 65535, 1, 1, errbuf);
if(!m_p)
{
osd_printf_verbose("Unable to open %s: %s\n", name, errbuf);
return;
}
if(pcap_set_datalink_dl(m_p, DLT_EN10MB) == -1)
{
osd_printf_verbose("Unable to set %s to ethernet\n", name);
pcap_close_dl(m_p);
m_p = NULL;
return;
}
set_mac(get_mac());
}
void netdev_pcap::set_mac(const char *mac)
{
char filter[256];
struct bpf_program fp;
if(!m_p) return;
sprintf(filter, "ether dst %.2X:%.2X:%.2X:%.2X:%.2X:%.2X 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]);
if(pcap_compile_dl(m_p, &fp, filter, 1, 0) == -1) {
osd_printf_verbose("Error with pcap_compile\n");
}
if(pcap_setfilter_dl(m_p, &fp) == -1) {
osd_printf_verbose("Error with pcap_setfilter\n");
}
}
int netdev_pcap::send(UINT8 *buf, int len)
{
if(!m_p) return 0;
return (!pcap_sendpacket_dl(m_p, buf, len))?len:0;
}
int netdev_pcap::recv_dev(UINT8 **buf)
{
struct pcap_pkthdr *header;
if(!m_p) return 0;
return (pcap_next_ex_dl(m_p, &header, (const u_char **)buf) == 1)?header->len:0;
}
netdev_pcap::~netdev_pcap()
{
if(m_p) pcap_close_dl(m_p);
}
static CREATE_NETDEV(create_pcap)
{
class netdev_pcap *dev = global_alloc(netdev_pcap(ifname, ifdev, rate));
return dynamic_cast<netdev *>(dev);
}
void init_pcap()
{
pcap_if_t *devs;
char errbuf[PCAP_ERRBUF_SIZE];
handle = NULL;
try
{
if(!(handle = dlopen("libpcap.so", RTLD_LAZY))) throw dlerror();
if(!(pcap_findalldevs_dl = (int (*)(pcap_if_t **, char *))dlsym(handle, "pcap_findalldevs")))
throw dlerror();
if(!(pcap_open_live_dl = (pcap_t* (*)(const char *, int, int, int, char *))dlsym(handle, "pcap_open_live")))
throw dlerror();
if(!(pcap_next_ex_dl = (int (*)(pcap_t *, struct pcap_pkthdr **, const u_char **))dlsym(handle, "pcap_next_ex")))
throw dlerror();
if(!(pcap_compile_dl = (int (*)(pcap_t *, struct bpf_program *, char *, int, bpf_u_int32))dlsym(handle, "pcap_compile")))
throw dlerror();
if(!(pcap_close_dl = (void (*)(pcap_t *))dlsym(handle, "pcap_close")))
throw dlerror();
if(!(pcap_setfilter_dl = (int (*)(pcap_t *, struct bpf_program *))dlsym(handle, "pcap_setfilter")))
throw dlerror();
if(!(pcap_sendpacket_dl = (int (*)(pcap_t *, u_char *, int))dlsym(handle, "pcap_sendpacket")))
throw dlerror();
if(!(pcap_set_datalink_dl = (int (*)(pcap_t *, int))dlsym(handle, "pcap_set_datalink")))
throw dlerror();
}
catch (const char *e)
{
dlclose(handle);
osd_printf_verbose("Unable to load winpcap: %s\n", e);
return;
}
if(pcap_findalldevs_dl(&devs, errbuf) == -1)
{
dlclose(handle);
osd_printf_verbose("Unable to get network devices: %s\n", errbuf);
return;
}
while(devs)
{
add_netdev(devs->name, devs->description, create_pcap);
devs = devs->next;
}
}
void deinit_pcap()
{
clear_netdev();
dlclose(handle);
handle = NULL;
}
#endif // SDLMAME_WIN32

View File

@ -1,7 +0,0 @@
#ifndef __NETDEV_PCAP_H__
#define __NETDEV_PCAP_H__
void init_pcap();
void deinit_pcap();
#endif

View File

@ -1,175 +0,0 @@
#ifdef SDLMAME_WIN32
#include "../windows/netdev_pcap.c"
#else
#include <pcap.h>
#include "emu.h"
#include "osdnet.h"
#include <pthread.h>
#include <libkern/OSAtomic.h>
#define pcap_compile_dl pcap_compile
#define pcap_findalldevs_dl pcap_findalldevs
#define pcap_open_live_dl pcap_open_live
#define pcap_next_ex_dl pcap_next_ex
#define pcap_close_dl pcap_close
#define pcap_setfilter_dl pcap_setfilter
#define pcap_sendpacket_dl pcap_sendpacket
#define pcap_set_datalink_dl pcap_set_datalink
struct netdev_pcap_context {
UINT8 *pkt;
int len;
pcap_t *p;
UINT8 packets[32][1600];
int packetlens[32];
int head;
int tail;
};
class netdev_pcap : public netdev
{
public:
netdev_pcap(const char *name, class device_network_interface *ifdev, int rate);
~netdev_pcap();
int send(UINT8 *buf, int len);
void set_mac(const char *mac);
protected:
int recv_dev(UINT8 **buf);
private:
pcap_t *m_p;
struct netdev_pcap_context m_ctx;
pthread_t m_thread;
};
static void netdev_pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) {
struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)user;
if(OSAtomicCompareAndSwapInt((ctx->head+1) & 0x1F, ctx->tail, &ctx->tail)) {
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);
}
static void *netdev_pcap_blocker(void *arg) {
struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)arg;
while(1) {
pcap_dispatch(ctx->p, 1, netdev_pcap_handler, (u_char*)ctx);
}
return 0;
}
netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev, int rate)
: netdev(ifdev, rate)
{
char errbuf[PCAP_ERRBUF_SIZE];
m_p = pcap_open_live_dl(name, 65535, 1, 1, errbuf);
if(!m_p)
{
osd_printf_verbose("Unable to open %s: %s\n", name, errbuf);
return;
}
if(pcap_set_datalink_dl(m_p, DLT_EN10MB) == -1)
{
osd_printf_verbose("Unable to set %s to ethernet\n", name);
pcap_close_dl(m_p);
m_p = NULL;
return;
}
set_mac(get_mac());
m_ctx.head = 0;
m_ctx.tail = 0;
m_ctx.p = m_p;
pthread_create(&m_thread, NULL, netdev_pcap_blocker, &m_ctx);
}
void netdev_pcap::set_mac(const char *mac)
{
char filter[256];
struct bpf_program fp;
if(!m_p) return;
sprintf(filter, "not ether src %.2X:%.2X:%.2X:%.2X:%.2X:%.2X and (ether dst %.2X:%.2X:%.2X:%.2X:%.2X:%.2X 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]);
if(pcap_compile_dl(m_p, &fp, filter, 1, 0) == -1) {
osd_printf_verbose("Error with pcap_compile\n");
}
if(pcap_setfilter_dl(m_p, &fp) == -1) {
osd_printf_verbose("Error with pcap_setfilter\n");
}
}
int netdev_pcap::send(UINT8 *buf, int len)
{
if(!m_p) return 0;
return (!pcap_sendpacket_dl(m_p, buf, len))?len:0;
}
int netdev_pcap::recv_dev(UINT8 **buf)
{
UINT8 pktbuf[2048];
int ret;
// Empty
if(OSAtomicCompareAndSwapInt(m_ctx.head, m_ctx.tail, &m_ctx.tail)) {
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;
return ret;
}
netdev_pcap::~netdev_pcap()
{
if(m_p) pcap_close_dl(m_p);
}
static CREATE_NETDEV(create_pcap)
{
class netdev_pcap *dev = global_alloc(netdev_pcap(ifname, ifdev, rate));
return dynamic_cast<netdev *>(dev);
}
void init_pcap()
{
pcap_if_t *devs;
char errbuf[PCAP_ERRBUF_SIZE];
if(pcap_findalldevs_dl(&devs, errbuf) == -1)
{
osd_printf_verbose("Unable to get network devices: %s\n", errbuf);
return;
}
#if 1
while(devs)
{
add_netdev(devs->name, devs->description, create_pcap);
devs = devs->next;
}
#else
if (devs)
{
while(devs->next)
{
add_netdev(devs->name, devs->description ? devs->description : devs->name, create_pcap);
devs = devs->next;
}
}
#endif
}
void deinit_pcap()
{
clear_netdev();
}
#endif // SDLMAME_WIN32

View File

@ -1,6 +0,0 @@
#ifndef __NETDEV_TAP_H__
#define __NETDEV_TAP_H__
void init_tap();
void deinit_tap();
#endif

View File

@ -195,18 +195,12 @@ public:
virtual void input_pause();
virtual void input_resume();
virtual bool output_init();
#ifdef USE_NETWORK
virtual bool network_init();
#endif
//virtual bool midi_init();
virtual void video_exit();
virtual void window_exit();
virtual void input_exit();
virtual void output_exit();
#ifdef USE_NETWORK
virtual void network_exit();
#endif
//virtual void midi_exit();
sdl_options &options() { return m_options; }

View File

@ -403,6 +403,7 @@ OBJDIRS += $(SDLOBJ) \
$(OSDOBJ)/modules/lib \
$(OSDOBJ)/modules/midi \
$(OSDOBJ)/modules/font \
$(OSDOBJ)/modules/netdev \
#-------------------------------------------------
# OSD core library
@ -445,6 +446,8 @@ OSDOBJS = \
$(OSDOBJ)/modules/font/font_windows.o \
$(OSDOBJ)/modules/font/font_osx.o \
$(OSDOBJ)/modules/font/font_none.o \
$(OSDOBJ)/modules/netdev/taptun.o \
$(OSDOBJ)/modules/netdev/pcap.o \
ifdef NO_USE_MIDI
OSDOBJS += $(OSDOBJ)/modules/midi/none.o
@ -452,10 +455,6 @@ else
OSDOBJS += $(OSDOBJ)/modules/midi/portmidi.o
endif
ifeq ($(BASE_TARGETOS),win32)
OSDOBJS += $(OSDOBJ)/modules/sound/direct_sound.o
endif
# Add SDL2.0 support
ifeq ($(SDL_LIBVER),sdl2)
@ -465,12 +464,6 @@ endif
# add an ARCH define
DEFS += -DSDLMAME_ARCH="$(ARCHOPTS)" -DSYNC_IMPLEMENTATION=$(SYNC_IMPLEMENTATION)
# Add JavaScript sound module for Emscripten compiles
ifeq ($(TARGETOS),emscripten)
OSDOBJS += $(OSDOBJ)/modules/sound/js_sound.o
endif
#-------------------------------------------------
# Generic defines and additions
#-------------------------------------------------
@ -828,29 +821,21 @@ endif # USE_XINPUT
# Network (TAP/TUN)
#-------------------------------------------------
OSDOBJS += $(SDLOBJ)/netdev.o
ifndef DONT_USE_NETWORK
ifeq ($(SDL_NETWORK),taptun)
OSDOBJS += $(SDLOBJ)/netdev_tap.o
DEFS += -DSDLMAME_NETWORK -DSDLMAME_NET_TAPTUN
DEFS += -DSDLMAME_NET_TAPTUN
endif
ifeq ($(SDL_NETWORK),pcap)
ifeq ($(TARGETOS),macosx)
OSDOBJS += $(SDLOBJ)/netdev_pcap_osx.o
else
OSDOBJS += $(SDLOBJ)/netdev_pcap.o
endif
DEFS += -DSDLMAME_NET_PCAP
DEFS += -DSDLMAME_NETWORK -DSDLMAME_NET_PCAP
ifneq ($(TARGETOS),win32)
LIBS += -lpcap
endif
# dynamically linked ...
#ifneq ($(TARGETOS),win32)
#LIBS += -lpcap
#endif
endif # ifeq ($(SDL_NETWORK),pcap)

View File

@ -1,14 +0,0 @@
#include "emu.h"
#include "winmain.h"
#include "netdev_pcap.h"
bool windows_osd_interface::network_init()
{
init_pcap();
return true;
}
void windows_osd_interface::network_exit()
{
deinit_pcap();
}

View File

@ -1,137 +0,0 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <pcap.h>
static int (*pcap_compile_dl)(pcap_t *, struct bpf_program *, char *, int, bpf_u_int32) = NULL;
static int (*pcap_findalldevs_dl)(pcap_if_t **, char *) = NULL;
static pcap_t *(*pcap_open_live_dl)(const char *name, int, int, int, char *) = NULL;
static int (*pcap_next_ex_dl)(pcap_t *, struct pcap_pkthdr **, const u_char **) = NULL;
static void (*pcap_close_dl)(pcap_t *) = NULL;
static int (*pcap_setfilter_dl)(pcap_t *, struct bpf_program *) = NULL;
static int (*pcap_sendpacket_dl)(pcap_t *, u_char *, int) = NULL;
static int (*pcap_set_datalink_dl)(pcap_t *, int) = NULL;
static HMODULE handle = NULL;
#include "emu.h"
#include "osdnet.h"
class netdev_pcap : public netdev
{
public:
netdev_pcap(const char *name, class device_network_interface *ifdev, int rate);
~netdev_pcap();
int send(UINT8 *buf, int len);
void set_mac(const char *mac);
protected:
int recv_dev(UINT8 **buf);
private:
pcap_t *m_p;
};
netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev, int rate)
: netdev(ifdev, rate)
{
char errbuf[PCAP_ERRBUF_SIZE];
m_p = pcap_open_live_dl(name, 65535, 1, -1, errbuf);
if(!m_p)
{
logerror("Unable to open %s: %s\n", name, errbuf);
return;
}
if(pcap_set_datalink_dl(m_p, DLT_EN10MB) == -1)
{
logerror("Unable to set %s to ethernet", name);
pcap_close_dl(m_p);
m_p = NULL;
return;
}
set_mac(get_mac());
}
void netdev_pcap::set_mac(const char *mac)
{
char filter[256];
struct bpf_program fp;
if(!m_p) return;
sprintf(filter, "ether dst %.2X:%.2X:%.2X:%.2X:%.2X:%.2X 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]);
pcap_compile_dl(m_p, &fp, filter, 1, 0);
pcap_setfilter_dl(m_p, &fp);
}
int netdev_pcap::send(UINT8 *buf, int len)
{
if(!m_p) return 0;
return (!pcap_sendpacket_dl(m_p, buf, len))?len:0;
}
int netdev_pcap::recv_dev(UINT8 **buf)
{
struct pcap_pkthdr *header;
if(!m_p) return 0;
return (pcap_next_ex_dl(m_p, &header, (const u_char **)buf) == 1)?header->len:0;
}
netdev_pcap::~netdev_pcap()
{
if(m_p && handle) pcap_close_dl(m_p);
}
static CREATE_NETDEV(create_pcap)
{
class netdev_pcap *dev = global_alloc(netdev_pcap(ifname, ifdev, rate));
return dynamic_cast<netdev *>(dev);
}
void init_pcap()
{
pcap_if_t *devs;
char errbuf[PCAP_ERRBUF_SIZE];
handle = NULL;
try
{
if(!(handle = LoadLibrary(L"wpcap.dll"))) throw GetLastError();
if(!(pcap_findalldevs_dl = (int (*)(pcap_if_t **, char *))GetProcAddress(handle, "pcap_findalldevs")))
throw GetLastError();
if(!(pcap_open_live_dl = (pcap_t* (*)(const char *, int, int, int, char *))GetProcAddress(handle, "pcap_open_live")))
throw GetLastError();
if(!(pcap_next_ex_dl = (int (*)(pcap_t *, struct pcap_pkthdr **, const u_char **))GetProcAddress(handle, "pcap_next_ex")))
throw GetLastError();
if(!(pcap_compile_dl = (int (*)(pcap_t *, struct bpf_program *, char *, int, bpf_u_int32))GetProcAddress(handle, "pcap_compile")))
throw GetLastError();
if(!(pcap_close_dl = (void (*)(pcap_t *))GetProcAddress(handle, "pcap_close")))
throw GetLastError();
if(!(pcap_setfilter_dl = (int (*)(pcap_t *, struct bpf_program *))GetProcAddress(handle, "pcap_setfilter")))
throw GetLastError();
if(!(pcap_sendpacket_dl = (int (*)(pcap_t *, u_char *, int))GetProcAddress(handle, "pcap_sendpacket")))
throw GetLastError();
if(!(pcap_set_datalink_dl = (int (*)(pcap_t *, int))GetProcAddress(handle, "pcap_set_datalink")))
throw GetLastError();
}
catch (DWORD e)
{
FreeLibrary(handle);
osd_printf_verbose("Unable to load winpcap: %lx\n", e);
return;
}
if(pcap_findalldevs_dl(&devs, errbuf) == -1)
{
FreeLibrary(handle);
osd_printf_verbose("Unable to get network devices: %s\n", errbuf);
return;
}
while(devs)
{
add_netdev(devs->name, devs->description, create_pcap);
devs = devs->next;
}
}
void deinit_pcap()
{
clear_netdev();
FreeLibrary(handle);
handle = NULL;
}

View File

@ -1,7 +0,0 @@
#ifndef __NETDEV_PCAP_H__
#define __NETDEV_PCAP_H__
void init_pcap();
void deinit_pcap();
#endif

View File

@ -92,6 +92,7 @@ OBJDIRS += $(WINOBJ) \
$(OSDOBJ)/modules/lib \
$(OSDOBJ)/modules/midi \
$(OSDOBJ)/modules/font \
$(OSDOBJ)/modules/netdev \
ifdef USE_QTDEBUG
OBJDIRS += $(OSDOBJ)/modules/debugger/qt
@ -387,6 +388,8 @@ OSDOBJS = \
$(OSDOBJ)/modules/font/font_windows.o \
$(OSDOBJ)/modules/font/font_osx.o \
$(OSDOBJ)/modules/font/font_none.o \
$(OSDOBJ)/modules/netdev/pcap.o \
$(OSDOBJ)/modules/netdev/taptun.o \
ifdef USE_SDL
OSDOBJS += \
@ -394,9 +397,7 @@ OSDOBJS += \
endif
ifndef DONT_USE_NETWORK
OSDOBJS += \
$(WINOBJ)/netdev.o \
$(WINOBJ)/netdev_pcap.o
DEFS += -DSDLMAME_NET_PCAP
endif
CCOMFLAGS += -DDIRECT3D_VERSION=0x0900

View File

@ -260,17 +260,11 @@ public:
virtual void input_pause();
virtual void input_resume();
virtual bool output_init();
#ifdef USE_NETWORK
virtual bool network_init();
#endif
virtual void video_exit();
virtual void window_exit();
virtual void input_exit();
virtual void output_exit();
#ifdef USE_NETWORK
virtual void network_exit();
#endif
private:
void osd_exit();