mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2024-12-24 13:45:37 +03:00
P2P, rough cut
This commit is contained in:
parent
1014178db6
commit
19385ed951
40
Facepunch.Steamworks.Test/Client.Networking.cs
Normal file
40
Facepunch.Steamworks.Test/Client.Networking.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Facepunch.Steamworks.Test
|
||||
{
|
||||
public partial class Client
|
||||
{
|
||||
[TestMethod]
|
||||
public void PeerToPeerSend()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var TestString = "This string will be transformed to bytes, sent over the Steam P2P network, then converted back to a string.";
|
||||
var OutputReceived = false;
|
||||
var data = Encoding.UTF8.GetBytes( TestString );
|
||||
|
||||
client.Networking.OnP2PData = ( steamid, ms, channel ) =>
|
||||
{
|
||||
var str = Encoding.UTF8.GetString( ms.GetBuffer() );
|
||||
Assert.AreEqual( str, TestString );
|
||||
Assert.AreEqual( steamid, client.SteamId );
|
||||
OutputReceived = true;
|
||||
};
|
||||
|
||||
client.Networking.SendP2PPacket( client.SteamId, data, data.Length );
|
||||
|
||||
while( true )
|
||||
{
|
||||
Thread.Sleep( 10 );
|
||||
client.Update();
|
||||
|
||||
if ( OutputReceived )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ namespace Facepunch.Steamworks.Test
|
||||
[TestClass]
|
||||
[DeploymentItem( "FacepunchSteamworksApi.dll" )]
|
||||
[DeploymentItem( "steam_appid.txt" )]
|
||||
public class Client
|
||||
public partial class Client
|
||||
{
|
||||
[TestMethod]
|
||||
public void Init()
|
||||
|
@ -87,6 +87,7 @@
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="Client.cs" />
|
||||
<Compile Include="Client.Networking.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
146
Facepunch.Steamworks/Client.Networking.cs
Normal file
146
Facepunch.Steamworks/Client.Networking.cs
Normal file
@ -0,0 +1,146 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Valve.Steamworks;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public partial class Client : IDisposable
|
||||
{
|
||||
private Networking _net;
|
||||
|
||||
public Networking Networking
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _net == null )
|
||||
_net = new Networking( this );
|
||||
|
||||
return _net;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Networking
|
||||
{
|
||||
public Action<ulong, MemoryStream, int> OnP2PData;
|
||||
|
||||
internal Client client;
|
||||
|
||||
internal class Callback
|
||||
{
|
||||
internal delegate void P2PSessionRequest( P2PSessionRequest_t a );
|
||||
internal delegate void P2PSessionConnectFail( P2PSessionConnectFail_t a );
|
||||
}
|
||||
|
||||
internal Networking( Client c )
|
||||
{
|
||||
client = c;
|
||||
|
||||
{
|
||||
Callback.P2PSessionRequest cb = onP2PConnectionRequest;
|
||||
client.InstallCallback( Valve.Steamworks.SteamAPI.k_iSteamNetworkingCallbacks + 2, cb );
|
||||
}
|
||||
|
||||
{
|
||||
Callback.P2PSessionConnectFail cb = onP2PConnectionFailed;
|
||||
client.InstallCallback( Valve.Steamworks.SteamAPI.k_iSteamNetworkingCallbacks + 2, cb );
|
||||
}
|
||||
}
|
||||
|
||||
internal void Update()
|
||||
{
|
||||
for ( int i = 0; i < 32; i++ )
|
||||
{
|
||||
// POOL ME
|
||||
using ( var ms = new MemoryStream() )
|
||||
{
|
||||
while( ReadP2PPacket( ms, i ) )
|
||||
{
|
||||
// Nothing Here.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onP2PConnectionRequest( P2PSessionRequest_t o )
|
||||
{
|
||||
Console.WriteLine( "onP2PConnectionRequest " + o.m_steamIDRemote );
|
||||
}
|
||||
|
||||
private void onP2PConnectionFailed( P2PSessionConnectFail_t o )
|
||||
{
|
||||
Console.WriteLine( "onP2PConnectionFailed " + o.m_steamIDRemote );
|
||||
}
|
||||
|
||||
public enum EP2PSend : int
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic UDP send. Packets can't be bigger than 1200 bytes (your typical MTU size). Can be lost, or arrive out of order (rare).
|
||||
/// The sending API does have some knowledge of the underlying connection, so if there is no NAT-traversal accomplished or
|
||||
/// there is a recognized adjustment happening on the connection, the packet will be batched until the connection is open again.
|
||||
/// </summary>
|
||||
|
||||
Unreliable = 0,
|
||||
|
||||
/// <summary>
|
||||
/// As above, but if the underlying p2p connection isn't yet established the packet will just be thrown away. Using this on the first
|
||||
/// packet sent to a remote host almost guarantees the packet will be dropped.
|
||||
/// This is only really useful for kinds of data that should never buffer up, i.e. voice payload packets
|
||||
/// </summary>
|
||||
UnreliableNoDelay = 1,
|
||||
|
||||
//// <summary>
|
||||
/// Reliable message send. Can send up to 1MB of data in a single message.
|
||||
/// Does fragmentation/re-assembly of messages under the hood, as well as a sliding window for efficient sends of large chunks of data.
|
||||
/// </summary>
|
||||
Reliable = 2,
|
||||
|
||||
/// <summary>
|
||||
/// As above, but applies the Nagle algorithm to the send - sends will accumulate
|
||||
/// until the current MTU size (typically ~1200 bytes, but can change) or ~200ms has passed (Nagle algorithm).
|
||||
/// Useful if you want to send a set of smaller messages but have the coalesced into a single packet
|
||||
/// Since the reliable stream is all ordered, you can do several small message sends with k_EP2PSendReliableWithBuffering and then
|
||||
/// do a normal k_EP2PSendReliable to force all the buffered data to be sent.
|
||||
/// </summary>
|
||||
ReliableWithBuffering = 3,
|
||||
|
||||
}
|
||||
|
||||
public unsafe bool SendP2PPacket( ulong steamid, byte[] data, int length, EP2PSend eP2PSendType = EP2PSend.Reliable, int nChannel = 0 )
|
||||
{
|
||||
fixed ( byte* p = data )
|
||||
{
|
||||
return client._networking.SendP2PPacket( steamid, (IntPtr) p, (uint)length, (uint)eP2PSendType, nChannel );
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe bool ReadP2PPacket( MemoryStream ms, int channel = 0 )
|
||||
{
|
||||
uint DataAvailable = 0;
|
||||
|
||||
if ( !client._networking.IsP2PPacketAvailable( ref DataAvailable, channel ) || DataAvailable == 0 )
|
||||
return false;
|
||||
|
||||
if ( ms.Capacity < DataAvailable )
|
||||
ms.Capacity = (int) DataAvailable;
|
||||
|
||||
ms.Position = 0;
|
||||
ms.SetLength( DataAvailable );
|
||||
|
||||
fixed ( byte* p = ms.GetBuffer() )
|
||||
{
|
||||
ulong steamid = 1;
|
||||
if ( !client._networking.ReadP2PPacket( (IntPtr)p, (uint)DataAvailable, ref DataAvailable, ref steamid, channel ) || DataAvailable == 0 )
|
||||
return false;
|
||||
|
||||
ms.SetLength( DataAvailable );
|
||||
|
||||
OnP2PData?.Invoke( steamid, ms, channel );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ public partial class Client : IDisposable
|
||||
internal Valve.Steamworks.ISteamFriends _friends;
|
||||
internal Valve.Steamworks.ISteamMatchmakingServers _servers;
|
||||
internal Valve.Steamworks.ISteamInventory _inventory;
|
||||
internal Valve.Steamworks.ISteamNetworking _networking;
|
||||
|
||||
/// <summary>
|
||||
/// Current running program's AppId
|
||||
@ -62,6 +63,7 @@ public Client( uint appId )
|
||||
_user = _client.GetISteamUser( _huser, _hpipe, "SteamUser019" );
|
||||
_servers = _client.GetISteamMatchmakingServers( _huser, _hpipe, "SteamMatchMakingServers002" );
|
||||
_inventory = _client.GetISteamInventory( _huser, _hpipe, "STEAMINVENTORY_INTERFACE_V001" );
|
||||
_networking = _client.GetISteamNetworking( _huser, _hpipe, "SteamNetworking005" );
|
||||
|
||||
AppId = appId;
|
||||
Username = _friends.GetPersonaName();
|
||||
@ -106,6 +108,7 @@ public void Update()
|
||||
Valve.Steamworks.SteamAPI.RunCallbacks();
|
||||
Voice.Update();
|
||||
Inventory.Update();
|
||||
Networking.Update();
|
||||
}
|
||||
|
||||
public bool Valid
|
||||
@ -113,7 +116,7 @@ public bool Valid
|
||||
get { return _client != null; }
|
||||
}
|
||||
|
||||
internal Action InstallCallback<T>( int type, Action<T> action )
|
||||
internal Action InstallCallback( int type, Delegate action )
|
||||
{
|
||||
var ptr = Marshal.GetFunctionPointerForDelegate( action );
|
||||
Valve.Steamworks.SteamAPI.RegisterCallback( ptr, type );
|
||||
|
@ -113,6 +113,7 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Client.Networking.cs" />
|
||||
<Compile Include="Client.Overlay.cs" />
|
||||
<Compile Include="Client.ServerList.cs" />
|
||||
<Compile Include="Client.ServerList.Request.cs" />
|
||||
|
@ -710,7 +710,7 @@ internal class NativeEntrypoints
|
||||
[DllImportAttribute( "FacepunchSteamworksApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SteamAPI_ISteamNetworking_IsP2PPacketAvailable" )]
|
||||
internal static extern bool SteamAPI_ISteamNetworking_IsP2PPacketAvailable( IntPtr instancePtr, ref uint pcubMsgSize, int nChannel );
|
||||
[DllImportAttribute( "FacepunchSteamworksApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SteamAPI_ISteamNetworking_ReadP2PPacket" )]
|
||||
internal static extern bool SteamAPI_ISteamNetworking_ReadP2PPacket( IntPtr instancePtr, IntPtr pubDest, uint cubDest, ref uint pcubMsgSize, ref CSteamID psteamIDRemote, int nChannel );
|
||||
internal static extern bool SteamAPI_ISteamNetworking_ReadP2PPacket( IntPtr instancePtr, IntPtr pubDest, uint cubDest, ref uint pcubMsgSize, ref ulong psteamIDRemote, int nChannel );
|
||||
[DllImportAttribute( "FacepunchSteamworksApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SteamAPI_ISteamNetworking_AcceptP2PSessionWithUser" )]
|
||||
internal static extern bool SteamAPI_ISteamNetworking_AcceptP2PSessionWithUser( IntPtr instancePtr, ulong steamIDRemote );
|
||||
[DllImportAttribute( "FacepunchSteamworksApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SteamAPI_ISteamNetworking_CloseP2PSessionWithUser" )]
|
||||
@ -1982,7 +1982,7 @@ internal abstract class ISteamNetworking
|
||||
internal abstract IntPtr GetIntPtr();
|
||||
internal abstract bool SendP2PPacket( ulong steamIDRemote, IntPtr pubData, uint cubData, uint eP2PSendType, int nChannel );
|
||||
internal abstract bool IsP2PPacketAvailable( ref uint pcubMsgSize, int nChannel );
|
||||
internal abstract bool ReadP2PPacket( IntPtr pubDest, uint cubDest, ref uint pcubMsgSize, ref CSteamID psteamIDRemote, int nChannel );
|
||||
internal abstract bool ReadP2PPacket( IntPtr pubDest, uint cubDest, ref uint pcubMsgSize, ref ulong psteamIDRemote, int nChannel );
|
||||
internal abstract bool AcceptP2PSessionWithUser( ulong steamIDRemote );
|
||||
internal abstract bool CloseP2PSessionWithUser( ulong steamIDRemote );
|
||||
internal abstract bool CloseP2PChannelWithUser( ulong steamIDRemote, int nChannel );
|
||||
@ -2475,7 +2475,7 @@ internal override ISteamNetworking GetISteamNetworking( uint hSteamUser, uint hS
|
||||
{
|
||||
CheckIfUsable();
|
||||
IntPtr result = NativeEntrypoints.SteamAPI_ISteamClient_GetISteamNetworking(m_pSteamClient,hSteamUser,hSteamPipe,pchVersion);
|
||||
return (ISteamNetworking)Marshal.PtrToStructure( result, typeof( ISteamNetworking ) );
|
||||
return new CSteamNetworking( result );
|
||||
}
|
||||
internal override ISteamRemoteStorage GetISteamRemoteStorage( uint hSteamuser, uint hSteamPipe, string pchVersion )
|
||||
{
|
||||
@ -4730,7 +4730,7 @@ internal override bool IsP2PPacketAvailable( ref uint pcubMsgSize, int nChannel
|
||||
bool result = NativeEntrypoints.SteamAPI_ISteamNetworking_IsP2PPacketAvailable(m_pSteamNetworking,ref pcubMsgSize,nChannel);
|
||||
return result;
|
||||
}
|
||||
internal override bool ReadP2PPacket( IntPtr pubDest, uint cubDest, ref uint pcubMsgSize, ref CSteamID psteamIDRemote, int nChannel )
|
||||
internal override bool ReadP2PPacket( IntPtr pubDest, uint cubDest, ref uint pcubMsgSize, ref ulong psteamIDRemote, int nChannel )
|
||||
{
|
||||
CheckIfUsable();
|
||||
pcubMsgSize = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user