Ejemplo n.º 1
0
        /// <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.");
        }
Ejemplo n.º 3
0
        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;
        }
Ejemplo n.º 4
0
        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;
            }
        }