コード例 #1
0
ファイル: FakeServer.cs プロジェクト: kouweizhong/Ella
        public void SubscribeResponseMessageEvent(int msgId)
        {
            RemoteSubscriptionHandle h = new RemoteSubscriptionHandle();

            //SubscriptionReference has to be equal the msgID of the SubscribeMsg
            h.SubscriptionReference = msgId;
            h.PublisherId           = 234;
            h.SubscriberNodeID      = EllaConfiguration.Instance.NodeId;
            h.PublisherNodeID       = EllaConfiguration.Instance.NodeId + 1;

            List <RemoteSubscriptionHandle> handles = new List <RemoteSubscriptionHandle>();

            handles.Add(h);

            byte[] handledata = Serializer.Serialize(handles);
            byte[] reply      = new byte[handledata.Length + 4];
            byte[] idbytes    = BitConverter.GetBytes(h.SubscriptionReference);

            Array.Copy(idbytes, reply, idbytes.Length);
            Array.Copy(handledata, 0, reply, idbytes.Length, handledata.Length);
            Message m = new Message {
                Type = MessageType.SubscribeResponse, Data = reply, Sender = h.PublisherNodeID
            };

            NewMessage(this, new MessageEventArgs(m));
        }
コード例 #2
0
ファイル: MessageProcessor.cs プロジェクト: kouweizhong/Ella
 private static bool CompareSubscriptionHandles(RemoteSubscriptionHandle handle, RemoteSubscriptionHandle h)
 {
     return
         (handle.EventID == h.EventID &&
          handle.PublisherNodeID == h.PublisherNodeID &&
          handle.PublisherId == h.PublisherId &&
          handle.SubscriberNodeID == h.SubscriberNodeID);
 }
コード例 #3
0
        public bool SendMessage(ApplicationMessage message, RemoteSubscriptionHandle remoteSubscriptionHandle, bool isReply = false)
        {
            countMsg++;

            if (!MessageTypes.ContainsKey(message.MessageType))
            {
                MessageTypes.Add(message.MessageType, 1);
            }
            else
            {
                MessageTypes[message.MessageType] += 1;
            }

            return(true);
        }
コード例 #4
0
        public bool SendMessage(ApplicationMessage message, RemoteSubscriptionHandle remoteSubscriptionHandle, bool isReply = false)
        {
            Message m = new Message {
                Data = Serializer.Serialize(message), Type = isReply ? MessageType.ApplicationMessageResponse : MessageType.ApplicationMessage
            };
            var key = remoteSubscriptionHandle.PublisherNodeID == EllaConfiguration.Instance.NodeId ? remoteSubscriptionHandle.SubscriberNodeID : remoteSubscriptionHandle.PublisherNodeID;

            if (!_messageProcessor.RemoteHosts.ContainsKey(key))
            {
                return(false);
            }
            IPEndPoint ep = (IPEndPoint)_messageProcessor.RemoteHosts[key];

            if (ep != null)
            {
                SenderBase.SendAsync(m, ep);
                return(true);
            }
            return(false);
        }
コード例 #5
0
ファイル: MessageProcessor.cs プロジェクト: kouweizhong/Ella
        /// <summary>
        /// Processes the publish.
        /// </summary>
        /// <param name="e">The <see cref="MessageEventArgs"/> instance containing the event data.</param>
        private void ProcessPublish(MessageEventArgs e)
        {
            /*
             * Remote publisher is identified by
             * Remote node ID (contained in the message object)
             * Remote publisher ID
             * Remote publisher-event ID
             * The message reference (message ID used for the subscribe message)
             * SubscriptionRequest node ID
             * Assume shorts for all
             *
             */
            short publisherID = BitConverter.ToInt16(e.Message.Data, 0);
            short eventID     = BitConverter.ToInt16(e.Message.Data, 2);
            RemoteSubscriptionHandle handle = new RemoteSubscriptionHandle
            {
                EventID          = eventID,
                PublisherId      = publisherID,
                PublisherNodeID  = e.Message.Sender,
                SubscriberNodeID = EllaConfiguration.Instance.NodeId
            };

            byte[] data = new byte[e.Message.Data.Length - 4];
            Buffer.BlockCopy(e.Message.Data, 4, data, 0, data.Length);
            var subscriptions = EllaModel.Instance.FilterSubscriptions(s =>
            {
                var h = (s.Handle as RemoteSubscriptionHandle);

                return(h != null && CompareSubscriptionHandles(handle, h));
            });
            var subs = subscriptions as SubscriptionBase[] ?? subscriptions.ToArray();

            _log.DebugFormat("Found {0} subscriptions for handle {1}", subs.Length, handle);
            foreach (var sub in subs)
            {
                (sub.Event.Publisher as Stub).NewMessage(data);
            }
        }
