add proper support for master NAK messages; ensure states are properly reset when a connection error occurs;

4.32j_maint
Bryan Biedenkapp 10 months ago
parent 0419c2fac7
commit 78e74f9074

@ -66,7 +66,58 @@ namespace fnecore
} // public enum ConnectionState
/// <summary>
///
/// Peer Connection NAK Messages
/// </summary>
public enum ConnectionMSTNAK
{
/// <summary>
/// General Failure
/// </summary>
GENERAL_FAILURE,
/// <summary>
/// Mode Not Enabled
/// </summary>
MODE_NOT_ENABLED,
/// <summary>
/// Illegal Packet
/// </summary>
ILLEGAL_PACKET,
/// <summary>
/// FNE Unauthorized
/// </summary>
FNE_UNAUTHORIZED,
/// <summary>
/// Bad Connection State
/// </summary>
BAD_CONN_STATE,
/// <summary>
/// Invalid Configuration Data
/// </summary>
INVALID_CONFIG_DATA,
/// <summary>
/// Peer Reset
/// </summary>
PEER_RESET,
/// <summary>
/// Peer ACL
/// </summary>
PEER_ACL,
/// <summary>
/// FNE Maximum Connections
/// </summary>
FNE_MAX_CONN,
/// <summary>
/// Invalid
/// </summary>
INVALID = 0xFFFF
} // public enum ConnectionMSTNAK
/// <summary>
/// Call Type
/// </summary>
public enum CallType : byte
{
@ -81,7 +132,7 @@ namespace fnecore
} // public enum CallType : byte
/// <summary>
///
/// Frame Type
/// </summary>
public enum FrameType : byte
{
@ -105,7 +156,7 @@ namespace fnecore
} // public enum FrameType : byte
/// <summary>
///
/// DVM State
/// </summary>
public enum DVMState : byte
{

@ -163,11 +163,6 @@ namespace fnecore
/// </summary>
public ConnectionState State;
/// <summary>
/// Flag indicating peer is "connected".
/// </summary>
public bool Connection;
/// <summary>
/// Number of pings received.
/// </summary>

@ -27,6 +27,7 @@ using fnecore.DMR;
using fnecore.P25;
using fnecore.NXDN;
using fnecore.P25.KMM;
using System.Net.NetworkInformation;
namespace fnecore
{
@ -142,7 +143,7 @@ namespace fnecore
info = new PeerInformation();
info.PeerID = peerId;
info.Connection = false;
info.State = ConnectionState.WAITING_LOGIN;
PingsAcked = 0;
}
@ -557,8 +558,67 @@ namespace fnecore
{
if (this.peerId == peerId)
{
info.Connection = false;
Log(LogLevel.DEBUG, $"({systemName}) PEER {this.peerId} MSTNAK received");
// DVM 3.6 adds support to respond with a NAK reason, as such we just check if the NAK response is greater
// then 10 bytes and process the reason value
ConnectionMSTNAK reason = ConnectionMSTNAK.INVALID;
if (message.Length > 10)
{
reason = (ConnectionMSTNAK)FneUtils.ToUInt16(message, 10);
switch (reason)
{
case ConnectionMSTNAK.MODE_NOT_ENABLED:
Log(LogLevel.WARNING, $"({systemName}) PEER {this.peerId} master NAK; digital mode not enabled on FNE");
break;
case ConnectionMSTNAK.ILLEGAL_PACKET:
Log(LogLevel.WARNING, $"({systemName}) PEER {this.peerId} master NAK; illegal/unknown packet");
break;
case ConnectionMSTNAK.FNE_UNAUTHORIZED:
Log(LogLevel.WARNING, $"({systemName}) PEER {this.peerId} master NAK; unauthorized");
break;
case ConnectionMSTNAK.BAD_CONN_STATE:
Log(LogLevel.WARNING, $"({systemName}) PEER {this.peerId} master NAK; bad connection state");
break;
case ConnectionMSTNAK.INVALID_CONFIG_DATA:
Log(LogLevel.WARNING, $"({systemName}) PEER {this.peerId} master NAK; invalid configuration data");
break;
case ConnectionMSTNAK.FNE_MAX_CONN:
Log(LogLevel.WARNING, $"({systemName}) PEER {this.peerId} master NAK; FNE has reached maximum permitted connections");
break;
case ConnectionMSTNAK.PEER_RESET:
Log(LogLevel.WARNING, $"({systemName}) PEER {this.peerId} master NAK; FNE demanded connection reset");
break;
case ConnectionMSTNAK.PEER_ACL:
Log(LogLevel.ERROR, $"({systemName}) PEER {this.peerId} master NAK; ACL rejection, network disabled");
info.State = ConnectionState.WAITING_LOGIN;
Stop();
break;
case ConnectionMSTNAK.GENERAL_FAILURE:
default:
Log(LogLevel.WARNING, $"({systemName}) PEER {this.peerId} master NAK; general failure");
break;
}
}
if (info.State == ConnectionState.RUNNING && (reason == ConnectionMSTNAK.FNE_MAX_CONN))
{
Log(LogLevel.WARNING, $"({systemName}) PEER {this.peerId} master NAK; attemping to relogin");
// reset states
PingsSent = 0;
PingsAcked = 0;
info.State = ConnectionState.WAITING_LOGIN;
}
else
{
Log(LogLevel.ERROR, $"({systemName}) PEER {this.peerId} master NAK; network reconnect");
// reset states
PingsSent = 0;
PingsAcked = 0;
info.State = ConnectionState.WAITING_LOGIN;
return;
}
}
}
break;
@ -664,7 +724,6 @@ namespace fnecore
else
{
info.State = ConnectionState.WAITING_LOGIN;
info.Connection = false;
Log(LogLevel.ERROR, $"({systemName}) PEER {this.peerId} master ACK contained wrong ID - connection reset");
}
}
@ -672,7 +731,6 @@ namespace fnecore
{
if (this.peerId == peerId)
{
info.Connection = true;
info.State = ConnectionState.RUNNING;
Log(LogLevel.INFO, $"({systemName}) PEER {this.peerId} connection to MASTER completed");
@ -682,7 +740,6 @@ namespace fnecore
else
{
info.State = ConnectionState.WAITING_LOGIN;
info.Connection = false;
Log(LogLevel.ERROR, $"({systemName}) PEER {this.peerId} master ACK contained wrong ID - connection reset");
}
}
@ -692,7 +749,7 @@ namespace fnecore
{
if (this.peerId == peerId)
{
info.Connection = false;
info.State = ConnectionState.WAITING_LOGIN;
Log(LogLevel.DEBUG, $"({systemName}) PEER {this.peerId} MSTCL received");
// userland actions
@ -740,6 +797,12 @@ namespace fnecore
catch (InvalidOperationException)
{
Log(LogLevel.ERROR, $"({systemName}) Not connected or lost connection to {masterEndpoint}; reconnecting...");
// reset states
PingsSent = 0;
PingsAcked = 0;
info.State = ConnectionState.WAITING_LOGIN;
client.Connect(masterEndpoint);
}
catch (SocketException se)
@ -752,6 +815,12 @@ namespace fnecore
case SocketError.ConnectionAborted:
case SocketError.ConnectionRefused:
Log(LogLevel.ERROR, $"({systemName}) Not connected or lost connection to {masterEndpoint}; reconnecting...");
// reset states
PingsSent = 0;
PingsAcked = 0;
info.State = ConnectionState.WAITING_LOGIN;
client.Connect(masterEndpoint);
break;
default:
@ -776,8 +845,9 @@ namespace fnecore
try
{
// if we're not connected, zero out the connection stats and send a login request to the master
if (!info.Connection || info.State == ConnectionState.WAITING_LOGIN)
if (info.State == ConnectionState.WAITING_LOGIN)
{
// reset states
PingsSent = 0;
PingsAcked = 0;
info.State = ConnectionState.WAITING_LOGIN;
@ -792,12 +862,13 @@ namespace fnecore
}
// if we are connected, sent a ping to the master and increment the counter
if (info.Connection && info.State == ConnectionState.RUNNING)
if (info.State == ConnectionState.RUNNING)
{
if (PingsSent > (PingsAcked + MAX_MISSED_PEER_PINGS))
{
Log(LogLevel.WARNING, $"({systemName} Peer connection lost to {masterEndpoint}; reconnecting...");
// reset states
PingsSent = 0;
PingsAcked = 0;
info.State = ConnectionState.WAITING_LOGIN;
@ -818,6 +889,12 @@ namespace fnecore
catch (InvalidOperationException)
{
Log(LogLevel.ERROR, $"({systemName}) Not connected or lost connection to {masterEndpoint}; reconnecting...");
// reset states
PingsSent = 0;
PingsAcked = 0;
info.State = ConnectionState.WAITING_LOGIN;
client.Connect(masterEndpoint);
}
catch (SocketException se)
@ -830,6 +907,12 @@ namespace fnecore
case SocketError.ConnectionAborted:
case SocketError.ConnectionRefused:
Log(LogLevel.ERROR, $"({systemName}) Not connected or lost connection to {masterEndpoint}; reconnecting...");
// reset states
PingsSent = 0;
PingsAcked = 0;
info.State = ConnectionState.WAITING_LOGIN;
client.Connect(masterEndpoint);
break;
default:

Loading…
Cancel
Save

Powered by TurnKey Linux.