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