/// <summary>
 /// Sends a message to another component
 /// </summary>
 /// <param name="address">The destination address of the message</param>
 /// <param name="message">The message to send</param>
 public void SendMessage(Message message)
 {
     // Enqueue the message for processing by Dispatch threads
     messages.Enqueue(message);
 }
 /// <summary>
 /// Attempts to route the specified message
 /// </summary>
 /// <remarks>The server should check if the target of this message is a remote component and 
 /// if not, attempt to discover it. Any exception thrown by this message will be used to 
 /// return an error message to the sender</remarks>
 /// <param name="m">The message to route</param>
 public void RouteMessage(Message m)
 {
     RemoteComponent rc = remoteComponents[m.Target];
     string scheme = rc.Address.Substring(0, rc.Address.IndexOf(':'));
     if (!protocols.ContainsKey(scheme))
     {
         string msg = "Invalid Scheme (" + scheme + "), could not find matching protocol handler";
         log.Error("[RouteMessage] " + msg);
         throw new InvalidOperationException(msg);
     }
     IProtocol protocol = protocols[scheme];
     protocol.Send(m, rc.Address);
     log.Info("[RouteMessage] Message for component \"" + m.Target + "\" routed to: " + rc.Address);
 }
 /// <summary>
 /// Dispatches the specified control message
 /// </summary>
 /// <param name="m">A control message to dispatch</param>
 public object DispatchControl(Message m)
 {
     object r = null;
     switch (m.Action.ToUpper())
     {
         case "ADDRECIEVER":
             AddReciever();
             log.Info("[Dispatch] AddReciever");
             return null;
         case "REMOVERECIEVER":
             RemoveReciever();
             log.Info("[Dispatch] RemoveReciever");
             return null;
         case "ADDDISPATCHER":
             AddDispatcher();
             log.Info("[Dispatch] AddDispatcher");
             return null;
         case "REMOVEDISPATCHER":
             RemoveDispatcher();
             log.Info("[Dispatch] RemoveDispatcher");
             return null;
         case "GETRTHREADCOUNT":
             r = (object)GetRThreadCount();
             log.Info("[Dispatch] GetRThreadCount");
             return r;
         case "GETDTHREADCOUNT":
             r = (object)GetDThreadCount();
             log.Info("[Dispatch] GetDThreadCount");
             return r;
         case "REGISTERCOMPONENT":
             RegisterComponent((RemoteComponent)m.Arguments[0]);
             log.Info("[Dispatch] RegisterComponent");
             return null;
         case "UNREGISTERCOMPONENT":
             UnregisterComponent((string)m.Arguments[0]);
             log.Info("[Dispatch] UnregisterComponent");
             return null;
         case "RESOLVECONTRACT":
             r = (object)ResolveContract((string)m.Arguments[0]);
             log.Info("[Dispatch] ResolveContract");
             return r;
         case "GETNAME":
             log.Info("[Dispatch] GetName");
             return name;
         case "SENDMESSAGE":
             SendMessage((Message)m.Arguments[0]);
             log.Info("[Dispatch] SendMessage");
             return null;
     }
     return null;
 }
        private void RecieveLoop()
        {
            // Start at 0
            int i = 0;

            if (protocols.Count == 0)
                return;

            Monitor.Enter(locker);
            while (!stop)
            {
                // Setup variables
                Message m = null;
                IProtocol p = null;

                // Lock the protocol list and get a protocol
                Monitor.Enter(protocols);
                p = protocols[i];
                Monitor.Exit(protocols);

                // Recieve a Message
                m = p.Recieve();

                if (m != null)
                {
                    // TODO: Use log4net Nested Diagnostic Context to log messages that occur during the processing of a message

                    // If the target is local, enqueue the message
                    if (server.Manager.Contains(m.Target))
                        server.Messages.Enqueue(m);
                    // If the target is remote, or we can discover it, route the message
                    else if ((server.RemoteComponents.ContainsKey(m.Target)) || (server.Discover(m.Target)))
                        server.SendMessage(m);
                    // Otherwise, if we don't know the component, we can't recieve the message
                    else
                    {
                        // Log the error
                        string message = "Unable to locate target component (" + m.Target + ") for this message";
                        log.Error(message);
                        // If we do know how to reach the sender (i.e. its local or known remote)
                        if ((server.Manager.Contains(m.Sender)) || (server.RemoteComponents.ContainsKey(m.Sender)))
                        {
                            // Create an exception message and send it with the same RefId but with our server name as the sender
                            Message err = new Message("ERR", m.Sender, "SRV:" + server.Name);
                            err.Arguments.Add(new NullReferenceException(message));
                            err.Type = MessageTypeEnum.Exception;
                            err.RefId = m.RefId;
                            server.SendMessage(err);
                        }
                        // Don't log that we recieved the message
                        continue;
                    }
                    log.Info("Message Recieved by " + p.Scheme + " protocol");
                }

                // If we are on the last protocol, go back to 0
                if (i == (protocols.Count - 1))
                    i = 0;
                // Otherwise, move on to the next protocol
                else
                    i++;

                // Let others modify the stop flag
                Monitor.Wait(locker);
            }
        }
 /// <summary>
 /// Adds the specified message to the queue
 /// </summary>
 /// <param name="msg">The message to add to the queue</param>
 public void Enqueue(Message msg)
 {
     // Add message to appropriate sub-queue
     switch (msg.Priority)
     {
         case MessagePriorityEnum.Low:
             lock(locker)
                 lowQueue.Enqueue(msg);
             return;
         case MessagePriorityEnum.Normal:
             lock(locker)
                 midQueue.Enqueue(msg);
             return;
         case MessagePriorityEnum.High:
             lock(locker)
                 highQueue.Enqueue(msg);
             return;
     }
 }
 /// <summary>
 /// Sends a message to another component
 /// </summary>
 /// <param name="address">The destination address of the message</param>
 /// <param name="message">The message to send</param>
 public void SendMessage(Message message)
 {
     if (manager.Contains(message.Target))
     {
         messages.Enqueue(message);
     }
     else if (remoteComponents.ContainsKey(message.Target))
     {
         RemoteComponent rc = remoteComponents[message.Target];
         string scheme = rc.Address.Substring(0, rc.Address.IndexOf(':'));
         if (!protocols.ContainsKey(scheme))
         {
             string msg = "Invalid Scheme (" + scheme + "), could not find matching protocol handler";
             log.Error("[SendMessage] " + msg);
             throw new InvalidDataException(msg);
         }
         IProtocol protocol = protocols[scheme];
         protocol.Send(message, rc.Address);
         log.Info("[SendMessage] Message for component \"" + message.Target + "\" routed to: " + rc.Address);
     }
     else
     {
         log.Error("[SendMessage] Unable to send message to component: " + message.Target + ", component is not registered or attached");
     }
 }