Start adding netplay compat layer for legacy stuff.

This commit is contained in:
Themaister 2012-01-24 21:00:30 +01:00
parent e6f2aa81f7
commit 03a892c7f2
5 changed files with 231 additions and 21 deletions

View File

@ -38,6 +38,9 @@ endif
ifeq ($(HAVE_NETPLAY), 1)
OBJ += netplay.o
ifeq ($(HAVE_SOCKET_LEGACY), 1)
OBJ += netplay_compat.o
endif
endif
ifeq ($(HAVE_RSOUND), 1)

View File

@ -33,8 +33,10 @@
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#ifndef SSNES_CONSOLE
#include <signal.h>
#endif
#endif
#include "netplay.h"
#include "general.h"
@ -44,6 +46,8 @@
#include <stdlib.h>
#include <string.h>
#include "netplay_compat.h"
// Checks if input port/index is controlled by netplay or not.
static bool netplay_is_alive(netplay_t *handle);
@ -59,18 +63,6 @@ static void netplay_set_spectate_input(netplay_t *handle, int16_t input);
static bool netplay_send_cmd(netplay_t *handle, uint32_t cmd, const void *data, size_t size);
static bool netplay_get_cmd(netplay_t *handle);
#ifdef _WIN32
// Woohoo, Winsock has headers from the STONE AGE! :D
#define close(x) closesocket(x)
#define CONST_CAST (const char*)
#define NONCONST_CAST (char*)
#else
#define CONST_CAST
#define NONCONST_CAST
#include <sys/time.h>
#include <unistd.h>
#endif
#define PREV_PTR(x) ((x) == 0 ? handle->buffer_size - 1 : (x) - 1)
#define NEXT_PTR(x) ((x + 1) % handle->buffer_size)
@ -218,13 +210,17 @@ static void log_connection(const struct sockaddr_storage *their_addr,
{
const struct sockaddr_storage *storage;
const struct sockaddr_in *v4;
#ifndef HAVE_SOCKET_LEGACY
const struct sockaddr_in6 *v6;
#endif
} u;
u.storage = their_addr;
const char *str = NULL;
char buf_v4[INET_ADDRSTRLEN] = {0};
#ifndef HAVE_SOCKET_LEGACY
char buf_v6[INET6_ADDRSTRLEN] = {0};
#endif
if (their_addr->ss_family == AF_INET)
{
@ -237,6 +233,7 @@ static void log_connection(const struct sockaddr_storage *their_addr,
getnameinfo((struct sockaddr*)&in, sizeof(struct sockaddr_in), buf_v4, sizeof(buf_v4),
NULL, 0, NI_NUMERICHOST);
}
#ifndef HAVE_SOCKET_LEGACY
else if (their_addr->ss_family == AF_INET6)
{
str = buf_v6;
@ -248,6 +245,7 @@ static void log_connection(const struct sockaddr_storage *their_addr,
getnameinfo((struct sockaddr*)&in, sizeof(struct sockaddr_in6),
buf_v6, sizeof(buf_v6), NULL, 0, NI_NUMERICHOST);
}
#endif
if (str)
{
@ -262,7 +260,7 @@ static bool init_tcp_socket(netplay_t *handle, const char *server, uint16_t port
{
struct addrinfo hints, *res = NULL;
memset(&hints, 0, sizeof(hints));
#ifdef _WIN32 // Lolol, no AF_UNSPEC, wtf.
#if defined(_WIN32) || defined(HAVE_SOCKET_LEGACY)
hints.ai_family = AF_INET;
#else
hints.ai_family = AF_UNSPEC;
@ -354,7 +352,7 @@ static bool init_udp_socket(netplay_t *handle, const char *server, uint16_t port
{
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
#ifdef _WIN32 // Lolol, no AF_UNSPEC, wtf.
#if defined(_WIN32) || defined(HAVE_SOCKET_LEGACY)
hints.ai_family = AF_INET;
#else
hints.ai_family = AF_UNSPEC;
@ -398,8 +396,13 @@ static bool init_udp_socket(netplay_t *handle, const char *server, uint16_t port
return true;
}
static bool init_socket(netplay_t *handle, const char *server, uint16_t port)
// Platform specific socket library init.
static bool init_network(void)
{
static bool inited = false;
if (inited)
return true;
#ifdef _WIN32
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
@ -411,13 +414,20 @@ static bool init_socket(netplay_t *handle, const char *server, uint16_t port)
signal(SIGPIPE, SIG_IGN); // Do not like SIGPIPE killing our app :(
#endif
inited = true;
return true;
}
static bool init_socket(netplay_t *handle, const char *server, uint16_t port)
{
if (!init_network())
return false;
if (!init_tcp_socket(handle, server, port, handle->spectate))
return false;
if (!handle->spectate)
{
if (!init_udp_socket(handle, server, port))
return false;
}
if (!handle->spectate && !init_udp_socket(handle, server, port))
return false;
return true;
}

103
netplay_compat.c Normal file
View File

@ -0,0 +1,103 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "netplay_compat.h"
#undef getaddrinfo
#undef freeaddrinfo
#undef sockaddr_storage
#undef addrinfo
#if defined(_WIN32) && !defined(_XBOX)
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#elif defined(_XBOX)
#include <Xtl.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define addrinfo addrinfo_ssnes__
int getaddrinfo_ssnes__(const char *node, const char *service,
const struct addrinfo *hints,
struct addrinfo **res)
{
struct addrinfo *info = (struct addrinfo*)calloc(1, sizeof(*info));
if (!info)
return -1;
info->ai_family = PF_INET;
info->ai_socktype = hints->ai_socktype;
struct sockaddr_in *in_addr = calloc(1, sizeof(*in_addr));
if (!in_addr)
{
free(info);
return -1;
}
info->ai_addrlen = sizeof(*in_addr);
in_addr->sin_family = AF_INET;
in_addr->sin_port = htons(strtoul(service, NULL, 0));
if (!node && (hints->ai_flags & AI_PASSIVE))
in_addr->sin_addr.s_addr = INADDR_ANY;
else if (node && isdigit(*node))
in_addr->sin_addr.s_addr = inet_addr(node);
else if (node && !isdigit(*node))
{
struct hostent *host = gethostbyname(node);
if (!host || !host->h_addr_list[0])
goto error;
in_addr->sin_addr.s_addr = inet_addr(host->h_addr_list[0]);
}
else
goto error;
info->ai_addr = (struct sockaddr*)in_addr;
*res = info;
return 0;
error:
free(in_addr);
free(info);
return -1;
}
void freeaddrinfo_ssnes__(struct addrinfo *res)
{
free(res->ai_addr);
free(res);
}

83
netplay_compat.h Normal file
View File

@ -0,0 +1,83 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETPLAY_COMPAT_H__
#define NETPLAY_COMPAT_H__
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(_WIN32)
// Woohoo, Winsock has headers from the STONE AGE! :D
#define close(x) closesocket(x)
#define CONST_CAST (const char*)
#define NONCONST_CAST (char*)
#else
#define CONST_CAST
#define NONCONST_CAST
#include <sys/time.h>
#include <unistd.h>
#if defined(__CELLOS_LV2__)
#define close(x) socketclose(x)
#endif
#endif
// Compatibility layer for legacy or incomplete BSD socket implementations.
// Only for IPv4. Mostly useful for the consoles which do not support
// anything reasonably modern on the socket API side of things.
#ifdef HAVE_SOCKET_LEGACY
#define sockaddr_storage sockaddr_in
#define addrinfo addrinfo_ssnes__
#define getaddrinfo(serv, port, hints, res) getaddrinfo_ssnes__(serv, port, hints, res)
#define freeaddrinfo(res) freeaddrinfo_ssnes__(res)
struct addrinfo
{
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
int getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints,
struct addrinfo **res);
void freeaddrinfo(struct addrinfo *res);
#ifndef AI_PASSIVE
#define AI_PASSIVE 1
#endif
#define ss_family sin_family
// gai_strerror() not used, so we skip that.
#endif
#endif

View File

@ -33,7 +33,18 @@ fi
check_lib THREADS -lpthread pthread_create
check_lib DYLIB $DYLIB dlopen
check_lib NETPLAY -lc socket
if [ $HAVE_NETPLAY = yes ]; then
HAVE_GETADDRINFO=auto
check_lib GETADDRINFO -lc getaddrinfo
if [ $HAVE_GETADDRINFO = yes ]; then
HAVE_SOCKET_LEGACY=no
else
HAVE_SOCKET_LEGACY=yes
fi
fi
check_lib GETOPT_LONG -lc getopt_long
if [ $HAVE_DYLIB = no ] && [ $HAVE_DYNAMIC = yes ]; then
@ -124,7 +135,7 @@ check_pkgconf PYTHON python3
add_define_make OS $OS
# Creates config.mk and config.h.
VARS="ALSA OSS OSS_BSD OSS_LIB AL RSOUND ROAR JACK COREAUDIO PULSE SDL OPENGL DYLIB GETOPT_LONG THREADS CG XML SDL_IMAGE DYNAMIC FFMPEG AVCODEC AVFORMAT AVUTIL SWSCALE CONFIGFILE FREETYPE XVIDEO X11 XEXT NETPLAY FBO STRL PYTHON FFMPEG_ALLOC_CONTEXT3 FFMPEG_AVCODEC_OPEN2 FFMPEG_AVIO_OPEN FFMPEG_AVFORMAT_WRITE_HEADER FFMPEG_AVFORMAT_NEW_STREAM X264RGB"
VARS="ALSA OSS OSS_BSD OSS_LIB AL RSOUND ROAR JACK COREAUDIO PULSE SDL OPENGL DYLIB GETOPT_LONG THREADS CG XML SDL_IMAGE DYNAMIC FFMPEG AVCODEC AVFORMAT AVUTIL SWSCALE CONFIGFILE FREETYPE XVIDEO X11 XEXT NETPLAY SOCKET_LEGACY FBO STRL PYTHON FFMPEG_ALLOC_CONTEXT3 FFMPEG_AVCODEC_OPEN2 FFMPEG_AVIO_OPEN FFMPEG_AVFORMAT_WRITE_HEADER FFMPEG_AVFORMAT_NEW_STREAM X264RGB"
create_config_make config.mk $VARS
create_config_header config.h $VARS