diff options
Diffstat (limited to 'mDNSResponder/mDNSMacOS9/Searcher.c')
-rw-r--r-- | mDNSResponder/mDNSMacOS9/Searcher.c | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/mDNSResponder/mDNSMacOS9/Searcher.c b/mDNSResponder/mDNSMacOS9/Searcher.c new file mode 100644 index 00000000..a1096839 --- /dev/null +++ b/mDNSResponder/mDNSMacOS9/Searcher.c @@ -0,0 +1,240 @@ +/* -*- 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 <string.h> // For strcpy() + +#include <Events.h> // For WaitNextEvent() +#include <CodeFragments.h> // For SIOkUnresolvedCFragSymbolAddress + +#include <SIOUX.h> // For SIOUXHandleOneEvent() + +#include <OpenTransport.h> +#include <OpenTptInternet.h> + +#include "dns_sd.h" + +#define ns_c_in 1 +#define ns_t_a 1 + +typedef union { UInt8 b[2]; UInt16 NotAnInteger; } mDNSOpaque16; +static UInt16 mDNSVal16(mDNSOpaque16 x) { return((UInt16)(x.b[0]<<8 | x.b[1])); } +static mDNSOpaque16 mDNSOpaque16fromIntVal(UInt16 v) +{ mDNSOpaque16 x; x.b[0] = (UInt8)(v >> 8); x.b[1] = (UInt8)(v & 0xFF); return(x); } + +typedef struct +{ + OTLIFO serviceinfolist; + Boolean headerPrinted; + Boolean lostRecords; +} SearcherServices; + +typedef struct +{ + SearcherServices *services; + char name[kDNSServiceMaxDomainName]; + char type[kDNSServiceMaxDomainName]; + char domn[kDNSServiceMaxDomainName]; + char host[kDNSServiceMaxDomainName]; + char text[kDNSServiceMaxDomainName]; + InetHost address; + mDNSOpaque16 notAnIntPort; + DNSServiceRef sdRef; + Boolean add; + Boolean dom; + OTLink link; +} linkedServiceInfo; + +static SearcherServices services; + +// 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 void FoundInstanceAddress(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, + const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context) +{ + linkedServiceInfo *info = (linkedServiceInfo *)context; + SearcherServices *services = info->services; + (void)sdRef; // Unused + (void)interfaceIndex; // Unused + (void)fullname; // Unused + (void)ttl; // Unused + if (errorCode == kDNSServiceErr_NoError) + if (flags & kDNSServiceFlagsAdd) + if (rrclass == ns_c_in && rrtype == ns_t_a && rdlen == sizeof(info->address)) + { + memcpy(&info->address, rdata, sizeof(info->address)); + DNSServiceRefDeallocate(info->sdRef); + OTLIFOEnqueue(&services->serviceinfolist, &info->link); + } +} + +static void FoundInstanceInfo(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t notAnIntPort, + uint16_t txtLen, const unsigned char *txtRecord, void *context) +{ + linkedServiceInfo *info = (linkedServiceInfo *)context; + SearcherServices *services = info->services; + (void)sdRef; // Unused + (void)flags; // Unused + (void)interfaceIndex; // Unused + (void)errorCode; // Unused + (void)fullname; // Unused + strcpy(info->host, hosttarget); + if (txtLen == 0) info->text[0] = 0; + else + { + strncpy(info->text, (char *)txtRecord+1, txtRecord[0]); + info->text[txtRecord[0]] = 0; + } + info->notAnIntPort.NotAnInteger = notAnIntPort; + DNSServiceRefDeallocate(info->sdRef); + DNSServiceQueryRecord(&info->sdRef, 0, 0, info->host, ns_t_a, ns_c_in, FoundInstanceAddress, info); +} + +// 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); +} + +// 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() +{ + 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); +} |