/// <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); } } }
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); } } }
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; } } } } }
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? } } }
/// <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; } } } }
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; } }