summaryrefslogtreecommitdiffstats
path: root/mDNSResponder/mDNSMacOS9/Searcher.c
diff options
context:
space:
mode:
Diffstat (limited to 'mDNSResponder/mDNSMacOS9/Searcher.c')
-rw-r--r--mDNSResponder/mDNSMacOS9/Searcher.c240
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);
+}