Beispiel #1
0
int SearchByTarget(int Mx, char *St, void *Cookie)
{
	char errorBuffer[ERROR_BUFFER_LEN];
	int *id = NULL;
	int ret = 0;
	char ReqBufv4[BUFSIZE];
#ifdef UPNP_ENABLE_IPV6
	char ReqBufv6[BUFSIZE];
	char ReqBufv6UlaGua[BUFSIZE];
#endif
	struct sockaddr_storage __ss_v4;
#ifdef UPNP_ENABLE_IPV6
	struct sockaddr_storage __ss_v6;
#endif
	struct sockaddr_in *destAddr4 = (struct sockaddr_in *)&__ss_v4;
#ifdef UPNP_ENABLE_IPV6
	struct sockaddr_in6 *destAddr6 = (struct sockaddr_in6 *)&__ss_v6;
#endif
	fd_set wrSet;
	SsdpSearchArg *newArg = NULL;
	int timeTillRead = 0;
	int handle;
	struct Handle_Info *ctrlpt_info = NULL;
	enum SsdpSearchType requestType;
	unsigned long addrv4 = inet_addr(gIF_IPV4);
	SOCKET max_fd = 0;
	int retVal;

	/*ThreadData *ThData; */
	ThreadPoolJob job;

	memset(&job, 0, sizeof(job));

	requestType = ssdp_request_type1(St);
	if (requestType == SSDP_SERROR)
		return UPNP_E_INVALID_PARAM;
	UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
		   "Inside SearchByTarget\n");
	timeTillRead = Mx;
	if (timeTillRead < MIN_SEARCH_TIME)
		timeTillRead = MIN_SEARCH_TIME;
	else if (timeTillRead > MAX_SEARCH_TIME)
		timeTillRead = MAX_SEARCH_TIME;
	retVal = CreateClientRequestPacket(ReqBufv4, sizeof(ReqBufv4), timeTillRead, St, AF_INET);
	if (retVal != UPNP_E_SUCCESS)
		return retVal;
#ifdef UPNP_ENABLE_IPV6
	retVal = CreateClientRequestPacket(ReqBufv6, sizeof(ReqBufv6), timeTillRead, St, AF_INET6);
	if (retVal != UPNP_E_SUCCESS)
		return retVal;
	retVal = CreateClientRequestPacketUlaGua(ReqBufv6UlaGua, sizeof(ReqBufv6UlaGua), timeTillRead, St, AF_INET6);
	if (retVal != UPNP_E_SUCCESS)
		return retVal;
#endif

	memset(&__ss_v4, 0, sizeof(__ss_v4));
	destAddr4->sin_family = (sa_family_t)AF_INET;
	inet_pton(AF_INET, SSDP_IP, &destAddr4->sin_addr);
	destAddr4->sin_port = htons(SSDP_PORT);

#ifdef UPNP_ENABLE_IPV6
	memset(&__ss_v6, 0, sizeof(__ss_v6));
	destAddr6->sin6_family = (sa_family_t)AF_INET6;
	inet_pton(AF_INET6, SSDP_IPV6_SITELOCAL, &destAddr6->sin6_addr);
	destAddr6->sin6_port = htons(SSDP_PORT);
	destAddr6->sin6_scope_id = gIF_INDEX;
