#include "CRefTable.h"
#include "CLog.h"
#define DSSERVERTCP 1
#include "DSNetworkUtilities.h"
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/sysctl.h> // for struct kinfo_proc and sysctl()
#include <syslog.h> // for syslog()
extern dsBool gLogAPICalls;
extern uInt32 gDaemonIPAddress;
CRefTable::CRefTable ( RefDeallocateProc *deallocProc )
{
CFNumberRef aPIDCount = 0;
CFStringRef aPIDString = 0;
CFStringRef anIPString = 0;
CFMutableArrayRef aClientPIDArray;
uInt32 aCount = 0;
CFMutableDictionaryRef aPIDDict = 0;
fSunsetTime = time( nil);
fClientPIDList = nil;
fClientIPList = nil;
fRefCleanUpEntriesHead = nil;
fRefCleanUpEntriesTail = nil;
fClientPIDListLock = new DSMutexSemaphore();
if (fClientPIDListLock != nil )
{
fClientPIDListLock->Wait();
if (fClientIPList == nil)
{
fClientIPList = CFDictionaryCreateMutable( kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
{
fClientPIDList = CFDictionaryCreateMutable( kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
aClientPIDArray = CFArrayCreateMutable( kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks);
aPIDString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), getpid());
aPIDDict = CFDictionaryCreateMutable( kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
aPIDCount = CFNumberCreate(kCFAllocatorDefault,kCFNumberIntType,&aCount);
CFDictionarySetValue( aPIDDict, CFSTR("RefCount"), aPIDCount );
CFDictionarySetValue( fClientPIDList, aPIDString, aPIDDict );
CFArrayAppendValue(aClientPIDArray, aPIDString);
CFDictionarySetValue( fClientPIDList, CFSTR("ClientPIDArray"), aClientPIDArray );
CFRelease(aPIDCount);
CFRelease(aPIDDict);
CFRelease(aClientPIDArray);
CFRelease(aPIDString);
}
anIPString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), gDaemonIPAddress);
CFDictionarySetValue( fClientIPList, anIPString, fClientPIDList );
CFRelease(anIPString);
}
fClientPIDListLock->Signal();
}
fTableCount = 0;
::memset( fRefTables, 0, sizeof( fRefTables ) );
fDeallocProc = deallocProc;
}
CRefTable::~CRefTable ( void )
{
uInt32 i = 1;
uInt32 j = 1;
for ( i = 1; i <= kMaxTables; i++ ) {
if ( fRefTables[ i ] != nil )
{
for (j=0; j< kMaxTableItems; j++)
{
if (fRefTables[ i ]->fTableData[j] != nil)
{
free(fRefTables[ i ]->fTableData[j]);
fRefTables[ i ]->fTableData[j] = nil;
}
}
free( fRefTables[ i ] ); fRefTables[ i ] = nil;
}
}
if (fClientPIDListLock != nil)
{
fClientPIDListLock->Wait();
if (fClientIPList != nil)
{
CFRelease(fClientIPList);
fClientIPList = 0;
}
fClientPIDListLock->Signal();
delete(fClientPIDListLock);
fClientPIDListLock = nil;
}
}
void CRefTable::Lock ( )
{
fTableMutex.Wait();
}
void CRefTable::Unlock ( )
{
fTableMutex.Signal();
}
tDirStatus CRefTable::VerifyReference ( tDirReference inDirRef,
uInt32 inType,
CServerPlugin **outPlugin,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSNoErr;
sRefEntry *refData = nil;
sPIDInfo *pPIDInfo = nil;
siResult = GetReference( inDirRef, &refData );
if ( siResult == eDSNoErr )
{
if ( refData->fType != inType )
{
siResult = eDSInvalidRefType;
}
else
{
siResult = eDSInvalidRefType;
if ( (refData->fPID == inPID) && (refData->fIPAddress == inIPAddress) )
{
siResult = eDSNoErr;
}
else
{
pPIDInfo = refData->fChildPID;
while ( (pPIDInfo != nil) && (siResult != eDSNoErr) )
{
if ( (pPIDInfo->fPID == inPID) && (pPIDInfo->fIPAddress == inIPAddress) )
{
siResult = eDSNoErr;
}
pPIDInfo = pPIDInfo->fNext;
}
}
if (siResult == eDSNoErr)
{
if ( outPlugin != nil )
{
*outPlugin = refData->fPlugin;
}
}
}
}
return( siResult );
}
tDirStatus CRefTable::VerifyDirRef ( tDirReference inDirRef,
CServerPlugin **outPlugin,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->VerifyReference( inDirRef, eDirectoryRefType, outPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::VerifyNodeRef ( tDirNodeReference inDirNodeRef,
CServerPlugin **outPlugin,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->VerifyReference( inDirNodeRef, eNodeRefType, outPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::VerifyRecordRef ( tRecordReference inRecordRef,
CServerPlugin **outPlugin,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->VerifyReference( inRecordRef, eRecordRefType, outPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::VerifyAttrListRef ( tAttributeListRef inAttributeListRef,
CServerPlugin **outPlugin,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->VerifyReference( inAttributeListRef, eAttrListRefType, outPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::VerifyAttrValueRef ( tAttributeValueListRef inAttributeValueListRef,
CServerPlugin **outPlugin,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->VerifyReference( inAttributeValueListRef, eAttrValueListRefType, outPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::NewDirRef ( uInt32 *outNewRef,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->GetNewRef( outNewRef, 0, eDirectoryRefType, nil, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::NewNodeRef ( uInt32 *outNewRef,
CServerPlugin *inPlugin,
uInt32 inParentID,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->GetNewRef( outNewRef, inParentID, eNodeRefType, inPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::NewRecordRef ( uInt32 *outNewRef,
CServerPlugin *inPlugin,
uInt32 inParentID,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->GetNewRef( outNewRef, inParentID, eRecordRefType, inPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::NewAttrListRef ( uInt32 *outNewRef,
CServerPlugin *inPlugin,
uInt32 inParentID,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->GetNewRef( outNewRef, inParentID, eAttrListRefType, inPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::NewAttrValueRef ( uInt32 *outNewRef,
CServerPlugin *inPlugin,
uInt32 inParentID,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->GetNewRef( outNewRef, inParentID, eAttrValueListRefType, inPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::RemoveDirRef ( uInt32 inDirRef,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->RemoveRef( inDirRef, eDirectoryRefType, inPID, inIPAddress, true );
}
return( siResult );
}
tDirStatus CRefTable::RemoveNodeRef ( uInt32 inNodeRef,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->RemoveRef( inNodeRef, eNodeRefType, inPID, inIPAddress, true );
}
return( siResult );
}
tDirStatus CRefTable::RemoveRecordRef ( uInt32 inRecRef,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->RemoveRef( inRecRef, eRecordRefType, inPID, inIPAddress, true );
}
return( siResult );
}
tDirStatus CRefTable::RemoveAttrListRef ( uInt32 inAttrListRef,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->RemoveRef( inAttrListRef, eAttrListRefType, inPID, inIPAddress, true );
}
return( siResult );
}
tDirStatus CRefTable::RemoveAttrValueRef ( uInt32 inAttrValueRef,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->RemoveRef( inAttrValueRef, eAttrValueListRefType, inPID, inIPAddress, true );
}
return( siResult );
}
tDirStatus CRefTable::SetNodePluginPtr ( tDirNodeReference inNodeRef,
CServerPlugin *inPlugin )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->SetPluginPtr( inNodeRef, eNodeRefType, inPlugin );
}
return( siResult );
}
sRefEntry* CRefTable::GetTableRef ( uInt32 inRefNum )
{
uInt32 uiSlot = 0;
uInt32 uiRefNum = (inRefNum & 0x00FFFFFF);
uInt32 uiTableNum = (inRefNum & 0xFF000000) >> 24;
sRefTable *pTable = nil;
sRefEntry *pOutEntry = nil;
fTableMutex.Wait();
try
{
pTable = GetThisTable( uiTableNum );
if ( pTable == nil ) throw( (sInt32)eDSInvalidReference );
uiSlot = uiRefNum % kMaxTableItems;
if ( pTable->fTableData != nil)
{
if ( pTable->fTableData[ uiSlot ] != nil )
{
if ( uiRefNum == pTable->fTableData[ uiSlot ]->fRefNum )
{
pOutEntry = pTable->fTableData[ uiSlot ];
}
}
}
}
catch( sInt32 err )
{
DBGLOG2( kLogAssert, "Reference %l error = %l", inRefNum, err );
}
fTableMutex.Signal();
return( pOutEntry );
}
sRefTable* CRefTable::GetNextTable ( sRefTable *inTable )
{
uInt32 uiTblNum = 0;
sRefTable *pOutTable = nil;
fTableMutex.Wait();
try
{
if ( inTable == nil )
{
if ( fRefTables[ 1 ] == nil )
{
fRefTables[ 1 ] = (sRefTable *)::calloc( sizeof( sRefTable ), sizeof( char ) );
if ( fRefTables[ 1 ] == nil ) throw((sInt32)eMemoryAllocError);
fRefTables[ 1 ]->fTableNum = 1;
fTableCount = 1;
}
pOutTable = fRefTables[ 1 ];
}
else
{
uiTblNum = inTable->fTableNum + 1;
if (uiTblNum > kMaxTables) throw( (sInt32)eDSInvalidReference );
if ( fRefTables[ uiTblNum ] == nil )
{
fTableCount = uiTblNum;
fRefTables[ uiTblNum ] = (sRefTable *)::calloc( sizeof( sRefTable ), sizeof( char ) );
if ( fRefTables[ uiTblNum ] == nil ) throw((sInt32)eMemoryAllocError);
if (uiTblNum == 0) throw( (sInt32)eDSInvalidReference );
fRefTables[ uiTblNum ]->fTableNum = uiTblNum;
}
pOutTable = fRefTables[ uiTblNum ];
}
}
catch( sInt32 err )
{
DBGLOG1( kLogAssert, "Reference table error = %l", err );
}
fTableMutex.Signal();
return( pOutTable );
}
sRefTable* CRefTable::GetThisTable ( uInt32 inTableNum )
{
sRefTable *pOutTable = nil;
fTableMutex.Wait();
pOutTable = fRefTables[ inTableNum ];
fTableMutex.Signal();
return( pOutTable );
}
tDirStatus CRefTable::GetNewRef ( uInt32 *outRef,
uInt32 inParentID,
eRefTypes inType,
CServerPlugin *inPlugin,
sInt32 inPID,
uInt32 inIPAddress )
{
bool done = false;
tDirStatus outResult = eDSNoErr;
sRefTable *pCurTable = nil;
uInt32 uiRefNum = 0;
uInt32 uiCntr = 0;
uInt32 uiSlot = 0;
uInt32 uiTableNum = 0;
uInt32 refCountUpdate = 0;
fTableMutex.Wait();
try
{
*outRef = 0;
while ( !done )
{
pCurTable = GetNextTable( pCurTable );
if ( pCurTable == nil ) throw( (sInt32)eDSRefTableAllocError );
if ( pCurTable->fItemCnt < kMaxTableItems )
{
uiCntr = 0;
uiTableNum = pCurTable->fTableNum;
while ( (uiCntr < kMaxTableItems) && !done ) {
if ( (pCurTable->fCurRefNum == 0) ||
(pCurTable->fCurRefNum > 0x000FFFFF) )
{
pCurTable->fCurRefNum = 1;
}
uiRefNum = pCurTable->fCurRefNum++;
uiSlot = uiRefNum % kMaxTableItems;
if ( pCurTable->fTableData[ uiSlot ] == nil )
{
pCurTable->fTableData[ uiSlot ] = (sRefEntry *)::calloc( sizeof( sRefEntry ), sizeof( char ) );
if ( pCurTable->fTableData[ uiSlot ] == nil ) throw( (sInt32)eDSRefTableAllocError );
pCurTable->fTableData[ uiSlot ]->fRefNum = uiRefNum;
pCurTable->fTableData[ uiSlot ]->fType = inType;
pCurTable->fTableData[ uiSlot ]->fParentID = inParentID;
pCurTable->fTableData[ uiSlot ]->fPID = inPID;
pCurTable->fTableData[ uiSlot ]->fIPAddress = inIPAddress;
pCurTable->fTableData[ uiSlot ]->fPlugin = inPlugin;
pCurTable->fTableData[ uiSlot ]->fChildren = nil;
pCurTable->fTableData[ uiSlot ]->fChildPID = nil;
uiTableNum = (uiTableNum << 24);
uiRefNum = uiRefNum | uiTableNum;
*outRef = uiRefNum;
pCurTable->fItemCnt++;
outResult = eDSNoErr;
done = true;
if (inType == eDirectoryRefType)
{
refCountUpdate = UpdateClientPIDRefCount(inPID, inIPAddress, true, uiRefNum);
}
else
{
refCountUpdate = UpdateClientPIDRefCount(inPID, inIPAddress, true);
}
}
uiCntr++; }
}
}
if ( inParentID != 0 )
{
outResult = LinkToParent( *outRef, inType, inParentID, inPID, inIPAddress );
}
}
catch( sInt32 err )
{
outResult = (tDirStatus)err;
}
fTableMutex.Signal();
return( outResult );
}
tDirStatus CRefTable::LinkToParent ( uInt32 inRefNum,
uInt32 inType,
uInt32 inParentID,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus dsResult = eDSNoErr;
sRefEntry *pCurrRef = nil;
sListInfo *pChildInfo = nil;
fTableMutex.Wait();
try
{
pCurrRef = GetTableRef( inParentID );
if ( pCurrRef == nil ) throw( (sInt32)eDSInvalidReference );
pChildInfo = (sListInfo *)::calloc( sizeof( sListInfo ), sizeof( char ) );
if ( pChildInfo == nil ) throw( (sInt32)eDSRefTableAllocError );
pChildInfo->fRefNum = inRefNum;
pChildInfo->fType = inType;
pChildInfo->fPID = inPID;
pChildInfo->fIPAddress = inIPAddress;
pChildInfo->fNext = pCurrRef->fChildren;
pCurrRef->fChildren = pChildInfo;
}
catch( sInt32 err )
{
dsResult = (tDirStatus)err;
}
fTableMutex.Signal();
return( dsResult );
}
tDirStatus CRefTable::UnlinkFromParent ( uInt32 inRefNum )
{
tDirStatus dsResult = eDSNoErr;
uInt32 i = 1;
uInt32 parentID = 0;
sRefEntry *pCurrRef = nil;
sRefEntry *pParentRef = nil;
sListInfo *pCurrChild = nil;
sListInfo *pPrevChild = nil;
fTableMutex.Wait();
try
{
pCurrRef = GetTableRef( inRefNum );
if ( pCurrRef == nil ) throw( (sInt32)eDSInvalidReference );
parentID = pCurrRef->fParentID;
if ( parentID != 0 )
{
pParentRef = GetTableRef( parentID );
if ( pParentRef == nil ) throw( (sInt32)eDSInvalidReference );
pCurrChild = pParentRef->fChildren;
pPrevChild = pParentRef->fChildren;
while ( pCurrChild != nil )
{
if ( pCurrChild->fRefNum == inRefNum )
{
if ( i == 1 )
{
pParentRef->fChildren = pCurrChild->fNext;
}
else
{
pPrevChild->fNext = pCurrChild->fNext;
}
free( pCurrChild );
pCurrChild = nil;
break;
}
pPrevChild = pCurrChild;
pCurrChild = pCurrChild->fNext;
i++;
}
}
}
catch( sInt32 err )
{
dsResult = (tDirStatus)err;
}
fTableMutex.Signal();
return( dsResult );
}
tDirStatus CRefTable::GetReference ( uInt32 inRefNum, sRefEntry **outRefData )
{
tDirStatus dsResult = eDSNoErr;
sRefEntry *pCurrRef = nil;
fTableMutex.Wait();
try
{
pCurrRef = GetTableRef( inRefNum );
if ( pCurrRef == nil ) throw( (sInt32)eDSInvalidReference );
*outRefData = pCurrRef;
}
catch( sInt32 err )
{
dsResult = (tDirStatus)err;
}
fTableMutex.Signal();
return( dsResult );
}
tDirStatus CRefTable::RemoveRef ( uInt32 inRefNum,
uInt32 inType,
sInt32 inPID,
uInt32 inIPAddress,
bool inbAtTop)
{
tDirStatus dsResult = eDSNoErr;
sRefEntry *pCurrRef = nil;
sRefTable *pTable = nil;
uInt32 uiSlot = 0;
uInt32 uiTableNum = (inRefNum & 0xFF000000) >> 24;
uInt32 uiRefNum = (inRefNum & 0x00FFFFFF);
bool doFree = false;
sPIDInfo *pPIDInfo = nil;
sPIDInfo *pPrevPIDInfo = nil;
uInt32 refCountUpdate = 0;
sRefCleanUpEntry *aRefCleanUpEntries = nil;
sRefCleanUpEntry *aRefCleanUpEntriesIter = nil;
sInt32 deallocResult = eDSNoErr;
fTableMutex.Wait();
try
{
dsResult = VerifyReference( inRefNum, inType, nil, inPID, inIPAddress );
if ( dsResult == eDSNoErr )
{
pTable = GetThisTable( uiTableNum );
if ( pTable == nil ) throw( (sInt32)eDSInvalidReference );
uiSlot = uiRefNum % kMaxTableItems;
if ( inType != eDirectoryRefType ) {
dsResult = UnlinkFromParent( inRefNum );
if ( dsResult != eDSNoErr ) throw( (sInt32)dsResult );
}
pCurrRef = GetTableRef( inRefNum ); if ( pCurrRef == nil ) throw( (sInt32)eDSInvalidReference );
if (inType != pCurrRef->fType) throw( (sInt32)eDSInvalidReference );
if ( pCurrRef->fChildren != nil )
{
RemoveChildren( pCurrRef->fChildren, inPID, inIPAddress );
}
if ( (pCurrRef->fPID == inPID) && (pCurrRef->fIPAddress == inIPAddress) )
{
pCurrRef->fPID = -1;
if (pCurrRef->fChildPID == nil)
{
doFree = true;
}
}
else
{
pPIDInfo = pCurrRef->fChildPID;
pPrevPIDInfo = pCurrRef->fChildPID;
while (pPIDInfo != nil)
{
if ( (pPIDInfo->fPID == inPID) && (pPIDInfo->fIPAddress == inIPAddress) )
{
if (pPIDInfo == pCurrRef->fChildPID)
{
pCurrRef->fChildPID = pCurrRef->fChildPID->fNext;
free(pPIDInfo);
pPIDInfo = pCurrRef->fChildPID;
pPrevPIDInfo = pCurrRef->fChildPID;
}
else
{
pPrevPIDInfo->fNext = pPIDInfo->fNext;
free(pPIDInfo);
pPIDInfo = pPrevPIDInfo->fNext;
}
}
else
{
pPrevPIDInfo = pPIDInfo;
pPIDInfo = pPIDInfo->fNext;
}
}
if ( (pCurrRef->fPID == -1) && (pCurrRef->fChildPID == nil) )
{
doFree = true;
}
}
if (doFree)
{
if ( pTable->fTableData[ uiSlot ] != nil )
{
if ( uiRefNum == pTable->fTableData[ uiSlot ]->fRefNum )
{
pCurrRef = pTable->fTableData[ uiSlot ];
pTable->fTableData[ uiSlot ] = nil;
pTable->fItemCnt--;
refCountUpdate = UpdateClientPIDRefCount(inPID, inIPAddress, false);
if (fDeallocProc != nil)
{
if (fRefCleanUpEntriesHead == nil)
{
fRefCleanUpEntriesHead = (sRefCleanUpEntry *)calloc(1, sizeof(sRefCleanUpEntry));
fRefCleanUpEntriesHead->fRefNum = inRefNum; fRefCleanUpEntriesHead->fType = pCurrRef->fType;
fRefCleanUpEntriesHead->fPlugin = pCurrRef->fPlugin;
fRefCleanUpEntriesHead->fNext = nil;
fRefCleanUpEntriesTail = fRefCleanUpEntriesHead;
}
else
{
fRefCleanUpEntriesTail->fNext = (sRefCleanUpEntry *)calloc(1, sizeof(sRefCleanUpEntry));
fRefCleanUpEntriesTail->fNext->fRefNum = inRefNum; fRefCleanUpEntriesTail->fNext->fType = pCurrRef->fType;
fRefCleanUpEntriesTail->fNext->fPlugin = pCurrRef->fPlugin;
fRefCleanUpEntriesTail->fNext->fNext = nil;
fRefCleanUpEntriesTail = fRefCleanUpEntriesTail->fNext;
}
}
free(pCurrRef);
pCurrRef = nil;
}
}
}
}
}
catch( sInt32 err )
{
dsResult = (tDirStatus)err;
}
if (inbAtTop) {
aRefCleanUpEntriesIter = fRefCleanUpEntriesHead;
fRefCleanUpEntriesHead = nil;
fRefCleanUpEntriesTail = nil;
}
fTableMutex.Signal();
if (inbAtTop) {
while (aRefCleanUpEntriesIter != nil)
{
aRefCleanUpEntries = aRefCleanUpEntriesIter;
if (aRefCleanUpEntries->fPlugin != nil)
{
deallocResult = (tDirStatus)(*fDeallocProc)( aRefCleanUpEntries->fRefNum, aRefCleanUpEntries->fType, aRefCleanUpEntries->fPlugin );
}
aRefCleanUpEntriesIter = aRefCleanUpEntries->fNext;
free(aRefCleanUpEntries);
}
}
return( dsResult );
}
void CRefTable::RemoveChildren ( sListInfo *inChildList,
sInt32 inPID,
uInt32 inIPAddress )
{
sListInfo *pCurrChild = nil;
sListInfo *pNextChild = nil;
fTableMutex.Wait();
try
{
pCurrChild = inChildList;
while ( pCurrChild != nil )
{
pNextChild = pCurrChild->fNext;
if ( ( pCurrChild->fPID == inPID ) && ( pCurrChild->fIPAddress == inIPAddress ) )
{
RemoveRef( pCurrChild->fRefNum, pCurrChild->fType, inPID, inIPAddress, false );
}
pCurrChild = pNextChild;
}
}
catch( sInt32 err )
{
}
fTableMutex.Signal();
}
tDirStatus CRefTable::SetPluginPtr ( uInt32 inRefNum, uInt32 inType, CServerPlugin *inPlugin )
{
tDirStatus dsResult = eDSNoErr;
sRefEntry *pCurrRef = nil;
fTableMutex.Wait();
try
{
pCurrRef = GetTableRef( inRefNum );
if ( pCurrRef == nil ) throw( (sInt32)eDSInvalidReference );
if (inType != pCurrRef->fType) throw( (sInt32)eDSInvalidReference );
pCurrRef->fPlugin = inPlugin;
}
catch( sInt32 err )
{
}
fTableMutex.Signal();
return( dsResult );
}
tDirStatus CRefTable:: AddChildPIDToRef ( uInt32 inRefNum, uInt32 inParentPID, sInt32 inChildPID, uInt32 inIPAddress )
{
tDirStatus dsResult = eDSNoErr;
sRefEntry *pCurrRef = nil;
sPIDInfo *pChildPIDInfo = nil;
gRefTable->Lock();
try
{
dsResult = gRefTable->VerifyReference( inRefNum, eNodeRefType, nil, inParentPID, inIPAddress );
if ( dsResult != eDSNoErr ) throw( (sInt32)dsResult );
pCurrRef = gRefTable->GetTableRef( inRefNum );
if ( pCurrRef == nil ) throw( (sInt32)eDSInvalidReference );
pChildPIDInfo = (sPIDInfo *)::calloc( 1, sizeof( sPIDInfo ) );
if ( pChildPIDInfo == nil ) throw( (sInt32)eDSRefTableAllocError );
pChildPIDInfo->fPID = inChildPID;
pChildPIDInfo->fIPAddress = inIPAddress;
pChildPIDInfo->fNext = pCurrRef->fChildPID;
pCurrRef->fChildPID = pChildPIDInfo;
}
catch( sInt32 err )
{
dsResult = (tDirStatus)err;
}
gRefTable->Unlock();
return( dsResult );
}
uInt32 CRefTable:: UpdateClientPIDRefCount ( sInt32 inClientPID, uInt32 inIPAddress, bool inUpRefCount, uInt32 inDirRef )
{
CFNumberRef aRefCount = 0;
CFStringRef aComparePIDString = 0;
CFStringRef aCompareIPString = 0;
uInt32 aCount = 0;
CFNumberRef aPIDCount = 0;
CFMutableArrayRef aClientPIDArray;
CFMutableDictionaryRef aPIDDict = 0;
fClientPIDListLock->Wait();
if (fClientIPList != nil)
{
aCompareIPString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), inIPAddress);
aComparePIDString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), inClientPID);
if ( (aCompareIPString != nil) && (aComparePIDString != nil) )
{
if ( CFDictionaryContainsKey( fClientIPList, aCompareIPString ) )
{
fClientPIDList = nil;
fClientPIDList = (CFMutableDictionaryRef)CFDictionaryGetValue( fClientIPList, aCompareIPString );
if (fClientPIDList != nil)
{
if ( CFDictionaryContainsKey( fClientPIDList, aComparePIDString ) )
{
aPIDDict = (CFMutableDictionaryRef)CFDictionaryGetValue( fClientPIDList, aComparePIDString );
aRefCount = (CFNumberRef)CFDictionaryGetValue( aPIDDict, CFSTR("RefCount") );
CFNumberGetValue(aRefCount, kCFNumberIntType, &aCount);
if (inUpRefCount)
{
aCount++;
if (gLogAPICalls)
{
syslog(LOG_INFO,"Client PID: %d, has %d open references.", inClientPID, aCount);
}
}
else
{
aCount--;
if (gLogAPICalls)
{
syslog(LOG_INFO,"Client PID: %d, has %d open references.", inClientPID, aCount);
}
}
if (aCount == 0)
{
CFMutableArrayRef clientPIDArray = NULL;
clientPIDArray = (CFMutableArrayRef)CFDictionaryGetValue(fClientPIDList, CFSTR("ClientPIDArray"));
if (clientPIDArray != NULL)
{
int aPIDArrayCount = CFArrayGetCount( clientPIDArray );
for (CFIndex indexToPID=0; indexToPID < aPIDArrayCount; indexToPID++ )
{
CFStringRef aStringRef = (CFStringRef)CFArrayGetValueAtIndex(clientPIDArray, indexToPID);
if ( ( aStringRef != NULL ) &&
(kCFCompareEqualTo == CFStringCompare(aStringRef, aComparePIDString, 0)) )
{
CFArrayRemoveValueAtIndex(clientPIDArray, indexToPID);
CFDictionaryRemoveValue(fClientPIDList, aComparePIDString);
break;
}
}
}
}
else
{
aRefCount = CFNumberCreate(kCFAllocatorDefault,kCFNumberIntType,&aCount);
if (inDirRef != 0) {
if ( CFDictionaryContainsKey( aPIDDict, CFSTR("DirRefs")) )
{
CFMutableArrayRef aDirRefArray = (CFMutableArrayRef)CFDictionaryGetValue(aPIDDict, CFSTR("DirRefs"));
CFNumberRef aCFDirRef = CFNumberCreate(kCFAllocatorDefault,kCFNumberIntType,&inDirRef);
CFArrayAppendValue(aDirRefArray, aCFDirRef);
CFRelease(aCFDirRef);
}
else
{
CFMutableArrayRef aDirRefArray = CFArrayCreateMutable( kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks);
CFNumberRef aCFDirRef = CFNumberCreate(kCFAllocatorDefault,kCFNumberIntType,&inDirRef);
CFArrayAppendValue(aDirRefArray, aCFDirRef);
CFDictionarySetValue( aPIDDict, CFSTR("DirRefs"), aDirRefArray );
CFRelease(aCFDirRef);
CFRelease(aDirRefArray);
}
}
CFDictionaryReplaceValue(aPIDDict, CFSTR("RefCount"), aRefCount);
CFRelease(aRefCount);
}
}
else if (inUpRefCount)
{
CFMutableArrayRef clientPIDArray;
clientPIDArray = (CFMutableArrayRef)CFDictionaryGetValue(fClientPIDList, CFSTR("ClientPIDArray"));
CFArrayAppendValue(clientPIDArray, aComparePIDString);
aCount = 1;
aRefCount = CFNumberCreate(kCFAllocatorDefault,kCFNumberIntType,&aCount);
aPIDDict = CFDictionaryCreateMutable( kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
CFDictionarySetValue( aPIDDict, CFSTR("RefCount"), aRefCount );
CFRelease(aRefCount);
if (inDirRef != 0)
{
CFMutableArrayRef aDirRefArray = CFArrayCreateMutable( kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks);
CFNumberRef aCFDirRef = CFNumberCreate(kCFAllocatorDefault,kCFNumberIntType,&inDirRef);
CFArrayAppendValue(aDirRefArray, aCFDirRef);
CFDictionarySetValue( aPIDDict, CFSTR("DirRefs"), aDirRefArray );
CFRelease(aCFDirRef);
CFRelease(aDirRefArray);
}
CFDictionarySetValue( fClientPIDList, aComparePIDString, aPIDDict );
CFRelease(aPIDDict);
}
}
} else
{
fClientPIDList = CFDictionaryCreateMutable( kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
aClientPIDArray = CFArrayCreateMutable( kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks);
aPIDDict = CFDictionaryCreateMutable( kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
if (inDirRef != 0)
{
CFMutableArrayRef aDirRefArray = CFArrayCreateMutable( kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks);
CFNumberRef aCFDirRef = CFNumberCreate(kCFAllocatorDefault,kCFNumberIntType,&inDirRef);
CFArrayAppendValue(aDirRefArray, aCFDirRef);
CFDictionarySetValue( aPIDDict, CFSTR("DirRefs"), aDirRefArray );
aCount = 1;
aPIDCount = CFNumberCreate(kCFAllocatorDefault,kCFNumberIntType,&aCount);
CFDictionarySetValue( aPIDDict, CFSTR("RefCount"), aPIDCount );
CFDictionarySetValue( fClientPIDList, aComparePIDString, aPIDDict );
CFRelease(aCFDirRef);
CFRelease(aDirRefArray);
}
CFArrayAppendValue(aClientPIDArray, aComparePIDString);
CFDictionarySetValue( fClientPIDList, CFSTR("ClientPIDArray"), aClientPIDArray );
CFRelease(aPIDCount);
CFRelease(aPIDDict);
CFRelease(aClientPIDArray);
CFDictionarySetValue( fClientIPList, aCompareIPString, fClientPIDList );
}
CFRelease(aCompareIPString);
CFRelease(aComparePIDString);
}
}
fClientPIDListLock->Signal();
return aCount;
}
void CRefTable::CheckClientPIDs ( bool inUseTimeOuts, uInt32 inIPAddress, uInt32 inPIDorPort )
{
if (gRefTable != nil)
{
gRefTable->DoCheckClientPIDs(inUseTimeOuts, inIPAddress, inPIDorPort);
}
}
void CRefTable::DoCheckClientPIDs ( bool inUseTimeOuts, uInt32 inIPAddress, uInt32 inPIDorPort )
{
CFStringRef aPIDString = NULL;
CFStringRef aCompareIPString = 0;
char aStringBuff[16]; uInt32 strBuffSize = 16;
sInt32 aPIDValue = 0;
CFNumberRef aRefCount = 0;
uInt32 aCount = 0;
size_t iSize = 0;
register size_t i = 0;
bool bPIDRunning = true;
int mib [] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
size_t ulSize = 0;
CFMutableDictionaryRef
aPIDDict = NULL;
uInt32 aDirRef = 0;
CFStringRef aNullStringName = 0;
CFIndex indexToPID = 0;
sInt32 siResult = eDSNoErr;
struct kinfo_proc *kpspArray = nil;
sInt32 zeroVal = 0;
bool bReloadDict = true;
if (inUseTimeOuts)
{
if (::time( nil ) < fSunsetTime)
{
return;
}
}
if (fClientPIDListLock->Wait(1) != eDSNoErr)
{
fClientPIDListLock->Signal(); return;
}
if (inIPAddress == 0)
{
if ( 0 > sysctl( mib, 4, NULL, &ulSize, NULL, 0) )
{
fClientPIDListLock->Signal(); return; }
iSize = ulSize / sizeof(struct kinfo_proc);
kpspArray = new kinfo_proc[ iSize ];
if (!kpspArray)
{
fClientPIDListLock->Signal(); return; }
ulSize = iSize * sizeof(struct kinfo_proc);
if ( 0 > sysctl( mib, 4, kpspArray, &ulSize, NULL, 0 ) )
{
delete [] kpspArray;
fClientPIDListLock->Signal(); return; }
}
if (fClientIPList != nil)
{
aNullStringName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), zeroVal);
aCompareIPString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), inIPAddress);
if ( (aNullStringName != nil) && (aCompareIPString != nil) )
{
while (bReloadDict)
{
bReloadDict = false;
if ( CFDictionaryContainsKey( fClientIPList, aCompareIPString ) )
{
fClientPIDList = nil;
fClientPIDList = (CFMutableDictionaryRef)CFDictionaryGetValue( fClientIPList, aCompareIPString );
if (fClientPIDList != nil)
{
CFMutableArrayRef clientPIDArray = NULL;
clientPIDArray = (CFMutableArrayRef)CFDictionaryGetValue(fClientPIDList, CFSTR("ClientPIDArray"));
if (clientPIDArray != NULL)
{
int aPIDArrayCount = CFArrayGetCount( clientPIDArray );
for (indexToPID=0; indexToPID < aPIDArrayCount; indexToPID++ )
{
aPIDString = (CFStringRef)CFArrayGetValueAtIndex(clientPIDArray, indexToPID);
if (aPIDString != NULL)
{
memset(aStringBuff, 0, strBuffSize);
if ( CFStringGetCString( aPIDString, aStringBuff, strBuffSize, kCFStringEncodingUTF8 ) &&
(aStringBuff[0] != '\0') && (aStringBuff[strBuffSize] == '\0') )
{
char *endPtr = nil;
aPIDValue = (sInt32)strtol(aStringBuff, &endPtr, 10);
bPIDRunning = false;
if (inIPAddress == 0)
{
i = iSize;
register struct kinfo_proc *kpsp = kpspArray;
for ( ; i-- ; kpsp++ )
{
if (aPIDValue == kpsp->kp_proc.p_pid)
{
bPIDRunning = true;
break;
}
}
}
else if ((uInt32)aPIDValue != inPIDorPort)
{
bPIDRunning = true;
}
if ( CFDictionaryContainsKey( fClientPIDList, aPIDString ) )
{
aPIDDict = (CFMutableDictionaryRef)CFDictionaryGetValue( fClientPIDList, aPIDString );
if (aPIDDict != NULL)
{
aRefCount = (CFNumberRef)CFDictionaryGetValue( aPIDDict, CFSTR("RefCount") );
CFMutableArrayRef aDirRefArray = (CFMutableArrayRef)CFDictionaryGetValue(aPIDDict, CFSTR("DirRefs"));
CFNumberGetValue(aRefCount, kCFNumberIntType, &aCount);
if (bPIDRunning)
{
if (gLogAPICalls)
{
syslog(LOG_INFO,"Client PID %d has ref count = %d",aPIDValue, aCount);
}
DBGLOG2( kLogHandler, "The client PID %d has ref count = %d.", aPIDValue, aCount );
}
else
{
CFRetain(aPIDDict);
CFDictionaryRemoveValue(fClientPIDList, aPIDString);
CFArraySetValueAtIndex(clientPIDArray, indexToPID, aNullStringName);
fClientPIDListLock->Signal();
if (aDirRefArray != NULL)
{
int aDirRefArrayCount = CFArrayGetCount( aDirRefArray );
for (CFIndex indexToDirRef=0; indexToDirRef < aDirRefArrayCount; indexToDirRef++ )
{
CFNumberRef aCFDirRef= (CFNumberRef)CFArrayGetValueAtIndex( aDirRefArray, indexToDirRef );
CFNumberGetValue(aCFDirRef, kCFNumberIntType, &aDirRef);
siResult = CRefTable::RemoveDirRef( aDirRef, aPIDValue, inIPAddress );
}
} fClientPIDListLock->Wait();
if (gLogAPICalls)
{
syslog(LOG_INFO,"Client PID %d had ref count = %d before cleanup.",aPIDValue, aCount);
}
DBGLOG2( kLogHandler, "The client PID %d had ref count = %d before cleanup.", aPIDValue, aCount );
CFRelease(aPIDDict);
bReloadDict = true;
break;
}
} }
} } } indexToPID = (CFArrayGetCount( clientPIDArray )) - 1;
while (indexToPID > 0) {
if (kCFCompareEqualTo == CFStringCompare((CFStringRef)CFArrayGetValueAtIndex(clientPIDArray, indexToPID), aNullStringName, 0))
{
CFArrayRemoveValueAtIndex(clientPIDArray, indexToPID);
}
indexToPID--;
}
} }
}
}
CFRelease(aNullStringName);
CFRelease(aCompareIPString);
} }
fSunsetTime = time(nil) + 300;
fClientPIDListLock->Signal();
if (kpspArray != NULL)
{
delete [] kpspArray;
}
}