예제 #1
0
		public static StompFrame CreateErrorFrame(string message, StompFrame inResponseTo)
		{
			var errorFrame = CreateErrorFrame(message);
			var receiptId = inResponseTo.Headers[StompHeader.Receipt];
			if (receiptId != null)
			{
				errorFrame.Headers[StompHeader.ReceiptId] = receiptId;
			}
			return errorFrame;
		}
예제 #2
0
		/// <summary>
		/// 	Creates a copy of the frame
		/// </summary>
		/// <param name = "frame">Frame to take a copy of.</param>
		/// <returns>
		/// 	Returns a new frame whose command and headers can be modified without changing the original frame.
		/// 	The body, however, is shared with the original frame.
		/// </returns>
		public static StompFrame CreateCopy(StompFrame frame)
		{
			var copy = new StompFrame
			           	{
			           		Command = frame.Command
			           	};
			copy.Headers.Add(frame.Headers);
			copy.Body = frame.Body;
			return copy;
		}
예제 #3
0
		public static void DisconnectImmediately(StompClient client)
		{
			Verify.ArgumentNotNull(client, "client");
			var message = new StompFrame(StompCommand.Disconnect)
			              	{
			              		Headers =
			              			{
			              				{StompHeader.NonStandard.KeepSession, "true"}
			              			}
			              	};
			client.SendRawMessage(message, false);
		}
예제 #4
0
		public static StompFrame CreateErrorFrame(string message)
		{
			var errorFrame = new StompFrame
			                 	{
			                 		Command = StompCommand.Error,
			                 		Headers =
			                 			{
			                 				{StompHeader.Message, message}
			                 			}
			                 	};

			return errorFrame;
		}
		public void SendFrame(StompFrame frame)
		{
			using (_lockObject.Lock())
			{
				if (_stateAction == ShuttingDown)
				{
					Log.Warn(_logMessagePrefix + "Discarded frame: transport is shutting down: " + frame);
				}
				else
				{
					_transport.SendFrame(frame);
					StartOutgoingHeartBeatTimer();
				}
			} 
		}
		public void SendFrame(StompFrame frame)
		{
			using (_lockObject.Lock())
			{
				var messageId = ++_lastMessageId;
				frame.Headers[StompHeader.MessageId] = messageId.ToString();
				frame.Headers[StompHeader.Subscription] = SubscriptionId;
				if (!AutoAcknowledge)
				{
					_unacknowledgedFrames.Add(messageId, frame);
				}
			}

			Session.SendFrame(frame);
		}
예제 #7
0
 /// <summary>
 /// 客户端取消订阅
 /// </summary>
 /// <param name="unSubScribeFrame"></param>
 /// <param name="stompBehavior"></param>
 public void UnSubScribe(StompFrame unSubScribeFrame, StompBehavior stompBehavior)
 {
     lock (stompSubscribeDictionaryLock)
     {
         if (unSubScribeFrame.Headers.ContainsKey(StompHeaders.Id) && string.IsNullOrEmpty(unSubScribeFrame.Headers[StompHeaders.Id]))
         {
             string destinationOfsubid = stompBehavior.topicPathSubidDictionary.FirstOrDefault(d => d.Value == unSubScribeFrame.Headers[StompHeaders.Id]).Key;
             if (stompSubscribeDictionary.ContainsKey(destinationOfsubid))
             {
                 if (stompSubscribeDictionary[destinationOfsubid].ContainsKey(stompBehavior.ID))
                 {
                     stompSubscribeDictionary[destinationOfsubid].Remove(stompBehavior.ID);
                 }
             }
         }
     }
 }
예제 #8
0
파일: Tests.cs 프로젝트: tomlane/REstomp
        public void StompFrameWithHeaders(string headerKey, string headerValue)
        {
            var header      = new KeyValuePair <string, string>(headerKey, headerValue);
            var headerArray = new KeyValuePair <string, string> [1];

            headerArray[0] = header;
            var expectation = new StompFrame(StompParser.Command.MESSAGE, headerArray);

            var newFrame = new StompFrame(StompParser.Command.MESSAGE)
                           .With(frame => frame.Headers, headerArray);

            Assert.NotNull(newFrame);
            Assert.Equal(expectation.Command, newFrame.Command);

            Assert.Equal(expectation.Headers[0].Key, newFrame.Headers[0].Key);
            Assert.Equal(expectation.Headers[0].Value, newFrame.Headers[0].Value);
            Assert.True(newFrame.Body.IsDefault);
        }
예제 #9
0
        public override void Reflex(StompFrame sourceStomp)
        {
#if DEBUG
            //System.Diagnostics.Debug.WriteLine(sourceStomp.ToString());
#endif
            switch (sourceStomp.Headers[StompHeaders.Destination])
            {
            case "/application/cmd":    //  ---> /topic/cmd
            {
                try
                {
                    MessageFrame messageFrame = new MessageFrame("/topic/cmd", MessageID, topicPathSubidDictionary[sourceStomp.Headers[StompHeaders.Destination]], null, sourceStomp.Body + ":Application OK", null);
                    PublishManager.Publish(messageFrame);
                }
                catch (Exception ex)
                {
#if DEBUG
                    System.Diagnostics.Debug.WriteLine(ex.ToString());
                    System.Diagnostics.Debug.WriteLine(ex.StackTrace);
                    System.Diagnostics.Debug.WriteLine(ex.Source);
#endif
                }
                break;
            }

            case "/application/control":    // ---> /application/control
            {
                try
                {
                    MessageFrame messageFrame = new MessageFrame("/application/control", MessageID, topicPathSubidDictionary[sourceStomp.Headers[StompHeaders.Destination]], null, sourceStomp.Body + ": Control OK", null);
                    Publish(messageFrame);
                }
                catch (Exception ex)
                {
#if DEBUG
                    System.Diagnostics.Debug.WriteLine(ex.ToString());
                    System.Diagnostics.Debug.WriteLine(ex.StackTrace);
                    System.Diagnostics.Debug.WriteLine(ex.Source);
#endif
                }
                break;
            }
            }
        }
예제 #10
0
파일: Tests.cs 프로젝트: tomlane/REstomp
        public async void ContentEndsOnNull()
        {
            var bodyString  = "0123456789abcdefghijk1234567890abcd";
            var command     = StompParser.Command.MESSAGE;
            var header      = new KeyValuePair <string, string>("key", "value");
            var headerArray = new KeyValuePair <string, string> [1];

            headerArray[0] = header;
            var body = Encoding.UTF8.GetBytes(bodyString);

            var expectation = new StompFrame(command, headerArray, body);

            using (var memStream = new MemoryStream())
                using (var streamWriter = new StreamWriter(memStream))
                {
                    var eol = "\r\n";
                    streamWriter.Write(command);
                    streamWriter.Write(eol);
                    foreach (var headerPair in headerArray)
                    {
                        streamWriter.Write($"{headerPair.Key}:{headerPair.Value}");
                    }
                    streamWriter.Write(eol);
                    streamWriter.Write(eol);
                    streamWriter.Write(bodyString);
                    streamWriter.Write((char)0x00);
                    streamWriter.Flush();

                    memStream.Position = 0;

                    var parsedCommand = await StompParser.ReadStompCommand(memStream.AsPrependableStream());

                    var parsedHeaders = await StompParser.ReadStompHeaders(parsedCommand.Item1, parsedCommand.Item2);

                    var parsedBody = await StompParser
                                     .ReadStompBody(parsedHeaders.Item1, parsedHeaders.Item2, CancellationToken.None);

                    Assert.StrictEqual(expectation.Command, parsedCommand.Item2.Command);
                    Assert.Equal(expectation.Headers[0], parsedHeaders.Item2.Headers[0]);
                    Assert.True(Encoding.UTF8.GetString(expectation.Body.ToArray())
                                == Encoding.UTF8.GetString(parsedBody.Item2.Body.ToArray()));
                    Assert.Equal(parsedBody.Item2.Body.Length, bodyString.Length);
                }
        }
예제 #11
0
    protected virtual void WriteMessageAck(MessageAck command, BinaryWriter dataOut)
    {
        var frame = new StompFrame("ACK", _encodeHeaders);

        if (command.ResponseRequired)
        {
            frame.SetProperty(PropertyKeys.Receipt, "ignore:" + command.CommandId);
        }

        frame.SetProperty(PropertyKeys.MessageId, command.LastMessageId.ToString());
        frame.SetProperty(PropertyKeys.Subscription, command.ConsumerId.ToString());

        if (command.TransactionId != null)
        {
            frame.SetProperty(PropertyKeys.Transaction, command.TransactionId.ToString());
        }

        frame.ToStream(dataOut);
    }
예제 #12
0
 protected override void OnMessage(MessageEventArgs e)
 {
     if (isConnected)
     {
         // 此处使用了多线程处理
         Thread reflexThread = new Thread(
             () =>
         {
             StompFrame StompFrame = StompFrameSerializer.Deserialize(e.Data);
             OnStompProtocol(StompFrame);
         });
         reflexThread.Start();
     }
     else
     {
         StompFrame StompFrame = StompFrameSerializer.Deserialize(e.Data);
         OnStompProtocol(StompFrame);
     }
 }
예제 #13
0
파일: Tests.cs 프로젝트: tomlane/REstomp
        public void FrameToString(string charset, Encoding encoding)
        {
            var bodyString  = "0123456789abcdefghijk1234567890abcd";
            var command     = StompParser.Command.MESSAGE;
            var header      = new KeyValuePair <string, string>("content-type", $"application/json;charset={charset}");
            var headerArray = new KeyValuePair <string, string> [1];

            headerArray[0] = header;
            var body = Encoding.UTF8.GetBytes(bodyString);

            var frame = new StompFrame(command, headerArray, body);

            var expectation =
                "MESSAGE\n" +
                $"content-type:application/json;charset={charset}\n" +
                "\n" +
                encoding.GetString(body) +
                "\0";

            Assert.Equal(expectation, frame.ToString());
        }
예제 #14
0
파일: Tests.cs 프로젝트: tomlane/REstomp
        public async void FrameParses()
        {
            var bodyString  = "0123456789abcdefghijk1234567890abcd";
            var command     = StompParser.Command.MESSAGE;
            var header      = new KeyValuePair <string, string>("key", "value");
            var headerArray = new KeyValuePair <string, string> [1];

            headerArray[0] = header;
            var body = Encoding.UTF8.GetBytes(bodyString);

            var expectation = new StompFrame(command, headerArray, body);

            using (var memStream = new MemoryStream())
                using (var streamWriter = new StreamWriter(memStream))
                {
                    var eol = "\r\n";
                    streamWriter.Write(command);
                    streamWriter.Write(eol);
                    foreach (var headerPair in headerArray)
                    {
                        streamWriter.Write($"{headerPair.Key}:{headerPair.Value}");
                    }
                    streamWriter.Write(eol);
                    streamWriter.Write(eol);
                    streamWriter.Write(bodyString);
                    streamWriter.Write((char)0x00);
                    streamWriter.Flush();

                    memStream.Position = 0;

                    var parser = new StompParser();
                    var frame  = await parser.ReadStompFrame(memStream).UnWrapFrame();

                    Assert.StrictEqual(expectation.Command, frame.Command);
                    Assert.Equal(expectation.Headers[0], frame.Headers[0]);
                    Assert.True(Encoding.UTF8.GetString(expectation.Body.ToArray())
                                == Encoding.UTF8.GetString(frame.Body.ToArray()));
                    Assert.Equal(frame.Body.Length, bodyString.Length);
                }
        }
예제 #15
0
		private void HandleUnknownCommand(StompFrame frame)
		{
			var message = "Unknown command: " + frame.Command;
			var errorFrame = StompFrameUtils.CreateErrorFrame(message, frame);
			SendFrame(errorFrame);
			Disconnect();
		}
