int Exp);
如upnp.h的注释,此函数是device广告自己的接口。第一个参数是deviceHandle,第二个参数是有效期,秒为单位。
具体实现如下:
int UpnpSendAdvertisement(UpnpDevice_Handle Hnd, int Exp)
{
return UpnpSendAdvertisementLowPower (Hnd, Exp, -1, -1, -1);
}
int UpnpSendAdvertisementLowPower(UpnpDevice_Handle Hnd, int Exp,
int PowerState, int SleepPeriod, int RegistrationState)
{
struct Handle_Info *SInfo = NULL;
int retVal = 0,*ptrMx;
upnp_timeout *adEvent;
ThreadPoolJob job;
........
HandleLock();
switch( GetHandleInfo( Hnd, &SInfo ) ) {
case HND_DEVICE:
break;
default:
HandleUnlock();
return UPNP_E_INVALID_HANDLE;
}
if( Exp < 1 )
Exp = DEFAULT_MAXAGE;
SInfo->MaxAge = Exp;
SInfo->PowerState = PowerState;
if( SleepPeriod < 0 )
SleepPeriod = -1;
SInfo->SleepPeriod = SleepPeriod;
SInfo->RegistrationState = RegistrationState;
HandleUnlock();
retVal = AdvertiseAndReply( 1, Hnd, ( enum SsdpSearchType )0, /*sendto 239.255.255.250:1900地址发送ssdp:alive消息,通过hnd带上deviceinfo,具体可以参考
( struct sockaddr * )NULL, ( char * )NULL, AdvertiseAndReply实现*/
( char * )NULL, ( char * )NULL, Exp );
if( retVal != UPNP_E_SUCCESS )
return retVal;
ptrMx = ( int * )malloc( sizeof( int ) );
if( ptrMx == NULL )
return UPNP_E_OUTOF_MEMORY;
adEvent = ( upnp_timeout * ) malloc( sizeof( upnp_timeout ) );
*ptrMx = Exp; /*从这里看到的信息是:讲hnd跟exp存到了adEvent里面。用于AutoAdvertise里面使用*/
adEvent->handle = Hnd; /*AutoAdvertise顾名思义,就是自动发广告的意思。而AutoAdvertise就是UpnpSendAdvertisement*/
adEvent->Event = ptrMx;
#ifdef SSDP_PACKET_DISTRIBUTE /*此处从宏注释中可以看出,意思是为了ssdp packets顺利到达ctrl point*/
TPJobInit( &job, ( start_routine ) AutoAdvertise, adEvent );
TPJobSetFreeFunction( &job, ( free_routine ) free_upnp_timeout );
TPJobSetPriority( &job, MED_PRIORITY );
if( ( retVal = TimerThreadSchedule( &gTimerThread,
( ( Exp / 2 ) -
( AUTO_ADVERTISEMENT_TIME ) ),
REL_SEC, &job, SHORT_TERM,
&( adEvent->eventId ) ) )
#else
........//省略
#endif
HandleUnlock();
return retVal;
}
void AutoAdvertise(void *input)
{
upnp_timeout *event = (upnp_timeout *)input;
UpnpSendAdvertisement(event->handle, *((int *)event->Event));
free_upnp_timeout(event);
}
好的,现在大概思路非常清晰了。
1 UpnpSendAdvertisement通过AdvertiseAndReply往239.255.255.250:1900 地址发送ssdp:alive为messageType的discovery消息。
2 UpnpSendAdvertisement为了增加ssdp消息到达ctrl point的可能性,以及循环发ssdp消息,嵌套调用了AutoAdvertise,即UpnpSendAdvertisement。
3 以默认的100s exp有效期为参考,整体的时间点划分是:发布一个ssdp packets,exp/2-30=20s后再发布一条,然后再20s发布一条。。。。,即以exp/2-30的周期发送。
注意:如果exp小于62 相当于周期为0,即不停的发。。。。可以看如下意思是:根据abs绝对时间轴来run event动作。time时间最小(早)的先执行。
tempNode = ListHead( &timer->eventQ );
/* add job to Q. Q is ordered by eventTime with the head of the Q being
* the next event. */
while( tempNode != NULL ) {
temp = ( TimerEvent * ) tempNode->item;
if( temp->eventTime >= timeout ) {
if (ListAddBefore( &timer->eventQ, newEvent, tempNode))
rc = 0;
found = 1;
break;
}
tempNode = ListNext( &timer->eventQ, tempNode );
}