// When a new named instance of a service is found, FoundInstance() is called. // In this sample code we turn around and immediately issue a query to resolve that service name to // find its address, port, and txtinfo, but a normal browing application would just display the name. static void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) { #pragma unused (question) SearcherServices *services = (SearcherServices *)question->QuestionContext; linkedServiceInfo *info; debugf("FoundInstance %##s PTR %##s", answer->name->c, answer->rdata->u.name.c); if (answer->rrtype != kDNSType_PTR) return; if (!services) { debugf("FoundInstance: services is NULL"); return; } info = (linkedServiceInfo *)OTAllocMem(sizeof(linkedServiceInfo)); if (!info) { services->lostRecords = true; return; } info->i.name = answer->rdata->u.name; info->i.InterfaceID = answer->InterfaceID; info->i.ip.type = mDNSAddrType_IPv4; info->i.ip.ip.v4 = zerov4Addr; info->i.port = zeroIPPort; info->add = AddRecord; info->dom = mDNSfalse; if (!AddRecord) // If TTL == 0 we're deleting a service, OTLIFOEnqueue(&services->serviceinfolist, &info->link); else // else we're adding a new service { ServiceInfoQuery *q = (ServiceInfoQuery *)OTAllocMem(sizeof(ServiceInfoQuery)); if (!q) { OTFreeMem(info); services->lostRecords = true; return; } mDNS_StartResolveService(m, q, &info->i, FoundInstanceInfo, services); } }
// When a new named instance of a service is found, FoundInstance() is called. // In this sample code we turn around and immediately to a DNSServiceResolve() to resolve that service name // to find its target host, port, and txtinfo, but a normal browing application would just display the name. // Resolving every single thing you find can be quite hard on the network, so you shouldn't do this // in a real application. Defer resolving until the client has picked which instance from the // long list of services is the one they want to use, and then resolve only that one. static void FoundInstance(DNSServiceRef client, DNSServiceFlags flags, uint32_t interface, DNSServiceErrorType errorCode, const char *replyName, const char *replyType, const char *replyDomain, void *context) { #pragma unused(client, interface, errorCode) SearcherServices *services = (SearcherServices *)context; linkedServiceInfo *info; if (!services) { DebugStr("\pFoundInstance: services is NULL"); return; } info = (linkedServiceInfo *)OTAllocMem(sizeof(linkedServiceInfo)); if (!info) { services->lostRecords = true; return; } info->services = services; strcpy(info->name, replyName); strcpy(info->type, replyType); strcpy(info->domn, replyDomain); info->text[0] = 0; info->add = (flags & kDNSServiceFlagsAdd) ? true : false; info->dom = false; if (!info->add) // If TTL == 0 we're deleting a service, OTLIFOEnqueue(&services->serviceinfolist, &info->link); else // else we're adding a new service DNSServiceResolve(&info->sdRef, 0, 0, info->name, info->type, info->domn, FoundInstanceInfo, info); }
static void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) { #pragma unused (m) #pragma unused (question) SearcherServices *services = (SearcherServices *)question->QuestionContext; linkedServiceInfo *info; debugf("FoundDomain %##s PTR %##s", answer->name->c, answer->rdata->u.name.c); if (answer->rrtype != kDNSType_PTR) return; if (!services) { debugf("FoundDomain: services is NULL"); return; } info = (linkedServiceInfo *)OTAllocMem(sizeof(linkedServiceInfo)); if (!info) { services->lostRecords = true; return; } info->i.name = answer->rdata->u.name; info->i.InterfaceID = answer->InterfaceID; info->i.ip.type = mDNSAddrType_IPv4; info->i.ip.ip.v4 = zerov4Addr; info->i.port = zeroIPPort; info->add = AddRecord; info->dom = mDNStrue; OTLIFOEnqueue(&services->serviceinfolist, &info->link); }
mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result) { if (result == mStatus_GrowCache) { // Allocate another chunk of cache storage CacheEntity *storage = OTAllocMem(sizeof(CacheEntity) * RR_CACHE_SIZE); if (storage) mDNS_GrowCache(m, storage, RR_CACHE_SIZE); } }
int main() { OSStatus err; void *tempmem; DNSServiceRef sdRef; DNSServiceErrorType dse; SIOUXSettings.asktosaveonclose = false; SIOUXSettings.userwindowtitle = "\pMulticast DNS Searcher"; SIOUXSettings.rows = 40; SIOUXSettings.columns = 160; printf("DNS-SD Search Client\n\n"); printf("This software reports errors using MacsBug breaks,\n"); printf("so if you don't have MacsBug installed your Mac may crash.\n\n"); printf("******************************************************************************\n\n"); if (DNSServiceBrowse == (void*)kUnresolvedCFragSymbolAddress) { printf("Before you can use mDNS/DNS-SD clients, you need to place the \n"); printf("\"Multicast DNS & DNS-SD\" Extension in the Extensions Folder and restart\n"); return(-1); } err = InitOpenTransport(); if (err) { printf("InitOpenTransport failed %d", err); return(err); } // Make sure OT has a large enough memory pool for us to draw from at OTNotifier (interrupt) time tempmem = OTAllocMem(0x10000); if (tempmem) OTFreeMem(tempmem); else printf("**** Warning: OTAllocMem couldn't pre-allocate 64K for us.\n"); services.serviceinfolist.fHead = NULL; services.headerPrinted = false; services.lostRecords = false; printf("Sending mDNS service lookup queries and waiting for responses...\n\n"); dse = DNSServiceBrowse(&sdRef, 0, 0, "_http._tcp", "", FoundInstance, &services); if (dse == kDNSServiceErr_NoError) { while (!YieldSomeTime(35)) { if (services.serviceinfolist.fHead) PrintServiceInfo(&services); if (services.lostRecords) { services.lostRecords = false; printf("**** Warning: Out of memory: Records have been missed.\n"); } } } DNSServiceRefDeallocate(sdRef); CloseOpenTransport(); return(0); }
//ECF - added this to be able to keep a nice, full reserve as time goes on. - just call periodically at system-time NMErr UpkeepOTMemoryReserve(void) { NMErr err = noErr; Boolean done = false; OTLink * thisChunk; if (gReserveInited == false) return paramErr; //if its full, return happy if (gReserveChunksAllocated >= gMaxReserveChunks) return 0; do { // Only try allocating this chunk if doing so will not // break the minimum free space requirement. thisChunk = nil; if ( FreeMem() >= (gFreeHeapSpaceRequired + gReserveChunkSize) ) { //thisChunk = OTAllocMemInContext(chunkSize, clientContext); #if (OP_PLATFORM_MAC_CARBON_FLAG) thisChunk = (OTLink*)OTAllocMemInContext(gReserveChunkSize,gOTClientContext); #else thisChunk = (OTLink*)OTAllocMem(gReserveChunkSize); #endif } if (thisChunk == nil) { // Either the next block is going to push us below the free // space requirement, or we tried to get the block and failed. if (gReserveChunksAllocated < gMinReserveChunks) { // Because weÕre still trying to get our minimum chunks, // this is a fatal error. err = memFullErr; } else { // The block was optional so we donÕt need to error. // We set done and leave the loop. done = true; } } else { // We got the block. Put it into the reserve. If we have // all of our chunks, set done so that we leave the loop. OTLIFOEnqueue(&gMemoryReserve, (OTLink *) thisChunk); gReserveChunksAllocated += 1; if (gReserveChunksAllocated == gMaxReserveChunks) { done = true; } } } while (err == noErr && !done); return err; }
static void * _interruptSafeAllocate(long size) { #if (OP_PLATFORM_MAC_CFM) #if (TARGET_API_MAC_CARBON) return OTAllocMemInContext(size,theOTContext); #else return OTAllocMem(size); #endif #elif (OP_PLATFORM_WINDOWS) return GlobalAlloc(GPTR,size); #elif (OP_PLATFORM_UNIX) return malloc(size); #endif }
void *OTAllocMemFromReserve(OTByteCount size) // See comment in interface part. { void *result; // First try to allocate the memory from the OT client pool. // If this succeeds, weÕre done. If it fails, the failure // will trigger OT to try and grow the client pool the next // time SystemTask is called. However, if the memory reserve // still has memory we free a block of the reserve and retry // the allocation. Hopefully that will allow the allocation to // succeed. // // Note that I originally wrapped this in a do {} while loop, // however I deleted that because I figured that all of the // blocks are the same size, so if freeing one block didnÕt // help then freeing another wonÕt help either. Except // OT might try to coallesce the memory blocks if they live // in the same Mac OS Memory Manager memory block. However, // they probably wonÕt live in the same Memory Manager block // because the blocks are large. Regardless, freeing all of // our reserve blocks at once will cause the entire reserve // to go the first time if the client tries to allocate a // block large than our block size, which is not good. //ECF: we're doing the while() thing again - since we refill the cache // its not terribly catastrophic, and there is a chance it will work... //if the memory-reserve hasnt been inited yet, just return a normal call if (gReserveInited == false) #ifdef OP_PLATFORM_MAC_CARBON_FLAG return OTAllocMemInContext(size,gOTClientContext); #else return OTAllocMem(size); #endif //when running OSX we just return what we get the first time #if OP_PLATFORM_MAC_CARBON_FLAG if (gRunningOSX) return OTAllocMemInContext(size,gOTClientContext); result = OTAllocMemInContext(size,gOTClientContext); #else result = OTAllocMem(size); #endif while (result == nil) { OTLink *thisChunk; //if theres nothing left to release, give up if (gReserveChunksAllocated == 0) break; thisChunk = OTLIFODequeue(&gMemoryReserve); if (thisChunk != nil) { OTFreeMem(thisChunk); gReserveChunksAllocated--; #if (OP_PLATFORM_MAC_CARBON_FLAG) result = OTAllocMemInContext(size,gOTClientContext); #else result = OTAllocMem(size); #endif } } return result; }
int main() { mStatus err; Boolean DoneSetup = false; void *tempmem; SIOUXSettings.asktosaveonclose = false; SIOUXSettings.userwindowtitle = "\pMulticast DNS Searcher"; SIOUXSettings.rows = 40; SIOUXSettings.columns = 132; printf("Multicast DNS Searcher\n\n"); printf("This software reports errors using MacsBug breaks,\n"); printf("so if you don't have MacsBug installed your Mac may crash.\n\n"); printf("******************************************************************************\n"); err = InitOpenTransport(); if (err) { debugf("InitOpenTransport failed %d", err); return(err); } err = mDNS_Init(&mDNSStorage, &PlatformSupportStorage, rrcachestorage, RR_CACHE_SIZE, mDNS_Init_DontAdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); if (err) return(err); // Make sure OT has a large enough memory pool for us to draw from at OTNotifier (interrupt) time tempmem = OTAllocMem(0x10000); if (tempmem) OTFreeMem(tempmem); else printf("**** Warning: OTAllocMem couldn't pre-allocate 64K for us.\n"); services.serviceinfolist.fHead = NULL; services.headerPrinted = false; services.lostRecords = false; while (!YieldSomeTime(35)) { #if MDNS_ONLYSYSTEMTASK // For debugging, use "#define MDNS_ONLYSYSTEMTASK 1" and call mDNSPlatformIdle() periodically. // For shipping code, don't define MDNS_ONLYSYSTEMTASK, and you don't need to call mDNSPlatformIdle() extern void mDNSPlatformIdle(mDNS *const m); mDNSPlatformIdle(&mDNSStorage); // Only needed for debugging version #endif if (mDNSStorage.mDNSPlatformStatus == mStatus_NoError && !DoneSetup) { domainname srvtype, srvdom; DoneSetup = true; printf("\nSending mDNS service lookup queries and waiting for responses...\n\n"); MakeDomainNameFromDNSNameString(&srvtype, "_http._tcp."); MakeDomainNameFromDNSNameString(&srvdom, "local."); err = mDNS_StartBrowse(&mDNSStorage, &browsequestion, &srvtype, &srvdom, mDNSInterface_Any, mDNSfalse, FoundInstance, &services); if (err) break; err = mDNS_GetDomains(&mDNSStorage, &domainquestion, mDNS_DomainTypeBrowse, NULL, mDNSInterface_Any, FoundDomain, &services); if (err) break; } if (services.serviceinfolist.fHead) PrintServiceInfo(&services); if (services.lostRecords) { services.lostRecords = false; printf("**** Warning: Out of memory: Records have been missed.\n"); } } mDNS_StopBrowse(&mDNSStorage, &browsequestion); mDNS_Close(&mDNSStorage); return(0); }