BOOL cg_upnp_controlpoint_parseservicesfordevice(CgUpnpDevice *dev, CgUpnpSSDPPacket *ssdpPkt) { CgUpnpService *service; CgUpnpDevice *childDev; cg_log_debug_l4("Entering...\n"); for (service=cg_upnp_device_getservices(dev); service != NULL; service = cg_upnp_service_next(service)) { if (cg_upnp_controlpoint_parsescservicescpd(service) == FALSE) { return FALSE; } } /* Now only root SCPDs for root services are parsed, but also child devices' services have to be parsed, so parse them */ for (childDev=cg_upnp_device_getdevices(dev); childDev != NULL; childDev = cg_upnp_device_next(childDev)) { if (cg_upnp_controlpoint_parseservicesfordevice(childDev, ssdpPkt) == FALSE) { return FALSE; } } cg_log_debug_l4("Leaving...\n"); return TRUE; }
/** * Find a device from the controlpoint by the UDN of the device. * * \param ctrlPoint Controlpoint in question * \param udn Type of the device * */ CgUpnpDevice *cg_upnp_controlpoint_getdevicebyudn(CgUpnpControlPoint *ctrlPoint, char *udn) { CgUpnpDevice *dev = NULL; CgUpnpDevice *childDev = NULL; cg_log_debug_l4("Entering...\n"); if (cg_strlen(udn) <= 0 || ctrlPoint == NULL) { return NULL; } for (dev = cg_upnp_controlpoint_getdevices(ctrlPoint); dev != NULL; dev = cg_upnp_device_next(dev)) { if (cg_strcmp(cg_upnp_device_getudn(dev), udn) == 0) { return dev; } childDev = cg_upnp_device_getdevicebyudn(dev, udn); if (childDev != NULL) { return childDev; } } cg_log_debug_l4("Leaving...\n"); return NULL; }
void PrintIGDInfos(CgUpnpControlPoint *ctrlPoint) { CgUpnpDevice *dev; int igdNum; igdNum = 0; for (dev = cg_upnp_controlpoint_getdevices(ctrlPoint); dev != NULL; dev = cg_upnp_device_next(dev)) { if (cg_upnp_device_isdevicetype(dev, UPNPAVDUMP_IGD_DEVICETYPE)) PrintIGDInfo(dev, ++igdNum); } if (igdNum <= 0) printf("IGD is not found !!\n"); }
/** * Find a device from the controlpoint by the type of the device. * This function searches for devices, whose *type part* (i.e. not including * the version) of the device type string matches the given string. * For example: "urn:schemas-upnp-org:device:FooDevice". If you need * to know the version of a device, use \ref cg_upnp_devicetype_getversion * * \param ctrlPoint Controlpoint in question * \param type Type of the device * */ CgUpnpDevice *cg_upnp_controlpoint_getdevicebytype(CgUpnpControlPoint *ctrlPoint, char *type) { CgUpnpDevice *dev = NULL; CgUpnpDevice *childDev = NULL; const char* typeString = NULL; char* part = NULL; cg_log_debug_l4("Entering...\n"); if (cg_strlen(type) <= 0 || ctrlPoint == NULL) { return NULL; } for (dev = cg_upnp_controlpoint_getdevices(ctrlPoint); dev != NULL; dev = cg_upnp_device_next(dev)) { typeString = cg_upnp_device_getdevicetype(dev); if (typeString != NULL) { part = cg_upnp_devicetype_getschematype(typeString); if (cg_strcmp(part, type) == 0) { free(part); return dev; } else { free(part); } } childDev = cg_upnp_device_getdevicebytype(dev, type); if (childDev != NULL) { return childDev; } } cg_log_debug_l4("Leaving...\n"); return NULL; }
void cg_upnp_device_ssdpmessagereceived(CgUpnpDevice *dev, CgUpnpSSDPPacket *ssdpPkt, int filter) { BOOL isRootDev; char *ssdpST; char *devUDN, *devType; char ssdpMsg[CG_UPNP_SSDP_HEADER_LINE_MAXSIZE]; char deviceUSN[CG_UPNP_SSDP_HEADER_LINE_MAXSIZE]; #if defined WINCE size_t n; #else int n; #endif CgUpnpService *service; CgUpnpDevice *childDev; char *ssdpMXString; int ssdpMX; cg_log_debug_l4("Entering...\n"); ssdpMXString = cg_http_headerlist_getvalue(ssdpPkt->headerList, CG_HTTP_MX); ssdpST = cg_upnp_ssdp_packet_getst(ssdpPkt); /* Check if this ssdp packet has already been checked + filtered */ if (filter) { /**************************************** * Request line * Check the request line for errors, this is not ideal as it currently only * checks for the presence of the strings and not the order. ***************************************/ /**** check for M-SEARCH and return if not found ****/ if (cg_strstr(cg_string_getvalue(ssdpPkt->dgmPkt->data), CG_HTTP_MSEARCH) < 0) return; /**** check for * and return if not found ****/ if (cg_strstr(cg_string_getvalue(ssdpPkt->dgmPkt->data), "*") < 0) return; /**** check HTTP version and return if not found ****/ if (cg_strstr(cg_string_getvalue(ssdpPkt->dgmPkt->data), CG_HTTP_VER11) < 0) return; /**************************************** * check HOST header, should always be 239.255.255.250:1900, return if incorrect ***************************************/ if (cg_strcmp(cg_upnp_ssdp_packet_gethost(ssdpPkt), CG_UPNP_SSDP_MULTICAST_ADDRESS) != 0) return; /**************************************** * check MAN header, return if incorrect ***************************************/ if (cg_upnp_ssdp_packet_isdiscover(ssdpPkt) == FALSE) return; /**************************************** * check MX header, return if incorrect ***************************************/ if (ssdpMXString == NULL || cg_strlen(ssdpMXString)==0) /* return if the MX value does not exist or is empty */ return; /* check if MX value is not an integer */ for (n=0; n<strlen(ssdpMXString); n++) { if (isdigit(ssdpMXString[n]) == 0) /* MX value contains a non-digit so is invalid */ return; } /**************************************** * check ST header and if empty return ***************************************/ if (cg_strlen(ssdpST) <= 0) return; /* Check if we have received this search recently * and ignore duplicates. */ if ( filter_duplicate_m_search(ssdpPkt) ) return; ssdpMX = cg_upnp_ssdp_packet_getmx(ssdpPkt); cg_log_debug("Sleeping for a while... (MX:%d)\n", ssdpMX); cg_waitrandom((ssdpMX*1000)/4); } isRootDev = cg_upnp_device_isrootdevice(dev); if (cg_upnp_st_isalldevice(ssdpST) == TRUE) { /* for root device only */ if (isRootDev == TRUE) { cg_upnp_device_getnotifydevicent(dev, ssdpMsg, sizeof(ssdpMsg)); cg_upnp_device_getnotifydeviceusn(dev, deviceUSN, sizeof(deviceUSN)); cg_upnp_device_postsearchresponse(dev, ssdpPkt, ssdpMsg, deviceUSN); } /* for all devices send */ /* device type : device version */ cg_upnp_device_getnotifydevicetypent(dev, ssdpMsg, sizeof(ssdpMsg)); cg_upnp_device_getnotifydevicetypeusn(dev, deviceUSN, sizeof(deviceUSN)); cg_upnp_device_postsearchresponse(dev, ssdpPkt, ssdpMsg, deviceUSN); /* device UUID */ cg_upnp_device_postsearchresponse(dev, ssdpPkt, cg_upnp_device_getudn(dev), cg_upnp_device_getudn(dev)); } else if (cg_upnp_st_isrootdevice(ssdpST) == TRUE) { if (isRootDev == TRUE) { cg_upnp_device_getnotifydeviceusn(dev, deviceUSN, sizeof(deviceUSN)); cg_upnp_device_postsearchresponse(dev, ssdpPkt, CG_UPNP_ST_ROOT_DEVICE, deviceUSN); } } else if (cg_upnp_st_isuuiddevice(ssdpST) == TRUE) { devUDN = cg_upnp_device_getudn(dev); if (cg_streq(ssdpST, devUDN) == TRUE) cg_upnp_device_postsearchresponse(dev, ssdpPkt, devUDN, devUDN); } else if (cg_upnp_st_isurn(ssdpST) == TRUE) { devType = cg_upnp_device_getdevicetype(dev); if (cg_streq(ssdpST, devType) == TRUE) { cg_upnp_device_getnotifydevicetypeusn(dev, deviceUSN, sizeof(deviceUSN)); cg_upnp_device_postsearchresponse(dev, ssdpPkt, devType, deviceUSN); } } for (service=cg_upnp_device_getservices(dev); service != NULL; service = cg_upnp_service_next(service)) cg_upnp_service_ssdpmessagereceived(service, ssdpPkt); for (childDev = cg_upnp_device_getdevices(dev); childDev != NULL; childDev = cg_upnp_device_next(childDev)) cg_upnp_device_ssdpmessagereceived(childDev, ssdpPkt, FALSE); cg_log_debug_l4("Leaving...\n"); }
/** * 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"); }
BOOL cg_upnp_controlpoint_ipchanged(CgUpnpControlPoint *ctrlPoint) { CgNetworkInterfaceList *current, *added, *removed; CgNetworkInterface *netIf; CgUpnpDevice *dev, *tmp; CgUpnpSSDPPacket *ssdpPkt; char *address; cg_log_debug_l4("Entering...\n"); current = cg_net_interfacelist_new(); added = cg_net_interfacelist_new(); removed = cg_net_interfacelist_new(); if (current == NULL || added == NULL || removed == NULL) { if (current != NULL) cg_net_interfacelist_delete(current); if (added != NULL) cg_net_interfacelist_delete(added); if (removed != NULL) cg_net_interfacelist_delete(removed); return FALSE; } /* Get Interface changes */ cg_net_gethostinterfaces(current); cg_net_interfacelist_getchanges(ctrlPoint->ifCache, current, added, removed); /* Remove all devices registered through old interface */ for (netIf = cg_net_interfacelist_gets(removed); netIf != NULL; netIf = cg_net_interface_next(netIf)) { cg_upnp_controlpoint_lock(ctrlPoint); tmp = cg_upnp_controlpoint_getdevices(ctrlPoint); while (tmp != NULL) { dev = tmp; tmp = cg_upnp_device_next(dev); ssdpPkt = cg_upnp_device_getssdppacket(dev); address = cg_upnp_ssdp_packet_getlocaladdress(ssdpPkt); if (address != NULL && cg_strcmp(address, cg_net_interface_getaddress(netIf)) == 0) { /* This device has been received from the removed interface, so it does not exist */ cg_upnp_controlpoint_unlock(ctrlPoint); cg_upnp_controlpoint_removedevicebyssdppacket(ctrlPoint, ssdpPkt); cg_upnp_controlpoint_lock(ctrlPoint); address = NULL; dev = NULL; ssdpPkt = NULL; } } cg_upnp_controlpoint_unlock(ctrlPoint); } /* Launch new M-SEARCH */ cg_upnp_controlpoint_search(ctrlPoint, CG_UPNP_ST_ROOT_DEVICE); /**** Cache current interfaces ****/ cg_net_gethostinterfaces(ctrlPoint->ifCache); cg_net_interfacelist_delete(current); cg_net_interfacelist_delete(added); cg_net_interfacelist_delete(removed); cg_log_debug_l4("Leaving...\n"); return TRUE; }
/** * Stop the control point. Stops sending/receiveing/responding to any messages. * * @param ctrlPoint The control point to stop * * @return TRUE if successful; otherwise FALSE * */ BOOL cg_upnp_controlpoint_stop(CgUpnpControlPoint *ctrlPoint) { CgUpnpDevice *dev = NULL; CgUpnpSSDPServerList *ssdpServerList; CgUpnpSSDPResponseServerList *ssdpResServerList; CgHttpServerList *httpServerList; const char *udn = NULL; CG_UPNP_DEVICE_LISTENER listener = cg_upnp_controlpoint_getdevicelistener(ctrlPoint); cg_log_debug_l4("Entering...\n"); /* Stop expiration handling */ cg_thread_stop_with_cond(ctrlPoint->expThread, ctrlPoint->expCond); cg_log_debug_s("Expiration thread stopped.\n"); /**** SSDP Server ****/ ssdpServerList = cg_upnp_controlpoint_getssdpserverlist(ctrlPoint); cg_log_debug_s("Stopping ssdp servers.\n"); cg_upnp_ssdp_serverlist_stop(ssdpServerList); cg_log_debug_s("Done\n"); cg_upnp_ssdp_serverlist_close(ssdpServerList); cg_upnp_ssdp_serverlist_clear(ssdpServerList); /**** SSDP Response Server ****/ ssdpResServerList = cg_upnp_controlpoint_getssdpresponseserverlist(ctrlPoint); cg_log_debug_s("Stopping ssdp response servers.\n"); cg_upnp_ssdpresponse_serverlist_stop(ssdpResServerList); cg_log_debug_s("Done\n"); cg_upnp_ssdpresponse_serverlist_close(ssdpResServerList); cg_upnp_ssdpresponse_serverlist_clear(ssdpResServerList); /**** HTTP Server ****/ httpServerList = cg_upnp_controlpoint_gethttpserverlist(ctrlPoint); cg_log_debug_s("Stopping http servers.\n"); cg_http_serverlist_stop(httpServerList); cg_log_debug_s("Done\n"); cg_http_serverlist_close(httpServerList); cg_http_serverlist_clear(httpServerList); cg_upnp_controlpoint_lock(ctrlPoint); cg_log_debug_s("Got controlpoint lock.\n"); /* Unsubscribe from all services */ for (dev = cg_upnp_controlpoint_getdevices(ctrlPoint); dev != NULL; dev = cg_upnp_device_next(dev)) { udn = cg_upnp_device_getudn(dev); /* Call device listener for each device */ if (udn != NULL && listener != NULL) { cg_upnp_controlpoint_unlock(ctrlPoint); listener(ctrlPoint, udn, CgUpnpDeviceStatusRemoved); cg_upnp_controlpoint_lock(ctrlPoint); } } /* Empty device cache */ cg_upnp_devicelist_clear(ctrlPoint->deviceList); cg_log_debug_s("Device list cleared.\n"); cg_upnp_controlpoint_unlock(ctrlPoint); cg_log_debug_l4("Leaving...\n"); return TRUE; }