Beispiel #1
0
 protected override MessageBase CopyImpl(MessageBase clone)
 {
     // Instantiate the clone, if a derived type hasn't already.
     if (clone == null)
     {
         clone = new AcknowledgeMessage();
     }
     return(base.CopyImpl(clone));
 }
		public CachedBody(AMFBody requestBody, IMessage message, object content):base(requestBody, content)
		{
			//Fix content of body for flex messages
			AcknowledgeMessage responseMessage = new AcknowledgeMessage();
			responseMessage.body = content;
			responseMessage.correlationId = message.messageId;
			responseMessage.destination = message.destination;
			responseMessage.clientId = message.clientId;

			this.Content = responseMessage;
		}
		/// <summary>
		/// Call this method in order to send a message from your code into the message routing system.
		/// The message is routed to a service that is defined to handle messages of this type.
		/// Once the service is identified, the destination property of the message is used to find a destination configured for that service.
		/// The adapter defined for that destination is used to handle the message.
		/// </summary>
		/// <param name="message">The message to be routed to a service.</param>
		/// <param name="endpoint">This can identify the endpoint that is sending the message but it is currently not used so you may pass in null.</param>
        /// <returns>The result of the message routing.</returns>
		internal IMessage RouteMessage(IMessage message, IEndpoint endpoint)
		{
			IService service = null;
			object result = null;
			IMessage responseMessage = null;

            if( log.IsDebugEnabled )
                log.Debug(__Res.GetString(__Res.MessageBroker_RoutingMessage, message.ToString()));

			CommandMessage commandMessage = message as CommandMessage;
			if( commandMessage != null && (commandMessage.operation == CommandMessage.LoginOperation || commandMessage.operation == CommandMessage.LogoutOperation) )//Login, Logout
			{
				try
				{
					service = GetService(AuthenticationService.ServiceId);
					result = service.ServiceMessage(commandMessage);
					responseMessage = result as IMessage;
				}
                catch (UnauthorizedAccessException uae)
                {
                    if (log.IsDebugEnabled)
                        log.Debug(uae.Message);
                    responseMessage = ErrorMessage.GetErrorMessage(message, uae);
                }
                catch (SecurityException exception)
                {
                    if (log.IsDebugEnabled)
                        log.Debug(exception.Message);
                    responseMessage = ErrorMessage.GetErrorMessage(message, exception);
                }
				catch(Exception exception)
				{
					if(log.IsErrorEnabled)
						log.Error(__Res.GetString(__Res.MessageBroker_RoutingError), exception);
					responseMessage = ErrorMessage.GetErrorMessage(message, exception);
				}
			}
            else if (commandMessage != null && commandMessage.operation == CommandMessage.ClientPingOperation)
            {
                responseMessage = new AcknowledgeMessage();
                responseMessage.body = true;
            }
            else
            {
				//The only case when context is not set should be when one starts a new thread in the backend
                //if( FluorineContext.Current != null )
                //    FluorineContext.Current.RestorePrincipal(this.LoginCommand);
                _loginManager.RestorePrincipal();
				service = GetService(message);
                if (service != null)
                {
                    try
                    {
                        service.CheckSecurity(message);
                        result = service.ServiceMessage(message);
                    }
                    catch (UnauthorizedAccessException uae)
                    {
                        if (log.IsDebugEnabled)
                            log.Debug(uae.Message);
                        result = ErrorMessage.GetErrorMessage(message, uae);
                    }
                    catch (SecurityException exception)
                    {
                        if (log.IsDebugEnabled)
                            log.Debug(exception.Message);
                        result = ErrorMessage.GetErrorMessage(message, exception);
                    }
                    catch (ServiceException exception)
                    {
                        if (log.IsDebugEnabled)
                            log.Debug(exception.Message);
                        result = ErrorMessage.GetErrorMessage(message, exception);
                    }
                    catch (Exception exception)
                    {
                        if (log.IsErrorEnabled)
                            log.Error(exception.Message, exception);
                        result = ErrorMessage.GetErrorMessage(message, exception);
                    }
                }
                else
                {
                    string msg = __Res.GetString(__Res.Destination_NotFound, message.destination);
                    if (log.IsErrorEnabled)
                        log.Error(msg);
                    result = ErrorMessage.GetErrorMessage(message, new FluorineException(msg));
                }
                if (!(result is IMessage))
                {
                    responseMessage = new AcknowledgeMessage();
                    responseMessage.body = result;
                }
                else
                    responseMessage = result as IMessage;
            }

			if( responseMessage is AsyncMessage )
			{
				((AsyncMessage)responseMessage).correlationId = message.messageId;
			}
			responseMessage.destination = message.destination;
			responseMessage.clientId = message.clientId;

			//Debug
			if( message.HeaderExists(AMFHeader.DebugHeader) )
			{
				log.Debug("MessageBroker processing debug header");
				ArrayList traceStack = NetDebug.GetTraceStack();
				responseMessage.SetHeader(AMFHeader.DebugHeader, traceStack.ToArray(typeof(object)) as object[]);
				NetDebug.Clear();
			}
            //The only case when we do not have context should be when the server side initiates a push
            if( FluorineContext.Current != null && FluorineContext.Current.Client != null )
                responseMessage.SetHeader(MessageBase.FlexClientIdHeader, FluorineContext.Current.Client.Id);

            if (log.IsDebugEnabled)
                log.Debug(__Res.GetString(__Res.MessageBroker_Response, responseMessage.ToString()));

			return responseMessage;
		}
