Example #1
0
bool UPnP::NetScan(int waitSec)
{
	int res;
	m_addedDev = false;
	res = UpnpSearchAsync(CtrlPnt, waitSec, MEDIASERVERS, this);

	if(res != UPNP_E_SUCCESS)
	{
		Log::err("UpnpSearchAsync error: %s",UpnpGetErrorMessage(res));
	}

	res = UpnpSearchAsync(CtrlPnt, waitSec, MEDIARENDERERS, this);

	if(res != UPNP_E_SUCCESS)
	{
		Log::err("UpnpSearchAsync error: %s", UpnpGetErrorMessage(res));
	}

	//wait
	return true;//cfg->GetXml(deviceList);
	/*
	    res = UpnpSearchAsync( CtrlPnt, waitSec, ALL_DEVICE_TYPES, this );
	    if( res != UPNP_E_SUCCESS )
	    {
	        std::cerr<<"UpnpSearchAsync error: "<<UpnpGetErrorMessage( res )<<std::endl;
	    }
	        return deviceList;

	    */
}
Example #2
0
File: upnp.cpp Project: ZMacer/vlc
/*
 * Initializes UPNP instance.
 */
static int Open( vlc_object_t *p_this )
{
    services_discovery_t *p_sd = ( services_discovery_t* )p_this;
    services_discovery_sys_t *p_sys  = ( services_discovery_sys_t * )
            calloc( 1, sizeof( services_discovery_sys_t ) );

    if( !( p_sd->p_sys = p_sys ) )
        return VLC_ENOMEM;

    p_sys->p_server_list = new(std::nothrow) SD::MediaServerList( p_sd );
    if ( unlikely( p_sys->p_server_list == NULL ) )
    {
        return VLC_ENOMEM;
    }

    p_sys->p_upnp = UpnpInstanceWrapper::get( p_this, SD::MediaServerList::Callback, p_sys->p_server_list );
    if ( !p_sys->p_upnp )
    {
        Close( p_this );
        return VLC_EGENERIC;
    }

    /* Search for media servers */
    int i_res = UpnpSearchAsync( p_sys->p_upnp->handle(), 5,
            MEDIA_SERVER_DEVICE_TYPE, p_sys->p_upnp );
    if( i_res != UPNP_E_SUCCESS )
    {
        msg_Err( p_sd, "Error sending search request: %s", UpnpGetErrorMessage( i_res ) );
        Close( p_this );
        return VLC_EGENERIC;
    }

    return VLC_SUCCESS;
}
Example #3
0
/*
 * Initializes UPNP instance.
 */
static int Open( vlc_object_t *p_this )
{
    int i_res;
    services_discovery_t *p_sd = ( services_discovery_t* )p_this;
    services_discovery_sys_t *p_sys  = ( services_discovery_sys_t * )
            calloc( 1, sizeof( services_discovery_sys_t ) );

    if( !( p_sd->p_sys = p_sys ) )
        return VLC_ENOMEM;

    /* Initialize on first IPv4-capable adapter and first open port
     * TODO: use UpnpInit2() to utilize IPv6.
     */
    i_res = UpnpInit( 0, 0 );
    if( i_res != UPNP_E_SUCCESS )
    {
        msg_Err( p_sd, "Initialization failed: %s", UpnpGetErrorMessage( i_res ) );
        free( p_sys );
        return VLC_EGENERIC;
    }

    p_sys->p_server_list = new MediaServerList( p_sd );
    vlc_mutex_init( &p_sys->callback_lock );

    /* Register a control point */
    i_res = UpnpRegisterClient( Callback, p_sd, &p_sys->client_handle );
    if( i_res != UPNP_E_SUCCESS )
    {
        msg_Err( p_sd, "Client registration failed: %s", UpnpGetErrorMessage( i_res ) );
        Close( (vlc_object_t*) p_sd );
        return VLC_EGENERIC;
    }

    /* Search for media servers */
    i_res = UpnpSearchAsync( p_sys->client_handle, 5,
            MEDIA_SERVER_DEVICE_TYPE, p_sd );
    if( i_res != UPNP_E_SUCCESS )
    {
        msg_Err( p_sd, "Error sending search request: %s", UpnpGetErrorMessage( i_res ) );
        Close( (vlc_object_t*) p_sd );
        return VLC_EGENERIC;
    }

    /* libupnp does not treat a maximum content length of 0 as unlimited
     * until 64dedf (~ pupnp v1.6.7) and provides no sane way to discriminate
     * between versions */
    if( (i_res = UpnpSetMaxContentLength( INT_MAX )) != UPNP_E_SUCCESS )
    {
        msg_Err( p_sd, "Failed to set maximum content length: %s",
                UpnpGetErrorMessage( i_res ));

        Close( (vlc_object_t*) p_sd );
        return VLC_EGENERIC;
    }

    return VLC_SUCCESS;
}
Example #4
0
/********************************************************************************
 * TvCtrlPointVerifyTimeouts
 *
 * Description: 
 *       Checks the advertisement  each device
 *        in the global device list.  If an advertisement expires,
 *       the device is removed from the list.  If an advertisement is about to
 *       expire, a search request is sent for that device.  
 *
 * Parameters:
 *    incr -- The increment to subtract from the timeouts each time the
 *            function is called.
 *
 ********************************************************************************/
