📄 cache.cpp
字号:
is running, skip remove!", CacheEntry);
}
} else
{
TraceTag(ttidSsdpCache, "Byebye for %x which is not current earliest, just remove", CacheEntry);
RemoveEntryWithNotification(CacheEntry, pSsdpRequest);
}
}
else
{
// alive or search result, cache list owns the memory in SsdpRequest if updated
if (CacheEntry != pCacheEntryFirst)
{
bRetVal = UpdateCacheEntry(CacheEntry, pSsdpRequest);
} else
{
if (CTEStopTimer(&timerCleanup))
{
bRetVal = UpdateCacheEntry(CacheEntry, pSsdpRequest);
StartCacheCleanupTimer();
} else
{
// Too late, the timer has fired.
// The current entry will be removed by timer proc.
// Insert a new one.
found = FALSE;
break;
}
}
}
#ifdef DBG
PrintListCache();
#endif // DBG
break;
}
}
if (!found && !IsByebye && IsSubscribed)
{
PSSDP_CACHE_ENTRY CacheEntry = CreateCacheEntryFromRequest(pSsdpRequest,0);
if (CacheEntry != NULL)
{
AddToListCache(CacheEntry);
TraceTag(ttidSsdpCache, "Created cache entry %x", CacheEntry);
bRetVal = TRUE;
#ifdef DBG
PrintListCache();
#endif // DBG
}
else
{
TraceTag(ttidSsdpCache, "Couldn't create cache entry");
}
}
LeaveCriticalSection(&CSListCache);
return bRetVal;
}
VOID PrintCacheEntry(SSDP_CACHE_ENTRY *CacheEntry)
{
CHAR szBuf[BUF_SIZE];
TraceTag(ttidSsdpCache, "----- SSDP Cache Entry %x-----",CacheEntry);
FileTimeToString(FILETIME_FROM_ULONGLONG(CacheEntry->ExpireTime), szBuf, BUF_SIZE);
TraceTag(ttidSsdpCache, "Expired ? : %d", CacheEntryExpired(CacheEntry));
TraceTag(ttidSsdpCache, "Expire Time is %s", szBuf);
PrintSsdpRequest(&CacheEntry->SsdpRequest);
}
VOID PrintListCache()
{
PLIST_ENTRY p;
LIST_ENTRY *pListHead = &listCache;
TraceTag(ttidSsdpCache, "----- SSDP Cache List -----");
EnterCriticalSection(&CSListCache);
for (p = pListHead->Flink; p != pListHead; p = p->Flink)
{
SSDP_CACHE_ENTRY *CacheEntry;
CacheEntry = CONTAINING_RECORD (p, SSDP_CACHE_ENTRY, linkage);
PrintCacheEntry(CacheEntry);
}
LeaveCriticalSection(&CSListCache);
}
BOOL WriteCacheEntryToFile(HANDLE CacheFile, PSSDP_CACHE_ENTRY CacheEntry)
{
CHAR *Buffer = NULL;
DWORD BufferSize = 0;
DWORD BytesWritten = 0;
if(!ComposeSsdpRequest(&CacheEntry->SsdpRequest, &Buffer))
{
TraceTag(ttidSsdpCache, "----- ComposeSsdpRequest failed");
return FALSE;
}
BufferSize = strlen(Buffer) + 1;
// Write the absolute expire time to file.
WriteFile(CacheFile, (CHAR *) &BufferSize, sizeof(INT), &BytesWritten, NULL);
if (BytesWritten != sizeof(INT))
{
TraceTag(ttidSsdpCache, "----- Write size failed. %d written, should be "
"%d -----", BytesWritten, BufferSize);
free(Buffer);
return FALSE;
}
WriteFile(CacheFile, Buffer, BufferSize, &BytesWritten, NULL);
free(Buffer);
if (BufferSize != BytesWritten)
{
TraceTag(ttidSsdpCache, "----- Write failed. %d written, should "
"be %d -----", BytesWritten, BufferSize);
return FALSE;
}
WriteFile(CacheFile, (CHAR *) &CacheEntry->ExpireTime,
sizeof(ULONGLONG), &BytesWritten, NULL);
if (BytesWritten != sizeof(ULONGLONG))
{
TraceTag(ttidSsdpCache, "----- Write Expire time failed. %d written, should be "
"%d -----", BytesWritten, BufferSize);
return FALSE;
}
return TRUE;
}
VOID ReadCacheFileToList()
{
HANDLE CacheFile;
DWORD EntrySize;
DWORD BytesRead = 0;
TCHAR CacheFilePath[BUF_SIZE];
TraceTag(ttidSsdpCache, "----- Reading SSDP Cache File -----");
#ifdef UNDER_CE
memcpy(CacheFilePath,g_szWinDir,sizeof(g_szWinDir));
#else
GetEnvironmentVariable(g_szSystemDir, CacheFilePath, BUF_SIZE);
#endif
lstrcat(CacheFilePath, g_szCacheFileName);
CacheFile = CreateFile(CacheFilePath, GENERIC_READ, 0, NULL,
OPEN_EXISTING, 0, NULL);
if (CacheFile == INVALID_HANDLE_VALUE)
{
TraceTag(ttidSsdpCache, "Failed to open cache file, error (%d).",
GetLastError());
// To-Do: Event Log.
return;
}
while (ReadFile(CacheFile, (CHAR *) &EntrySize, sizeof(INT),
&BytesRead, NULL) && BytesRead > 0)
{
CHAR *Buffer;
SSDP_REQUEST SsdpRequest;
ULONGLONG ExpireTime;
PSSDP_CACHE_ENTRY CacheEntry;
BOOL bOK;
Assert(EntrySize > 0);
// Should terminate with '\0'
Buffer = (CHAR *) malloc(sizeof(CHAR) * EntrySize);
if(!Buffer)
{
TraceTag(ttidSsdpCache, "%s: OOM allocating Buffer.", __FUNCTION__);
break;
}
bOK = ReadFile(CacheFile, Buffer, EntrySize, &BytesRead, NULL);
if (!bOK || BytesRead != EntrySize)
{
TraceTag(ttidSsdpCache, "Need %d, read %d, error %d.", EntrySize,
BytesRead, GetLastError());
return;
}
Assert(Buffer[EntrySize-1] == '\0');
bOK = ReadFile(CacheFile, (CHAR *) &ExpireTime, sizeof(ULONGLONG),
&BytesRead, NULL);
if (!bOK || BytesRead != sizeof(ULONGLONG))
{
TraceTag(ttidSsdpCache, "Need %d, read %d, error %d.", sizeof(ULONGLONG),
BytesRead, GetLastError());
return;
}
InitializeSsdpRequest(&SsdpRequest);
ParseHeaders(Buffer, &SsdpRequest);
CacheEntry = CreateCacheEntryFromRequest(&SsdpRequest,ExpireTime);
if (CacheEntry != NULL && !CacheEntryExpired(CacheEntry))
{
AddToListCache(CacheEntry);
TraceTag(ttidSsdpCache, "Created cache entry %x", CacheEntry);
}
else
{
TraceTag(ttidSsdpCache, "Couldn't create cache entry");
FreeSsdpRequest(&SsdpRequest);
}
if(Buffer)
free(Buffer);
}
CloseHandle(CacheFile);
}
VOID WriteListCacheToFile()
{
PLIST_ENTRY p;
LIST_ENTRY *pListHead = &listCache;
HANDLE CacheFile;
TCHAR CacheFilePath[BUF_SIZE];
TraceTag(ttidSsdpCache, "----- Writing SSDP Cache List to File -----");
#ifdef UNDER_CE
memcpy(CacheFilePath,g_szWinDir,sizeof(g_szWinDir));
#else
GetEnvironmentVariable(g_szSystemDir, CacheFilePath, BUF_SIZE);
#endif
lstrcat(CacheFilePath, g_szCacheFileName);
CacheFile = CreateFile(CacheFilePath, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, 0, NULL);
if (CacheFile == INVALID_HANDLE_VALUE)
{
TraceTag(ttidSsdpCache, "Failed to open file to write the cache. (%d)",
GetLastError());
// To-Do: Event Log.
return;
}
EnterCriticalSection(&CSListCache);
for (p = pListHead->Flink; p != pListHead; p = p->Flink)
{
SSDP_CACHE_ENTRY *CacheEntry;
CacheEntry = CONTAINING_RECORD (p, SSDP_CACHE_ENTRY, linkage);
WriteCacheEntryToFile(CacheFile, CacheEntry);
}
LeaveCriticalSection(&CSListCache);
CloseHandle(CacheFile);
}
BOOL CacheEntryExpired(SSDP_CACHE_ENTRY *CacheEntry)
{
FILETIME TempTime;
ULONGLONG CurrentTime;
#ifdef DBG
CHAR szBuf[BUF_SIZE];
#endif // DBG
GetSystemTimeAsFileTime(&TempTime);
// FILETIME is in 100 nano seconds, max-age is in seconds.
CurrentTime = ULONGLONG_FROM_FILETIME(TempTime);
#ifdef DBG
FileTimeToString(TempTime, szBuf, BUF_SIZE);
TraceTag(ttidSsdpCache, "Current Time is %s", szBuf);
FileTimeToString(FILETIME_FROM_ULONGLONG(CacheEntry->ExpireTime), szBuf, BUF_SIZE);
TraceTag(ttidSsdpCache, "Expire Time is %s", szBuf);
#endif // DBG
if (CurrentTime < CacheEntry->ExpireTime)
{
return FALSE;
}
else
{
return TRUE;
}
}
INT SearchListCache(CHAR *szType, SSDP_MESSAGE ***svcList)
{
LIST_ENTRY *pListHead = &listCache;
PLIST_ENTRY p;
SSDP_MESSAGE **pSsdpMessageList = NULL;
INT nHits = 0;
EnterCriticalSection(&CSListCache);
TraceTag(ttidSsdpCache, "Searching cache list for %s", szType);
// First scan cache to calculate number of matches
p = pListHead->Flink;
while (p != pListHead)
{
SSDP_CACHE_ENTRY *CacheEntry;
CacheEntry = CONTAINING_RECORD (p, SSDP_CACHE_ENTRY, linkage);
p = p->Flink;
if (CacheEntryExpired(CacheEntry))
{
TraceTag(ttidSsdpCache, " !!!!! WARNING !!!!!! : Cache entry 0x%08X has expired. Continue to the next one.",
CacheEntry);
continue;
}
// To-Do: Should this be case insensitive?
if ((strcmp(szType, "ssdp:all") == 0) ||
(CacheEntry->SsdpRequest.Headers[SSDP_NT] != NULL &&
strcmp(CacheEntry->SsdpRequest.Headers[SSDP_NT], szType) == 0) ||
(CacheEntry->SsdpRequest.Headers[SSDP_ST] != NULL &&
strcmp(CacheEntry->SsdpRequest.Headers[SSDP_ST], szType) == 0))
{
nHits++;
}
}
if (nHits)
{
// allocate memory
pSsdpMessageList = (PSSDP_MESSAGE *)malloc(sizeof(PSSDP_MESSAGE) * nHits);
nHits = 0;
if (pSsdpMessageList)
{
// Now scan cache to copy the matched contents
p = pListHead->Flink;
while (p != pListHead)
{
SSDP_CACHE_ENTRY *CacheEntry;
CacheEntry = CONTAINING_RECORD (p, SSDP_CACHE_ENTRY, linkage);
p = p->Flink;
if (CacheEntryExpired(CacheEntry))
{
TraceTag(ttidSsdpCache, " !!!!! WARNING !!!!!! : Cache entry 0x%08X has expired. Continue to the next one.",
CacheEntry);
continue;
}
// To-Do: Should this be case insensitive?
if ((strcmp(szType, "ssdp:all") == 0) ||
(CacheEntry->SsdpRequest.Headers[SSDP_NT] != NULL &&
strcmp(CacheEntry->SsdpRequest.Headers[SSDP_NT], szType) == 0) ||
(CacheEntry->SsdpRequest.Headers[SSDP_ST] != NULL &&
strcmp(CacheEntry->SsdpRequest.Headers[SSDP_ST], szType) == 0))
{
pSsdpMessageList[nHits] = InitializeSsdpMessageFromRequest(&CacheEntry->SsdpRequest);
if (!pSsdpMessageList[nHits])
break; // out of memory
++nHits;
}
}
}
}
*svcList = pSsdpMessageList;
LeaveCriticalSection(&CSListCache);
return nHits;
}
void FreeSsdpMessageList(SSDP_MESSAGE **pSsdpMessageList, int nEntries)
{
Assert(pSsdpMessageList);
int i;
for (i=0; i < nEntries;i++)
{
if (pSsdpMessageList[i])
FreeSsdpMessage(pSsdpMessageList[i]);
}
free(pSsdpMessageList);
}
VOID FileTimeToString(FILETIME FileTime, CHAR *szBuf, INT BufSize)
{
SYSTEMTIME SystemTime;
INT Size;
FileTimeToLocalFileTime(&FileTime, &FileTime);
FileTimeToSystemTime(&FileTime,&SystemTime);
#ifdef UNDER_CE
WCHAR wszTemp[128];
Size=GetDateFormatW(LOCALE_SYSTEM_DEFAULT, 0, &SystemTime, NULL,
wszTemp, min(sizeof(wszTemp)/sizeof(WCHAR),BufSize-1) );
wcstombs(szBuf,wszTemp,Size);
szBuf[Size-1] = ' ';
szBuf += Size;
Size= GetTimeFormatW(LOCALE_SYSTEM_DEFAULT, 0, &SystemTime, NULL,
wszTemp, min(sizeof(wszTemp)/sizeof(WCHAR),BufSize-Size));
wcstombs(szBuf, wszTemp, Size);
#else
Size = GetDateFormatA(LOCALE_SYSTEM_DEFAULT, 0, &SystemTime, NULL,
szBuf, BufSize-1 );
szBuf[Size-1] = ' ';
GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &SystemTime, NULL,
szBuf+Size, BufSize-Size);
#endif
}
VOID InitializeSsdpRequestFromMessage(
PSSDP_REQUEST pSsdpRequest,
const SSDP_MESSAGE *pSsdpMessage)
{
memset(pSsdpRequest,0, sizeof(SSDP_REQUEST));
pSsdpRequest->Method = SSDP_NOTIFY;
pSsdpRequest->Headers[SSDP_NT] = SsdpDup(pSsdpMessage->szType);
pSsdpRequest->Headers[SSDP_LOCATION] = SsdpDup(pSsdpMessage->szLocHeader);
pSsdpRequest->Headers[SSDP_USN] = SsdpDup(pSsdpMessage->szUSN);
if ((int)(pSsdpMessage->iLifeTime) >= 0
&& (pSsdpRequest->Headers[SSDP_CACHECONTROL] = (LPSTR)SsdpAlloc(64)))
{
sprintf(pSsdpRequest->Headers[SSDP_CACHECONTROL],"max-age=%d", pSsdpMessage->iLifeTime);
}
}
// Public APIs
VOID _UpdateCache(PSSDP_MESSAGE pSsdpMessage)
{
SSDP_REQUEST SsdpRequest;
InitializeSsdpRequestFromMessage(&SsdpRequest, pSsdpMessage);
if (UpdateListCache(&SsdpRequest, TRUE) == FALSE)
{
FreeSsdpRequest(&SsdpRequest);
}
}
//+---------------------------------------------------------------------------
//
// Function: CleanupCache
//
// Purpose: Public API to clean up SSDP cache
//
BOOL WINAPI _CleanupCache()
{
BOOL fResult = TRUE;
if (cInitialized == 0)
{
SetLastError(ERROR_NOT_READY);
return FALSE;
}
CleanupListCache();
TraceResult("CleanupCache", fResult);
return fResult;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -