From 25dadeb8c5c9acf041cfebb7cbce6593e55bd186 Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Sat, 5 Sep 2015 12:24:46 +0200 Subject: [PATCH] refactored slirp to make it possible to use an alternative implementation --- ethernet.cpp | 43 ++-- include/ethernet.h | 13 +- include/uae/slirp.h | 23 ++ od-win32/sysconfig.h | 1 + od-win32/win32_uaenet.cpp | 69 +----- od-win32/winuae_msvc14/winuae_msvc.vcxproj | 1 + .../winuae_msvc14/winuae_msvc.vcxproj.filters | 3 + slirp_uae.cpp | 226 ++++++++++++++++++ 8 files changed, 288 insertions(+), 91 deletions(-) create mode 100644 include/uae/slirp.h create mode 100644 slirp_uae.cpp diff --git a/ethernet.cpp b/ethernet.cpp index 5f2a7696..43c09989 100644 --- a/ethernet.cpp +++ b/ethernet.cpp @@ -1,15 +1,25 @@ +#include "sysconfig.h" +#include "sysdeps.h" -#include "slirp/slirp.h" -#include "slirp/libslirp.h" - +#include "ethernet.h" #ifdef _WIN32 #include "win32_uaenet.h" -#else -#include "ethernet.h" #endif #include "threaddep/thread.h" #include "options.h" #include "sana2.h" +#include "uae/slirp.h" + +#ifndef HAVE_INET_ATON +static int inet_aton(const char *cp, struct in_addr *ia) +{ + uint32_t addr = inet_addr(cp); + if (addr == 0xffffffff) + return 0; + ia->s_addr = addr; + return 1; +} +#endif struct ethernet_data { @@ -44,12 +54,7 @@ static struct netdriverdata slirpd2 = 1 }; -int slirp_can_output(void) -{ - return 1; -} - -void slirp_output (const uint8 *pkt, int pkt_len) +void slirp_output (const uint8_t *pkt, int pkt_len) { if (!slirp_data) return; @@ -77,7 +82,7 @@ void ethernet_trigger (struct netdriverdata *ndd, void *vsd) uae_sem_post (&slirp_sem1); if (v) { uae_sem_wait (&slirp_sem2); - slirp_input(pkt, len); + uae_slirp_input(pkt, len); uae_sem_post (&slirp_sem2); } } @@ -105,21 +110,21 @@ int ethernet_open (struct netdriverdata *ndd, void *vsd, void *user, ethernet_go slirp_data = ed; uae_sem_init (&slirp_sem1, 0, 1); uae_sem_init (&slirp_sem2, 0, 1); - slirp_init (); + uae_slirp_init(); for (int i = 0; i < MAX_SLIRP_REDIRS; i++) { struct slirp_redir *sr = &currprefs.slirp_redirs[i]; if (sr->proto) { struct in_addr a; if (sr->srcport == 0) { inet_aton("10.0.2.15", &a); - slirp_redir (0, sr->dstport, a, sr->dstport); + uae_slirp_redir (0, sr->dstport, a, sr->dstport); } else { #ifdef HAVE_STRUCT_IN_ADDR_S_UN a.S_un.S_addr = sr->addr; #else a.s_addr = sr->addr; #endif - slirp_redir (sr->proto == 1 ? 0 : 1, sr->dstport, a, sr->srcport); + uae_slirp_redir (sr->proto == 1 ? 0 : 1, sr->dstport, a, sr->srcport); } } } @@ -135,11 +140,11 @@ int ethernet_open (struct netdriverdata *ndd, void *vsd, void *user, ethernet_go break; } if (j == MAX_SLIRP_REDIRS) - slirp_redir (0, port + SLIRP_PORT_OFFSET, a, port); + uae_slirp_redir (0, port + SLIRP_PORT_OFFSET, a, port); } } netmode = ndd->type; - slirp_start (); + uae_slirp_start (); } return 1; #ifdef WITH_UAENET_PCAP @@ -164,8 +169,8 @@ void ethernet_close (struct netdriverdata *ndd, void *vsd) case UAENET_SLIRP_INBOUND: if (slirp_data) { slirp_data = NULL; - slirp_end (); - slirp_cleanup (); + uae_slirp_end (); + uae_slirp_cleanup (); uae_sem_destroy (&slirp_sem1); uae_sem_destroy (&slirp_sem2); } diff --git a/include/ethernet.h b/include/ethernet.h index 77465ef7..c1585d02 100644 --- a/include/ethernet.h +++ b/include/ethernet.h @@ -1,5 +1,7 @@ -#ifndef _UAE_ETHERNET_H_ -#define _UAE_ETHERNET_H_ +#ifndef UAE_ETHERNET_H +#define UAE_ETHERNET_H + +#include "uae/types.h" #define UAENET_NONE 0 #define UAENET_SLIRP 1 @@ -28,11 +30,6 @@ extern int ethernet_getdatalenght (struct netdriverdata *ndd); extern int ethernet_getbytespending (void*); extern int ethernet_open (struct netdriverdata *ndd, void*, void*, ethernet_gotfunc*, ethernet_getfunc*, int); extern void ethernet_close (struct netdriverdata *ndd, void*); -extern void ethernet_gotdata (struct s2devstruct *dev, const uae_u8 *data, int len); -extern int ethernet_getdata (struct s2devstruct *dev, uae_u8 *d, int *len); extern void ethernet_trigger (struct netdriverdata *ndd, void*); -extern bool slirp_start (void); -extern void slirp_end (void); - -#endif // _UAE_ETHERNET_H_ +#endif /* UAE_ETHERNET_H */ diff --git a/include/uae/slirp.h b/include/uae/slirp.h new file mode 100644 index 00000000..bf040389 --- /dev/null +++ b/include/uae/slirp.h @@ -0,0 +1,23 @@ +#ifndef UAE_SLIRP_H +#define UAE_SLIRP_H + +#include "uae/types.h" + +#ifdef _WIN32 +#else +#include +#include +#include +#endif + +int uae_slirp_init(void); +void uae_slirp_cleanup(void); +int uae_slirp_redir(int is_udp, int host_port, struct in_addr guest_addr, + int guest_port); +bool uae_slirp_start (void); +void uae_slirp_end (void); +void uae_slirp_input(const uint8_t *pkt, int pkt_len); + +void slirp_output(const uint8_t *pkt, int pkt_len); + +#endif /* UAE_SLIRP_H */ diff --git a/od-win32/sysconfig.h b/od-win32/sysconfig.h index 8e66204b..fd8adea8 100644 --- a/od-win32/sysconfig.h +++ b/od-win32/sysconfig.h @@ -92,6 +92,7 @@ #define WITH_LUA /* lua scripting */ #define WITH_UAENATIVE #define WITH_SLIRP +#define WITH_BUILTIN_SLIRP #define WITH_TABLETLIBRARY #define WITH_UAENET_PCAP #define WITH_PPC diff --git a/od-win32/win32_uaenet.cpp b/od-win32/win32_uaenet.cpp index 2f528a54..e9762656 100644 --- a/od-win32/win32_uaenet.cpp +++ b/od-win32/win32_uaenet.cpp @@ -6,7 +6,11 @@ * Copyright 2007 Toni Wilen */ -#include "slirp/slirp.h" +#include "sysconfig.h" + +#ifdef WITH_SLIRP +#include "../slirp/slirp.h" +#endif #include @@ -432,66 +436,3 @@ void uaenet_close_driver (struct netdriverdata *tc) tc[i].active = 0; } } - - -static volatile int slirp_thread_active; -static HANDLE slirp_thread; -static uae_thread_id slirp_tid; -extern uae_sem_t slirp_sem2; - -static void *slirp_receive_func(void *arg) -{ - slirp_thread_active = 1; - while (slirp_thread_active) { - // Wait for packets to arrive - fd_set rfds, wfds, xfds; - SOCKET nfds; - int ret, timeout; - - // ... in the output queue - nfds = -1; - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_ZERO(&xfds); - uae_sem_wait (&slirp_sem2); - timeout = slirp_select_fill(&nfds, &rfds, &wfds, &xfds); - uae_sem_post (&slirp_sem2); - if (nfds < 0) { - /* Windows does not honour the timeout if there is not - descriptor to wait for */ - sleep_millis (timeout / 1000); - ret = 0; - } - else { - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = timeout; - ret = select(0, &rfds, &wfds, &xfds, &tv); - } - if (ret >= 0) { - uae_sem_wait (&slirp_sem2); - slirp_select_poll(&rfds, &wfds, &xfds); - uae_sem_post (&slirp_sem2); - } - } - slirp_thread_active = -1; - return 0; -} - -bool slirp_start (void) -{ - slirp_end (); - uae_start_thread_fast (slirp_receive_func, NULL, &slirp_tid); - return true; -} -void slirp_end (void) -{ - if (slirp_thread_active > 0) { - slirp_thread_active = 0; - while (slirp_thread_active == 0) { - sleep_millis (10); - } - uae_end_thread (&slirp_tid); - } - slirp_thread_active = 0; -} diff --git a/od-win32/winuae_msvc14/winuae_msvc.vcxproj b/od-win32/winuae_msvc14/winuae_msvc.vcxproj index 5a5b09fc..062320d0 100644 --- a/od-win32/winuae_msvc14/winuae_msvc.vcxproj +++ b/od-win32/winuae_msvc14/winuae_msvc.vcxproj @@ -870,6 +870,7 @@ + diff --git a/od-win32/winuae_msvc14/winuae_msvc.vcxproj.filters b/od-win32/winuae_msvc14/winuae_msvc.vcxproj.filters index b8d17d91..ae07b235 100644 --- a/od-win32/winuae_msvc14/winuae_msvc.vcxproj.filters +++ b/od-win32/winuae_msvc14/winuae_msvc.vcxproj.filters @@ -805,6 +805,9 @@ x86 + + slirp + diff --git a/slirp_uae.cpp b/slirp_uae.cpp new file mode 100644 index 00000000..7097c92a --- /dev/null +++ b/slirp_uae.cpp @@ -0,0 +1,226 @@ +#include "sysconfig.h" +#ifdef _WIN32 +#include "Winsock2.h" +#endif +#include "sysdeps.h" + +#ifdef WITH_SLIRP + +#include "options.h" +#include "uae/slirp.h" +#include "uae.h" + +#ifdef WITH_BUILTIN_SLIRP +#include "slirp/slirp.h" +#include "slirp/libslirp.h" +#include "threaddep/thread.h" +#endif + +#ifdef WITH_QEMU_SLIRP +#include "uae/dlopen.h" +#include "uae/ppc.h" +#include "uae/qemu.h" +#endif + +/* Implementation enumeration must correspond to slirp_implementations in + * cfgfile.cpp. */ +enum Implementation { + AUTO_IMPLEMENTATION = 0, + NO_IMPLEMENTATION, + BUILTIN_IMPLEMENTATION, + QEMU_IMPLEMENTATION, +}; + +static Implementation impl; + +static Implementation check_conf(Implementation check) +{ + int conf = AUTO_IMPLEMENTATION; + if (conf == AUTO_IMPLEMENTATION || conf == check) { + return check; + } + return AUTO_IMPLEMENTATION; +} + +int uae_slirp_init(void) +{ +#if defined(WITH_QEMU_SLIRP) + if (impl == AUTO_IMPLEMENTATION) { + impl = check_conf(QEMU_IMPLEMENTATION); + } +#endif +#if defined(WITH_BUILTIN_SLIRP) + if (impl == AUTO_IMPLEMENTATION) { + impl = check_conf(BUILTIN_IMPLEMENTATION); + } +#endif + if (impl == AUTO_IMPLEMENTATION) { + impl = NO_IMPLEMENTATION; + } + +#ifdef WITH_QEMU_SLIRP + if (impl == QEMU_IMPLEMENTATION) { + return uae_qemu_uae_init() == NULL; + } +#endif +#ifdef WITH_BUILTIN_SLIRP + if (impl == BUILTIN_IMPLEMENTATION) { + return slirp_init(); + } +#endif + return -1; +} + +void uae_slirp_cleanup(void) +{ +#ifdef WITH_QEMU_SLIRP + if (impl == QEMU_IMPLEMENTATION) { + UAE_LOG_STUB(""); + return; + } +#endif +#ifdef WITH_BUILTIN_SLIRP + if (impl == BUILTIN_IMPLEMENTATION) { + slirp_cleanup(); + return; + } +#endif +} + +void uae_slirp_input(const uint8_t *pkt, int pkt_len) +{ +#ifdef WITH_QEMU_SLIRP + if (impl == QEMU_IMPLEMENTATION) { + if (qemu_uae_slirp_input) { + qemu_uae_slirp_input(pkt, pkt_len); + } + return; + } +#endif +#ifdef WITH_BUILTIN_SLIRP + if (impl == BUILTIN_IMPLEMENTATION) { + slirp_input(pkt, pkt_len); + return; + } +#endif +} + +void uae_slirp_output(const uint8_t *pkt, int pkt_len) +{ +#if 0 + write_log(_T("uae_slirp_output pkt_len %d\n"), pkt_len); +#endif + slirp_output(pkt, pkt_len); +} + +int uae_slirp_redir(int is_udp, int host_port, struct in_addr guest_addr, + int guest_port) +{ +#ifdef WITH_QEMU_SLIRP + if (impl == QEMU_IMPLEMENTATION) { + UAE_LOG_STUB(""); + return 0; + } +#endif +#ifdef WITH_BUILTIN_SLIRP + if (impl == BUILTIN_IMPLEMENTATION) { + return slirp_redir(is_udp, host_port, guest_addr, guest_port); + } +#endif + return 0; +} + +#ifdef WITH_BUILTIN_SLIRP + +static volatile int slirp_thread_active; +static uae_thread_id slirp_tid; +extern uae_sem_t slirp_sem2; + +static void *slirp_receive_func(void *arg) +{ + slirp_thread_active = 1; + while (slirp_thread_active) { + // Wait for packets to arrive + fd_set rfds, wfds, xfds; + SOCKET nfds; + int ret, timeout; + + // ... in the output queue + nfds = -1; + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&xfds); + uae_sem_wait (&slirp_sem2); + timeout = slirp_select_fill(&nfds, &rfds, &wfds, &xfds); + uae_sem_post (&slirp_sem2); + if (nfds < 0) { + /* Windows does not honour the timeout if there is not + descriptor to wait for */ + sleep_millis (timeout / 1000); + ret = 0; + } else { + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = timeout; + ret = select(0, &rfds, &wfds, &xfds, &tv); + } + if (ret >= 0) { + uae_sem_wait (&slirp_sem2); + slirp_select_poll(&rfds, &wfds, &xfds); + uae_sem_post (&slirp_sem2); + } + } + slirp_thread_active = -1; + return 0; +} + +int slirp_can_output(void) +{ + return 1; +} + +#endif + +bool uae_slirp_start (void) +{ +#ifdef WITH_QEMU_SLIRP + if (impl == QEMU_IMPLEMENTATION) { + UAE_LOG_STUB(""); + return true; + } +#endif +#ifdef WITH_BUILTIN_SLIRP + if (impl == BUILTIN_IMPLEMENTATION) { + uae_slirp_end (); + uae_start_thread(_T("slirp-receive"), slirp_receive_func, NULL, + &slirp_tid); + return true; + } +#endif + return false; +} + +void uae_slirp_end (void) +{ +#ifdef WITH_QEMU_SLIRP + if (impl == QEMU_IMPLEMENTATION) { + UAE_LOG_STUB(""); + return; + } +#endif +#ifdef WITH_BUILTIN_SLIRP + if (impl == BUILTIN_IMPLEMENTATION) { + if (slirp_thread_active > 0) { + slirp_thread_active = 0; + while (slirp_thread_active == 0) { + sleep_millis (10); + } + uae_end_thread (&slirp_tid); + } + slirp_thread_active = 0; + return; + } +#endif +} + +#endif /* WITH_SLIRP */ -- 2.47.3