diff options
Diffstat (limited to 'mDNSResponder/mDNSMacOS9/Mac OS Test Searcher.c')
-rw-r--r-- | mDNSResponder/mDNSMacOS9/Mac OS Test Searcher.c | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/mDNSResponder/mDNSMacOS9/Mac OS Test Searcher.c b/mDNSResponder/mDNSMacOS9/Mac OS Test Searcher.c new file mode 100644 index 00000000..1de64631 --- /dev/null +++ b/mDNSResponder/mDNSMacOS9/Mac OS Test Searcher.c @@ -0,0 +1,243 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> // For printf() +#include <Events.h> // For WaitNextEvent() +#include <SIOUX.h> // For SIOUXHandleOneEvent() + +#include "mDNSEmbeddedAPI.h" // Defines the interface to the client layer above +#include "mDNSMacOS9.h" // Defines the specific types needed to run mDNS on this platform + +typedef struct + { + OTLIFO serviceinfolist; + Boolean headerPrinted; + Boolean lostRecords; + } SearcherServices; + +typedef struct { ServiceInfo i; mDNSBool add; mDNSBool dom; OTLink link; } linkedServiceInfo; + +// These don't have to be globals, but their memory does need to remain valid for as +// long as the search is going on. They are declared as globals here for simplicity. +#define RR_CACHE_SIZE 1000 +static CacheEntity rrcachestorage[RR_CACHE_SIZE]; +static mDNS mDNSStorage; +static mDNS_PlatformSupport PlatformSupportStorage; +static SearcherServices services; +static DNSQuestion browsequestion, domainquestion; + +// 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); + } + } + +// 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); + } + } + +// 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 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); + } + +// YieldSomeTime() just cooperatively yields some time to other processes running on classic Mac OS +static Boolean YieldSomeTime(UInt32 milliseconds) + { + extern Boolean SIOUXQuitting; + EventRecord e; + WaitNextEvent(everyEvent, &e, milliseconds / 17, NULL); + SIOUXHandleOneEvent(&e); + return(SIOUXQuitting); + } + +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); + } |