Commit a1c18398 authored by Rinnegatamante's avatar Rinnegatamante
Browse files

Added network game support.

parent 07950202
......@@ -109,10 +109,14 @@ ifneq ($(STATIC_LINKING),1)
$(CORE_DIR)/libretro-common/compat/compat_strl.c \
$(CORE_DIR)/libretro-common/compat/compat_posix_string.c \
$(CORE_DIR)/libretro-common/compat/compat_strcasestr.c \
$(CORE_DIR)/libretro-common/compat/compat_snprintf.c
$(CORE_DIR)/libretro-common/compat/compat_snprintf.c \
$(CORE_DIR)/libretro-common/net/net_compat.c \
$(CORE_DIR)/libretro-common/net/net_socket.c
endif
SOURCES_C += $(CORE_DIR)/common/net_none.c
SOURCES_C += $(CORE_DIR)/common/net_dgrm.c \
$(CORE_DIR)/common/net_udp.c \
$(CORE_DIR)/common/net_bsd.c
ifeq ($(USE_CODEC_FLAC),1)
INCFLAGS += -I$(LIBFLAC_DIR)/include
......
......@@ -114,7 +114,7 @@ enum m_state_enum {
m_search, m_slist
};
static int m_state;
int m_state;
#include "libretro.h"
extern retro_environment_t environ_cb;
......
......@@ -18,6 +18,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
extern int m_state;
#if defined(_WIN32)
#include <winsock2.h>
#include <windows.h>
......
......@@ -436,7 +436,9 @@ NET_Connect(const char *host)
qsocket_t *ret;
int i, n;
int numdrivers = net_numdrivers;
printf("Attempting to connect to %s\n", host);
SetNetTime();
if (host && *host == 0)
......
......@@ -19,15 +19,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <unistd.h>
#include <net/if.h>
#include <net/net_compat.h>
#include <net/net_socket.h>
#include "common.h"
#include "console.h"
......@@ -55,10 +51,14 @@ static netadr_t broadcastaddr;
* to only listen on a particular address. Set on the
* command line using the "-ip" option.
*/
#ifndef IF_NAMESIZE
#define IF_NAMESIZE 16
#define MAXHOSTNAMELEN 64
#endif
static netadr_t myAddr;
static netadr_t localAddr;
static netadr_t bindAddr;
static char ifname[IFNAMSIZ];
static char ifname[IF_NAMESIZE];
static void
......@@ -78,44 +78,6 @@ SockadrToNetadr(const struct sockaddr_in *s, netadr_t *a)
a->port = s->sin_port;
}
static int
udp_scan_iface(int sock)
{
struct ifconf ifc;
struct ifreq *ifr;
char buf[8192];
int i, n;
struct sockaddr_in *iaddr;
if (COM_CheckParm("-noifscan"))
return -1;
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) {
Con_Printf("%s: SIOCGIFCONF failed\n", __func__);
return -1;
}
ifr = ifc.ifc_req;
n = ifc.ifc_len / sizeof(struct ifreq);
for (i = 0; i < n; i++) {
if (ioctl(sock, SIOCGIFADDR, &ifr[i]) == -1)
continue;
iaddr = (struct sockaddr_in *)&ifr[i].ifr_addr;
Con_DPrintf("%s: %s\n", ifr[i].ifr_name, inet_ntoa(iaddr->sin_addr));
if (iaddr->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
SockadrToNetadr(iaddr, &myAddr);
strcpy (ifname, ifr[i].ifr_name);
return 0;
}
}
return -1;
}
int
UDP_Init(void)
{
......@@ -128,7 +90,9 @@ UDP_Init(void)
if (COM_CheckParm("-noudp"))
return -1;
network_init();
/* determine my name & address, default to loopback */
myAddr.ip.l = htonl(INADDR_LOOPBACK);
myAddr.port = htons(DEFAULTnet_hostport);
......@@ -140,8 +104,7 @@ UDP_Init(void)
buff[MAXHOSTNAMELEN - 1] = 0;
local = gethostbyname(buff);
if (!local) {
Con_Printf("%s: WARNING: gethostbyname failed (%s)\n", __func__,
hstrerror(h_errno));
Con_Printf("%s: WARNING: gethostbyname failed\n", __func__);
} else if (local->h_addrtype != AF_INET) {
Con_Printf("%s: address from gethostbyname not IPv4\n", __func__);
} else {
......@@ -182,11 +145,6 @@ UDP_Init(void)
/* myAddr may resolve to 127.0.0.1, see if we can do any better */
memset (ifname, 0, sizeof(ifname));
if (myAddr.ip.l == htonl(INADDR_LOOPBACK)) {
if (udp_scan_iface(net_controlsocket) == 0)
Con_Printf ("UDP, Local address: %s (%s)\n",
NET_AdrToString(&myAddr), ifname);
}
if (ifname[0] == 0) {
Con_Printf ("UDP, Local address: %s\n", NET_AdrToString(&myAddr));
}
......@@ -243,8 +201,7 @@ UDP_OpenSocket(int port)
if ((newsocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
return -1;
if (ioctl(newsocket, FIONBIO, &_true) == -1)
goto ErrorReturn;
socket_nonblock(newsocket);
address.sin_family = AF_INET;
if (bindAddr.ip.l != INADDR_NONE)
......@@ -283,12 +240,9 @@ UDP_CheckNewConnections(void)
if (net_acceptsocket == -1)
return -1;
if (ioctl(net_acceptsocket, FIONREAD, &available) == -1)
Sys_Error("%s: ioctlsocket (FIONREAD) failed", __func__);
if (available)
return net_acceptsocket;
/* quietly absorb empty packets */
recvfrom (net_acceptsocket, buff, 0, 0, (struct sockaddr *)&from, &fromlen);
if (recvfrom (net_acceptsocket, buff, 0, 0, (struct sockaddr *)&from, &fromlen) >= 0)
return net_acceptsocket;
return -1;
}
......@@ -302,7 +256,7 @@ UDP_Read(int socket, void *buf, int len, netadr_t *addr)
ret = recvfrom(socket, buf, len, 0, (struct sockaddr *)&saddr, &addrlen);
SockadrToNetadr(&saddr, addr);
if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED))
if (isagain(ret))
return 0;
return ret;
}
......@@ -349,7 +303,7 @@ UDP_Write(int socket, const void *buf, int len, const netadr_t *addr)
NetadrToSockadr(addr, &saddr);
ret = sendto(socket, buf, len, 0, (struct sockaddr *)&saddr, sizeof(saddr));
if (ret == -1 && errno == EWOULDBLOCK)
if (isagain(ret))
return 0;
return ret;
}
......
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (net_compat.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef LIBRETRO_SDK_NETPLAY_COMPAT_H__
#define LIBRETRO_SDK_NETPLAY_COMPAT_H__
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <boolean.h>
#include <retro_inline.h>
#include <stdint.h>
#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>
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
#elif defined(_XBOX)
#define NOD3D
#include <xtl.h>
#include <io.h>
#elif defined(GEKKO)
#include <network.h>
#elif defined(VITA)
#include <psp2/net/net.h>
#include <psp2/net/netctl.h>
#define sockaddr_in SceNetSockaddrIn
#define sockaddr SceNetSockaddr
#define sendto sceNetSendto
#define recvfrom sceNetRecvfrom
#define socket(a,b,c) sceNetSocket("unknown",a,b,c)
#define bind sceNetBind
#define accept sceNetAccept
#define setsockopt sceNetSetsockopt
#define connect sceNetConnect
#define listen sceNetListen
#define send sceNetSend
#define recv sceNetRecv
#define MSG_DONTWAIT SCE_NET_MSG_DONTWAIT
#define AF_INET SCE_NET_AF_INET
#define AF_UNSPEC 0
#define INADDR_ANY SCE_NET_INADDR_ANY
#define INADDR_NONE 0xffffffff
#define SOCK_STREAM SCE_NET_SOCK_STREAM
#define SOCK_DGRAM SCE_NET_SOCK_DGRAM
#define SOL_SOCKET SCE_NET_SOL_SOCKET
#define SO_REUSEADDR SCE_NET_SO_REUSEADDR
#define SO_SNDBUF SCE_NET_SO_SNDBUF
#define SO_SNDTIMEO SCE_NET_SO_SNDTIMEO
#define SO_NBIO SCE_NET_SO_NBIO
#define htonl sceNetHtonl
#define ntohl sceNetNtohl
#define htons sceNetHtons
#define socklen_t unsigned int
struct hostent
{
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
char *h_addr;
};
struct SceNetInAddr inet_aton(const char *ip_addr);
#else
#include <sys/select.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#ifndef __PSL1GHT__
#include <netinet/tcp.h>
#endif
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
#include <cell/sysmodule.h>
#include <netex/net.h>
#include <netex/libnetctl.h>
#include <sys/timer.h>
#ifndef EWOULDBLOCK
#define EWOULDBLOCK SYS_NET_EWOULDBLOCK
#endif
#else
#include <signal.h>
#endif
#endif
#include <errno.h>
#ifdef GEKKO
#define sendto(s, msg, len, flags, addr, tolen) net_sendto(s, msg, len, 0, addr, 8)
#define socket(domain, type, protocol) net_socket(domain, type, protocol)
#define bind(s, name, namelen) net_bind(s, name, namelen)
#define listen(s, backlog) net_listen(s, backlog)
#define accept(s, addr, addrlen) net_accept(s, addr, addrlen)
#define connect(s, addr, addrlen) net_connect(s, addr, addrlen)
#define send(s, data, size, flags) net_send(s, data, size, flags)
#define recv(s, mem, len, flags) net_recv(s, mem, len, flags)
#define recvfrom(s, mem, len, flags, from, fromlen) net_recvfrom(s, mem, len, flags, from, fromlen)
#define select(maxfdp1, readset, writeset, exceptset, timeout) net_select(maxfdp1, readset, writeset, exceptset, timeout)
#endif
static INLINE bool isagain(int bytes)
{
#if defined(_WIN32)
if (bytes != SOCKET_ERROR)
return false;
if (WSAGetLastError() != WSAEWOULDBLOCK)
return false;
return true;
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
return (sys_net_errno == SYS_NET_EWOULDBLOCK) || (sys_net_errno == SYS_NET_EAGAIN);//35
#elif defined(VITA)
return (bytes<0 && (bytes == SCE_NET_ERROR_EAGAIN || bytes == SCE_NET_ERROR_EWOULDBLOCK));
#elif defined(WIIU)
return (bytes == -1) && ((socketlasterr() == SO_SUCCESS) || (socketlasterr() == SO_EWOULDBLOCK));
#else
return (bytes < 0 && (errno == EAGAIN || errno == EWOULDBLOCK));
#endif
}
#ifdef _XBOX
#define socklen_t int
#ifndef h_addr
#define h_addr h_addr_list[0] /* for backward compatibility */
#endif
#ifndef SO_KEEPALIVE
#define SO_KEEPALIVE 0 /* verify if correct */
#endif
#endif
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
#ifndef _WIN32
#include <sys/time.h>
#include <unistd.h>
#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_retro__
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;
};
#ifndef AI_PASSIVE
#define AI_PASSIVE 1
#endif
/* gai_strerror() not used, so we skip that. */
#endif
uint16_t inet_htons(uint16_t hostshort);
int inet_ptrton(int af, const char *src, void *dst);
int getaddrinfo_retro(const char *node, const char *service,
struct addrinfo *hints, struct addrinfo **res);
void freeaddrinfo_retro(struct addrinfo *res);
/**
* network_init:
*
* Platform specific socket library initialization.
*
* Returns: true (1) if successful, otherwise false (0).
**/
bool network_init(void);
/**
* network_deinit:
*
* Deinitialize platform specific socket libraries.
**/
void network_deinit(void);
const char *inet_ntop_compat(int af, const void *src, char *dst, socklen_t cnt);
bool udp_send_packet(const char *host, uint16_t port, const char *msg);
#endif
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (net_socket.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _LIBRETRO_SDK_NET_SOCKET_H
#define _LIBRETRO_SDK_NET_SOCKET_H
#include <stdint.h>
#include <boolean.h>
#include <string.h>
#include <retro_common_api.h>
RETRO_BEGIN_DECLS
enum socket_domain
{
SOCKET_DOMAIN_INET = 0
};
enum socket_type
{
SOCKET_TYPE_DATAGRAM = 0,
SOCKET_TYPE_STREAM,
SOCKET_TYPE_SEQPACKET
};
enum socket_protocol
{
SOCKET_PROTOCOL_NONE = 0,
SOCKET_PROTOCOL_TCP,
SOCKET_PROTOCOL_UDP
};
typedef struct socket_target
{
unsigned port;
const char *server;
enum socket_domain domain;
enum socket_protocol prot;
} socket_target_t;
int socket_init(void **address, uint16_t port, const char *server, enum socket_type type);
int socket_next(void **address);
int socket_close(int fd);
bool socket_nonblock(int fd);
int socket_select(int nfds, fd_set *readfs, fd_set *writefds,
fd_set *errorfds, struct timeval *timeout);
int socket_send_all_blocking(int fd, const void *data_, size_t size, bool no_signal);
ssize_t socket_send_all_nonblocking(int fd, const void *data_, size_t size,
bool no_signal);
int socket_receive_all_blocking(int fd, void *data_, size_t size);
ssize_t socket_receive_all_nonblocking(int fd, bool *error,
void *data_, size_t size);
bool socket_bind(int fd, void *data);
int socket_connect(int fd, void *data, bool timeout_enable);
int socket_create(
const char *name,
enum socket_domain domain_type,
enum socket_type socket_type,
enum socket_protocol protocol_type);
void socket_set_target(void *data, socket_target_t *in_addr);
RETRO_END_DECLS
#endif
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (net_compat.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <net/net_compat.h>
#include <net/net_socket.h>
#include <retro_timers.h>
#include <compat/strl.h>
#if defined(_XBOX)
/* TODO - implement h_length and h_addrtype */
struct hostent
{
int h_addrtype; /* host address type */
int h_length; /* length of addresses */
char **h_addr_list; /* list of addresses */
};
struct hostent *gethostbyname(const char *name)
{
WSAEVENT event;
static struct hostent he;
static struct in_addr addr;
static char *addr_ptr = NULL;
XNDNS *dns = NULL;
he.h_addr_list = &addr_ptr;
addr_ptr = (char*)&addr;
if (!name)
return NULL;
event = WSACreateEvent();
XNetDnsLookup(name, event, &dns);
if (!dns)
goto error;
WaitForSingleObject((HANDLE)event, INFINITE);
if (dns->iStatus)
goto error;
memcpy(&addr, dns->aina, sizeof(addr));
WSACloseEvent(event);
XNetDnsRelease(dns);
return &he;
error:
if (event)
WSACloseEvent(event);
return NULL;
}
#elif defined(VITA)
static void *_net_compat_net_memory = NULL;
#define COMPAT_NET_INIT_SIZE 512*1024
#define INET_ADDRSTRLEN sizeof(struct sockaddr_in)