mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2024-12-24 13:45:37 +03:00
Pin the SererRules functions so they don't get collected etc
This commit is contained in:
parent
01c8083869
commit
0cf2761166
@ -127,6 +127,7 @@
|
||||
<Compile Include="Client\Screenshots.cs" />
|
||||
<Compile Include="Client\Stats.cs" />
|
||||
<Compile Include="Client\Voice.cs" />
|
||||
<Compile Include="Config.cs" />
|
||||
<Compile Include="Interop\ServerRules.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="steam_api_interop.cs" />
|
||||
|
@ -8,52 +8,83 @@ namespace Facepunch.Steamworks.Interop
|
||||
{
|
||||
class ServerRules
|
||||
{
|
||||
private GCHandle thisPin;
|
||||
// Pins and pointers for the created vtable
|
||||
private GCHandle vTablePin;
|
||||
private IntPtr vTablePtr;
|
||||
private GCHandle vTableHandle;
|
||||
|
||||
// Pins for the functions
|
||||
private GCHandle RulesRespondPin;
|
||||
private GCHandle FailedRespondPin;
|
||||
private GCHandle CompletePin;
|
||||
|
||||
// The server that called us
|
||||
private ServerList.Server Server;
|
||||
|
||||
public ServerRules( ServerList.Server server, uint address, int queryPort )
|
||||
{
|
||||
Server = server;
|
||||
|
||||
//
|
||||
// Create a fake VTable to pass to c++
|
||||
//
|
||||
InstallVTable();
|
||||
|
||||
//
|
||||
// Ask Steam to get the server rules, respond to our fake vtable
|
||||
//
|
||||
Valve.Interop.NativeEntrypoints.SteamAPI_ISteamMatchmakingServers_ServerRules( Server.Client.native.servers.GetIntPtr(), address, (short) queryPort, GetPtr() );
|
||||
}
|
||||
|
||||
void InstallVTable()
|
||||
{
|
||||
GC.KeepAlive( Server );
|
||||
GC.SuppressFinalize( Server );
|
||||
|
||||
if ( Server.Client.UseThisCall )
|
||||
//
|
||||
// Depending on platform, we either use ThisCall or stdcall.
|
||||
// This is a bit of a fuckabout but you need to define Client.UseThisCall
|
||||
//
|
||||
|
||||
if ( Config.UseThisCall )
|
||||
{
|
||||
ThisVTable.InternalRulesResponded da = ( _, k, v ) => InternalOnRulesResponded( k, v );
|
||||
ThisVTable.InternalRulesFailedToRespond db = ( _ ) => InternalOnRulesFailedToRespond();
|
||||
ThisVTable.InternalRulesRefreshComplete dc = ( _ ) => InternalOnRulesRefreshComplete();
|
||||
|
||||
RulesRespondPin = GCHandle.Alloc( da );
|
||||
FailedRespondPin = GCHandle.Alloc( db );
|
||||
CompletePin = GCHandle.Alloc( dc );
|
||||
|
||||
var t = new ThisVTable()
|
||||
{
|
||||
m_VTRulesResponded = ( _, k, v ) => InternalOnRulesResponded( k, v ),
|
||||
m_VTRulesFailedToRespond = ( _ ) => InternalOnRulesFailedToRespond(),
|
||||
m_VTRulesRefreshComplete = ( _ ) => InternalOnRulesRefreshComplete(),
|
||||
m_VTRulesResponded = da,
|
||||
m_VTRulesFailedToRespond = db,
|
||||
m_VTRulesRefreshComplete = dc,
|
||||
};
|
||||
vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( ThisVTable ) ) );
|
||||
Marshal.StructureToPtr( t, vTablePtr, false );
|
||||
|
||||
vTableHandle = GCHandle.Alloc( vTablePtr, GCHandleType.Pinned );
|
||||
vTablePin = GCHandle.Alloc( vTablePtr, GCHandleType.Pinned );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
StdVTable.InternalRulesResponded da = InternalOnRulesResponded;
|
||||
StdVTable.InternalRulesFailedToRespond db = InternalOnRulesFailedToRespond;
|
||||
StdVTable.InternalRulesRefreshComplete dc = InternalOnRulesRefreshComplete;
|
||||
|
||||
RulesRespondPin = GCHandle.Alloc( da );
|
||||
FailedRespondPin = GCHandle.Alloc( db );
|
||||
CompletePin = GCHandle.Alloc( dc );
|
||||
|
||||
var t = new StdVTable()
|
||||
{
|
||||
m_VTRulesResponded = InternalOnRulesResponded,
|
||||
m_VTRulesFailedToRespond = InternalOnRulesFailedToRespond,
|
||||
m_VTRulesRefreshComplete = InternalOnRulesRefreshComplete
|
||||
m_VTRulesResponded = da,
|
||||
m_VTRulesFailedToRespond = db,
|
||||
m_VTRulesRefreshComplete = dc
|
||||
};
|
||||
vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( StdVTable ) ) );
|
||||
Marshal.StructureToPtr( t, vTablePtr, false );
|
||||
|
||||
vTableHandle = GCHandle.Alloc( vTablePtr, GCHandleType.Pinned );
|
||||
vTablePin = GCHandle.Alloc( vTablePtr, GCHandleType.Pinned );
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,22 +93,26 @@ void Unpin()
|
||||
if ( vTablePtr != IntPtr.Zero )
|
||||
{
|
||||
Marshal.FreeHGlobal( vTablePtr );
|
||||
vTablePtr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
if ( vTableHandle.IsAllocated )
|
||||
{
|
||||
vTableHandle.Free();
|
||||
}
|
||||
if ( vTablePin.IsAllocated )
|
||||
vTablePin.Free();
|
||||
|
||||
if ( RulesRespondPin.IsAllocated )
|
||||
vTablePin.Free();
|
||||
|
||||
if ( FailedRespondPin.IsAllocated )
|
||||
vTablePin.Free();
|
||||
|
||||
if ( CompletePin.IsAllocated )
|
||||
vTablePin.Free();
|
||||
|
||||
if ( thisPin.IsAllocated )
|
||||
{
|
||||
thisPin.Free();
|
||||
}
|
||||
}
|
||||
|
||||
private void InternalOnRulesResponded( IntPtr k, IntPtr v )
|
||||
private void InternalOnRulesResponded( string k, string v )
|
||||
{
|
||||
// Server.Rules.Add( k, v );
|
||||
Server.Rules.Add( k, v );
|
||||
}
|
||||
private void InternalOnRulesFailedToRespond()
|
||||
{
|
||||
@ -91,20 +126,17 @@ private void InternalOnRulesRefreshComplete()
|
||||
[StructLayout( LayoutKind.Sequential )]
|
||||
private class StdVTable
|
||||
{
|
||||
[NonSerialized]
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||
public InternalRulesResponded m_VTRulesResponded;
|
||||
|
||||
[NonSerialized]
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||
public InternalRulesFailedToRespond m_VTRulesFailedToRespond;
|
||||
|
||||
[NonSerialized]
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||
public InternalRulesRefreshComplete m_VTRulesRefreshComplete;
|
||||
|
||||
[UnmanagedFunctionPointer( CallingConvention.StdCall )]
|
||||
public delegate void InternalRulesResponded( IntPtr pchRule, IntPtr pchValue );
|
||||
public delegate void InternalRulesResponded( string pchRule, string pchValue );
|
||||
[UnmanagedFunctionPointer( CallingConvention.StdCall )]
|
||||
public delegate void InternalRulesFailedToRespond();
|
||||
[UnmanagedFunctionPointer( CallingConvention.StdCall )]
|
||||
@ -114,20 +146,17 @@ private class StdVTable
|
||||
[StructLayout( LayoutKind.Sequential )]
|
||||
private class ThisVTable
|
||||
{
|
||||
[NonSerialized]
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||
public InternalRulesResponded m_VTRulesResponded;
|
||||
|
||||
[NonSerialized]
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||
public InternalRulesFailedToRespond m_VTRulesFailedToRespond;
|
||||
|
||||
[NonSerialized]
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||
public InternalRulesRefreshComplete m_VTRulesRefreshComplete;
|
||||
|
||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
||||
public delegate void InternalRulesResponded( IntPtr thisptr, IntPtr pchRule, IntPtr pchValue );
|
||||
public delegate void InternalRulesResponded( IntPtr thisptr, string pchRule, string pchValue );
|
||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
||||
public delegate void InternalRulesFailedToRespond( IntPtr thisptr );
|
||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
||||
@ -136,7 +165,7 @@ private class ThisVTable
|
||||
|
||||
public System.IntPtr GetPtr()
|
||||
{
|
||||
return vTableHandle.AddrOfPinnedObject();
|
||||
return vTablePin.AddrOfPinnedObject();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user