コード例 #6
0
        /// <summary>
        /// Performs the system-internal unsubscribe consisting of canelling all matching subscription according to <paramref name="selector" /> and also finding and cancelling remote subscriptions
        /// </summary>
        /// <param name="selector">The selector.</param>
        /// <param name="performRemoteUnsubscribe">if set to <c>true</c> [perform remote unsubscribe].</param>
        internal static void PerformUnsubscribe(Predicate <SubscriptionBase> selector, bool performRemoteUnsubscribe = true)
        {
            var remoteSubscriptions = EllaModel.Instance.FilterSubscriptions(selector).Where(s => s.Handle is RemoteSubscriptionHandle);

            foreach (var remoteSubscription in remoteSubscriptions)
            {
                RemoteSubscriptionHandle handle = remoteSubscription.Handle as RemoteSubscriptionHandle;
                if (handle.PublisherNodeID == EllaConfiguration.Instance.NodeId)
                {
                    continue;
                }
                _log.DebugFormat("Cancelling remote subscription to {0}", handle);

                if (performRemoteUnsubscribe)
                {
                    Networking.Unsubscribe(handle.SubscriptionReference, handle.PublisherNodeID);
                }
                Stop.Publisher(remoteSubscription.Event.Publisher);
            }
            int removedSubscriptions = EllaModel.Instance.RemoveSubscriptions(selector);

            _log.DebugFormat("{0} local subscriptions have been removed.", removedSubscriptions);
        }
コード例 #7
0
        /// <summary>
        /// Performs a subscription to a remote publisher for a local subscriber<br />#
        /// In this method, the remote subscription is completed
        /// </summary>
        internal static void SubscribeToRemotePublisher <T>(RemoteSubscriptionHandle handle, object subscriberInstance, Action <T, SubscriptionHandle> newDataCallBack, DataModifyPolicy policy, Func <T, bool> evaluateTemplateObject, Action <Type, SubscriptionHandle> subscriptionCallback)
        {
            _log.DebugFormat("Completing subscription to remote publisher {0} on node {1},handle: {2}, type: {3}",
                             handle.PublisherId, handle.PublisherNodeID, handle, typeof(T).Name);
            //TODO template object

            //Create a stub
            Stub <T> s = new Stub <T> {
                DataType = typeof(T), Handle = handle
            };

            if (
                (EllaModel.Instance.GetActivePublishers().Where(p => p.Instance is Stub && (p.Instance as Stub).Handle == handle)).Any())
            {
                _log.DebugFormat("Avoiding double subscription for handle {0}. Anready an active stub available.", handle);
                return;
            }
            var publishesAttribute = (PublishesAttribute)s.GetType().GetCustomAttributes(typeof(PublishesAttribute), false).First();

            if (handle is MulticastRemoteSubscriptionhandle)
            {
                _log.DebugFormat("{0} is potential multicast subscription, opening multicast port", handle);
                MulticastRemoteSubscriptionhandle mh = handle as MulticastRemoteSubscriptionhandle;
                Networking.ConnectToMulticast(mh.IpAddress, mh.Port);
                RemoteSubscriptionHandle h = new RemoteSubscriptionHandle()
                {
                    PublisherNodeID       = handle.PublisherNodeID,
                    PublisherId           = handle.PublisherId,
                    SubscriptionReference = handle.SubscriptionReference,
                    EventID          = handle.EventID,
                    SubscriberNodeID = handle.SubscriberNodeID
                };
                s.Handle = h;
            }
            Start.Publisher(s);
            Event ev = new Event
            {
                Publisher   = s,
                EventDetail = publishesAttribute
            };

            handle.SubscriberId = EllaModel.Instance.GetSubscriberId(subscriberInstance);
            Subscription sub = new Subscription(subscriberInstance, ev, newDataCallBack.Method, newDataCallBack.Target)
            {
                Handle = s.Handle, DataType = typeof(T)
            };


            EllaModel.Instance.AddSubscription(sub);
            var sanity = EllaModel.Instance.CheckSubscriptionSanity();

            if (sanity > 0)
            {
                _log.WarnFormat("Subscription sanity restored. removed {0} subscriptions", sanity);
            }

            if (subscriptionCallback != null)
            {
                _log.DebugFormat("Found subscription callback for {0}, notifying subscriber", handle);
                subscriptionCallback(typeof(T), sub.Handle);
            }
            else
            {
                _log.DebugFormat("Subscription callback for {0} was null, not notifying subscriber", handle);
            }
        }
