From 8ba70f2cdae0a0dd23eadca7b3f72331494e910e Mon Sep 17 00:00:00 2001 From: hgn Date: Sun, 7 Aug 2022 08:36:19 +0100 Subject: [PATCH] server --- src/vg/vg.h | 50 +-- src/vg/vg_io.h | 1 + src/vg/vg_m.h | 10 + src/vg/vg_platform.h | 9 - src/vg/vg_stdint.h | 15 + src/vg/vg_steam.h | 570 +++++++++++++++++++++++++++++++++++ src/vg/vg_steam_http.h | 162 ++++++++++ src/vg/vg_steam_networking.h | 521 ++++++++++++++++++++++++++++++++ 8 files changed, 1309 insertions(+), 29 deletions(-) create mode 100644 src/vg/vg_stdint.h create mode 100644 src/vg/vg_steam.h create mode 100644 src/vg/vg_steam_http.h create mode 100644 src/vg/vg_steam_networking.h diff --git a/src/vg/vg.h b/src/vg/vg.h index 31cfa80..a2a85fd 100644 --- a/src/vg/vg.h +++ b/src/vg/vg.h @@ -6,14 +6,19 @@ #include #include #include -#include #include #include #include #include -#include "glad/glad.h" -#include "glfw/glfw3.h" +#if defined(VG_SERVER) || defined(VG_TOOLS) + #define VG_NON_CLIENT +#endif + +#ifndef VG_SERVER +#include "../../dep/glad/glad.h" +#include "../../dep/glfw/glfw3.h" +#endif #define STB_DS_IMPLEMENTATION #include "stb/stb_ds.h" @@ -21,16 +26,25 @@ #define QOI_IMPLEMENTATION #include "phoboslab/qoi.h" -#include "vg/vg_platform.h" +#include "vg_stdint.h" +#include "vg_platform.h" void vg_register_exit( void( *funcptr )(void), const char *name ); void vg_exiterr( const char *strErr ); -#include "vg/vg_m.h" -#include "vg/vg_io.h" -#include "vg/vg_gldiag.h" +#include "vg_m.h" +#include "vg_io.h" -#ifndef VG_TOOLS +#ifdef VG_STEAM +//#include "vg_steamworks.h" +#include "vg_steam.h" +#endif + +#ifndef VG_NON_CLIENT +#include "vg_gldiag.h" +#endif + +#ifndef VG_NON_CLIENT /* Engine globals */ GLFWwindow* vg_window; @@ -57,18 +71,14 @@ double vg_time, vg_time_last, vg_time_delta; -#include "vg/vg_audio.h" -#include "vg/vg_shader.h" -#include "vg/vg_tex.h" -#include "vg/vg_input.h" -#include "vg/vg_ui.h" -#include "vg/vg_console.h" -#include "vg/vg_lines.h" -#include "vg/vg_debug.h" - -#ifdef VG_STEAM -#include "vg/vg_steamworks.h" -#endif +#include "vg_audio.h" +#include "vg_shader.h" +#include "vg_tex.h" +#include "vg_input.h" +#include "vg_ui.h" +#include "vg_console.h" +#include "vg_lines.h" +#include "vg_debug.h" #ifndef VG_RELEASE void vg_checkgl( const char *src_info ) diff --git a/src/vg/vg_io.h b/src/vg/vg_io.h index 376dfda..56e6219 100644 --- a/src/vg/vg_io.h +++ b/src/vg/vg_io.h @@ -45,6 +45,7 @@ static void NAME(const char *fmt, ...) \ VG_LOGX( vg_success, stdout, (KGRN "success" KWHT "| " KGRN) ) VG_LOGX( vg_info, stdout, (KNRM " info" KWHT "| " KNRM) ) +VG_LOGX( vg_log, stdout, (KWHT " log" KWHT "| " KWHT) ) VG_LOGX( vg_warn, stdout, (KYEL " warn" KWHT "| " KYEL) ) VG_LOGX( vg_error, stderr, (KRED " error" KWHT "| " KRED) ) diff --git a/src/vg/vg_m.h b/src/vg/vg_m.h index 8ecadbd..7e827a5 100644 --- a/src/vg/vg_m.h +++ b/src/vg/vg_m.h @@ -23,6 +23,11 @@ static inline float vg_signf( float a ) return a < 0.0f? -1.0f: 1.0f; } +static inline float vg_fractf( float a ) +{ + return a - floorf( a ); +} + static inline float vg_randf(void) { return (float)rand()/(float)(RAND_MAX); @@ -69,6 +74,11 @@ static inline void v2_copy( v2f a, v2f b ) b[0] = a[0]; b[1] = a[1]; } +static inline void v2_zero( v2f a ) +{ + a[0] = 0.f; a[1] = 0.f; +} + static inline void v2i_copy( v2i a, v2i b ) { b[0] = a[0]; b[1] = a[1]; diff --git a/src/vg/vg_platform.h b/src/vg/vg_platform.h index b0794ba..ca8b55a 100644 --- a/src/vg/vg_platform.h +++ b/src/vg/vg_platform.h @@ -3,15 +3,6 @@ /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */ -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; -typedef int8_t i8; -typedef int16_t i16; -typedef int32_t i32; -typedef int64_t i64; - typedef unsigned int uint; typedef int v2i[2]; diff --git a/src/vg/vg_stdint.h b/src/vg/vg_stdint.h new file mode 100644 index 0000000..7f9928a --- /dev/null +++ b/src/vg/vg_stdint.h @@ -0,0 +1,15 @@ +#ifndef VG_STDINT_H +#define VG_STDINT_H + +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; + +#endif /* VG_STDINT_H */ diff --git a/src/vg/vg_steam.h b/src/vg/vg_steam.h new file mode 100644 index 0000000..d6866b2 --- /dev/null +++ b/src/vg/vg_steam.h @@ -0,0 +1,570 @@ +#ifndef VG_STEAM_H +#define VG_STEAM_H + +#include "vg.h" + +#if defined(__linux__) || defined(__APPLE__) +/* + * The 32-bit version of gcc has the alignment requirement for u64 and double + * set to 4 meaning that even with #pragma pack(8) these types will only be + * four-byte aligned. The 64-bit version of gcc has the alignment requirement + * for these types set to 8 meaning that unless we use #pragma pack(4) our + * structures will get bigger. The 64-bit structure packing has to match the + * 32-bit structure packing for each platform. + */ + #define VALVE_CALLBACK_PACK_SMALL + #pragma pack( push, 4 ) +#else + #define VALVE_CALLBACK_PACK_LARGE + #pragma pack( push, 8 ) +#endif + +typedef i32 HSteamPipe; +typedef i32 HSteamUser; + +typedef int E_iCallBack_t; + +typedef u64 u64_steamid; +typedef u64 SteamAPICall_t; + +enum { k_iSteamUserCallbacks = 100 }; +enum { k_iSteamGameServerCallbacks = 200 }; +enum { k_iSteamFriendsCallbacks = 300 }; +enum { k_iSteamBillingCallbacks = 400 }; +enum { k_iSteamMatchmakingCallbacks = 500 }; +enum { k_iSteamContentServerCallbacks = 600 }; +enum { k_iSteamUtilsCallbacks = 700 }; +enum { k_iClientFriendsCallbacks = 800 }; +enum { k_iClientUserCallbacks = 900 }; +enum { k_iSteamAppsCallbacks = 1000 }; +enum { k_iSteamUserStatsCallbacks = 1100 }; +enum { k_iSteamNetworkingCallbacks = 1200 }; +enum { k_iSteamNetworkingSocketsCallbacks = 1220 }; +enum { k_iSteamNetworkingMessagesCallbacks = 1250 }; +enum { k_iSteamNetworkingUtilsCallbacks = 1280 }; +enum { k_iClientRemoteStorageCallbacks = 1300 }; +enum { k_iClientDepotBuilderCallbacks = 1400 }; +enum { k_iSteamGameServerItemsCallbacks = 1500 }; +enum { k_iClientUtilsCallbacks = 1600 }; +enum { k_iSteamGameCoordinatorCallbacks = 1700 }; +enum { k_iSteamGameServerStatsCallbacks = 1800 }; +enum { k_iSteam2AsyncCallbacks = 1900 }; +enum { k_iSteamGameStatsCallbacks = 2000 }; +enum { k_iClientHTTPCallbacks = 2100 }; +enum { k_iClientScreenshotsCallbacks = 2200 }; +enum { k_iSteamScreenshotsCallbacks = 2300 }; +enum { k_iClientAudioCallbacks = 2400 }; +enum { k_iClientUnifiedMessagesCallbacks = 2500 }; +enum { k_iSteamStreamLauncherCallbacks = 2600 }; +enum { k_iClientControllerCallbacks = 2700 }; +enum { k_iSteamControllerCallbacks = 2800 }; +enum { k_iClientParentalSettingsCallbacks = 2900 }; +enum { k_iClientDeviceAuthCallbacks = 3000 }; +enum { k_iClientNetworkDeviceManagerCallbacks = 3100 }; +enum { k_iClientMusicCallbacks = 3200 }; +enum { k_iClientRemoteClientManagerCallbacks = 3300 }; +enum { k_iClientUGCCallbacks = 3400 }; +enum { k_iSteamStreamClientCallbacks = 3500 }; +enum { k_IClientProductBuilderCallbacks = 3600 }; +enum { k_iClientShortcutsCallbacks = 3700 }; +enum { k_iClientRemoteControlManagerCallbacks = 3800 }; +enum { k_iSteamAppListCallbacks = 3900 }; +enum { k_iSteamMusicCallbacks = 4000 }; +enum { k_iSteamMusicRemoteCallbacks = 4100 }; +enum { k_iClientVRCallbacks = 4200 }; +enum { k_iClientGameNotificationCallbacks = 4300 }; +enum { k_iSteamGameNotificationCallbacks = 4400 }; +enum { k_iSteamHTMLSurfaceCallbacks = 4500 }; +enum { k_iClientVideoCallbacks = 4600 }; +enum { k_iClientInventoryCallbacks = 4700 }; +enum { k_iClientBluetoothManagerCallbacks = 4800 }; +enum { k_iClientSharedConnectionCallbacks = 4900 }; +enum { k_ISteamParentalSettingsCallbacks = 5000 }; +enum { k_iClientShaderCallbacks = 5100 }; +enum { k_iSteamGameSearchCallbacks = 5200 }; +enum { k_iSteamPartiesCallbacks = 5300 }; +enum { k_iClientPartiesCallbacks = 5400 }; +enum { k_iSteamSTARCallbacks = 5500 }; +enum { k_iClientSTARCallbacks = 5600 }; +enum { k_iSteamRemotePlayCallbacks = 5700 }; +enum { k_iClientCompatCallbacks = 5800 }; +enum { k_iSteamChatCallbacks = 5900 }; + +// General result codes +typedef enum EResult +{ + k_EResultNone = 0, // no result + k_EResultOK = 1, // success + k_EResultFail = 2, // generic failure + k_EResultNoConnection = 3, // no/failed network connection +// k_EResultNoConnectionRetry = 4, // OBSOLETE - removed + k_EResultInvalidPassword = 5, // password/ticket is invalid + k_EResultLoggedInElsewhere = 6, // same user logged in elsewhere + k_EResultInvalidProtocolVer = 7, // protocol version is incorrect + k_EResultInvalidParam = 8, // a parameter is incorrect + k_EResultFileNotFound = 9, // file was not found + k_EResultBusy = 10, // called method busy - action not taken + k_EResultInvalidState = 11, // called object was in an invalid state + k_EResultInvalidName = 12, // name is invalid + k_EResultInvalidEmail = 13, // email is invalid + k_EResultDuplicateName = 14, // name is not unique + k_EResultAccessDenied = 15, // access is denied + k_EResultTimeout = 16, // operation timed out + k_EResultBanned = 17, // VAC2 banned + k_EResultAccountNotFound = 18, // account not found + k_EResultInvalidSteamID = 19, // steamID is invalid + k_EResultServiceUnavailable = 20,// The requested service is currently + // unavailable + k_EResultNotLoggedOn = 21, // The user is not logged on + k_EResultPending = 22, // Request is pending (may be in process, or + // waiting on third party) + k_EResultEncryptionFailure = 23, // Encryption or Decryption failed + k_EResultInsufficientPrivilege = 24,// Insufficient privilege + k_EResultLimitExceeded = 25, // Too much of a good thing + k_EResultRevoked = 26, // Access has been revoked (used for revoked + // guest passes) + k_EResultExpired = 27, // License/Guest pass the user is trying to + // access is expired + k_EResultAlreadyRedeemed = 28, // Guest pass has already been redeemed by + // account, cannot be acked again + k_EResultDuplicateRequest = 29, // The request is a duplicate and the action + // has already occurred in the past, ignored + // this time + k_EResultAlreadyOwned = 30, // All the games in this guest pass + // redemption request are already owned by + // the user + k_EResultIPNotFound = 31, // IP address not found + k_EResultPersistFailed = 32, // failed to write change to the data store + k_EResultLockingFailed = 33, // failed to acquire access lock for this + // operation + k_EResultLogonSessionReplaced = 34, + k_EResultConnectFailed = 35, + k_EResultHandshakeFailed = 36, + k_EResultIOFailure = 37, + k_EResultRemoteDisconnect = 38, + k_EResultShoppingCartNotFound = 39, // failed to find the shopping cart + // requested + k_EResultBlocked = 40, // a user didn't allow it + k_EResultIgnored = 41, // target is ignoring sender + k_EResultNoMatch = 42, // nothing matching the request found + k_EResultAccountDisabled = 43, + k_EResultServiceReadOnly = 44, // this service is not accepting content + // changes right now + k_EResultAccountNotFeatured = 45, // account doesn't have value, so this + // feature isn't available + k_EResultAdministratorOK = 46, // allowed to take this action, but only + // because requester is admin + k_EResultContentVersion = 47, // A Version mismatch in content + // transmitted within the Steam protocol. + k_EResultTryAnotherCM = 48, // The current CM can't service the user + // making a request, user should try + // another. + k_EResultPasswordRequiredToKickSession = 49, // You are already logged in + // elsewhere, this cached credential + // login has failed. + k_EResultAlreadyLoggedInElsewhere = 50, // You are already logged in + // elsewhere, you must wait + k_EResultSuspended = 51, // Long running operation (content download) + // suspended/paused + k_EResultCancelled = 52, // Operation canceled (typically by user: + // content download) + k_EResultDataCorruption = 53, // Operation canceled because data is ill + // formed or unrecoverable + k_EResultDiskFull = 54, // Operation canceled - not enough disk space. + k_EResultRemoteCallFailed = 55, // an remote call or IPC call failed + k_EResultPasswordUnset = 56, // Password could not be verified as it's + // unset server side + k_EResultExternalAccountUnlinked = 57, // External account (PSN, Facebook...) + // is not linked to a Steam account + k_EResultPSNTicketInvalid = 58, // PSN ticket was invalid + k_EResultExternalAccountAlreadyLinked = 59, // External account (PSN, + // Facebook...) is already linked to some other account, + // must explicitly request to replace/delete the link first + k_EResultRemoteFileConflict = 60, // The sync cannot resume due to a conflict + // between the local and remote files + k_EResultIllegalPassword = 61, // The requested new password is not legal + k_EResultSameAsPreviousValue = 62,// new value is the same as the old one ( + // secret question and answer ) + k_EResultAccountLogonDenied = 63, // account login denied due to 2nd factor + // authentication failure + k_EResultCannotUseOldPassword = 64, // The requested new password is not + // legal + k_EResultInvalidLoginAuthCode = 65, // account login denied due to auth code + // invalid + k_EResultAccountLogonDeniedNoMail = 66, // account login denied due to 2nd + // factor auth failure - and no mail + // has been sent + k_EResultHardwareNotCapableOfIPT = 67, + k_EResultIPTInitError = 68, + k_EResultParentalControlRestricted = 69,// operation failed due to parental + // control restrictions for current + // user + k_EResultFacebookQueryError = 70, // Facebook query returned an error + k_EResultExpiredLoginAuthCode = 71, // account login denied due to auth + // code expired + k_EResultIPLoginRestrictionFailed = 72, + k_EResultAccountLockedDown = 73, + k_EResultAccountLogonDeniedVerifiedEmailRequired = 74, + k_EResultNoMatchingURL = 75, + k_EResultBadResponse = 76, // parse failure, missing field, etc. + k_EResultRequirePasswordReEntry = 77, // The user cannot complete the action + // until they re-enter their password + k_EResultValueOutOfRange = 78, // the value entered is outside the + // acceptable range + k_EResultUnexpectedError = 79, // something happened that we didn't expect + // to ever happen + k_EResultDisabled = 80, // The requested service has been configured + // to be unavailable + k_EResultInvalidCEGSubmission = 81, // The set of files submitted to the CEG + // server are not valid ! + k_EResultRestrictedDevice = 82, // The device being used is not allowed + // to perform this action + k_EResultRegionLocked = 83, // The action could not be complete + // because it is region restricted + k_EResultRateLimitExceeded = 84, // Temporary rate limit exceeded, try + // again later, different from + // k_EResultLimitExceeded which may be + // permanent + k_EResultAccountLoginDeniedNeedTwoFactor = 85, // Need two-factor code to + // login + k_EResultItemDeleted = 86, // The thing we're trying to access has been + // deleted + k_EResultAccountLoginDeniedThrottle = 87, // login attempt failed, try to + // throttle response to possible + // attacker + k_EResultTwoFactorCodeMismatch = 88, // two factor code mismatch + k_EResultTwoFactorActivationCodeMismatch = 89, // activation code for + // two-factor didn't match + k_EResultAccountAssociatedToMultiplePartners = 90, // account has been + // associated with multiple partners + k_EResultNotModified = 91, // data not modified + k_EResultNoMobileDevice = 92, // the account does not have a mobile + // device associated with it + k_EResultTimeNotSynced = 93, // the time presented is out of range or + // tolerance + k_EResultSmsCodeFailed = 94, // SMS code failure (no match, none pending, + // etc.) + k_EResultAccountLimitExceeded = 95, // Too many accounts access this resource + k_EResultAccountActivityLimitExceeded = 96,// Too many changes to + // this account + k_EResultPhoneActivityLimitExceeded = 97, // Too many changes to this phone + k_EResultRefundToWallet = 98, // Cannot refund to payment method, must use + // wallet + k_EResultEmailSendFailure = 99, // Cannot send an email + k_EResultNotSettled = 100, // Can't perform operation till payment + // has settled + k_EResultNeedCaptcha = 101,// Needs to provide a valid captcha + k_EResultGSLTDenied = 102, // a game server login token owned by this token's + // owner has been banned + k_EResultGSOwnerDenied = 103, // game server owner is denied for other reason + // (account lock, community ban, vac ban, missing phone) + k_EResultInvalidItemType = 104,// the type of thing we were requested to act + // on is invalid + k_EResultIPBanned = 105,// the ip address has been banned from taking this + // action + k_EResultGSLTExpired = 106,// this token has expired from disuse; can be + // reset for use + k_EResultInsufficientFunds = 107,// user doesn't have enough wallet funds to + // complete the action + k_EResultTooManyPending = 108, // There are too many of this thing pending + // already + k_EResultNoSiteLicensesFound = 109, // No site licenses found + k_EResultWGNetworkSendExceeded = 110,// the WG couldn't send a response + // because we exceeded max network send size + k_EResultAccountNotFriends = 111, // the user is not mutually friends + k_EResultLimitedUserAccount = 112,// the user is limited + k_EResultCantRemoveItem = 113, // item can't be removed + k_EResultAccountDeleted = 114, // account has been deleted + k_EResultExistingUserCancelledLicense = 115, + // A license for this already exists, but cancelled + k_EResultCommunityCooldown = 116, // access is denied because of a + // community cooldown (probably from support profile data resets) + k_EResultNoLauncherSpecified = 117, // No launcher was specified, but a + // launcher was needed to choose correct realm for operation. + k_EResultMustAgreeToSSA = 118,// User must agree to china SSA or global SSA + // before login + k_EResultLauncherMigrated = 119, // The specified launcher type is no longer + // supported; the user should be directed elsewhere + k_EResultSteamRealmMismatch = 120, // The user's realm does not match the + // realm of the requested resource + k_EResultInvalidSignature = 121, // signature check did not match + k_EResultParseFailure = 122, // Failed to parse input + k_EResultNoVerifiedPhone = 123, // account does not have a verified phone + // number +} EResult; + +typedef struct { + + HSteamUser m_hSteamUser; // Specific user to whom this callback applies. + int m_iCallback; + u8 *m_pubParam; // Points to the callback structure + int m_cubParam; // Size of the data pointed to by m_pubParam + +} CallbackMsg_t; + +typedef struct { + + SteamAPICall_t m_hAsyncCall; + int m_iCallback; + u32 m_cubParam; + +} SteamAPICallCompleted_t; + +enum { k_iSteamAPICallCompleted = k_iSteamUtilsCallbacks + 3 }; + +// Steam universes. Each universe is a self-contained Steam instance. +typedef enum { + k_EUniverseInvalid = 0, + k_EUniversePublic = 1, + k_EUniverseBeta = 2, + k_EUniverseInternal = 3, + k_EUniverseDev = 4, + // k_EUniverseRC = 5, // no such universe anymore + k_EUniverseMax +} EUniverse_t; + +struct SteamIDComponent_t +{ +#ifdef VALVE_BIG_ENDIAN + EUniverse_t m_EUniverse : 8 + unsigned int m_EAccountType : 4; + unsigned int m_unAccountInstance : 20; + u32 m_unAccountID : 32; +#else + u32 m_unAccountID : 32; + unsigned int m_unAccountInstance : 20; + unsigned int m_EAccountType : 4; + EUniverse_t m_EUniverse : 8; +#endif +}; + +typedef struct +{ + // 64 bits total + union + { + struct SteamIDComponent_t m_comp; + u64 m_unAll64Bits; + }; +} +CSteamID; + +typedef struct GameID_t +{ +#ifdef VALVE_BIG_ENDIAN + unsigned int m_nModID : 32; + unsigned int m_nType : 8; + unsigned int m_nAppID : 24; +#else + unsigned int m_nAppID : 24; + unsigned int m_nType : 8; + unsigned int m_nModID : 32; +#endif +} CGameID; + +#pragma pack( pop ) + +/* + * Standard login + * ============================================================================= + */ + +int SteamAPI_RestartAppIfNecessary( u32 unOwnAppID ); +int SteamAPI_Init(void); +void SteamAPI_Shutdown(void); + +/* + * Server mode login + * ============================================================================= + */ + +typedef enum EServerMode EServerMode; +enum EServerMode +{ + eServerModeInvalid = 0, + eServerModeNoAuthentication = 1, + eServerModeAuthentication = 2, + eServerModeAuthenticationAndSecure = 3, +}; + +int SteamInternal_GameServer_Init( u32 unIP, u16 usLegacySteamPort, + u16 usGamePort, u16 usQueryPort, + EServerMode eServerMode, + const char *pchVersionString ); + +/* Initialize SteamGameServer client and interface objects, and set server + * properties which may not be changed. + * After calling this function, you should set any additional server parameters, + * and then call ISteamGameServer::LogOnAnonymous() or ISteamGameServer::LogOn() + * + * - unIP will usually be zero. If you are on a machine with multiple IP + * addresses, you can pass a non-zero value here and the relevant sockets will + * be bound to that IP. This can be used to ensure that the IP you desire is + * the one used in the server browser. + * - usGamePort is the port that clients will connect to for gameplay. You will + * usually open up your own socket bound to this port. + * - usQueryPort is the port that will manage server browser related duties and + * info pings from clients. If you pass STEAMGAMESERVER_QUERY_PORT_SHARED for + * usQueryPort, then it will use "GameSocketShare" mode, which means that the + * game is responsible for sending and receiving UDP packets for the master + * server updater. (See ISteamGameServer::HandleIncomingPacket and + * ISteamGameServer::GetNextOutgoingPacket.) + * - The version string should be in the form x.x.x.x, and is used by the master + * server to detect when the server is out of date. (Only servers with the + * latest version will be listed.) + */ +int SteamGameServer_Init( u32 unIP, u16 usGamePort, u16 usQueryPort, + EServerMode eServerMode, + const char *pchVersionString ) +{ + return SteamInternal_GameServer_Init( unIP, 0, usGamePort, usQueryPort, + eServerMode, pchVersionString ); +} + +void SteamGameServer_Shutdown(void); + +int SteamGameServer_BSecure(void); +u64 SteamGameServer_GetSteamID(void); + +/* + * Async callbacks + * ============================================================================= + */ +typedef struct steam_async steam_async; +struct steam_async +{ + SteamAPICall_t id; + void *data; + + void (*p_handler)( void *result, void *userdata ); +} +static steam_async_trackers[32]; +static u32 steam_async_track_count; + +steam_async *steam_new_async(void) +{ + if( steam_async_track_count == vg_list_size(steam_async_trackers) ) + { + vg_error( "Maximum concurrent API calls exceeded (%u)\n", + steam_async_track_count ); + return NULL; + } + + return &steam_async_trackers[ steam_async_track_count ++ ]; +} + +/* + * Event loop + */ +HSteamPipe SteamAPI_GetHSteamPipe(void); +HSteamPipe SteamGameServer_GetHSteamPipe(void); +HSteamUser SteamAPI_GetHSteamUser(void); +void SteamAPI_ManualDispatch_Init(void); +void SteamAPI_ManualDispatch_RunFrame( HSteamPipe hSteamPipe ); +int SteamAPI_ManualDispatch_GetNextCallback( HSteamPipe hSteamPipe, + CallbackMsg_t *pCallbackMsg ); +void SteamAPI_ManualDispatch_FreeLastCallback( HSteamPipe hSteamPipe ); +int SteamAPI_ManualDispatch_GetAPICallResult( HSteamPipe hSteamPipe, + SteamAPICall_t hSteamAPICall, void *pCallback, int cubCallback, + int iCallbackExpected, int *pbFailed ); + +void SteamAPI_ReleaseCurrentThreadMemory(void); + +static void steamworks_event_loop( HSteamPipe pipe, + void(*callback_handler)(CallbackMsg_t *msg) ) +{ + SteamAPI_ManualDispatch_RunFrame( pipe ); + CallbackMsg_t callback; + + while( SteamAPI_ManualDispatch_GetNextCallback( pipe, &callback ) ) + { + vg_log( "steamworks_event::callback( %i )\n", callback.m_iCallback ); + + /* Check for dispatching API call results */ + if( callback.m_iCallback == k_iSteamAPICallCompleted ) + { + SteamAPICallCompleted_t *pCallCompleted = + (SteamAPICallCompleted_t *)callback.m_pubParam; + + void *pTmpCallResult = malloc( pCallCompleted->m_cubParam ); + int bFailed; + + if( SteamAPI_ManualDispatch_GetAPICallResult( + pipe, + pCallCompleted->m_hAsyncCall, + pTmpCallResult, + pCallCompleted->m_cubParam, + pCallCompleted->m_iCallback, + &bFailed ) + ) + { + /* + * Dispatch the call result to the registered handler(s) for the + * call identified by pCallCompleted->m_hAsyncCall + */ + + vg_info( "steamworks_event::api_call_completed( %lu )\n", + pCallCompleted->m_hAsyncCall ); + + int j=0; + for( int i=0; im_hAsyncCall ) + { + steam_async_trackers[j ++] = steam_async_trackers[i]; + } + else + { + steam_async *pasync = &steam_async_trackers[j]; + pasync->p_handler( pTmpCallResult, pasync->data ); + } + } + + if( steam_async_track_count == j ) + { + vg_error( "No tracker was register for API call\n" ); + } + + steam_async_track_count = j; + } + else + { +#if 0 + typedef enum ESteamAPICallFailure + { + k_ESteamAPICallFailureNone = -1, + k_ESteamAPICallFailureSteamGone = 0, + k_ESteamAPICallFailureNetworkFailure = 1, + k_ESteamAPICallFailureInvalidHandle = 2, + k_ESteamAPICallFailureMismatchedCallback = 3, + } + + ESteamAPICallFailure; + ESteamAPICallFailure fail_why = + SteamAPI_ISteamUtils_GetAPICallFailureReason( + steam_api_classes.utils, pCallCompleted->m_hAsyncCall ); + + vg_error( "steamworks_event: error getting call result on" + "%lu (code %d)\n", + pCallCompleted->m_hAsyncCall, fail_why ); +#endif + } + + free( pTmpCallResult ); + } + else + { + /* + * Look at callback.m_iCallback to see what kind of callback it is, + * and dispatch to appropriate handler(s) + * void *data = callback.m_pubParam; + */ + + callback_handler(&callback); + } + + SteamAPI_ManualDispatch_FreeLastCallback( pipe ); + } +} + +#endif /* VG_STEAM_H */ diff --git a/src/vg/vg_steam_http.h b/src/vg/vg_steam_http.h new file mode 100644 index 0000000..f4b6bd1 --- /dev/null +++ b/src/vg/vg_steam_http.h @@ -0,0 +1,162 @@ +#ifndef VG_STEAM_HTTP_H +#define VG_STEAM_HTTP_H + +#include "vg_steam.h" + +/* + * HTTP Status codes that the server can send in response to a request, see + * rfc2616 section 10.3 for descriptions of each of these. + */ +typedef enum EHTTPStatusCode +{ + /* Invalid status code (this isn't defined in HTTP, used to indicate unset + * in our code) */ + + k_EHTTPStatusCodeInvalid = 0, + + /* Informational codes */ + k_EHTTPStatusCode100Continue = 100, + k_EHTTPStatusCode101SwitchingProtocols = 101, + + /* Success codes */ + k_EHTTPStatusCode200OK = 200, + k_EHTTPStatusCode201Created = 201, + k_EHTTPStatusCode202Accepted = 202, + k_EHTTPStatusCode203NonAuthoritative = 203, + k_EHTTPStatusCode204NoContent = 204, + k_EHTTPStatusCode205ResetContent = 205, + k_EHTTPStatusCode206PartialContent = 206, + + /* Redirection codes */ + k_EHTTPStatusCode300MultipleChoices = 300, + k_EHTTPStatusCode301MovedPermanently = 301, + k_EHTTPStatusCode302Found = 302, + k_EHTTPStatusCode303SeeOther = 303, + k_EHTTPStatusCode304NotModified = 304, + k_EHTTPStatusCode305UseProxy = 305, + + /* (used in old HTTP spec, now unused in 1.1) + k_EHTTPStatusCode306Unused = 306, + */ + + k_EHTTPStatusCode307TemporaryRedirect = 307, + + /* Error codes */ + k_EHTTPStatusCode400BadRequest = 400, + + /* + * You probably want 403 or something else. 401 implies you're sending a + * WWW-Authenticate header and the client can sent an Authorization header in + * response. + */ + k_EHTTPStatusCode401Unauthorized = 401, + + /* This is reserved for future HTTP specs, not really supported by clients */ + k_EHTTPStatusCode402PaymentRequired = 402, + k_EHTTPStatusCode403Forbidden = 403, + k_EHTTPStatusCode404NotFound = 404, + k_EHTTPStatusCode405MethodNotAllowed = 405, + k_EHTTPStatusCode406NotAcceptable = 406, + k_EHTTPStatusCode407ProxyAuthRequired = 407, + k_EHTTPStatusCode408RequestTimeout = 408, + k_EHTTPStatusCode409Conflict = 409, + k_EHTTPStatusCode410Gone = 410, + k_EHTTPStatusCode411LengthRequired = 411, + k_EHTTPStatusCode412PreconditionFailed = 412, + k_EHTTPStatusCode413RequestEntityTooLarge=413, + k_EHTTPStatusCode414RequestURITooLong = 414, + k_EHTTPStatusCode415UnsupportedMediaType =415, + k_EHTTPStatusCode416RequestedRangeNotSatisfiable = 416, + k_EHTTPStatusCode417ExpectationFailed = 417, + + /* 418 is reserved, so we'll use it to mean unknown */ + k_EHTTPStatusCode4xxUnknown = 418, + k_EHTTPStatusCode429TooManyRequests = 429, + k_EHTTPStatusCode444ConnectionClosed = 444, /* nginx only? */ + + /* Server error codes */ + k_EHTTPStatusCode500InternalServerError = 500, + k_EHTTPStatusCode501NotImplemented = 501, + k_EHTTPStatusCode502BadGateway = 502, + k_EHTTPStatusCode503ServiceUnavailable = 503, + k_EHTTPStatusCode504GatewayTimeout = 504, + k_EHTTPStatusCode505HTTPVersionNotSupported = 505, + k_EHTTPStatusCode5xxUnknown = 599, +} +EHTTPStatusCode; + +enum EHTTPMethod +{ + k_EHTTPMethodInvalid = 0, + k_EHTTPMethodGET, + k_EHTTPMethodHEAD, + k_EHTTPMethodPOST, + k_EHTTPMethodPUT, + k_EHTTPMethodDELETE, + k_EHTTPMethodOPTIONS, + k_EHTTPMethodPATCH, + + /* The remaining HTTP methods are not yet supported, per rfc2616 section + * 5.1.1 only GET and HEAD are required for a compliant general purpose + * server. We'll likely add more as we find uses for them. + * + * k_EHTTPMethodTRACE, + * k_EHTTPMethodCONNECT + */ +}; +typedef enum EHTTPMethod EHTTPMethod; + +typedef u32 HTTPRequestHandle; + +#ifdef VALVE_CALLBACK_PACK_SMALL + #pragma pack( push, 4 ) +#else + #pragma pack( push, 8 ) +#endif + +typedef struct HTTPRequestCompleted_t HTTPRequestCompleted_t; +struct HTTPRequestCompleted_t +{ + HTTPRequestHandle m_hRequest; + u64 m_ulContextValue; + int m_bRequestSuccessful; + EHTTPStatusCode m_eStatusCode; + u32 m_unBodySize; +}; + +#pragma pack(pop) + +/* + * Methods + * TODO: Copy steamworks documentation here + */ + +void *SteamAPI_SteamGameServerHTTP_v003(void); +void *SteamAPI_SteamGameServerHTTP(void) +{ + return SteamAPI_SteamGameServerHTTP_v003(); +} + +/* Interfaces */ +void *SteamAPI_SteamHTTP_v003(void); +void *SteamAPI_SteamHTTP(void) +{ + return SteamAPI_SteamHTTP_v003(); +} + +HTTPRequestHandle SteamAPI_ISteamHTTP_CreateHTTPRequest( + void *self, EHTTPMethod eHTTPRequestMethod, const char *pchAbsoluteURL ); + +int SteamAPI_ISteamHTTP_SendHTTPRequest( void* self, HTTPRequestHandle hRequest, + SteamAPICall_t * pCallHandle ); + +int SteamAPI_ISteamHTTP_ReleaseHTTPRequest( void *self, + HTTPRequestHandle hRequest ); + +int SteamAPI_ISteamHTTP_GetHTTPResponseBodySize( void *self, + HTTPRequestHandle hRequest, u32 *unBodySize ); + +int SteamAPI_ISteamHTTP_GetHTTPResponseBodyData( void* self, + HTTPRequestHandle hRequest, u8 *pBodyDataBuffer, u32 unBufferSize ); + +#endif /* VG_STEAM_HTTP_H */ diff --git a/src/vg/vg_steam_networking.h b/src/vg/vg_steam_networking.h new file mode 100644 index 0000000..494e846 --- /dev/null +++ b/src/vg/vg_steam_networking.h @@ -0,0 +1,521 @@ +#ifndef VG_STEAM_NETWORKING_H +#define VG_STEAM_NETWORKING_H + +#include "vg_steam.h" + +#ifdef VALVE_CALLBACK_PACK_SMALL + #pragma pack(push,4) +#else + #pragma pack(push,8) +#endif + +typedef enum ESteamNetworkingConfigScope ESteamNetworkingConfigScope; +enum ESteamNetworkingConfigScope +{ + k_ESteamNetworkingConfig_Global = 1, + k_ESteamNetworkingConfig_SocketsInterface = 2, + k_ESteamNetworkingConfig_ListenSocket = 3, + k_ESteamNetworkingConfig_Connection = 4, + k_ESteamNetworkingConfigScope__Force32Bit = 0x7fffffff +}; + +typedef enum ESteamNetworkingConfigDataType ESteamNetworkingConfigDataType; +enum ESteamNetworkingConfigDataType +{ + k_ESteamNetworkingConfig_Int32 = 1, + k_ESteamNetworkingConfig_Int64 = 2, + k_ESteamNetworkingConfig_Float = 3, + k_ESteamNetworkingConfig_String = 4, + k_ESteamNetworkingConfig_Ptr = 5, + + k_ESteamNetworkingConfigDataType__Force32Bit = 0x7fffffff +}; + +typedef enum ESteamNetworkingConfigValue ESteamNetworkingConfigValue; +enum ESteamNetworkingConfigValue +{ + k_ESteamNetworkingConfig_Invalid = 0, + k_ESteamNetworkingConfig_TimeoutInitial = 24, + k_ESteamNetworkingConfig_TimeoutConnected = 25, + k_ESteamNetworkingConfig_SendBufferSize = 9, + k_ESteamNetworkingConfig_ConnectionUserData = 40, + k_ESteamNetworkingConfig_SendRateMin = 10, + k_ESteamNetworkingConfig_SendRateMax = 11, + k_ESteamNetworkingConfig_NagleTime = 12, + k_ESteamNetworkingConfig_IP_AllowWithoutAuth = 23, + k_ESteamNetworkingConfig_MTU_PacketSize = 32, + k_ESteamNetworkingConfig_MTU_DataSize = 33, + k_ESteamNetworkingConfig_Unencrypted = 34, + k_ESteamNetworkingConfig_SymmetricConnect = 37, + k_ESteamNetworkingConfig_LocalVirtualPort = 38, + k_ESteamNetworkingConfig_DualWifi_Enable = 39, + k_ESteamNetworkingConfig_EnableDiagnosticsUI = 46, + k_ESteamNetworkingConfig_FakePacketLoss_Send = 2, + k_ESteamNetworkingConfig_FakePacketLoss_Recv = 3, + k_ESteamNetworkingConfig_FakePacketLag_Send = 4, + k_ESteamNetworkingConfig_FakePacketLag_Recv = 5, + k_ESteamNetworkingConfig_FakePacketReorder_Send = 6, + k_ESteamNetworkingConfig_FakePacketReorder_Recv = 7, + k_ESteamNetworkingConfig_FakePacketReorder_Time = 8, + k_ESteamNetworkingConfig_FakePacketDup_Send = 26, + k_ESteamNetworkingConfig_FakePacketDup_Recv = 27, + k_ESteamNetworkingConfig_FakePacketDup_TimeMax = 28, + k_ESteamNetworkingConfig_PacketTraceMaxBytes = 41, + k_ESteamNetworkingConfig_FakeRateLimit_Send_Rate = 42, + k_ESteamNetworkingConfig_FakeRateLimit_Send_Burst = 43, + k_ESteamNetworkingConfig_FakeRateLimit_Recv_Rate = 44, + k_ESteamNetworkingConfig_FakeRateLimit_Recv_Burst = 45, + k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged = 201, + k_ESteamNetworkingConfig_Callback_AuthStatusChanged = 202, + k_ESteamNetworkingConfig_Callback_RelayNetworkStatusChanged = 203, + k_ESteamNetworkingConfig_Callback_MessagesSessionRequest = 204, + k_ESteamNetworkingConfig_Callback_MessagesSessionFailed = 205, + k_ESteamNetworkingConfig_Callback_CreateConnectionSignaling = 206, + k_ESteamNetworkingConfig_Callback_FakeIPResult = 207, + k_ESteamNetworkingConfig_P2P_STUN_ServerList = 103, + k_ESteamNetworkingConfig_P2P_Transport_ICE_Enable = 104, + k_ESteamNetworkingConfig_P2P_Transport_ICE_Penalty = 105, + k_ESteamNetworkingConfig_P2P_Transport_SDR_Penalty = 106, + k_ESteamNetworkingConfig_SDRClient_ConsecutitivePingTimeoutsFailInitial = 19, + k_ESteamNetworkingConfig_SDRClient_ConsecutitivePingTimeoutsFail = 20, + k_ESteamNetworkingConfig_SDRClient_MinPingsBeforePingAccurate = 21, + k_ESteamNetworkingConfig_SDRClient_SingleSocket = 22, + k_ESteamNetworkingConfig_SDRClient_ForceRelayCluster = 29, + k_ESteamNetworkingConfig_SDRClient_DebugTicketAddress = 30, + k_ESteamNetworkingConfig_SDRClient_ForceProxyAddr = 31, + k_ESteamNetworkingConfig_SDRClient_FakeClusterPing = 36, + k_ESteamNetworkingConfig_LogLevel_AckRTT = 13, + k_ESteamNetworkingConfig_LogLevel_PacketDecode = 14, + k_ESteamNetworkingConfig_LogLevel_Message = 15, + k_ESteamNetworkingConfig_LogLevel_PacketGaps = 16, + k_ESteamNetworkingConfig_LogLevel_P2PRendezvous = 17, + k_ESteamNetworkingConfig_LogLevel_SDRRelayPings = 18, + k_ESteamNetworkingConfig_DELETED_EnumerateDevVars = 35, + k_ESteamNetworkingConfigValue__Force32Bit = 0x7fffffff +}; + + +typedef enum ESteamNetworkingConnectionState ESteamNetworkingConnectionState; +enum ESteamNetworkingConnectionState +{ + k_ESteamNetworkingConnectionState_None = 0, + k_ESteamNetworkingConnectionState_Connecting = 1, + k_ESteamNetworkingConnectionState_FindingRoute = 2, + k_ESteamNetworkingConnectionState_Connected = 3, + k_ESteamNetworkingConnectionState_ClosedByPeer = 4, + k_ESteamNetworkingConnectionState_ProblemDetectedLocally = 5, + k_ESteamNetworkingConnectionState_FinWait = -1, + k_ESteamNetworkingConnectionState_Linger = -2, + k_ESteamNetworkingConnectionState_Dead = -3, + k_ESteamNetworkingConnectionState__Force32Bit = 0x7fffffff +}; + +typedef enum ESteamNetConnectionEnd ESteamNetConnectionEnd; +enum ESteamNetConnectionEnd +{ + k_ESteamNetConnectionEnd_Invalid = 0, + k_ESteamNetConnectionEnd_App_Min = 1000, + k_ESteamNetConnectionEnd_App_Generic = k_ESteamNetConnectionEnd_App_Min, + k_ESteamNetConnectionEnd_App_Max = 1999, + k_ESteamNetConnectionEnd_AppException_Min = 2000, + k_ESteamNetConnectionEnd_AppException_Generic = + k_ESteamNetConnectionEnd_AppException_Min, + k_ESteamNetConnectionEnd_AppException_Max = 2999, + k_ESteamNetConnectionEnd_Local_Min = 3000, + k_ESteamNetConnectionEnd_Local_OfflineMode = 3001, + k_ESteamNetConnectionEnd_Local_ManyRelayConnectivity = 3002, + k_ESteamNetConnectionEnd_Local_HostedServerPrimaryRelay = 3003, + k_ESteamNetConnectionEnd_Local_NetworkConfig = 3004, + k_ESteamNetConnectionEnd_Local_Rights = 3005, + k_ESteamNetConnectionEnd_Local_P2P_ICE_NoPublicAddresses = 3006, + + k_ESteamNetConnectionEnd_Local_Max = 3999, + k_ESteamNetConnectionEnd_Remote_Min = 4000, + k_ESteamNetConnectionEnd_Remote_Timeout = 4001, + k_ESteamNetConnectionEnd_Remote_BadCrypt = 4002, + k_ESteamNetConnectionEnd_Remote_BadCert = 4003, + k_ESteamNetConnectionEnd_Remote_BadProtocolVersion = 4006, + k_ESteamNetConnectionEnd_Remote_P2P_ICE_NoPublicAddresses = 4007, + + k_ESteamNetConnectionEnd_Remote_Max = 4999, + + k_ESteamNetConnectionEnd_Misc_Min = 5000, + k_ESteamNetConnectionEnd_Misc_Generic = 5001, + k_ESteamNetConnectionEnd_Misc_InternalError = 5002, + k_ESteamNetConnectionEnd_Misc_Timeout = 5003, + k_ESteamNetConnectionEnd_Misc_SteamConnectivity = 5005, + k_ESteamNetConnectionEnd_Misc_NoRelaySessionsToClient = 5006, + k_ESteamNetConnectionEnd_Misc_P2P_Rendezvous = 5008, + k_ESteamNetConnectionEnd_Misc_P2P_NAT_Firewall = 5009, + k_ESteamNetConnectionEnd_Misc_PeerSentNoConnection = 5010, + + k_ESteamNetConnectionEnd_Misc_Max = 5999, + k_ESteamNetConnectionEnd__Force32Bit = 0x7fffffff +}; + +typedef enum ESteamNetworkingIdentityType ESteamNetworkingIdentityType; +enum ESteamNetworkingIdentityType +{ + k_ESteamNetworkingIdentityType_Invalid = 0, + k_ESteamNetworkingIdentityType_SteamID = 16, + k_ESteamNetworkingIdentityType_IPAddress = 1, + k_ESteamNetworkingIdentityType_GenericString = 2, + k_ESteamNetworkingIdentityType_GenericBytes = 3, + k_ESteamNetworkingIdentityType_UnknownType = 4, + k_ESteamNetworkingIdentityType__Force32bit = 0x7fffffff, +}; + +typedef enum ESteamNetworkingAvailability ESteamNetworkingAvailability; +enum ESteamNetworkingAvailability +{ + k_ESteamNetworkingAvailability_CannotTry = -102, + k_ESteamNetworkingAvailability_Failed = -101, + k_ESteamNetworkingAvailability_Previously = -100, + k_ESteamNetworkingAvailability_Retrying = -10, + k_ESteamNetworkingAvailability_NeverTried = 1, + k_ESteamNetworkingAvailability_Waiting = 2, + k_ESteamNetworkingAvailability_Attempting = 3, + k_ESteamNetworkingAvailability_Current = 100, + k_ESteamNetworkingAvailability_Unknown = 0, + k_ESteamNetworkingAvailability__Force32bit = 0x7fffffff, +}; + +/* Handle used to identify a connection to a remote host. */ +typedef u32 HSteamNetConnection; +HSteamNetConnection const k_HSteamNetConnection_Invalid = 0; + +/* + * Handle used to identify a "listen socket". Unlike traditional + * Berkeley sockets, a listen socket and a connection are two + * different abstractions. + */ +typedef u32 HSteamListenSocket; +HSteamListenSocket const k_HSteamListenSocket_Invalid = 0; + +typedef u32 SteamNetworkingPOPID; + +#define k_cchSteamNetworkingMaxConnectionCloseReason 128 +#define k_cchSteamNetworkingMaxConnectionDescription 128 +#define k_cchSteamNetworkingMaxConnectionAppName 32 + +#pragma pack(push,1) +/* Store an IP and port. IPv6 is always used; IPv4 is represented using + * "IPv4-mapped" addresses: IPv4 aa.bb.cc.dd => IPv6 ::ffff:aabb:ccdd + * (RFC 4291 section 2.5.5.2.) + */ +typedef struct SteamNetworkingIPAddr SteamNetworkingIPAddr; +struct SteamNetworkingIPAddr +{ + union + { + u8 m_ipv6[ 16 ]; + + /* RFC4038, section 4.2 */ + struct IPv4MappedAddress + { + u64 m_8zeros; + u16 m_0000; + u16 m_ffff; + u8 m_ip[ 4 ]; /* NOTE: As bytes, i.e. network byte order */ + } + m_ipv4; + }; + + u16 m_port; // Host byte order +}; + +typedef struct SteamNetworkingIdentity SteamNetworkingIdentity; +struct SteamNetworkingIdentity +{ + ESteamNetworkingIdentityType m_eType; + + int m_cbSize; + union + { + u64 m_steamID64; + char m_szGenericString[ 32 ]; + u8 m_genericBytes[ 32 ]; + char m_szUnknownRawString[ 128 ]; + SteamNetworkingIPAddr m_ip; + u32 m_reserved[ 32 ]; + }; +}; + +#pragma pack(pop) + +/* + * "Fake IPs" are assigned to hosts, to make it easier to interface with + * older code that assumed all hosts will have an IPv4 address + */ +typedef enum ESteamNetworkingFakeIPType ESteamNetworkingFakeIPType; +enum ESteamNetworkingFakeIPType +{ + k_ESteamNetworkingFakeIPType_Invalid, + k_ESteamNetworkingFakeIPType_NotFake, + k_ESteamNetworkingFakeIPType_GlobalIPv4, + k_ESteamNetworkingFakeIPType_LocalIPv4, + k_ESteamNetworkingFakeIPType__Force32Bit = 0x7fffffff +}; + +/* Set everything to zero. E.g. [::]:0 */ +void SteamAPI_SteamNetworkingIPAddr_Clear( SteamNetworkingIPAddr* self ); + +/* Returns true if the IP is ::0. (Doesn't check port.) */ +int SteamAPI_SteamNetworkingIPAddr_IsIPv6AllZeros( + SteamNetworkingIPAddr* self ); + +/* + * Set IPv6 address. IP is interpreted as bytes, so there are no endian issues. + * (Same as inaddr_in6.) The IP can be a mapped IPv4 address + */ +void SteamAPI_SteamNetworkingIPAddr_SetIPv6( SteamNetworkingIPAddr* self, + u8 *ipv6, u16 nPort ); + +/* Sets to IPv4 mapped address. IP and port are in host byte order. */ +void SteamAPI_SteamNetworkingIPAddr_SetIPv4( SteamNetworkingIPAddr* self, + u32 nIP, u16 nPort ); + +/* Return true if IP is mapped IPv4 */ +int SteamAPI_SteamNetworkingIPAddr_IsIPv4( SteamNetworkingIPAddr* self ); + +/* + * Returns IP in host byte order (e.g. aa.bb.cc.dd as 0xaabbccdd). + * Returns 0 if IP is not mapped IPv4. + */ +u32 SteamAPI_SteamNetworkingIPAddr_GetIPv4( SteamNetworkingIPAddr* self ); + +/* Set to the IPv6 localhost address ::1, and the specified port. */ +void SteamAPI_SteamNetworkingIPAddr_SetIPv6LocalHost( + SteamNetworkingIPAddr* self, u16 nPort ); + +/* + * Return true if this identity is localhost. + * (Either IPv6 ::1, or IPv4 127.0.0.1) + */ +int SteamAPI_SteamNetworkingIPAddr_IsLocalHost( SteamNetworkingIPAddr* self ); + +/* + * Print to a string, with or without the port. Mapped IPv4 addresses are + * printed as dotted decimal (12.34.56.78), otherwise this will print the + * canonical form according to RFC5952. If you include the port, IPv6 will be + * surrounded by brackets, e.g. [::1:2]:80. Your buffer should be at least + * k_cchMaxString bytes to avoid truncation + * + * See also SteamNetworkingIdentityRender + */ +void SteamAPI_SteamNetworkingIPAddr_ToString( SteamNetworkingIPAddr* self, + char *buf, u32 cbBuf, int bWithPort ); + +/* + * Parse an IP address and optional port. If a port is not present, it is set + * to 0. + * (This means that you cannot tell if a zero port was explicitly specified.) + */ +int SteamAPI_SteamNetworkingIPAddr_ParseString( SteamNetworkingIPAddr* self, + const char *pszStr ); + +/* See if two addresses are identical */ +int SteamAPI_SteamNetworkingIPAddr_IsEqualTo( SteamNetworkingIPAddr* self, + SteamNetworkingIPAddr *x ); + +/* + * Classify address as FakeIP. This function never returns + * k_ESteamNetworkingFakeIPType_Invalid. + */ +ESteamNetworkingFakeIPType SteamAPI_SteamNetworkingIPAddr_GetFakeIPType( + SteamNetworkingIPAddr* self ); + +/* Return true if we are a FakeIP */ +int SteamAPI_SteamNetworkingIPAddr_IsFakeIP( SteamNetworkingIPAddr* self ); + + +/* Describe the state of a connection. */ +typedef struct SteamNetConnectionInfo_t SteamNetConnectionInfo_t; +struct SteamNetConnectionInfo_t +{ + SteamNetworkingIdentity m_identityRemote; + + /* Arbitrary user data set by the local application code */ + i64 m_nUserData; + + /* Handle to listen socket this was connected on, or + * k_HSteamListenSocket_Invalid if we initiated the connection */ + HSteamListenSocket m_hListenSocket; + + /* Remote address. Might be all 0's if we don't know it, or if this is N/A. + * (E.g. Basically everything except direct UDP connection.) */ + SteamNetworkingIPAddr m_addrRemote; + u16 m__pad1; + + /* What data center is the remote host in? (0 if we don't know.) */ + SteamNetworkingPOPID m_idPOPRemote; + + /* What relay are we using to communicate with the remote host? + * (0 if not applicable.) */ + SteamNetworkingPOPID m_idPOPRelay; + + /* High level state of the connection */ + ESteamNetworkingConnectionState m_eState; + + /* Basic cause of the connection termination or problem. + * See ESteamNetConnectionEnd for the values used */ + int m_eEndReason; + + /* + * Human-readable, but non-localized explanation for connection + * termination or problem. This is intended for debugging / + * diagnostic purposes only, not to display to users. It might + * have some details specific to the issue. + */ + char m_szEndDebug[ 128 ]; + + /* + * Debug description. This includes the internal connection ID, + * connection type (and peer information), and any name + * given to the connection by the app. This string is used in various + * internal logging messages. + * + * Note that the connection ID *usually* matches the HSteamNetConnection + * handle, but in certain cases with symmetric connections it might not. + */ + char m_szConnectionDescription[ 128 ]; + + /* + * Misc flags. Bitmask of k_nSteamNetworkConnectionInfoFlags_Xxxx + */ + int m_nFlags; + + /* + * Internal stuff, room to change API easily + */ + u32 reserved[63]; +}; + +/* + * In a few places we need to set configuration options on listen sockets and + * connections, and have them take effect *before* the listen socket or + * connection really starts doing anything. Creating the object and then setting + * the options "immediately" after creation doesn't work completely, because + * network packets could be received between the time the object is created and + * when the options are applied. To set options at creation time in a reliable + * way, they must be passed to the creation function. This structure is used to + * pass those options. + * + * For the meaning of these fields, see ISteamNetworkingUtils::SetConfigValue. + * Basically when the object is created, we just iterate over the list of + * options and call ISteamNetworkingUtils::SetConfigValueStruct, where the scope + * arguments are supplied by the object being created. + */ +typedef struct SteamNetworkingConfigValue_t SteamNetworkingConfigValue_t; +struct SteamNetworkingConfigValue_t +{ + /* Which option is being set */ + ESteamNetworkingConfigValue m_eValue; + + /// Which field below did you fill in? + ESteamNetworkingConfigDataType m_eDataType; + + /// Option value + union + { + i32 m_int32; + i64 m_int64; + float m_float; + const char *m_string; // Points to your '\0'-terminated buffer + void *m_ptr; + } m_val; +}; + +void SteamAPI_SteamNetworkingConfigValue_t_SetInt32( + SteamNetworkingConfigValue_t* self, + ESteamNetworkingConfigValue eVal, i32 data ); + +void SteamAPI_SteamNetworkingConfigValue_t_SetInt64( + SteamNetworkingConfigValue_t* self, + ESteamNetworkingConfigValue eVal, i64 data ); + +void SteamAPI_SteamNetworkingConfigValue_t_SetFloat( + SteamNetworkingConfigValue_t* self, + ESteamNetworkingConfigValue eVal, float data ); + +void SteamAPI_SteamNetworkingConfigValue_t_SetPtr( + SteamNetworkingConfigValue_t* self, + ESteamNetworkingConfigValue eVal, void *data ); + +void SteamAPI_SteamNetworkingConfigValue_t_SetString( + SteamNetworkingConfigValue_t* self, ESteamNetworkingConfigValue eVal, + const char * data ); + +/* + * Handle used to identify a poll group, used to query many + * connections at once efficiently. + */ +typedef u32 HSteamNetPollGroup; +HSteamNetPollGroup const k_HSteamNetPollGroup_Invalid = 0; + +void *SteamAPI_SteamGameServerNetworkingSockets_SteamAPI_v012(void); +void *SteamAPI_SteamGameServerNetworkingSockets_SteamAPI(void) +{ + return SteamAPI_SteamGameServerNetworkingSockets_SteamAPI_v012(); +} + + +void *SteamAPI_SteamNetworkingSockets_SteamAPI_v012(); +void *SteamAPI_SteamNetworkingSockets_SteamAPI() +{ + return SteamAPI_SteamNetworkingSockets_SteamAPI_v012(); +} + +HSteamListenSocket SteamAPI_ISteamNetworkingSockets_CreateListenSocketIP( + void *self, SteamNetworkingIPAddr *localAddress, int nOptions, + SteamNetworkingConfigValue_t *pOptions ); + +HSteamNetConnection SteamAPI_ISteamNetworkingSockets_ConnectByIPAddress( + void *self, + SteamNetworkingIPAddr *address, int nOptions, + SteamNetworkingConfigValue_t *pOptions ); + +int SteamAPI_ISteamNetworkingSockets_CloseConnection( + void *self, HSteamNetConnection hPeer, int nReason, const char *pszDebug, + int bEnableLinger ); + +int SteamAPI_ISteamNetworkingSockets_CloseListenSocket( + void *self, HSteamListenSocket hSocket ); + +/* + * Callbacks + */ + +enum { k_iSteamNetConnectionStatusChangedCallBack = + k_iSteamNetworkingSocketsCallbacks + 1 }; + +typedef struct SteamNetConnectionStatusChangedCallback_t + SteamNetConnectionStatusChangedCallback_t; +struct SteamNetConnectionStatusChangedCallback_t +{ + /// Connection handle + HSteamNetConnection m_hConn; + + /// Full connection info + SteamNetConnectionInfo_t m_info; + + /// Previous state. (Current state is in m_info.m_eState) + ESteamNetworkingConnectionState m_eOldState; +}; + +enum { k_iSteamNetAuthenticationStatus = + k_iSteamNetworkingSocketsCallbacks + 2 }; + +typedef struct SteamNetAuthenticationStatus_t SteamNetAuthenticationStatus_t; +struct SteamNetAuthenticationStatus_t +{ + /// Status + ESteamNetworkingAvailability m_eAvail; + + /// Non-localized English language status. For diagnostic/debugging + /// purposes only. + char m_debugMsg[ 256 ]; +}; + +#pragma pack(pop) +#endif /* VG_STEAM_NETWORKING_H */ -- 2.25.1