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; }
/// <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; }
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); }
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); }
/// <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); } } } } }
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); }
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; } } }
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); } }
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); }
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); } }
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()); }
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); } }
private void HandleUnknownCommand(StompFrame frame) { var message = "Unknown command: " + frame.Command; var errorFrame = StompFrameUtils.CreateErrorFrame(message, frame); SendFrame(errorFrame); Disconnect(); }
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); }
private void HandleAbortCommand(StompFrame frame) { // TODO: handle send command SendNotImplementedError(frame); }
protected virtual void WriteKeepAliveInfo(KeepAliveInfo command, BinaryWriter dataOut) { var frame = new StompFrame(StompFrame.Keepalive, _encodeHeaders); frame.ToStream(dataOut); }
/// <summary> /// Initializes a new instance. /// </summary> public StompFrameException(StompFrame frame, string message) : base(message) { Frame = frame; }
/// <summary> /// Note that the caller handles exceptions here /// </summary> /// <param name="frame"></param> public void ProcessFrame(StompFrame frame) { using (_lockObject.Lock()) { ProcessFrameByCommand(frame); } }
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); } }
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()); } } }
internal StompFrameEventArgs(StompFrame Frame) { _Frame = Frame; }
/// <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; } }
/// <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); }
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); }
private void SendNotImplementedError(StompFrame frame) { var message = "Sorry, the " + frame.Command + " has not been implemented yet."; var errorFrame = StompFrameUtils.CreateErrorFrame(message, frame); SendFrame(errorFrame); }
internal StompMessageEventArgs(StompFrame Frame) : base(Frame) { SendNAck = false; }
public void SendFrame(StompFrame frame) { using (_lockObject.Lock()) { if (_clientConnection != null) { _clientConnection.SendFrame(frame); } } }
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)); } }
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. } } } } }
/// <summary> /// Initializes a new instance. /// </summary> public StompFrameException(StompFrame frame) : base() { Frame = frame; }
/// <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"); }
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); }
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); } }
/// <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)); }); }
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); }
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; } }
// 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; }
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); }
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); }
public void AddFrame(StompFrame frame) { lock (_lockObject) { ++_totalMessageCount; _linkedList.AddLast(frame); } ThreadPool.QueueUserWorkItem(delegate { MessageReceived(this, EventArgs.Empty); }); }
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); }
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(); }