void
TvCtrlPointVerifyTimeouts( int incr )
{
    struct TvDeviceNode *prevdevnode,
     *curdevnode;
    int ret;

    ithread_mutex_lock( &DeviceListMutex );

    prevdevnode = NULL;
    curdevnode = GlobalDeviceList;

    while( curdevnode ) {
        curdevnode->device.AdvrTimeOut -= incr;
        //SampleUtil_Print("Advertisement Timeout: %d\n", curdevnode->device.AdvrTimeOut);

        if( curdevnode->device.AdvrTimeOut <= 0 ) {
            /*
               This advertisement has expired, so we should remove the device
               from the list 
             */

            if( GlobalDeviceList == curdevnode )
                GlobalDeviceList = curdevnode->next;
            else
                prevdevnode->next = curdevnode->next;
            TvCtrlPointDeleteNode( curdevnode );
            if( prevdevnode )
                curdevnode = prevdevnode->next;
            else
                curdevnode = GlobalDeviceList;
        } else {

            if( curdevnode->device.AdvrTimeOut < 2 * incr ) {
                /*
                   This advertisement is about to expire, so send
                   out a search request for this device UDN to 
                   try to renew 
                 */
                ret = UpnpSearchAsync( ctrlpt_handle, incr,
                                       curdevnode->device.UDN, NULL );
                if( ret != UPNP_E_SUCCESS )
                    SampleUtil_Print
                        ( "Error sending search request for Device UDN: %s -- err = %d",
                          curdevnode->device.UDN, ret );
            }

            prevdevnode = curdevnode;
            curdevnode = curdevnode->next;
        }

    }
    ithread_mutex_unlock( &DeviceListMutex );

}
Example #5
0
static void *
SearchThread( void *p_data )
{
    services_discovery_t *p_sd = ( services_discovery_t* )p_data;
    services_discovery_sys_t *p_sys  = p_sd->p_sys;

    /* Search for media servers */
    int i_res = UpnpSearchAsync( p_sys->p_upnp->handle(), 5,
                                 MEDIA_SERVER_DEVICE_TYPE, p_sys->p_upnp );
    if( i_res != UPNP_E_SUCCESS )
    {
        msg_Err( p_sd, "Error sending search request: %s", UpnpGetErrorMessage( i_res ) );
        return NULL;
    }

    /* Search for Sat Ip servers*/
    i_res = UpnpSearchAsync( p_sys->p_upnp->handle(), 5,
                             SATIP_SERVER_DEVICE_TYPE, p_sys->p_upnp );
    if( i_res != UPNP_E_SUCCESS )
        msg_Err( p_sd, "Error sending search request: %s", UpnpGetErrorMessage( i_res ) );
    return NULL;
}
Example #6
0
/********************************************************************************
 * TvCtrlPointRefresh
 *
 * Description: 
 *       Clear the current global device list and issue new search
 *	 requests to build it up again from scratch.
 *
 * Parameters:
 *   None
 *
 ********************************************************************************/
int TvCtrlPointRefresh(void)
{
	int rc;

	TvCtrlPointRemoveAll();
	/* Search for all devices of type tvdevice version 1,
	 * waiting for up to 5 seconds for the response */
	rc = UpnpSearchAsync(ctrlpt_handle, 5, TvDeviceType, NULL);
	if (UPNP_E_SUCCESS != rc) {
		SampleUtil_Print("Error sending search request%d\n", rc);

		return TV_ERROR;
	}

	return TV_SUCCESS;
}
Example #7
0
/********************************************************************************
 * upnp_igd_verify_timeouts
 *
 * Description:
 *       Check all the device for refreshing which ones are close to timeout.
 *
 * Parameters:
 *   igd_ctxt -- The upnp igd context
 *   incr     -- Number of second before next check
 *
 ********************************************************************************/
