Improve platform compatibility

Replace a bunch of non-standard defines with standard ones

Don't #define POSIX in public header or test for it.  Fixes #228.
(We shoulkd probably also make this change to Steamworks headers.)

Use IsLinux(), IsPosix(), etc instead of #ifdef LINUX or #ifdef POSIX

Moved some platform socket stuff out of steamnetworkingsockets_platform.h
and into platform_sockets.h.  (none of this is actually particular to
steamnetworkingsockets.)

Some platforms don't have IPv6 support.
This commit is contained in:
Fletcher Dunn
2022-06-14 11:57:53 -07:00
parent 78481e083d
commit 09871d2dc4
24 changed files with 335 additions and 216 deletions
+3 -3
View File
@@ -158,11 +158,11 @@ function(set_target_common_gns_properties TGT)
endif()
if(CMAKE_SYSTEM_NAME MATCHES Linux)
target_compile_definitions(${TGT} PUBLIC POSIX LINUX)
target_compile_definitions(${TGT} PUBLIC LINUX)
elseif(CMAKE_SYSTEM_NAME MATCHES Darwin)
target_compile_definitions(${TGT} PUBLIC POSIX OSX)
target_compile_definitions(${TGT} PUBLIC OSX)
elseif(CMAKE_SYSTEM_NAME MATCHES FreeBSD)
target_compile_definitions(${TGT} PUBLIC POSIX FREEBSD)
target_compile_definitions(${TGT} PUBLIC FREEBSD)
elseif(CMAKE_SYSTEM_NAME MATCHES Windows)
target_compile_definitions(${TGT} PUBLIC _WINDOWS)
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
+2 -2
View File
@@ -22,7 +22,7 @@
#include <steam/steam_api.h>
#endif
#ifdef WIN32
#ifdef _WIN32
#include <windows.h> // Ug, for NukeProcess -- see below
#else
#include <unistd.h>
@@ -43,7 +43,7 @@ SteamNetworkingMicroseconds g_logTimeZero;
// down the thread that is reading from stdin.
static void NukeProcess( int rc )
{
#ifdef WIN32
#ifdef _WIN32
ExitProcess( rc );
#else
(void)rc; // Unused formal parameter
+1 -1
View File
@@ -14,7 +14,7 @@
#include <steam/isteamnetworkingutils.h>
#include <steam/steamnetworkingcustomsignaling.h>
#ifdef POSIX
#ifdef VALVE_POSIX
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
+4 -2
View File
@@ -17,11 +17,13 @@
typedef unsigned char uint8;
#endif
#if defined( __GNUC__ ) && !defined(_WIN32) && !defined(POSIX)
#if ( defined(POSIX) || defined(_POSIX_VERSION) || ( defined( __GNUC__ ) && !defined(_WIN32) ) ) && !defined(VALVE_POSIX)
#define VALVE_POSIX 1
#endif
#ifdef __GNUC__
#if __GNUC__ < 4
#error "Steamworks requires GCC 4.X (4.2 or 4.4 have been tested)"
#endif
#define POSIX 1
#endif
#if defined(__LP64__) || defined(__x86_64__) || defined(_WIN64) || defined(__aarch64__) || defined(__s390x__)
+2 -2
View File
@@ -10,7 +10,7 @@
#define _X86INTRIN_H_INCLUDED
#endif
#include "winlite.h"
#elif defined(POSIX)
#elif IsPosix()
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
@@ -397,7 +397,7 @@ void CCrypto::GenerateRandomBlock( void *pvDest, int cubDest )
bool bRtlGenRandomOK = s_pfnRtlGenRandom && ( s_pfnRtlGenRandom( pubDest, (unsigned long)cubDest ) == TRUE );
AssertFatal( bRtlGenRandomOK );
#elif defined(POSIX)
#elif IsPosix()
// Reading from /dev/urandom is threadsafe, but possibly slow due to a kernel
// spinlock or mutex protecting access to the internal PRNG state. In theory,
+5 -5
View File
@@ -85,7 +85,7 @@
// Linux had a few areas where it didn't construct objects in the same order that Windows does.
// So when CVProfile::CVProfile() would access g_pMemAlloc, it would crash because the allocator wasn't initalized yet.
#if defined( GNUC ) || defined ( COMPILER_GCC ) || defined( COMPILER_SNC )
#if defined( __GNUC__ ) || defined ( COMPILER_GCC ) || defined( COMPILER_SNC )
#define CONSTRUCT_EARLY __attribute__((init_priority(101)))
#else
#define CONSTRUCT_EARLY
@@ -93,7 +93,7 @@
#ifdef _WIN32
#define SELECTANY __declspec(selectany)
#elif defined(GNUC) || defined ( COMPILER_GCC ) || defined( COMPILER_SNC )
#elif defined(__GNUC__) || defined ( COMPILER_GCC ) || defined( COMPILER_SNC )
#define SELECTANY __attribute__((weak))
#else
#define SELECTANY static
@@ -105,7 +105,7 @@
#if defined(_WIN32) && !defined(_XBOX)
#define PLAT_DECL_EXPORT __declspec( dllexport )
#define PLAT_DECL_IMPORT __declspec( dllimport )
#elif defined(GNUC) || defined(COMPILER_GCC)
#elif defined(__GNUC__) || defined(COMPILER_GCC)
#define PLAT_DECL_EXPORT __attribute__((visibility("default")))
#define PLAT_DECL_IMPORT
#elif defined(_XBOX) || defined(COMPILER_SNC)
@@ -156,7 +156,7 @@
#define __stdcall __attribute__ ((__stdcall__))
#endif
#define FASTCALL
#elif defined(POSIX)
#elif IsPosix()
#define __stdcall
#define __cdecl
#define STDCALL
@@ -167,7 +167,7 @@
#define NOINLINE __declspec(noinline)
#define NORETURN __declspec(noreturn)
#define FORCEINLINE __forceinline
#elif defined(GNUC) || defined(COMPILER_GCC) || defined(COMPILER_SNC)
#elif defined(__GNUC__) || defined(COMPILER_GCC) || defined(COMPILER_SNC)
#define NOINLINE __attribute__ ((noinline))
#define NORETURN __attribute__ ((noreturn))
#if defined(COMPILER_GCC) || defined(COMPILER_SNC)
+36 -26
View File
@@ -48,10 +48,6 @@
#endif
#endif
#if ( defined(LINUX) || defined(OSX) || defined(ANDROID) ) && !defined(POSIX)
#define POSIX
#endif
#if defined(_WIN32) && !defined(WINDED)
#if defined(_M_IX86)
#define __i386__ 1
@@ -110,6 +106,10 @@
#define IsRetail() false
#endif
#ifdef IsPosix
#error "Too soon"
#endif
#ifdef _DEBUG
#define IsRelease() false
#define IsDebug() true
@@ -122,29 +122,41 @@
#define IsXboxOne() true
#define IsConsole() true
#elif defined( NN_NINTENDO_SDK )
#if !defined(POSIX) && !defined(_WIN32)
#define POSIX
#ifndef _WIN32
#define IsPosix() true
#endif
#define IsNintendoSwitch() true
#define IsConsole() true
#elif defined( _PS5 )
#ifndef POSIX
#define POSIX
#endif
#elif defined( __PROSPERO__ )
#define IsPosix() true
#define IsPS5() true
#define IsConsole() true
#elif defined( __ORBIS__ )
#define IsPosix() true
#define IsPS4() true
#define IsConsole() true
#elif defined( _WIN32 )
#define IsWindows() true
#define IsPC() true
#elif defined(POSIX)
#define IsPC() true
#ifdef LINUX
#define IsLinux() true
#endif
#ifdef OSX
#elif defined( __ANDROID__ ) || defined( ANDROID )
#define IsAndroid() true
#define IsPosix() true
#elif defined(__APPLE__)
#include <TargetConditionals.h>
#if defined( TARGET_OS_MAC )
#define SUPPORTS_IOPOLLINGHELPER
#define IsOSX() true
#define IsPosix() true
//#elif defined( TARGET_OS_IPHONE )
#else
#error "Unsupported platform"
#endif
#elif defined( LINUX ) || defined( __LINUX__ ) || defined(linux) || defined(__linux) || defined(__linux__)
#define IsLinux() true
#define IsPosix() true
#elif defined( _POSIX_VERSION ) || defined( POSIX ) || defined( VALVE_POSIX )
#define IsPosix() true
#define IsPC() true
#else
#error Undefined platform
#endif
@@ -155,6 +167,9 @@
#ifndef IsPC
#define IsPC() false
#endif
#ifndef IsAndroid
#define IsAndroid() false
#endif
#ifndef IsConsole
#define IsConsole() false
#endif
@@ -164,15 +179,17 @@
#ifndef IsXboxOne
#define IsXboxOne() false
#endif
#ifndef IsPS4
#define IsPS4() false
#endif
#ifndef IsPS5
#define IsPS5() false
#endif
#define IsPlaystation() ( IsPS4() || IsPS5() )
#ifndef IsLinux
#define IsLinux() false
#endif
#ifdef POSIX
#define IsPosix() true
#else
#ifndef IsPosix
#define IsPosix() false
#endif
#ifndef IsOSX
@@ -185,13 +202,6 @@
#define IsARM() false
#endif
#endif
#ifndef IsAndroid
#ifdef ANDROID
#define IsAndroid() true
#else
#define IsAndroid() false
#endif
#endif
// Detect if RTTI is enabled in the current compile
#if defined(__clang__)
+9 -7
View File
@@ -47,16 +47,18 @@
#if defined(_WIN32)
#define PLAT_DLL_EXT "dll"
#elif defined(LINUX)
#elif IsLinux()
#define PLAT_DLL_EXT "so"
#elif defined(OSX)
#elif IsOSX()
#define PLAT_DLL_EXT "dylib"
#endif
#if defined(_WIN32)
#define PLAT_PATH_SLASH "\\"
#elif defined(POSIX)
#elif IsPosix()
#define PLAT_PATH_SLASH "/"
#else
#error "?"
#endif
#if defined( _PS3 )
@@ -64,7 +66,7 @@
#define PATH_MAX CELL_GAME_PATH_MAX
#endif
#if (!defined(_WIN32) || defined(WINDED)) && defined(POSIX)
#if (!defined(_WIN32) || defined(WINDED)) && IsPosix()
#define MAX_PATH PATH_MAX
#define _MAX_PATH PATH_MAX
#endif
@@ -149,7 +151,7 @@ FORCEINLINE unsigned __int64 PLAT_CPU_TIME()
}
#elif defined(POSIX)
#elif IsPosix()
#include <sys/time.h>
@@ -252,7 +254,7 @@ char (*RtlpNumberOf( UNALIGNED T (&)[N] ))[N];
#endif
#endif
#elif defined(LINUX)
#elif IsLinux()
// On Linux/gcc, RtlpNumberOf doesn't work well with pointers to structs
// that are defined function locally. Here we have an alternative implementation
@@ -318,7 +320,7 @@ struct ErrorIfIsPointerNotArrayGivenToARRAYSIZE<false>
#endif
// Don't define for Windows, since it is defined unconditionally in winnt.h.
#if !defined( UNREFERENCED_PARAMETER ) && !defined( WIN32 )
#if !defined( UNREFERENCED_PARAMETER ) && !defined( _WIN32 )
#define UNREFERENCED_PARAMETER(parm) NOTE_UNUSED(parm)
#endif
+1 -1
View File
@@ -75,7 +75,7 @@ typedef uint32 uint32_t;
// NOTE: int64_t must match the compiler stdint.h definition
// and so may not match the Steam int64. Mixing the two is
// error-prone so always use the Steam non-_t types in Steam code.
#if defined(COMPILER_GCC) && defined(PLATFORM_64BITS) && !defined(__MINGW32__) && !defined(OSX) && !(defined(IOS) || defined(TVOS))
#if defined(COMPILER_GCC) && defined(PLATFORM_64BITS) && !defined(__MINGW32__) && !IsOSX() && !(defined(IOS) || defined(TVOS))
#define INT64_DIFFERENT_FROM_INT64_T 1
typedef long int int64_t;
typedef unsigned long int uint64_t;
+1 -1
View File
@@ -30,7 +30,7 @@
#pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#if IsPS5() /* This is the wrong way to detect this. HALP */
#if defined( __PROSPERO__ ) || defined( __ORBIS__ ) /* This is the wrong way to detect this. HALP */
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wreorder-ctor"
#endif
+2 -2
View File
@@ -30,7 +30,7 @@
#include "minbase/minbase_macros.h"
#include "minbase/minbase_endian.h"
#ifdef POSIX
#if IsPosix()
typedef int SOCKET;
#define INVALID_SOCKET (-1)
#else
@@ -53,7 +53,7 @@
#include "platformtime.h"
#if defined( POSIX )
#if IsPosix()
// handle mapping windows names used in tier0 to posix names in one place
#define _snprintf snprintf //validator.cpp
@@ -1,13 +1,34 @@
//====== Copyright Valve Corporation, All rights reserved. ====================
//
// Include the relevant platform-specific headers for socket-related stuff,
// and declare some functions make them look similar
// Include the relevant platform-specific headers for socket-related
// stuff, and declare some functions make them look as similar to
// plain BSD sockets as possible.
//
// This includes a bunch of stuff. DO NOT INCLUDE THIS FROM A HEADER
//
// Some things that will be defined by this file:
//
// closesocket()
// GetLastSocketError()
// SetSocketNonBlocking()
//
// USE_EPOLL or USE_POLL
// If USE_EPOLL:
// EPollHandle, INVALID_EPOLL_HANDLE, EPollCreate()
//
// WAKE_THREAD_USING_EVENT or WAKE_THREAD_USING_SOCKET_PAIR
// If WAKE_THREAD_USING_EVENT:
// ThreadWakeEvent, INVALID_THREAD_WAKE_EVENT, SetWakeThreadEvent()
#ifndef STEAMNETWORKINGSOCKETS_PLATFORM_H
#define STEAMNETWORKINGSOCKETS_PLATFORM_H
#ifndef TIER0_PLATFORM_SOCKETS_H
#define TIER0_PLATFORM_SOCKETS_H
#pragma once
#include "platform.h"
// !KLUDGE!
typedef char SteamNetworkingErrMsg[ 1024 ];
// Socket headers
#ifdef _WIN32
//#include <windows.h>
@@ -45,12 +66,11 @@
#elif IsNintendoSwitch()
// NDA-protected material, so all this is in a separate file
#include "clientlib/nswitch/steamnetworkingsockets_platform_nswitch.h"
#elif IsPS5()
#include "platform_sockets_nswitch.h"
#elif IsPlaystation()
// NDA-protected material, so all this is in a separate file
#include "clientlib/ps5/steamnetworkingsockets_platform_ps5.h"
#else
#include "platform_sockets_playstation.h"
#elif IsPosix()
// POSIX-ish platform (Linux, OSX, Android, IOS)
#include <sys/types.h>
@@ -61,7 +81,7 @@
#include <poll.h>
#include <errno.h>
#ifndef ANDROID
#if !IsAndroid()
#include <ifaddrs.h>
#endif
#include <net/if.h>
@@ -95,7 +115,7 @@
inline EPollHandle EPollCreate( SteamNetworkingErrMsg &errMsg )
{
int flags = 0;
#ifdef LINUX
#if IsLinux()
flags |= EPOLL_CLOEXEC;
#endif
EPollHandle e = epoll_create1( flags );
@@ -113,6 +133,8 @@
// instead of a socket pair?
#endif
#else
#error "How do?"
#endif
#endif // #ifndef STEAMNETWORKINGSOCKETS_PLATFORM_H
#endif // _H
+2 -2
View File
@@ -31,7 +31,7 @@ typedef unsigned char uint8;
typedef unsigned char BYTE;
typedef unsigned char byte;
#ifdef WIN32
#ifdef _WIN32
#include <tchar.h>
#include <wchar.h>
#elif defined( _PS3 )
@@ -85,7 +85,7 @@ typedef char tchar;
#endif
#if defined( _MSC_VER ) || defined( WIN32 )
#if defined( _MSC_VER ) || defined( _WIN32 )
typedef wchar_t uchar16;
typedef unsigned int uchar32;
#else
+2 -2
View File
@@ -19,7 +19,7 @@
#pragma once
#endif
#if defined(POSIX)
#ifdef __GNUC__
// clang will error if the symbol visibility for an object changes between static libraries (and/or your main dylib)
// so force the FmtStr templates and importantly the global scAsserted below to hidden (i.e don't escape the dll) forcefully
#pragma GCC visibility push(hidden)
@@ -318,7 +318,7 @@ void CFmtStrN< SIZE_BUF, QT, ON_STACK >::Set( const char *pchValue, int nSize )
m_nLength = CopyStringLength( BaseClass::m_szBuf, pchValue, nMaxLength );
}
#if defined(POSIX)
#ifdef __GNUC__
#pragma GCC visibility pop
#endif
+1 -1
View File
@@ -13,7 +13,7 @@
// Forward declarations of tag types and some template helper classes
//-----------------------------------------------------------------------------
#if !defined( OSX ) && !defined( IOS ) && !defined( TVOS ) && !defined(COMPILER_CLANG)
#if !IsOSX() && !defined( IOS ) && !defined( TVOS ) && !defined(COMPILER_CLANG)
namespace std
{
struct forward_iterator_tag;
+5 -5
View File
@@ -104,13 +104,13 @@ extern void V_StripTrailingWhitespaceASCII( char *pch );
// trim whitespace from both ends of the string
extern int V_StrTrim( char *pStr );
#ifdef POSIX
#ifdef ANDROID
#if IsPosix()
#if IsAndroid()
#include <wchar.h>
#endif
#define _atoi64 atoll
#define _wtoi(arg) wcstol(arg, NULL, 10)
#ifdef ANDROID
#if IsAndroid()
// TODO - Android doesn't support wcstoi64, so just use a basic implementation of our own.
#define _wcstoi64 vstdlib_wcstoi64
#define _wcstoui64 vstdlib_wcstoui64
@@ -124,7 +124,7 @@ extern int V_StrTrim( char *pStr );
#define _strtoi64 strtoll
#define _strtoui64 strtoull
#define _vsnprintf vsnprintf
#if defined(OSX) || defined(ANDROID)
#if IsOSX() || IsAndroid()
// TODO - OSX doesn't support wcscasecmp until 10.7, so just
// use a basic implementation of our own.
#define _wcsicmp vstdlib_wcsicmp
@@ -139,7 +139,7 @@ extern int V_StrTrim( char *pStr );
#endif
#define TEXT(str) str
#endif // POSIX
#endif // IsPosix()
END_TIER0_NAMESPACE
@@ -2384,7 +2384,7 @@ const char *CSteamNetworkingUtils::GetBuildString()
const char *CSteamNetworkingUtils::GetPlatformString()
{
#if defined( NN_NINTENDO_SDK )
#if IsNintendoSwitch()
return "nswitch";
#elif defined( _GAMECORE )
// Is this right? This might actually require a system call.
@@ -2392,11 +2392,11 @@ const char *CSteamNetworkingUtils::GetPlatformString()
#elif defined( _STADIA )
// Not sure if this works.
return "stadia";
#elif defined( _XBOX_ONE )
#elif IsXboxOne()
return "xbone";
#elif defined( _PS4 )
#elif IsPS4()
return "ps4";
#elif defined( _PS5 )
#elif IsPS5()
return "ps5";
#elif defined( TVOS ) || defined( __TVOS__ )
return "tvos";
@@ -2408,13 +2408,13 @@ const char *CSteamNetworkingUtils::GetPlatformString()
#else
return "osx";
#endif
#elif defined( OSX )
#elif IsOSX()
return "osx";
#elif defined( ANDROID ) || defined( __ANDROID__ )
#elif IsAndroid()
return "android";
#elif defined( _WINDOWS )
return "windows";
#elif defined( LINUX ) || defined( __LINUX__ ) || defined(linux) || defined(__linux) || defined(__linux__)
#elif IsLinux()
return "linux";
#elif defined( FREEBSD ) || defined( __FreeBSD__ )
return "freebsd";
@@ -15,16 +15,8 @@
#include <mutex>
#include <atomic>
#ifdef POSIX
#include <pthread.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#endif
#include "steamnetworkingsockets_lowlevel.h"
#include "../steamnetworkingsockets_platform.h"
#include <tier0/platform_sockets.h>
#include "../steamnetworkingsockets_internal.h"
#include "../steamnetworkingsockets_thinker.h"
#include "steamnetworkingsockets_connections.h"
@@ -33,6 +25,18 @@
#include <tier1/utllinkedlist.h>
#include "crypto.h"
#if IsPosix()
#include <pthread.h>
#include <sched.h>
#include <sys/types.h>
#if !IsNintendoSwitch()
#include <sys/socket.h>
#endif
#ifdef STEAMNETWORKINGSOCKETS_ENABLE_RESOLVEHOSTNAME
#include <netdb.h>
#endif
#endif
#include <tier0/memdbgoff.h>
// Ugggggggggg MSVC VS2013 STL bug: try_lock_for doesn't actually respect the timeout, it always ends up using an infinite timeout.
@@ -888,6 +892,33 @@ static void UpdateFakeRateLimitTokenBuckets( SteamNetworkingMicroseconds usecNow
inline IRawUDPSocket::IRawUDPSocket() {}
inline IRawUDPSocket::~IRawUDPSocket() {}
// Perform gather-based send, on platform that doesn't have sendmsg
#ifdef PLATFORM_NO_SENDMSG
bool sendto_gather( int sockfd, int nChunks, const iovec *pChunks, sockaddr *pAddr, socklen_t addrSize )
{
COMPILE_TIME_ASSERT( k_cbSteamNetworkingSocketsMaxUDPMsgLen < 1500 );
char pkt[ 2048 ];
char *max = pkt + sizeof(pkt);
char *d = pkt;
for ( int i = 0 ; i < nChunks ; ++i )
{
const iovec &chunk = pChunks[i];
if ( d + chunk.iov_len > max )
{
AssertMsg( false, "Gather send too big!" );
return false;
}
memcpy( d, chunk.iov_base, chunk.iov_len );
d += chunk.iov_len;
}
ssize_t cbTotal = d - pkt;
ssize_t r = sendto( sockfd, pkt, cbTotal, 0, pAddr, addrSize );
return ( r == cbTotal );
}
#endif
class CRawUDPSocketImpl final : public IRawUDPSocket
{
public:
@@ -917,6 +948,7 @@ public:
inline bool BReallySendRawPacket( int nChunks, const iovec *pChunks, const netadr_t &adrTo ) const
{
Assert( m_socket != INVALID_SOCKET );
Assert( nChunks > 0 );
// Add a tag. If we end up holding the lock for a long time, this tag
// will tell us how many packets were sent
@@ -927,8 +959,13 @@ public:
socklen_t addrSize;
if ( m_nAddressFamilies & k_nAddressFamily_IPv6 )
{
addrSize = sizeof(sockaddr_in6);
adrTo.ToSockadrIPV6( &destAddress );
#ifdef PLATFORM_NO_IPV6
Assert( false );
return false;
#else
addrSize = sizeof(sockaddr_in6);
adrTo.ToSockadrIPV6( &destAddress );
#endif
}
else
{
@@ -953,7 +990,7 @@ public:
SteamNetworkingMicroseconds usecSendStart = SteamNetworkingSockets_GetLocalTimestamp();
#endif
#ifdef WIN32
#ifdef _WIN32
// Confirm that iovec and WSABUF are indeed bitwise equivalent
COMPILE_TIME_ASSERT( sizeof( iovec ) == sizeof( WSABUF ) );
COMPILE_TIME_ASSERT( offsetof( iovec, iov_len ) == offsetof( WSABUF, len ) );
@@ -992,17 +1029,30 @@ public:
}
#endif
#else
msghdr msg;
msg.msg_name = (sockaddr *)&destAddress;
msg.msg_namelen = addrSize;
msg.msg_iov = const_cast<struct iovec *>( pChunks );
msg.msg_iovlen = nChunks;
msg.msg_control = nullptr;
msg.msg_controllen = 0;
msg.msg_flags = 0;
bool bResult;
if ( nChunks == 1 )
{
ssize_t r = sendto( m_socket, pChunks->iov_base, pChunks->iov_len, 0, (sockaddr *)&destAddress, addrSize );
bResult = ( r == (ssize_t)pChunks->iov_len );
}
else
{
#ifdef PLATFORM_NO_SENDMSG
bResult = sendto_gather( m_socket, nChunks, pChunks, (sockaddr *)&destAddress, addrSize );
#else
msghdr msg;
msg.msg_name = (sockaddr *)&destAddress;
msg.msg_namelen = addrSize;
msg.msg_iov = const_cast<struct iovec *>( pChunks );
msg.msg_iovlen = nChunks;
msg.msg_control = nullptr;
msg.msg_controllen = 0;
msg.msg_flags = 0;
int r = ::sendmsg( m_socket, &msg, 0 );
bool bResult = ( r >= 0 ); // just check for -1 for error, since we don't want to take the time here to scan the iovec and sum up the expected total number of bytes sent
ssize_t r = sendmsg( m_socket, &msg, 0 );
bResult = ( r >= 0 ); // just check for -1 for error, since we don't want to take the time here to scan the iovec and sum up the expected total number of bytes sent
#endif
}
#endif
#ifdef STEAMNETWORKINGSOCKETS_LOWLEVEL_TIME_SOCKET_CALLS
@@ -1284,6 +1334,11 @@ static CPacketLaggerRecv s_packetLagQueueRecv;
#ifdef USE_POLL
static CUtlVector<pollfd> s_vecPollFDs;
static bool s_bRecreatePollList = true;
#ifndef POLLEVENT_INVALID
#define POLLEVENT_INVALID (-1)
#endif
#endif
#ifdef USE_EPOLL
@@ -1461,16 +1516,16 @@ void CRawUDPSocketImpl::Close()
}
}
static SOCKET OpenUDPSocketBoundToSockAddr( const void *sockaddr, size_t len, SteamNetworkingErrMsg &errMsg, int *pnIPv6AddressFamilies, int nBindInterface = -1 )
static SOCKET OpenUDPSocketBoundToSockAddr( const void *pSockaddr, size_t len, SteamNetworkingErrMsg &errMsg, int *pnIPv6AddressFamilies, int nBindInterface = -1 )
{
unsigned int opt;
const sockaddr_in *inaddr = (const sockaddr_in *)sockaddr;
const sockaddr_in *inaddr = (const sockaddr_in *)pSockaddr;
// Select socket type. For linux, use the "close on exec" flag, so that the
// socket will not be inherited by any child process that we spawn.
int sockType = SOCK_DGRAM;
#ifdef LINUX
#if IsLinux()
sockType |= SOCK_CLOEXEC;
#endif
#if IsNintendoSwitch() && !defined( _WIN32 )
@@ -1514,36 +1569,43 @@ static SOCKET OpenUDPSocketBoundToSockAddr( const void *sockaddr, size_t len, St
// Handle IP v6 dual stack?
if ( pnIPv6AddressFamilies )
{
#ifdef PLATFORM_NO_IPV6
Assert( false ); // Caller should check this define
V_strcpy_safe( errMsg, "No IPV6 support" );
closesocket( sock );
return INVALID_SOCKET;
#else
// Enable dual stack?
opt = ( *pnIPv6AddressFamilies == k_nAddressFamily_IPv6 ) ? 1 : 0;
if ( setsockopt( sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&opt, sizeof( opt ) ) != 0 )
{
if ( *pnIPv6AddressFamilies == k_nAddressFamily_IPv6 )
// Enable dual stack?
opt = ( *pnIPv6AddressFamilies == k_nAddressFamily_IPv6 ) ? 1 : 0;
if ( setsockopt( sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&opt, sizeof( opt ) ) != 0 )
{
// Spew a warning, but continue
SpewWarning( "Failed to set socket for IPv6 only (IPV6_V6ONLY=1). Error code 0x%08X. Continuing anyway.\n", GetLastSocketError() );
if ( *pnIPv6AddressFamilies == k_nAddressFamily_IPv6 )
{
// Spew a warning, but continue
SpewWarning( "Failed to set socket for IPv6 only (IPV6_V6ONLY=1). Error code 0x%08X. Continuing anyway.\n", GetLastSocketError() );
}
else
{
// Dual stack required, or only requested?
if ( *pnIPv6AddressFamilies == k_nAddressFamily_DualStack )
{
V_sprintf_safe( errMsg, "Failed to set socket for dual stack (IPV6_V6ONLY=0). Error code 0x%08X.", GetLastSocketError() );
closesocket( sock );
return INVALID_SOCKET;
}
// Let caller know we're IPv6 only, and spew about this.
SpewWarning( "Failed to set socket for dual stack (IPV6_V6ONLY=0). Error code 0x%08X. Continuing using IPv6 only!\n", GetLastSocketError() );
*pnIPv6AddressFamilies = k_nAddressFamily_IPv6;
}
}
else
{
// Dual stack required, or only requested?
if ( *pnIPv6AddressFamilies == k_nAddressFamily_DualStack )
{
V_sprintf_safe( errMsg, "Failed to set socket for dual stack (IPV6_V6ONLY=0). Error code 0x%08X.", GetLastSocketError() );
closesocket( sock );
return INVALID_SOCKET;
}
// Let caller know we're IPv6 only, and spew about this.
SpewWarning( "Failed to set socket for dual stack (IPV6_V6ONLY=0). Error code 0x%08X. Continuing using IPv6 only!\n", GetLastSocketError() );
*pnIPv6AddressFamilies = k_nAddressFamily_IPv6;
// Tell caller what they've got
*pnIPv6AddressFamilies = opt ? k_nAddressFamily_IPv6 : k_nAddressFamily_DualStack;
}
}
else
{
// Tell caller what they've got
*pnIPv6AddressFamilies = opt ? k_nAddressFamily_IPv6 : k_nAddressFamily_DualStack;
}
#endif
}
// Bind to particular interface
@@ -1586,7 +1648,7 @@ static SOCKET OpenUDPSocketBoundToSockAddr( const void *sockaddr, size_t len, St
}
// Bind it to specific desired local port/IP
if ( bind( sock, (struct sockaddr *)sockaddr, (socklen_t)len ) == -1 )
if ( bind( sock, (struct sockaddr *)pSockaddr, (socklen_t)len ) == -1 )
{
V_sprintf_safe( errMsg, "Failed to bind socket. Error code 0x%08X.", GetLastSocketError() );
closesocket( sock );
@@ -1659,31 +1721,33 @@ static CRawUDPSocketImpl *OpenRawUDPSocketInternal( CRecvPacketCallback callback
// Try IPv6?
SOCKET sock = INVALID_SOCKET;
if ( nAddressFamilies & k_nAddressFamily_IPv6 )
{
sockaddr_in6 address6;
memset( &address6, 0, sizeof(address6) );
address6.sin6_family = AF_INET6;
memcpy( address6.sin6_addr.s6_addr, addrLocal.m_ipv6, 16 );
address6.sin6_port = BigWord( addrLocal.m_port );
// Try to get socket
int nIPv6AddressFamilies = nAddressFamilies;
sock = OpenUDPSocketBoundToSockAddr( &address6, sizeof(address6), errMsg, &nIPv6AddressFamilies, nBindInterface );
if ( sock == INVALID_SOCKET )
#ifndef PLATFORM_NO_IPV6
if ( nAddressFamilies & k_nAddressFamily_IPv6 )
{
// Allowing fallback to IPv4?
if ( nAddressFamilies != k_nAddressFamily_Auto )
return nullptr;
sockaddr_in6 address6;
memset( &address6, 0, sizeof(address6) );
address6.sin6_family = AF_INET6;
memcpy( address6.sin6_addr.s6_addr, addrLocal.m_ipv6, 16 );
address6.sin6_port = BigWord( addrLocal.m_port );
// Continue below, we'll try IPv4
// Try to get socket
int nIPv6AddressFamilies = nAddressFamilies;
sock = OpenUDPSocketBoundToSockAddr( &address6, sizeof(address6), errMsg, &nIPv6AddressFamilies, nBindInterface );
if ( sock == INVALID_SOCKET )
{
// Allowing fallback to IPv4?
if ( nAddressFamilies != k_nAddressFamily_Auto )
return nullptr;
// Continue below, we'll try IPv4
}
else
{
nAddressFamilies = nIPv6AddressFamilies;
}
}
else
{
nAddressFamilies = nIPv6AddressFamilies;
}
}
#endif
// Try IPv4?
if ( sock == INVALID_SOCKET )
@@ -1721,11 +1785,13 @@ static CRawUDPSocketImpl *OpenRawUDPSocketInternal( CRecvPacketCallback callback
const sockaddr_in *boundaddr4 = (const sockaddr_in *)&addrBound;
addrLocal.SetIPv4( BigDWord( boundaddr4->sin_addr.s_addr ), BigWord( boundaddr4->sin_port ) );
}
#ifndef PLATFORM_NO_IPV6
else if ( addrBound.ss_family == AF_INET6 )
{
const sockaddr_in6 *boundaddr6 = (const sockaddr_in6 *)&addrBound;
addrLocal.SetIPv6( boundaddr6->sin6_addr.s6_addr, BigWord( boundaddr6->sin6_port ) );
}
#endif
else
{
Assert( false );
@@ -1978,7 +2044,7 @@ static bool PollRawUDPSockets( int nMaxTimeoutMS, bool bManualPoll )
Assert( f != INVALID_SOCKET ); \
p.fd = f; \
p.events = POLLRDNORM; \
p.revents = -1; /* Make sure kernel is clearing events properly */ \
p.revents = POLLEVENT_INVALID; /* Make sure kernel is clearing events properly */ \
}
for ( CRawUDPSocketImpl *pSock: s_vecRawSockets )
@@ -2015,7 +2081,7 @@ static bool PollRawUDPSockets( int nMaxTimeoutMS, bool bManualPoll )
struct epoll_event epoll_events[ 32 ];
int num_epoll_events = epoll_wait( s_epollfd, epoll_events, V_ARRAYSIZE( epoll_events ), nMaxTimeoutMS );
#elif defined( USE_POLL )
poll( s_vecPollFDs.Base(), s_vecPollFDs.Count(), nMaxTimeoutMS );
int poll_result = poll( s_vecPollFDs.Base(), s_vecPollFDs.Count(), nMaxTimeoutMS );
#elif defined( _WIN32 )
WaitForSingleObject( s_hEventWakeThread, nMaxTimeoutMS );
#else
@@ -2099,6 +2165,41 @@ static bool PollRawUDPSockets( int nMaxTimeoutMS, bool bManualPoll )
#else
// On POSIX, check return value, and also handle the wake "fd"
#ifdef USE_POLL
{
// Make sure we actually got some descriptors with data
if ( poll_result <= 0 )
{
if ( poll_result < 0 )
SpewWarning( "poll() returned %d, errno %d\n", poll_result, errno );
goto exit_polling;
}
pollfd &wake = s_vecPollFDs[ nSocketsToPoll ];
if ( (int)( wake.revents & POLLRDNORM ) )
{
Assert( wake.revents != POLLEVENT_INVALID );
#if defined( WAKE_THREAD_USING_EVENT )
Assert( wake.fd == s_hEventWakeThread );
ClearWakeThreadEvent( wake, s_hEventWakeThread );
#elif defined( WAKE_THREAD_USING_SOCKET_PAIR )
Assert( wake.fd == s_hSockWakeThreadRead );
// Just eat one request for now.
// I think it's probably safe to eat all of them, but
// it's a small optimization and I don't want to debug
// it is that's not true.
char buf[8];
::recv( s_hSockWakeThreadRead, buf, sizeof(buf), 0 );
#else
#error "How did we wake up?"
#endif
}
}
#endif
// Not using epoll, just check all sockets
for ( int idx = 0 ; idx < nSocketsToPoll ; ++idx )
{
@@ -2117,7 +2218,7 @@ static bool PollRawUDPSockets( int nMaxTimeoutMS, bool bManualPoll )
#elif defined( USE_POLL )
if ( !( s_vecPollFDs[ idx ].revents & POLLRDNORM ) )
continue;
Assert( s_vecPollFDs[ idx ].revents != -1 ); // Make sure kernel actually populated this
Assert( s_vecPollFDs[ idx ].revents != POLLEVENT_INVALID ); // Make sure kernel actually populated this
#else
#error "How to tell if we need to drain socket?"
#endif
@@ -2127,32 +2228,6 @@ static bool PollRawUDPSockets( int nMaxTimeoutMS, bool bManualPoll )
if ( !DrainSocket( pSock ) )
goto exit_polling;
}
// On POSIX, check for draining the thread wake "socket"
#ifdef USE_POLL
{
pollfd &wake = s_vecPollFDs[ nSocketsToPoll ];
if ( wake.revents & POLLRDNORM )
{
Assert( wake.revents != -1 );
#if defined( WAKE_THREAD_USING_EVENT )
Assert( wake.fd == s_hEventWakeThread );
ClearWakeThreadEvent( wake, s_hEventWakeThread )
#elif defined( WAKE_THREAD_USING_SOCKET_PAIR )
Assert( wake.fd == s_hSockWakeThreadRead );
// Just eat one request for now.
// I think it's probably safe to eat all of them, but
// it's a small optimization and I don't want to debug
// it is that's not true.
char buf[8];
::recv( s_hSockWakeThreadRead, buf, sizeof(buf), 0 );
#else
#error "How did we wake up?"
#endif
}
}
#endif
#endif // USE_EPOLL, else
exit_polling:
@@ -2687,7 +2762,7 @@ static void SteamNetworkingThreadProc()
// for packets to arrive.
#if defined(_WIN32)
DbgVerify( SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST ) );
#elif defined(POSIX)
#elif IsPosix()
// This probably won't work on Linux, because you cannot raise thread priority
// without being root. But on some systems it works. So we try, and if it
// works, great.
@@ -3222,7 +3297,7 @@ bool BSteamNetworkingSocketsLowLevelAddRef( SteamNetworkingErrMsg &errMsg )
V_sprintf_safe( errMsg, "nn::socket::EventFd. Error code 0x%08x.", GetLastError() );
return false;
}
#elif IsPS5()
#elif IsPlaystation()
// No additional setup needed here
#else
{
@@ -3230,7 +3305,7 @@ bool BSteamNetworkingSocketsLowLevelAddRef( SteamNetworkingErrMsg &errMsg )
Assert( s_hSockWakeThreadWrite == INVALID_SOCKET );
int sockType = SOCK_DGRAM;
#ifdef LINUX
#if IsLinux()
sockType |= SOCK_CLOEXEC;
#endif
int sock[2];
@@ -3344,7 +3419,7 @@ void SteamNetworkingSocketsLowLevelDecRef()
nn::socket::Close( s_hEventWakeThread );
s_hEventWakeThread = INVALID_SOCKET;
}
#elif IsPS5()
#elif IsPlaystation()
// Nothing to do here
#else
if ( s_hSockWakeThreadRead != INVALID_SOCKET )
@@ -22,7 +22,7 @@
#undef min
#undef max
#endif
#if defined( POSIX ) && defined( STEAMNETWORKINGSOCKETS_ENABLE_WEBRTC )
#if IsPosix() && defined( STEAMNETWORKINGSOCKETS_ENABLE_WEBRTC )
#include <dlfcn.h>
#endif
@@ -309,8 +309,8 @@ void CSteamNetworkConnectionP2P::CheckInitICE()
return;
}
g_SteamNetworkingSockets_CreateICESessionFunc = (CreateICESession_t)::GetProcAddress( h, pszExportFunc );
#elif defined( POSIX )
#if defined( OSX ) || defined( IOS ) || defined( TVOS )
#elif IsPosix()
#if IsOSX() || defined( IOS ) || defined( TVOS )
static const char pszModule[] = "libsteamwebrtc.dylib";
#else
static const char pszModule[] = "libsteamwebrtc.so";
@@ -8,7 +8,7 @@
#ifdef STEAMNETWORKINGSOCKETS_ENABLE_ICE
#include "csteamnetworkingsockets.h"
#include "../steamnetworkingsockets_platform.h"
#include <tier0/platform_sockets.h>
#include "crypto.h"
// Put everything in a namespace, so we don't violate the one definition rule
+15 -14
View File
@@ -22,26 +22,30 @@ using namespace SteamNetworkingSocketsLib;
#include <assert.h>
#ifdef POSIX
#if IsPosix()
#include <unistd.h>
#if !IsPS5()
#if !IsPlaystation()
#include <signal.h>
#endif
#endif // POSIX
#ifdef LINUX
#if IsLinux()
#include <sys/ptrace.h>
#endif
#ifdef OSX
#if IsOSX()
#include <sys/sysctl.h>
#endif
#if IsPlaystation() && defined(_DEBUG)
// NDA material
#endif
bool Plat_IsInDebugSession()
{
#ifdef _WIN32
return (IsDebuggerPresent() != 0);
#elif defined(OSX)
#elif IsOSX()
int mib[4];
struct kinfo_proc info;
size_t size;
@@ -53,7 +57,7 @@ bool Plat_IsInDebugSession()
info.kp_proc.p_flag = 0;
sysctl(mib,4,&info,&size,NULL,0);
return ((info.kp_proc.p_flag & P_TRACED) == P_TRACED);
#elif defined(LINUX)
#elif IsLinux()
static FILE *fp;
if ( !fp )
{
@@ -80,15 +84,12 @@ bool Plat_IsInDebugSession()
}
}
return (nTracePid != 0);
#elif IsPS5()
// There might be a way to tell. Do we care?
#elif IsPlaystation()
// NDA material
#elif IsNintendoSwitch()
return false;
#elif defined( _PS3 )
#ifdef _CERT
return false;
#else
return snIsDebuggerPresent();
#endif
#else
#error "HALP"
#endif
}
+11 -3
View File
@@ -9,16 +9,20 @@
#else
#include <sys/time.h>
#include <unistd.h>
#if defined OSX
#if IsOSX()
#include <mach/mach.h>
#include <mach/mach_time.h>
#endif
#endif
#if IsNintendoSwitch()
// NDA material
#endif
BEGIN_TIER0_NAMESPACE
#if defined( _WIN32 ) || IsOSX()
#if defined( _WIN32 ) || IsOSX() || IsNintendoSwitch()
static uint64 g_TickFrequency;
static double g_TickFrequencyDouble;
static double g_TicksToUS;
@@ -59,6 +63,8 @@ static uint64 InitTicks()
g_TickFrequencyDouble = (double) TimebaseInfo.denom / (double) TimebaseInfo.numer * 1.0e9;
g_TickFrequency = (uint64)( g_TickFrequencyDouble + 0.5 );
g_TickBase = mach_absolute_time();
#elif IsNintendoSwitch()
// NDA material
#elif IsPosix()
// TickFrequency is constant since clock_gettime always returns nanoseconds
timespec TimeSpec;
@@ -68,7 +74,7 @@ static uint64 InitTicks()
#error Unknown platform
#endif
#if defined( _WIN32 ) || defined( OSX )
#if defined( _WIN32 ) || IsOSX() || IsNintendoSwitch()
g_TicksToUS = 1.0e6 / g_TickFrequencyDouble;
#endif
@@ -97,6 +103,8 @@ uint64 Plat_RelativeTicks()
}
#elif IsOSX()
Ticks = mach_absolute_time();
#elif IsNintendoSwitch()
// NDA material
#elif IsPosix()
timespec TimeSpec;
clock_gettime( CLOCK_MONOTONIC, &TimeSpec );
+7 -8
View File
@@ -3,14 +3,7 @@
#include <functional>
#include <tier1/netadr.h>
#ifdef WIN32
#include <ws2tcpip.h>
#undef SetPort
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include <tier0/platform_sockets.h>
#include <vstdlib/strtools.h>
#include "ipv6text.h"
@@ -456,6 +449,7 @@ bool CIPAddress::SetFromSockadr(const void *addr, size_t addr_size, uint16 *punP
return true;
}
#ifndef PLATFORM_NO_IPV6
case AF_INET6:
{
if ( addr_size < sizeof(sockaddr_in6) )
@@ -473,6 +467,7 @@ bool CIPAddress::SetFromSockadr(const void *addr, size_t addr_size, uint16 *punP
return true;
}
#endif
}
return false;
}
@@ -686,6 +681,7 @@ size_t CIPAndPort::ToSockadr(void *addr, size_t addr_size) const
}
break;
#ifndef PLATFORM_NO_IPV6
case k_EIPTypeV6:
{
if ( addr_size < sizeof(sockaddr_in6) )
@@ -702,6 +698,7 @@ size_t CIPAndPort::ToSockadr(void *addr, size_t addr_size) const
struct_size = sizeof(sockaddr_in6);
}
break;
#endif // #ifndef PLATFORM_NO_IPV6
}
return struct_size;
@@ -713,6 +710,7 @@ size_t CIPAndPort::ToSockadr(void *addr, size_t addr_size) const
//-----------------------------------------------------------------------------
// Purpose: Convert to an ipv6 sockaddr structure
//-----------------------------------------------------------------------------
#ifndef PLATFORM_NO_IPV6
void CIPAndPort::ToSockadrIPV6(void *addr, size_t addr_size) const
{
memset( addr, 0, addr_size);
@@ -728,3 +726,4 @@ void CIPAndPort::ToSockadrIPV6(void *addr, size_t addr_size) const
s->sin6_scope_id = m_unIPv6Scope;
s->sin6_port = BigWord( m_usPort );
}
#endif // PLATFORM_NO_IPV6
+1 -1
View File
@@ -8,7 +8,7 @@
#include "winlite.h"
#endif
#ifdef POSIX
#if IsPosix()
#include <unistd.h>
#endif