#endif

	/* add search criteria to list */
	HandleLock();
	if (GetClientHandleInfo(&handle, &ctrlpt_info) != HND_CLIENT) {
		HandleUnlock();
		return UPNP_E_INTERNAL_ERROR;
	}
	newArg = (SsdpSearchArg *) malloc(sizeof(SsdpSearchArg));
	newArg->searchTarget = strdup(St);
	newArg->cookie = Cookie;
	newArg->requestType = requestType;
	id = (int *)malloc(sizeof(int));
	TPJobInit(&job, (start_routine) searchExpired, id);
	TPJobSetPriority(&job, MED_PRIORITY);
	TPJobSetFreeFunction(&job, (free_routine) free);
	/* Schedule a timeout event to remove search Arg */
	TimerThreadSchedule(&gTimerThread, timeTillRead,
			    REL_SEC, &job, SHORT_TERM, id);
	newArg->timeoutEventId = *id;
	ListAddTail(&ctrlpt_info->SsdpSearchList, newArg);
	HandleUnlock();
	/* End of lock */

	FD_ZERO(&wrSet);
	if (gSsdpReqSocket4 != INVALID_SOCKET) {
		setsockopt(gSsdpReqSocket4, IPPROTO_IP, IP_MULTICAST_IF,
			   (char *)&addrv4, sizeof(addrv4));
		FD_SET(gSsdpReqSocket4, &wrSet);
		max_fd = max(max_fd, gSsdpReqSocket4);
	}
#ifdef UPNP_ENABLE_IPV6
	if (gSsdpReqSocket6 != INVALID_SOCKET) {
		setsockopt(gSsdpReqSocket6, IPPROTO_IPV6, IPV6_MULTICAST_IF,
			   (char *)&gIF_INDEX, sizeof(gIF_INDEX));
		FD_SET(gSsdpReqSocket6, &wrSet);
		max_fd = max(max_fd, gSsdpReqSocket6);
	}
#endif
	ret = select(max_fd + 1, NULL, &wrSet, NULL, NULL);
	if (ret == -1) {
		strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
		UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
			   "SSDP_LIB: Error in select(): %s\n", errorBuffer);
		shutdown(gSsdpReqSocket4, SD_BOTH);
		UpnpCloseSocket(gSsdpReqSocket4);
#ifdef UPNP_ENABLE_IPV6
		shutdown(gSsdpReqSocket6, SD_BOTH);
		UpnpCloseSocket(gSsdpReqSocket6);
#endif
		return UPNP_E_INTERNAL_ERROR;
	}
#ifdef UPNP_ENABLE_IPV6
	if (gSsdpReqSocket6 != INVALID_SOCKET &&
	    FD_ISSET(gSsdpReqSocket6, &wrSet)) {
		int NumCopy = 0;

		while (NumCopy < NUM_SSDP_COPY) {
			UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
				   ">>> SSDP SEND M-SEARCH >>>\n%s\n",
				   ReqBufv6UlaGua);
			sendto(gSsdpReqSocket6,
			       ReqBufv6UlaGua, strlen(ReqBufv6UlaGua), 0,
			       (struct sockaddr *)&__ss_v6,
			       sizeof(struct sockaddr_in6));
			NumCopy++;
			imillisleep(SSDP_PAUSE);
		}
		NumCopy = 0;
		inet_pton(AF_INET6, SSDP_IPV6_LINKLOCAL, &destAddr6->sin6_addr);
		while (NumCopy < NUM_SSDP_COPY) {
			UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
				   ">>> SSDP SEND M-SEARCH >>>\n%s\n",
				   ReqBufv6);
			sendto(gSsdpReqSocket6,
			       ReqBufv6, strlen(ReqBufv6), 0,
			       (struct sockaddr *)&__ss_v6,
			       sizeof(struct sockaddr_in6));
			NumCopy++;
			imillisleep(SSDP_PAUSE);
		}
	}
#endif /* IPv6 */
	if (gSsdpReqSocket4 != INVALID_SOCKET &&
	    FD_ISSET(gSsdpReqSocket4, &wrSet)) {
		int NumCopy = 0;
		while (NumCopy < NUM_SSDP_COPY) {
			UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
				   ">>> SSDP SEND M-SEARCH >>>\n%s\n",
				   ReqBufv4);
			sendto(gSsdpReqSocket4,
			       ReqBufv4, strlen(ReqBufv4), 0,
			       (struct sockaddr *)&__ss_v4,
			       sizeof(struct sockaddr_in));
			NumCopy++;
			imillisleep(SSDP_PAUSE);
		}
	}

	return 1;
}
Beispiel #2
0
/*!
 * \brief Thread job to Notify a control point.
 *
 * It validates the subscription and copies the subscription. Also make sure
 * that events are sent in order.
 *
 * \note calls the genaNotify to do the actual work.
 */