void upnp_igd_verify_timeouts(upnp_igd_context *igd_ctxt, int incr) {
	upnp_igd_device_node *prevdevnode, *curdevnode;
	int ret;

	ithread_mutex_lock(&igd_ctxt->devices_mutex);

	prevdevnode = NULL;
	curdevnode = igd_ctxt->devices;
	while (curdevnode) {
		if(curdevnode->device.advr_time_out > igd_ctxt->max_adv_timeout) {
			curdevnode->device.advr_time_out = igd_ctxt->max_adv_timeout;
		}
		curdevnode->device.advr_time_out -= incr;
		upnp_igd_print(igd_ctxt, UPNP_IGD_DEBUG, "IGD device: %s[%s] | Advertisement Timeout: %d",
				curdevnode->device.friendly_name,
				curdevnode->device.udn,
				curdevnode->device.advr_time_out);
		if (curdevnode->device.advr_time_out <= 0) {
			/* This advertisement has expired, so we should remove the device
			 * from the list */
			if (igd_ctxt->devices == curdevnode)
				igd_ctxt->devices = curdevnode->next;
			else
				prevdevnode->next = curdevnode->next;
			upnp_igd_delete_node(igd_ctxt, curdevnode);
			if (prevdevnode)
				curdevnode = prevdevnode->next;
			else
				curdevnode = igd_ctxt->devices;
		} else {
			if (curdevnode->device.advr_time_out < 2 * incr) {
				/* This advertisement is about to expire, so
				 * send out a search request for this device
				 * UDN to try to renew */
				ret = UpnpSearchAsync(igd_ctxt->upnp_handle, incr, curdevnode->device.udn, igd_ctxt);
				if (ret != UPNP_E_SUCCESS)
					upnp_igd_print(igd_ctxt, UPNP_IGD_ERROR, "Error sending search request for Device UDN: %s -- err = %d",
					     curdevnode->device.udn, ret);
			}
			prevdevnode = curdevnode;
			curdevnode = curdevnode->next;
		}
	}

	ithread_mutex_unlock(&igd_ctxt->devices_mutex);
}
Example #8
0
/********************************************************************************
 * TvCtrlPointRefresh
 *
 * Description: 
 *       Clear the current global device list and issue new search
 *	 requests to build it up again from scratch.
 *
 * Parameters:
 *   None
 *
 ********************************************************************************/
int
Tvctrlpointrefresh( void )
{
    int rc;
    TvCtrlPointRemoveAll(  );
    /*upnp:rootdevice
       Search for all devices of type tvdevice version 1, 
       waiting for up to 5 seconds for the response 
     */
    rc = UpnpSearchAsync( ctrlpt_handle, 5, TvDeviceType, NULL );
    if( UPNP_E_SUCCESS != rc )
    	 {
        printf( "Error sending search request%d", rc );
        return TV_ERROR;
    }
printf("Tvctrlpointrefresh ok\n");
    return TV_SUCCESS;
}
/********************************************************************************
 * WscUPnPCPRefresh
 *
 * Description: 
 *       Clear the current wsc device list and issue new search
 *	 requests to build it up again from scratch.
 *
 * Parameters:
 *   None
 *
 * Return:
 *    Always success
 ********************************************************************************/
int WscUPnPCPRefresh(void)
{
	int rc;

	WscUPnPCPRemoveAll();

	/*
		Search for all devices of type Wsc UPnP Device version 1, 
		waiting for up to 5 seconds for the response 
	*/
	rc = UpnpSearchAsync(WscCPHandle, 5, WscDeviceTypeStr, NULL);
	if (rc != UPNP_E_SUCCESS)
	{
		DBGPRINTF(RT_DBG_ERROR, "Error sending search request%d\n", rc);
		return WSC_SYS_ERROR;
	}

	return WSC_SYS_SUCCESS;
}
Example #10
0
static int Open( vlc_object_t *p_this )
{
    int res;
    services_discovery_t *p_sd = ( services_discovery_t* )p_this;
    services_discovery_sys_t *p_sys  = ( services_discovery_sys_t * )
            calloc( 1, sizeof( services_discovery_sys_t ) );

    if(!(p_sd->p_sys = p_sys))
        return VLC_ENOMEM;

    res = UpnpInit( 0, 0 );
    if( res != UPNP_E_SUCCESS )
    {
        msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );
        free( p_sys );
        return VLC_EGENERIC;
    }

    p_sys->serverList = new MediaServerList( p_sd );
    vlc_mutex_init( &p_sys->callbackLock );

    res = UpnpRegisterClient( Callback, p_sd, &p_sys->clientHandle );
    if( res != UPNP_E_SUCCESS )
    {
        msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );
        Close( (vlc_object_t*) p_sd );
        return VLC_EGENERIC;
    }

    res = UpnpSearchAsync( p_sys->clientHandle, 5,
            MEDIA_SERVER_DEVICE_TYPE, p_sd );

    if( res != UPNP_E_SUCCESS )
    {
        msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );
        Close( (vlc_object_t*) p_sd );
        return VLC_EGENERIC;
    }

    return VLC_SUCCESS;
}
Example #11
0
/********************************************************************************
 * upnp_igd_refresh
 *
 * Description:
 *       Clear the current context device list and issue new search
 *	 requests to build it up again from scratch.
 *
 * Parameters:
 *   igd_ctxt -- The upnp igd context
 *
 ********************************************************************************/
