void SSDPCache::Add( const QString &sURI, const QString &sUSN, const QString &sLocation, long sExpiresInSecs ) { // -------------------------------------------------------------- // Calculate when this cache entry should expire. // -------------------------------------------------------------- TaskTime ttExpires; gettimeofday ( (&ttExpires), NULL ); AddSecondsToTaskTime( ttExpires, sExpiresInSecs ); // -------------------------------------------------------------- // Get a Pointer to a Entries QDict... (Create if not found) // -------------------------------------------------------------- SSDPCacheEntries *pEntries = Find( sURI ); if (pEntries == NULL) { pEntries = new SSDPCacheEntries(); pEntries->AddRef(); m_cache.insert( sURI, pEntries ); } pEntries->AddRef(); // -------------------------------------------------------------- // See if the Entries Collection contains our USN... (Create if not found) // -------------------------------------------------------------- DeviceLocation *pEntry = pEntries->Find( sUSN ); if (pEntry == NULL) { pEntry = new DeviceLocation( sURI, sUSN, sLocation, ttExpires ); Lock(); pEntries->Insert( sUSN, pEntry ); Unlock(); NotifyAdd( sURI, sUSN, sLocation ); } else { pEntry->AddRef(); pEntry->m_sLocation = sLocation; pEntry->m_ttExpires = ttExpires; pEntry->Release(); } pEntries->Release(); }
int SSDPCache::RemoveStale() { int nCount = 0; TaskTime ttNow; QStringList lstKeys; gettimeofday( (&ttNow), NULL ); Lock(); // ---------------------------------------------------------------------- // Iterate through all Type URI's and build list of stale entries keys // ---------------------------------------------------------------------- for (SSDPCacheEntriesMap::Iterator it = m_cache.begin(); it != m_cache.end(); ++it ) { SSDPCacheEntries *pEntries = *it; if (pEntries != NULL) { pEntries->AddRef(); nCount += pEntries->RemoveStale( ttNow ); if (pEntries->Count() == 0) lstKeys.append( it.key() ); pEntries->Release(); } } Unlock(); nCount = lstKeys.count(); // ---------------------------------------------------------------------- // Iterate through list of keys and remove them. // (This avoids issues when removing from a QMap while iterating it) // ---------------------------------------------------------------------- for ( QStringList::Iterator itKey = lstKeys.begin(); itKey != lstKeys.end(); ++itKey ) { SSDPCacheEntriesMap::iterator it = m_cache.find( *itKey ); if (it == m_cache.end()) continue; if (*it) { (*it)->Release(); m_cache.erase(it); } } return nCount; }
DeviceLocation *SSDPCache::Find( const QString &sURI, const QString &sUSN ) { DeviceLocation *pEntry = NULL; SSDPCacheEntries *pEntries = Find( sURI ); if (pEntries != NULL) { pEntries->AddRef(); pEntry = pEntries->Find( sUSN ); pEntries->Release(); } return pEntry; }
void BackendSelection::Init(void) { EntryMap::Iterator it; EntryMap ourMap; DeviceLocation *pDevLoc; SSDPCacheEntries *pEntries = SSDPCache::Instance()->Find( gBackendURI ); if (!pEntries) { VERBOSE(VB_GENERAL, "Found zero backends, bailing"); return; } pEntries->AddRef(); pEntries->Lock(); EntryMap *pMap = pEntries->GetEntryMap(); for (it = pMap->begin(); it != pMap->end(); ++it) { pDevLoc = (DeviceLocation *)*it; if (!pDevLoc) continue; pDevLoc->AddRef(); ourMap.insert(pDevLoc->m_sUSN, pDevLoc); } pEntries->Unlock(); pEntries->Release(); for (it = ourMap.begin(); it != ourMap.end(); ++it) { pDevLoc = (DeviceLocation *)*it; AddItem(pDevLoc); // this does a Release() } }
void SSDPCache::Remove( const QString &sURI, const QString &sUSN ) { Lock(); // -------------------------------------------------------------- // Get a Pointer to a Entries QDict... (Create if not found) // -------------------------------------------------------------- SSDPCacheEntriesMap::Iterator it = m_cache.find( sURI ); if (it != m_cache.end()) { SSDPCacheEntries *pEntries = *it; if (pEntries != NULL) { pEntries->AddRef(); pEntries->Remove( sUSN ); if (pEntries->Count() == 0) { pEntries->Release(); m_cache.erase(it); } pEntries->Release(); } } Unlock(); // -=>TODO: // Should this only by notified if we actually had any entry removed? NotifyRemove( sURI, sUSN ); }
/** * If there is only a single UPnP backend, use it. * * This does <i>not</i> prompt for PIN entry. If the backend requires one, * it will fail, and the caller needs to put up a UI to ask for one. */ int MythContextPrivate::UPnPautoconf(const int milliSeconds) { SSDPCacheEntries *backends = NULL; int count; QString loc = "UPnPautoconf() - "; QTime timer; SSDP::Instance()->PerformSearch( gBackendURI ); for (timer.start(); timer.elapsed() < milliSeconds; usleep(25000)) { backends = SSDP::Instance()->Find( gBackendURI ); if (backends) { backends->AddRef(); break; } putchar('.'); } putchar('\n'); if (!backends) { VERBOSE(VB_GENERAL, loc + "No UPnP backends found"); return 0; } count = backends->Count(); switch (count) { case 0: VERBOSE(VB_IMPORTANT, loc + "No UPnP backends found, but SSDP::Find() not NULL!"); break; case 1: VERBOSE(VB_GENERAL, loc + "Found one UPnP backend"); break; default: VERBOSE(VB_GENERAL, (loc + "More than one UPnP backend found (%1)").arg(count)); } if (count != 1) { backends->Release(); return count; } // Get this backend's location: backends->Lock(); DeviceLocation *BE = *(backends->GetEntryMap()->begin()); backends->Unlock(); backends->Release(); // We don't actually know the backend's access PIN, so this will // only work for ones that have PIN access disabled (i.e. 0000) if (UPnPconnect(BE, QString::null)) return 1; return -1; // Try to force chooser & PIN }