// PrintServiceInfo prints the service information to standard out // A real application might want to do something else with the information static void PrintServiceInfo(SearcherServices *services) { OTLink *link = OTReverseList(OTLIFOStealList(&services->serviceinfolist)); while (link) { linkedServiceInfo *s = OTGetLinkObject(link, linkedServiceInfo, link); if (!services->headerPrinted) { printf("%-55s Type Domain Target Host IP Address Port Info\n", "Name"); services->headerPrinted = true; } if (s->dom) { if (s->add) printf("%-55s available for browsing\n", s->domn); else printf("%-55s no longer available for browsing\n", s->domn); } else { char ip[16]; unsigned char *p = (unsigned char *)&s->address; sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); printf("%-55s %-16s %-14s ", s->name, s->type, s->domn); if (s->add) printf("%-15s %-15s %5d %s\n", s->host, ip, mDNSVal16(s->notAnIntPort), s->text); else printf("Removed\n"); } link = link->fNext; OTFreeMem(s); } }
static OSStatus MemTest(void) { OSStatus err; OSStatus junk; EndpointRef ep; void *p1; void *p2; p1 = NULL; p2 = NULL; ep = OTOpenEndpointInContext(OTCreateConfiguration("tcp"), 0, NULL, &err, NULL); if (err == noErr) { p1 = OTAllocInContext(ep, T_BIND, T_ALL, &err, NULL); } if (err == noErr) { p2 = OTAllocMemInContext(100, NULL); } if (p2 != NULL) { OTFreeMem(p2); } if (p1 != NULL) { junk = OTFree(p1, T_BIND); assert(junk == noErr); } if (ep != NULL) { junk = OTCloseProvider(ep); assert(junk == noErr); } return err; }
// 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); } }
static OSStatus RunServersForInterface(InetInterfaceInfo* interfaceInfo, SInt32 interfaceIndex) // Run HTTP servers for all of the IP addresses associated // with the interface denoted by interfaceInfo and interfaceIndex. // This routine first starts a server for the primary address // of the interface, then iterates through the secondary addresses on // the interface, starting a server thread for each one. { OSStatus err; InetHost *secondaryAddressBuffer; UInt32 numberOfSecondaryAddresses; UInt32 addressIndex; secondaryAddressBuffer = NULL; // First run the server for the interfaces primary address. err = RunOneServer(interfaceInfo->fAddress); // Now start a server for each of the interface's secondary // addresses. This stuff can only be done on systems that // support IP single link multihoming. numberOfSecondaryAddresses = interfaceInfo->fIPSecondaryCount; if ( err == noErr && gHaveIPSingleLinkMultihoming && numberOfSecondaryAddresses > 0 ) { // Allocate a buffer for the secondary address info. secondaryAddressBuffer = (InetHost *) OTAllocMemInContext( numberOfSecondaryAddresses * sizeof(InetHost) , NULL); if (secondaryAddressBuffer == NULL) { err = kENOMEMErr; } // Ask OT for the list of secondary addresses on this interface. if (err == noErr) { err = OTInetGetSecondaryAddresses(secondaryAddressBuffer, &numberOfSecondaryAddresses, interfaceIndex); } // Start a server for each secondary address. addressIndex = 0; while (err == noErr && addressIndex < numberOfSecondaryAddresses) { err = RunOneServer(secondaryAddressBuffer[addressIndex]); if (err == noErr) { addressIndex += 1; } } } // Clean up. if (secondaryAddressBuffer != NULL) { OTFreeMem(secondaryAddressBuffer); } return err; }
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); }
static void _interruptSafeDispose(void *data) { #if (OP_PLATFORM_MAC_CFM) OTFreeMem(data); #elif (OP_PLATFORM_WINDOWS) GlobalFree((HGLOBAL)data); #elif (OP_PLATFORM_UNIX) free(data); #endif }
// When the name, address, port, and txtinfo for a service is found, FoundInstanceInfo() // enqueues a record for PrintServiceInfo() to print. // Note, a browsing application would *not* normally need to get all this information -- // all it needs is the name, to display to the user. // Finding out the address, port, and txtinfo should be deferred to the time that the user // actually needs to contact the service to use it. static void FoundInstanceInfo(mDNS *const m, ServiceInfoQuery *query) { SearcherServices *services = (SearcherServices *)query->ServiceInfoQueryContext; linkedServiceInfo *info = (linkedServiceInfo *)(query->info); if (query->info->ip.type == mDNSAddrType_IPv4) { mDNS_StopResolveService(m, query); // For this test code, one answer is sufficient OTLIFOEnqueue(&services->serviceinfolist, &info->link); OTFreeMem(query); } }
void OTMemoryReserveTest(void) // This routine is designed to help test OTMemoryReserve // by allocating all the memory in the reserve and checking // that it roughly matches the expected size of the reserve. { OTLink *thisBlock; OTList blockList; ByteCount bytesAllocated; ByteCount targetBytes = (((gReserveChunksAllocated * gReserveChunkSize) * 9) / 10); op_assert(gReserveChunkSize != 0); // You must init the module before doing the test. #if (OP_PLATFORM_MAC_CARBON_FLAG) return; //cant use OTEnterIntertupt(); #endif // Tell OT that weÕre at interrupt time so that it wonÕt // grow the client pool. #if (!OP_PLATFORM_MAC_CARBON_FLAG) OTEnterInterrupt(); #endif // Allocate all of the memory that OT will give us - or until we get what we need... blockList.fHead = nil; bytesAllocated = 0; do { thisBlock = (OTLink*)OTAllocMemFromReserve(1024); if (thisBlock != nil) { OTAddFirst(&blockList, thisBlock); bytesAllocated += 1024; } } while ((thisBlock != nil) && (bytesAllocated < targetBytes)); // Check that itÕs approproximately what the client asked for. // Note that the * 9 / 10 wonÕt work properly for very large client pools. op_assert( bytesAllocated >= targetBytes ); // Free the memory we allocated. do { thisBlock = OTRemoveFirst(&blockList); if (thisBlock != nil) { OTFreeMem(thisBlock); } } while (thisBlock != nil); #if (!OP_PLATFORM_MAC_CARBON_FLAG) OTLeaveInterrupt(); #endif }
void TermOTMemoryReserve(void) // See comment in interface part. { do { OTLink *thisChunk; thisChunk = OTLIFODequeue(&gMemoryReserve); if (thisChunk != nil) { OTFreeMem(thisChunk); } } while ( gMemoryReserve.fHead != nil ); }
// PrintServiceInfo prints the service information to standard out // A real application might want to do something else with the information static void PrintServiceInfo(SearcherServices *services) { OTLink *link = OTReverseList(OTLIFOStealList(&services->serviceinfolist)); while (link) { linkedServiceInfo *ls = OTGetLinkObject(link, linkedServiceInfo, link); ServiceInfo *s = &ls->i; if (!services->headerPrinted) { printf("%-55s Type Domain IP Address Port Info\n", "Name"); services->headerPrinted = true; } if (ls->dom) { char c_dom[MAX_ESCAPED_DOMAIN_NAME]; ConvertDomainNameToCString(&s->name, c_dom); if (ls->add) printf("%-55s available for browsing\n", c_dom); else printf("%-55s no longer available for browsing\n", c_dom); } else { domainlabel name; domainname type, domain; char c_name[MAX_DOMAIN_LABEL+1], c_type[MAX_ESCAPED_DOMAIN_NAME], c_dom[MAX_ESCAPED_DOMAIN_NAME], c_ip[20]; DeconstructServiceName(&s->name, &name, &type, &domain); ConvertDomainLabelToCString_unescaped(&name, c_name); ConvertDomainNameToCString(&type, c_type); ConvertDomainNameToCString(&domain, c_dom); sprintf(c_ip, "%d.%d.%d.%d", s->ip.ip.v4.b[0], s->ip.ip.v4.b[1], s->ip.ip.v4.b[2], s->ip.ip.v4.b[3]); printf("%-55s %-16s %-14s ", c_name, c_type, c_dom); if (ls->add) printf("%-15s %5d %#s\n", c_ip, mDNSVal16(s->port), s->TXTinfo); else printf("Removed\n"); } link = link->fNext; OTFreeMem(ls); } }
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); }