int upnp_igd_refresh(upnp_igd_context* igd_ctxt) {
	int ret;

	ithread_mutex_lock(&igd_ctxt->mutex);
	
	upnp_igd_remove_all(igd_ctxt);

	upnp_igd_print(igd_ctxt, UPNP_IGD_MESSAGE, "IGD client searching...");
	ret = UpnpSearchAsync(igd_ctxt->upnp_handle, 5, IGDDeviceType, igd_ctxt);
	if (UPNP_E_SUCCESS != ret) {
		upnp_igd_print(igd_ctxt, UPNP_IGD_ERROR, "Error sending search request%d", ret);
		ithread_mutex_unlock(&igd_ctxt->mutex);
		return -1;
	}
	
	ithread_mutex_unlock(&igd_ctxt->mutex);

	upnp_context_handle_callbacks(igd_ctxt);
	
	return 0;
}
Example #12
0
/* TODO: create thread to periodically search */
int dial_discover() {
    UpnpSearchAsync(handle, 5, CHROMECAST_DEVICE_TYPE, NULL); 
    return 0;
}
Example #13
0
int wphoto_upnp_handshake(void)
{
	int ret = -1, err;
	char descurl[256];
	const char *desc_xml = "MobileDevDesc.xml";
	struct timespec timer;
	int camera_responded_save;
	char *camera_url_save;
	int pinged_camera;

	ithread_mutex_init(&state_mutex, NULL);
	ithread_cond_init(&state_cond, NULL);
	camera_url = NULL;
	camera_responded = 0;
	err = UpnpInit(NULL, 0);
	if (err != UPNP_E_SUCCESS) {
		upnp_perror("UpnpInit", err);
		goto err_init;
	}
	server_ip = UpnpGetServerIpAddress();
	server_port = UpnpGetServerPort();
	if (init_xml_docs() < 0) {
		perror("init_xml_docs");
		goto err_init;
	}

	printf("address: %s:%d\n", server_ip, server_port);

	snprintf(descurl, sizeof(descurl), "http://%s:%d/%s",
			server_ip, server_port, desc_xml);
	err = web_add_callback("/MobileDevDesc.xml", web_MobileDevDesc, NULL);
	if (err) {
		perror("web_add_callback");
		goto err_init;
	}
	err = web_add_callback("/desc_iml/CameraConnectedMobile.xml",
			web_CameraConnectedMobile, NULL);
	if (err) {
		perror("web_add_callback");
		goto err_init;
	}
	if (web_start() < 0) {
		printf("web_init error\n");
		goto err_init;
	}
	err = UpnpRegisterRootDevice(descurl, upnp_device_event_handler,
			&device_handle, &device_handle);
	if (err != UPNP_E_SUCCESS) {
		upnp_perror("UpnpRegisterRootDevice", err);
		goto err_init;
	}
	err = UpnpRegisterClient(upnp_client_event_handler,
			&client_handle, &client_handle);
	if (err != UPNP_E_SUCCESS) {
		upnp_perror("UpnpRegisterClient", err);
		goto err_register;
	}
	clock_gettime(CLOCK_REALTIME, &timer);
	discovery_timeout = 1;
	camera_responded_save = 0;
	camera_url_save = NULL;
	pinged_camera = 0;
	do {
		int wait_err;

		if (!camera_responded_save) {
			err = UpnpSendAdvertisement(device_handle, 0);
			if (err != UPNP_E_SUCCESS) {
				upnp_perror("UpnpSendAdvertisement", err);
				goto err_register;
			}
			printf("NOTIFY sent\n");
		}
		if (camera_url_save && !pinged_camera)
			if (ping_camera(camera_url_save) == 0)
				pinged_camera = 1;
		timer.tv_sec += ADVERTISEMENT_INTERVAL;
wait:
		ithread_mutex_lock(&state_mutex);
		wait_err = 0;
		while (camera_responded == camera_responded_save &&
				strcmp_null(camera_url, camera_url_save) == 0 &&
				!discovery_timeout && wait_err == 0)
			wait_err = ithread_cond_timedwait(
					&state_cond, &state_mutex, &timer);
		camera_responded_save = camera_responded;
		if (strcmp_null(camera_url, camera_url_save) != 0) {
			free(camera_url_save);
			camera_url_save = strdup(camera_url);
		}
		/*
		 * Once we have the camera url, we stop sending M-SEARCH
		 * requests
		 */
		if (discovery_timeout && !camera_url_save) {
			err = UpnpSearchAsync(client_handle, MSEARCH_INTERVAL,
					CAMERA_SERVICE_NAME, (void*)42);
			if (err != UPNP_E_SUCCESS) {
				upnp_perror("UpnpSearchAsync", err);
				goto err_register;
			}
			printf("M-SEARCH sent\n");
		}
		discovery_timeout = 0;
		ithread_mutex_unlock(&state_mutex);
		if (wait_err != ETIMEDOUT &&
				(!pinged_camera || !camera_responded_save))
			goto wait;
	} while (!pinged_camera || !camera_responded_save);
	return 0;
err_register:
	UpnpUnRegisterRootDevice(device_handle);
err_init:
	UpnpFinish();
	return ret;
}
Example #14
0
/*
 * Initializes UPNP instance.
 */