Beispiel #4
0
		public override object ServiceMessage(IMessage message)
		{
			CommandMessage commandMessage = message as CommandMessage;
			if( commandMessage != null )
			{
                //Sub/unsub handled by base class
				return base.ServiceMessage(commandMessage);
			}
			else
			{
				AsyncMessage responseMessage = null;
				DataMessage dataMessage = message as DataMessage;

				DataDestination dataDestination = this.GetDestination(dataMessage) as DataDestination;
				if( dataDestination.SubscriptionManager.GetSubscriber(dataMessage.clientId as string) == null )
				{
					//Subscribe here as DS doesn't send a separate subscribe command
                    CommandMessage commandMessageSubscribe = new CommandMessage();
                    commandMessageSubscribe.destination = dataDestination.Id;
                    commandMessageSubscribe.operation = CommandMessage.SubscribeOperation;
                    commandMessageSubscribe.clientId = dataMessage.clientId as string;
                    string endpointId = dataMessage.GetHeader(MessageBase.EndpointHeader) as string;
                    commandMessageSubscribe.headers[MessageBase.EndpointHeader] = endpointId;
                    string flexClientIdHeader = dataMessage.GetHeader(MessageBase.FlexClientIdHeader) as string;
                    if( flexClientIdHeader != null )
                        commandMessageSubscribe.headers[MessageBase.FlexClientIdHeader] = flexClientIdHeader;
                    IEndpoint endpoint = GetMessageBroker().GetEndpoint(endpointId);
                    endpoint.ServiceMessage(commandMessageSubscribe);//route through the endpoint again
                    //base.ServiceMessage(commandMessageSubscribe);
				}

				switch(dataMessage.operation)
				{
					case DataMessage.FillOperation:
						responseMessage = ExecuteFillOperation(message);
						break;
					case DataMessage.GetOperation:
						responseMessage = ExecuteGetOperation(message);
						break;
					case DataMessage.BatchedOperation:
					case DataMessage.MultiBatchOperation:
					case DataMessage.TransactedOperation:
						responseMessage = ExecuteMultiBatchOperation(message);
						break;
					case DataMessage.PageItemsOperation:
						responseMessage = ExecutePageItemsOperation(message);
						break;
					case DataMessage.PageOperation:
						responseMessage = ExecutePageOperation(message);
						break;
					case DataMessage.ReleaseCollectionOperation:
						responseMessage = ExecuteReleaseCollectionOperation(message);
						break;
					case DataMessage.GetSequenceIdOperation:
						responseMessage = ExecuteGetSequenceIdOperation(message);
						break;
					case DataMessage.ReleaseItemOperation:
						responseMessage = ExecuteReleaseItemOperation(message);
						break;
					default:
						if(log.IsErrorEnabled)
							log.Error(__Res.GetString(__Res.DataService_Unknown, dataMessage.operation));

						responseMessage = new AcknowledgeMessage();
						break;
				}
				responseMessage.clientId = message.clientId;
				responseMessage.correlationId = message.messageId;
				//Dump();
				return responseMessage;
			}
		}
Beispiel #5
0
		private AcknowledgeMessage ExecuteMultiBatchOperation(IMessage message)
		{
			//May contain multiple batched, create, update or delete operations that involve 
			//more than one destination, that is, more than one remote adapter
			AcknowledgeMessage responseMessage = null;
			DataMessage dataMessage = message as DataMessage;
			IList messages = dataMessage.body as IList;

			DataServiceTransaction dataServiceTransaction = DataServiceTransaction.Begin(this);
			dataServiceTransaction.ClientId = message.clientId as string;
			//correlate al generated messages
			dataServiceTransaction.CorrelationId = message.messageId;

			string currentDestination = null;
			ArrayList currentMessageBatch = new ArrayList();

			for(int i = 0; i < messages.Count; i++)
			{
				DataMessage batchMessage = messages[i] as DataMessage;
				string destination = batchMessage.destination;
				DataDestination dataDestination = GetDestination(batchMessage) as DataDestination;
				
				if( currentDestination != null && destination != currentDestination &&
					currentMessageBatch.Count > 0 )
				{
					MessageBatch messageBatch = ServiceBatch(message, currentMessageBatch);
					dataServiceTransaction.AddProcessedMessageBatch(messageBatch);
					currentMessageBatch = new ArrayList();
				}
				currentMessageBatch.Add(batchMessage);
				currentDestination = destination;

				if(batchMessage is UpdateCollectionMessage)
					dataServiceTransaction.AddClientUpdateCollection(batchMessage as UpdateCollectionMessage);
			}
			if(currentMessageBatch.Count > 0)
			{
				MessageBatch messageBatch = ServiceBatch(message, currentMessageBatch);
				dataServiceTransaction.AddProcessedMessageBatch(messageBatch);
			}
			
			dataServiceTransaction.Commit();
			IList outgoingMessages = dataServiceTransaction.GetOutgoingMessages();
			responseMessage = new AcknowledgeMessage();
			object[] result = new object[outgoingMessages.Count];
			outgoingMessages.CopyTo(result, 0);
			responseMessage.body = result;//outgoingMessages.ToArray(typeof(object));
			return responseMessage;
		}
