/// <summary> /// Skips over to the next non-empty frame in the message. /// </summary> private void NextNonEmptyFrame() { _framePosition = 0; // Increment until we reach the next non-empty frame. do { _messagePosition++; } while (_message[_messagePosition]?.FrameType == MqFrameType.Empty); _currentFrame = _messagePosition >= _message.Count ? null : _message[_messagePosition]; }
/// <summary> /// Copies the current data in the builder_frame into a new frame of the correct size. Resets position to 0. /// </summary> private void InternalFinalizeFrame() { if (_position == 0) { throw new InvalidOperationException("Can not finalize frame when it is empty."); } var bytes = new byte[_position]; var frame = new MqFrame(bytes, MqFrameType.Last, _config); Buffer.BlockCopy(_builderFrame.Buffer, 0, bytes, 0, _position); _frames.Add(frame); _position = 0; }
/// <summary> /// Processes an incoming command frame from the connection. /// </summary> /// <param name="frame">Command frame to process.</param> protected virtual void ProcessCommand(MqFrame frame) { var commandType = (MqCommandType)frame.ReadByte(0); switch (commandType) { case MqCommandType.Disconnect: CurrentState = State.Closing; Close((SocketCloseReason)frame.ReadByte(1)); break; default: Close(SocketCloseReason.ProtocolError); break; } }
/// <summary> /// Peeks at the next char value. /// >=1 Byte. /// </summary> public override int PeekChar() { // Store the temporary state of the reader. var previousFrame = _currentFrame; var previousPosition = _framePosition; var previousMessagePosition = _messagePosition; var value = ReadChar(); // Restore the original state of the reader. _currentFrame = previousFrame; _framePosition = previousPosition; _messagePosition = previousMessagePosition; return(value); }
/// <summary> /// Closes this session with the specified reason. /// Notifies the recipient connection the reason for the session's closure. /// </summary> /// <param name="reason">Reason for closing this session.</param> public override void Close(SocketCloseReason reason) { if (CurrentState == State.Closed) { return; } MqFrame closeFrame = null; if (CurrentState == State.Connected) { CurrentState = State.Closing; closeFrame = CreateFrame(new byte[2], MqFrameType.Command); closeFrame.Write(0, (byte)0); closeFrame.Write(1, (byte)reason); } // If we are passed a closing frame, then send it to the other connection. if (closeFrame != null) { MqMessage msg; if (_outbox.IsEmpty == false) { while (_outbox.TryDequeue(out msg)) { } } msg = new MqMessage(closeFrame); _outbox.Enqueue(msg); // Process the last bit of data. ProcessOutbox(); } base.Close(reason); }
/// <summary> /// Adds a frame to the outbox to be processed. /// </summary> /// <param name="frame">Frame to send.</param> public void Send(MqFrame frame) { Send(new MqMessage(frame)); }
/// <summary> /// Advances the reader to the next frame and resets reading positions. /// </summary> public void NextFrame() { _framePosition = 0; _messagePosition += 1; _currentFrame = _message[_messagePosition]; }
/// <summary> /// Creates a new message writer with the specified socket configurations and encoding. /// </summary> /// <param name="config">Current socket configurations. Used to create new frames.</param> /// <param name="encoding">Encoding to use for string and char parsing.</param> public MqMessageWriter(MqConfig config, Encoding encoding) { _config = config; _encoding = encoding; _builderFrame = new MqFrame(new byte[config.FrameBufferSize], MqFrameType.More, config); }
/// <summary> /// Writes a whole frame to the message. /// </summary> /// <param name="value">Value to write to the message.</param> public void Write(MqFrame value) { InternalFinalizeFrame(); _frames.Add(value); }