コード例 #8
0
        /// <summary>
        /// Performs a local subscription for a remote subscriber
        /// </summary>
        /// <param name="type">The type to subscribe to.</param>
        /// <param name="nodeId">The node id of the remote node.</param>
        /// <param name="subscriberAddress">The subscriber address.</param>
        /// <param name="subscriptionReference">The subscription reference.</param>
        /// <returns>An enumerable of <seealso cref="RemoteSubscriptionHandle"/> containing all new subscriptions for this object</returns>
        internal static IEnumerable <RemoteSubscriptionHandle> SubscribeRemoteSubscriber(Type type, int nodeId, IPEndPoint subscriberAddress, int subscriptionReference)
        {
            _log.DebugFormat("Performing remote subscription for type {0}", type);
            var matches = EllaModel.Instance.ActiveEvents.FirstOrDefault(g => g.Key == type);

            if (matches != null)
            {
                _log.DebugFormat("Found {0} matching events for type {1}", matches.Count(), type);
                List <RemoteSubscriptionHandle> handles = new List <RemoteSubscriptionHandle>();
                foreach (var match in matches)
                {
                    Predicate <SubscriptionBase> filterExisting = (s) =>
                    {
                        var remoteSubHandle = s.Handle as RemoteSubscriptionHandle;
                        if (remoteSubHandle == null)
                        {
                            return(false);
                        }
                        return(remoteSubHandle.SubscriptionReference == subscriptionReference &&
                               remoteSubHandle.PublisherId == EllaModel.Instance.GetPublisherId(match.Publisher) && remoteSubHandle.SubscriberNodeID == nodeId);
                    };
                    if (EllaModel.Instance.FilterSubscriptions(filterExisting).Any())
                    {
                        _log.DebugFormat("Subscription from reference {0} to publisher {1} already exists", subscriptionReference, EllaModel.Instance.GetPublisherId(match.Publisher));
                        continue;
                    }
                    var proxy = match.EventDetail.NeedsReliableTransport
                        ? new Proxy()
                        : GetMulticastProxy(match);
                    proxy.EventToHandle = match;
                    proxy.IpSender      = new IpSender(subscriberAddress.Address.ToString(), subscriberAddress.Port);


                    //TODO make max queue size changeable
                    if (!match.EventDetail.NeedsReliableTransport)
                    {
                        proxy.IpSender.MaxQueueSize = 50;
                    }

                    EllaModel.Instance.AddActiveSubscriber(proxy);

                    RemoteSubscriptionHandle handle = match.EventDetail.NeedsReliableTransport
                        ? new RemoteSubscriptionHandle()
                        : new MulticastRemoteSubscriptionhandle
                    {
                        IpAddress = proxy.UdpSender.TargetNode.Address.ToString(),
                        Port      = proxy.UdpSender.TargetNode.Port
                    };
                    handle.EventID               = match.EventDetail.ID;
                    handle.PublisherId           = EllaModel.Instance.GetPublisherId(match.Publisher);
                    handle.SubscriberNodeID      = nodeId;
                    handle.PublisherNodeID       = EllaConfiguration.Instance.NodeId;
                    handle.SubscriberId          = EllaModel.Instance.GetSubscriberId(proxy);
                    handle.SubscriptionReference = subscriptionReference;

                    _log.DebugFormat("Constructing remote subscription handle {0} for {1} subscription", handle, type);
                    SubscriptionBase subscription = new Subscription(proxy, match,
                                                                     proxy.GetType().GetMethod("HandleEvent", BindingFlags.NonPublic | BindingFlags.Instance), proxy);
                    subscription.Handle   = handle;
                    subscription.DataType = type;
                    _log.InfoFormat("Subscribing remote subscriber to {0} for type {1}", match.Publisher,
                                    match.EventDetail.DataType);
                    EllaModel.Instance.AddSubscription(subscription);
                    var removedSubscriptions = EllaModel.Instance.CheckSubscriptionSanity();
                    if (removedSubscriptions > 0)
                    {
                        _log.WarnFormat("Subscription sanity restored after subscribing remote subscriber. removed {0} subscriptions", removedSubscriptions);
                    }
                    handles.Add(handle);
                    _log.DebugFormat("Notifying publisher {0} of new subscription (if callback is supplied)", match.Publisher.GetType().Name);
                    NotifyPublisher(match, handle);
                }
                return(handles);
            }
            else
            {
                _log.DebugFormat("No suitable matching events found for type {0}", type);
            }
            return(null);
        }