Beispiel #6
0
		private AcknowledgeMessage ExecuteReleaseItemOperation(IMessage message)
		{
			AcknowledgeMessage responseMessage = new AcknowledgeMessage();
			DataMessage dataMessage = message as DataMessage;
			DataDestination dataDestination = this.GetDestination(dataMessage) as DataDestination;
			dataDestination.SequenceManager.ReleaseItemOperation(dataMessage);
			return responseMessage;
		}
Beispiel #7
0
		private AcknowledgeMessage ExecuteGetOperation(IMessage message)
		{
			DataMessage dataMessage = message as DataMessage;
			AcknowledgeMessage responseMessage = null;
			DataDestination dataDestination = this.GetDestination(dataMessage) as DataDestination;
			object result = dataDestination.ServiceAdapter.Invoke(message);
			if( result == null )
				responseMessage = new AcknowledgeMessage();
			else
			{
				ArrayList collection = new ArrayList(1);
				collection.Add(result);
				responseMessage = dataDestination.SequenceManager.ManageSequence(dataMessage, collection);
			}
			return responseMessage;
		}
        private void HandleFlexClientStreamingOpenRequest(HttpRequest request, HttpResponse response, IClient flexClient)
        {
            Session session = FluorineContext.Current.Session as Session;
            if (session == null)
            {
                string msg = string.Format("Cannot grant streaming connection when ASP.NET session state is disabled", this.Id);
                if (log.IsWarnEnabled)
                    log.Warn(msg);
                try
                {
                    HandleBadRequest(msg, HttpContext.Current.Response);
                }
                catch (HttpException)
                { }
                return;
            }
            if (!_canStream || !session.CanStream)
            {
                string msg = string.Format("Cannot grant streaming connection, limit has been reached", this.Id);
                try
                {
                    HandleBadRequest(msg, HttpContext.Current.Response);
                }
                catch (HttpException)
                { }
                return;
            }

            bool canStream = false;
            lock (this.SyncRoot)
            {
                _streamingClientsCount.Increment();
                if (_streamingClientsCount.Value == this.MaxStreamingClients)
                {
                    canStream = true; // This thread got the last spot.
                    _canStream = false;
                    
                }
                else if (_streamingClientsCount.Value > this.MaxStreamingClients)
                {
                    canStream = false; // This thread lost the last spot.
                    _streamingClientsCount.Decrement();// We're not going to grant the streaming right to the client.
                }
                else
                {
                    // Allow this thread to stream.
                    canStream = true;
                }
            }
            if (!canStream)
            {
                string msg = string.Format("Cannot service streaming request, max-streaming-clients reached in endpoint {0}", this.Id);
                try
                {
                    HandleBadRequest(msg, HttpContext.Current.Response);
                }
                catch (HttpException)
                { }
                return;
            }

            UserAgent userAgent = this.ChannelDefinition.Properties.UserAgentSettings[request.Browser.Browser];
            if (userAgent != null)
            {
                lock (session.SyncRoot)
                {
                    session.MaxConnectionsPerSession = userAgent.MaxStreamingConnectionsPerSession;
                }
            }

            lock (session.SyncRoot)
            {
                session.StreamingConnectionsCount++;
                if (session.StreamingConnectionsCount == session.MaxConnectionsPerSession)
                {
                    canStream = true; // This thread got the last spot in the session.
                    session.CanStream = false;
                }
                else if (session.StreamingConnectionsCount > session.MaxConnectionsPerSession)
                {
                    canStream = false;
                    session.StreamingConnectionsCount--;
                    _streamingClientsCount.Decrement();
                }
                else
                {
                    canStream = true;
                }
            }
            if (!canStream)
            {
                string msg = string.Format("Cannot grant streaming connection, limit has been reached", this.Id);
                try
                {
                    HandleBadRequest(msg, HttpContext.Current.Response);
                }
                catch (HttpException)
                { }
                return;
            }

            EndpointPushNotifier notifier = null;
            try
            {
                response.ContentType = ContentType.AMF;
                response.AppendHeader("Cache-Control", "no-cache");
                response.AppendHeader("Pragma", "no-cache");
                response.AppendHeader("Connection", "close");
                //response.AppendHeader("Transfer-Encoding", "chunked");
                response.Flush();

                // Setup for specific user agents.
                byte[] kickStartBytesToStream = null;
                int kickStartBytes = userAgent != null ? userAgent.KickstartBytes : 0;
                if (kickStartBytes > 0)
                {
                    // The minimum number of actual bytes that need to be sent to kickstart, taking into account transfer-encoding overhead.
                    try
                    {
                        int chunkLengthHeaderSize = System.Text.Encoding.ASCII.GetBytes(System.Convert.ToString(kickStartBytes, 0x10)).Length; //System.Text.ASCIIEncoding.ASCII.GetBytes(kickStartBytes.ToString("X")).Length;
                        int chunkOverhead = chunkLengthHeaderSize + 4; // 4 for the 2 wrapping CRLF tokens.
                        int minimumKickstartBytes = kickStartBytes - chunkOverhead;
                        kickStartBytesToStream = new byte[(minimumKickstartBytes > 0) ? minimumKickstartBytes : kickStartBytes];
                    }
                    catch
                    {
                        kickStartBytesToStream = new byte[kickStartBytes];
                    }
                }
                if (kickStartBytesToStream != null)
                {
                    StreamChunk(kickStartBytesToStream, response);
                }
                try
                {
                    notifier = new EndpointPushNotifier(this, flexClient);
                    lock (_currentStreamingRequests.SyncRoot)
                    {
                        _currentStreamingRequests.Add(notifier.Id, notifier);
                    }
                    // Push down an acknowledgement for the 'connect' request containing the unique id for this specific stream.
                    AcknowledgeMessage connectAck = new AcknowledgeMessage();
                    connectAck.body = notifier.Id;
                    connectAck.correlationId = OpenCommand;
                    StreamMessage(connectAck, response);
                }
                catch (MessageException)
                {
                }

                if (log.IsDebugEnabled)
                {
                    string msg = string.Format("Start streaming for endpoint with id {0} and client with id {1}", this.Id, flexClient.Id);
                    log.Debug(msg);
                }

                int serverToClientHeartbeatMillis = this.ChannelDefinition.Properties.ServerToClientHeartbeatMillis >= 0 ? this.ChannelDefinition.Properties.ServerToClientHeartbeatMillis : 0;
                serverToClientHeartbeatMillis = 100;
                while (!notifier.IsClosed)
                {
                    IList messages = notifier.GetPendingMessages();
                    StreamMessages(messages, response);
                    lock (notifier.SyncRoot)
                    {
                        Monitor.Wait(notifier.SyncRoot, serverToClientHeartbeatMillis);

                        messages = notifier.GetPendingMessages();
                        // If there are no messages to send to the client, send a 0
                        // byte as a heartbeat to make sure the client is still valid.
                        if ((messages == null || messages.Count == 0) && serverToClientHeartbeatMillis > 0)
                        {
                            try
                            {
                                StreamChunk(Heartbeat, response);
                                response.Flush();
                            }
                            catch (HttpException)
                            {
                                break;
                            }
                            catch (IOException)
                            {
                                break;
                            }
                        }
                        else
                        {
                            StreamMessages(messages, response);
                        }
                    }
                }
                // Terminate the response.
                StreamChunk(null, response);
                if (log.IsDebugEnabled)
                {
                    string msg = string.Format("Releasing streaming connection for endpoint with id {0} and and client with id {1}", this.Id, flexClient.Id);
                    log.Debug(msg);
                }
            }
            catch (IOException ex)//HttpException?
            {
                if (log.IsWarnEnabled)
                    log.Warn("Streaming thread for endpoint with id " + this.Id + " is closing connection due to an IO error.", ex);
            }
            catch (Exception ex)
            {
                if (log.IsErrorEnabled)
                    log.Error("Streaming thread for endpoint with id " + this.Id + " is closing connection due to an error.", ex);
            }
            finally
            {
                if (notifier != null && _currentStreamingRequests != null)
                {
                    if (_currentStreamingRequests != null)
                    {
                        lock (_currentStreamingRequests.SyncRoot)
                        {
                            _currentStreamingRequests.Remove(notifier.Id);
                        }
                    }
                    notifier.Close();
                }
                _streamingClientsCount.Decrement();
                lock (session.SyncRoot)
                {
                    session.StreamingConnectionsCount--;
                    session.CanStream = session.StreamingConnectionsCount < session.MaxConnectionsPerSession;
                }
            }
        }
