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; }
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; } }
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; }
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; }
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; } } }
/// <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; }
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); }