diff --git a/Facepunch.Steamworks.Test/Facepunch.Steamworks.TestWin32.csproj b/Facepunch.Steamworks.Test/Facepunch.Steamworks.TestWin32.csproj index 03f2d4b..9b2faa0 100644 --- a/Facepunch.Steamworks.Test/Facepunch.Steamworks.TestWin32.csproj +++ b/Facepunch.Steamworks.Test/Facepunch.Steamworks.TestWin32.csproj @@ -99,6 +99,8 @@ + + diff --git a/Facepunch.Steamworks.Test/Facepunch.Steamworks.TestWin64.csproj b/Facepunch.Steamworks.Test/Facepunch.Steamworks.TestWin64.csproj index 9f40a26..908c7b6 100644 --- a/Facepunch.Steamworks.Test/Facepunch.Steamworks.TestWin64.csproj +++ b/Facepunch.Steamworks.Test/Facepunch.Steamworks.TestWin64.csproj @@ -99,6 +99,8 @@ + + diff --git a/Facepunch.Steamworks.Test/NetworkingSockets.cs b/Facepunch.Steamworks.Test/NetworkingSockets.cs index bcaa549..16c1ea3 100644 --- a/Facepunch.Steamworks.Test/NetworkingSockets.cs +++ b/Facepunch.Steamworks.Test/NetworkingSockets.cs @@ -9,10 +9,10 @@ namespace Steamworks { - [TestClass] + [TestClass] [DeploymentItem( "steam_api64.dll" )] [DeploymentItem( "steam_api.dll" )] - public class NetworkingSocketsTest + public partial class NetworkingSocketsTest { [TestMethod] @@ -46,16 +46,18 @@ public async Task RelayEndtoEnd() { SteamNetworkingUtils.InitRelayNetworkAccess(); + // For some reason giving steam a couple of seconds here + // seems to prevent it returning null connections from ConnectNormal + await Task.Delay( 2000 ); + Console.WriteLine( $"----- Creating Socket Relay Socket.." ); - var socket = SteamNetworkingSockets.CreateRelaySocket( 7788 ); + var socket = SteamNetworkingSockets.CreateRelaySocket( 6 ); var server = socket.RunAsync(); - Console.WriteLine( $"----- Created Relay Socket: {(uint)socket.Socket}" ); - - await Task.Delay( 5000 ); + await Task.Delay( 1000 ); Console.WriteLine( $"----- Connecting To Socket via SteamId ({SteamClient.SteamId})" ); - var connection = SteamNetworkingSockets.ConnectRelay( SteamClient.SteamId, 7788 ); + var connection = SteamNetworkingSockets.ConnectRelay( SteamClient.SteamId, 6 ); var client = connection.RunAsync(); await Task.WhenAll( server, client ); @@ -64,231 +66,26 @@ public async Task RelayEndtoEnd() [TestMethod] public async Task NormalEndtoEnd() { + // For some reason giving steam a couple of seconds here + // seems to prevent it returning null connections from ConnectNormal + await Task.Delay( 2000 ); + + // + // Start the server + // + Console.WriteLine( "CreateNormalSocket" ); var socket = SteamNetworkingSockets.CreateNormalSocket( NetAddress.AnyIp( 12445 ) ); var server = socket.RunAsync(); - await Task.Delay( 5000 ); - + // + // Start the client + // + Console.WriteLine( "ConnectNormal" ); var connection = SteamNetworkingSockets.ConnectNormal( NetAddress.From( System.Net.IPAddress.Parse( "127.0.0.1" ), 12445 ) ); var client = connection.RunAsync(); await Task.WhenAll( server, client ); } - - private class TestConnectionInterface : ConnectionInterface - { - public override void OnConnectionChanged( ConnectionInfo data ) - { - Console.WriteLine( $"[Connection][{Connection}] [{data.State}]" ); - - base.OnConnectionChanged( data ); - } - - public override void OnConnecting( ConnectionInfo data ) - { - Console.WriteLine( $" - OnConnecting" ); - base.OnConnecting( data ); - } - - /// - /// Client is connected. They move from connecting to Connections - /// - public override void OnConnected( ConnectionInfo data ) - { - Console.WriteLine( $" - OnConnected" ); - base.OnConnected( data ); - } - - /// - /// The connection has been closed remotely or disconnected locally. Check data.State for details. - /// - public override void OnDisconnected( ConnectionInfo data ) - { - Console.WriteLine( $" - OnDisconnected" ); - base.OnDisconnected( data ); - } - - internal async Task RunAsync() - { - Console.WriteLine( "[Connection] RunAsync" ); - - var sw = System.Diagnostics.Stopwatch.StartNew(); - - while ( Connecting ) - { - await Task.Delay( 10 ); - - if ( sw.Elapsed.TotalSeconds > 30 ) - break; - } - - if ( !Connected ) - { - Console.WriteLine( "[Connection] Couldn't connect!" ); - Console.WriteLine( Connection.DetailedStatus() ); - return; - } - - Console.WriteLine( "[Connection] Hey We're Connected!" ); - - - sw = System.Diagnostics.Stopwatch.StartNew(); - while ( Connected ) - { - Receive(); - await Task.Delay( 100 ); - - if ( sw.Elapsed.TotalSeconds > 10 ) - { - Assert.Fail( "Client Took Too Long" ); - break; - } - } - } - - public override unsafe void OnMessage( IntPtr data, int size, long messageNum, long recvTime, int channel ) - { - // We're only sending strings, so it's fine to read this like this - var str = UTF8Encoding.UTF8.GetString( (byte*) data, size ); - - Console.WriteLine( $"[Connection][{messageNum}][{recvTime}][{channel}] \"{str}\"" ); - - if ( str.Contains( "Hello" ) ) - { - Connection.SendMessage( "Hello, How are you!?" ); - - Connection.SendMessage( "How do you like 20 messages in a row?" ); - - for ( int i=0; i<20; i++ ) - { - Connection.SendMessage( $"BLAMMO!" ); - } - } - - if ( str.Contains( "status" )) - { - Console.WriteLine( Connection.DetailedStatus() ); - } - - if ( str.Contains( "how about yourself" ) ) - { - Connection.SendMessage( "I'm great, but I have to go now, bye." ); - } - - if ( str.Contains( "hater" ) ) - { - Close(); - } - - } - } - - - private class TestSocketInterface : SocketInterface - { - public bool HasFinished = false; - - public override void OnConnectionChanged( Connection connection, ConnectionInfo data ) - { - Console.WriteLine( $"[Socket{Socket}][{connection}] [{data.State}]" ); - - base.OnConnectionChanged( connection, data ); - } - - public override void OnConnecting( Connection connection, ConnectionInfo data ) - { - Console.WriteLine( $" - OnConnecting" ); - base.OnConnecting( connection, data ); - } - - /// - /// Client is connected. They move from connecting to Connections - /// - public override void OnConnected( Connection connection, ConnectionInfo data ) - { - Console.WriteLine( $" - OnConnected" ); - base.OnConnected( connection, data ); - } - - /// - /// The connection has been closed remotely or disconnected locally. Check data.State for details. - /// - public override void OnDisconnected( Connection connection, ConnectionInfo data ) - { - Console.WriteLine( $" - OnDisconnected" ); - base.OnDisconnected( connection, data ); - } - - internal async Task RunAsync() - { - var sw = System.Diagnostics.Stopwatch.StartNew(); - - while ( Connected.Count == 0 ) - { - await Task.Delay( 10 ); - - if ( sw.Elapsed.TotalSeconds > 2 ) - { - Assert.Fail( "Client Took Too Long To Connect" ); - break; - } - } - - await Task.Delay( 1000 ); - - var singleClient = Connected.First(); - - singleClient.SendMessage( "Hey?" ); - await Task.Delay( 100 ); - singleClient.SendMessage( "Anyone?" ); - await Task.Delay( 100 ); - singleClient.SendMessage( "What's this?" ); - await Task.Delay( 100 ); - singleClient.SendMessage( "What's your status?" ); - await Task.Delay( 10 ); - singleClient.SendMessage( "Greetings!!??" ); - await Task.Delay( 100 ); - singleClient.SendMessage( "Hello Client!?" ); - - sw = System.Diagnostics.Stopwatch.StartNew(); - - while ( Connected.Contains( singleClient ) ) - { - Receive(); - await Task.Delay( 100 ); - - if ( sw.Elapsed.TotalSeconds > 10 ) - { - Assert.Fail( "Socket Took Too Long" ); - break; - } - } - - await Task.Delay( 1000 ); - - Close(); - } - - public override unsafe void OnMessage( Connection connection, NetIdentity identity, IntPtr data, int size, long messageNum, long recvTime, int channel ) - { - // We're only sending strings, so it's fine to read this like this - var str = UTF8Encoding.UTF8.GetString( (byte*)data, size ); - - Console.WriteLine( $"[SOCKET][{connection}[{identity}][{messageNum}][{recvTime}][{channel}] \"{str}\"" ); - - if ( str.Contains( "Hello, How are you" ) ) - { - connection.SendMessage( "I'm great thanks, how about yourself?" ); - } - - if ( str.Contains( "bye" ) ) - { - connection.SendMessage( "See you later, hater." ); - connection.Flush(); - connection.Close( true, 10, "Said Bye" ); - } - } - } } } \ No newline at end of file diff --git a/Facepunch.Steamworks.Test/NetworkingSocketsTest.TestConnectionInterface.cs b/Facepunch.Steamworks.Test/NetworkingSocketsTest.TestConnectionInterface.cs new file mode 100644 index 0000000..e5b5756 --- /dev/null +++ b/Facepunch.Steamworks.Test/NetworkingSocketsTest.TestConnectionInterface.cs @@ -0,0 +1,120 @@ +using System; +using System.Text; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Steamworks.Data; + +namespace Steamworks +{ + public partial class NetworkingSocketsTest + { + private class TestConnectionInterface : ConnectionInterface + { + public override void OnConnectionChanged( ConnectionInfo data ) + { + Console.WriteLine( $"[Connection][{Connection}] [{data.State}]" ); + + base.OnConnectionChanged( data ); + } + + public override void OnConnecting( ConnectionInfo data ) + { + Console.WriteLine( $" - OnConnecting" ); + base.OnConnecting( data ); + } + + /// + /// Client is connected. They move from connecting to Connections + /// + public override void OnConnected( ConnectionInfo data ) + { + Console.WriteLine( $" - OnConnected" ); + base.OnConnected( data ); + } + + /// + /// The connection has been closed remotely or disconnected locally. Check data.State for details. + /// + public override void OnDisconnected( ConnectionInfo data ) + { + Console.WriteLine( $" - OnDisconnected" ); + base.OnDisconnected( data ); + } + + internal async Task RunAsync() + { + Console.WriteLine( "[Connection] RunAsync" ); + + var sw = System.Diagnostics.Stopwatch.StartNew(); + + while ( Connecting ) + { + await Task.Delay( 10 ); + + if ( sw.Elapsed.TotalSeconds > 30 ) + break; + } + + if ( !Connected ) + { + Console.WriteLine( "[Connection] Couldn't connect!" ); + Console.WriteLine( Connection.DetailedStatus() ); + return; + } + + Console.WriteLine( "[Connection] Hey We're Connected!" ); + + + sw = System.Diagnostics.Stopwatch.StartNew(); + while ( Connected ) + { + Receive(); + await Task.Delay( 100 ); + + if ( sw.Elapsed.TotalSeconds > 10 ) + { + Assert.Fail( "Client Took Too Long" ); + break; + } + } + } + + public override unsafe void OnMessage( IntPtr data, int size, long messageNum, long recvTime, int channel ) + { + // We're only sending strings, so it's fine to read this like this + var str = UTF8Encoding.UTF8.GetString( (byte*) data, size ); + + Console.WriteLine( $"[Connection][{messageNum}][{recvTime}][{channel}] \"{str}\"" ); + + if ( str.Contains( "Hello" ) ) + { + Connection.SendMessage( "Hello, How are you!?" ); + + Connection.SendMessage( "How do you like 20 messages in a row?" ); + + for ( int i=0; i<20; i++ ) + { + Connection.SendMessage( $"BLAMMO!" ); + } + } + + if ( str.Contains( "status" )) + { + Console.WriteLine( Connection.DetailedStatus() ); + } + + if ( str.Contains( "how about yourself" ) ) + { + Connection.SendMessage( "I'm great, but I have to go now, bye." ); + } + + if ( str.Contains( "hater" ) ) + { + Close(); + } + + } + } + } + +} \ No newline at end of file diff --git a/Facepunch.Steamworks.Test/NetworkingSocketsTest.TestSocketInterface.cs b/Facepunch.Steamworks.Test/NetworkingSocketsTest.TestSocketInterface.cs new file mode 100644 index 0000000..8941fcb --- /dev/null +++ b/Facepunch.Steamworks.Test/NetworkingSocketsTest.TestSocketInterface.cs @@ -0,0 +1,119 @@ +using System; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Steamworks.Data; + +namespace Steamworks +{ + public partial class NetworkingSocketsTest + { + private class TestSocketInterface : SocketInterface + { + public bool HasFinished = false; + + public override void OnConnectionChanged( Connection connection, ConnectionInfo data ) + { + Console.WriteLine( $"[Socket{Socket}][{connection}] [{data.State}]" ); + + base.OnConnectionChanged( connection, data ); + } + + public override void OnConnecting( Connection connection, ConnectionInfo data ) + { + Console.WriteLine( $" - OnConnecting" ); + base.OnConnecting( connection, data ); + } + + /// + /// Client is connected. They move from connecting to Connections + /// + public override void OnConnected( Connection connection, ConnectionInfo data ) + { + Console.WriteLine( $" - OnConnected" ); + base.OnConnected( connection, data ); + } + + /// + /// The connection has been closed remotely or disconnected locally. Check data.State for details. + /// + public override void OnDisconnected( Connection connection, ConnectionInfo data ) + { + Console.WriteLine( $" - OnDisconnected" ); + base.OnDisconnected( connection, data ); + } + + internal async Task RunAsync() + { + var sw = System.Diagnostics.Stopwatch.StartNew(); + + while ( Connected.Count == 0 ) + { + await Task.Delay( 10 ); + + if ( sw.Elapsed.TotalSeconds > 5 ) + { + Assert.Fail( "Client Took Too Long To Connect" ); + break; + } + } + + await Task.Delay( 1000 ); + + var singleClient = Connected.First(); + + singleClient.SendMessage( "Hey?" ); + await Task.Delay( 100 ); + singleClient.SendMessage( "Anyone?" ); + await Task.Delay( 100 ); + singleClient.SendMessage( "What's this?" ); + await Task.Delay( 100 ); + singleClient.SendMessage( "What's your status?" ); + await Task.Delay( 10 ); + singleClient.SendMessage( "Greetings!!??" ); + await Task.Delay( 100 ); + singleClient.SendMessage( "Hello Client!?" ); + + sw = System.Diagnostics.Stopwatch.StartNew(); + + while ( Connected.Contains( singleClient ) ) + { + Receive(); + await Task.Delay( 100 ); + + if ( sw.Elapsed.TotalSeconds > 10 ) + { + Assert.Fail( "Socket Took Too Long" ); + break; + } + } + + await Task.Delay( 1000 ); + + Close(); + } + + public override unsafe void OnMessage( Connection connection, NetIdentity identity, IntPtr data, int size, long messageNum, long recvTime, int channel ) + { + // We're only sending strings, so it's fine to read this like this + var str = UTF8Encoding.UTF8.GetString( (byte*)data, size ); + + Console.WriteLine( $"[SOCKET][{connection}[{identity}][{messageNum}][{recvTime}][{channel}] \"{str}\"" ); + + if ( str.Contains( "Hello, How are you" ) ) + { + connection.SendMessage( "I'm great thanks, how about yourself?" ); + } + + if ( str.Contains( "bye" ) ) + { + connection.SendMessage( "See you later, hater." ); + connection.Flush(); + connection.Close( true, 10, "Said Bye" ); + } + } + } + } + +} \ No newline at end of file diff --git a/Facepunch.Steamworks/Classes/SocketInterface.cs b/Facepunch.Steamworks/Classes/SocketInterface.cs index d6998d1..44c13c7 100644 --- a/Facepunch.Steamworks/Classes/SocketInterface.cs +++ b/Facepunch.Steamworks/Classes/SocketInterface.cs @@ -11,10 +11,28 @@ public class SocketInterface public List Connected = new List(); public Socket Socket { get; internal set; } - public bool Close() => Socket.Close(); - public override string ToString() => Socket.ToString(); + internal HSteamNetPollGroup pollGroup; + + internal void Initialize() + { + pollGroup = SteamNetworkingSockets.Internal.CreatePollGroup(); + } + + public bool Close() + { + if ( SteamNetworkingSockets.Internal.IsValid ) + { + SteamNetworkingSockets.Internal.DestroyPollGroup( pollGroup ); + Socket.Close(); + } + + pollGroup = 0; + Socket = 0; + return true; + } + public virtual void OnConnectionChanged( Connection connection, ConnectionInfo data ) { switch ( data.State ) @@ -40,6 +58,8 @@ public virtual void OnConnecting( Connection connection, ConnectionInfo data ) { connection.Accept(); Connecting.Add( connection ); + + SteamNetworkingSockets.Internal.SetConnectionPollGroup( connection, pollGroup ); } /// @@ -67,10 +87,10 @@ public void Receive( int bufferSize = 32 ) int processed = 0; IntPtr messageBuffer = Marshal.AllocHGlobal( IntPtr.Size * bufferSize ); - /* + try { - processed = SteamNetworkingSockets.Internal.ReceiveMessagesOnListenSocket( Socket, messageBuffer, bufferSize ); + processed = SteamNetworkingSockets.Internal.ReceiveMessagesOnPollGroup( pollGroup, messageBuffer, bufferSize ); for ( int i = 0; i < processed; i++ ) { @@ -81,7 +101,7 @@ public void Receive( int bufferSize = 32 ) { Marshal.FreeHGlobal( messageBuffer ); } - */ + // // Overwhelmed our buffer, keep going diff --git a/Facepunch.Steamworks/SteamNetworkingSockets.cs b/Facepunch.Steamworks/SteamNetworkingSockets.cs index 09e3bff..6e2b38f 100644 --- a/Facepunch.Steamworks/SteamNetworkingSockets.cs +++ b/Facepunch.Steamworks/SteamNetworkingSockets.cs @@ -73,9 +73,10 @@ internal static void SetConnectionInterface( uint id, ConnectionInterface iface internal static void InstallEvents( bool server = false ) { - Dispatch.Install( x => ConnectionStatusChanged( x ), server ); + Dispatch.Install( ConnectionStatusChanged, server ); } + private static void ConnectionStatusChanged( SteamNetConnectionStatusChangedCallback_t data ) { // @@ -107,6 +108,8 @@ private static void ConnectionStatusChanged( SteamNetConnectionStatusChangedCall var t = new T(); var options = new NetKeyValue[0]; t.Socket = Internal.CreateListenSocketIP( ref address, options.Length, options ); + t.Initialize(); + SetSocketInterface( t.Socket.Id, t ); return t; } diff --git a/Facepunch.Steamworks/Structs/Connection.cs b/Facepunch.Steamworks/Structs/Connection.cs index 48c2046..eaac660 100644 --- a/Facepunch.Steamworks/Structs/Connection.cs +++ b/Facepunch.Steamworks/Structs/Connection.cs @@ -94,27 +94,5 @@ public string DetailedStatus() return strVal; } - - /* - [ThreadStatic] - private static SteamNetworkingMessage_t[] messageBuffer; - - public IEnumerable Messages - { - get - { - if ( messageBuffer == null ) - messageBuffer = new SteamNetworkingMessage_t[128]; - - var num = SteamNetworkingSockets.Internal.ReceiveMessagesOnConnection( this, ref messageBuffer, messageBuffer.Length ); - - for ( int i = 0; i < num; i++) - { - yield return messageBuffer[i]; - messageBuffer[i].Release(); - } - } - }*/ - } } diff --git a/Facepunch.Steamworks/Structs/NetIdentity.cs b/Facepunch.Steamworks/Structs/NetIdentity.cs index c466c99..aaa2c85 100644 --- a/Facepunch.Steamworks/Structs/NetIdentity.cs +++ b/Facepunch.Steamworks/Structs/NetIdentity.cs @@ -24,7 +24,12 @@ public static implicit operator SteamId( NetIdentity value ) return value.steamID; } - public override string ToString() => $"{type};{m_cbSize};{steamID}"; + public override string ToString() + { + var id = this; + SteamNetworkingUtils.Internal.SteamNetworkingIdentity_ToString( ref id, out var str ); + return str; + } internal enum IdentityType { diff --git a/Facepunch.Steamworks/Structs/Socket.cs b/Facepunch.Steamworks/Structs/Socket.cs index 864223e..24cbc71 100644 --- a/Facepunch.Steamworks/Structs/Socket.cs +++ b/Facepunch.Steamworks/Structs/Socket.cs @@ -17,7 +17,7 @@ public struct Socket /// public bool Close() { - return SteamNetworkingSockets.Internal.CloseListenSocket( this ); + return SteamNetworkingSockets.Internal.CloseListenSocket( Id ); } public SocketInterface Interface