static void genaNotifyThread(
	/*! [in] notify thread structure containing all the headers and property set info. */
	void *input)
{
	subscription *sub;
	service_info *service;
	subscription sub_copy;
	notify_thread_struct *in = (notify_thread_struct *) input;
	int return_code;
	struct Handle_Info *handle_info;
	ThreadPoolJob job;

	memset(&job, 0, sizeof(job));

	/* This should be a HandleLock and not a HandleReadLock otherwise if there
	 * is a lot of notifications, then multiple threads will acquire a read
	 * lock and the thread which sends the notification will be blocked forever
	 * on the HandleLock at the end of this function. */
	/*HandleReadLock(); */
	HandleLock();
	/* validate context */

	if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}

	if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) ||
	    !service->active ||
	    !(sub = GetSubscriptionSID(in->sid, service)) ||
	    copy_subscription(sub, &sub_copy) != HTTP_SUCCESS) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}
#ifdef UPNP_ENABLE_NOTIFICATION_REORDERING
	/*If the event is out of order push it back to the job queue */
	if (in->eventKey != sub->ToSendEventKey) {
		TPJobInit(&job, (start_routine) genaNotifyThread, input);
		TPJobSetFreeFunction(&job, (free_function) free_notify_struct);
		TPJobSetPriority(&job, MED_PRIORITY);
		/* Sleep a little before creating another thread otherwise if there is
		 * a lot of notifications to send, the device will take 100% of the CPU
		 * to create threads and push them back to the job queue. */
		imillisleep(1);
		ThreadPoolAdd(&gSendThreadPool, &job, NULL);
		freeSubscription(&sub_copy);
		HandleUnlock();
		return;
	}
