/// <summary> /// Main thread loop /// </summary> private void MainLoop() { //initialize the pipe Logger.Info("RPC Connection Started"); if (Logger.Level <= LogLevel.Trace) { Logger.Trace("============================"); Logger.Trace("Assembly: " + System.Reflection.Assembly.GetAssembly(typeof(RichPresence)).FullName); Logger.Trace("Pipe: " + _namedPipe.GetType().FullName); Logger.Trace("Platform: " + Environment.OSVersion.ToString()); Logger.Trace("applicationID: " + _discordApplicationId); Logger.Trace("targetPipe: " + _currentTargetPipeNumber); Logger.Trace("POLL_RATE: " + POLL_RATE); Logger.Trace("_maxRtQueueSize: " + _maxRtQueueSize); Logger.Trace("_maxRxQueueSize: " + _maxRxQueueSize); Logger.Trace("============================"); } //Forever trying to connect unless the abort signal is sent //Keep Alive Loop while (!_aborting && !_shutdown) { try { //Wrap everything up in a try get //Dispose of the pipe if we have any (could be broken) if (_namedPipe == null) { Logger.Error("Something bad has happened with our pipe client!"); _aborting = true; return; } //Connect to a new pipe Logger.Trace("Connecting to the pipe through the {0}", _namedPipe.GetType().FullName); if (_namedPipe.Connect(_currentTargetPipeNumber)) { #region Connected //We connected to a pipe! Reset the delay Logger.Trace("Connected to the pipe. Attempting to establish handshake..."); EnqueueMessage(new ConnectionEstablishedMessage() { ConnectedPipe = _namedPipe.ConnectedPipe }); //Attempt to establish a handshake EstablishHandshake(); Logger.Trace("Connection Established. Starting reading loop..."); //Continously iterate, waiting for the frame //We want to only stop reading if the inside tells us (mainloop), if we are aborting (abort) or the pipe disconnects // We dont want to exit on a shutdown, as we still have information bool isCloseRequired = false; while (!isCloseRequired && !_aborting && !_shutdown && _namedPipe.IsConnected) { PipeFrame frame; #region Read Loop //Iterate over every frame we have queued up, processing its contents if (_namedPipe.ReadFrame(out frame)) { //Do some basic processing on the frame ProcessRawFrame(frame, out isCloseRequired); } else if (!_aborting && _namedPipe.IsConnected) { //Wait for some time, or until a command has been queued up _receivedMessageSignal.WaitOne(POLL_RATE); } #endregion } #endregion Logger.Trace("Left main read loop for some reason. Aborting: {0}, Shutting Down: {1}", _aborting, _shutdown); } else { Logger.Error("Failed to connect for some reason."); EnqueueMessage(new ConnectionFailedMessage() { FailedPipe = _currentTargetPipeNumber }); } //If we are not aborting, we have to wait a bit before trying to connect again if (!_aborting && !_shutdown) { //We have disconnected for some reason, either a failed pipe or a bad reading, // so we are going to wait a bit before doing it again long sleep = _delay.NextDelay(); Logger.Trace("Waiting {0}ms before attempting to connect again", sleep); Thread.Sleep(_delay.NextDelay()); } } //catch(InvalidPipeException e) //{ // Logger.Error("Invalid Pipe Exception: {0}", e.Message); //} catch (Exception e) { Logger.Error("Unhandled Exception: {0}", e.GetType().FullName); Logger.Error(e.Message); Logger.Error(e.StackTrace); } finally { //Disconnect from the pipe because something bad has happened. An exception has been thrown or the main read loop has terminated. if (_namedPipe.IsConnected) { //Terminate the pipe Logger.Trace("Closing the named pipe."); _namedPipe.Close(); } //Update our state SetConnectionState(RpcState.Disconnected); } } //We have disconnected, so dispose of the thread and the pipe. Logger.Trace("Left Main Loop"); if (_namedPipe != null) { _namedPipe.Dispose(); } Logger.Info("Thread Terminated, no longer performing RPC connection."); }
/// <summary> /// Main thread loop /// </summary> private void MainLoop() { //initialize the pipe Logger.Info("Initializing Thread. Creating pipe object."); //Forever trying to connect unless the abort signal is sent //Keep Alive Loop while (!aborting && !shutdown) { try { //Wrap everything up in a try get //Dispose of the pipe if we have any (could be broken) if (namedPipe == null) { Logger.Error("Something bad has happened with our pipe client!"); aborting = true; return; } //Connect to a new pipe Logger.Info("Connecting to the pipe through the {0}", namedPipe.GetType().FullName); if (namedPipe.Connect(targetPipe)) { #region Connected //We connected to a pipe! Reset the delay Logger.Info("Connected to the pipe. Attempting to establish handshake..."); EnqueueMessage(new ConnectionEstablishedMessage() { ConnectedPipe = namedPipe.ConnectedPipe }); //Attempt to establish a handshake EstablishHandshake(); Logger.Info("Connection Established. Starting reading loop..."); //Continously iterate, waiting for the frame //We want to only stop reading if the inside tells us (mainloop), if we are aborting (abort) or the pipe disconnects // We dont want to exit on a shutdown, as we still have information PipeFrame frame; bool mainloop = true; while (mainloop && !aborting && !shutdown && namedPipe.IsConnected) { #region Read Loop //Iterate over every frame we have queued up, processing its contents if (namedPipe.ReadFrame(out frame)) { #region Read Payload Logger.Info("Read Payload: {0}", frame.Opcode); //Do some basic processing on the frame switch (frame.Opcode) { //We have been told by discord to close, so we will consider it an abort case Opcode.Close: ClosePayload close = frame.GetObject <ClosePayload>(); Logger.Warning("We have been told to terminate by discord: ({0}) {1}", close.Code, close.Reason); EnqueueMessage(new CloseMessage() { Code = close.Code, Reason = close.Reason }); mainloop = false; break; //We have pinged, so we will flip it and respond back with pong case Opcode.Ping: Logger.Info("PING"); frame.Opcode = Opcode.Pong; namedPipe.WriteFrame(frame); break; //We have ponged? I have no idea if Discord actually sends ping/pongs. case Opcode.Pong: Logger.Info("PONG"); break; //A frame has been sent, we should deal with that case Opcode.Frame: if (shutdown) { //We are shutting down, so skip it Logger.Warning("Skipping frame because we are shutting down."); break; } if (frame.Data == null) { //We have invalid data, thats not good. Logger.Error("We received no data from the frame so we cannot get the event payload!"); break; } //We have a frame, so we are going to process the payload and add it to the stack EventPayload response = null; try { response = frame.GetObject <EventPayload>(); } catch (Exception e) { Logger.Error("Failed to parse event! " + e.Message); Logger.Error("Data: " + frame.Message); } if (response != null) { ProcessFrame(response); } break; default: case Opcode.Handshake: //We have a invalid opcode, better terminate to be safe Logger.Error("Invalid opcode: {0}", frame.Opcode); mainloop = false; break; } #endregion } if (!aborting && namedPipe.IsConnected) { //Process the entire command queue we have left ProcessCommandQueue(); //Wait for some time, or until a command has been queued up queueUpdatedEvent.WaitOne(POLL_RATE); } #endregion } #endregion Logger.Info("Left main read loop for some reason. Aborting: {0}, Shutting Down: {1}", aborting, shutdown); } else { Logger.Error("Failed to connect for some reason."); EnqueueMessage(new ConnectionFailedMessage() { FailedPipe = targetPipe }); } //If we are not aborting, we have to wait a bit before trying to connect again if (!aborting && !shutdown) { //We have disconnected for some reason, either a failed pipe or a bad reading, // so we are going to wait a bit before doing it again long sleep = delay.NextDelay(); Logger.Info("Waiting {0}ms before attempting to connect again", sleep); Thread.Sleep(delay.NextDelay()); } } catch (InvalidPipeException e) { Logger.Error("Invalid Pipe Exception: {0}", e.Message); } catch (Exception e) { Logger.Error("Unhandled Exception: {0}", e.GetType().FullName); Logger.Error(e.Message); Logger.Error(e.StackTrace); } finally { //Disconnect from the pipe because something bad has happened. An exception has been thrown or the main read loop has terminated. if (namedPipe.IsConnected) { //Terminate the pipe Logger.Info("Closing the named pipe."); namedPipe.Close(); } //Update our state SetConnectionState(RpcState.Disconnected); } } //We have disconnected, so dispose of the thread and the pipe. Logger.Info("Left Main Loop"); if (namedPipe != null) { namedPipe.Dispose(); } Logger.Info("Thread Terminated, no longer performing RPC connection."); }
/// <summary> /// Main thread loop /// </summary> private void MainLoop() { //initialize the pipe Logger.Info("Initializing Thread. Creating pipe object."); //Forever trying to connect unless the abort signal is sent //Keep Alive Loop while (!aborting) { try { //Wrap everything up in a try get //Dispose of the pipe if we have any (could be broken) if (namedPipe == null) { Logger.Error("Something bad has happened with our pipe client!"); aborting = true; return; } //Connect to a new pipe Logger.Info("Connecting to the pipe through the {0}", namedPipe.GetType().FullName); if (namedPipe.Connect(targetPipe)) { #region Connected //We connected to a pipe! Reset the delay Logger.Info("Connected to the pipe. Attempting to establish handshake..."); EnqueueMessage(new ConnectionEstablishedMessage() { ConnectedPipe = namedPipe.ConnectedPipe }); delay.Reset(); //Attempt to establish a handshake EstablishHandshake(); Logger.Info("Connection Established. Starting reading loop..."); //Continously iterate, waiting for the frame PipeFrame frame; bool mainloop = true; while (mainloop && !aborting && namedPipe.IsConnected) { #region Read Loop //Iterate over every frame we have queued up, processing its contents if (namedPipe.ReadFrame(out frame)) { #region Read Payload Logger.Info("Read Payload: {0}", frame.Opcode); //Do some basic processing on the frame switch (frame.Opcode) { case Opcode.Close: //We have been told by discord to close, so we will consider it an abort Logger.Warning("We have been told to terminate by discord. ", frame.Message); EnqueueMessage(new CloseMessage() { Reason = frame.Message }); mainloop = false; break; case Opcode.Ping: //We have pinged, so we will flip it and respond back with pong Logger.Info("PING"); frame.Opcode = Opcode.Pong; namedPipe.WriteFrame(frame); break; case Opcode.Pong: //We have ponged? I have no idea if Discord actually sends ping/pongs. Logger.Info("PONG"); break; case Opcode.Frame: //We have a frame, so we are going to process the payload and add it to the stack if (frame.Data == null) { Logger.Error("We received no data from the frame so we cannot get the event payload!"); break; } else { EventPayload response = frame.GetObject <EventPayload>(); ProcessFrame(response); break; } default: case Opcode.Handshake: //We have a invalid opcode, better terminate to be safe Logger.Error("Invalid opcode: {0}", frame.Opcode); mainloop = false; break; } #endregion } //Process the entire command queue we have left ProcessCommandQueue(); //We should wait some time, unless we have been aborted. if (!aborting) { //Wait for some time, or until a command has been queued up queueUpdatedEvent.WaitOne(POLL_RATE); } #endregion } #endregion Logger.Warning("Left main read loop for some reason. IsAbort: {0}", aborting); } else { Logger.Error("Failed to connect for some reason."); EnqueueMessage(new ConnectionFailedMessage() { FailedPipe = targetPipe }); } //If we are not aborting, we have to wait a bit before trying to connect again if (!aborting) { //We have disconnected for some reason, either a failed pipe or a bad reading, // so we are going to wait a bit before doing it again long sleep = delay.NextDelay(); Logger.Info("Waiting {0}ms", sleep); Thread.Sleep(delay.NextDelay()); } } catch (InvalidPipeException e) { Logger.Error("Invalid Pipe Exception: {0}", e.Message); } catch (Exception e) { Logger.Error("Unhandled Exception: {0}", e.GetType().FullName); Logger.Error(e.Message); Logger.Error(e.StackTrace); } finally { //Disconnect from the pipe because something bad has happened. An exception has been thrown or the main read loop has terminated. if (namedPipe.IsConnected) { namedPipe.Close(); } } } //We have disconnected, so dispose of the thread and the pipe. Logger.Info("Left Main Loop"); namedPipe.Dispose(); Logger.Info("Thread Terminated"); }