#include "CNSLHeaders.h"
#include <mach/mach_time.h> // for dsTimeStamp
#include "CNSLTimingUtils.h"
#ifndef kServerRunLoop
#define kServerRunLoop (eDSPluginCalls)(kHandleNetworkTransition + 1)
#endif
#define DONT_WAIT_FOR_NSL_TO_ACTIVATE_US
int LogHexDump(char *pktPtr, long pktLen);
boolean_t NetworkChangeCallBack(SCDynamicStoreRef session, void *callback_argument);
void NSLReleaseNodeData( CFAllocatorRef allocator, const void* value );
CFStringRef NSLNodeValueCopyDesctriptionCallback ( const void *item );
Boolean NSLNodeValueEqualCallback ( const void *value1, const void *value2 );
void NSLNodeHandlerFunction(const void *inKey, const void *inValue, void *inContext);
typedef struct AttrDataContext {
sInt32 count;
CDataBuff* attrDataBuf;
Boolean attrOnly;
} AttrDataContext;
void AddToAttrData(const void *key, const void *value, void *context);
sInt16 gOutstandingSearches = 0;
pthread_mutex_t gOutstandingSearchesLock = PTHREAD_MUTEX_INITIALIZER;
CNSLPlugin* CNSLPlugin::gsTheNSLPlugin = NULL;
void SearchStarted( void )
{
pthread_mutex_lock(&gOutstandingSearchesLock);
gOutstandingSearches++;
pthread_mutex_unlock(&gOutstandingSearchesLock);
DBGLOG( "SearchStarted, gOutstandingSearches=%d\n", gOutstandingSearches );
}
void SearchCompleted( void )
{
Boolean okToStartNextSearch = false;
pthread_mutex_lock(&gOutstandingSearchesLock);
gOutstandingSearches--;
DBGLOG( "SearchCompleted, gOutstandingSearches=%d\n", gOutstandingSearches );
pthread_mutex_unlock(&gOutstandingSearchesLock);
if ( okToStartNextSearch )
{
CNSLPlugin::TheNSLPlugin()->LockSearchQueue();
CNSLPlugin::TheNSLPlugin()->StartNextQueuedSearch(); CNSLPlugin::TheNSLPlugin()->UnlockSearchQueue();
}
}
#pragma mark -
CFStringRef NSLQueuedSearchesCopyDesctriptionCallback ( const void *item )
{
return kDSNSLQueuedSearchSAFE_CFSTR;
}
Boolean NSLQueuedSearchesEqualCallback ( const void *item1, const void *item2 )
{
return item1 == item2;
}
NodeData * AllocateNodeData()
{
NodeData *newNode = (NodeData*)calloc( 1, sizeof(NodeData) );
return newNode;
}
void DeallocateNodeData( NodeData *nodeData )
{
if ( nodeData != NULL )
{
if ( nodeData->fNodeName )
::CFRelease( nodeData->fNodeName );
nodeData->fNodeName = NULL;
if ( nodeData->fServicesRefTable )
::CFRelease( nodeData->fServicesRefTable );
nodeData->fServicesRefTable = NULL;
if ( nodeData->fDSName )
{
dsDataListDeallocatePriv( nodeData->fDSName );
free( nodeData->fDSName );
nodeData->fDSName = NULL;
}
free( nodeData );
}
}
CNSLPlugin::CNSLPlugin( void )
{
DBGLOG( "CNSLPlugin::CNSLPlugin\n" );
mPublishedNodes = NULL;
mLastNodeLookupStartTime = 0;
mOpenRefTable = NULL;
mActivatedByNSL = false;
mDSLocalNodeLabel = NULL;
mDSNetworkNodeLabel = NULL;
mSearchQueue = NULL;
mRunLoopRef = NULL;
mTimerRef = NULL;
mNodeLookupTimerRef = NULL;
mSearchTicklerInstalled = false;
mNodeLookupTimerInstalled = false;
mState = kUnknownState;
gsTheNSLPlugin = this;
}
CNSLPlugin::~CNSLPlugin( void )
{
DBGLOG( "CNSLPlugin::~CNSLPlugin\n" );
if ( mTimerRef )
{
UnInstallSearchTickler();
}
if ( mNodeLookupTimerRef )
{
UnInstallNodeLookupTimer();
}
if ( mPublishedNodes )
{
ClearOutAllNodes();
::CFDictionaryRemoveAllValues( mPublishedNodes );
::CFRelease( mPublishedNodes );
mPublishedNodes = NULL;
}
if ( mOpenRefTable )
{
::CFDictionaryRemoveAllValues( mOpenRefTable );
::CFRelease( mOpenRefTable );
mOpenRefTable = NULL;
}
if ( mSearchQueue )
::CFRelease( mSearchQueue );
}
sInt32 CNSLPlugin::Validate ( const char *inVersionStr, const uInt32 inSignature )
{
mSignature = inSignature;
return( noErr );
}
sInt32 CNSLPlugin::Initialize( void )
{
sInt32 siResult = eDSNoErr;
DBGLOG( "CNSLPlugin::Initialize\n" );
CFDictionaryKeyCallBacks keyCallBack;
CFDictionaryValueCallBacks valueCallBack;
valueCallBack.version = 0;
valueCallBack.retain = NULL;
valueCallBack.release = NSLReleaseNodeData;
valueCallBack.copyDescription = NSLNodeValueCopyDesctriptionCallback;
valueCallBack.equal = NSLNodeValueEqualCallback;
if ( !mPublishedNodes )
mPublishedNodes = ::CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &valueCallBack);
CFArrayCallBacks callBack;
callBack.version = 0;
callBack.retain = NULL;
callBack.release = NULL;
callBack.copyDescription = NSLQueuedSearchesCopyDesctriptionCallback;
callBack.equal = NSLQueuedSearchesEqualCallback;
if ( !mSearchQueue )
mSearchQueue= ::CFArrayCreateMutable( NULL, 0, &callBack );
pthread_mutex_init( &mQueueLock, NULL );
pthread_mutex_init( &mPluginLock, NULL );
pthread_mutex_init( &mOpenRefTableLock, NULL );
pthread_mutex_init( &mSearchQueueLock, NULL );
pthread_mutex_init( &mSearchLookupTimerLock, NULL );
pthread_mutex_init( &mNodeLookupTimerLock, NULL );
keyCallBack.version = 0;
keyCallBack.retain = NULL;
keyCallBack.release = NULL;
keyCallBack.copyDescription = NULL;
keyCallBack.equal = NULL;
keyCallBack.hash = NULL;
valueCallBack.release = NULL;
valueCallBack.copyDescription = NULL;
valueCallBack.equal = NULL;
if ( !mOpenRefTable )
mOpenRefTable = ::CFDictionaryCreateMutable( NULL, 0, &keyCallBack, &valueCallBack );
if ( !mOpenRefTable )
DBGLOG("************* mOpenRefTable is NULL ***************\n");
if ( !siResult )
{
mState = kInitialized | kInactive;
}
if ( !siResult )
siResult = InitPlugin();
return siResult;
}
void CNSLPlugin::WaitForInit( void )
{
volatile uInt32 uiAttempts = 0;
while ( !(mState & kInitialized) &&
!(mState & kFailedToInit) )
{
if ( uiAttempts++ >= 240 )
{
return;
}
SmartSleep( (uInt32)(50000) );
}
}
Boolean CNSLPlugin::IsActive( void )
{
Boolean isActive = ((mState & kActive) || !(mState & kInactive));
return isActive;
}
#pragma mark -
void PeriodicTimerCallback( CFRunLoopTimerRef timer, void *info );
void PeriodicTimerCallback( CFRunLoopTimerRef timer, void *info )
{
CNSLPlugin* plugin = (CNSLPlugin*)info;
plugin->NSLSearchTickler();
}
void CNSLPlugin::InstallSearchTickler( void )
{
if ( !mSearchTicklerInstalled && mRunLoopRef )
{
DBGLOG( "CNSLPlugin::InstallSearchTickler (%s)\n", GetProtocolPrefixString() );
CFRunLoopTimerContext c = {0, this, NULL, NULL, NULL};
if ( !mTimerRef )
mTimerRef = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent()+kTaskInterval, 0, 0, 0, PeriodicTimerCallback, (CFRunLoopTimerContext*)&c);
CFRunLoopAddTimer(mRunLoopRef, mTimerRef, kCFRunLoopDefaultMode);
}
mSearchTicklerInstalled = true;
}
void CNSLPlugin::UnInstallSearchTickler( void )
{
if ( mSearchTicklerInstalled && mRunLoopRef )
{
DBGLOG( "CNSLPlugin::UnInstallSearchTickler (%s)\n", GetProtocolPrefixString() );
if ( mTimerRef )
{
CFRunLoopRemoveTimer( mRunLoopRef, mTimerRef, kCFRunLoopDefaultMode );
CFRelease( mTimerRef );
mTimerRef = NULL;
}
}
mSearchTicklerInstalled = false;
}
sInt32 CNSLPlugin::NSLSearchTickler( void )
{
sInt32 siResult = eDSNoErr;
LockSearchQueue();
if ( IsActive() && mActivatedByNSL )
{
DBGLOG( "CNSLPlugin::NSLSearchTickler, Outstanding Searches: %ld, queued Searches: %ld\n", NumOutstandingSearches(), (mSearchQueue)?CFArrayGetCount(mSearchQueue):-1 );
while ( NumOutstandingSearches() < kMaxNumOutstandingSearches && mSearchQueue && CFArrayGetCount(mSearchQueue) > 0 )
StartNextQueuedSearch();
if ( NumOutstandingSearches() == 0 )
UnInstallSearchTickler();
if ( mSearchTicklerInstalled )
CFRunLoopTimerSetNextFireDate( mTimerRef, CFAbsoluteTimeGetCurrent()+kTaskInterval );
}
else if ( mSearchTicklerInstalled )
UnInstallSearchTickler();
UnlockSearchQueue();
return( siResult );
}
void CNSLPlugin::CancelCurrentlyQueuedSearches( void )
{
LockSearchQueue();
while ( mSearchQueue && CFArrayGetCount(mSearchQueue) > 0 )
{
CNSLServiceLookupThread* newLookup = (CNSLServiceLookupThread*)::CFArrayGetValueAtIndex( mSearchQueue, 0 );
::CFArrayRemoveValueAtIndex( mSearchQueue, 0 );
delete( newLookup );
}
UnlockSearchQueue();
}
#pragma mark -
void NodeLookupTimerCallback( CFRunLoopTimerRef timer, void *info );
void NodeLookupTimerCallback( CFRunLoopTimerRef timer, void *info )
{
CNSLPlugin* plugin = (CNSLPlugin*)info;
plugin->PeriodicNodeLookupTask();
}
void CNSLPlugin::InstallNodeLookupTimer( void )
{
LockNodeLookupTimer();
if ( !mNodeLookupTimerInstalled && mActivatedByNSL && mRunLoopRef )
{
DBGLOG( "CNSLPlugin::InstallNodeLookupTimer (%s) called\n", GetProtocolPrefixString() );
CFRunLoopTimerContext c = {0, this, NULL, NULL, NULL};
if ( !mNodeLookupTimerRef )
mNodeLookupTimerRef = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent()+kNodeTimerIntervalImmediate, kKeepTimerAroundAfterFiring, 0, 0, NodeLookupTimerCallback, (CFRunLoopTimerContext*)&c);
CFRunLoopAddTimer(mRunLoopRef, mNodeLookupTimerRef, kCFRunLoopDefaultMode);
}
mNodeLookupTimerInstalled = true;
UnlockNodeLookupTimer();
}
void CNSLPlugin::UnInstallNodeLookupTimer( void )
{
LockNodeLookupTimer();
if ( mNodeLookupTimerInstalled && mRunLoopRef )
{
DBGLOG( "CNSLPlugin::UnInstallNodeLookupTimer (%s)\n", GetProtocolPrefixString() );
if ( mNodeLookupTimerRef )
{
CFRunLoopRemoveTimer( mRunLoopRef, mNodeLookupTimerRef, kCFRunLoopDefaultMode );
CFRelease( mNodeLookupTimerRef );
mNodeLookupTimerRef = NULL;
}
}
mNodeLookupTimerInstalled = false;
UnlockNodeLookupTimer();
}
void CNSLPlugin::ResetNodeLookupTimer( UInt32 timeTillNewLookup )
{
LockNodeLookupTimer();
if ( mNodeLookupTimerInstalled && mRunLoopRef )
{
DBGLOG( "CNSLPlugin::ResetNodeLookupTimer (%s) setting timer to fire %d seconds from now\n", GetProtocolPrefixString(), timeTillNewLookup );
CFRunLoopTimerSetNextFireDate( mNodeLookupTimerRef, CFAbsoluteTimeGetCurrent() + timeTillNewLookup );
}
UnlockNodeLookupTimer();
}
void CNSLPlugin::PeriodicNodeLookupTask( void )
{
if ( mActivatedByNSL && IsActive() )
{
DBGLOG( "CNSLPlugin::PeriodicNodeLookupTask (%s), time to start new node lookup\n", GetProtocolPrefixString() );
StartNodeLookup();
}
else
{
DBGLOG( "CNSLPlugin::PeriodicNodeLookupTask (%s), called but mActivatedByNSL== %d && IsActive() == %d!\n", GetProtocolPrefixString(), mActivatedByNSL, IsActive() );
}
}
#pragma mark -
sInt32 CNSLPlugin::ProcessRequest ( void *inData )
{
sInt32 siResult = 0;
WaitForInit();
if ( inData == nil )
{
DBGLOG( "CNSLPlugin::ProcessRequest, inData is NULL!\n" );
return( ePlugInDataError );
}
if ( (mState & kFailedToInit) )
{
DBGLOG( "CNSLPlugin::ProcessRequest, kFailedToInit!\n" );
return( ePlugInFailedToInitialize );
}
if ( ((sHeader *)inData)->fType == kServerRunLoop )
{
DBGLOG( "CNSLPlugin::ProcessRequest, received a RunLoopRef, 0x%x\n",((sHeader *)inData)->fContextData );
return SetServerIdleRunLoopRef( (CFRunLoopRef)(((sHeader *)inData)->fContextData) );
}
else if ( !IsActive() )
{
if ( ((sHeader *)inData)->fType == kOpenDirNode )
{
char *pathStr = nil;
tDataListPtr pNodeList = nil;
char *protocolStr = nil;
pNodeList = ((sOpenDirNode *)inData)->fInDirNodeName;
pathStr = dsGetPathFromListPriv( pNodeList, (char *)"/" );
protocolStr = pathStr + 1;
if ( strstr( protocolStr, "NSLActivate" ) )
{
mActivatedByNSL = true;
free( pathStr );
return( ePlugInNotActive );
}
else if ( pathStr && GetProtocolPrefixString() && strcmp( protocolStr, GetProtocolPrefixString() ) == 0 )
{
DBGLOG( "CNSLPlugin::ProcessRequest (kOpenDirNode), plugin not active, open on (%s) ok\n", protocolStr );
free( pathStr );
}
else
{
DBGLOG( "CNSLPlugin::ProcessRequest (kOpenDirNode), plugin not active, returning ePlugInNotActive on open (%s)\n", protocolStr );
free( pathStr );
return( ePlugInNotActive );
}
}
else if ( ((sHeader *)inData)->fType == kCloseDirNode )
{
DBGLOG( "CNSLPlugin::ProcessRequest (kCloseDirNode), plugin not active, returning noErr\n" );
}
else if ( ((sHeader *)inData)->fType != kDoPlugInCustomCall )
{
DBGLOG( "CNSLPlugin::ProcessRequest (%d), plugin not active!\n", ((sHeader *)inData)->fType );
return( ePlugInNotActive );
}
}
siResult = HandleRequest( inData );
return( siResult );
}
#pragma mark -
sInt32 CNSLPlugin::SetServerIdleRunLoopRef( CFRunLoopRef idleRunLoopRef )
{
mRunLoopRef = idleRunLoopRef;
return eDSNoErr;
}
sInt32 CNSLPlugin::SetPluginState ( const uInt32 inState )
{
WaitForInit();
DBGLOG( "CNSLPlugin::SetPluginState(%s):", GetProtocolPrefixString() );
if ( (kActive & inState) && (mState & kInactive) ) {
DBGLOG( "kActive\n" );
if ( mState & kInactive )
mState -= kInactive;
if ( !(mState & kActive) )
mState += kActive;
#ifdef DONT_WAIT_FOR_NSL_TO_ACTIVATE_US
mActivatedByNSL = true; #endif
ActivateSelf();
}
if ( (kInactive & inState) && (mState & kActive) ) {
DBGLOG( "kInactive\n" );
if ( !(mState & kInactive) )
mState += kInactive;
if ( mState & kActive )
mState -= kActive;
DeActivateSelf();
}
return( eDSNoErr );
}
void CNSLPlugin::ActivateSelf( void )
{
if ( mActivatedByNSL )
{
ZeroLastNodeLookupStartTime();
InstallNodeLookupTimer();
}
}
void CNSLPlugin::DeActivateSelf( void )
{
UnInstallSearchTickler();
UnInstallNodeLookupTimer();
ClearOutAllNodes();
}
#pragma mark -
void CNSLPlugin::AddNode( CFStringRef nodeNameRef, Boolean isLocalNode )
{
if ( !nodeNameRef || !IsActive() )
return;
char nodeString[1024] = {0};
CFIndex bufferLen = sizeof(nodeString);
if ( CFStringGetCString( nodeNameRef, nodeString, bufferLen, kCFStringEncodingUTF8 ) )
{
AddNode( nodeString, isLocalNode );
}
else
fprintf(stderr, "CNSLPlugin::AddNode, CFStringGetCString failed!");
}
void CNSLPlugin::AddNode( const char* nodeName, Boolean isLocalNode )
{
if ( !nodeName || !IsActive() )
return;
NodeData* node = NULL;
CFStringRef nodeRef = CFStringCreateWithCString( NULL, nodeName, kCFStringEncodingUTF8 );
bool isADefaultNode = false;
bool isADefaultOnlyNode = false;
if ( nodeRef )
{
DBGLOG( "CNSLPlugin::AddNode (%s) called with %s\n", GetProtocolPrefixString(), nodeName );
LockPublishedNodes();
if ( ::CFDictionaryContainsKey( mPublishedNodes, nodeRef ) )
node = (NodeData*)::CFDictionaryGetValue( mPublishedNodes, nodeRef );
if ( isLocalNode || IsLocalNode( nodeName ) )
isADefaultNode = true;
if ( isADefaultNode )
isADefaultOnlyNode = IsADefaultOnlyNode( nodeName );
if ( node && isADefaultNode != node->fIsADefaultNode )
{
::CFDictionaryRemoveValue( mPublishedNodes, node->fNodeName );
node = NULL;
}
if ( node )
{
node->fTimeStamp = GetCurrentTime(); }
else
{
DBGLOG( "CNSLPlugin::AddNode(%s) Adding new %snode %s\n", GetProtocolPrefixString(), (isADefaultNode)?"local ":"", nodeName );
node = AllocateNodeData();
node->fNodeName = nodeRef;
CFRetain( node->fNodeName );
node->fDSName = dsBuildListFromStringsPriv(GetProtocolPrefixString(), nodeName, nil);
node->fTimeStamp = GetCurrentTime();
node->fServicesRefTable = ::CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
node->fIsADefaultNode = isADefaultNode;
node->fSignature = mSignature;
if ( node->fDSName )
{
eDirNodeType nodeTypeToRegister = kUnknownNodeType;
if ( isADefaultNode )
nodeTypeToRegister = kDefaultNetworkNodeType;
if ( !isADefaultOnlyNode )
nodeTypeToRegister = (eDirNodeType)( nodeTypeToRegister | kDirNodeType );
if ( nodeTypeToRegister != kUnknownNodeType )
DSRegisterNode( mSignature, node->fDSName, nodeTypeToRegister );
}
::CFDictionaryAddValue( mPublishedNodes, nodeRef, node );
}
CFRelease( nodeRef );
UnlockPublishedNodes();
}
}
void CNSLPlugin::RemoveNode( CFStringRef nodeNameRef )
{
NodeData* node = NULL;
DBGLOG( "CNSLPlugin::RemoveNode called with" );
if ( getenv("NSLDEBUG") )
CFShow(nodeNameRef);
LockPublishedNodes();
Boolean containsNode = ::CFDictionaryContainsKey( mPublishedNodes, nodeNameRef );
if ( containsNode )
{
node = (NodeData*)::CFDictionaryGetValue( mPublishedNodes, nodeNameRef );
::CFDictionaryRemoveValue( mPublishedNodes, node->fNodeName );
node = NULL;
}
UnlockPublishedNodes();
}
void CNSLPlugin::NodeLookupComplete( void )
{
DBGLOG( "CNSLPlugin::NodeLookupComplete\n" );
ClearOutStaleNodes(); }
const char* CNSLPlugin::GetLocalNodeString( void )
{
return NULL; }
Boolean CNSLPlugin::IsLocalNode( const char *inNode )
{
#pragma unused (inNode)
return false; }
Boolean CNSLPlugin::IsADefaultOnlyNode( const char *inNode )
{
#pragma unused (inNode)
return false; }
#pragma mark -
CFStringRef NetworkChangeNSLCopyStringCallback( const void *item );
CFStringRef NetworkChangeNSLCopyStringCallback( const void *item )
{
return kNetworkChangeNSLCopyStringCallbackSAFE_CFSTR;
}
static void DoNetworkTransition(CFRunLoopTimerRef timer, void *info);
void DoNetworkTransition(CFRunLoopTimerRef timer, void *info)
{
if ( info != nil )
{
((CNSLPlugin *)info)->HandleNetworkTransitionIfTime();
}
}
#pragma mark -
sInt32 CNSLPlugin::HandleRequest( void *inData )
{
sInt32 siResult = 0;
sHeader *pMsgHdr = nil;
if ( inData == nil )
{
return( -8088 );
}
pMsgHdr = (sHeader *)inData;
switch ( pMsgHdr->fType )
{
case kOpenDirNode:
siResult = OpenDirNode( (sOpenDirNode *)inData );
break;
case kCloseDirNode:
siResult = CloseDirNode( (sCloseDirNode *)inData );
break;
case kGetDirNodeInfo:
siResult = GetDirNodeInfo( (sGetDirNodeInfo *)inData );
break;
case kGetRecordList:
siResult = GetRecordList( (sGetRecordList *)inData );
break;
case kGetRecordEntry:
DBGLOG( "CNSLPlugin::HandleRequest, we don't handle kGetRecordEntry yet\n" );
siResult = eNotHandledByThisNode;
break;
case kGetAttributeEntry:
DBGLOG( "CNSLPlugin::HandleRequest, we don't handle kGetAttributeEntry yet\n" );
siResult = eNotHandledByThisNode;
break;
case kGetAttributeValue:
DBGLOG( "CNSLPlugin::HandleRequest, we don't handle kGetAttributeValue yet\n" );
siResult = eNotHandledByThisNode;
break;
case kOpenRecord:
siResult = OpenRecord( (sOpenRecord *)inData );
break;
case kGetRecordReferenceInfo:
DBGLOG( "CNSLPlugin::HandleRequest, we don't handle kGetRecordReferenceInfo yet\n" );
siResult = eNotHandledByThisNode;
break;
case kGetRecordAttributeInfo:
DBGLOG( "CNSLPlugin::HandleRequest, we don't handle kGetRecordAttributeInfo yet\n" );
siResult = eNotHandledByThisNode;
break;
case kGetRecordAttributeValueByID:
DBGLOG( "CNSLPlugin::HandleRequest, we don't handle kGetRecordAttributeValueByID yet\n" );
siResult = eNotHandledByThisNode;
break;
case kGetRecordAttributeValueByIndex:
DBGLOG( "CNSLPlugin::HandleRequest, we don't handle kGetRecordAttributeValueByIndex yet\n" );
siResult = eNotHandledByThisNode;
break;
case kFlushRecord:
siResult = FlushRecord( (sFlushRecord *)inData );
break;
case kCloseAttributeList:
DBGLOG( "CNSLPlugin::HandleRequest, we don't handle kCloseAttributeList yet\n" );
siResult = eNotHandledByThisNode;
break;
case kCloseAttributeValueList:
DBGLOG( "CNSLPlugin::HandleRequest, we don't handle kCloseAttributeValueList yet\n" );
siResult = eNotHandledByThisNode;
break;
case kCloseRecord:
siResult = CloseRecord( (sCloseRecord*)inData );
break;
case kSetRecordName:
DBGLOG( "CNSLPlugin::HandleRequest, we don't handle kSetRecordName yet\n" );
siResult = eNotHandledByThisNode;
break;
case kSetRecordType:
DBGLOG( "CNSLPlugin::HandleRequest, we don't handle kSetRecordType yet\n" );
siResult = eNotHandledByThisNode;
break;
case kDeleteRecord:
siResult = DeleteRecord( (sDeleteRecord*)inData );
break;
case kCreateRecord:
case kCreateRecordAndOpen:
siResult = CreateRecord( (sCreateRecord *)inData );
break;
case kAddAttribute:
DBGLOG( "CNSLPlugin::HandleRequest, we don't handle kAddAttribute yet\n" );
siResult = eNotHandledByThisNode;
break;
case kRemoveAttribute:
siResult = RemoveAttribute( (sRemoveAttribute*)inData );
break;
case kAddAttributeValue:
DBGLOG( "CNSLPlugin::HandleRequest, calling AddAttributeValue\n" );
siResult = AddAttributeValue( (sAddAttributeValue *)inData );
break;
case kRemoveAttributeValue:
siResult = RemoveAttributeValue( (sRemoveAttributeValue*)inData );
break;
case kSetAttributeValue:
siResult = SetAttributeValue( (sSetAttributeValue*)inData );
break;
case kDoDirNodeAuth:
DBGLOG( "CNSLPlugin::HandleRequest, we don't handle kDoDirNodeAuth yet\n" );
siResult = eNotHandledByThisNode;
break;
case kDoAttributeValueSearch:
case kDoAttributeValueSearchWithData:
DBGLOG( "CNSLPlugin::HandleRequest, we don't handle kDoAttributeValueSearch or kDoAttributeValueSearchWithData yet\n" );
siResult = eNotHandledByThisNode;
break;
case kDoPlugInCustomCall:
siResult = DoPlugInCustomCall( (sDoPlugInCustomCall *)inData );
break;
case kHandleNetworkTransition:
DBGLOG( "CNSLPlugin::HandleRequest, we have some sort of network transition\n" );
mTransitionCheckTime = time(nil) + 5;
if (mRunLoopRef != nil)
{
CFRunLoopTimerContext c = {0, (void*)this, NULL, NULL, NetworkChangeNSLCopyStringCallback};
CFRunLoopTimerRef timer = CFRunLoopTimerCreate( NULL,
CFAbsoluteTimeGetCurrent() + 5,
0,
0,
0,
DoNetworkTransition,
(CFRunLoopTimerContext*)&c);
CFRunLoopAddTimer(mRunLoopRef, timer, kCFRunLoopDefaultMode);
if (timer) CFRelease(timer);
}
break;
default:
siResult = eNotHandledByThisNode;
break;
}
pMsgHdr->fResult = siResult;
if ( siResult )
DBGLOG( "CNSLPlugin::HandleRequest returning %ld on a request of type %ld\n", siResult, pMsgHdr->fType );
return( siResult );
}
sInt32 CNSLPlugin::DoPlugInCustomCall ( sDoPlugInCustomCall *inData )
{
sInt32 siResult = eNotHandledByThisNode;
return siResult;
}
sInt32 CNSLPlugin::GetDirNodeInfo( sGetDirNodeInfo *inData )
{
sInt32 siResult = eNotHandledByThisNode;
DBGLOG( "CNSLPlugin::GetDirNodeInfo not handled by this plugin\n" );
return siResult;
}
sInt32 CNSLPlugin::OpenDirNode ( sOpenDirNode *inData )
{
sInt32 siResult = eDSNoErr;
char *nodeName = nil;
char *pathStr = nil;
char *protocolStr = nil;
tDataListPtr pNodeList = nil;
const char* subStr = nil;
Boolean weHandleThisNode = false;
DBGLOG( "CNSLPlugin::OpenDirNode %lx\n", inData->fOutNodeRef );
if ( inData != nil )
{
try {
pNodeList = inData->fInDirNodeName;
pathStr = dsGetPathFromListPriv( pNodeList, (char *)"/" );
protocolStr = pathStr + 1;
DBGLOG( "CNSLPlugin::OpenDirNode, ProtocolPrefixString is %s, pathStr is %s\n", GetProtocolPrefixString(), pathStr );
if ( strstr( pathStr, "NSLActivate" ) )
{
if ( !mActivatedByNSL )
{
mActivatedByNSL = true;
if ( IsActive() ) {
InstallNodeLookupTimer();
}
}
free( pathStr );
return eDSNoErr;
}
else if ( strcmp( protocolStr, GetProtocolPrefixString() ) == 0 )
{
nodeName = new char[1+strlen(protocolStr)];
if ( !nodeName ) throw ( eDSNullNodeName );
::strcpy(nodeName,protocolStr);
if ( nodeName )
{
DBGLOG( "CNSLPlugin::OpenDirNode on %s\n", nodeName );
CNSLDirNodeRep* newNodeRep = new CNSLDirNodeRep( this, (const void*)inData->fOutNodeRef );
if (!newNodeRep) throw ( eDSNullNodeName );
newNodeRep->Initialize( nodeName, inData->fInUID, true );
newNodeRep->Retain();
LockOpenRefTable();
::CFDictionaryAddValue( mOpenRefTable, (const void*)inData->fOutNodeRef, (const void*)newNodeRep );
UnlockOpenRefTable();
delete( nodeName );
nodeName = nil;
}
free( pathStr );
return eDSNoErr;
}
else if ( IsActive() && (strlen(pathStr) > strlen(GetProtocolPrefixString()+1)) && (::strncmp(protocolStr, GetProtocolPrefixString(), strlen(GetProtocolPrefixString())) == 0) && protocolStr[strlen(GetProtocolPrefixString())] == '/' )
{
subStr = pathStr + strlen(GetProtocolPrefixString()) + 2;
CFStringRef nodeAsRef = ::CFStringCreateWithCString( NULL, subStr, kCFStringEncodingUTF8 );
if ( nodeAsRef )
{
LockPublishedNodes();
weHandleThisNode = ::CFDictionaryContainsKey( mPublishedNodes, nodeAsRef );
UnlockPublishedNodes();
if ( weHandleThisNode )
DBGLOG( "CNSLPlugin::OpenDirNode, we will handle the request since we have this node (%s) already published\n", subStr );
else
{
if ( getenv("NSLDEBUG") )
{
DBGLOG( "CNSLPlugin::OpenDirNode, we don't handle this node, ref/publishedNodes\n" );
if ( nodeAsRef ) CFShow(nodeAsRef);
}
}
::CFRelease( nodeAsRef );
if ( !weHandleThisNode )
{
weHandleThisNode = OKToOpenUnPublishedNode( subStr );
if ( weHandleThisNode )
{
subStr = pathStr + strlen(GetProtocolPrefixString()) + 2;
DBGLOG( "CNSLPlugin::OpenDirNode Adding new node %s\n", subStr );
CFStringRef nodeRef = CFStringCreateWithCString( NULL, subStr, kCFStringEncodingUTF8 );
if ( nodeRef )
{
NodeData* node = AllocateNodeData();
node->fNodeName = nodeRef;
CFRetain( node->fNodeName );
node->fDSName = dsBuildListFromStringsPriv(GetProtocolPrefixString(), subStr, nil);
node->fTimeStamp = GetCurrentTime();
node->fServicesRefTable = ::CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
node->fIsADefaultNode = IsLocalNode( subStr );
node->fSignature = mSignature;
if ( node->fDSName )
{
eDirNodeType nodeTypeToRegister = kUnknownNodeType;
if ( IsLocalNode( subStr ) )
nodeTypeToRegister = kDefaultNetworkNodeType;
nodeTypeToRegister = (eDirNodeType)( nodeTypeToRegister | kDirNodeType );
if ( nodeTypeToRegister != kUnknownNodeType )
DSRegisterNode( mSignature, node->fDSName, nodeTypeToRegister );
}
::CFDictionaryAddValue( mPublishedNodes, nodeRef, node );
::CFRelease( nodeRef );
}
}
}
if ( !weHandleThisNode )
DBGLOG( "CNSLPlugin::OpenDirNode, we won't handle the request on this node (%s)\n", pathStr );
}
}
if ( weHandleThisNode )
{
if ( !subStr )
subStr = pathStr + strlen(GetProtocolPrefixString()) + 2;
if ( subStr )
{
DBGLOG( "CNSLPlugin::OpenDirNode subStr is %s\n", subStr );
nodeName = new char[1+strlen(subStr)];
if( !nodeName ) throw ( eDSNullNodeName );
::strcpy(nodeName,subStr);
}
if ( nodeName )
{
DBGLOG( "CNSLPlugin::OpenDirNode on %s\n", nodeName );
CNSLDirNodeRep* newNodeRep = new CNSLDirNodeRep( this, (const void*)inData->fOutNodeRef );
if( !newNodeRep ) throw (eMemoryAllocError);
newNodeRep->Initialize( nodeName, inData->fInUID, false );
newNodeRep->Retain();
LockOpenRefTable();
::CFDictionaryAddValue( mOpenRefTable, (const void*)inData->fOutNodeRef, (const void*)newNodeRep );
UnlockOpenRefTable();
delete( nodeName );
nodeName = nil;
}
else
{
inData->fOutNodeRef = 0;
DBGLOG( "CNSLPlugin::OpenDirNode nodeName is NULL!\n" );
}
}
else
{
siResult = eNotHandledByThisNode;
DBGLOG( "CNSLPlugin::OpenDirNode skipping cuz path is %s\n", pathStr );
}
}
catch( int err )
{
siResult = err;
DBGLOG( "CNSLPlugin::CloseDirNode, Caught error:%li\n", siResult );
}
}
else
DBGLOG( "CNSLPlugin::OpenDirNode inData is NULL!\n" );
if (pathStr != NULL)
{
free(pathStr);
pathStr = NULL;
}
if ( nodeName )
{
delete( nodeName );
nodeName = nil;
}
return siResult;
}
sInt32 CNSLPlugin::CloseDirNode ( sCloseDirNode *inData )
{
sInt32 siResult = eDSNoErr;
DBGLOG( "CNSLPlugin::CloseDirNode %lx\n", inData->fInNodeRef );
try
{
if ( inData != nil && inData->fInNodeRef && mOpenRefTable )
{
CNSLDirNodeRep* nodeRep = NULL;
LockOpenRefTable();
nodeRep = (CNSLDirNodeRep*)::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInNodeRef );
DBGLOG( "CNSLPlugin::CloseDirNode, CFDictionaryGetValue returned nodeRep: 0x%x\n", (void*)nodeRep );
if ( nodeRep )
{
::CFDictionaryRemoveValue( mOpenRefTable, (void*)inData->fInNodeRef );
DBGLOG( "CNSLPlugin::CloseDirNode, delete nodeRep: 0x%x\n", (void*)nodeRep );
nodeRep->Release();
}
else
{
DBGLOG( "CNSLPlugin::CloseDirNode, nodeRef not found in our list\n" );
}
UnlockOpenRefTable();
}
}
catch( int err )
{
siResult = err;
DBGLOG( "CNSLPlugin::CloseDirNode, Caught error:%li\n", siResult );
}
return siResult;
}
sInt32 CNSLPlugin::GetRecordList ( sGetRecordList *inData )
{
sInt32 siResult = eDSNoErr;
char *pRecType = nil;
char *pNSLRecType = nil;
CAttributeList *cpRecNameList = nil;
CAttributeList *cpRecTypeList = nil;
CAttributeList *cpAttrTypeList = nil;
CBuff *outBuff = nil;
uInt32 countDownRecTypes = 0;
const void* dictionaryResult = NULL;
CNSLDirNodeRep* nodeDirRep = NULL;
unsigned long incomingRecEntryCount = inData->fOutRecEntryCount;
LockOpenRefTable();
DBGLOG( "CNSLPlugin::GetRecordList called\n" );
dictionaryResult = ::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInNodeRef );
nodeDirRep = (CNSLDirNodeRep*)dictionaryResult;
if( !nodeDirRep )
{
DBGLOG( "CNSLPlugin::GetRecordList called but we couldn't find the nodeDirRep!\n" );
UnlockOpenRefTable();
return eDSInvalidNodeRef;
}
if ( nodeDirRep->IsTopLevelNode() )
{
DBGLOG( "CNSLPlugin::GetRecordList called on a top level node, return no results\n" );
inData->fIOContinueData = NULL;
inData->fOutRecEntryCount = 0;
UnlockOpenRefTable();
return eDSNoErr;
}
nodeDirRep->Retain();
UnlockOpenRefTable();
inData->fOutRecEntryCount = 0;
try
{
if ( nodeDirRep && !nodeDirRep->IsLookupStarted() )
{
DBGLOG( "CNSLPlugin::GetRecordList called, lookup hasn't been started yet.\n" );
if( !inData ) throw( eMemoryError );
if( !inData->fInDataBuff) throw( eDSEmptyBuffer );
if( (inData->fInDataBuff->fBufferSize == 0) ) throw( eDSEmptyBuffer );
if( !inData->fInRecNameList ) throw( eDSEmptyRecordNameList );
if( !inData->fInRecTypeList ) throw( eDSEmptyRecordTypeList );
if( !inData->fInAttribTypeList ) throw( eDSEmptyAttributeTypeList );
if (incomingRecEntryCount >= 0)
{
nodeDirRep->LimitRecSearch( incomingRecEntryCount );
}
cpRecTypeList = new CAttributeList( inData->fInRecTypeList );
if( !cpRecTypeList ) throw( eDSEmptyRecordTypeList );
countDownRecTypes = cpRecTypeList->GetCount();
if( (countDownRecTypes == 0) ) throw( eDSEmptyRecordTypeList );
sInt32 error = eDSNoErr;
nodeDirRep->LookupHasStarted();
Boolean alreadyLookedupSMBType = false;
for ( uInt16 i=1; i<=countDownRecTypes; i++ )
{
if ( (error = cpRecTypeList->GetAttribute( i, &pRecType )) == eDSNoErr )
{
DBGLOG( "CNSLPlugin::GetRecordList, GetAttribute returned pRecType:%s\n", pRecType );
if ( pRecType )
{
if ( strcmp( pRecType, kDSStdRecordTypeSMBServer ) == 0 )
{
if ( alreadyLookedupSMBType )
{
free( pNSLRecType );
continue; }
alreadyLookedupSMBType = true;
}
pNSLRecType = CreateNSLTypeFromRecType( pRecType );
if ( pNSLRecType )
{
DBGLOG( "CNSLPlugin::GetRecordList, CreateNSLTypeFromRecType returned pNSLRecType:%s\n", pNSLRecType );
StartServicesLookup( pNSLRecType, nodeDirRep );
free( pNSLRecType );
inData->fIOContinueData = (void*)inData->fInNodeRef; }
}
}
else
{
DBGLOG( "CNSLPlugin::GetRecordList, GetAttribute returned error:%li\n", error );
}
}
}
else if ( nodeDirRep && nodeDirRep->HaveResults() )
{
siResult = RetrieveResults( inData, nodeDirRep );
inData->fIOContinueData = (void*)inData->fInNodeRef; DBGLOG( "***Sending Back Results, fBufferSize = %ld, fBufferLength = %ld, inData->fOutRecEntryCount = %d\n", inData->fInDataBuff->fBufferSize, inData->fInDataBuff->fBufferLength, inData->fOutRecEntryCount );
}
else if ( nodeDirRep && nodeDirRep->LookupComplete() )
{
DBGLOG( "CNSLPlugin::GetRecordList called and nodeDirRep->LookupComplete so setting inData->fIOContinueData to NULL\n" );
inData->fIOContinueData = NULL;
nodeDirRep->ResetLookupHasStarted(); }
else
SmartSleep( 100000 ); }
catch ( int err )
{
siResult = err;
DBGLOG( "CNSLPlugin::GetRecordList, Caught error:%li\n", siResult );
}
LockOpenRefTable();
if ( nodeDirRep )
nodeDirRep->Release();
UnlockOpenRefTable();
if ( cpRecNameList != nil )
{
delete( cpRecNameList );
cpRecNameList = nil;
}
if ( cpRecTypeList != nil )
{
delete( cpRecTypeList );
cpRecTypeList = nil;
}
if ( cpAttrTypeList != nil )
{
delete( cpAttrTypeList );
cpAttrTypeList = nil;
}
if ( outBuff != nil )
{
delete( outBuff );
outBuff = nil;
}
return( siResult );
}
sInt32 CNSLPlugin::OpenRecord ( sOpenRecord *inData )
{
sInt32 siResult = eDSRecordNotFound; const void* dictionaryResult = NULL;
DBGLOG( "CNSLPlugin::OpenRecord called on refNum:0x%x\n", inData->fOutRecRef );
LockOpenRefTable();
dictionaryResult = ::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInNodeRef );
if ( !dictionaryResult )
{
UnlockOpenRefTable();
DBGLOG( "CNSLPlugin::OpenRecord called but we couldn't find the nodeDirRep!\n" );
return eDSInvalidNodeRef;
}
((CNSLDirNodeRep*)dictionaryResult)->Retain();
UnlockOpenRefTable();
CFStringRef nodeNameRef = ((CNSLDirNodeRep*)dictionaryResult)->GetNodeName();
char* pNSLRecType = CreateNSLTypeFromRecType( (char*)inData->fInRecType->fBufferData );
if ( pNSLRecType )
{
CFMutableStringRef serviceKeyRef = ::CFStringCreateMutable( NULL, 0 ); CFStringRef recordTypeRef = ::CFStringCreateWithCString( kCFAllocatorDefault, pNSLRecType, kCFStringEncodingUTF8 );
CFStringRef recordNameRef = ::CFStringCreateWithCString( kCFAllocatorDefault, (char*)inData->fInRecName->fBufferData, kCFStringEncodingUTF8 );
if ( serviceKeyRef && recordTypeRef && recordNameRef )
{
::CFStringAppend( serviceKeyRef, recordNameRef );
::CFStringAppend( serviceKeyRef, recordTypeRef );
}
if ( recordNameRef )
CFRelease( recordNameRef );
if ( recordTypeRef )
CFRelease( recordTypeRef );
free( pNSLRecType );
LockPublishedNodes();
NodeData* node = (NodeData*)::CFDictionaryGetValue( mPublishedNodes, nodeNameRef );
if ( node )
{
if ( getenv("NSLDEBUG") )
{
DBGLOG( "CNSLPlugin::OpenRecord, found the node in question\n" );
CFShow( nodeNameRef );
DBGLOG( "CNSLPlugin::OpenRecord, looking up record\n" );
CFShow( serviceKeyRef );
}
CFDictionaryRef recordRef = (CFDictionaryRef)::CFDictionaryGetValue( node->fServicesRefTable, serviceKeyRef );
if ( recordRef )
CFRetain( recordRef );
UnlockPublishedNodes();
if ( recordRef && CFGetTypeID(recordRef) == CFDictionaryGetTypeID() )
{
CFStringRef recordName = (CFStringRef)::CFDictionaryGetValue( recordRef, kDSNAttrRecordNameSAFE_CFSTR );
CFStringRef nodeName = (CFStringRef)::CFDictionaryGetValue( recordRef, kDS1AttrLocationSAFE_CFSTR );
if ( !recordName && !nodeName )
{
if ( getenv("NSLDEBUG") )
{
DBGLOG( "CNSLPlugin::OpenRecord, the node->fServicesRefTable doesn't have both recordName and nodeName keys!\n" );
if (recordName) CFShow( recordName ); else DBGLOG( "CNSLPlugin::OpenRecord, recordName is null\n" );
if (nodeName) CFShow( nodeName ); else DBGLOG( "CNSLPlugin::OpenRecord, nodeName is null\n" );
}
}
else if ( CFGetTypeID(recordName) == CFStringGetTypeID() && CFGetTypeID(nodeName) == CFStringGetTypeID() )
{
CFRetain( recordRef );
LockOpenRefTable();
::CFDictionaryAddValue( mOpenRefTable, (void*)inData->fOutRecRef, (void*)recordRef );
UnlockOpenRefTable();
siResult = eDSNoErr;
if ( getenv("NSLDEBUG") )
{
DBGLOG( "CNSLPlugin::OpenRecord, found the record in question (ref:0x%x)\n", inData->fOutRecRef );
}
}
else
DBGLOG( "CNSLPlugin::OpenRecord, we just grabbed a name or node name that wasn't a CFString!\n" );
}
else if ( recordRef )
DBGLOG( "CNSLPlugin::OpenRecord, we just grabbed something out of our node->fServicesRefTable that wasn't a CFDictionary!\n" );
else
DBGLOG( "CNSLPlugin::OpenRecord, couldn't find previously created record\n" );
if ( recordRef )
CFRelease( recordRef ); }
else
{
UnlockPublishedNodes();
DBGLOG( "CNSLPlugin::OpenRecord this record already opened...\n" );
siResult = eDSNoErr;
}
::CFRelease( serviceKeyRef );
}
((CNSLDirNodeRep*)dictionaryResult)->Release();
return( siResult );
}
sInt32 CNSLPlugin::CloseRecord ( sCloseRecord *inData )
{
sInt32 siResult = eDSNoErr;
DBGLOG( "CNSLPlugin::CloseRecord called on ref:%ld\n", inData->fInRecRef );
LockOpenRefTable();
CFDictionaryRef recordRef = (CFDictionaryRef)::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInRecRef );
if ( recordRef )
{
::CFDictionaryRemoveValue( mOpenRefTable, (const void*)inData->fInRecRef );
CFRelease( recordRef );
}
else
{
DBGLOG( "CNSLPlugin::CloseRecord called but the record wasn't found!\n" );
siResult = eDSRecordNotFound;
}
UnlockOpenRefTable();
return( siResult );
}
sInt32 CNSLPlugin::CreateRecord ( sCreateRecord *inData )
{
sInt32 siResult = eDSNoErr; const void* dictionaryResult = NULL;
CNSLDirNodeRep* nodeDirRep = NULL;
tDataNodePtr pRecName = NULL;
tDataNodePtr pRecType = NULL;
char *pNSLRecType = NULL;
CFMutableStringRef serviceKeyRef = NULL;
CFMutableDictionaryRef newService = NULL;
DBGLOG( "CNSLPlugin::CreateRecord called\n" );
DBGLOG( "CNSLPlugin::CreateRecord, fOutRecRef is 0x%x\n", inData->fOutRecRef );
DBGLOG( "CNSLPlugin::CreateRecord, fInOpen is %d\n", inData->fInOpen );
if ( ReadOnlyPlugin() )
{
return eDSReadOnly;
}
if ( !IsClientAuthorizedToCreateRecords( inData ) )
{
return eDSPermissionError;
}
try
{
LockOpenRefTable();
dictionaryResult = ::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInNodeRef );
if ( !dictionaryResult )
{
UnlockOpenRefTable();
DBGLOG( "CNSLPlugin::CreateRecord called but we couldn't find the nodeDirRep!\n" );
return eDSInvalidNodeRef;
}
nodeDirRep = (CNSLDirNodeRep*)dictionaryResult;
nodeDirRep->Retain();
UnlockOpenRefTable();
serviceKeyRef = ::CFStringCreateMutable( NULL, 0 );
newService = ::CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
pRecType = inData->fInRecType;
if( !pRecType ) throw( eDSNullRecType );
pRecName = inData->fInRecName;
if( !pRecName ) throw( eDSNullRecName );
pNSLRecType = CreateNSLTypeFromRecType( (char*)pRecType->fBufferData );
if( !pNSLRecType ) throw( eDSInvalidRecordType );
if ( pNSLRecType )
{
if ( getenv("NSLDEBUG") )
{
DBGLOG( "CNSLPlugin::CreateRecord, CreateNSLTypeFromRecType returned pNSLRecType:%s\n", pNSLRecType );
DBGLOG( "dictionary contents before:\n");
CFShow( newService );
}
CFStringRef keyRef, valueRef;
keyRef = ::CFStringCreateWithCString( kCFAllocatorDefault, kDS1AttrLocation, kCFStringEncodingUTF8 );
valueRef = nodeDirRep->GetNodeName();
if ( !CFDictionaryContainsKey( newService, keyRef ) )
::CFDictionaryAddValue( newService, keyRef, valueRef );
::CFRelease( keyRef );
keyRef = ::CFStringCreateWithCString( kCFAllocatorDefault, kDSNAttrRecordName, kCFStringEncodingUTF8 );
valueRef = ::CFStringCreateWithCString( kCFAllocatorDefault, (char*)pRecName->fBufferData, kCFStringEncodingUTF8 );
if ( !CFDictionaryContainsKey( newService, keyRef ) )
::CFDictionaryAddValue( newService, keyRef, valueRef );
::CFStringAppend( serviceKeyRef, valueRef );
::CFRelease( keyRef );
::CFRelease( valueRef );
keyRef = ::CFStringCreateWithCString( kCFAllocatorDefault, kDS1AttrServiceType, kCFStringEncodingUTF8 );
valueRef = ::CFStringCreateWithCString( kCFAllocatorDefault, pNSLRecType, kCFStringEncodingUTF8 );
::CFDictionarySetValue( newService, keyRef, valueRef );
::CFStringAppend( serviceKeyRef, valueRef );
::CFRelease( keyRef );
::CFRelease( valueRef );
if ( getenv("NSLDEBUG") )
{
DBGLOG( "dictionary contents after:\n");
CFShow( newService );
DBGLOG( "CNSLPlugin::CreateRecord, finished intial creation of opened service dictionary\n" );
if ( getenv( "NSLDEBUG" ) )
::CFShow( newService );
}
free( pNSLRecType );
LockPublishedNodes();
if ( ::CFDictionaryContainsKey( mPublishedNodes, nodeDirRep->GetNodeName() ) )
{
NodeData* node = (NodeData*)::CFDictionaryGetValue( mPublishedNodes, nodeDirRep->GetNodeName() );
if ( node )
{
::CFDictionarySetValue( node->fServicesRefTable, serviceKeyRef, newService );
if ( getenv( "NSLDEBUG" ) )
{
DBGLOG( "CNSLPlugin::CreateRecord, adding key to node\n" );
CFShow( serviceKeyRef );
}
}
else
DBGLOG( "CNSLPlugin::CreateRecord, couldn't find node in our published nodes!\n" );
}
UnlockPublishedNodes();
}
}
catch ( int err )
{
siResult = err;
}
LockOpenRefTable();
nodeDirRep->Release();
UnlockOpenRefTable();
if ( serviceKeyRef )
CFRelease( serviceKeyRef );
if ( newService )
CFRelease( newService );
DBGLOG( "CNSLPlugin::CreateRecord, fOutRecRef is 0x%x\n", inData->fOutRecRef );
if ( !siResult && inData->fInOpen )
{
sOpenRecord inCopyData = { inData->fType, inData->fResult, inData->fInNodeRef, inData->fInRecType, inData->fInRecName, inData->fOutRecRef };
siResult = OpenRecord( &inCopyData );
DBGLOG( "CNSLPlugin::CreateRecord, fOutRecRef after OpenRecord is 0x%x\n", inData->fOutRecRef );
}
else
DBGLOG( "CNSLPlugin::CreateRecord, siResult:%ld, inData->fInOpen=%d, fOutRecRef is 0x%x\n", siResult, inData->fInOpen, inData->fOutRecRef );
if ( kCreateRecordAndOpen == inData->fType )
DBGLOG( "CNSLPlugin::CreateRecord, this was supposed to be a kCreateRecordAndOpen\n");
return( siResult );
}
sInt32 CNSLPlugin::DeleteRecord ( sDeleteRecord *inData )
{
sInt32 siResult = eDSNoErr;
CFMutableDictionaryRef serviceToDeregister = NULL;
DBGLOG( "CNSLPlugin::DeleteRecord called on refNum:%ld\n", inData->fInRecRef );
if ( inData->fInRecRef )
{
LockOpenRefTable();
serviceToDeregister = (CFMutableDictionaryRef)::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInRecRef );
if ( serviceToDeregister )
CFRetain( serviceToDeregister );
UnlockOpenRefTable();
if ( serviceToDeregister )
{
siResult = DeregisterService( inData->fInRecRef, serviceToDeregister );
if ( siResult && siResult != eDSNullAttribute )
{
char name[1024] = {0,};
char type[256] = {0,};
CFStringRef nameOfService = (CFStringRef)::CFDictionaryGetValue( serviceToDeregister, kDSNAttrRecordNameSAFE_CFSTR );
if ( nameOfService )
CFStringGetCString( nameOfService, name, sizeof(name), kCFStringEncodingUTF8 );
CFStringRef typeOfService = (CFStringRef)::CFDictionaryGetValue( serviceToDeregister, kDS1AttrServiceTypeSAFE_CFSTR );
if ( !typeOfService )
typeOfService = (CFStringRef)::CFDictionaryGetValue( serviceToDeregister, kDSNAttrRecordTypeSAFE_CFSTR );
if ( typeOfService )
CFStringGetCString( typeOfService, type, sizeof(type), kCFStringEncodingUTF8 );
DBGLOG( "DS (%s) couldn't deregister %s (%s) due to an error: %d!\n", GetProtocolPrefixString(), name, type, siResult );
}
CFRelease( serviceToDeregister );
}
else
syslog( LOG_ERR, "CNSLPlugin::DeleteRecord, couldn't find record to delete!\n" );
}
else
{
siResult = eDSInvalidRecordRef;
syslog( LOG_ERR, "CNSLPlugin::DeleteRecord called with invalid fInRecRef (0x%x)!\n", inData->fInRecRef );
}
return( siResult );
}
sInt32 CNSLPlugin::FlushRecord ( sFlushRecord *inData )
{
sInt32 siResult = eDSNoErr;
CFMutableDictionaryRef serviceToRegister = NULL;
DBGLOG( "CNSLPlugin::FlushRecord called on refNum:%ld\n", inData->fInRecRef );
try
{
if ( inData->fInRecRef )
{
LockOpenRefTable();
serviceToRegister = (CFMutableDictionaryRef)::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInRecRef );
if ( serviceToRegister )
CFRetain( serviceToRegister );
UnlockOpenRefTable();
if ( serviceToRegister )
{
DBGLOG( "CNSLPlugin::FlushRecord calling RegisterService with the following service:\n" );
if ( getenv( "NSLDEBUG" ) )
::CFShow( serviceToRegister );
siResult = RegisterService( inData->fInRecRef, serviceToRegister );
if ( siResult && siResult != eDSNullAttribute )
{
char name[1024] = {0,};
char type[256] = {0,};
CFStringRef nameOfService = (CFStringRef)::CFDictionaryGetValue( serviceToRegister, kDSNAttrRecordNameSAFE_CFSTR );
if ( nameOfService )
CFStringGetCString( nameOfService, name, sizeof(name), kCFStringEncodingUTF8 );
CFStringRef typeOfService = (CFStringRef)::CFDictionaryGetValue( serviceToRegister, kDS1AttrServiceTypeSAFE_CFSTR );
if ( !typeOfService )
typeOfService = (CFStringRef)::CFDictionaryGetValue( serviceToRegister, kDSNAttrRecordTypeSAFE_CFSTR );
if ( typeOfService )
CFStringGetCString( typeOfService, type, sizeof(type), kCFStringEncodingUTF8 );
syslog( LOG_ERR, "DS (%s) couldn't register %s (%s) due to an error: %d!\n", GetProtocolPrefixString(), name, type, siResult );
}
CFRelease( serviceToRegister );
}
else
DBGLOG( "CNSLPlugin::FlushRecord, couldn't find service to register!\n" );
}
else
{
siResult = eDSInvalidReference;
DBGLOG( "CNSLPlugin::FlushRecord called with invalid fInRecRef.\n" );
}
}
catch ( int err )
{
siResult = err;
}
return( siResult );
}
#pragma mark -
sInt32 CNSLPlugin::AddAttributeValue ( sAddAttributeValue *inData )
{
sInt32 siResult = eDSNoErr;
CFMutableDictionaryRef serviceToManipulate = NULL;
DBGLOG( "CNSLPlugin::AddAttributeValue called\n" );
try
{
if ( inData->fInRecRef )
{
LockOpenRefTable();
serviceToManipulate = (CFMutableDictionaryRef)::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInRecRef );
if ( serviceToManipulate )
CFRetain( serviceToManipulate );
UnlockOpenRefTable();
if ( serviceToManipulate && CFGetTypeID(serviceToManipulate) == CFDictionaryGetTypeID() )
{
CFStringRef keyRef, valueRef;
CFTypeRef existingValueRef = NULL;
keyRef = ::CFStringCreateWithCString( kCFAllocatorDefault, inData->fInAttrType->fBufferData, kCFStringEncodingUTF8 );
valueRef = ::CFStringCreateWithCString( kCFAllocatorDefault, inData->fInAttrValue->fBufferData, kCFStringEncodingUTF8 );
if ( keyRef && valueRef )
{
existingValueRef = ::CFDictionaryGetValue( serviceToManipulate, keyRef );
if ( existingValueRef && ::CFGetTypeID( existingValueRef ) == ::CFArrayGetTypeID() )
{
::CFArrayAppendValue( (CFMutableArrayRef)existingValueRef, valueRef );
}
else if ( existingValueRef && ::CFGetTypeID( existingValueRef ) == ::CFStringGetTypeID() )
{
if ( ::CFStringCompare( (CFStringRef)keyRef, kDS1AttrServiceTypeSAFE_CFSTR, 0 ) != kCFCompareEqualTo )
{
if ( ::CFStringCompare( (CFStringRef)existingValueRef, valueRef, 0 ) != kCFCompareEqualTo )
{
CFStringRef oldStringRef = (CFStringRef)existingValueRef;
CFMutableArrayRef newArrayRef = ::CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
::CFArrayAppendValue( newArrayRef, oldStringRef );
::CFArrayAppendValue( newArrayRef, valueRef );
::CFDictionaryRemoveValue( serviceToManipulate, keyRef );
::CFDictionaryAddValue( serviceToManipulate, keyRef, newArrayRef );
::CFRelease( newArrayRef );
}
}
}
else
{
::CFDictionaryAddValue( serviceToManipulate, keyRef, valueRef );
}
::CFRelease( keyRef );
::CFRelease( valueRef );
}
else if ( !keyRef )
siResult = eDSInvalidRefType;
else if ( !valueRef )
siResult = eDSInvalidAttrValueRef;
}
else
siResult = eDSInvalidRecordRef;
if ( serviceToManipulate )
CFRelease( serviceToManipulate );
}
else
{
siResult = eDSInvalidRecordRef;
DBGLOG( "CNSLPlugin::AddAttributeValue called but with no value in fInRecRef (0x%x) not in our list.\n", (const void*)inData->fInRecRef );
}
}
catch ( int err )
{
siResult = err;
}
return( siResult );
}
sInt32 CNSLPlugin::RemoveAttribute ( sRemoveAttribute *inData )
{
sInt32 siResult = eDSNoErr;
CFMutableDictionaryRef serviceToManipulate = NULL;
try
{
if ( inData->fInRecRef )
{
LockOpenRefTable();
serviceToManipulate = (CFMutableDictionaryRef)::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInRecRef );
CFStringRef keyRef;
keyRef = ::CFStringCreateWithCString( kCFAllocatorDefault, inData->fInAttribute->fBufferData, kCFStringEncodingUTF8 );
if ( keyRef )
{
::CFDictionaryRemoveValue( serviceToManipulate, keyRef );
::CFRelease( keyRef );
}
UnlockOpenRefTable();
}
else
{
siResult = eDSInvalidRecordRef;
DBGLOG( "CNSLPlugin::RemoveAttribute called but with no value in fOurRecRef.\n" );
}
}
catch ( int err )
{
siResult = err;
}
return( siResult );
}
sInt32 CNSLPlugin::RemoveAttributeValue ( sRemoveAttributeValue *inData )
{
sInt32 siResult = eDSNoErr;
CFMutableDictionaryRef serviceToManipulate = NULL;
try
{
if ( inData->fInRecRef )
{
LockOpenRefTable();
serviceToManipulate = (CFMutableDictionaryRef)::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInRecRef );
if ( serviceToManipulate )
CFRetain( serviceToManipulate );
UnlockOpenRefTable();
if ( serviceToManipulate )
{
CFStringRef keyRef;
CFPropertyListRef valueRef;
keyRef = ::CFStringCreateWithCString( kCFAllocatorDefault, inData->fInAttrType->fBufferData, kCFStringEncodingUTF8 );
valueRef = (CFPropertyListRef)::CFDictionaryGetValue( serviceToManipulate, keyRef );
if ( valueRef && ::CFGetTypeID( valueRef ) == ::CFArrayGetTypeID() )
{
if ( (UInt32)::CFArrayGetCount( (CFMutableArrayRef)valueRef ) > inData->fInAttrValueID )
::CFArrayRemoveValueAtIndex( (CFMutableArrayRef)valueRef, inData->fInAttrValueID );
else
siResult = eDSIndexOutOfRange;
}
else if ( valueRef && ::CFGetTypeID( valueRef ) == ::CFStringGetTypeID() )
{
::CFDictionaryRemoveValue( serviceToManipulate, keyRef );
}
else
siResult = eDSInvalidAttrValueRef;
if ( keyRef )
::CFRelease( keyRef );
if ( valueRef )
::CFRelease( valueRef );
CFRelease( serviceToManipulate );
}
}
else
{
siResult = eDSInvalidRecordRef;
DBGLOG( "CNSLPlugin::RemoveAttributeValue called but with no value in fOurRecRef.\n" );
}
}
catch ( int err )
{
siResult = err;
}
return( siResult );
}
sInt32 CNSLPlugin::SetAttributeValue ( sSetAttributeValue *inData )
{
sInt32 siResult = eDSNoErr;
CFMutableDictionaryRef serviceToManipulate = NULL;
try
{
if ( inData->fInRecRef )
{
LockOpenRefTable();
serviceToManipulate = (CFMutableDictionaryRef)::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInRecRef );
if ( serviceToManipulate )
CFRetain( serviceToManipulate );
UnlockOpenRefTable();
if ( serviceToManipulate )
{
CFStringRef keyRef = NULL, valueRef = NULL;
CFMutableArrayRef attributeArrayRef = NULL;
keyRef = ::CFStringCreateWithCString( kCFAllocatorDefault, inData->fInAttrType->fBufferData, kCFStringEncodingUTF8 );
valueRef = ::CFStringCreateWithCString( kCFAllocatorDefault, inData->fInAttrValueEntry->fAttributeValueData.fBufferData, kCFStringEncodingUTF8 );
if ( keyRef )
attributeArrayRef = (CFMutableArrayRef)::CFDictionaryGetValue( serviceToManipulate, keyRef );
if ( attributeArrayRef && ::CFGetTypeID( attributeArrayRef ) == ::CFArrayGetTypeID() )
{
if ( (UInt32)::CFArrayGetCount( (CFMutableArrayRef)attributeArrayRef ) > inData->fInAttrValueEntry->fAttributeValueID )
::CFArraySetValueAtIndex( (CFMutableArrayRef)attributeArrayRef, inData->fInAttrValueEntry->fAttributeValueID, valueRef );
else
siResult = eDSIndexOutOfRange;
}
else if ( attributeArrayRef && ::CFGetTypeID( attributeArrayRef ) == ::CFStringGetTypeID() )
{
::CFDictionaryRemoveValue( serviceToManipulate, keyRef );
::CFDictionarySetValue( serviceToManipulate, keyRef, valueRef );
}
else
siResult = eDSInvalidAttrValueRef;
if ( keyRef )
CFRelease( keyRef );
if ( valueRef )
CFRelease( valueRef );
CFRelease( serviceToManipulate );
}
}
else
{
siResult = eDSInvalidRecordRef;
DBGLOG( "CNSLPlugin::SetAttributeValue called but with no value in fOurRecRef.\n" );
}
}
catch ( int err )
{
siResult = err;
}
return( siResult );
}
sInt32 CNSLPlugin::RegisterService( tRecordReference recordRef, CFDictionaryRef service )
{
return eDSReadOnly;
}
sInt32 CNSLPlugin::DeregisterService( tRecordReference recordRef, CFDictionaryRef service )
{
return eDSReadOnly;
}
#pragma mark -
void CNSLPlugin::HandleNetworkTransitionIfTime( void )
{
if (time(nil) >= mTransitionCheckTime)
HandleNetworkTransition( NULL );
}
sInt32 CNSLPlugin::HandleNetworkTransition( sHeader *inData )
{
sInt32 siResult = eDSNoErr;
DBGLOG( "CNSLPlugin::HandleNetworkTransition called (%s)\n", GetProtocolPrefixString() );
if ( mActivatedByNSL && IsActive() )
{
ClearOutAllNodes();
ResetNodeLookupTimer( kNodeTimerIntervalImmediate );
}
else
{
DBGLOG( "CNSLPlugin::HandleNetworkTransition called (%s) but mActivatedByNSL == %d && IsActive() == %d \n", GetProtocolPrefixString(), mActivatedByNSL, IsActive() );
}
return siResult;
}
Boolean CNSLPlugin::IsClientAuthorizedToCreateRecords( sCreateRecord *inData )
{
return true;
}
Boolean CNSLPlugin::ResultMatchesRequestCriteria( const CNSLResult* result, sGetRecordList* request )
{
if ( request->fInPatternMatch == eDSAnyMatch )
return true;
Boolean resultIsOK = false;
CAttributeList* cpRecNameList = new CAttributeList( request->fInRecNameList );
CFStringRef resultRecordNameRef = result->GetAttributeRef( kDSNAttrRecordNameSAFE_CFSTR );
if ( cpRecNameList )
{
sInt32 error = eDSNoErr;
uInt32 numRecNames = cpRecNameList->GetCount();
char *pRecName = nil;
for ( uInt16 i=1; !resultIsOK && i<=numRecNames; i++ )
{
if ( (error = cpRecNameList->GetAttribute( i, &pRecName )) == eDSNoErr )
{
CFStringRef recNameMatchRef = NULL;
if ( pRecName && strcmp( pRecName, kDSRecordsAll ) == 0 )
{
resultIsOK = true;
break;
}
else if ( pRecName && strcmp( pRecName, kDSRecordsStandardAll ) == 0 )
{
if ( result->GetAttributeRef( kDSNAttrRecordNameSAFE_CFSTR ) && CFStringHasPrefix( result->GetAttributeRef( kDSNAttrRecordTypeSAFE_CFSTR ), kDSStdRecordTypePrefixSAFE_CFSTR ) )
{
resultIsOK = true;
break;
}
else
continue;
}
else if ( pRecName && strcmp( pRecName, kDSRecordsNativeAll ) == 0 )
{
if ( result->GetAttributeRef( kDSNAttrRecordNameSAFE_CFSTR ) && CFStringHasPrefix( result->GetAttributeRef( kDSNAttrRecordTypeSAFE_CFSTR ), kDSNativeRecordTypePrefixSAFE_CFSTR ) )
{
resultIsOK = true;
break;
}
else
continue;
}
recNameMatchRef = CFStringCreateWithCString( NULL, pRecName, kCFStringEncodingUTF8 );
if ( recNameMatchRef )
{
if ( request->fInPatternMatch == eDSExact && CFStringCompare( resultRecordNameRef, recNameMatchRef, 0 ) == kCFCompareEqualTo )
{
resultIsOK = true;
}
else if ( request->fInPatternMatch >= eDSiExact && CFStringCompare( resultRecordNameRef, recNameMatchRef, kCFCompareCaseInsensitive ) == kCFCompareEqualTo )
{
resultIsOK = true;
}
else if ( request->fInPatternMatch == eDSStartsWith && CFStringHasPrefix( resultRecordNameRef, recNameMatchRef ) )
{
resultIsOK = true;
}
else if ( request->fInPatternMatch == eDSEndsWith && CFStringHasSuffix( resultRecordNameRef, recNameMatchRef ) )
{
resultIsOK = true;
}
else if ( request->fInPatternMatch == eDSContains )
{
CFRange result = CFStringFind( resultRecordNameRef, recNameMatchRef, 0 );
if ( result.length > 0 )
resultIsOK = true;
}
CFRelease( recNameMatchRef );
}
}
}
delete cpRecNameList;
}
return resultIsOK;
}
sInt32 CNSLPlugin::RetrieveResults( sGetRecordList* inData, CNSLDirNodeRep* nodeRep )
{
sInt32 siResult = eDSNoErr;
CDataBuff* aRecData = nil;
CDataBuff* aAttrData = nil;
CDataBuff* aTempData = nil;
CBuff* outBuff = nil;
DBGLOG( "CNSLPlugin::RetrieveResults called for %lx\n", inData->fInNodeRef );
if ( inData->fInPatternMatch != eDSExact
&& inData->fInPatternMatch != eDSiExact
&& inData->fInPatternMatch != eDSAnyMatch
&& inData->fInPatternMatch != eDSStartsWith
&& inData->fInPatternMatch != eDSEndsWith
&& inData->fInPatternMatch != eDSContains )
{
return eNotYetImplemented;
}
try
{
aRecData = new CDataBuff();
if( !aRecData ) throw( eMemoryError );
aAttrData = new CDataBuff();
if( !aAttrData ) throw( eMemoryError );
aTempData = new CDataBuff();
if( !aTempData ) throw( eMemoryError );
outBuff = new CBuff();
if( !outBuff ) throw( eMemoryError );
siResult = outBuff->Initialize( inData->fInDataBuff, true );
if( siResult ) throw ( siResult );
siResult = outBuff->GetBuffStatus();
if( siResult ) throw ( siResult );
siResult = outBuff->SetBuffType( kClientSideParsingBuff );
if( siResult ) throw ( siResult );
while ( nodeRep->HaveResults() && !siResult )
{
const CNSLResult* newResult = nodeRep->GetNextResult();
if ( !ResultMatchesRequestCriteria( newResult, inData ) )
continue;
aAttrData->Clear();
aRecData->Clear();
if ( newResult )
{
char stackBuf[1024];
char* curURL = NULL;
char* curServiceType = NULL;
CFIndex curServiceTypeLength = 0;
CFStringRef serviceTypeRef = NULL;
char* recordName = NULL;
CFIndex recordNameLength = 0;
CFStringRef recordNameRef = NULL;
serviceTypeRef = newResult->GetServiceTypeRef();
if ( !serviceTypeRef )
continue;
curServiceTypeLength = ::CFStringGetMaximumSizeForEncoding( CFStringGetLength(serviceTypeRef), kCFStringEncodingUTF8) +1;
if ( curServiceTypeLength > (CFIndex)sizeof(stackBuf) )
curServiceType = (char*)malloc( curServiceTypeLength+1 );
else
curServiceType = stackBuf;
if ( !::CFStringGetCString( serviceTypeRef, curServiceType, curServiceTypeLength+1, kCFStringEncodingUTF8 ) )
{
DBGLOG( "CNSLPlugin::RetrieveResults couldn't convert serviceTypeRef CFString to char* in UTF8!\n" );
curServiceType[0] = '\0';
}
else
DBGLOG( "CNSLPlugin::RetrieveResults curServiceType=%s\n", curServiceType );
char* recType = CreateRecTypeFromURL( curServiceType );
if ( curServiceType != stackBuf )
free( curServiceType );
curServiceType = NULL;
if ( recType != nil )
{
DBGLOG( "CNSLPlugin::RetrieveResults recType=%s\n", recType );
aRecData->AppendShort( ::strlen( recType ) );
aRecData->AppendString( recType );
free(recType);
} else
{
aRecData->AppendShort( ::strlen( "Record Type Unknown" ) );
aRecData->AppendString( "Record Type Unknown" );
}
recordNameRef = newResult->GetAttributeRef( kDSNAttrRecordNameSAFE_CFSTR );
if ( !recordNameRef )
{
continue; }
recordNameLength = ::CFStringGetMaximumSizeForEncoding( CFStringGetLength(recordNameRef), kCFStringEncodingUTF8) +1;
if ( recordNameLength > (CFIndex)sizeof(stackBuf) )
recordName = (char*)malloc( recordNameLength );
else
recordName = stackBuf;
if ( !::CFStringGetCString( recordNameRef, recordName, recordNameLength, kCFStringEncodingUTF8 ) )
{
DBGLOG( "CNSLPlugin::RetrieveResults couldn't convert recordNameRef CFString to char* in UTF8!\n" );
recordName[0] = '\0';
}
else
DBGLOG( "CNSLPlugin::RetrieveResults recordName=%s\n", recordName );
if ( recordNameRef != nil && recordName[0] != '\0' )
{
aRecData->AppendShort( ::strlen( recordName ) );
aRecData->AppendString( recordName );
}
else
{
aRecData->AppendShort( ::strlen( "Record Name Unknown" ) );
aRecData->AppendString( "Record Name Unknown" );
}
if ( recordName != stackBuf )
free( recordName );
recordName = NULL;
AttrDataContext context = {0,aAttrData,inData->fInAttribInfoOnly};
if ( newResult->GetAttributeDict() )
{
uInt32 numAttrTypes = 0;
CAttributeList cpAttributeList( inData->fInAttribTypeList );
numAttrTypes = cpAttributeList.GetCount();
if( (numAttrTypes == 0) ) throw( eDSEmptyRecordTypeList );
sInt32 error = eDSNoErr;
char* pAttrType = nil;
char* valueBuf = NULL;
DBGLOG( "CNSLPlugin::RetrieveResults, numAttrTypes:%ld\n", numAttrTypes );
for ( uInt32 i=1; i<=numAttrTypes; i++ )
{
if ( (error = cpAttributeList.GetAttribute( i, &pAttrType )) == eDSNoErr )
{
DBGLOG( "CNSLPlugin::RetrieveResults, GetAttribute returned pAttrType:%s\n", pAttrType );
if ( strcmp( pAttrType, kDSAttributesAll ) == 0 )
{
::CFDictionaryApplyFunction( newResult->GetAttributeDict(), AddToAttrData, &context );
}
else
{
char stackBuf[1024];
CFStringRef keyRef = ::CFStringCreateWithCString( NULL, pAttrType, kCFStringEncodingUTF8 );
CFStringRef valueRef = NULL;
CFTypeRef valueTypeRef = NULL;
CFArrayRef valueArrayRef = NULL;
aTempData->Clear();
if ( ::CFDictionaryContainsKey( newResult->GetAttributeDict(), keyRef ) )
valueTypeRef = (CFTypeRef)::CFDictionaryGetValue( newResult->GetAttributeDict(), keyRef );
CFRelease( keyRef );
if ( valueTypeRef )
{
if ( CFGetTypeID(valueTypeRef) == CFArrayGetTypeID() )
{
valueArrayRef = (CFArrayRef)valueTypeRef;
CFRetain( valueArrayRef ); }
else
if ( CFGetTypeID(valueTypeRef) == CFStringGetTypeID() )
{
valueRef = (CFStringRef)valueTypeRef;
valueArrayRef = CFArrayCreateMutable( NULL, 1, &kCFTypeArrayCallBacks );
if ( CFStringGetLength( valueRef ) > 0 )
CFArrayAppendValue( (CFMutableArrayRef)valueArrayRef, valueRef );
}
else
DBGLOG( "CNSLPlugin::RetrieveResults, got unknown value type (%ld), ignore\n", CFGetTypeID(valueTypeRef) );
if ( valueArrayRef )
{
aTempData->AppendShort( ::strlen( pAttrType ) ); aTempData->AppendString( pAttrType );
DBGLOG( "CNSLPlugin::RetrieveResults, adding pAttrType: %s\n", pAttrType );
aTempData->AppendShort( CFArrayGetCount(valueArrayRef) );
CFIndex valueArrayCount = CFArrayGetCount(valueArrayRef);
for ( CFIndex i=0; i<valueArrayCount ; i++ )
{
valueRef = (CFStringRef)::CFArrayGetValueAtIndex( valueArrayRef, i );
if ( !inData->fInAttribInfoOnly && valueRef && ::CFStringGetLength(valueRef) > 0 )
{
CFIndex maxValueEncodedSize = ::CFStringGetMaximumSizeForEncoding(CFStringGetLength(valueRef),kCFStringEncodingUTF8) + 1;
if ( maxValueEncodedSize > (CFIndex)sizeof(stackBuf) )
valueBuf = (char*)malloc( maxValueEncodedSize );
else
valueBuf = stackBuf;
if ( ::CFStringGetCString( valueRef, valueBuf, maxValueEncodedSize, kCFStringEncodingUTF8 ) )
{
aTempData->AppendShort( ::strlen( valueBuf ) );
aTempData->AppendString( valueBuf );
DBGLOG( "CNSLPlugin::RetrieveResults, adding valueBuf: %s\n", valueBuf );
}
else
DBGLOG( "CNSLPlugin::RetrieveResults, CFStringGetCString couldn't create a string for valueRef!\n" );
if ( valueBuf != stackBuf )
delete( valueBuf );
valueBuf = NULL;
}
}
CFRelease( valueArrayRef ); valueArrayRef = NULL;
}
else if ( valueRef && CFStringGetLength(valueRef) == 0 )
DBGLOG( "CNSLPlugin::RetrieveResults, CFStringGetLength(valueRef) == 0!\n" );
else if ( inData->fInAttribInfoOnly )
DBGLOG( "CNSLPlugin::RetrieveResults, inData->fInAttribInfoOnly\n" );
context.count++;
aAttrData->AppendShort(aTempData->GetLength());
aAttrData->AppendBlock(aTempData->GetData(), aTempData->GetLength() );
}
}
}
else
{
DBGLOG( "CNSLPlugin::RetrieveResults, GetAttribute returned error:%li\n", error );
}
}
}
aRecData->AppendShort( context.count );
aRecData->AppendBlock( aAttrData->GetData(), aAttrData->GetLength() );
DBGLOG( "CNSLPlugin::RetrieveResults calling outBuff->AddData()\n" );
siResult = outBuff->AddData( aRecData->GetData(), aRecData->GetLength() );
if ( curURL )
free( curURL );
curURL = NULL;
if ( siResult == CBuff::kBuffFull )
{
DBGLOG( "CNSLPlugin::RetrieveResults siResult == CBuff::kBuffFull, reset last result for next time\n" );
nodeRep->NeedToRedoLastResult();
UInt32 numDataBlocks = 0;
if ( outBuff->GetDataBlockCount( &numDataBlocks ) != eDSNoErr || numDataBlocks == 0 )
siResult = eDSBufferTooSmall; }
else
inData->fOutRecEntryCount++;
}
}
if ( siResult == CBuff::kBuffFull )
siResult = eDSNoErr;
outBuff->SetLengthToSize();
}
catch ( int err )
{
siResult = err;
}
if (aRecData != nil)
{
delete (aRecData);
aRecData = nil;
}
if (aTempData != nil)
{
delete (aTempData);
aTempData = nil;
}
if (aAttrData != nil)
{
delete (aAttrData);
aAttrData = nil;
}
if ( outBuff != nil )
{
delete( outBuff );
outBuff = nil;
}
return( siResult );
}
char* CNSLPlugin::CreateNSLTypeFromRecType ( char *inRecType )
{
char *outResult = nil;
uInt32 uiStrLen = 0;
uInt32 uiNativeLen = ::strlen( kDSNativeRecordTypePrefix );
uInt32 uiStdLen = ::strlen( kDSStdRecordTypePrefix );
DBGLOG( "CNSLPlugin::CreateNSLTypeFromRecType called on %s\n", inRecType );
if ( ( inRecType != nil ) )
{
uiStrLen = ::strlen( inRecType );
if ( ::strncmp( inRecType, kDSNativeRecordTypePrefix, uiNativeLen ) == 0 )
{
DBGLOG( "CNSLPlugin::CreateNSLTypeFromRecType kDSNativeRecordTypePrefix, uiStrLen:%ld uiNativeLen:%ld\n", uiStrLen, uiNativeLen );
if ( uiStrLen > uiNativeLen )
{
uiStrLen = uiStrLen - uiNativeLen;
outResult = new char[ uiStrLen + 2 ];
::strcpy( outResult, inRecType + uiNativeLen );
}
} else if ( ::strncmp( inRecType, kDSStdRecordTypePrefix, uiStdLen ) == 0 )
{
DBGLOG( "CNSLPlugin::CreateNSLTypeFromRecType kDSStdRecordTypePrefix, uiStrLen:%ld uiStdLen:%ld\n", uiStrLen, uiStdLen );
if ( strcmp( inRecType, kDSStdRecordTypeAFPServer ) == 0 )
{
outResult = new char[1+::strlen(kAFPServiceType)];
::strcpy(outResult, kAFPServiceType);
}
else
if ( strcmp( inRecType, kDSStdRecordTypeSMBServer ) == 0 )
{
outResult = new char[1+::strlen(kSMBServiceType)];
::strcpy(outResult, kSMBServiceType);
}
else
if ( strcmp( inRecType, kDSStdRecordTypeFTPServer ) == 0 )
{
outResult = new char[1+::strlen(kFTPServiceType)];
::strcpy(outResult, kFTPServiceType);
}
else
if ( strcmp( inRecType, kDSStdRecordTypeNFS ) == 0 )
{
outResult = new char[1+::strlen(kNFSServiceType)];
::strcpy(outResult, kNFSServiceType);
}
else
if ( strcmp( inRecType, kDSStdRecordTypeWebServer ) == 0 )
{
outResult = new char[1+::strlen(kHTTPServiceType)];
::strcpy(outResult, kHTTPServiceType);
}
else
if ( strcmp( inRecType, kDSStdRecordTypePrinters ) == 0 )
{
outResult = new char[1+::strlen(kLaserWriterServiceType)];
::strcpy(outResult, kLaserWriterServiceType);
}
else if ( uiStrLen > uiStdLen )
{
}
else
DBGLOG( "CNSLPlugin::CreateNSLTypeFromRecType, uiStrLen:%ld <= uiStdLen:%ld\n", uiStrLen, uiStdLen );
} else
DBGLOG( "CNSLPlugin::CreateNSLTypeFromRecType, inRecType:%s doesn't map to \"dsRecTypeNative:\" OR \"dsRecTypeStandard:\"!\n", inRecType );
}
DBGLOG( "CNSLPlugin::CreateNSLTypeFromRecType mapping %s to %s\n", inRecType, outResult );
return( outResult );
}
char* CNSLPlugin::CreateRecTypeFromURL( char *inNSLType )
{
char *outResult = nil;
uInt32 uiStrLen = 0;
DBGLOG( "CNSLPlugin::CreateRecTypeFromURL called to map %s to a DS type\n", inNSLType );
if ( inNSLType != nil )
{
uiStrLen = ::strlen( inNSLType );
if ( strcmp( inNSLType, kAFPServiceType ) == 0 )
{
outResult = new char[1+::strlen(kDSStdRecordTypeAFPServer)];
::strcpy(outResult,kDSStdRecordTypeAFPServer);
}
else if ( strcmp( inNSLType, kSMBServiceType ) == 0 )
{
outResult = new char[1+::strlen(kDSStdRecordTypeSMBServer)];
::strcpy(outResult,kDSStdRecordTypeSMBServer);
}
else if ( strcmp( inNSLType, kNFSServiceType ) == 0 )
{
outResult = new char[1+::strlen(kDSStdRecordTypeNFS)];
::strcpy(outResult,kDSStdRecordTypeNFS);
}
else if ( strcmp( inNSLType, kFTPServiceType ) == 0 )
{
outResult = new char[1+::strlen(kDSStdRecordTypeFTPServer)];
::strcpy(outResult,kDSStdRecordTypeFTPServer);
}
else if ( strcmp( inNSLType, kHTTPServiceType ) == 0 )
{
outResult = new char[1+::strlen(kDSStdRecordTypeWebServer)];
::strcpy(outResult,kDSStdRecordTypeWebServer);
}
else
{
outResult = new char[1+::strlen(kDSNativeAttrTypePrefix)+strlen(inNSLType)];
::strcpy(outResult,kDSNativeAttrTypePrefix);
::strcat(outResult,inNSLType);
}
}
return( outResult );
}
CFStringRef CNSLPlugin::CreateRecTypeFromNativeType ( char *inNativeType )
{
CFMutableStringRef outResultRef = NULL;
DBGLOG( "CNSLPlugin::CreateRecTypeFromNativeType called on %s\n", inNativeType );
if ( ( inNativeType != nil ) )
{
outResultRef = CFStringCreateMutable( NULL, 0 );
if ( ::strcmp( inNativeType, kAFPServiceType ) == 0 )
{
CFStringAppend( outResultRef, kDSStdRecordTypeAFPServerSAFE_CFSTR );
}
else if ( ::strcmp( inNativeType, kSMBServiceType ) == 0 )
{
CFStringAppend( outResultRef, kDSStdRecordTypeSMBServerSAFE_CFSTR );
}
else if ( ::strcmp( inNativeType, kNFSServiceType ) == 0 )
{
CFStringAppend( outResultRef, kDSStdRecordTypeNFSSAFE_CFSTR );
}
else if ( ::strcmp( inNativeType, kDSStdRecordTypeFTPServer ) == 0 )
{
CFStringAppend( outResultRef, kDSStdRecordTypeFTPServerSAFE_CFSTR );
}
else if ( ::strcmp( inNativeType, kDSStdRecordTypeWebServer ) == 0 )
{
CFStringAppend( outResultRef, kDSStdRecordTypeWebServerSAFE_CFSTR );
}
else if ( outResultRef )
{
CFStringAppend( outResultRef, kDSNativeRecordTypePrefixSAFE_CFSTR );
CFStringRef nativeStringRef = CFStringCreateWithCString( NULL, inNativeType, kCFStringEncodingUTF8 );
if ( nativeStringRef )
{
CFStringAppend( outResultRef, nativeStringRef );
CFRelease( nativeStringRef );
}
}
}
return( outResultRef );
}
CFStringRef CNSLPlugin::CreateRecTypeFromNativeType ( CFStringRef inNativeType )
{
CFStringRef returnTypeRef = NULL;
UInt32 nativeCStrLen = ::CFStringGetMaximumSizeForEncoding( CFStringGetLength(inNativeType), kCFStringEncodingUTF8 ) + 1;
char* nativeCStr = (char*)malloc( nativeCStrLen );
::CFStringGetCString( inNativeType, nativeCStr, nativeCStrLen, kCFStringEncodingUTF8 );
returnTypeRef = CreateRecTypeFromNativeType( nativeCStr );
free( nativeCStr );
return returnTypeRef;
}
#pragma mark -
void CNSLPlugin::StartNodeLookup( void )
{
mLastNodeLookupStartTime = GetCurrentTime(); DBGLOG( "CNSLPlugin::StartNodeLookup (%s), called\n", GetProtocolPrefixString() );
ResetNodeLookupTimer( GetTimeBetweenNodeLookups() );
NewNodeLookup();
}
sInt16 CNSLPlugin::NumOutstandingSearches( void )
{
return gOutstandingSearches;
}
Boolean CNSLPlugin::OKToStartNewSearch( void )
{
pthread_mutex_lock(&gOutstandingSearchesLock);
Boolean okToStartNewSearch = NumOutstandingSearches() < kMaxNumOutstandingSearches;
pthread_mutex_unlock(&gOutstandingSearchesLock);
if ( okToStartNewSearch )
DBGLOG( "CNSLPlugin::OKToStartNewSearch is returning true (%d current searches)\n", gOutstandingSearches );
else
DBGLOG( "CNSLPlugin::OKToStartNewSearch is returning false (%d current searches)\n", gOutstandingSearches );
return okToStartNewSearch;
}
void CNSLPlugin::StartSubNodeLookup( char* parentNodeName )
{
DBGLOG( "CNSLPlugin::StartSubNodeLookup called on %s\n", parentNodeName );
OKToOpenUnPublishedNode( parentNodeName );
}
void CNSLPlugin::ClearOutStaleNodes( void )
{
DBGLOG( "CNSLPlugin::ClearOutStaleNodes\n" );
NSLNodeHandlerContext context = {mPublishedNodes, kClearOutStaleNodes, (void*)GetLastNodeLookupStartTime(), NULL};
CFIndex arrayCount;
CFStringRef skeetString;
LockPublishedNodes();
::CFDictionaryApplyFunction( mPublishedNodes, NSLNodeHandlerFunction, &context );
if ( context.fNodesToRemove )
{
arrayCount = CFArrayGetCount( context.fNodesToRemove );
for ( CFIndex i = 0; i < arrayCount; i++ )
{
skeetString = (CFStringRef)CFArrayGetValueAtIndex( context.fNodesToRemove, i );
if ( skeetString != NULL )
CFDictionaryRemoveValue( mPublishedNodes, skeetString );
}
CFRelease( context.fNodesToRemove );
}
UnlockPublishedNodes();
}
void CNSLPlugin::ClearOutAllNodes( void )
{
DBGLOG( "CNSLPlugin::ClearOutAllNodes\n" );
LockPublishedNodes();
::CFDictionaryRemoveAllValues( mPublishedNodes );
UnlockPublishedNodes();
}
void CNSLPlugin::QueueNewSearch( CNSLServiceLookupThread* newLookup )
{
LockSearchQueue();
if ( mSearchQueue )
{
if ( !mSearchTicklerInstalled )
InstallSearchTickler();
::CFArrayAppendValue( mSearchQueue, newLookup );
DBGLOG( "CNSLPlugin::QueueNewSearch called, %ld searches waiting to start\n", CFArrayGetCount(mSearchQueue) );
}
UnlockSearchQueue();
}
#define DEQUEUE_LIFO 1
void CNSLPlugin::StartNextQueuedSearch( void )
{
if ( mSearchQueue && ::CFArrayGetCount(mSearchQueue) > 0 )
{
#if DEQUEUE_LIFO
CNSLServiceLookupThread* newLookup = (CNSLServiceLookupThread*)::CFArrayGetValueAtIndex( mSearchQueue, CFArrayGetCount(mSearchQueue)-1 );
::CFArrayRemoveValueAtIndex( mSearchQueue, CFArrayGetCount(mSearchQueue)-1 );
#else
CNSLServiceLookupThread* newLookup = (CNSLServiceLookupThread*)::CFArrayGetValueAtIndex( mSearchQueue, 0 );
::CFArrayRemoveValueAtIndex( mSearchQueue, 0 );
#endif
LockOpenRefTable();
Boolean newLookupInRefTable = ::CFDictionaryContainsValue( mOpenRefTable, newLookup->GetNodeToSearch() );
UnlockOpenRefTable();
if ( newLookupInRefTable && !newLookup->AreWeCanceled() )
{
DBGLOG( "CNSLPlugin::StartNextQueuedSearch starting new search, %ld searches waiting to start\n", CFArrayGetCount(mSearchQueue) );
newLookup->Resume();
}
else
{
DBGLOG( "CNSLPlugin::StartNextQueuedSearch deleting already canceled search, %ld searches waiting to start\n", CFArrayGetCount(mSearchQueue) );
delete newLookup;
}
}
}
void CNSLPlugin::StartServicesLookup( char* serviceType, CNSLDirNodeRep* nodeDirRep )
{
if ( serviceType )
NewServiceLookup( serviceType, nodeDirRep );
}
#pragma mark -
void NSLReleaseNodeData( CFAllocatorRef allocator, const void* value )
{
NodeData* nodeData = (NodeData*)value;
if ( nodeData )
{
if ( nodeData->fDSName )
DSUnregisterNode( nodeData->fSignature, nodeData->fDSName );
DeallocateNodeData( nodeData );
}
}
CFStringRef NSLNodeValueCopyDesctriptionCallback ( const void *value )
{
NodeData* nodeData = (NodeData*)value;
return nodeData->fNodeName;
}
Boolean NSLNodeValueEqualCallback ( const void *value1, const void *value2 )
{
NodeData* nodeData1 = (NodeData*)value1;
NodeData* nodeData2 = (NodeData*)value2;
Boolean areEqual = false;
if ( nodeData1 && nodeData2 && nodeData1->fNodeName && nodeData2->fNodeName )
areEqual = ( CFStringCompare( nodeData1->fNodeName, nodeData2->fNodeName, kCFCompareCaseInsensitive ) == kCFCompareEqualTo );
return areEqual;
}
void NSLNodeHandlerFunction(const void *inKey, const void *inValue, void *inContext)
{
NodeData* curNodeData = (NodeData*)inValue;
NSLNodeHandlerContext* context = (NSLNodeHandlerContext*)inContext;
if ( !inKey || !inValue || !inContext )
return;
switch ( context->fMessage )
{
case kClearOutStaleNodes:
{
if ( curNodeData->fTimeStamp < (UInt32)(context->fDataPtr) )
{
DBGLOG( "NSLNodeHandlerFunction, Removing Node from published list\n" );
if ( !context->fNodesToRemove )
context->fNodesToRemove = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
if ( curNodeData->fNodeName != NULL )
CFArrayAppendValue( context->fNodesToRemove, curNodeData->fNodeName ); }
}
break;
default:
break;
};
}
#pragma mark -
UInt32 GetCurrentTime( void ) {
struct timeval curTime;
if ( gettimeofday( &curTime, NULL ) != 0 )
fprintf( stderr, "call to gettimeofday returned error: %s", strerror(errno) );
return curTime.tv_sec;
}
void AddToAttrData(const void *key, const void *value, void *context)
{
CFStringRef keyRef = (CFStringRef)key;
CFTypeRef valueTypeRef = (CFTypeRef)value; CFStringRef valueRef = NULL;
CFArrayRef valueArrayRef = NULL;
char keyBuf[256] = {0};
char stackBuf[1024];
char* valueBuf = NULL;
CDataBuff* aTmpData = nil;
AttrDataContext* dataContext = (AttrDataContext*)context;
dataContext->count++;
aTmpData = new CDataBuff();
if( !aTmpData ) throw( eMemoryError );
aTmpData->Clear();
if ( valueTypeRef )
{
if ( CFGetTypeID(valueTypeRef) == CFArrayGetTypeID() )
{
valueArrayRef = (CFArrayRef)valueTypeRef;
CFRetain( valueArrayRef ); }
else
if ( CFGetTypeID(valueTypeRef) == CFStringGetTypeID() )
{
valueRef = (CFStringRef)valueTypeRef;
valueArrayRef = CFArrayCreateMutable( NULL, 1, &kCFTypeArrayCallBacks );
if ( CFStringGetLength( valueRef ) > 0 )
CFArrayAppendValue( (CFMutableArrayRef)valueArrayRef, valueRef );
}
else
DBGLOG( "AddToAttrData, got unknown value type (%ld), ignore\n", CFGetTypeID(valueTypeRef) );
if ( valueArrayRef && ::CFStringGetCString( keyRef, keyBuf, sizeof(keyBuf), kCFStringEncodingUTF8 ) )
{
aTmpData->AppendShort( ::strlen( keyBuf ) ); aTmpData->AppendString( keyBuf );
DBGLOG( "AddToAttrData, adding keyBuf: %s\n", keyBuf );
aTmpData->AppendShort( CFArrayGetCount(valueArrayRef) );
CFIndex valueArrayCount = CFArrayGetCount(valueArrayRef);
for ( CFIndex i=0; i<valueArrayCount ; i++ )
{
valueRef = (CFStringRef)::CFArrayGetValueAtIndex( valueArrayRef, i );
if ( !dataContext->attrOnly && ::CFStringGetLength(valueRef) > 0 )
{
CFIndex maxValueEncodedSize = ::CFStringGetMaximumSizeForEncoding(CFStringGetLength(valueRef), kCFStringEncodingUTF8) + 1;
if ( maxValueEncodedSize > (CFIndex)sizeof(stackBuf) )
valueBuf = (char*)malloc( maxValueEncodedSize );
else
valueBuf = stackBuf;
if ( ::CFStringGetCString( valueRef, valueBuf, maxValueEncodedSize, kCFStringEncodingUTF8 ) )
{
aTmpData->AppendShort( ::strlen( valueBuf ) ); aTmpData->AppendString( valueBuf );
DBGLOG( "AddToAttrData, adding valueBuf: %s\n", valueBuf );
}
else
{
DBGLOG( "AddToAttrData, CFStringGetCString couldn't create a string for valueRef!\n" );
if ( getenv( "NSLDEBUG" ) )
::CFShow( valueRef );
}
if ( valueBuf != stackBuf )
delete( valueBuf );
valueBuf = NULL;
}
}
dataContext->attrDataBuf->AppendShort( aTmpData->GetLength() );
dataContext->attrDataBuf->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
delete aTmpData;
}
if ( valueArrayRef )
CFRelease( valueArrayRef );
}
}
void AddToAttrData2(CFStringRef keyRef, CFStringRef valueRef, void *context)
{
}
#define kOffset 0
#define kHexData 7
#define kASCIIData (kHexData+50)
#define kEOL (kASCIIData+16)
#define kLineLength (kEOL+1)
#define kLineEnding '\n'
#define kBufferTooBig -1
#define kMaxBufSize 10240
#define kMaxPacketLen (((kMaxBufSize - 2)/kLineLength)*16)-15
int LogHexDump(char *pktPtr, long pktLen)
{
static char hexChars[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
register unsigned char *curPtr=NULL; register char *hexPtr=NULL; register char *charPtr=NULL; char *offsetPtr=NULL; unsigned char *p=NULL; short i,j;
char *buf=NULL;
long bufLen;
short numLines;
short numCharsOnLine;
short remainder;
short offset;
if ( pktLen == 0 )
{
DBGLOG( "LogHexDump was passed in a pktLen of zero!\n" );
return noErr; }
if ( pktLen > kMaxPacketLen )
pktLen = kMaxPacketLen;
numLines = (pktLen + 15)/16; remainder = pktLen - (numLines-1)*16;
bufLen = numLines * kLineLength + 2;
if (bufLen > kMaxBufSize)
{
DBGLOG( "LogHexDump kBufferTooBig (%ld), setting to max log size (%d)\n", bufLen, kMaxBufSize );
bufLen = kMaxBufSize;
}
DBGLOG( "Dumping %ld bytes of hex-format data:\n",pktLen );
buf = (char*)malloc(bufLen);
if (!buf)
{
DBGLOG( "LogHexDump return eMemoryAllocError\n" );
return(eMemoryAllocError);
}
for (i=0; i<bufLen; i++) buf[i] = ' ';
curPtr = (unsigned char *)pktPtr; offsetPtr = buf; for (j=0; j<numLines; j++) {
hexPtr = offsetPtr+kHexData; charPtr = offsetPtr+kASCIIData;
offset = j*16; p = (unsigned char*)&offset; *(offsetPtr++) = hexChars[(*p>>4)];
*(offsetPtr++) = hexChars[(*p++&0x0F)]; *(offsetPtr++) = hexChars[(*p>>4)];
*(offsetPtr++) = hexChars[(*p&0x0F)];
*offsetPtr = ':';
if (j == numLines-1) numCharsOnLine = remainder;
else numCharsOnLine = 16;
for (i=0; i<numCharsOnLine; i++) {
*(hexPtr++) = hexChars[(*curPtr>>4)];
*(hexPtr++) = hexChars[(*curPtr&0x0F)];
hexPtr++;
if (isprint(*curPtr))
*(charPtr++) = *curPtr;
else *(charPtr++) = '.';
curPtr++; }
*(charPtr++) = kLineEnding; offsetPtr = charPtr; }
*(charPtr++) = kLineEnding;
*charPtr = '\0';
DBGLOG( "%s\n",buf);
free(buf);
return noErr;
}
CFStringEncoding gsEncoding = kCFStringEncodingInvalidId;
CFStringEncoding NSLGetSystemEncoding( void )
{
if ( gsEncoding == kCFStringEncodingInvalidId )
{
FILE * fp;
char buf[1024];
CFStringEncoding encoding = 0;
fp = fopen("/var/root/.CFUserTextEncoding","r");
if (fp == NULL) {
DBGLOG( "NSLGetSystemEncoding: Could not open config file, return 0 (MacRoman)" );
return 0;
}
if ( fgets(buf,sizeof(buf),fp) != NULL)
{
int i = 0;
while ( buf[i] != '\0' && buf[i] != ':' )
i++;
buf[i] = '\0';
char* endPtr = NULL;
encoding = strtol(buf,&endPtr,10);
}
fclose(fp);
gsEncoding = encoding;
}
DBGLOG( "NSLGetSystemEncoding: returning encoding (%ld)", gsEncoding );
return gsEncoding;
}