2005-07-24 16:12:37 +02:00
|
|
|
/* $Id$ */
|
|
|
|
|
2009-08-21 22:21:05 +02:00
|
|
|
/*
|
|
|
|
* This file is part of OpenTTD.
|
|
|
|
* OpenTTD 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 Foundation, version 2.
|
|
|
|
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2007-01-02 18:34:03 +01:00
|
|
|
/**
|
|
|
|
* @file os_abstraction.h Network stuff has many things that needs to be
|
|
|
|
* included and/or implemented by default.
|
|
|
|
* All those things are in this file.
|
|
|
|
*/
|
2004-12-04 18:54:56 +01:00
|
|
|
|
2007-02-23 09:37:33 +01:00
|
|
|
#ifndef NETWORK_CORE_OS_ABSTRACTION_H
|
|
|
|
#define NETWORK_CORE_OS_ABSTRACTION_H
|
|
|
|
|
2007-01-02 18:34:03 +01:00
|
|
|
/* Include standard stuff per OS */
|
2004-12-04 18:54:56 +01:00
|
|
|
|
2005-05-15 01:48:39 +02:00
|
|
|
#ifdef ENABLE_NETWORK
|
|
|
|
|
2007-01-02 18:34:03 +01:00
|
|
|
/* Windows stuff */
|
2018-12-09 02:28:14 +01:00
|
|
|
#if defined(_WIN32)
|
2010-06-28 20:14:00 +02:00
|
|
|
#include <errno.h>
|
2004-12-23 23:31:46 +01:00
|
|
|
#include <winsock2.h>
|
|
|
|
#include <ws2tcpip.h>
|
2005-10-03 00:39:56 +02:00
|
|
|
#include <windows.h>
|
2004-12-23 21:23:05 +01:00
|
|
|
|
2009-04-03 16:01:45 +02:00
|
|
|
#define GET_LAST_ERROR() WSAGetLastError()
|
2010-06-28 20:14:00 +02:00
|
|
|
#undef EWOULDBLOCK
|
2009-04-03 16:01:45 +02:00
|
|
|
#define EWOULDBLOCK WSAEWOULDBLOCK
|
|
|
|
/* Windows has some different names for some types */
|
|
|
|
typedef unsigned long in_addr_t;
|
|
|
|
|
2005-03-14 20:27:19 +01:00
|
|
|
#if !(defined(__MINGW32__) || defined(__CYGWIN__))
|
2007-01-02 18:34:03 +01:00
|
|
|
/* Windows has some different names for some types */
|
2004-12-23 23:31:46 +01:00
|
|
|
typedef SSIZE_T ssize_t;
|
2005-02-07 21:36:41 +01:00
|
|
|
typedef int socklen_t;
|
2009-04-04 01:44:31 +02:00
|
|
|
# define IPPROTO_IPV6 41
|
2009-04-03 01:22:59 +02:00
|
|
|
#else
|
2009-09-01 16:20:35 +02:00
|
|
|
#include "../../os/windows/win32.h"
|
2009-04-03 16:01:45 +02:00
|
|
|
#include "../../core/alloc_func.hpp"
|
|
|
|
|
2010-02-10 22:06:05 +01:00
|
|
|
#define AI_ADDRCONFIG 0x00000400 /* Resolution only if global address configured */
|
2009-04-04 01:44:31 +02:00
|
|
|
#define IPV6_V6ONLY 27
|
2009-04-03 01:22:59 +02:00
|
|
|
|
|
|
|
static inline int OTTDgetnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, DWORD hostlen, char *serv, DWORD servlen, int flags)
|
|
|
|
{
|
|
|
|
static int (WINAPI *getnameinfo)(const struct sockaddr *, socklen_t, char *, DWORD, char *, DWORD, int) = NULL;
|
|
|
|
static bool first_time = true;
|
|
|
|
|
|
|
|
if (first_time) {
|
|
|
|
LoadLibraryList((Function*)&getnameinfo, "ws2_32.dll\0getnameinfo\0\0");
|
|
|
|
first_time = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getnameinfo != NULL) return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
|
|
|
|
|
2012-10-04 17:25:57 +02:00
|
|
|
strncpy(host, inet_ntoa(((const struct sockaddr_in *)sa)->sin_addr), hostlen);
|
2009-04-03 01:22:59 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#define getnameinfo OTTDgetnameinfo
|
2004-12-23 23:31:46 +01:00
|
|
|
|
2009-04-03 16:01:45 +02:00
|
|
|
static inline int OTTDgetaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
|
|
|
|
{
|
|
|
|
static int (WINAPI *getaddrinfo)(const char *, const char *, const struct addrinfo *, struct addrinfo **) = NULL;
|
|
|
|
static bool first_time = true;
|
|
|
|
|
|
|
|
if (first_time) {
|
|
|
|
LoadLibraryList((Function*)&getaddrinfo, "ws2_32.dll\0getaddrinfo\0\0");
|
|
|
|
first_time = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getaddrinfo != NULL) return getaddrinfo(nodename, servname, hints, res);
|
|
|
|
|
|
|
|
*res = NULL;
|
|
|
|
|
|
|
|
in_addr_t ip = inet_addr(nodename);
|
|
|
|
if (ip == INADDR_NONE) {
|
|
|
|
struct hostent *he = gethostbyname(nodename);
|
|
|
|
if (he == NULL) return EAI_NONAME;
|
|
|
|
ip = (*(struct in_addr *)he->h_addr).s_addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sockaddr_in *sin = CallocT<struct sockaddr_in>(1);
|
|
|
|
sin->sin_family = AF_INET;
|
|
|
|
sin->sin_port = htons(strtoul(servname, NULL, 10));
|
|
|
|
sin->sin_addr.s_addr = ip;
|
|
|
|
|
|
|
|
struct addrinfo *ai = CallocT<struct addrinfo>(1);
|
|
|
|
ai->ai_family = PF_INET;
|
|
|
|
ai->ai_addr = (struct sockaddr*)sin;
|
|
|
|
ai->ai_addrlen = sizeof(*sin);
|
|
|
|
ai->ai_socktype = hints->ai_socktype;
|
|
|
|
|
|
|
|
*res = ai;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#define getaddrinfo OTTDgetaddrinfo
|
|
|
|
|
|
|
|
static inline void OTTDfreeaddrinfo(struct addrinfo *ai)
|
|
|
|
{
|
|
|
|
static int (WINAPI *freeaddrinfo)(struct addrinfo *) = NULL;
|
|
|
|
static bool first_time = true;
|
|
|
|
|
|
|
|
if (ai == NULL) return;
|
|
|
|
|
|
|
|
if (first_time) {
|
2009-04-13 00:13:05 +02:00
|
|
|
LoadLibraryList((Function*)&freeaddrinfo, "ws2_32.dll\0freeaddrinfo\0\0");
|
2009-04-03 16:01:45 +02:00
|
|
|
first_time = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (freeaddrinfo != NULL) {
|
|
|
|
freeaddrinfo(ai);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
struct addrinfo *next = ai->ai_next;
|
|
|
|
free(ai->ai_addr);
|
|
|
|
free(ai);
|
|
|
|
ai = next;
|
2009-08-14 19:11:59 +02:00
|
|
|
} while (ai != NULL);
|
2009-04-03 16:01:45 +02:00
|
|
|
}
|
|
|
|
#define freeaddrinfo OTTDfreeaddrinfo
|
|
|
|
#endif /* __MINGW32__ && __CYGWIN__ */
|
2018-12-09 02:28:14 +01:00
|
|
|
#endif /* _WIN32 */
|
2004-12-04 18:54:56 +01:00
|
|
|
|
2007-01-02 18:34:03 +01:00
|
|
|
/* UNIX stuff */
|
2007-01-05 19:03:30 +01:00
|
|
|
#if defined(UNIX) && !defined(__OS2__)
|
2010-05-10 19:11:24 +02:00
|
|
|
# if defined(OPENBSD) || defined(__NetBSD__)
|
2010-01-16 23:01:33 +01:00
|
|
|
# define AI_ADDRCONFIG 0
|
|
|
|
# endif
|
2004-12-04 18:54:56 +01:00
|
|
|
# define SOCKET int
|
|
|
|
# define INVALID_SOCKET -1
|
|
|
|
# if !defined(__MORPHOS__) && !defined(__AMIGA__)
|
|
|
|
# define ioctlsocket ioctl
|
|
|
|
# if !defined(BEOS_NET_SERVER)
|
|
|
|
# define closesocket close
|
|
|
|
# endif
|
|
|
|
# define GET_LAST_ERROR() (errno)
|
|
|
|
# endif
|
2007-01-02 18:34:03 +01:00
|
|
|
/* Need this for FIONREAD on solaris */
|
2004-12-04 18:54:56 +01:00
|
|
|
# define BSD_COMP
|
|
|
|
|
2007-01-02 18:34:03 +01:00
|
|
|
/* Includes needed for UNIX-like systems */
|
2004-12-04 18:54:56 +01:00
|
|
|
# include <unistd.h>
|
|
|
|
# include <sys/ioctl.h>
|
|
|
|
# if defined(__BEOS__) && defined(BEOS_NET_SERVER)
|
|
|
|
# include <be/net/socket.h>
|
2009-03-15 01:32:18 +01:00
|
|
|
# include <be/kernel/OS.h> /* snooze() */
|
2004-12-04 18:54:56 +01:00
|
|
|
# include <be/net/netdb.h>
|
|
|
|
typedef unsigned long in_addr_t;
|
|
|
|
# define INADDR_NONE INADDR_BROADCAST
|
|
|
|
# else
|
|
|
|
# include <sys/socket.h>
|
|
|
|
# include <netinet/in.h>
|
|
|
|
# include <netinet/tcp.h>
|
|
|
|
# include <arpa/inet.h>
|
|
|
|
# include <net/if.h>
|
2007-01-02 18:34:03 +01:00
|
|
|
/* According to glibc/NEWS, <ifaddrs.h> appeared in glibc-2.3. */
|
2009-09-21 20:36:33 +02:00
|
|
|
# if !defined(__sgi__) && !defined(SUNOS) && !defined(__MORPHOS__) && !defined(__BEOS__) && !defined(__HAIKU__) && !defined(__INNOTEK_LIBC__) \
|
2008-04-30 09:39:46 +02:00
|
|
|
&& !(defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 2)) && !defined(__dietlibc__) && !defined(HPUX)
|
2007-01-02 18:34:03 +01:00
|
|
|
/* If for any reason ifaddrs.h does not exist on your system, comment out
|
|
|
|
* the following two lines and an alternative way will be used to fetch
|
|
|
|
* the list of IPs from the system. */
|
2004-12-18 18:31:02 +01:00
|
|
|
# include <ifaddrs.h>
|
|
|
|
# define HAVE_GETIFADDRS
|
2005-02-28 23:33:31 +01:00
|
|
|
# endif
|
2008-08-26 00:10:47 +02:00
|
|
|
# if !defined(INADDR_NONE)
|
2004-12-18 18:31:02 +01:00
|
|
|
# define INADDR_NONE 0xffffffff
|
2005-02-28 23:33:31 +01:00
|
|
|
# endif
|
2005-01-17 14:13:11 +01:00
|
|
|
# if defined(__BEOS__) && !defined(BEOS_NET_SERVER)
|
2007-01-02 18:34:03 +01:00
|
|
|
/* needed on Zeta */
|
2005-01-17 14:13:11 +01:00
|
|
|
# include <sys/sockio.h>
|
|
|
|
# endif
|
2007-01-02 18:34:03 +01:00
|
|
|
# endif /* BEOS_NET_SERVER */
|
2004-12-23 20:23:56 +01:00
|
|
|
|
2005-05-15 01:48:39 +02:00
|
|
|
# if !defined(__BEOS__) && defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 1)
|
2004-12-23 20:23:56 +01:00
|
|
|
typedef uint32_t in_addr_t;
|
2005-02-28 23:33:31 +01:00
|
|
|
# endif
|
2004-12-23 20:23:56 +01:00
|
|
|
|
2004-12-04 18:54:56 +01:00
|
|
|
# include <errno.h>
|
|
|
|
# include <sys/time.h>
|
|
|
|
# include <netdb.h>
|
2009-03-15 01:32:18 +01:00
|
|
|
#endif /* UNIX */
|
2004-12-04 18:54:56 +01:00
|
|
|
|
2005-03-06 13:26:38 +01:00
|
|
|
#ifdef __BEOS__
|
2005-03-06 17:23:32 +01:00
|
|
|
typedef int socklen_t;
|
2005-03-06 13:26:38 +01:00
|
|
|
#endif
|
|
|
|
|
2009-09-21 20:36:33 +02:00
|
|
|
#ifdef __HAIKU__
|
|
|
|
#define IPV6_V6ONLY 27
|
|
|
|
#endif
|
|
|
|
|
2007-01-02 18:34:03 +01:00
|
|
|
/* OS/2 stuff */
|
2004-12-23 15:46:16 +01:00
|
|
|
#if defined(__OS2__)
|
|
|
|
# define SOCKET int
|
|
|
|
# define INVALID_SOCKET -1
|
|
|
|
# define ioctlsocket ioctl
|
|
|
|
# define closesocket close
|
2004-12-27 11:40:04 +01:00
|
|
|
# define GET_LAST_ERROR() (sock_errno())
|
2004-12-23 15:46:16 +01:00
|
|
|
|
2007-01-02 18:34:03 +01:00
|
|
|
/* Includes needed for OS/2 systems */
|
2004-12-23 15:46:16 +01:00
|
|
|
# include <types.h>
|
|
|
|
# include <unistd.h>
|
|
|
|
# include <sys/ioctl.h>
|
|
|
|
# include <sys/socket.h>
|
|
|
|
# include <netinet/in.h>
|
|
|
|
# include <netinet/tcp.h>
|
|
|
|
# include <arpa/inet.h>
|
|
|
|
# include <net/if.h>
|
|
|
|
# include <errno.h>
|
|
|
|
# include <sys/time.h>
|
|
|
|
# include <netdb.h>
|
|
|
|
# include <nerrno.h>
|
2004-12-27 11:40:04 +01:00
|
|
|
# define INADDR_NONE 0xffffffff
|
2014-12-24 18:17:18 +01:00
|
|
|
# include "../../3rdparty/os2/getaddrinfo.h"
|
|
|
|
# include "../../3rdparty/os2/getnameinfo.h"
|
|
|
|
|
|
|
|
#define IPV6_V6ONLY 27
|
|
|
|
|
|
|
|
/*
|
|
|
|
* IPv6 address
|
|
|
|
*/
|
|
|
|
struct in6_addr {
|
|
|
|
union {
|
|
|
|
uint8_t __u6_addr8[16];
|
|
|
|
uint16_t __u6_addr16[8];
|
|
|
|
uint32_t __u6_addr32[4];
|
|
|
|
} __u6_addr; /* 128-bit IP6 address */
|
|
|
|
};
|
|
|
|
|
|
|
|
#define s6_addr __u6_addr.__u6_addr8
|
|
|
|
|
|
|
|
struct sockaddr_in6 {
|
|
|
|
uint8_t sin6_len; /* length of this struct */
|
|
|
|
sa_family_t sin6_family; /* AF_INET6 */
|
|
|
|
in_port_t sin6_port; /* Transport layer port # */
|
|
|
|
uint32_t sin6_flowinfo; /* IP6 flow information */
|
|
|
|
struct in6_addr sin6_addr; /* IP6 address */
|
|
|
|
uint32_t sin6_scope_id; /* scope zone index */
|
|
|
|
};
|
2004-12-23 15:46:16 +01:00
|
|
|
|
2005-03-15 13:21:59 +01:00
|
|
|
typedef int socklen_t;
|
2006-12-10 01:20:26 +01:00
|
|
|
#if !defined(__INNOTEK_LIBC__)
|
2004-12-23 15:46:16 +01:00
|
|
|
typedef unsigned long in_addr_t;
|
2006-12-10 01:20:26 +01:00
|
|
|
#endif /* __INNOTEK_LIBC__ */
|
2014-12-24 18:17:18 +01:00
|
|
|
|
2007-01-02 18:34:03 +01:00
|
|
|
#endif /* OS/2 */
|
2004-12-23 15:46:16 +01:00
|
|
|
|
2007-01-02 18:34:03 +01:00
|
|
|
/* MorphOS and Amiga stuff */
|
2004-12-04 18:54:56 +01:00
|
|
|
#if defined(__MORPHOS__) || defined(__AMIGA__)
|
|
|
|
# include <exec/types.h>
|
2009-03-15 01:32:18 +01:00
|
|
|
# include <proto/exec.h> /* required for Open/CloseLibrary() */
|
2007-01-26 09:27:59 +01:00
|
|
|
/* MorphOS defines his network functions with UBYTE arrays while we
|
|
|
|
* use char arrays. This gives tons of unneeded warnings */
|
|
|
|
# define UBYTE char
|
2004-12-04 18:54:56 +01:00
|
|
|
# if defined(__MORPHOS__)
|
2009-03-15 01:32:18 +01:00
|
|
|
# include <sys/filio.h> /* FIO* defines */
|
|
|
|
# include <sys/sockio.h> /* SIO* defines */
|
2005-02-08 16:42:28 +01:00
|
|
|
# include <netinet/in.h>
|
2007-01-02 18:34:03 +01:00
|
|
|
# else /* __AMIGA__ */
|
2004-12-04 18:54:56 +01:00
|
|
|
# include <proto/socket.h>
|
|
|
|
# endif
|
|
|
|
|
2007-01-02 18:34:03 +01:00
|
|
|
/* Make the names compatible */
|
2004-12-04 18:54:56 +01:00
|
|
|
# define closesocket(s) CloseSocket(s)
|
|
|
|
# define GET_LAST_ERROR() Errno()
|
2007-04-19 00:10:36 +02:00
|
|
|
# define ioctlsocket(s, request, status) IoctlSocket((LONG)s, (ULONG)request, (char*)status)
|
2004-12-22 22:12:36 +01:00
|
|
|
# define ioctl ioctlsocket
|
2004-12-04 18:54:56 +01:00
|
|
|
|
2004-12-22 22:12:36 +01:00
|
|
|
typedef unsigned int in_addr_t;
|
2005-02-08 16:42:28 +01:00
|
|
|
typedef long socklen_t;
|
2004-12-22 22:12:36 +01:00
|
|
|
extern struct Library *SocketBase;
|
|
|
|
|
|
|
|
# ifdef __AMIGA__
|
2007-01-02 18:34:03 +01:00
|
|
|
/* for usleep() implementation */
|
2004-12-22 22:12:36 +01:00
|
|
|
extern struct Device *TimerBase;
|
|
|
|
extern struct MsgPort *TimerPort;
|
|
|
|
extern struct timerequest *TimerRequest;
|
|
|
|
# endif
|
2009-03-15 01:32:18 +01:00
|
|
|
#endif /* __MORPHOS__ || __AMIGA__ */
|
2004-12-04 18:54:56 +01:00
|
|
|
|
2011-05-01 15:29:40 +02:00
|
|
|
/**
|
|
|
|
* Try to set the socket into non-blocking mode.
|
|
|
|
* @param d The socket to set the non-blocking more for.
|
|
|
|
* @return True if setting the non-blocking mode succeeded, otherwise false.
|
|
|
|
*/
|
2007-02-11 14:39:23 +01:00
|
|
|
static inline bool SetNonBlocking(SOCKET d)
|
2005-02-07 10:56:16 +01:00
|
|
|
{
|
2018-12-09 02:28:14 +01:00
|
|
|
#ifdef _WIN32
|
2005-03-09 12:49:34 +01:00
|
|
|
u_long nonblocking = 1;
|
2007-01-02 18:34:03 +01:00
|
|
|
#else
|
2005-02-07 10:56:16 +01:00
|
|
|
int nonblocking = 1;
|
2007-01-02 18:34:03 +01:00
|
|
|
#endif
|
2018-04-29 14:12:23 +02:00
|
|
|
#if (defined(__BEOS__) && defined(BEOS_NET_SERVER))
|
2005-02-07 10:56:16 +01:00
|
|
|
return setsockopt(d, SOL_SOCKET, SO_NONBLOCK, &nonblocking, sizeof(nonblocking)) == 0;
|
2007-01-02 18:34:03 +01:00
|
|
|
#else
|
2005-02-07 10:56:16 +01:00
|
|
|
return ioctlsocket(d, FIONBIO, &nonblocking) == 0;
|
2007-01-02 18:34:03 +01:00
|
|
|
#endif
|
2005-02-07 10:56:16 +01:00
|
|
|
}
|
|
|
|
|
2011-05-01 15:29:40 +02:00
|
|
|
/**
|
|
|
|
* Try to set the socket to not delay sending.
|
|
|
|
* @param d The socket to disable the delaying for.
|
|
|
|
* @return True if disabling the delaying succeeded, otherwise false.
|
|
|
|
*/
|
2007-02-11 14:39:23 +01:00
|
|
|
static inline bool SetNoDelay(SOCKET d)
|
2005-02-07 10:56:16 +01:00
|
|
|
{
|
2007-01-02 18:34:03 +01:00
|
|
|
/* XXX should this be done at all? */
|
2009-03-15 01:32:18 +01:00
|
|
|
#if !defined(BEOS_NET_SERVER) /* not implemented on BeOS net_server */
|
2005-02-07 10:56:16 +01:00
|
|
|
int b = 1;
|
2007-01-02 18:34:03 +01:00
|
|
|
/* The (const char*) cast is needed for windows */
|
2005-02-07 10:56:16 +01:00
|
|
|
return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b)) == 0;
|
2007-01-02 18:34:03 +01:00
|
|
|
#else
|
2005-02-07 10:56:16 +01:00
|
|
|
return true;
|
2007-01-02 18:34:03 +01:00
|
|
|
#endif
|
2005-02-07 10:56:16 +01:00
|
|
|
}
|
|
|
|
|
2009-04-09 01:41:48 +02:00
|
|
|
/* Make sure these structures have the size we expect them to be */
|
2011-05-01 15:29:40 +02:00
|
|
|
assert_compile(sizeof(in_addr) == 4); ///< IPv4 addresses should be 4 bytes.
|
|
|
|
assert_compile(sizeof(in6_addr) == 16); ///< IPv6 addresses should be 16 bytes.
|
2009-04-09 01:41:48 +02:00
|
|
|
|
2005-05-15 01:48:39 +02:00
|
|
|
#endif /* ENABLE_NETWORK */
|
|
|
|
|
2007-01-02 18:34:03 +01:00
|
|
|
#endif /* NETWORK_CORE_OS_ABSTRACTION_H */
|