示例#1
0
        /// <summary>
        /// Attempts to write a frame
        /// </summary>
        /// <param name="frame"></param>
        /// <returns></returns>
        public bool WriteFrame(PipeFrame frame)
        {
            if (!IsConnected)
            {
                throw new Exception("Cannot write Native Stream as pipe is not connected");
            }

            //Create a memory stream so we can write it to the pipe
            using (MemoryStream stream = new MemoryStream())
            {
                //Write the stream and the send it to the pipe
                frame.WriteStream(stream);

                //Get the bytes and send it
                byte[] bytes = stream.ToArray();

                //Copy the bytes into a new marshaled block
                int    size = Marshal.SizeOf(bytes[0]) * bytes.Length;
                IntPtr pnt  = Marshal.AllocHGlobal(size);
                try
                {
                    //Send the marshaled block
                    Marshal.Copy(bytes, 0, pnt, bytes.Length);
                    return(NativePipeExtern.WriteFrame(pnt, bytes.Length));
                }
                finally
                {
                    //Finally, before exiting the try catch, free the memory we assigned.
                    Marshal.FreeHGlobal(pnt);
                }
            }
        }
示例#2
0
        public bool ReadFrame(out PipeFrame frame)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException("_stream");
            }

            //We are not connected so we cannot read!
            if (!IsConnected)
            {
                frame = default(PipeFrame);
                return(false);
            }

            //Try and read a frame
            int length = _stream.Read(_buffer, 0, _buffer.Length);

            Logger.Trace("Read {0} bytes", length);

            if (length == 0)
            {
                frame = default(PipeFrame);
                return(false);
            }

            //Read the stream now
            using (MemoryStream memory = new MemoryStream(_buffer, 0, length))
            {
                frame = new PipeFrame();
                if (!frame.ReadStream(memory))
                {
                    Logger.Error("Failed to read a frame! {0}", frame.Opcode);
                    return(false);
                }
                else
                {
                    Logger.Trace("Read pipe frame!");
                    return(true);
                }
            }
        }
示例#3
0
        public bool WriteFrame(PipeFrame frame)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException("_stream");
            }

            //Write the frame. We are assuming proper duplex connection here
            if (!IsConnected)
            {
                Logger.Error("Failed to write frame because the stream is closed");
                return(false);
            }

            try
            {
                //Write the pipe
                //This can only happen on the main thread so it should be fine.
                Logger.Trace("Writing frame");
                frame.WriteStream(_stream);
                return(true);
            }
            catch (IOException io)
            {
                Logger.Error("Failed to write frame because of a IO Exception: {0}", io.Message);
            }
            catch (ObjectDisposedException)
            {
                Logger.Warning("Failed to write frame as the stream was already disposed");
            }
            catch (InvalidOperationException)
            {
                Logger.Warning("Failed to write frame because of a invalid operation");
            }

            //We must have failed the try catch
            return(false);
        }
        private void ProcessCommandQueue()
        {
            //Logger.Info("Checking command queue");

            //We are not ready yet, dont even try
            if (State != RpcState.Connected)
            {
                return;
            }

            //We are aborting, so we will just log a warning so we know this is probably only going to send the CLOSE
            if (aborting)
            {
                Logger.Warning("We have been told to write a queue but we have also been aborted.");
            }

            //Prepare some variabels we will clone into with locks
            bool     needsWriting = true;
            ICommand item         = null;

            //Continue looping until we dont need anymore messages
            while (needsWriting && namedPipe.IsConnected)
            {
                lock (l_rtqueue)
                {
                    //Pull the value and update our writing needs
                    // If we have nothing to write, exit the loop
                    needsWriting = _rtqueue.Count > 0;
                    if (!needsWriting)
                    {
                        break;
                    }

                    //Peek at the item
                    item = _rtqueue.Peek();
                }

                //BReak out of the loop as soon as we send this item
                if (shutdown || (!aborting && LOCK_STEP))
                {
                    needsWriting = false;
                }

                //Prepare the payload
                IPayload payload = item.PreparePayload(GetNextNonce());
                Logger.Info("Attempting to send payload: " + payload.Command);

                //Prepare the frame
                PipeFrame frame = new PipeFrame();
                if (item is CloseCommand)
                {
                    //We have been sent a close frame. We better just send a handwave
                    //Send it off to the server
                    SendHandwave();

                    //Queue the item
                    Logger.Info("Handwave sent, ending queue processing.");
                    lock (l_rtqueue) _rtqueue.Dequeue();

                    //Stop sending any more messages
                    return;
                }
                else
                {
                    if (aborting)
                    {
                        //We are aborting, so just dequeue the message and dont bother sending it
                        Logger.Warning("- skipping frame because of abort.");
                        lock (l_rtqueue) _rtqueue.Dequeue();
                    }
                    else
                    {
                        //Prepare the frame
                        frame.SetObject(Opcode.Frame, item.PreparePayload(GetNextNonce()));

                        //Write it and if it wrote perfectly fine, we will dequeue it
                        Logger.Info("Sending payload: " + payload.Command);
                        if (namedPipe.WriteFrame(frame))
                        {
                            //We sent it, so now dequeue it
                            Logger.Info("Sent Successfully.");
                            lock (l_rtqueue) _rtqueue.Dequeue();
                        }
                        else
                        {
                            //Something went wrong, so just giveup and wait for the next time around.
                            Logger.Warning("Something went wrong during writing!");
                            return;
                        }
                    }
                }
            }
        }
