2828
2929namespace lib60870 . CS104
3030{
31+ /// <summary>
32+ /// Server events concerning listening
33+ /// </summary>
34+ public class ServerStateEvent {
35+
36+ private bool nowListening ;
37+ private bool fatal ;
38+ private Exception occurredException ;
39+ /// <summary>
40+ /// Either true (by Start()) or false (by Stop() or exception)
41+ /// </summary>
42+ public bool NowListening
43+ {
44+ get { return nowListening ; }
45+ }
46+ /// <summary>
47+ /// Is it a fatal exception (while listening) or not (no exception or while closing)
48+ /// </summary>
49+ public bool Fatal
50+ {
51+ get { return fatal ; }
52+ }
53+ /// <summary>
54+ /// Either null (by Start() and Stop() or caught exception)
55+ /// </summary>
56+ public Exception OccurredException
57+ {
58+ get { return occurredException ; }
59+ }
60+ internal ServerStateEvent ( bool nowListening , bool fatal , Exception occurredException )
61+ {
62+ this . nowListening = nowListening ;
63+ this . fatal = fatal ;
64+ this . occurredException = occurredException ;
65+ }
66+ }
67+ public delegate void ServerStateEventHandler ( object parameter , ServerStateEvent stateEvent ) ;
3168
3269 /// <summary>
3370 /// Connection request handler is called when a client tries to connect to the server.
@@ -467,6 +504,19 @@ public void AddRedundancyGroup(RedundancyGroup redundancyGroup)
467504 redGroups . Add ( redundancyGroup ) ;
468505 }
469506
507+ public ServerStateEventHandler serverStateEventHandler = null ;
508+ public object serverStateEventHandlerParameter = null ;
509+ /// <summary>
510+ /// Sets a callback handler for server state changes.
511+ /// </summary>
512+ /// <param name="handler">Handler.</param>
513+ /// <param name="parameter">Parameter.</param>
514+ public void SetServerStateEventHandler ( ServerStateEventHandler handler , object parameter )
515+ {
516+ this . serverStateEventHandler = handler ;
517+ this . serverStateEventHandlerParameter = parameter ;
518+ }
519+
470520 public ConnectionRequestHandler connectionRequestHandler = null ;
471521 public object connectionRequestHandlerParameter = null ;
472522
@@ -584,6 +634,7 @@ public int GetNumberOfQueueEntries(RedundancyGroup redundancyGroup = null)
584634 private void ServerAcceptThread ( )
585635 {
586636 running = true ;
637+ CallServerStateEventHandler ( new ServerStateEvent ( true , false , null ) ) ;
587638
588639 DebugLog ( "Waiting for connections..." ) ;
589640
@@ -675,8 +726,13 @@ private void ServerAcceptThread()
675726 }
676727 catch ( Exception e )
677728 {
678- running = false ;
679- DebugLog ( "Exception: " + e . ToString ( ) ) ;
729+ DebugLog ( "Exception: " + e . Message ) ;
730+ bool socketExceptionDuringShutdown = ! running && ( e is SocketException ) ;
731+ if ( ! socketExceptionDuringShutdown )
732+ {
733+ running = false ;
734+ CallServerStateEventHandler ( new ServerStateEvent ( false , true , e ) ) ;
735+ }
680736 }
681737
682738 }
@@ -767,16 +823,18 @@ public void Start()
767823 public void Stop ( )
768824 {
769825 running = false ;
826+ CallServerStateEventHandler ( new ServerStateEvent ( false , false , null ) ) ;
770827
771828 try
772829 {
773830 try
774831 {
775832 listeningSocket . Shutdown ( SocketShutdown . Both ) ;
776833 }
777- catch ( SocketException ex )
834+ catch ( SocketException ex ) // seems to be side effect of Shutdown(). No idea how to avoid it.
778835 {
779- DebugLog ( "SocketException: " + ex . Message ) ;
836+ DebugLog ( "SocketException: " + ex . Message + " with code " + ex . ErrorCode ) ;
837+ // CallServerStateEventHandler(new ServerStateEvent(false, false, ex));
780838 }
781839
782840 listeningSocket . Close ( ) ;
@@ -790,6 +848,7 @@ public void Stop()
790848 catch ( Exception e )
791849 {
792850 DebugLog ( "Exception: " + e . Message ) ;
851+ CallServerStateEventHandler ( new ServerStateEvent ( false , false , e ) ) ;
793852 }
794853 }
795854
@@ -835,6 +894,12 @@ public void EnqueueASDU(ASDU asdu)
835894 }
836895 }
837896
897+ internal void CallServerStateEventHandler ( ServerStateEvent e )
898+ {
899+ if ( serverStateEventHandler != null )
900+ serverStateEventHandler ( serverStateEventHandlerParameter , e ) ;
901+ }
902+
838903 internal void CallConnectionEventHandler ( ClientConnection connection , ClientConnectionEvent e )
839904 {
840905 if ( connection . State == MasterConnectionState . M_CON_STATE_STARTED )
0 commit comments