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; */ }
/* * 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; }
/* * 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; }
/******************************************************************************** * 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 ); }
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; }
/******************************************************************************** * 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; }
/******************************************************************************** * 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); }
/******************************************************************************** * 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; }
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; }
/******************************************************************************** * 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; }
/* TODO: create thread to periodically search */ int dial_discover() { UpnpSearchAsync(handle, 5, CHROMECAST_DEVICE_TYPE, NULL); return 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; }
/* * 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); } }