public ServerSideSubscription(ServerSideSession session, string subscriptionId, MessageQueue messageQueue,
		                              string ack)
		{
			Session = Verify.ArgumentNotNull(session, "session");
			SubscriptionId = Verify.ArgumentNotNull(subscriptionId, "subscriptionId");
			MessageQueue = Verify.ArgumentNotNull(messageQueue, "messageQueue");
			MessageQueue.AddSubscription(this);
			AutoAcknowledge = ack == StompAck.Auto;

			MessageQueue.MessageReceived += MessageQueueMessageReceived;
			MessageQueue.MessagePublished += MessageQueueMessagePublished;
		}
예제 #2
0
		public void EndSession(ServerSideSession session)
		{
			if (session != null)
			{
				using (_lockObject.Lock())
				{
					_sessions.Remove(session.SessionId);
					session.Dispose();
				}
			}
		}
		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.
						}
					}
				}
			}
		}
예제 #4
0
		public ServerSideSession CreateSession()
		{
			using (_lockObject.Lock())
			{
				var session = new ServerSideSession(this);
				_sessions.Add(session.SessionId, session);
				return session;
			}
		}
		// 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");
		}