Skip to content

Commit

Permalink
Issue: #27
Browse files Browse the repository at this point in the history
Added IrcReconnector, which handles all of the reconnection logic if our watchdog timer times out.

Hopefully this will prevent the consistent joining/rejoining issue we've seen.

The only thing left to do is to add FitNesse tests.
  • Loading branch information
xforever1313 committed Jan 21, 2018
1 parent 68602d7 commit 2b1e1cd
Show file tree
Hide file tree
Showing 3 changed files with 285 additions and 61 deletions.
1 change: 1 addition & 0 deletions Chaskis/ChaskisCore/ChaskisCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
<Compile Include="IHandlerConfig.cs" />
<Compile Include="IrcConfig.cs" />
<Compile Include="ChaskisPlugin.cs" />
<Compile Include="IrcReconnector.cs" />
<Compile Include="PluginInitor.cs" />
<Compile Include="PongHandler.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down
93 changes: 32 additions & 61 deletions Chaskis/ChaskisCore/IrcConnection.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright Seth Hendrick 2016-2017.
// Copyright Seth Hendrick 2016-2018.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
Expand Down Expand Up @@ -103,26 +103,15 @@ public class IrcConnection : IDisposable, IConnection, IChaskisEventScheduler, I
/// </summary>
private ManualResetEvent reconnectAbortEvent;

/// <summary>
/// Connection watch dog: Restarts the connection if
/// we can't talk to the server.
/// </summary>
private Thread connectionWatchDog;

private ManualResetEvent connectionWatchDogKeepGoing;

/// <summary>
/// Event that gets triggered when we get a pong.
/// </summary>
private AutoResetEvent connectionWatchDogPongEvent;

private bool inited;

/// <summary>
/// TODO: Remove this.
/// </summary>
private INonDisposableStringParsingQueue parsingQueue;

private IrcReconnector reconnector;

// -------- Constructor --------

/// <summary>
Expand Down Expand Up @@ -150,6 +139,18 @@ public IrcConnection( IIrcConfig config, INonDisposableStringParsingQueue parsin
this.eventScheduler = new EventScheduler();

this.parsingQueue = parsingQueue;
this.reconnector = new IrcReconnector(
() => this.SendPing( "watchdog" ),
() =>
{
this.AddCoreEvent( "WATCHDOG FAILED" );
this.AttemptReconnect();
},
60 * 1000
);

this.reconnector.OnMessage += Reconnector_OnMessage;
this.reconnector.OnError += Reconnector_OnError;
}

// ---------------- Properties ----------------
Expand Down Expand Up @@ -197,11 +198,7 @@ public void Init()
{
// Start Executing
this.writerQueue.Start();

this.connectionWatchDog = new Thread( this.ConnectionWatchDogEntry );
this.connectionWatchDogKeepGoing = new ManualResetEvent( false );
this.connectionWatchDogPongEvent = new AutoResetEvent( false );
this.connectionWatchDog.Start();
this.reconnector.Start();

this.inited = true;
}
Expand Down Expand Up @@ -375,9 +372,7 @@ public void ReceivedPong( string response )
{
if( response == "watchdog" )
{
// TODO: Maybe add verbose output?
// StaticLogger.WriteLine( "Received Watchdog Pong!" );
this.connectionWatchDogPongEvent.Set();
this.reconnector.ResetWatchdog();
}
}

Expand Down Expand Up @@ -507,12 +502,7 @@ public void Disconnect()
// Finish disconnecting by closing the connection.
DisconnectHelper();

this.connectionWatchDogKeepGoing.Set();
this.connectionWatchDogPongEvent.Set();
this.connectionWatchDog.Interrupt();
this.connectionWatchDog.Join();
this.connectionWatchDogKeepGoing.Dispose();
this.connectionWatchDogPongEvent.Dispose();
this.reconnector.Dispose();

StaticLogger.Log.WriteLine( "Disconnect Complete." );
}
Expand Down Expand Up @@ -547,6 +537,8 @@ public void Dispose()
{
Disconnect();
this.writerQueue.OnError -= this.EventQueue_OnError;
this.reconnector.OnMessage -= Reconnector_OnMessage;
this.reconnector.OnError -= Reconnector_OnError;
}

/// <summary>
Expand Down Expand Up @@ -703,41 +695,10 @@ private void ReaderThread()
"If this was because of a watchdog timeout, stand by..."
);
}
}

private void ConnectionWatchDogEntry()
{
StaticLogger.Log.WriteLine( "Connection Watchdog Started." );
bool keepGoing = true;
while( keepGoing )
finally
{
try
{
if( this.connectionWatchDogKeepGoing.WaitOne( 60 * 1000 ) == false )
{
// If we timeout, send a ping. If we do NOT timeout, then we want to wait for a ping.
this.SendPing( "watchdog" );
if( this.connectionWatchDogPongEvent.WaitOne( 60 * 1000 ) == false )
{
StaticLogger.Log.WriteLine(
"Watch Dog has failed to receive a PONG within 60 seconds, attempting reconnect"
);
this.AddCoreEvent( "WATCHDOG FAILED" );
this.AttemptReconnect();
}
}
else
{
keepGoing = false;
}
}
catch( Exception e )
{
StaticLogger.Log.ErrorWriteLine( "Connection Watch Dog had an exception:" );
StaticLogger.Log.ErrorWriteLine( e.ToString() );
}
StaticLogger.Log.WriteLine( "ReaderThread Exiting" );
}
StaticLogger.Log.WriteLine( "Connection Watchdog Exiting." );
}

/// <summary>
Expand Down Expand Up @@ -855,5 +816,15 @@ private void WriterQueue_OnError( Exception err )

StaticLogger.Log.ErrorWriteLine( errorMessage.ToString() );
}

private void Reconnector_OnMessage( string obj )
{
StaticLogger.Log.WriteLine( Convert.ToInt32( LogVerbosityLevel.HighVerbosity ), obj );
}

private void Reconnector_OnError( string obj )
{
StaticLogger.Log.ErrorWriteLine( Convert.ToInt32( LogVerbosityLevel.NoVerbosity ), obj );
}
}
}
Loading

0 comments on commit 2b1e1cd

Please sign in to comment.