Beispiel #9
0
        /// <summary>
        /// Handles a message routed to the service by the MessageBroker.
        /// </summary>
        /// <param name="message">The message that should be handled by the service.</param>
        /// <returns>The result of the message processing.</returns>
		public override object ServiceMessage(IMessage message)
		{
			CommandMessage commandMessage = message as CommandMessage;
			MessageDestination messageDestination = GetDestination(message) as MessageDestination;
			if( commandMessage != null )
			{
				string clientId = commandMessage.clientId as string;
                MessageClient messageClient = messageDestination.SubscriptionManager.GetSubscriber(clientId);
                AcknowledgeMessage acknowledgeMessage = null;
                switch (commandMessage.operation)
                {
                    case CommandMessage.SubscribeOperation:
                        if (messageClient == null)
                        {
                            if (clientId == null)
                                clientId = Guid.NewGuid().ToString("D");

                            if (log.IsDebugEnabled)
                                log.Debug(__Res.GetString(__Res.MessageServiceSubscribe, messageDestination.Id, clientId));

                            string endpointId = commandMessage.GetHeader(MessageBase.EndpointHeader) as string;
                            if (_messageBroker.GetEndpoint(endpointId) == null)
                            {
                                ServiceException serviceException = new ServiceException("Endpoint was not specified");
                                serviceException.FaultCode = "Server.Processing.MissingEndpoint";
                                throw serviceException;
                            }
                            commandMessage.clientId = clientId;

                            if (messageDestination.ServiceAdapter != null && messageDestination.ServiceAdapter.HandlesSubscriptions)
                            {
                                try
                                {
                                    acknowledgeMessage = messageDestination.ServiceAdapter.Manage(commandMessage) as AcknowledgeMessage;
                                }
                                catch (MessageException me)
                                {
                                    acknowledgeMessage = me.GetErrorMessage();
                                    //Leave, do not subscribe
                                    return acknowledgeMessage;
                                }
                                catch (Exception ex)
                                {
                                    //Guard against service adapter failure
                                    acknowledgeMessage = ErrorMessage.GetErrorMessage(commandMessage, ex);
                                    if (log.IsErrorEnabled)
                                        log.Error(__Res.GetString(__Res.ServiceAdapter_ManageFail, this.id, messageDestination.Id, commandMessage), ex);
                                    //Leave, do not subscribe
                                    return acknowledgeMessage;
                                }
                            }

                            Subtopic subtopic = null;
                            Selector selector = null;
                            if (commandMessage.headers != null)
                            {
                                if (commandMessage.headers.ContainsKey(CommandMessage.SelectorHeader))
                                {
                                    selector = Selector.CreateSelector(commandMessage.headers[CommandMessage.SelectorHeader] as string);
                                }
                                if (commandMessage.headers.ContainsKey(AsyncMessage.SubtopicHeader))
                                {
                                    subtopic = new Subtopic(commandMessage.headers[AsyncMessage.SubtopicHeader] as string);
                                }
                            }
                            IClient client = FluorineContext.Current.Client;
                            client.Renew();
                            messageClient = messageDestination.SubscriptionManager.AddSubscriber(clientId, endpointId, subtopic, selector);
                            if (acknowledgeMessage == null)
                                acknowledgeMessage = new AcknowledgeMessage();
                            acknowledgeMessage.clientId = clientId;
                        }
                        else
                        {
                            acknowledgeMessage = new AcknowledgeMessage();
                            acknowledgeMessage.clientId = clientId;
                        }
                        return acknowledgeMessage;
                    case CommandMessage.UnsubscribeOperation:
                        if (log.IsDebugEnabled)
                            log.Debug(__Res.GetString(__Res.MessageServiceUnsubscribe, messageDestination.Id, clientId));

                        if (messageDestination.ServiceAdapter != null && messageDestination.ServiceAdapter.HandlesSubscriptions)
                        {
                            try
                            {
                                acknowledgeMessage = messageDestination.ServiceAdapter.Manage(commandMessage) as AcknowledgeMessage;
                            }
                            catch (MessageException me)
                            {
                                acknowledgeMessage = me.GetErrorMessage();
                            }
                            catch (Exception ex)
                            {
                                //Guard against service adapter failure
                                acknowledgeMessage = ErrorMessage.GetErrorMessage(commandMessage, ex);
                                if (log.IsErrorEnabled)
                                    log.Error(__Res.GetString(__Res.ServiceAdapter_ManageFail, this.id, messageDestination.Id, commandMessage), ex);
                            }
                        }
                        if (messageClient != null)
                            messageDestination.SubscriptionManager.RemoveSubscriber(messageClient);
                        if (acknowledgeMessage == null)
                            acknowledgeMessage = new AcknowledgeMessage();
                        return acknowledgeMessage;
                    case CommandMessage.PollOperation:
                        {
                            if (messageClient == null)
                            {
                                ServiceException serviceException = new ServiceException(string.Format("MessageClient is not subscribed to {0}", commandMessage.destination));
                                serviceException.FaultCode = "Server.Processing.NotSubscribed";
                                throw serviceException;
                            }
                            IClient client = FluorineContext.Current.Client;
                            client.Renew();
                            try
                            {
                                acknowledgeMessage = messageDestination.ServiceAdapter.Manage(commandMessage) as AcknowledgeMessage;
                            }
                            catch (MessageException me)
                            {
                                acknowledgeMessage = me.GetErrorMessage();
                            }
                            catch (Exception ex)
                            {
                                //Guard against service adapter failure
                                acknowledgeMessage = ErrorMessage.GetErrorMessage(commandMessage, ex);
                                if (log.IsErrorEnabled)
                                    log.Error(__Res.GetString(__Res.ServiceAdapter_ManageFail, this.id, messageDestination.Id, commandMessage), ex);
                            }
                            if (acknowledgeMessage == null)
                                acknowledgeMessage = new AcknowledgeMessage();
                            return acknowledgeMessage;
                        }
                    case CommandMessage.ClientPingOperation:
                        if (messageDestination.ServiceAdapter != null && messageDestination.ServiceAdapter.HandlesSubscriptions)
                        {
                            try
                            {
                                messageDestination.ServiceAdapter.Manage(commandMessage);
                            }
                            catch (MessageException)
                            {
                                return false;
                            }
                            catch (Exception ex)
                            {
                                //Guard against service adapter failure
                                if (log.IsErrorEnabled)
                                    log.Error(__Res.GetString(__Res.ServiceAdapter_ManageFail, this.id, messageDestination.Id, commandMessage), ex);
                                return false;
                            }
                        }
                        return true;
                    default:
                        if (log.IsDebugEnabled)
                            log.Debug(__Res.GetString(__Res.MessageServiceUnknown, commandMessage.operation, messageDestination.Id));
                        try
                        {
                            acknowledgeMessage = messageDestination.ServiceAdapter.Manage(commandMessage) as AcknowledgeMessage;
                        }
                        catch (MessageException me)
                        {
                            acknowledgeMessage = me.GetErrorMessage();
                        }
                        catch (Exception ex)
                        {
                            //Guard against service adapter failure
                            acknowledgeMessage = ErrorMessage.GetErrorMessage(commandMessage, ex);
                            if (log.IsErrorEnabled)
                                log.Error(__Res.GetString(__Res.ServiceAdapter_ManageFail, this.id, messageDestination.Id, commandMessage), ex);
                        }
                        if (acknowledgeMessage == null)
                            acknowledgeMessage = new AcknowledgeMessage();
                        return acknowledgeMessage;
                }
			}
			else
			{
				if (log.IsDebugEnabled)
					log.Debug(__Res.GetString(__Res.MessageServiceRoute, messageDestination.Id, message.clientId));

                if (FluorineContext.Current != null && FluorineContext.Current.Client != null)//Not set when user code initiates push
                {
                    IClient client = FluorineContext.Current.Client;
                    client.Renew();
                }
                object result = messageDestination.ServiceAdapter.Invoke(message);
				return result;
			}
		}
		public override object ServiceMessage(IMessage message)
		{
			IMessage responseMessage = null;
			CommandMessage commandMessage = message as CommandMessage;
			if( commandMessage != null )
			{
				switch(commandMessage.operation)
				{
					case CommandMessage.LoginOperation:
						IPrincipal principal = null;
						try
						{
                            principal = Authenticate(message);
						}
                        catch (SecurityException)
                        {
                            throw;
                        }
                        catch (UnauthorizedAccessException)
                        {
                            throw;
                        }
                        catch (Exception exception)
						{
                            string msg = __Res.GetString(__Res.Security_AuthenticationFailed);
							if( log.IsErrorEnabled )
                                log.Error(msg, exception);
                            throw new SecurityException(msg, exception);
						}
						if( principal == null )
						{
                            string msg = __Res.GetString(__Res.Security_AuthenticationFailed);
                            throw new SecurityException(msg);
						}
						responseMessage = new AcknowledgeMessage();
						responseMessage.body = "success";
						break;
					case CommandMessage.LogoutOperation:
						//TODO: Logs the user out of the destination. Logging out of a destination applies to everything connected using the same ChannelSet as specified in the server configuration.
						//For example, if you're connected over the my-rtmp channel and you log out using one of your RPC components, anything that was 
						//connected over the same ChannelSet is logged out.
                        _messageBroker.LoginManager.Logout();
						responseMessage = new AcknowledgeMessage();
						responseMessage.body = "success";
						break;
				}
			}
			return responseMessage;
		}
        object ProcessMessage(AMFMessage amfMessage)
        {
            // Apply AMF-based operation selector
            /*
            Dictionary<string, string> operationNameDictionary = new Dictionary<string, string>();
            foreach (OperationDescription operation in _endpoint.Contract.Operations)
            {
                try
                {
                    operationNameDictionary.Add(operation.Name.ToLower(), operation.Name);
                }
                catch (ArgumentException)
                {
                    throw new Exception(String.Format("The specified contract cannot be used with case insensitive URI dispatch because there is more than one operation named {0}", operation.Name));
                }
            }
            */

            //SessionMode, CallbackContract, ProtectionLevel

            AMFMessage output = new AMFMessage(amfMessage.Version);
            for (int i = 0; i < amfMessage.BodyCount; i++)
            {
                AMFBody amfBody = amfMessage.GetBodyAt(i);
                object content = amfBody.Content;
                if (content is IList)
                    content = (content as IList)[0];
                IMessage message = content as IMessage;
                if (message != null)
                {
                    //WCF should not assign client id for Flex...
                    if (message.clientId == null)
                        message.clientId = Guid.NewGuid().ToString("D");

                    //IMessage resultMessage = _endpoint.ServiceMessage(message);
                    IMessage responseMessage = null;
                    CommandMessage commandMessage = message as CommandMessage;
                    if (commandMessage != null && commandMessage.operation == CommandMessage.ClientPingOperation)
                    {
                        responseMessage = new AcknowledgeMessage();
                        responseMessage.body = true;
                    }
                    else
                    {
                        RemotingMessage remotingMessage = message as RemotingMessage;
                        string operation = remotingMessage.operation;
                        //TODO: you could use an alias for a contract to expose a different name to the clients in the metadata using the Name property of the ServiceContract attribute
                        string source = remotingMessage.source;
                        Type serviceType = TypeHelper.Locate(source);
                        Type contractInterface = serviceType.GetInterface(_endpoint.Contract.ContractType.FullName);
                        //WCF also lets you apply the ServiceContract attribute directly on the service class. Avoid using it.
                        //ServiceContractAttribute serviceContractAttribute = ReflectionUtils.GetAttribute(typeof(ServiceContractAttribute), type, true) as ServiceContractAttribute;
                        if (contractInterface != null)
                        {
                            object instance = Activator.CreateInstance(serviceType);
                            IList parameterList = remotingMessage.body as IList;
                            MethodInfo mi = MethodHandler.GetMethod(contractInterface, operation, parameterList, false, false);
                            //MethodInfo mi = MethodHandler.GetMethod(serviceType, operation, parameterList, false, false);
                            if (mi != null)
                            {
                                //TODO OperationContract attribute to alias it to a different publicly exposed name
                                OperationContractAttribute operationContractAttribute = ReflectionUtils.GetAttribute(typeof(OperationContractAttribute), mi, true) as OperationContractAttribute;
                                if (operationContractAttribute != null)
                                {
                                    //mi = MethodHandler.GetMethod(serviceType, operation, parameterList, false, false);
                                    ParameterInfo[] parameterInfos = mi.GetParameters();
                                    object[] args = new object[parameterInfos.Length];
                                    parameterList.CopyTo(args, 0);
                                    TypeHelper.NarrowValues(args, parameterInfos);
                                    object result = mi.Invoke(instance, args);
                                    if (!(result is IMessage))
                                    {
                                        responseMessage = new AcknowledgeMessage();
                                        responseMessage.body = result;
                                    }
                                    else
                                        responseMessage = result as IMessage;
                                }
                                else
                                    responseMessage = ErrorMessage.GetErrorMessage(remotingMessage, new SecurityException("Method in not part of an service contract"));
                            }
                            else
                                responseMessage = ErrorMessage.GetErrorMessage(remotingMessage, new SecurityException("Method in not part of an service contract"));
                        }
                        else
                            responseMessage = ErrorMessage.GetErrorMessage(remotingMessage, new SecurityException(String.Format("The specified contract {0} cannot be used with the source named {1} and operation named {2}", _endpoint.Contract.ContractType.Name, source, operation)));
                    }

                    if (responseMessage is AsyncMessage)
                    {
                        ((AsyncMessage)responseMessage).correlationId = message.messageId;
                    }
                    responseMessage.destination = message.destination;
                    responseMessage.clientId = message.clientId;

                    ResponseBody responseBody = new ResponseBody(amfBody, responseMessage);
                    output.AddBody(responseBody);
                }
            }
            return output;
        }