示例#5
0
        public bool ReadFrame(out PipeFrame frame)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException("_stream");
            }

            //We are not connected so we cannot read!
            if (!IsConnected)
            {
                frame = default(PipeFrame);
                return(false);
            }

            if (_pendingReadFrames.Count > 0)
            {
                frame = _pendingReadFrames.Dequeue();
                return(true);
            }

            //Try and read a frame
            int length = _stream.Read(_buffer, 0, _buffer.Length);

            Logger.Trace("Read {0} bytes", length);

            if (length == 0)
            {
                frame = default(PipeFrame);
                return(false);
            }

            //Read the stream now
            using (MemoryStream memory = new MemoryStream(_buffer, 0, length))
            {
                frame = new PipeFrame();
                if (!frame.ReadStream(memory))
                {
                    Logger.Error("Failed to read a frame! {0}", frame.Opcode);
                    return(false);
                }
                else
                {
                    Logger.Trace("Read pipe frame!");
                    while (memory.Position < length)
                    {
                        Logger.Trace("There are still {0} bytes to read, try to read and enqueue another frame", length - memory.Position);
                        var pendingFrame = new PipeFrame();
                        if (pendingFrame.ReadStream(memory))
                        {
                            Logger.Trace("Read pending pipe frame!");
                            _pendingReadFrames.Enqueue(pendingFrame);
                        }
                        else
                        {
                            Logger.Error("Failed to read a pending frame! {0}", pendingFrame.Opcode);
                        }
                    }

                    return(true); // or false?
                }
            }
        }
示例#6
0
        /// <summary>
        /// Attempts to read a frame
        /// </summary>
        /// <param name="frame"></param>
        /// <returns></returns>
        public bool ReadFrame(out PipeFrame frame)
        {
            //Make sure we are connected
            if (!IsConnected)
            {
                throw new Exception("Cannot read Native Stream as pipe is not connected");
            }

            //Prepare bytes read and a buffer of memory to read into
            int    bytesRead = 0;
            int    size      = Marshal.SizeOf(_buffer[0]) * _buffer.Length;
            IntPtr pnt       = Marshal.AllocHGlobal(size);

            //Try and read the frame from the native pipe
            try
            {
                bytesRead = NativePipeExtern.ReadFrame(pnt, _buffer.Length);
                if (bytesRead <= 0)
                {
                    //We have not read a valid amount of bytes, so return a error message.
                    //Update the error message
                    _lasterr = NativePipeExtern.PipeReadError.ReadEmptyMessage;

                    //A error actively occured. If it is 0 we just read no bytes.
                    if (bytesRead < 0)
                    {
                        //We have a pretty bad error, we will log it for prosperity.
                        _lasterr = (NativePipeExtern.PipeReadError)bytesRead;
                        Logger.Error("Native pipe failed to read: {0}", _lasterr.ToString());

                        //Close this pipe
                        this.Close();
                    }

                    //Return a empty frame and return false (read failure).
                    frame = default(PipeFrame);
                    return(false);
                }
                else
                {
                    //WE have read a valid amount of bytes, so copy the marshaled bytes over to the buffer
                    Marshal.Copy(pnt, _buffer, 0, bytesRead);
                }
            }
            finally
            {
                //Finally, before we exit this try block, free the pointer we allocated.
                Marshal.FreeHGlobal(pnt);
            }

            //Parse the message by reading the contents into a memory stream.
            using (MemoryStream stream = new MemoryStream(_buffer, 0, bytesRead))
            {
                //Try to parse the stream
                frame = new PipeFrame();
                if (frame.ReadStream(stream) && frame.Length != 0)
                {
                    return(true);
                }

                //We failed
                Logger.Error("Pipe failed to read from the data received by the stream.");
                return(false);
            }
        }
        private void ProcessCommandQueue()
        {
            if (this.State != RpcState.Connected)
            {
                return;
            }
            if (this.aborting)
            {
                this.Logger.Warning("We have been told to write a queue but we have also been aborted.");
            }
            bool     flag    = true;
            ICommand command = (ICommand)null;

            while (flag && this.namedPipe.IsConnected)
            {
                lock (this.l_rtqueue)
                {
                    flag = this._rtqueue.Count > 0;
                    if (!flag)
                    {
                        break;
                    }
                    command = this._rtqueue.Peek();
                }
                if (this.shutdown || !this.aborting && RpcConnection.LOCK_STEP)
                {
                    flag = false;
                }
                IPayload ipayload = command.PreparePayload(this.GetNextNonce());
                this.Logger.Info("Attempting to send payload: " + (object)ipayload.Command);
                PipeFrame frame = new PipeFrame();
                if (command is CloseCommand)
                {
                    this.SendHandwave();
                    this.Logger.Info("Handwave sent, ending queue processing.");
                    lock (this.l_rtqueue)
                    {
                        this._rtqueue.Dequeue();
                        break;
                    }
                }
                else if (this.aborting)
                {
                    this.Logger.Warning("- skipping frame because of abort.");
                    lock (this.l_rtqueue)
                        this._rtqueue.Dequeue();
                }
                else
                {
                    frame.SetObject(Opcode.Frame, (object)command.PreparePayload(this.GetNextNonce()));
                    this.Logger.Info("Sending payload: " + (object)ipayload.Command);
                    if (this.namedPipe.WriteFrame(frame))
                    {
                        this.Logger.Info("Sent Successfully.");
                        lock (this.l_rtqueue)
                            this._rtqueue.Dequeue();
                    }
                    else
                    {
                        this.Logger.Warning("Something went wrong during writing!");
                        break;
                    }
                }
            }
        }
示例#8
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;
            }
        }