/// <summary> /// Creates a new message reader with the specified message to read and the specified encoding. /// </summary> /// <param name="initialMessage">Message to read.</param> /// <param name="encoding">Encoding to use for string interpretation.</param> public MqMessageReader(MqMessage initialMessage, Encoding encoding) : base(Stream.Null) { _encoding = encoding; _decoder = _encoding.GetDecoder(); _twoBytesPerChar = encoding is UnicodeEncoding; Message = initialMessage; }
/// <summary> /// Adds an existing message's frames to this message. /// </summary> /// <param name="message">Message to add.</param> public void Add(MqMessage message) { foreach (var frame in message) { _frames.Add(frame); } }
/// <summary> /// Deep copies this message with deep copied frames. /// </summary> /// <returns>Deep copied message.</returns> public MqMessage Clone() { var message = new MqMessage(); foreach (var frame in _frames) { message.Add(frame.Clone()); } return(message); }
/// <summary> /// Shallow copies this message with shallow copied frames. /// </summary> /// <returns>Shallow copied message.</returns> public MqMessage ShallowCopy() { var message = new MqMessage(); foreach (var frame in _frames) { message.Add(frame.ShallowCopy()); } return(message); }
/// <summary> /// Collects all the generated frames and outputs them as a single message. /// </summary> /// <param name="clearBuilder">Optionally clear this builder and prepare for a new message.</param> /// <returns>Message containing all frames.</returns> public MqMessage ToMessage(bool clearBuilder) { FinalizeFrame(); var message = new MqMessage(); message.AddRange(_frames); message.PrepareSend(); if (clearBuilder) { Clear(); } return(message); }
/// <summary> /// Sends a message to the session's client. /// </summary> /// <param name="message">Message to send.</param> public void Send(MqMessage message) { if (message.Count == 0) { return; } if (CurrentState != State.Connected) { return; } lock (_outboxLock) { _outbox.Enqueue(message); } if (_outboxTask == null || _outboxTask.IsCompleted) { _outboxTask = Task.Run((Action)ProcessOutbox); } }
/// <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> /// Internal method called by the Postmaster on a different thread to process all bytes in the inbox. /// </summary> /// <returns>True if incoming queue was processed; False if nothing was available for process.</returns> private void ProcessIncomingQueue() { if (_processMessage == null) { _processMessage = new MqMessage(); } Queue <MqMessage> messages = null; byte[] buffer; while (_inboxBytes.TryDequeue(out buffer)) { try { _frameBuilder.Write(buffer, 0, buffer.Length); } catch (InvalidDataException) { //logger.Error(ex, "Connector {0}: Client send invalid data.", Connection.Id); Close(SocketCloseReason.ProtocolError); break; } var frameCount = _frameBuilder.Frames.Count; //logger.Debug("Connector {0}: Parsed {1} frames.", Connection.Id, frame_count); for (var i = 0; i < frameCount; i++) { var frame = _frameBuilder.Frames.Dequeue(); // Do nothing if this is a ping frame. if (frame.FrameType == MqFrameType.Ping) { if (BaseSocket.Mode == SocketMode.Server) { // Re-send ping frame back to the client to refresh client connection timeout timer. Send(CreateFrame(null, MqFrameType.Ping)); } continue; } // Determine if this frame is a command type. If it is, process it and don't add it to the message. if (frame.FrameType == MqFrameType.Command) { ProcessCommand(frame); continue; } _processMessage.Add(frame); if (frame.FrameType != MqFrameType.EmptyLast && frame.FrameType != MqFrameType.Last) { continue; } if (messages == null) { messages = new Queue <MqMessage>(); } messages.Enqueue(_processMessage); _processMessage = new MqMessage(); } } if (messages == null) { return; } OnIncomingMessage(this, new IncomingMessageEventArgs <TSession, TConfig>(messages, (TSession)this)); lock (_inboxLock) { if (_inboxBytes.IsEmpty == false) { _inboxTask = Task.Run((Action)ProcessIncomingQueue); } } }
/// <summary> /// Creates a new message reader with the specified message to read and the default encoding of UTF8. /// </summary> /// <param name="initialMessage">Message to read.</param> public MqMessageReader(MqMessage initialMessage) : this(initialMessage, Encoding.UTF8) { }
/// <summary> /// Adds a message to the outbox to be processed. /// Empty messages will be ignored. /// </summary> /// <param name="message">Message to send.</param> public void Send(MqMessage message) { // Send the outgoing message to the session to be processed by the postmaster. Session.Send(message); }
/// <summary> /// Appends an existing message to this message. /// </summary> /// <param name="value">Value to write to the message.</param> public void Write(MqMessage value) { InternalFinalizeFrame(); _frames.AddRange(value); }