private void ProcessRawFrame(PipeFrame frame, out bool isCloseRequired) { Logger.Trace("Read Payload: {0}", frame.Opcode); isCloseRequired = false; 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 }); isCloseRequired = true; break; //We have pinged, so we will flip it and respond back with pong case Opcode.Ping: Logger.Trace("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.Trace("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); isCloseRequired = true; break; } }
/// <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"); }