CNBPServiceLookupThread.cpp [plain text]
#include "GenericNBPURL.h"
#include "CNBPPlugin.h"
#include "CNBPServiceLookupThread.h"
#include "CNSLDirNodeRep.h"
#include "CNSLResult.h"
#include "NSLDebugLog.h"
CNBPServiceLookupThread::CNBPServiceLookupThread( CNSLPlugin* parentPlugin, char* serviceType, CNSLDirNodeRep* nodeDirRep )
: CNSLServiceLookupThread( parentPlugin, serviceType, nodeDirRep )
{
DBGLOG( "CNBPServiceLookupThread::CNBPServiceLookupThread\n" );
mServiceListRef = NULL;
mNABuffer = NULL;
mBuffer = NULL;
}
CNBPServiceLookupThread::~CNBPServiceLookupThread()
{
DBGLOG( "CNBPServiceLookupThread::~CNBPServiceLookupThread\n" );
if ( mBuffer != NULL )
{
char *buffer = mBuffer;
mBuffer = NULL;
free( buffer );
}
if ( mNABuffer != NULL )
{
NBPNameAndAddress *buffer = mNABuffer;
mNABuffer = NULL;
free( buffer );
}
if ( mServiceListRef )
::CFRelease( mServiceListRef );
}
void* CNBPServiceLookupThread::Run( void )
{
DBGLOG( "CNBPServiceLookupThread::Run\n" );
char serviceType[256] = {0};
char searchScope[256] = {0};
if ( AreWeCanceled() )
{
DBGLOG( "CNBPServiceLookupThread::Run, we were canceled before we even started\n" );
}
else if ( GetNodeName() && ::CFStringGetCString(GetNodeName(), searchScope, sizeof(searchScope), NSLGetSystemEncoding()) )
{
if ( GetServiceTypeRef() && ::CFStringGetCString(GetServiceTypeRef(), serviceType, sizeof(serviceType), kCFStringEncodingUTF8) )
{
OSStatus status = noErr;
short zoneStatus;
zoneStatus = this->ConvertToLocalZoneIfThereAreNoZones( searchScope );
if ( strcmp( serviceType, kAFPServerURLType ) == 0 )
strcpy( serviceType, kAFPServerNBPType );
status = this->DoLookupOnService( serviceType, searchScope );
if ( status == -1 )
{
if ( zoneStatus == kMustSearchZoneNameAppleTalk )
{
status = 0;
}
else
{
status = 0;
}
}
}
else
DBGLOG( "CNBPServiceLookupThread::Run, CFStringGetCString returned false on the serviceType" );
}
else
DBGLOG( "CNBPServiceLookupThread::Run, CFStringGetCString returned false on the searchScope" );
return NULL;
}
OSStatus
CNBPServiceLookupThread::DoLookupOnService( char* service, char *zone )
{
OSStatus status = noErr;
long actualCount;
if ( service && zone )
{
long bufferSize = sizeof(NBPNameAndAddress) * kMaxServicesOnTryOne;
mNABuffer = (NBPNameAndAddress *)malloc( bufferSize );
actualCount = kMaxServicesOnTryOne;
do
{
if ( mNABuffer && !AreWeCanceled() )
status = NBPGetServerList( service, zone, mNABuffer, &actualCount );
else
status = memFullErr;
if ( status > 0 )
{
bufferSize *= 2;
mNABuffer = (NBPNameAndAddress *)realloc( mNABuffer, bufferSize );
if ( mNABuffer == nil )
status = memFullErr;
actualCount = bufferSize / sizeof(NBPNameAndAddress);
}
}
while ( status > 0 && mNABuffer && !AreWeCanceled() );
}
if ( status == noErr )
{
char urlStr[256]={0};
UInt16 urlLen;
if ( strcmp( service, kAFPServerNBPType ) == 0 )
strcpy( service, kAFPServerURLType );
for ( long index = 0; index < actualCount && !AreWeCanceled(); index++ )
{
if ( mNABuffer[index].name[0] != 0 )
{
urlLen = 256;
MakeGenericNBPURL( service, zone, mNABuffer[index].name, urlStr, &urlLen );
urlStr[urlLen] = '\0';
if ( urlLen && !AreWeCanceled() )
{
CNSLResult* newResult = new CNSLResult();
char serviceType[256] = {0};
char *endPtr;
short servceTypeLen;
endPtr = strstr( urlStr, ":/" );
if ( endPtr )
{
servceTypeLen = endPtr - urlStr;
strncpy( serviceType, urlStr, servceTypeLen );
serviceType[servceTypeLen] = '\0';
}
DBGLOG( "CNBPServiceLookupThread::DoLookupOnService creating new result with type:%s url:%s\n",
serviceType, urlStr );
newResult->SetURL( urlStr );
newResult->SetServiceType( serviceType );
CFStringRef nameKeyRef = ::CFStringCreateWithCString( NULL, kDSNAttrRecordName, kCFStringEncodingUTF8 );
CFStringRef nameValueRef = ::CFStringCreateWithCString( NULL, mNABuffer[index].name, NSLGetSystemEncoding() );
if ( nameKeyRef && nameValueRef )
{
newResult->AddAttribute( nameKeyRef, nameValueRef ); }
else
newResult->AddAttribute( kDSNAttrRecordName, mNABuffer[index].name );
AddResult( newResult );
if ( nameKeyRef )
::CFRelease( nameKeyRef );
if ( nameValueRef )
::CFRelease( nameValueRef );
}
}
}
}
return status;
}
void
CNBPServiceLookupThread::SetDefaultNeighborhoodNamePtr( const char *name )
{
mDefaultNeighborhoodName = name;
}
short
CNBPServiceLookupThread::ConvertToLocalZoneIfThereAreNoZones( char* zoneName )
{
short result = kNotConverted;
OSStatus status;
long actualCount = 0;
long bufferSize = sizeof(Str32) * kMaxZonesOnTryOne;
mBuffer = (char *)malloc( bufferSize );
if ( mBuffer == NULL )
return memFullErr;
if ( !AreWeCanceled() )
{
status = ZIPGetZoneList( LOOKUP_CURRENT, mBuffer, bufferSize, &actualCount );
if ( status == -1 )
{
strcpy( zoneName, kNoZoneLabel );
result = kConvertedToLocal;
}
else
result = kMustSearchZoneNameAppleTalk;
}
return result;
};
#include "serverlist.h"
#include <NSLSemaphore.h>
#define kMaxSemaphoreQueueSize 15
static NSLSemaphore *sNSLSemaphoreB = NULL;
static short sWaitCount = 0;
static Boolean sStartDumpingThreads = false;
int CNBPServiceLookupThread::NBPGetServerList(
char *service,
char *curr_zone,
struct NBPNameAndAddress *buffer,
long *actualCount )
{
at_nbptuple_t *tuple_buffer = NULL;
at_entity_t entity;
at_retry_t retry;
int i;
char len;
long entryCount = 0;
struct NBPNameAndAddress *currEntry = buffer;
long maxCount;
int error = 0;
at_nbptuple_t *tuple;
char *cptr;
if ( sNSLSemaphoreB == NULL ) {
sNSLSemaphoreB = new NSLSemaphore(1);
if ( sNSLSemaphoreB == NULL ) {
DBGLOG("sNSLSemaphoreB is NULL\n");
return -1;
}
}
maxCount = *actualCount;
try
{
tuple_buffer = (at_nbptuple_t *) malloc( sizeof(at_nbptuple_t) * maxCount );
if ( tuple_buffer == NULL ) {
DBGLOG( "NBPGetServerList, out of memory\n" );
throw(-1);
}
*actualCount = 0;
if (error = nbp_make_entity(&entity, "=", service, curr_zone) != 0) {
DBGLOG( "nbp_make_entity returned error %d\n", error);
throw(error);
}
if ( sWaitCount > kMaxSemaphoreQueueSize )
{
sStartDumpingThreads = true;
sNSLSemaphoreB->Wait();
sStartDumpingThreads = false;
sNSLSemaphoreB->Signal();
}
sWaitCount++;
sNSLSemaphoreB->Wait();
if ( !sStartDumpingThreads && !AreWeCanceled() )
{
retry.interval = 1;
retry.retries = 1;
retry.backoff = 0x01;
DBGLOG("NBP begin test run, service=%s\n", service);
entryCount = nbp_lookup (&entity, &tuple_buffer[0], 1, &retry);
DBGLOG("NBP end test run, entryCount=%ld\n", entryCount);
if ( entryCount > 0 && !sStartDumpingThreads && !AreWeCanceled() )
{
retry.interval = 1;
retry.retries = 2;
retry.backoff = 0x00;
DBGLOG("NBP begin real run\n");
entryCount = nbp_lookup (&entity, &tuple_buffer[0], maxCount, &retry);
DBGLOG("NBP end real run\n");
}
}
if (AreWeCanceled())
DBGLOG("NBP canceled\n");
sNSLSemaphoreB->Signal();
sWaitCount--;
if (entryCount < 0)
{
DBGLOG( "nbp_lookup returned error %ld\n", entryCount);
throw (-1);
}
tuple = &tuple_buffer[0];
for (i = 0; i < entryCount; i++, tuple++)
{
len = tuple->enu_entity.object.len;
if ( len > 33 )
{
len = 33;
DBGLOG( "NBPGetServerList: found len > 33\n" );
}
cptr = currEntry->name;
if (strncpy ((char*) cptr, (char*)tuple->enu_entity.object.str, len) <= 0 )
{
throw (-1);
}
*(cptr + len) = 0x00;
currEntry->atalkAddress.net = tuple->enu_addr.net;
currEntry->atalkAddress.node = tuple->enu_addr.node;
currEntry->atalkAddress.socket = tuple->enu_addr.socket;
currEntry++;
}
qsort (buffer, entryCount, sizeof (struct NBPNameAndAddress), my_strcmp2);
*actualCount = entryCount;
}
catch( int inError )
{
error = inError;
}
free ( tuple_buffer );
return(error);
}