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);
                    }
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Sends an event notification to our subscriber for the specified <paramref name="variables"/>.
        /// </summary>
        protected void SendEventNotification(IEnumerable <DvStateVariable> variables)
        {
            AsyncRequestState state;

            lock (_serverData.SyncObj)
            {
                foreach (DvStateVariable variable in variables)
                {
                    _eventingState.UpdateModerationData(variable);
                }
                String body;
                lock (_serverData.SyncObj)
                    body = GENAMessageBuilder.BuildEventNotificationMessage(variables, !_subscriberSupportsUPnP11);
                byte[] bodyData = UPnPConsts.UTF8_NO_BOM.GetBytes(body);

                state = new AsyncRequestState(_config, _sid, _callbackURLs, _eventingState.EventKey, bodyData);
                _pendingRequests.Add(state);
                _eventingState.IncEventKey();
            }
            // Outside the lock
            ContinueEventNotification(state);
        }