예제 #1
0
        /// <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");
        }