CgUpnpPropertyList *cg_upnp_event_notify_request_getpropertylist(CgUpnpNotifyRequest *notifyReq)
{
    CgUpnpPropertyList *propList;
    CgXmlNode *propSetNode;
    CgXmlNode *propNode;
    CgXmlNode *varNode;
    CgUpnpProperty *prop;
    const char *sid;
    size_t seq;

    cg_log_debug_l4("Entering...\n");

  sid = cg_upnp_event_notify_request_getsid(notifyReq);
    seq = cg_upnp_event_notify_request_getseq(notifyReq);

    propList = cg_upnp_event_notify_request_getpropertylistonly(notifyReq);
    cg_upnp_propertylist_clear(propList);

    propSetNode = cg_soap_request_getrootnoode(notifyReq);
    if (propSetNode == NULL)
        return propList;

    for (propNode = cg_xml_node_getchildnodes(propSetNode); propNode != NULL; propNode = cg_xml_node_next(propNode)) {
        varNode = cg_xml_node_getchildnodes(propNode);
        prop = cg_upnp_property_createfromnode(varNode);
        cg_upnp_property_setsid(prop, sid);
        cg_upnp_property_setseq(prop, seq);
        cg_upnp_propertylist_add(propList, prop);
    }

    cg_log_debug_l4("Leaving...\n");

    return propList;
}
/**
 * The function that calls all HTTP listener callback functions. Do not call
 * this from applications.
 *
 * @param httpReq The received HTTP request
 */
void cg_upnp_controlpoint_httprequestreceived(CgHttpRequest *httpReq)
{
	CgUpnpControlPoint *ctrlPoint = NULL;
	CgUpnpNotifyRequest *notifyReq = NULL;
	CgUpnpPropertyList *propList = NULL;
	CgUpnpProperty *prop = NULL;
	CgUpnpEventListenerList *eventListeners = NULL;
	const char *sid = NULL;
	long seq = 0;
	long timeout = 0;
	CgUpnpDevice *dev = NULL;
	CgUpnpService *service = NULL;
	int notifyListeners = 0;
	
	cg_log_debug_l4("Entering...\n");

	ctrlPoint = (CgUpnpControlPoint *)cg_http_request_getuserdata(httpReq);

	cg_upnp_controlpoint_lock(ctrlPoint);

#if !defined(CG_UPNP_NOUSE_SUBSCRIPTION)
	if (cg_http_request_isnotifyrequest(httpReq) == TRUE) {	
		notifyReq = cg_upnp_event_notify_request_new();
		cg_upnp_event_notify_request_sethttprequest(notifyReq, httpReq);

		/* Get service according to SID */
		sid = cg_upnp_event_notify_request_getsid(notifyReq);
		
		for (dev = cg_upnp_controlpoint_getdevices(ctrlPoint); 
		     dev != NULL;
		     dev = cg_upnp_device_next(dev))
		{
			service = cg_upnp_device_getservicebysid(dev, sid);
			if (service != NULL) break;
		}

		if (service != NULL) {
			/* We found a service */
			seq = cg_upnp_event_notify_request_getseq(notifyReq);
			
			/* Check that event key = previous + 1 */
			if (seq != 0 && seq != cg_upnp_service_geteventkey(service) + 1)
			{
				/* The sequence does not match, unsubscribe and subscribe */
				timeout = cg_upnp_service_getsubscriptiontimeout(service);
				cg_upnp_controlpoint_unsubscribe(ctrlPoint, service);
				cg_upnp_controlpoint_subscribe(ctrlPoint, service, timeout);
			} else {
				/* Wrap seq, so that assertion is true next time */
				if (seq == CG_UPNP_EVENT_MAX_SEQ) seq = 0;
				
				/* Set event key */
				cg_upnp_service_seteventkey(service, seq);
				
				notifyListeners = 1;
				propList = cg_upnp_event_notify_request_getpropertylist(notifyReq); 
				for (prop=cg_upnp_propertylist_gets(propList); 
				     prop != NULL; 
				     prop = cg_upnp_property_next(prop)) 
				{
					/* Update the service's state table from the event */
					cg_upnp_controlpoint_updatestatetablefromproperty(service, prop);
				}
			}
		}
		eventListeners = cg_upnp_controlpoint_geteventlisteners(ctrlPoint);
		cg_upnp_controlpoint_unlock(ctrlPoint);

		if (notifyListeners && propList != NULL) 
		{
			/* Notify listeners out of control point lock */
			for (prop=cg_upnp_propertylist_gets(propList); 
			     prop != NULL; 
			     prop = cg_upnp_property_next(prop)) 
			{
				cg_upnp_eventlistenerlist_notify(eventListeners, prop);
			}
		}

		cg_upnp_event_notify_request_delete(notifyReq);
		cg_http_request_postokrequest(httpReq);
		
		return;
	}
#endif
	
	cg_upnp_controlpoint_unlock(ctrlPoint);
	cg_http_request_postbadrequest(httpReq);

	cg_log_debug_l4("Leaving...\n");
}