#endif

	HandleUnlock();

	/* send the notify */
	return_code = genaNotify(in->headers, in->propertySet, &sub_copy);
	freeSubscription(&sub_copy);
	HandleLock();
	if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}
	/* validate context */
	if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) ||
	    !service->active ||
	    !(sub = GetSubscriptionSID(in->sid, service))) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}
	sub->ToSendEventKey++;
	if (sub->ToSendEventKey < 0)
		/* wrap to 1 for overflow */
		sub->ToSendEventKey = 1;
	if (return_code == GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB)
		RemoveSubscriptionSID(in->sid, service);
	free_notify_struct(in);

	HandleUnlock();
}
Beispiel #3
0
int AdvertiseAndReply(int AdFlag, UpnpDevice_Handle Hnd,
		      enum SsdpSearchType SearchType,
		      struct sockaddr *DestAddr, char *DeviceType,
		      char *DeviceUDN, char *ServiceType, int Exp)
{
	int retVal = UPNP_E_SUCCESS;
	long unsigned int i;
	long unsigned int j;
	int defaultExp = DEFAULT_MAXAGE;
	struct Handle_Info *SInfo = NULL;
	char UDNstr[100];
	char devType[100];
	char servType[100];
	IXML_NodeList *nodeList = NULL;
	IXML_NodeList *tmpNodeList = NULL;
	IXML_Node *tmpNode = NULL;
	IXML_Node *tmpNode2 = NULL;
	IXML_Node *textNode = NULL;
	const DOMString tmpStr;
	const DOMString dbgStr;
	int NumCopy = 0;

	memset(UDNstr, 0, sizeof(UDNstr));
	memset(devType, 0, sizeof(devType));
	memset(servType, 0, sizeof(servType));

	UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
		   "Inside AdvertiseAndReply with AdFlag = %d\n", AdFlag);

	/* Use a read lock */
	HandleReadLock();
	if (GetHandleInfo(Hnd, &SInfo) != HND_DEVICE) {
		retVal = UPNP_E_INVALID_HANDLE;
		goto end_function;
	}
	defaultExp = SInfo->MaxAge;
	/* parse the device list and send advertisements/replies */
	while (NumCopy == 0 || (AdFlag && NumCopy < NUM_SSDP_COPY)) {
		if (NumCopy != 0)
			imillisleep(SSDP_PAUSE);
		NumCopy++;
		for (i = 0lu;; i++) {
			UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
				   "Entering new device list with i = %lu\n\n",
				   i);
			tmpNode = ixmlNodeList_item(SInfo->DeviceList, i);
			if (!tmpNode) {
				UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
					   "Exiting new device list with i = %lu\n\n",
					   i);
				break;
			}
			dbgStr = ixmlNode_getNodeName(tmpNode);
			UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
				   "Extracting device type once for %s\n",
				   dbgStr);
			ixmlNodeList_free(nodeList);
			nodeList = ixmlElement_getElementsByTagName((IXML_Element *) tmpNode, "deviceType");
			if (!nodeList)
				continue;
			UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
				   "Extracting UDN for %s\n", dbgStr);
			UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
				   "Extracting device type\n");
			tmpNode2 = ixmlNodeList_item(nodeList, 0lu);
			if (!tmpNode2)
				continue;
			textNode = ixmlNode_getFirstChild(tmpNode2);
			if (!textNode)
				continue;
			UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
				   "Extracting device type \n");
			tmpStr = ixmlNode_getNodeValue(textNode);
			if (!tmpStr)
				continue;
			strncpy(devType, tmpStr, sizeof(devType) - 1);
			UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
				   "Extracting device type = %s\n", devType);
			if (!tmpNode) {
				UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
					   "TempNode is NULL\n");
			}
			dbgStr = ixmlNode_getNodeName(tmpNode);
			UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
				   "Extracting UDN for %s\n", dbgStr);
			ixmlNodeList_free(nodeList);
			nodeList = ixmlElement_getElementsByTagName((IXML_Element *) tmpNode, "UDN");
			if (!nodeList) {
				UpnpPrintf(UPNP_CRITICAL, API, __FILE__,
					   __LINE__, "UDN not found!\n");
				continue;
			}
			tmpNode2 = ixmlNodeList_item(nodeList, 0lu);
			if (!tmpNode2) {
				UpnpPrintf(UPNP_CRITICAL, API, __FILE__,
					   __LINE__, "UDN not found!\n");
				continue;
			}
			textNode = ixmlNode_getFirstChild(tmpNode2);
			if (!textNode) {
				UpnpPrintf(UPNP_CRITICAL, API, __FILE__,
					   __LINE__, "UDN not found!\n");
				continue;
			}
			tmpStr = ixmlNode_getNodeValue(textNode);
			if (!tmpStr) {
				UpnpPrintf(UPNP_CRITICAL, API, __FILE__,
					   __LINE__, "UDN not found!\n");
				continue;
			}
			strncpy(UDNstr, tmpStr, sizeof(UDNstr) - 1);
			UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
				   "Sending UDNStr = %s \n", UDNstr);
			if (AdFlag) {
				/* send the device advertisement */
				if (AdFlag == 1) {
                    DeviceAdvertisement(devType, i == 0lu, NumCopy - 1,
							    UDNstr,
							    SInfo->DescURL, Exp,
							    SInfo->DeviceAf,
							    SInfo->PowerState,
	                                                    SInfo->SleepPeriod,
	                                                    SInfo->RegistrationState);
				} else {
					/* AdFlag == -1 */
                    DeviceShutdown(devType, i == 0lu, NumCopy - 1, UDNstr,
						       SInfo->DescURL,
						       Exp, SInfo->DeviceAf,
						       SInfo->PowerState,
						       SInfo->SleepPeriod,
						       SInfo->RegistrationState);
				}
			} else {
				switch (SearchType) {
				case SSDP_ALL:
                    DeviceReply(DestAddr, devType, i == 0lu, NumCopy - 1,
						    UDNstr, SInfo->DescURL,
						    defaultExp, SInfo->PowerState,
						    SInfo->SleepPeriod,
						    SInfo->RegistrationState);
					break;
				case SSDP_ROOTDEVICE:
					if (i == 0lu) {
                        SendReply(DestAddr, devType, 1, NumCopy - 1,
							  UDNstr,
							  SInfo->DescURL,
							  defaultExp, 0,
							  SInfo->PowerState,
							  SInfo->SleepPeriod,
							  SInfo->RegistrationState);
					}
					break;
				case SSDP_DEVICEUDN: {
					if (DeviceUDN && strlen(DeviceUDN) != (size_t)0) {
						if (strcasecmp(DeviceUDN, UDNstr)) {
							UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
								"DeviceUDN=%s and search UDN=%s DID NOT match\n",
								UDNstr, DeviceUDN);
							break;
						} else {
							UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
								"DeviceUDN=%s and search UDN=%s MATCH\n",
								UDNstr, DeviceUDN);
                            SendReply(DestAddr, devType, 0, NumCopy - 1, UDNstr, SInfo->DescURL, defaultExp, 0,
								SInfo->PowerState,
								SInfo->SleepPeriod,
								SInfo->RegistrationState);
							break;
						}
					}
				}
				case SSDP_DEVICETYPE: {
					if (!strncasecmp(DeviceType, devType, strlen(DeviceType) - (size_t)2)) {
						if (atoi(strrchr(DeviceType, ':') + 1)
						    < atoi(&devType[strlen(devType) - (size_t)1])) {
							/* the requested version is lower than the device version
							 * must reply with the lower version number and the lower
							 * description URL */
							UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
								   "DeviceType=%s and search devType=%s MATCH\n",
								   devType, DeviceType);
                            SendReply(DestAddr, DeviceType, 0, NumCopy - 1, UDNstr, SInfo->LowerDescURL,
								  defaultExp, 1,
								  SInfo->PowerState,
								  SInfo->SleepPeriod,
								  SInfo->RegistrationState);
						} else if (atoi(strrchr(DeviceType, ':') + 1)
							   == atoi(&devType[strlen(devType) - (size_t)1])) {
							UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
								   "DeviceType=%s and search devType=%s MATCH\n",
								   devType, DeviceType);
                            SendReply(DestAddr, DeviceType, 0, NumCopy - 1, UDNstr, SInfo->DescURL,
								  defaultExp, 1,
								  SInfo->PowerState,
								  SInfo->SleepPeriod,
								  SInfo->RegistrationState);
						} else {
							UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
								   "DeviceType=%s and search devType=%s DID NOT MATCH\n",
								   devType, DeviceType);
						}
					} else {
						UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
							   "DeviceType=%s and search devType=%s DID NOT MATCH\n",
							   devType, DeviceType);
					}
					break;
				}
				default:
					break;
				}
			}
			/* send service advertisements for services corresponding
			 * to the same device */
			UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
				   "Sending service Advertisement\n");
			/* Correct service traversal such that each device's serviceList
			 * is directly traversed as a child of its parent device. This
			 * ensures that the service's alive message uses the UDN of
			 * the parent device. */
			tmpNode = ixmlNode_getFirstChild(tmpNode);
			while (tmpNode) {
				dbgStr = ixmlNode_getNodeName(tmpNode);
				if (!strncmp
				    (dbgStr, SERVICELIST_STR,
				     sizeof SERVICELIST_STR)) {
					break;
				}
				tmpNode = ixmlNode_getNextSibling(tmpNode);
			}
			ixmlNodeList_free(nodeList);
			if (!tmpNode) {
				nodeList = NULL;
				continue;
			}
			nodeList = ixmlElement_getElementsByTagName((IXML_Element *) tmpNode, "service");
			if (!nodeList) {
				UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
					   "Service not found 3\n");
				continue;
			}
			for (j = 0lu;; j++) {
				tmpNode = ixmlNodeList_item(nodeList, j);
				if (!tmpNode) {
					break;
				}
				ixmlNodeList_free(tmpNodeList);
				tmpNodeList = ixmlElement_getElementsByTagName((IXML_Element *) tmpNode, "serviceType");
				if (!tmpNodeList) {
					UpnpPrintf(UPNP_CRITICAL, API, __FILE__,
						   __LINE__,
						   "ServiceType not found \n");
					continue;
				}
				tmpNode2 = ixmlNodeList_item(tmpNodeList, 0lu);
				if (!tmpNode2)
					continue;
				textNode = ixmlNode_getFirstChild(tmpNode2);
				if (!textNode)
					continue;
				/* servType is of format Servicetype:ServiceVersion */
				tmpStr = ixmlNode_getNodeValue(textNode);
				if (!tmpStr)
					continue;
				strncpy(servType, tmpStr, sizeof(servType) - 1);
				UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
					   "ServiceType = %s\n", servType);
				if (AdFlag) {
					if (AdFlag == 1) {
                        ServiceAdvertisement(NumCopy - 1, UDNstr,
							servType, SInfo->DescURL,
							Exp, SInfo->DeviceAf,
							SInfo->PowerState,
							SInfo->SleepPeriod,
							SInfo->RegistrationState);
					} else {
						/* AdFlag == -1 */
                        ServiceShutdown(NumCopy - 1, UDNstr,
							servType, SInfo->DescURL,
							Exp, SInfo->DeviceAf,
							SInfo->PowerState,
							SInfo->SleepPeriod,
							SInfo->RegistrationState);
					}
				} else {
					switch (SearchType) {
					case SSDP_ALL:
                        ServiceReply(DestAddr,
                                 servType,
                                 NumCopy - 1,
							     UDNstr,
							     SInfo->DescURL,
							     defaultExp,
							     SInfo->PowerState,
							     SInfo->SleepPeriod,
							     SInfo->RegistrationState);
						break;
					case SSDP_SERVICE:
						if (ServiceType) {
							if (!strncasecmp(ServiceType, servType, strlen(ServiceType) - (size_t)2)) {
								if (atoi(strrchr(ServiceType, ':') + 1) <
								    atoi(&servType[strlen(servType) - (size_t)1])) {
									/* the requested version is lower than the service version
									 * must reply with the lower version number and the lower
									 * description URL */
									UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
										   "ServiceType=%s and search servType=%s MATCH\n",
										   ServiceType, servType);
                                    SendReply(DestAddr, ServiceType, 0, NumCopy - 1, UDNstr, SInfo->LowerDescURL,
										  defaultExp, 1,
										  SInfo->PowerState,
										  SInfo->SleepPeriod,
										  SInfo->RegistrationState);
								} else if (atoi(strrchr (ServiceType, ':') + 1) ==
									   atoi(&servType[strlen(servType) - (size_t)1])) {
									UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
										   "ServiceType=%s and search servType=%s MATCH\n",
										   ServiceType, servType);
                                    SendReply(DestAddr, ServiceType, 0, NumCopy - 1, UDNstr, SInfo->DescURL,
										  defaultExp, 1,
										  SInfo->PowerState,
										  SInfo->SleepPeriod,
										  SInfo->RegistrationState);
								} else {
									UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
									   "ServiceType=%s and search servType=%s DID NOT MATCH\n",
									   ServiceType, servType);
								}
							} else {
								UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
									   "ServiceType=%s and search servType=%s DID NOT MATCH\n",
									   ServiceType, servType);
							}
						}
						break;
					default:
						break;
					}
				}
			}
			ixmlNodeList_free(tmpNodeList);
			tmpNodeList = NULL;
			ixmlNodeList_free(nodeList);
			nodeList = NULL;
		}
	}

end_function:
	ixmlNodeList_free(tmpNodeList);
	ixmlNodeList_free(nodeList);
	UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
		   "Exiting AdvertiseAndReply.\n");
	HandleUnlock();

	return retVal;
}