예제 #16
0
		private void HandleAckCommand(StompFrame frame)
		{
			var subscriptionId = frame.Headers[StompHeader.Subscription];
			if (string.IsNullOrEmpty(subscriptionId))
			{
				var errorFrame = StompFrameUtils.CreateMissingHeaderError(StompHeader.Subscription, frame);
				SendFrame(errorFrame);
				Disconnect();
				return;
			}

			var messageId = frame.Headers[StompHeader.MessageId];
			if (string.IsNullOrEmpty(messageId))
			{
				var errorFrame = StompFrameUtils.CreateMissingHeaderError(StompHeader.MessageId, frame);
				SendFrame(errorFrame);
				Disconnect();
				return;
			}

			ServerSideSubscription subscription;
			if (!_subscriptions.TryGetValue(subscriptionId, out subscription))
			{
				var message = "Subscription does not exist: " + subscription;
				var errorFrame = StompFrameUtils.CreateErrorFrame(message, frame);
				SendFrame(errorFrame);
				Disconnect();
				return;
			}

			long messageId64;
			if (!long.TryParse(messageId, out messageId64))
			{
				var message = "Invalid value for " + StompHeader.MessageId + ": " + messageId;
				var errorFrame = StompFrameUtils.CreateErrorFrame(message, frame);
				SendFrame(errorFrame);
				Disconnect();
				return;
			}

			subscription.Acknowledge(messageId64);
			SendReceiptIfNecessary(frame);
		}
예제 #17
0
		private void HandleAbortCommand(StompFrame frame)
		{
			// TODO: handle send command
			SendNotImplementedError(frame);
		}
예제 #18
0
    protected virtual void WriteKeepAliveInfo(KeepAliveInfo command, BinaryWriter dataOut)
    {
        var frame = new StompFrame(StompFrame.Keepalive, _encodeHeaders);

        frame.ToStream(dataOut);
    }
예제 #19
0
 /// <summary>
 /// Initializes a new instance.
 /// </summary>
 public StompFrameException(StompFrame frame, string message) : base(message)
 {
     Frame = frame;
 }
예제 #20
0
		/// <summary>
		/// Note that the caller handles exceptions here
		/// </summary>
		/// <param name="frame"></param>
		public void ProcessFrame(StompFrame frame)
		{
			using (_lockObject.Lock())
			{
				ProcessFrameByCommand(frame);
			}
		}
예제 #21
0
		private void SendReceiptIfNecessary(StompFrame frame)
		{
			var receiptId = frame.Headers[StompHeader.Receipt];
			if (receiptId != null)
			{
				var receiptFrame = new StompFrame
				                   	{
				                   		Command = StompCommand.Receipt,
				                   		Headers =
				                   			{
				                   				{StompHeader.ReceiptId, receiptId}
				                   			}
				                   	};

				SendFrame(receiptFrame);
			}
		}
예제 #22
0
        private void DispatchFrame(StompFrame Frame)
        {
            // Dispatch the frame to the correct handler function or event

            if (Frame is StompMessageFrame)
            {
                HandleMessageFrame((StompMessageFrame)Frame);
            }
            else if (Frame is StompReceiptFrame)
            {
                try
                {
                    FrameReceipt(this, new StompFrameEventArgs(Frame));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
            else if (Frame is StompErrorFrame)
            {
                try
                {
                    ServerError(this, new StompErrorEventArgs((StompErrorFrame)Frame));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
            else if (Frame is StompConnectedFrame)
            {
                // Handle connection configuration
                StompConnectedFrame SCF = (StompConnectedFrame)Frame;

                int[] Timings = SCF.Heartbeat.Split(',').Select(x => int.Parse(x)).ToArray();

                _HeartbeatRxInterval = Math.Max(_Heartbeat, Timings[0]);
                _HeartbeatTxInterval = Math.Max(_Heartbeat, Timings[1]);

                _ConnectionVersion = float.Parse(SCF.Version);
            }
            else
            {
                try
                {
                    FrameReceived(this, new StompFrameEventArgs(Frame));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
        }
예제 #23
0
 internal StompFrameEventArgs(StompFrame Frame)
 {
     _Frame = Frame;
 }
예제 #24
0
        /// <summary>
        ///     Serializes and transmits a frame to the server
        /// </summary>
        /// <param name="Frame">
        ///     The <seealso cref="StompFrame"/> to send to the server 
        /// </param>
        /// <exception cref="ArgumentException">
        ///     Thrown if
        ///     <list type="number">
        ///         <item>You attempt to serialize a frame class that has no <seealso cref="StompFrameType"/> attribute</item>
        ///         <item>You attempt to send a frame that is marked as server to client only</item>
        ///         <item>You fail to fill in a mandatory frame parameter</item>
        ///     </list>
        /// </exception>
        public void SendFrame(StompFrame Frame)
        {
            // Get some metadata about the frame that we'll need
            StompFrameType SFT = Frame.GetType().GetCustomAttribute<StompFrameType>();

            // Validate frame before doing anything else
            if (SFT == null)
                throw new ArgumentException("Attempt to serialize frame without frame type attribute", "Frame");

            if (SFT.Direction == StompFrameDirection.ServerToClient)
                throw new ArgumentException("Attempt to send server frame from client", "Frame");

            // Serialize the frame and convert to byte array
            byte[] Data = Frame.Serialize();

            // Now send the frame
            lock (_Client)
            {
                _Client.GetStream().Write(Data, 0, Data.Length);
                _Client.GetStream().WriteByte(0);
                _HeartbeatTxIntervalTimeout = _HeartbeatTxInterval;
            }
        }
예제 #25
0
        /// <summary>
        ///     Tries to build a packet from the given ringbuffer
        /// </summary>
        /// <param name="Buffer">
        ///     The Ringbuffer to build a packet from
        /// </param>
        /// <returns>
        ///     Whether it was able to build a packet or not
        /// </returns>
        public bool TryBuildPacket(StompRingBuffer <byte> Buffer)
        {
            // See if we have rx'd a packet separator or a \0 in a binary frame body
            int PacketLength = Buffer.DistanceTo(0);

            // We have, so what did we find?
            if (PacketLength > 0)
            {
                // This is a really messy block of code.

                // The goal is that it tries to determine whether it has a full packet or needs to wait for more data
                // before building the packet and dispatching it

                byte[]   Data             = Buffer.Peek(PacketLength);
                string   Header           = Encoding.UTF8.GetString(Data);
                string[] HeaderCheck      = Header.Split('\n');
                int      ContentLength    = 0;
                bool     HasContentLength = false;

                // First, we look to see if our "packet" has a content-length header.  Since we scanned out to a null (\0) byte, we're guaranteed to at least have the headers
                // of whatever packet we're examining

                for (int i = 0; i < HeaderCheck.Length && HeaderCheck[i] != "" && HeaderCheck[i] != "\r"; i++)
                {
                    // We found a content-length header?  Flag it and store how large in bytes the content should be
                    if (HeaderCheck[i].StartsWith("content-length:"))
                    {
                        HasContentLength = true;
                        ContentLength    = int.Parse(HeaderCheck[i].Substring(15));
                    }
                }
                StompFrame Frame = null;

                if (HasContentLength)
                {
                    // We have a content-length header.  We need to find the start of the frame body, in bytes,
                    // and then make sure we have (ContentLength) bytes available after that

                    // Look for the end of the headers, either 1.0/1.1 or 1.2 (\r\n)-friendly
                    int EndOfHeaders = Header.IndexOf("\r\n\r\n") + 4;
                    if (EndOfHeaders == 3) // (-1) + 4
                    {
                        EndOfHeaders = Header.IndexOf("\n\n") + 2;
                    }

                    // Get the byte length of the header
                    int Offset = Encoding.UTF8.GetByteCount(Header.Substring(0, EndOfHeaders));

                    // Now see if we have that many bytes available in the ring buffer (realistically, we should except for obscene frame sizes)
                    if (Offset + ContentLength <= Buffer.AvailableRead)
                    {
                        // If we do, peek the exact packet length we want and assemble
                        Frame = StompFrame.Build(Buffer.Peek(Offset + ContentLength), _FrameTypeMapping);
                        Buffer.Seek(Offset + ContentLength);
                        DispatchFrame(Frame);

                        return(true);
                    }
                }
                else // No content-length.  We're guaranteed to be a text packet without any overshoot; no special treatment needed
                {
                    Frame = StompFrame.Build(Data, _FrameTypeMapping);
                    Buffer.Seek(PacketLength);
                    DispatchFrame(Frame);

                    return(true);
                }
            }

            return(false);
        }
예제 #26
0
    protected virtual ICommand CreateCommand(StompFrame frame)
    {
        var command = frame.Command;

        switch (command)
        {
        case "RECEIPT":
        {
            var text = frame.RemoveProperty(PropertyKeys.ReceiptId);
            if (text != null)
            {
                var answer = new Response();
                if (text.StartsWith("ignore:", StringComparison.Ordinal))
                {
                    text = text.Substring("ignore:".Length);
                }

                answer.CorrelationId = Int32.Parse(text);
                return(answer);
            }
        }
        break;

        case "CONNECTED":
            return(ReadConnected(frame));

        case "ERROR":
        {
            var text = frame.RemoveProperty(PropertyKeys.ReceiptId);

            if (text?.StartsWith("ignore:", StringComparison.Ordinal) == true)
            {
                return new Response {
                           CorrelationId = Int32.Parse(text.Substring("ignore:".Length))
                }
            }
            ;

            var answer = new ExceptionResponse();
            if (text != null)
            {
                answer.CorrelationId = Int32.Parse(text);
            }

            var error = new BrokerError {
                Message = frame.RemoveProperty(PropertyKeys.Message)
            };
            answer.Exception = error;
            return(answer);
        }

        case "KEEPALIVE":
            return(new KeepAliveInfo());

        case "MESSAGE":
            return(ReadMessage(frame));
        }

        if (Tracer.IsErrorEnabled)
        {
            Tracer.Error("Unknown command: " + frame.Command + " headers: " + frame.Properties);
        }

        return(null);
    }
예제 #27
0
		private void SendNotImplementedError(StompFrame frame)
		{
			var message = "Sorry, the " + frame.Command + " has not been implemented yet.";
			var errorFrame = StompFrameUtils.CreateErrorFrame(message, frame);
			SendFrame(errorFrame);
		}
예제 #28
0
 internal StompMessageEventArgs(StompFrame Frame)
     : base(Frame)
 {
     SendNAck = false;
 }
예제 #29
0
		public void SendFrame(StompFrame frame)
		{
			using (_lockObject.Lock())
			{
				if (_clientConnection != null)
				{
					_clientConnection.SendFrame(frame);
				}
			}
		}
예제 #30
0
		private void ServerStatusCallback(object state)
		{
			List<ServerSideSession> sessions;
			List<MessageQueue> messageQueues;

			using (_lockObject.Lock())
			{
				if (_serverStatusMessageQueue == null)
				{
					return;
				}

				sessions = new List<ServerSideSession>(_sessions.Values);
				messageQueues = new List<MessageQueue>(_messageQueues.Values);
			}

			// need to be unlocked to perform this, otherwise we could deadlock


			var message = new ServerStatusMessage
			              	{
			              		MessageQueues = new List<MessageQueueStatus>(),
			              		Sessions = new List<SessionStatus>(),
			              	};

			foreach (var session in sessions)
			{
				var status = session.CreateSessionStatus();
				message.Sessions.Add(status);
			}
			foreach (var messageQueue in messageQueues)
			{
				var status = messageQueue.CreateStatus();
				message.MessageQueues.Add(status);
			}

			var frame = new StompFrame(StompCommand.Message);
			frame.Serialize(message);
			frame.SetExpires(_config.ServerStatusPeriod);

			MessageQueue queue;
			using (_lockObject.Lock())
			{
				queue = _serverStatusMessageQueue;
			}

// ReSharper disable ConditionIsAlwaysTrueOrFalse
			if (queue != null)
// ReSharper restore ConditionIsAlwaysTrueOrFalse
			{
				queue.PublishFrame(frame);
				_serverStatusTimer.Change(_config.ServerStatusPeriod, TimeSpan.FromMilliseconds(-1));
			}
		}
예제 #31
0
 internal StompFrameEventArgs(StompFrame Frame)
 {
     _Frame = Frame;
 }
		private void Connected(StompFrame frame)
		{
			using (_lockObject.Lock())
			{
				StartIncomingHeartBeatTimer();
				if (frame.IsHeartBeat)
				{
					// nothing else to do
				}
				else if (frame.Command == StompCommand.Disconnect)
				{
					DisconnectWithoutLocking();
					var keepSession = frame.GetBoolean(StompHeader.NonStandard.KeepSession, false);
					if (!keepSession)
					{
						_serverData.EndSession(_session);
					}
					_session = null;
				}
				else
				{
					try
					{
						// ReSharper disable PossibleNullReferenceException
						_session.ProcessFrame(frame);
						// ReSharper restore PossibleNullReferenceException
					}
					catch (Exception ex)
					{
						if (ex.IsCorruptedStateException())
						{
							throw;
						}
						Log.Error(_logMessagePrefix + "Unexpected error handling " + frame.Command + " frame: " + ex.Message, ex);

						try
						{
							var errorFrame = StompFrameUtils.CreateErrorFrame("internal server error", frame);
							_transport.SendFrame(errorFrame);
							DisconnectWithoutLocking();
						}
						catch (InvalidOperationException)
						{
							// Not ideal, but we can encounter a situation where the transport is shutting down, so if
							// we send anything it is going to throw and exception. Because we currently do not have an
							// API for checking this, we just handle the exception.
						}
					}
				}
			}
		}
예제 #33
0
 /// <summary>
 /// Initializes a new instance.
 /// </summary>
 public StompFrameException(StompFrame frame) : base()
 {
     Frame = frame;
 }
예제 #34
0
        /// <summary>
        /// 添加一个新的订阅地址
        /// </summary>
        /// <param name="subScribeFrame">客户端的订阅数据包</param>
        /// <param name="stompBehavior">客户端连接对象</param>
        /// <returns>null:Success,not NULL:ERROR</returns>
        public StompFrame SubScribe(StompFrame subScribeFrame, StompBehavior stompBehavior)
        {
            //* If the server cannot successfully create the subscription, the server MUST send the client an ERROR frame and disconnect the client.
            lock (stompSubscribeDictionaryLock)
            {
                if (!subScribeFrame.Headers.ContainsKey(StompHeaders.Destination))
                {
                    return(new ErrorFrame("Headers missing:'destination'", "SUBSCRIBE 包必须携带'destination'头,而且值不能为空.\nSUBSCRIBE Frame's headers MUST Contain 'destination',and the value MUST NOT null/empty", subScribeFrame));
                }
                else if (string.IsNullOrEmpty(subScribeFrame.Headers[StompHeaders.Destination]))
                {
                    return(new ErrorFrame("Header['destination'] MUST NOT be null or empty", "SUBSCRIBE 包规定header['destination']的值不能为空.\nSUBSCRIBE Frame's header['destination']: MUST NOT be null/empty", subScribeFrame));
                }
                else if (!subscribeSupportTopicList.Contains(subScribeFrame.Headers[StompHeaders.Destination]))
                {
                    return(new ErrorFrame("Stomp Server not support this destination", "Stomp Server not support this destination : '" + subScribeFrame.Headers[StompHeaders.Destination] + "'\n", subScribeFrame));
                }
                else if (!subScribeFrame.Headers.ContainsKey(StompHeaders.Id))//subid
                {
                    return(new ErrorFrame("Headers missing: 'id'", "SUBSCRIBE 包必须携带'id'头,而且值不能为空.\nSUBSCRIBE Frame's headers MUST Contain 'id',and the value MUST uniquely" + "\nSince a single connection can have multiple open subscriptions with a server, an id header MUST be included in the frame to uniquely identify the subscription.", subScribeFrame));
                }
                else if (string.IsNullOrEmpty(subScribeFrame.Headers[StompHeaders.Id]))
                {
                    return(new ErrorFrame("Header['id'] MUST NOT be null or empty,and MUST uniquely.", "SUBSCRIBE 包必须携带'id'头,而且值必须唯一.\nSUBSCRIBE Frame's header['id'] MUST NOT null/empty,and MUST uniquely.", subScribeFrame));
                }
                if (stompBehavior.topicPathSubidDictionary.Values.Contains(subScribeFrame.Headers[StompHeaders.Id]))// check id
                {
                    if (stompBehavior.topicPathSubidDictionary.Keys.Contains(subScribeFrame.Headers[StompHeaders.Destination]) && stompBehavior.topicPathSubidDictionary[subScribeFrame.Headers[StompHeaders.Destination]] == subScribeFrame.Headers[StompHeaders.Id])
                    {
                        return(null);
                    }
                    else
                    {
                        // subid 已经用在了别的地址上
                        string destinationOfsubid = stompBehavior.topicPathSubidDictionary.FirstOrDefault(d => d.Value == subScribeFrame.Headers[StompHeaders.Id]).Key;
                        return(new ErrorFrame("SUBSCRIBE: ['id'] MUST uniquely", "this sub-id is alread been used with this destination:" + destinationOfsubid + ".\n sub-id MUST uniquely,please use another id", subScribeFrame));

                        //stompBehavior.topicPathSubidDictionary[subScribeFrame.Headers[StompHeaders.Destination]] = subScribeFrame.Headers[StompHeaders.Id];//update sub-id
                    }
                }

                if (stompBehavior.topicPathSubidDictionary.ContainsKey(subScribeFrame.Headers[StompHeaders.Destination]))//check destination
                {
                    // 已经订阅过,id都匹配
                    if (stompBehavior.topicPathSubidDictionary[subScribeFrame.Headers[StompHeaders.Destination]] == subScribeFrame.Headers[StompHeaders.Id])
                    {
                        return(null);
                    }
                    else //换了一个sub-id
                    {
                        // destination已经匹配了一个sub-id
                        //return new ErrorFrame("SUBSCRIBE: ['destination'] already linked a sub-id", "this destination is alread linked a sub-id:" + stompBehavior.topicPathSubidDictionary[subScribeFrame.Headers[StompHeaders.Destination]] + ".\n Stomp Server Don't want client Subscribe one destination by many times.", subScribeFrame);


                        // update sub-id
                        stompBehavior.topicPathSubidDictionary[subScribeFrame.Headers[StompHeaders.Destination]] = subScribeFrame.Headers[StompHeaders.Id];
                    }
                }

                //
                // ack ... Not support!
                //


                //
                // Stomp1.0
                // The body of the SUBSCRIBE command is ignored.
                //



                if (!stompBehavior.topicPathSubidDictionary.ContainsKey(subScribeFrame.Headers[StompHeaders.Destination]))
                {
                    stompBehavior.topicPathSubidDictionary.Add(subScribeFrame.Headers[StompHeaders.Destination], subScribeFrame.Headers[StompHeaders.Id]);//stompBehavior<destination:id> Add
                }

                //SubscribeFlowDirction subscribeFlowDirction = GetSubscribeFlowDirction(subScribeFrame.Headers[StompHeaders.Destination]);
                //if (subscribeFlowDirction == SubscribeFlowDirction.Application || subscribeFlowDirction == SubscribeFlowDirction.Unkonw)//Unkonw  is Error ?
                //{
                //    return null;
                //}


                if (stompSubscribeDictionary.ContainsKey(subScribeFrame.Headers[StompHeaders.Destination]))
                {
                    var idStompBehaviorKV = stompSubscribeDictionary[subScribeFrame.Headers[StompHeaders.Destination]];
                    if (!idStompBehaviorKV.ContainsKey(stompBehavior.ID))
                    {
                        stompSubscribeDictionary[subScribeFrame.Headers[StompHeaders.Destination]].Add(stompBehavior.ID, stompBehavior);
                    }
                }
                else
                {
                    stompSubscribeDictionary.Add(subScribeFrame.Headers[StompHeaders.Destination], new Dictionary <string, StompBehavior>()
                    {
                        { stompBehavior.ID, stompBehavior }
                    });
                }
            }
            return(null);
        }
		// ReSharper restore UnusedParameter.Local
		// ReSharper restore MemberCanBeMadeStatic.Local

		private void ExpectingConnect(StompFrame frame)
		{
			if (frame.Command != StompCommand.Connect
				&& frame.Command != StompCommand.Stomp)
			{
				string message = "Expecting " + StompCommand.Connected 
					+ " or " + StompCommand.Stomp
					+ " command, received " + frame.Command;
				Log.Error(_logMessagePrefix + message);
				var errorFrame = StompFrameUtils.CreateErrorFrame(message);
				_transport.SendFrame(errorFrame);
				DisconnectWithoutLocking();
				return;
			}

			var login = frame.Headers[StompHeader.Login];
			var passcode = frame.Headers[StompHeader.Passcode];

			if (!Authenticate(login, passcode))
			{
				string message = "Received " + frame.Command + " frame, Access denied";
				Log.Warn(_logMessagePrefix + message);
				var errorFrame = StompFrameUtils.CreateErrorFrame(message);
				_transport.SendFrame(errorFrame);
				DisconnectWithoutLocking();
				return;
			}

			Log.Debug(_logMessagePrefix + "Received " + frame.Command + " frame, authenticated OK");

			var sessionId = frame.Headers[StompHeader.Session];
			ServerSideSession session = null;

			if (sessionId != null)
			{
				session = _serverData.FindSession(sessionId);
				if (session == null)
				{
					Log.Warn(_logMessagePrefix + "Received " + frame.Command + " frame for non-existent session: " + sessionId);
					var message = ErrorMessages.SessionDoesNotExistPrefix + sessionId;
					var errorFrame = StompFrameUtils.CreateErrorFrame(message);
					_transport.SendFrame(errorFrame);
					DisconnectWithoutLocking();
					return;
				}

				if (!session.AddConnection(this))
				{
					var message = frame.Command + " frame requested a session already in use: " + sessionId;
					Log.Warn(_logMessagePrefix + message);
					var errorFrame = StompFrameUtils.CreateErrorFrame(message);
					_transport.SendFrame(errorFrame);
					DisconnectWithoutLocking();
					return;
				}

				Log.Debug(_logMessagePrefix + "Reconnected to session " + sessionId);
			}

			if (session == null)
			{
				session = _serverData.CreateSession();
				session.AddConnection(this);
				Log.Debug(_logMessagePrefix + "Created new session " + session.SessionId);
			}

			// helps with debugging if we give the session a more friendly name
			session.ClientId = frame.Headers[StompHeader.NonStandard.ClientId]; 
			_session = session;

			var connectedFrame = new StompFrame
			                     	{
			                     		Command = StompCommand.Connected,
			                     		Headers =
			                     			{
			                     				{StompHeader.Session, session.SessionId}
			                     			}
			                     	};

			if (frame.Headers[StompHeader.HeartBeat] == null)
			{
				// no heart-beat header received, so we default to 0,0
				_negotiatedHeartBeats = new HeartBeatValues(0, 0);
			}
			else
			{
				var otherHeartBeatValues = new HeartBeatValues(frame.Headers[StompHeader.HeartBeat]);
				var myHeartBeatValues = new HeartBeatValues(30000, 30000);
				_negotiatedHeartBeats = myHeartBeatValues.CombineWith(otherHeartBeatValues);
				connectedFrame.Headers[StompHeader.HeartBeat] = _negotiatedHeartBeats.ToString();
			}
			_transport.SendFrame(connectedFrame);
			StopConnectTimer();
			StartIncomingHeartBeatTimer();
			StartOutgoingHeartBeatTimer();
			_stateAction = Connected;
			Log.Debug(_logMessagePrefix + "Session " + session + " connected");
		}
예제 #36
0
    protected virtual void WriteMessage(BytesMessage command, BinaryWriter dataOut)
    {
        var frame = new StompFrame("SEND", _encodeHeaders);

        if (command.ResponseRequired)
        {
            frame.SetProperty(PropertyKeys.Receipt, command.CommandId);
        }

        frame.SetProperty(PropertyKeys.Destination, command.Destination.ConvertToStompString());

        if (command.ReplyTo != null)
        {
            frame.SetProperty(PropertyKeys.ReplyTo, command.ReplyTo.ConvertToStompString());
        }
        if (command.CorrelationId != null)
        {
            frame.SetProperty(PropertyKeys.CorrelationId, command.CorrelationId);
        }
        if (command.Expiration != 0)
        {
            frame.SetProperty(PropertyKeys.Expires, command.Expiration);
        }
        if (command.Timestamp != 0)
        {
            frame.SetProperty(PropertyKeys.TimeStamp, command.Timestamp);
        }
        if (command.Priority != 4)
        {
            frame.SetProperty(PropertyKeys.Priority, command.Priority);
        }
        if (command.Type != null)
        {
            frame.SetProperty(PropertyKeys.Type, command.Type);
        }
        if (command.TransactionId != null)
        {
            frame.SetProperty(PropertyKeys.Transaction, command.TransactionId.ToString());
        }

        frame.SetProperty(PropertyKeys.Persistent,
                          command.Persistent.ToString()
                          .ToLower());
        frame.SetProperty(PropertyKeys.NmsxDeliveryMode,
                          command.Persistent.ToString()
                          .ToLower());

        if (command.StompGroupId != null)
        {
            frame.SetProperty(PropertyKeys.JmsxGroupId, command.StompGroupId);
            frame.SetProperty(PropertyKeys.NmsxGroupId, command.StompGroupId);
            frame.SetProperty(PropertyKeys.JmsxGroupSeq, command.StompGroupSeq);
            frame.SetProperty(PropertyKeys.NmsxGroupSeq, command.StompGroupSeq);
        }

        // Store the Marshaled Content.
        frame.Content = command.Content;

        if (command.Content?.Length > 0 && StompNetConfiguration.AddContentLengthHeader)
        {
            frame.SetProperty(PropertyKeys.ContentLength, command.Content.Length);
        }

        frame.SetProperty(PropertyKeys.Transformation, "jms-byte");

        // Marshal all properties to the Frame.
        var map = command.Headers;

        foreach (var key in map.Keys)
        {
            frame.SetProperty(key, map[key]);
        }

        frame.ToStream(dataOut);
    }
예제 #37
0
		public void LogSendMessage(StompFrame frame, string destination)
		{
			MessageQueue messageLoggingQueue = null;

			if (_messageLogMessageQueue != null)
			{
				using (_lockObject.Lock())
				{
// ReSharper disable ConditionIsAlwaysTrueOrFalse
					if (_messageLogMessageQueue != null)
// ReSharper restore ConditionIsAlwaysTrueOrFalse
					{
						messageLoggingQueue = _messageLogMessageQueue;
					}
				}
			}

			if (messageLoggingQueue != null)
			{
				var msg = new MessageLogMessage
				          	{
				          		SentAt = DateTime.Now,
				          		ContentLength = frame.GetInt32(StompHeader.ContentLength, 0),
				          		Destination = destination,
				          	};
				var msgFrame = new StompFrame(StompCommand.Message)
				               	{
				               		Headers =
				               			{
				               				{StompHeader.Destination, messageLoggingQueue.Name}
				               			}
				               	};
				msgFrame.Serialize(msg);



				messageLoggingQueue.PublishFrame(msgFrame);
			}
		}
예제 #38
0
		/// <summary>
		/// 	Sends the frame to all currently published subscribers.
		/// </summary>
		public void PublishFrame(StompFrame frame)
		{
			lock (_lockObject)
			{
				++_totalMessageCount;
				if (_subscriptions.Count == 0)
				{
					// no subscriptions
					return;
				}
			}

			ThreadPool.QueueUserWorkItem(delegate { MessagePublished(this, new StompMessageEventArgs(frame)); });
		}
예제 #39
0
		public static StompFrame CreateMissingHeaderError(string missingHeader, StompFrame frame)
		{
			var message = frame.Command + " is missing mandatory header: " + missingHeader;
			return CreateErrorFrame(message, frame);
		}
		private void ShuttingDown(StompFrame frame)
		{
			Log.WarnFormat(_logMessagePrefix + "Discarded {0} message as connection is shutting down", frame.Command);
		}
예제 #41
0
		private void ProcessFrameByCommand(StompFrame frame)
		{
			// Note that we do not process the disconnect command here, as it is handled by the ClientConnection.
			switch (frame.Command)
			{
				case StompCommand.Send:
					HandleSendCommand(frame);
					break;

				case StompCommand.Subscribe:
					HandleSubscribeCommand(frame);
					break;

				case StompCommand.Unsubscribe:
					HandleUnsubscribeCommand(frame);
					break;

				case StompCommand.Begin:
					HandleBeginCommand(frame);
					break;

				case StompCommand.Commit:
					HandleCommitCommand(frame);
					break;

				case StompCommand.Abort:
					HandleAbortCommand(frame);
					break;

				case StompCommand.Ack:
					HandleAckCommand(frame);
					break;

				default:
					HandleUnknownCommand(frame);
					break;
			}
		}
예제 #42
0
		// Creates a unique, monotonically increasing message id
		// Current implementation would need to generate >10 million messages per second
		// Consistently to give any chance of a repeat number.
		public static long AllocateMessageId(StompFrame frame)
		{
			var messageId = Interlocked.Increment(ref _messageId);
			frame.Headers[StompHeader.MessageId] = messageId.ToString();
			return messageId;
		}
예제 #43
0
		private void HandleSendCommand(StompFrame frame)
		{
			var destination = frame.Headers[StompHeader.Destination];
			if (destination == null)
			{
				const string message = "Missing " + StompHeader.Destination + " in " + StompCommand.Send + " command";
				var errorFrame = StompFrameUtils.CreateErrorFrame(message, frame);
				SendFrame(errorFrame);
				return;
			}

			var publish = false;

			if (destination.StartsWith(QueueName.PublishPrefix))
			{
				destination = destination.Substring(QueueName.PublishPrefix.Length);
				publish = true;
			}
			else if (destination.StartsWith(QueueName.QueuePrefix))
			{
				destination = destination.Substring(QueueName.QueuePrefix.Length);
			}

			var messageQueue = _serverData.FindMessageQueue(destination);

			// TODO: we could probably get away without creating a copy, and modifying the frame
			// Don't allocate the message-id here, as the message queue does it.
			var messageFrame = StompFrameUtils.CreateCopy(frame);
			messageFrame.Command = StompCommand.Message;
			if (publish)
			{
				Log.Debug("Publishing message to topic: " + messageQueue.Name);
				messageQueue.PublishFrame(messageFrame);
			}
			else
			{
				Log.Debug("Adding message to queue: " + messageQueue.Name);
				messageQueue.AddFrame(messageFrame);
			}
			SendReceiptIfNecessary(frame);
			_serverData.LogSendMessage(frame, destination);
		}
예제 #44
0
		private void HandleSubscribeCommand(StompFrame frame)
		{
			var id = frame.Headers[StompHeader.Id];
			var destination = frame.Headers[StompHeader.Destination];
			var ack = frame.Headers[StompHeader.Ack];

			if (string.IsNullOrEmpty(id))
			{
				var errorFrame = StompFrameUtils.CreateMissingHeaderError(StompHeader.Id, frame);
				SendFrame(errorFrame);
				Disconnect();
				return;
			}

			if (string.IsNullOrEmpty(destination))
			{
				var errorFrame = StompFrameUtils.CreateMissingHeaderError(StompHeader.Destination, frame);
				SendFrame(errorFrame);
				Disconnect();
				return;
			}

			if (_subscriptions.ContainsKey(id))
			{
				var message = "Subscription already exists: " + id;
				var errorFrame = StompFrameUtils.CreateErrorFrame(message, frame);
				SendFrame(errorFrame);
				Disconnect();
				return;
			}

			var messageQueue = _serverData.FindMessageQueue(destination);

			var subscription = new ServerSideSubscription(this, id, messageQueue, ack);
			_subscriptions.Add(id, subscription);
			SendReceiptIfNecessary(frame);

		}
예제 #45
0
		public void AddFrame(StompFrame frame)
		{
			lock (_lockObject)
			{
				++_totalMessageCount;
				_linkedList.AddLast(frame);
			}

			ThreadPool.QueueUserWorkItem(delegate { MessageReceived(this, EventArgs.Empty); });
		}
예제 #46
0
		private void HandleUnsubscribeCommand(StompFrame frame)
		{
			var id = frame.Headers[StompHeader.Id];
			if (string.IsNullOrEmpty(id))
			{
				var errorFrame = StompFrameUtils.CreateMissingHeaderError(StompHeader.Id, frame);
				SendFrame(errorFrame);
				Disconnect();
				return;
			}

			if (!_subscriptions.ContainsKey(id))
			{
				var message = "Subscription does not exist: " + id;
				var errorFrame = StompFrameUtils.CreateErrorFrame(message, frame);
				SendFrame(errorFrame);
				Disconnect();
				return;
			}

			var subscription = _subscriptions[id];
			_subscriptions.Remove(id);
			subscription.Dispose();
			SendReceiptIfNecessary(frame);
		}
예제 #47
0
        static void Main(string[] args)
        {
            STOMPClient Client = new STOMPClient();

            NextTest("Frame Serialize, Deserialize, Serialize");

            StompSendFrame Frame = new StompSendFrame("MyDestination", "This is the packet body here");

            Frame.Receipt = "ReceiptIdHere";
            Frame.AdditionalHeaders.Add(new KeyValuePair <string, string>("my-header", "MyValue"));

            string Output = Client.GetSerializedPacket(Frame);

            Console.WriteLine(Output);

            StompFrame Rebuilt = Client.GetBuiltFrame(System.Text.Encoding.UTF8.GetBytes(Output));

            Console.WriteLine("");
            Console.WriteLine("------");
            Console.WriteLine("");

            Output = Client.GetSerializedPacket(Rebuilt);
            Console.WriteLine(Output);

            Console.WriteLine("");
            Console.WriteLine("------");

            NextTest("RingBuffer Data Length");

            StompRingBuffer <int> Buffer = new StompRingBuffer <int>(128);

            int[] Data = new int[64];
            for (int i = 0; i < Data.Length; i++)
            {
                Data[i] = i + 1;
            }

            Buffer.Write(Data);

            Console.WriteLine(string.Format("Available Write before read: {0}", Buffer.AvailableWrite));

            int[] Data2 = Buffer.Read(Buffer.AvailableRead);
            Console.WriteLine(string.Format("Available Write after read: {0}", Buffer.AvailableWrite));
            Console.WriteLine(string.Format("Lengths: {0} and {1}", Data.Length, Data2.Length));

            NextTest("Data Comparison");

            for (int i = 0; i < Math.Min(Data.Length, Data2.Length); i++)
            {
                Console.WriteLine(string.Format("{0} {1}", Data[i], Data2[i]));
            }

            NextTest("Seek Back 32");

            Console.WriteLine(string.Format("Seek Ptr is {0}", Buffer.Seek(-32)));
            Console.WriteLine(string.Format("Available is {0}", Buffer.AvailableRead));
            Data2 = Buffer.Read(Buffer.AvailableRead);
            Console.WriteLine(string.Format("Read out {0}", Data2.Length));
            Console.WriteLine(string.Format("Seek Ptr is {0}", Buffer.Seek(0)));

            NextTest("Old Data");


            foreach (int D in Data2)
            {
                Console.WriteLine(string.Format("{0} ", D));
            }

            NextTest("Write and Read");

            Buffer.Write(Data, 32);
            Buffer.Seek(-32);
            Data2 = Buffer.Read(Buffer.AvailableRead);
            Console.WriteLine(string.Format("Write 32; Read out {0}", Data2.Length));

            NextTest("Data");

            foreach (int D in Data2)
            {
                Console.WriteLine(string.Format("{0} ", D));
            }

            NextTest("Seek Forward");

            Console.WriteLine(string.Format("Available Read is {0}, should be 0", Buffer.AvailableRead));

            Console.WriteLine(string.Format("Write {0}", Data.Length));
            Buffer.Write(Data);

            Console.WriteLine(string.Format("Available Read is {0}", Buffer.AvailableRead));
            Buffer.Seek(10);
            Console.WriteLine(string.Format("Seek; Ptr is {0}", Buffer.Seek(0)));
            Console.WriteLine(string.Format("Available Read is {0}", Buffer.AvailableRead));

            Data2 = Buffer.Read(Buffer.AvailableRead);
            Console.WriteLine(string.Format("Read out {0}", Data2.Length, Data.Length));
            Console.WriteLine(string.Format("Available Read is {0}", Buffer.AvailableRead));

            Console.WriteLine(string.Format("Seek Ptr is {0}", Buffer.Seek(0)));

            NextTest("Data");

            foreach (int D in Data2)
            {
                Console.WriteLine(string.Format("{0} ", D));
            }

            Console.ReadLine();
        }
예제 #48
0
 internal StompMessageEventArgs(StompFrame Frame) : base(Frame)
 {
     SendNAck = false;
 }