static int Open( vlc_object_t *p_this )
{
    int i_res;
    services_discovery_t *p_sd = ( services_discovery_t* )p_this;
    services_discovery_sys_t *p_sys  = ( services_discovery_sys_t * )
            calloc( 1, sizeof( services_discovery_sys_t ) );

    if( !( p_sd->p_sys = p_sys ) )
        return VLC_ENOMEM;

#ifdef UPNP_ENABLE_IPV6
    char* psz_miface;
    psz_miface = var_InheritString( p_sd, "miface" );
    msg_Info( p_sd, "Initializing libupnp on '%s' interface", psz_miface );
    i_res = UpnpInit2( psz_miface, 0 );
    free( psz_miface );
#else
    /* If UpnpInit2 isnt available, initialize on first IPv4-capable interface */
    i_res = UpnpInit( 0, 0 );
#endif
    if( i_res != UPNP_E_SUCCESS )
    {
        msg_Err( p_sd, "Initialization failed: %s", UpnpGetErrorMessage( i_res ) );
        free( p_sys );
        return VLC_EGENERIC;
    }

    ixmlRelaxParser( 1 );

    p_sys->p_server_list = new MediaServerList( p_sd );
    vlc_mutex_init( &p_sys->callback_lock );

    /* Register a control point */
    i_res = UpnpRegisterClient( Callback, p_sd, &p_sys->client_handle );
    if( i_res != UPNP_E_SUCCESS )
    {
        msg_Err( p_sd, "Client registration failed: %s", UpnpGetErrorMessage( i_res ) );
        Close( (vlc_object_t*) p_sd );
        return VLC_EGENERIC;
    }

    /* Search for media servers */
    i_res = UpnpSearchAsync( p_sys->client_handle, 5,
            MEDIA_SERVER_DEVICE_TYPE, p_sd );
    if( i_res != UPNP_E_SUCCESS )
    {
        msg_Err( p_sd, "Error sending search request: %s", UpnpGetErrorMessage( i_res ) );
        Close( (vlc_object_t*) p_sd );
        return VLC_EGENERIC;
    }

    /* libupnp does not treat a maximum content length of 0 as unlimited
     * until 64dedf (~ pupnp v1.6.7) and provides no sane way to discriminate
     * between versions */
    if( (i_res = UpnpSetMaxContentLength( INT_MAX )) != UPNP_E_SUCCESS )
    {
        msg_Err( p_sd, "Failed to set maximum content length: %s",
                UpnpGetErrorMessage( i_res ));

        Close( (vlc_object_t*) p_sd );
        return VLC_EGENERIC;
    }

    return VLC_SUCCESS;
}
/********************************************************************************
 * WscUPnPCPHandleEvent
 *
 * Description: 
 *       Handle a UPnP event that was received.  Process the event and update
 *       the appropriate service state table.
 *
 * Parameters:
 *   sid -- The subscription id for the event
 *   eventkey -- The eventkey number for the event
 *   changes -- The DOM document representing the changes
 *
 * Return:
 *   None 
 ********************************************************************************/
void WscUPnPCPHandleEvent(
	IN Upnp_SID sid,
	IN int evntkey,
	IN IXML_Document * changes)
{
	struct upnpDeviceNode *devNode;
	char *inStr = NULL, *pWscU2KMsg = NULL;
	unsigned char *decodeStr = NULL;
	int decodeLen, wscU2KMsgLen;
	unsigned int UPnPDevIP = 0;
	
	devNode = WscDeviceList;
	while (devNode) 
	{
		if(strcmp(devNode->device.services.SID, sid) == 0) 
		{
			devNode->device.timeCount = devNode->device.AdvrTimeOut;
			UPnPDevIP = devNode->device.ipAddr;
			
			DBGPRINTF(RT_DBG_INFO, "Received WscService Event: %d for SID %s\n", evntkey, sid);
			WscStateVarUpdate(devNode, changes);

			inStr = devNode->device.services.StateVarVal[WSC_EVENT_WLANEVENT];
			if (inStr)
			{
#define WSC_EVENT_WLANEVENT_MSG_LEN_MIN		18	// The first byte is the msg type, the next 17 bytes is the MAC address in xx:xx format

				DBGPRINTF(RT_DBG_INFO, "\tWLANEvent=%s!\n", devNode->device.services.StateVarVal[WSC_EVENT_WLANEVENT]);
				decodeLen = ILibBase64Decode((unsigned char *)inStr, strlen(inStr), &decodeStr);

				if((decodeLen > WSC_EVENT_WLANEVENT_MSG_LEN_MIN) && (ioctl_sock >= 0))
				{
					RTMP_WSC_U2KMSG_HDR *msgHdr;
					WscEnvelope *msgEnvelope;
					int msgQIdx = -1;
			 
					
			 		decodeLen -= WSC_EVENT_WLANEVENT_MSG_LEN_MIN;
					
					/* Prepare the msg buffers */
					wscU2KMsgLen = wscU2KMsgCreate(&pWscU2KMsg, (char *)(decodeStr + WSC_EVENT_WLANEVENT_MSG_LEN_MIN), 
													decodeLen, EAP_FRAME_TYPE_WSC);
					if (wscU2KMsgLen == 0)
						goto done;

					/* Prepare the msg envelope */
					if ((msgEnvelope = wscEnvelopeCreate()) == NULL)
						goto done;
					msgEnvelope->callBack = wscCPPutMessage;
			
					/* Lock the msgQ and check if we can get a valid mailbox to insert our request! */
					if (wscMsgQInsert(msgEnvelope, &msgQIdx) != WSC_SYS_SUCCESS)
						goto done;

					// Fill the session ID to the U2KMsg buffer header.
					msgHdr = (RTMP_WSC_U2KMSG_HDR *)pWscU2KMsg;
					msgHdr->envID = msgEnvelope->envID;

					// copy the Addr1 & Addr2
					memcpy(msgHdr->Addr1, HostMacAddr, MAC_ADDR_LEN);
					memcpy(msgHdr->Addr2, &UPnPDevIP, sizeof(unsigned int));

					// Now send the msg to kernel space.
					DBGPRINTF(RT_DBG_INFO, "(%s):Ready to send pWscU2KMsg(len=%d) to kernel by ioctl(%d)!\n", __FUNCTION__, wscU2KMsgLen, ioctl_sock);
					//wsc_hexdump("U2KMsg", pWscU2KMsg, wscU2KMsgLen);
	
					if(wsc_set_oid(RT_OID_WSC_EAPMSG, pWscU2KMsg, wscU2KMsgLen) != 0)
						wscEnvelopeRemove(msgEnvelope, msgQIdx);
				}
			}
			if (devNode->device.services.StateVarVal[WSC_EVENT_APSTATUS] != NULL)
				DBGPRINTF(RT_DBG_INFO, "\tAPStatus=%s!\n", devNode->device.services.StateVarVal[WSC_EVENT_APSTATUS]);
			if (devNode->device.services.StateVarVal[WSC_EVENT_STASTATUS] != NULL)
				DBGPRINTF(RT_DBG_INFO, "\tSTAStatus=%s!\n", devNode->device.services.StateVarVal[WSC_EVENT_STASTATUS]);
			break;
		}
		devNode = devNode->next;
	}
	
done:

}


/********************************************************************************
 * WscUPnPCPHandleSubscribeUpdate
 *
 * Description: 
 *       Handle a UPnP subscription update that was received.  Find the 
 *       service the update belongs to, and update its subscription
 *       timeout.
 *
 * Parameters:
 *   eventURL -- The event URL for the subscription
 *   sid -- The subscription id for the subscription
 *   timeout  -- The new timeout for the subscription
 *
 * Return:
 *    None
 ********************************************************************************/
void WscUPnPCPHandleSubscribeUpdate(
	IN char *eventURL,
	IN Upnp_SID sid,
	IN int timeout)
{
	struct upnpDeviceNode *tmpdevnode;

	tmpdevnode = WscDeviceList;
	while (tmpdevnode) 
	{
		if( strcmp(tmpdevnode->device.services.EventURL, eventURL) == 0) 
		{
			DBGPRINTF(RT_DBG_INFO, "Received WscService Event Renewal for eventURL %s\n", eventURL);
			strcpy(tmpdevnode->device.services.SID, sid);
			break;
		}

		tmpdevnode = tmpdevnode->next;
	}
}



/********************************************************************************
 * WscUPnPCPDeviceHandler
 *
 * Description: 
 *       The callback handler registered with the SDK while registering the Control Point.
 *       This callback funtion detects the type of callback, and passes the request on to 
 *       the appropriate function.
 *
 * Parameters:
 *   EventType -- The type of callback event
 *   Event -- Data structure containing event data
 *   Cookie -- Optional data specified during callback registration
 *
 * Return:
 *    Always zero 
 ********************************************************************************/
