private IDictionary Invoke(IDictionary request) { ValidationUtils.ArgumentNotNull(request, "request"); object error = null; object result = null; ISession session = this.MessageBroker.SessionManager.GetHttpSession(HttpContext.Current); FluorineContext.Current.SetSession(session); //Context initialized, notify listeners. if (session != null && session.IsNew) session.NotifyCreated(); // Get the ID of the request. object id = request["id"]; string credentials = request["credentials"] as string; if (!StringUtils.IsNullOrEmpty(credentials)) { try { CommandMessage commandMessage = new CommandMessage(CommandMessage.LoginOperation); commandMessage.body = credentials; IMessage message = this.MessageBroker.RouteMessage(commandMessage); if (message is ErrorMessage) { error = FromException(message as ErrorMessage); return CreateResponse(id, result, error); } } catch (Exception ex) { error = FromException(ex); return CreateResponse(id, result, error); } } // If the ID is not there or was not set then this is a notification // request from the client that does not expect any response. Right // now, we don't support this. bool isNotification = JavaScriptConvert.IsNull(id); if (isNotification) throw new NotSupportedException("Notification are not yet supported."); log.Debug(string.Format("Received request with the ID {0}.", id.ToString())); // Get the method name and arguments. string methodName = StringUtils.MaskNullString((string)request["method"]); if (methodName.Length == 0) throw new JsonRpcException("No method name supplied for this request."); if (methodName == "clearCredentials") { try { CommandMessage commandMessage = new CommandMessage(CommandMessage.LogoutOperation); IMessage message = this.MessageBroker.RouteMessage(commandMessage); if (message is ErrorMessage) { error = FromException(message as ErrorMessage); return CreateResponse(id, result, error); } else return CreateResponse(id, message.body, null); } catch (Exception ex) { error = FromException(ex); return CreateResponse(id, result, error); } } //Info("Invoking method {1} on service {0}.", ServiceName, methodName); // Invoke the method on the service and handle errors. try { RemotingMessage message = new RemotingMessage(); message.destination = this.Request.QueryString["destination"] as string; message.source = this.Request.QueryString["source"] as string; message.operation = methodName; object argsObject = request["params"]; object[] args = (argsObject as JavaScriptArray).ToArray(); message.body = args; IMessage response = this.MessageBroker.RouteMessage(message); if (response is ErrorMessage) error = FromException(response as ErrorMessage); else result = response.body; /* Method method = serviceClass.GetMethodByName(methodName); object[] args; string[] names = null; object argsObject = request["params"]; IDictionary argByName = argsObject as IDictionary; if (argByName != null) { names = new string[argByName.Count]; argByName.Keys.CopyTo(names, 0); args = new object[argByName.Count]; argByName.Values.CopyTo(args, 0); } else { args = (argsObject as JavaScriptArray).ToArray(); } result = method.Invoke(instance, names, args); */ } catch (Exception ex) { log.Error(ex.Message, ex); throw; } // Setup and return the response object. return CreateResponse(id, result, error); }
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); }
/// <summary> /// Accept a command from the adapter's service (subscribe, unsubscribe and ping operations). /// </summary> /// <param name="commandMessage"></param> /// <returns></returns> public virtual object Manage(CommandMessage commandMessage) { return new AcknowledgeMessage(); }
/// <summary> /// Invalidates the MessageClient. /// </summary> /// <param name="notifyClient">Push a subscription invalidation message to the client.</param> public void Invalidate(bool notifyClient) { lock (this.SyncRoot) { if (!IsValid || IsInvalidating) return; // Already shutting down. SetIsInvalidating(true); _messageDestination.SubscriptionManager.CancelTimeout(this); } // Build a subscription invalidation message and push to the client if it is still valid. if (notifyClient && _client != null && _client.IsValid) { CommandMessage commandMessage = new CommandMessage(); commandMessage.destination = _messageDestination.Id; commandMessage.clientId = _clientId; commandMessage.operation = CommandMessage.SessionInvalidateOperation; MessageService messageService = _messageDestination.Service as MessageService; object[] subscribers = new object[] { commandMessage.clientId }; try { messageService.PushMessageToClients(subscribers, commandMessage); } catch (MessageException) { } } // Notify listeners that we're being invalidated. if (_messageClientDestroyedListeners != null && _messageClientDestroyedListeners.Count != 0) { foreach (IMessageClientListener listener in _messageClientDestroyedListeners.Keys) { listener.MessageClientDestroyed(this); } _messageClientDestroyedListeners.Clear(); } // Generate unsubscribe messages for all of the MessageClient's subscriptions and // route them to the destination this MessageClient is subscribed to. // Some adapters manage their own subscription state. ArrayList unsubscribeMessages = new ArrayList(); lock (this.SyncRoot) { foreach (SubscriptionInfo subscription in _subscriptions) { CommandMessage unsubscribeMessage = new CommandMessage(); unsubscribeMessage.destination = _messageDestination.Id; unsubscribeMessage.clientId = _clientId; unsubscribeMessage.operation = CommandMessage.UnsubscribeOperation; unsubscribeMessage.SetHeader(CommandMessage.SessionInvalidatedHeader, true); unsubscribeMessage.SetHeader(CommandMessage.SelectorHeader, subscription.Selector); unsubscribeMessage.SetHeader(AsyncMessage.SubtopicHeader, subscription.Subtopic); unsubscribeMessages.Add(unsubscribeMessage); } } // Release the lock and send the unsub messages. foreach (CommandMessage commandMessage in unsubscribeMessages) { try { _messageDestination.Service.ServiceMessage(commandMessage); } catch (MessageException me) { if (log.IsDebugEnabled) log.Debug("MessageClient: " + _clientId + " issued an unsubscribe message during invalidation that was not processed but will continue with invalidation.", me); } } //TODO RemoveSubscription(this.Selector, this.Subtopic); lock (this.SyncRoot) { // If we didn't clean up all subscriptions log an error and continue with shutdown. int remainingSubscriptionCount = _subscriptions.Count; if (remainingSubscriptionCount > 0 && log.IsErrorEnabled) log.Error("MessageClient: " + _clientId + " failed to remove " + remainingSubscriptionCount + " subscription(s) during invalidation"); } _messageDestination.SubscriptionManager.RemoveSubscriber(this); lock (this.SyncRoot) { SetIsValid(false); SetIsInvalidating(false); } }
protected override MessageBase CopyImpl(MessageBase clone) { // Instantiate the clone, if a derived type hasn't already. if (clone == null) clone = new CommandMessage(); // Allow base type(s) to copy their state into the new clone. base.CopyImpl(clone); // Copy our state into the clone. ((CommandMessage)clone)._messageRefType = _messageRefType; ((CommandMessage)clone)._operation = _operation; return clone; }
public override object Manage(CommandMessage commandMessage) { object result = base.Manage(commandMessage); switch (commandMessage.operation) { case CommandMessage.SubscribeOperation: lock (SyncRoot) { bool enableReceive = _consumers.Count == 0; _consumers[commandMessage.clientId] = null; if (enableReceive) EnableReceiving(true); } break; case CommandMessage.UnsubscribeOperation: lock (SyncRoot) { if (_consumers.Contains(commandMessage.clientId)) { _consumers.Remove(commandMessage.clientId); if (_consumers.Count == 0) EnableReceiving(false); } } break; } return result; }
/// <summary> /// Closes the handler. /// </summary> public void Close() { lock (this.SyncRoot) { if (IsClosed || IsClosing) return; SetIsClosing(true); } if (_session != null) _session.RemoveSessionDestroyedListener(this); _flexClient.UnregisterEndpointPushHandler(this, _endpoint.Id); #if !(NET_1_1) List<IMessage> list = new List<IMessage>(1); #else ArrayList list = new ArrayList(1); #endif CommandMessage disconnect = new CommandMessage(CommandMessage.DisconnectOperation); PushMessage(disconnect); // Invalidate associated subscriptions. This doesn't attempt to notify the client. foreach (MessageClient messageClient in _messageClients) messageClient.Invalidate(); lock (this.SyncRoot) { SetIsClosed(true); SetIsClosing(false); } lock (this.SyncRoot) { Monitor.PulseAll(this.SyncRoot); } }
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; } }