Fix for duplicate OnDisconnected callbacks when ConnectionState.ClosedByPeer or ConnectionState.ProblemDetectedLocally were followed by ConnectionState.None

This commit is contained in:
André Straubmeier 2020-08-19 18:27:09 +02:00
parent 4a2eb22ec7
commit f84872b38c
4 changed files with 55 additions and 22 deletions

View File

@ -1,7 +1,6 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Steamworks.Data; using Steamworks.Data;
@ -14,8 +13,6 @@ namespace Steamworks
{ {
public bool HasFinished = false; public bool HasFinished = false;
public List<Connection> Connected = new List<Connection>();
public override void OnConnectionChanged( Connection connection, ConnectionInfo data ) public override void OnConnectionChanged( Connection connection, ConnectionInfo data )
{ {
Console.WriteLine( $"[Socket{Socket}][connection:{connection}][data.Identity:{data.Identity}] [data.State:{data.State}]" ); Console.WriteLine( $"[Socket{Socket}][connection:{connection}][data.Identity:{data.Identity}] [data.State:{data.State}]" );
@ -34,8 +31,6 @@ namespace Steamworks
/// </summary> /// </summary>
public override void OnConnected( Connection connection, ConnectionInfo data ) public override void OnConnected( Connection connection, ConnectionInfo data )
{ {
Connected.Add( connection );
Console.WriteLine( $"" ); Console.WriteLine( $"" );
Console.WriteLine( $"Socket -> OnConnected:" ); Console.WriteLine( $"Socket -> OnConnected:" );
Console.WriteLine( $" data.Address: {data.Address}" ); Console.WriteLine( $" data.Address: {data.Address}" );
@ -57,8 +52,6 @@ namespace Steamworks
/// </summary> /// </summary>
public override void OnDisconnected( Connection connection, ConnectionInfo data ) public override void OnDisconnected( Connection connection, ConnectionInfo data )
{ {
Connected.Remove( connection );
Console.WriteLine( $" - OnDisconnected" ); Console.WriteLine( $" - OnDisconnected" );
base.OnDisconnected( connection, data ); base.OnDisconnected( connection, data );

View File

@ -11,10 +11,11 @@ namespace Steamworks.Data
/// You can override all the virtual functions to turn it into what you /// You can override all the virtual functions to turn it into what you
/// want it to do. /// want it to do.
/// </summary> /// </summary>
public struct Connection public struct Connection : IEquatable<Connection>
{ {
public uint Id { get; set; } public uint Id { get; set; }
public bool Equals( Connection other ) => Id == other.Id;
public override string ToString() => Id.ToString(); public override string ToString() => Id.ToString();
public static implicit operator Connection( uint value ) => new Connection() { Id = value }; public static implicit operator Connection( uint value ) => new Connection() { Id = value };
public static implicit operator uint( Connection value ) => value.Id; public static implicit operator uint( Connection value ) => value.Id;

View File

@ -47,18 +47,40 @@ namespace Steamworks
{ {
ConnectionInfo = info; ConnectionInfo = info;
//
// Some notes:
// - Update state before the callbacks, in case an exception is thrown
// - ConnectionState.None happens when a connection is destroyed, even if it was already disconnected (ClosedByPeer / ProblemDetectedLocally)
//
switch ( info.State ) switch ( info.State )
{ {
case ConnectionState.Connecting: case ConnectionState.Connecting:
if ( !Connecting && !Connected )
{
Connecting = true;
OnConnecting( info ); OnConnecting( info );
}
break; break;
case ConnectionState.Connected: case ConnectionState.Connected:
if ( Connecting && !Connected )
{
Connecting = false;
Connected = true;
OnConnected( info ); OnConnected( info );
}
break; break;
case ConnectionState.ClosedByPeer: case ConnectionState.ClosedByPeer:
case ConnectionState.ProblemDetectedLocally: case ConnectionState.ProblemDetectedLocally:
case ConnectionState.None: case ConnectionState.None:
if ( Connecting || Connected )
{
Connecting = false;
Connected = false;
OnDisconnected( info ); OnDisconnected( info );
}
break; break;
} }
} }
@ -69,8 +91,6 @@ namespace Steamworks
public virtual void OnConnecting( ConnectionInfo info ) public virtual void OnConnecting( ConnectionInfo info )
{ {
Interface?.OnConnecting( info ); Interface?.OnConnecting( info );
Connecting = true;
} }
/// <summary> /// <summary>
@ -79,9 +99,6 @@ namespace Steamworks
public virtual void OnConnected( ConnectionInfo info ) public virtual void OnConnected( ConnectionInfo info )
{ {
Interface?.OnConnected( info ); Interface?.OnConnected( info );
Connected = true;
Connecting = false;
} }
/// <summary> /// <summary>
@ -90,9 +107,6 @@ namespace Steamworks
public virtual void OnDisconnected( ConnectionInfo info ) public virtual void OnDisconnected( ConnectionInfo info )
{ {
Interface?.OnDisconnected( info ); Interface?.OnDisconnected( info );
Connected = false;
Connecting = false;
} }
public void Receive( int bufferSize = 32 ) public void Receive( int bufferSize = 32 )

View File

@ -16,6 +16,9 @@ namespace Steamworks
{ {
public ISocketManager Interface { get; set; } public ISocketManager Interface { get; set; }
public HashSet<Connection> Connecting = new HashSet<Connection>();
public HashSet<Connection> Connected = new HashSet<Connection>();
public Socket Socket { get; internal set; } public Socket Socket { get; internal set; }
public override string ToString() => Socket.ToString(); public override string ToString() => Socket.ToString();
@ -42,18 +45,40 @@ namespace Steamworks
public virtual void OnConnectionChanged( Connection connection, ConnectionInfo info ) public virtual void OnConnectionChanged( Connection connection, ConnectionInfo info )
{ {
//
// Some notes:
// - Update state before the callbacks, in case an exception is thrown
// - ConnectionState.None happens when a connection is destroyed, even if it was already disconnected (ClosedByPeer / ProblemDetectedLocally)
//
switch ( info.State ) switch ( info.State )
{ {
case ConnectionState.Connecting: case ConnectionState.Connecting:
if ( !Connecting.Contains( connection ) && !Connected.Contains( connection ) )
{
Connecting.Add( connection );
OnConnecting( connection, info ); OnConnecting( connection, info );
}
break; break;
case ConnectionState.Connected: case ConnectionState.Connected:
if ( Connecting.Contains( connection ) && !Connected.Contains( connection ) )
{
Connecting.Remove( connection );
Connected.Add( connection );
OnConnected( connection, info ); OnConnected( connection, info );
}
break; break;
case ConnectionState.ClosedByPeer: case ConnectionState.ClosedByPeer:
case ConnectionState.ProblemDetectedLocally: case ConnectionState.ProblemDetectedLocally:
case ConnectionState.None: case ConnectionState.None:
if ( Connecting.Contains( connection ) || Connected.Contains( connection ) )
{
Connecting.Remove( connection );
Connected.Remove( connection );
OnDisconnected( connection, info ); OnDisconnected( connection, info );
}
break; break;
} }
} }