Beispiel #12
0
        public override IMessage ServiceMessage(IMessage message)
        {
            if (FluorineContext.Current.Client != null)
                FluorineContext.Current.Client.Renew();

            if (message is CommandMessage)
            {
                CommandMessage commandMessage = message as CommandMessage;
                switch (commandMessage.operation)
                {
                    case CommandMessage.PollOperation:
                        {
                            if (log.IsDebugEnabled)
                                log.Debug(__Res.GetString(__Res.Endpoint_HandleMessage, this.Id, message.ToString()));

                            if (FluorineContext.Current.Client != null)
                                FluorineContext.Current.Client.Renew();

                            //IMessage[] messages = null;
                            IList messages = null;
                            _waitingPollRequests.Increment();
                            int waitIntervalMillis = this.ChannelDefinition.Properties.WaitIntervalMillis != -1 ? this.ChannelDefinition.Properties.WaitIntervalMillis : 60000;// int.MaxValue;

                            if (commandMessage.HeaderExists(CommandMessage.FluorineSuppressPollWaitHeader))
                                waitIntervalMillis = 0;
                            //If async handling was not set long polling is not supported
                            if (!FluorineConfiguration.Instance.FluorineSettings.Runtime.AsyncHandler)
                                waitIntervalMillis = 0;
                            if (this.ChannelDefinition.Properties.MaxWaitingPollRequests <= 0 || _waitingPollRequests.Value >= this.ChannelDefinition.Properties.MaxWaitingPollRequests)
                                waitIntervalMillis = 0;

                            if (message.destination != null && message.destination != string.Empty)
                            {
                                string clientId = commandMessage.clientId as string;
                                MessageDestination messageDestination = this.GetMessageBroker().GetDestination(message.destination) as MessageDestination;
                                MessageClient client = messageDestination.SubscriptionManager.GetSubscriber(clientId);
                                client.Renew();
                                //messages = client.GetPendingMessages();
                            }
                            else
                            {
                                //if (FluorineContext.Current.Client != null)
                                //    messages = FluorineContext.Current.Client.GetPendingMessages(waitIntervalMillis);
                            }

                            if (FluorineContext.Current.Client != null)
                            {
                                IEndpointPushHandler handler = FluorineContext.Current.Client.GetEndpointPushHandler(this.Id);
                                if (handler != null)
                                    messages = handler.GetPendingMessages();
                                if (messages == null)
                                {
                                    lock (handler.SyncRoot)
                                    {
                                        Monitor.Wait(handler.SyncRoot, waitIntervalMillis);
                                    }
                                    messages = handler.GetPendingMessages();
                                }
                            }

                            _waitingPollRequests.Decrement();
                            IMessage response = null;
                            if (messages == null || messages.Count == 0)
                                response = new AcknowledgeMessage();
                            else
                            {
                                CommandMessage resultMessage = new CommandMessage();
                                resultMessage.operation = CommandMessage.ClientSyncOperation;
                                resultMessage.body = messages;
                                response = resultMessage;
                            }
                            if (log.IsDebugEnabled)
                                log.Debug(__Res.GetString(__Res.Endpoint_Response, this.Id, response.ToString()));
                            return response;

                        }
                    case CommandMessage.SubscribeOperation:
                        {
                            /*
                            if (FluorineContext.Current.Client == null)
                                FluorineContext.Current.SetCurrentClient(this.GetMessageBroker().ClientRegistry.GetClient(message));
                            RemotingConnection remotingConnection = null;
                            foreach (IConnection connection in FluorineContext.Current.Client.Connections)
                            {
                                if (connection is RemotingConnection)
                                {
                                    remotingConnection = connection as RemotingConnection;
                                    break;
                                }
                            }
                            if (remotingConnection == null)
                            {
                                remotingConnection = new RemotingConnection(this, null, FluorineContext.Current.Client.Id, null);
                                FluorineContext.Current.Client.Renew(this.ClientLeaseTime);
                                remotingConnection.Initialize(FluorineContext.Current.Client);
                            }
                            FluorineWebContext webContext = FluorineContext.Current as FluorineWebContext;
                            webContext.SetConnection(remotingConnection);
                            */

                            if (this.ChannelDefinition.Properties.IsPollingEnabled)
                            {
                                //Create and forget, client will close the notifier
                                IEndpointPushHandler handler = FluorineContext.Current.Client.GetEndpointPushHandler(this.Id);
                                if( handler == null )
                                    handler = new EndpointPushNotifier(this, FluorineContext.Current.Client);
                                /*
                                lock (_endpointPushHandlers.SyncRoot)
                                {
                                    _endpointPushHandlers.Add(notifier.Id, notifier);
                                }
                                */
                            }
                        }
                        break;
                    case CommandMessage.DisconnectOperation:
                        {
                            if (log.IsDebugEnabled)
                                log.Debug(__Res.GetString(__Res.Endpoint_HandleMessage, this.Id, message.ToString()));

                            if (FluorineContext.Current.Client != null && FluorineContext.Current.Client.IsValid)
                            {
                                IList messageClients = FluorineContext.Current.Client.MessageClients;
                                if (messageClients != null)
                                {
                                    foreach (MessageClient messageClient in messageClients)
                                    {
                                        messageClient.Invalidate();
                                    }
                                }
                                FluorineContext.Current.Client.Invalidate();
                            }
                            if (FluorineContext.Current.Session != null)
                            {
                                FluorineContext.Current.Session.Invalidate();
                            }
                            //Disconnect command is received from a client channel.
                            //The response returned by this method is not guaranteed to get to the client, which is free to terminate its physical connection at any point.
                            IMessage response = new AcknowledgeMessage();

                            if (log.IsDebugEnabled)
                                log.Debug(__Res.GetString(__Res.Endpoint_Response, this.Id, response.ToString()));
                            return response;
                        }
                }
            }
            return base.ServiceMessage(message);
        }
 protected override MessageBase CopyImpl(MessageBase clone)
 {
     // Instantiate the clone, if a derived type hasn't already.
     if (clone == null) clone = new AcknowledgeMessage();
     return base.CopyImpl(clone);
 }