private void OnStateVariableChanged(DvStateVariable variable)
        {
            lock (_serverData.SyncObj)
            {
                // Unicast event notifications
                DvService service = variable.ParentService;
                foreach (EndpointConfiguration config in _serverData.UPnPEndPoints)
                {
                    foreach (EventSubscription subscription in config.EventSubscriptions)
                    {
                        if (subscription.Service == service && !subscription.IsDisposed)
                        {
                            subscription.StateVariableChanged(variable);
                        }
                    }
                }

                // Multicast event notifications
                if (variable.Multicast)
                {
                    EventingState eventingState = _serverData.GetMulticastEventKey(variable.ParentService);
                    if (eventingState.EventKey == 0)
                    {
                        // Avoid sending "normal" change events before the initial event was sent
                        return;
                    }
                    eventingState.ModerateChangeEvent(variable);
                    ScheduleMulticastEvents();
                }
            }
        }
        protected void SendMulticastEventNotification(DvService service, IEnumerable <DvStateVariable> variables)
        {
            DvDevice      device        = service.ParentDevice;
            EventingState eventingState = _serverData.GetMulticastEventKey(service);
            // First cluster variables by multicast event level so we can put variables of the same event level into a single message
            IDictionary <string, ICollection <DvStateVariable> > variablesByLevel =
                new Dictionary <string, ICollection <DvStateVariable> >();

            foreach (DvStateVariable variable in variables)
            {
                ICollection <DvStateVariable> variablesCollection;
                if (!variablesByLevel.TryGetValue(variable.MulticastEventLevel, out variablesCollection))
                {
                    variablesByLevel[variable.MulticastEventLevel] = variablesCollection = new List <DvStateVariable>();
                }
                variablesCollection.Add(variable);
            }
            foreach (KeyValuePair <string, ICollection <DvStateVariable> > varByLevel in variablesByLevel)
            {
                // Use a maximum cluster size of GENA_MAX_MULTICAST_EVENT_VAR_COUNT to keep UDP message small
                ICollection <IList <DvStateVariable> > variableClusters = CollectionUtils.Cluster(
                    varByLevel.Value, UPnPConsts.GENA_MAX_MULTICAST_EVENT_VAR_COUNT);
                foreach (IList <DvStateVariable> cluster in variableClusters)
                {
                    foreach (DvStateVariable variable in cluster)
                    {
                        eventingState.UpdateModerationData(variable);
                    }
                    eventingState.IncEventKey();
                    byte[] bodyData = UPnPConsts.UTF8_NO_BOM.GetBytes(GENAMessageBuilder.BuildEventNotificationMessage(
                                                                          cluster, false)); // Albert TODO: Is it correct not to force the simple string equivalent for extended data types here?
                    SimpleHTTPRequest request = new SimpleHTTPRequest("NOTIFY", "*");
                    request.SetHeader("CONTENT-LENGTH", bodyData.Length.ToString());
                    request.SetHeader("CONTENT-TYPE", "text/xml; charset=\"utf-8\"");
                    request.SetHeader("USN", device.UDN + "::" + service.ServiceTypeVersion_URN);
                    request.SetHeader("SVCID", service.ServiceId);
                    request.SetHeader("NT", "upnp:event");
                    request.SetHeader("NTS", "upnp:propchange");
                    request.SetHeader("SEQ", eventingState.EventKey.ToString());
                    request.SetHeader("LVL", varByLevel.Key);
                    request.SetHeader("BOOTID.UPNP.ORG", _serverData.BootId.ToString());

                    foreach (EndpointConfiguration config in _serverData.UPnPEndPoints)
                    {
                        IPEndPoint ep = new IPEndPoint(config.GENAMulticastAddress, UPnPConsts.GENA_MULTICAST_PORT);
                        request.SetHeader("HOST", NetworkHelper.IPEndPointToString(ep));
                        request.MessageBody = bodyData;
                        byte[] bytes = request.Encode();
                        NetworkHelper.SendData(config.GENA_UDP_Socket, ep, bytes, 1);
                    }
                }
            }
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Returns the event key for a multicast event for the given <paramref name="service"/> or <c>null</c>.
 /// </summary>
 public EventingState GetMulticastEventKey(DvService service)
 {
   EventingState result;
   if (!ServiceMulticastEventingState.TryGetValue(service, out result))
     ServiceMulticastEventingState[service] = result = new EventingState();
   return result;
 }