int
WscUPnPCPDeviceHandler(
	IN Upnp_EventType EventType,
	IN void *Event,
	IN void *Cookie)
{
    //wsc_PrintEvent( EventType, Event );

	switch (EventType) 
	{
		/*
			SSDP Stuff 
		*/
		case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE:
		case UPNP_DISCOVERY_SEARCH_RESULT:
			{
				struct Upnp_Discovery *d_event = (struct Upnp_Discovery *)Event;
				unsigned int ipAddr = 0;
				if (d_event->ErrCode != UPNP_E_SUCCESS)
				{
					DBGPRINTF(RT_DBG_ERROR, "Error in Discovery Adv Callback -- %d\n", d_event->ErrCode);
				}
				else 
				{
					if (strcmp(d_event->DeviceType, WscDeviceTypeStr) == 0)
					{	//We just need to take care about the WscDeviceTypeStr
						DBGPRINTF(RT_DBG_INFO, "Receive a Advertisement from a WFADevice(URL=%s)\n", d_event->Location);
						if (WscUPnPCPAddDevice(WscDeviceTypeStr, d_event, &ipAddr) == WSC_SYS_SUCCESS)
						{
							WscUPnPCPDumpList(); // Printing the Wsc Device List for debug
							WscUPnPCPSendAction(ipAddr,"GetDeviceInfo", NULL, NULL, 0);
						}
					}
				}
				break;
			}

		case UPNP_DISCOVERY_SEARCH_TIMEOUT:
			// Nothing to do here..
			break;

		case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE:
			{
				struct Upnp_Discovery *d_event = (struct Upnp_Discovery *)Event;

				if (d_event->ErrCode != UPNP_E_SUCCESS)
				{
					DBGPRINTF(RT_DBG_ERROR, "Error in Discovery ByeBye Callback -- %d\n", d_event->ErrCode);
				}
				else
				{
					DBGPRINTF(RT_DBG_INFO, "Received ByeBye for Device: %s\n", d_event->DeviceId);
	                WscUPnPCPRemoveDevice(d_event->DeviceId);
					//Dump it for debug
					WscUPnPCPDumpList();
				}

				break;
			}

		/*
			SOAP Stuff 
		*/
		case UPNP_CONTROL_ACTION_COMPLETE:
			{
				struct Upnp_Action_Complete *a_event = (struct Upnp_Action_Complete *)Event;

				if (a_event->ErrCode != UPNP_E_SUCCESS)
					DBGPRINTF(RT_DBG_ERROR, "Error in  Action Complete Callback -- %d\n", a_event->ErrCode);
				else 
				{
					DBGPRINTF(RT_DBG_INFO, "Get event:UPNP_CONTROL_ACTION_COMPLETE!\n");
					WscUPnPCPHandleActionResponse(a_event);
				}
				break;
			}

		case UPNP_CONTROL_GET_VAR_COMPLETE:
			{
				struct Upnp_State_Var_Complete *sv_event = (struct Upnp_State_Var_Complete *)Event;

				if (sv_event->ErrCode != UPNP_E_SUCCESS)
				{
					DBGPRINTF(RT_DBG_ERROR, "Error in Get Var Complete Callback -- %d\n", sv_event->ErrCode);
                } else {
					WscUPnPCPHandleGetVar(sv_event->CtrlUrl, sv_event->StateVarName, sv_event->CurrentVal);
				}

				break;
			}

		/*
			GENA Stuff 
		*/
		case UPNP_EVENT_RECEIVED:
			{
				struct Upnp_Event *e_event = (struct Upnp_Event *)Event;
				
				DBGPRINTF(RT_DBG_INFO, "Get event:UPNP_EVENT_RECEIVED!\n");
				
				WscUPnPCPHandleEvent(e_event->Sid, e_event->EventKey, e_event->ChangedVariables);
				break;
			}

		case UPNP_EVENT_SUBSCRIBE_COMPLETE:
		case UPNP_EVENT_UNSUBSCRIBE_COMPLETE:
		case UPNP_EVENT_RENEWAL_COMPLETE:
			{
				struct Upnp_Event_Subscribe *es_event = (struct Upnp_Event_Subscribe *)Event;

				if (es_event->ErrCode != UPNP_E_SUCCESS) 
				{
					DBGPRINTF(RT_DBG_ERROR, "Error in Event Subscribe Callback -- %d\n", es_event->ErrCode);
				} else {
					WscUPnPCPHandleSubscribeUpdate(es_event->PublisherUrl, es_event->Sid, es_event->TimeOut);
                }

				break;
			}

		case UPNP_EVENT_AUTORENEWAL_FAILED:
		case UPNP_EVENT_SUBSCRIPTION_EXPIRED:
			{
				int TimeOut = DEF_SUBSCRIPTION_TIMEOUT;
				Upnp_SID newSID;
				int ret;

				struct Upnp_Event_Subscribe *es_event = (struct Upnp_Event_Subscribe *)Event;

				ret = UpnpSubscribe(WscCPHandle, es_event->PublisherUrl, &TimeOut, newSID);

				if (ret == UPNP_E_SUCCESS) 
				{
					DBGPRINTF(RT_DBG_INFO, "Subscribed to EventURL with SID=%s\n", newSID);
					WscUPnPCPHandleSubscribeUpdate(es_event->PublisherUrl, newSID, TimeOut);
				} else {
					DBGPRINTF(RT_DBG_ERROR, "Error Subscribing to EventURL -- %d\n", ret);
				}
				break;
			}

			/*
				Ignore these cases, since this is not a device 
			*/
		case UPNP_EVENT_SUBSCRIPTION_REQUEST:
		case UPNP_CONTROL_GET_VAR_REQUEST:
		case UPNP_CONTROL_ACTION_REQUEST:
			break;
	}

	return 0;
}


