mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2024-12-24 13:45:37 +03:00
Server Auth callbacks
This commit is contained in:
parent
c2270c6840
commit
c3a1bf0bcf
@ -25,39 +25,87 @@ public void AuthCallback()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.Valid );
|
||||
|
||||
var ticket = client.Auth.GetAuthSessionTicket();
|
||||
var ticketBinary = ticket.Data;
|
||||
|
||||
using ( var server = new Facepunch.Steamworks.Server( 252490, 30000, 30001, 30002, 30003, false, "VersionString" ) )
|
||||
using ( var server = new Facepunch.Steamworks.Server( 252490, 0, 30001, 30002, 30003, true, "VersionString" ) )
|
||||
{
|
||||
Assert.IsTrue( client.Valid );
|
||||
|
||||
var ticket = client.Auth.GetAuthSessionTicket();
|
||||
var ticketBinary = ticket.Data;
|
||||
|
||||
Assert.IsTrue( server.Valid );
|
||||
|
||||
var auth = server.Auth;
|
||||
|
||||
var Authed = false;
|
||||
|
||||
server.Auth.OnAuthChange = ( steamid, ownerid, status ) =>
|
||||
{
|
||||
Authed = status == ServerAuth.Status.OK;
|
||||
|
||||
Assert.AreEqual( steamid, client.SteamId );
|
||||
|
||||
Console.WriteLine( "steamid: {0}", steamid );
|
||||
Console.WriteLine( "ownerid: {0}", ownerid );
|
||||
Console.WriteLine( "status: {0}", status );
|
||||
};
|
||||
|
||||
for ( int i = 0; i < 16; i++ )
|
||||
{
|
||||
System.Threading.Thread.Sleep( 10 );
|
||||
GC.Collect();
|
||||
server.Update();
|
||||
GC.Collect();
|
||||
client.Update();
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
if ( !server.Auth.StartSession( ticketBinary, client.SteamId ) )
|
||||
{
|
||||
Assert.Fail( "Start Session returned false" );
|
||||
}
|
||||
GC.Collect();
|
||||
|
||||
for( int i = 0; i<16; i++ )
|
||||
//
|
||||
// Server should receive a ServerAuth.Status.OK
|
||||
// message via the OnAuthChange callback
|
||||
//
|
||||
|
||||
for ( int i = 0; i< 100; i++ )
|
||||
{
|
||||
System.Threading.Thread.Sleep( 10 );
|
||||
GC.Collect();
|
||||
System.Threading.Thread.Sleep( 100 );
|
||||
GC.Collect();
|
||||
server.Update();
|
||||
client.Update();
|
||||
|
||||
if ( Authed )
|
||||
break;
|
||||
}
|
||||
|
||||
Assert.IsTrue( Authed );
|
||||
|
||||
//
|
||||
// Client cancels ticket
|
||||
//
|
||||
ticket.Cancel();
|
||||
|
||||
//
|
||||
// Server should receive a ticket cancelled message
|
||||
//
|
||||
|
||||
for ( int i = 0; i < 100; i++ )
|
||||
{
|
||||
System.Threading.Thread.Sleep( 100 );
|
||||
server.Update();
|
||||
client.Update();
|
||||
|
||||
if ( !Authed )
|
||||
break;
|
||||
}
|
||||
|
||||
Assert.IsTrue( !Authed );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
37
Facepunch.Steamworks/Callbacks/User.cs
Normal file
37
Facepunch.Steamworks/Callbacks/User.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Facepunch.Steamworks.Callbacks.User
|
||||
{
|
||||
[StructLayout( LayoutKind.Sequential )]
|
||||
internal class ValidateAuthTicketResponse
|
||||
{
|
||||
public enum Response : int
|
||||
{
|
||||
Okay = 0, // Steam has verified the user is online, the ticket is valid and ticket has not been reused.
|
||||
UserNotConnectedToSteam = 1, // The user in question is not connected to steam
|
||||
NoLicenseOrExpired = 2, // The license has expired.
|
||||
VACBanned = 3, // The user is VAC banned for this game.
|
||||
LoggedInElseWhere = 4, // The user account has logged in elsewhere and the session containing the game instance has been disconnected.
|
||||
VACCheckTimedOut = 5, // VAC has been unable to perform anti-cheat checks on this user
|
||||
AuthTicketCanceled = 6, // The ticket has been canceled by the issuer
|
||||
AuthTicketInvalidAlreadyUsed = 7, // This ticket has already been used, it is not valid.
|
||||
AuthTicketInvalid = 8, // This ticket is not from a user instance currently connected to steam.
|
||||
PublisherIssuedBan = 9, // The user is banned for this game. The ban came via the web api and not VAC
|
||||
};
|
||||
|
||||
public ulong SteamID;
|
||||
public Response AuthResponse;
|
||||
public ulong OwnerSteamID;
|
||||
|
||||
public const int CallbackId = Index.User + 43;
|
||||
};
|
||||
|
||||
internal static class Index
|
||||
{
|
||||
internal const int User = 100;
|
||||
}
|
||||
}
|
@ -16,6 +16,6 @@ public static class Config
|
||||
/// for releasing his shit open source under the MIT license so we can all learn and iterate.
|
||||
///
|
||||
/// </summary>
|
||||
public static bool UseThisCall { get; set; }
|
||||
public static bool UseThisCall { get; set; } = true;
|
||||
}
|
||||
}
|
||||
|
@ -113,6 +113,7 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Callbacks\User.cs" />
|
||||
<Compile Include="Client\Networking.cs" />
|
||||
<Compile Include="Client\Overlay.cs" />
|
||||
<Compile Include="Client\ServerList.cs" />
|
||||
@ -128,13 +129,16 @@
|
||||
<Compile Include="Client\Stats.cs" />
|
||||
<Compile Include="Client\Voice.cs" />
|
||||
<Compile Include="Config.cs" />
|
||||
<Compile Include="Interop\Callback.cs" />
|
||||
<Compile Include="Interop\ServerRules.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Interop\steam_api_interop.cs" />
|
||||
<Compile Include="Server.cs" />
|
||||
<Compile Include="Server\Auth.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Compile Include="Interop\Callback.This.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
|
52
Facepunch.Steamworks/Interop/Callback.This.cs
Normal file
52
Facepunch.Steamworks/Interop/Callback.This.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Facepunch.Steamworks.Interop.VTable.This
|
||||
{
|
||||
[StructLayout( LayoutKind.Sequential )]
|
||||
internal struct Callback
|
||||
{
|
||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
||||
public delegate void Result( IntPtr thisptr, IntPtr pvParam );
|
||||
|
||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
||||
public delegate int GetSize( IntPtr thisptr );
|
||||
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||
public Result m_RunCallback;
|
||||
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||
public Result m_RunCallResult;
|
||||
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||
public GetSize m_GetCallbackSizeBytes;
|
||||
|
||||
internal static IntPtr Get( Action<IntPtr> onRunCallback, Func<int> getSize )
|
||||
{
|
||||
var size = Marshal.SizeOf( typeof( Callback ) );
|
||||
var ptr = Marshal.AllocHGlobal( size );
|
||||
|
||||
Callback.Result da = ( _, p ) => onRunCallback( p );
|
||||
Callback.GetSize dc = ( _ ) => getSize();
|
||||
|
||||
var a = GCHandle.Alloc( da );
|
||||
var c = GCHandle.Alloc( dc );
|
||||
|
||||
var table = new Callback()
|
||||
{
|
||||
m_RunCallResult = da,
|
||||
m_RunCallback = da,
|
||||
m_GetCallbackSizeBytes = dc
|
||||
};
|
||||
|
||||
Marshal.StructureToPtr( table, ptr, false );
|
||||
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
119
Facepunch.Steamworks/Interop/Callback.cs
Normal file
119
Facepunch.Steamworks/Interop/Callback.cs
Normal file
@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
|
||||
//
|
||||
// THANSK AGAIN TO STEAMWORKS.NET
|
||||
//
|
||||
// https://github.com/rlabrecque/Steamworks.NET/blob/97935154cf08f60da92c55e2c73ee60a8f456e03/Plugins/Steamworks.NET/CallbackDispatcher.cs
|
||||
//
|
||||
|
||||
// Calling Conventions:
|
||||
// Unity x86 Windows - StdCall (No this pointer)
|
||||
// Unity x86 Linux - Cdecl
|
||||
// Unity x86 OSX - Cdecl
|
||||
// Unity x64 Windows - Cdecl
|
||||
// Unity x64 Linux - Cdecl
|
||||
// Unity x64 OSX - Cdecl
|
||||
// Microsoft x86 Windows - ThisCall
|
||||
// Microsoft x64 Windows - ThisCall
|
||||
// Mono x86 Linux - Cdecl
|
||||
// Mono x86 OSX - Cdecl
|
||||
// Mono x64 Linux - Cdecl
|
||||
// Mono x64 OSX - Cdecl
|
||||
// Mono on Windows is probably not supported.
|
||||
|
||||
namespace Facepunch.Steamworks.Interop
|
||||
{
|
||||
internal partial class Callback<T> : IDisposable
|
||||
{
|
||||
public int CallbackId = 0;
|
||||
public bool GameServer = false;
|
||||
public Action<T> Function;
|
||||
|
||||
private IntPtr vTablePtr = IntPtr.Zero;
|
||||
private GCHandle callbackPin;
|
||||
|
||||
private readonly int m_size = Marshal.SizeOf(typeof(T));
|
||||
|
||||
public Callback( bool gameserver, int callbackid, Action<T> func )
|
||||
{
|
||||
GameServer = gameserver;
|
||||
CallbackId = callbackid;
|
||||
Function = func;
|
||||
|
||||
BuildVTable();
|
||||
|
||||
Valve.Steamworks.SteamAPI.RegisterCallback( callbackPin.AddrOfPinnedObject(), CallbackId );
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
if ( callbackPin.IsAllocated )
|
||||
{
|
||||
Valve.Steamworks.SteamAPI.UnregisterCallback( callbackPin.AddrOfPinnedObject() );
|
||||
callbackPin.Free();
|
||||
}
|
||||
|
||||
if ( vTablePtr != IntPtr.Zero )
|
||||
{
|
||||
Marshal.FreeHGlobal( vTablePtr );
|
||||
vTablePtr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRunCallback( IntPtr ptr )
|
||||
{
|
||||
T data = (T) Marshal.PtrToStructure( ptr, typeof(T) );
|
||||
Function( data );
|
||||
}
|
||||
|
||||
|
||||
private int GetSize()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
// Steamworks.NET Specific
|
||||
private void BuildVTable()
|
||||
{
|
||||
InitVTable();
|
||||
|
||||
var callbackBase = new CallbackBase()
|
||||
{
|
||||
vTablePtr = vTablePtr,
|
||||
CallbackFlags = GameServer ? (byte) CallbackBase.Flags.GameServer : (byte) 0,
|
||||
CallbackId = CallbackId
|
||||
};
|
||||
callbackPin = GCHandle.Alloc( callbackBase, GCHandleType.Pinned );
|
||||
}
|
||||
|
||||
void InitVTable()
|
||||
{
|
||||
if ( Config.UseThisCall )
|
||||
{
|
||||
vTablePtr = VTable.This.Callback.Get( OnRunCallback, GetSize );
|
||||
return;
|
||||
}
|
||||
|
||||
//vTablePtr = VTable.CDecl.Callback.Get( OnRunCallback, GetSize );
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout( LayoutKind.Sequential )]
|
||||
internal class CallbackBase
|
||||
{
|
||||
internal enum Flags : byte
|
||||
{
|
||||
Registered = 0x01,
|
||||
GameServer = 0x02
|
||||
}
|
||||
|
||||
public IntPtr vTablePtr;
|
||||
public byte CallbackFlags;
|
||||
public int CallbackId;
|
||||
};
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
@ -119,7 +120,9 @@ public Server( uint appId, uint IpAddress, ushort SteamPort, ushort GamePort, us
|
||||
// Set up warning hook callback
|
||||
//
|
||||
SteamAPIWarningMessageHook ptr = InternalOnWarning;
|
||||
// native.client.SetWarningMessageHook( Marshal.GetFunctionPointerForDelegate( ptr ) );
|
||||
var d = Marshal.GetFunctionPointerForDelegate( ptr );
|
||||
var rr = GCHandle.Alloc( d );
|
||||
native.utils.SetWarningMessageHook( d );
|
||||
|
||||
//
|
||||
// Cache common, unchanging info
|
||||
@ -129,6 +132,10 @@ public Server( uint appId, uint IpAddress, ushort SteamPort, ushort GamePort, us
|
||||
//
|
||||
// Initial settings
|
||||
//
|
||||
native.gameServer.SetModDir( "rust" );
|
||||
native.gameServer.SetProduct( "rust" );
|
||||
native.gameServer.SetGameDescription( "rust" );
|
||||
native.gameServer.LogOnAnonymous();
|
||||
native.gameServer.EnableHeartbeats( true );
|
||||
MaxPlayers = 32;
|
||||
BotCount = 0;
|
||||
@ -147,17 +154,25 @@ public void Dispose()
|
||||
native.Dispose();
|
||||
native = null;
|
||||
}
|
||||
|
||||
foreach ( var d in Disposables )
|
||||
{
|
||||
d.Dispose();
|
||||
}
|
||||
Disposables.Clear();
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer( CallingConvention.Cdecl )]
|
||||
public delegate void SteamAPIWarningMessageHook( int nSeverity, System.Text.StringBuilder pchDebugText );
|
||||
public delegate void SteamAPIWarningMessageHook( int nSeverity, string pchDebugText );
|
||||
|
||||
private void InternalOnWarning( int nSeverity, System.Text.StringBuilder text )
|
||||
private void InternalOnWarning( int nSeverity, string text )
|
||||
{
|
||||
if ( OnMessage != null )
|
||||
{
|
||||
OnMessage( ( MessageType)nSeverity, text.ToString() );
|
||||
}
|
||||
|
||||
Console.WriteLine( "STEAM: {0}", text );
|
||||
}
|
||||
|
||||
internal event Action OnUpdate;
|
||||
@ -171,9 +186,10 @@ public void Update()
|
||||
return;
|
||||
|
||||
Valve.Interop.NativeEntrypoints.Extended.SteamGameServer_RunCallbacks();
|
||||
Valve.Steamworks.SteamAPI.RunCallbacks();
|
||||
// Voice.Update();
|
||||
// Inventory.Update();
|
||||
// Networking.Update();
|
||||
// Networking.Update();
|
||||
|
||||
if ( OnUpdate != null )
|
||||
OnUpdate();
|
||||
@ -184,20 +200,27 @@ public bool Valid
|
||||
get { return native != null; }
|
||||
}
|
||||
|
||||
internal Action InstallCallback( int type, Delegate action )
|
||||
internal Action InstallCallback<T>( Action<T> action )
|
||||
{
|
||||
var del = Marshal.GetFunctionPointerForDelegate( action );
|
||||
// var del = Marshal.GetFunctionPointerForDelegate( action );
|
||||
|
||||
// var ptr = Marshal.GetFunctionPointerForDelegate( action );
|
||||
// Valve.Steamworks.SteamAPI.RegisterCallback( del, type );
|
||||
// Valve.Steamworks.SteamAPI.RegisterCallback( del, type );
|
||||
|
||||
// Valve.Steamworks.SteamAPI.UnregisterCallback( del );
|
||||
// Valve.Steamworks.SteamAPI.UnregisterCallback( del );
|
||||
|
||||
//return () => Valve.Steamworks.SteamAPI.UnregisterCallback( ptr );
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
List<IDisposable> Disposables = new List<IDisposable>();
|
||||
|
||||
internal void CallResult<T>( Action<T> Callback, int id )
|
||||
{
|
||||
var callback = new Facepunch.Steamworks.Interop.Callback<T>( true, id, Callback );
|
||||
Disposables.Add( callback );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current MaxPlayers.
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Facepunch.Steamworks.Callbacks.User;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
@ -14,7 +15,7 @@ public ServerAuth Auth
|
||||
get
|
||||
{
|
||||
if ( _auth == null )
|
||||
_auth = new ServerAuth { server = this };
|
||||
_auth = new ServerAuth( this );
|
||||
|
||||
return _auth;
|
||||
}
|
||||
@ -26,7 +27,45 @@ public class ServerAuth
|
||||
internal Server server;
|
||||
|
||||
/// <summary>
|
||||
/// Start authorizing a ticket
|
||||
/// Steamid, Ownerid, Status
|
||||
/// </summary>
|
||||
public Action<ulong, ulong, Status> OnAuthChange;
|
||||
|
||||
/// <summary>
|
||||
/// Steam authetication statuses
|
||||
/// </summary>
|
||||
public enum Status : int
|
||||
{
|
||||
/// <summary>
|
||||
/// Steam has verified the user is online, the ticket is valid and ticket has not been reused.
|
||||
/// </summary>
|
||||
OK = 0,
|
||||
UserNotConnectedToSteam = 1, // The user in question is not connected to steam
|
||||
NoLicenseOrExpired = 2, // The license has expired.
|
||||
VACBanned = 3, // The user is VAC banned for this game.
|
||||
LoggedInElseWhere = 4, // The user account has logged in elsewhere and the session containing the game instance has been disconnected.
|
||||
VACCheckTimedOut = 5, // VAC has been unable to perform anti-cheat checks on this user
|
||||
AuthTicketCanceled = 6, // The ticket has been canceled by the issuer
|
||||
AuthTicketInvalidAlreadyUsed = 7, // This ticket has already been used, it is not valid.
|
||||
AuthTicketInvalid = 8, // This ticket is not from a user instance currently connected to steam.
|
||||
PublisherIssuedBan = 9, // The user is banned for this game. The ban came via the web api and not VAC
|
||||
}
|
||||
|
||||
internal ServerAuth( Server s )
|
||||
{
|
||||
server = s;
|
||||
|
||||
server.CallResult<ValidateAuthTicketResponse>( OnAuthTicketValidate, ValidateAuthTicketResponse.CallbackId );
|
||||
}
|
||||
|
||||
void OnAuthTicketValidate( ValidateAuthTicketResponse data )
|
||||
{
|
||||
if ( OnAuthChange != null )
|
||||
OnAuthChange( data.SteamID, data.OwnerSteamID, (Status) data.AuthResponse );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start authorizing a ticket. This user isn't authorized yet. Wait for a call to OnAuthChange.
|
||||
/// </summary>
|
||||
public unsafe bool StartSession( byte[] data, ulong steamid )
|
||||
{
|
||||
@ -41,6 +80,9 @@ public unsafe bool StartSession( byte[] data, ulong steamid )
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forget this guy. They're no longer in the game.
|
||||
/// </summary>
|
||||
public void EndSession( ulong steamid )
|
||||
{
|
||||
server.native.gameServer.EndAuthSession( steamid );
|
||||
|
Loading…
Reference in New Issue
Block a user