/// <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."); }
private void MainLoop() { this.Logger.Info("Initializing Thread. Creating pipe object."); while (!this.aborting) { if (!this.shutdown) { try { if (this.namedPipe == null) { this.Logger.Error("Something bad has happened with our pipe client!"); this.aborting = true; return; } this.Logger.Info("Connecting to the pipe through the {0}", (object)this.namedPipe.GetType().FullName); if (this.namedPipe.Connect(this.targetPipe)) { this.Logger.Info("Connected to the pipe. Attempting to establish handshake..."); this.EnqueueMessage((IMessage) new ConnectionEstablishedMessage() { ConnectedPipe = this.namedPipe.ConnectedPipe }); this.EstablishHandshake(); this.Logger.Info("Connection Established. Starting reading loop..."); bool flag = true; while (flag && !this.aborting && (!this.shutdown && this.namedPipe.IsConnected)) { PipeFrame frame; if (this.namedPipe.ReadFrame(out frame)) { this.Logger.Info("Read Payload: {0}", (object)frame.Opcode); switch (frame.Opcode) { case Opcode.Frame: if (this.shutdown) { this.Logger.Warning("Skipping frame because we are shutting down."); break; } if (frame.Data == null) { this.Logger.Error("We received no data from the frame so we cannot get the event payload!"); break; } EventPayload response = (EventPayload)null; try { response = frame.GetObject <EventPayload>(); } catch (Exception ex) { this.Logger.Error("Failed to parse event! " + ex.Message); this.Logger.Error("Data: " + frame.Message); } if (response != null) { this.ProcessFrame(response); break; } break; case Opcode.Close: ClosePayload closePayload = frame.GetObject <ClosePayload>(); this.Logger.Warning("We have been told to terminate by discord: ({0}) {1}", (object)closePayload.Code, (object)closePayload.Reason); this.EnqueueMessage((IMessage) new CloseMessage() { Code = closePayload.Code, Reason = closePayload.Reason }); flag = false; break; case Opcode.Ping: this.Logger.Info("PING"); frame.Opcode = Opcode.Pong; this.namedPipe.WriteFrame(frame); break; case Opcode.Pong: this.Logger.Info("PONG"); break; default: this.Logger.Error("Invalid opcode: {0}", (object)frame.Opcode); flag = false; break; } } if (!this.aborting && this.namedPipe.IsConnected) { this.ProcessCommandQueue(); this.queueUpdatedEvent.WaitOne(RpcConnection.POLL_RATE); } } this.Logger.Info("Left main read loop for some reason. Aborting: {0}, Shutting Down: {1}", (object)this.aborting, (object)this.shutdown); } else { this.Logger.Error("Failed to connect for some reason."); this.EnqueueMessage((IMessage) new ConnectionFailedMessage() { FailedPipe = this.targetPipe }); } if (!this.aborting) { if (!this.shutdown) { this.Logger.Info("Waiting {0}ms before attempting to connect again", (object)(long)this.delay.NextDelay()); Thread.Sleep(this.delay.NextDelay()); } } } catch (InvalidPipeException ex) { this.Logger.Error("Invalid Pipe Exception: {0}", (object)ex.Message); } catch (Exception ex) { this.Logger.Error("Unhandled Exception: {0}", (object)ex.GetType().FullName); this.Logger.Error(ex.Message); this.Logger.Error(ex.StackTrace); } finally { if (this.namedPipe.IsConnected) { this.Logger.Info("Closing the named pipe."); this.namedPipe.Close(); } this.SetConnectionState(RpcState.Disconnected); } } else { break; } } this.Logger.Info("Left Main Loop"); if (this.namedPipe != null) { this.namedPipe.Dispose(); } this.Logger.Info("Thread Terminated, no longer performing RPC connection."); }
void DiscordLoop() { bool connected = false; m_join = false; for (int i = 0; i < 10; ++i) { if (AttemptConnection(i)) { connected = true; break; } if (m_shutdown) { break; } } if (!connected) { InternalConsole.Error("Failed to connect to Discord"); m_shutdown = true; } else { m_internalClient.BeginRead(); EnqueueMessage(new ConnectionEstablishedMessage(m_connectedPipe)); Handshake(); while (!m_shutdown) { Frame frame; if (ReadFrame(out frame)) { switch (frame.OpCode) { case Frame.e_OpCode.Close: { ClosePayload close = frame.GetObject <ClosePayload>(); InternalConsole.AddMessage("Discord Client Remotely Terminated"); EnqueueMessage(new CloseMessage(close.Code, close.Reason)); m_shutdown = true; break; } case Frame.e_OpCode.Ping: { WriteFrame(new Frame(Frame.e_OpCode.Pong, frame.Data)); break; } case Frame.e_OpCode.Pong: { InternalConsole.Warning("Got a pong from Discord?"); break; } case Frame.e_OpCode.Frame: { if (m_shutdown) { break; } if (frame.Data == null) { InternalConsole.Error("Discord Client: No data in frame"); } EventPayload response = frame.GetObject <EventPayload>(); ProcessEvent(response); break; } default: { InternalConsole.Error("Discord Client: Invalid Operation"); m_shutdown = true; break; } } } ProcessCommandQueue(); } ProcessCommandQueue(); } m_join = true; }
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; } }