/********************************************************************************
 * WscUPnPCPGetVar
 *
 * Description: 
 *       Send a GetVar request to the specified service of a device.
 *
 * Parameters:
 *   ipAddr -- The IP address of the device.
 *   varname -- The name of the variable to request.
 *
 * Return:
 *    UPNP_E_SUCCESS - if success
 *    WSC_SYS_ERROR  - if failure
 ********************************************************************************/
int
WscUPnPCPGetVar(
	IN uint32 ipAddr,
	IN char *varname)
{
	struct upnpDeviceNode *devnode;
	int rc;

	rc = WscUPnPCPGetDevice(ipAddr, &devnode);

	if (rc == WSC_SYS_SUCCESS)
	{
		rc = UpnpGetServiceVarStatusAsync( WscCPHandle, devnode->device.services.ControlURL,
                                           varname, WscUPnPCPDeviceHandler, NULL);
		if( rc != UPNP_E_SUCCESS )
		{
			DBGPRINTF(RT_DBG_ERROR, "Error in UpnpGetServiceVarStatusAsync -- %d\n", rc);
			rc = WSC_SYS_ERROR;
		}
	}

	return rc;
}


#if 0
int WscUPnPCPGetVarSampleCode(
	IN int devnum)
{
    return WscUPnPCPGetVar(devnum, "Power");
}
#endif


/********************************************************************************
 * WscUPnPCPVerifyTimeouts
 *
 * Description: 
 *       Checks the advertisement each device in the global device list. 
 *		 If an advertisement expires, the device is removed from the list.
 *		 If an advertisement is about to expire, a search request is sent 
 *		 for that device.  
 *
 * Parameters:
 *    incr -- The increment to subtract from the timeouts each time the
 *            function is called.
 *
 * Return:
 *    None
 ********************************************************************************/
void WscUPnPCPVerifyTimeouts(int incr)
{
	struct upnpDeviceNode *prevdevnode, *curdevnode;
	int ret, timeLeft;

	prevdevnode = NULL;
	curdevnode = WscDeviceList;

	while (curdevnode)
	{
		curdevnode->device.timeCount += incr;
		timeLeft = curdevnode->device.AdvrTimeOut - curdevnode->device.timeCount;
		
		if (timeLeft <= 0)
		{
			/* This advertisement has expired, so we should remove the device from the list */
			if (WscDeviceList == curdevnode)
				WscDeviceList = curdevnode->next;
			else
				prevdevnode->next = curdevnode->next;
			DBGPRINTF(RT_DBG_INFO, "%s(), delete the node(ipAddr=0x%08x)!\n", __FUNCTION__, curdevnode->device.ipAddr);
			WscUPnPCPDeleteNode(curdevnode);
			curdevnode = prevdevnode ? prevdevnode->next : WscDeviceList;
		} else {
			if (timeLeft < 3 * incr)
			{
				/*
					This advertisement is about to expire, so send out a search request for this 
					device UDN to try to renew
				*/
				ret = UpnpSearchAsync(WscCPHandle, incr, curdevnode->device.UDN, NULL);
				if (ret != UPNP_E_SUCCESS)
					DBGPRINTF(RT_DBG_ERROR, "Err sending SearchReq for Device UDN: %s -- err = %d\n", curdevnode->device.UDN, ret);
			}

			prevdevnode = curdevnode;
			curdevnode = curdevnode->next;
		}

	}
}


/********************************************************************************
 * WscUPnPCPHouseKeep
 *
 * Description: 
 *       Function that runs in its own thread and monitors advertisement
 *       and subscription timeouts for devices in the global device list.
 *
 * Parameters:
 *    None
 *  
 * Return:
 *    UPNP_E_SUCCESS - if success
 *    WSC_SYS_ERROR  - if failure
 ********************************************************************************/
void *WscUPnPCPHouseKeep(void *args)
{
	int incr = 30;              // how often to verify the timeouts, in seconds

	while(1)
	{
		sleep(incr);
		WscUPnPCPVerifyTimeouts(incr);
	}
}