]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOS9/Searcher.c
mDNSResponder-379.27.tar.gz
[apple/mdnsresponder.git] / mDNSMacOS9 / Searcher.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <stdio.h> // For printf()
19 #include <string.h> // For strcpy()
20
21 #include <Events.h> // For WaitNextEvent()
22 #include <CodeFragments.h> // For SIOkUnresolvedCFragSymbolAddress
23
24 #include <SIOUX.h> // For SIOUXHandleOneEvent()
25
26 #include <OpenTransport.h>
27 #include <OpenTptInternet.h>
28
29 #include "dns_sd.h"
30
31 #define ns_c_in 1
32 #define ns_t_a 1
33
34 typedef union { UInt8 b[2]; UInt16 NotAnInteger; } mDNSOpaque16;
35 static UInt16 mDNSVal16(mDNSOpaque16 x) { return((UInt16)(x.b[0]<<8 | x.b[1])); }
36 static mDNSOpaque16 mDNSOpaque16fromIntVal(UInt16 v)
37 { mDNSOpaque16 x; x.b[0] = (UInt8)(v >> 8); x.b[1] = (UInt8)(v & 0xFF); return(x); }
38
39 typedef struct
40 {
41 OTLIFO serviceinfolist;
42 Boolean headerPrinted;
43 Boolean lostRecords;
44 } SearcherServices;
45
46 typedef struct
47 {
48 SearcherServices *services;
49 char name[kDNSServiceMaxDomainName];
50 char type[kDNSServiceMaxDomainName];
51 char domn[kDNSServiceMaxDomainName];
52 char host[kDNSServiceMaxDomainName];
53 char text[kDNSServiceMaxDomainName];
54 InetHost address;
55 mDNSOpaque16 notAnIntPort;
56 DNSServiceRef sdRef;
57 Boolean add;
58 Boolean dom;
59 OTLink link;
60 } linkedServiceInfo;
61
62 static SearcherServices services;
63
64 // PrintServiceInfo prints the service information to standard out
65 // A real application might want to do something else with the information
66 static void PrintServiceInfo(SearcherServices *services)
67 {
68 OTLink *link = OTReverseList(OTLIFOStealList(&services->serviceinfolist));
69
70 while (link)
71 {
72 linkedServiceInfo *s = OTGetLinkObject(link, linkedServiceInfo, link);
73
74 if (!services->headerPrinted)
75 {
76 printf("%-55s Type Domain Target Host IP Address Port Info\n", "Name");
77 services->headerPrinted = true;
78 }
79
80 if (s->dom)
81 {
82 if (s->add) printf("%-55s available for browsing\n", s->domn);
83 else printf("%-55s no longer available for browsing\n", s->domn);
84 }
85 else
86 {
87 char ip[16];
88 unsigned char *p = (unsigned char *)&s->address;
89 sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
90 printf("%-55s %-16s %-14s ", s->name, s->type, s->domn);
91 if (s->add) printf("%-15s %-15s %5d %s\n", s->host, ip, mDNSVal16(s->notAnIntPort), s->text);
92 else printf("Removed\n");
93 }
94
95 link = link->fNext;
96 OTFreeMem(s);
97 }
98 }
99
100 static void FoundInstanceAddress(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode,
101 const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context)
102 {
103 linkedServiceInfo *info = (linkedServiceInfo *)context;
104 SearcherServices *services = info->services;
105 (void)sdRef; // Unused
106 (void)interfaceIndex; // Unused
107 (void)fullname; // Unused
108 (void)ttl; // Unused
109 if (errorCode == kDNSServiceErr_NoError)
110 if (flags & kDNSServiceFlagsAdd)
111 if (rrclass == ns_c_in && rrtype == ns_t_a && rdlen == sizeof(info->address))
112 {
113 memcpy(&info->address, rdata, sizeof(info->address));
114 DNSServiceRefDeallocate(info->sdRef);
115 OTLIFOEnqueue(&services->serviceinfolist, &info->link);
116 }
117 }
118
119 static void FoundInstanceInfo(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
120 DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t notAnIntPort,
121 uint16_t txtLen, const unsigned char *txtRecord, void *context)
122 {
123 linkedServiceInfo *info = (linkedServiceInfo *)context;
124 SearcherServices *services = info->services;
125 (void)sdRef; // Unused
126 (void)flags; // Unused
127 (void)interfaceIndex; // Unused
128 (void)errorCode; // Unused
129 (void)fullname; // Unused
130 strcpy(info->host, hosttarget);
131 if (txtLen == 0) info->text[0] = 0;
132 else
133 {
134 strncpy(info->text, (char *)txtRecord+1, txtRecord[0]);
135 info->text[txtRecord[0]] = 0;
136 }
137 info->notAnIntPort.NotAnInteger = notAnIntPort;
138 DNSServiceRefDeallocate(info->sdRef);
139 DNSServiceQueryRecord(&info->sdRef, 0, 0, info->host, ns_t_a, ns_c_in, FoundInstanceAddress, info);
140 }
141
142 // When a new named instance of a service is found, FoundInstance() is called.
143 // In this sample code we turn around and immediately to a DNSServiceResolve() to resolve that service name
144 // to find its target host, port, and txtinfo, but a normal browing application would just display the name.
145 // Resolving every single thing you find can be quite hard on the network, so you shouldn't do this
146 // in a real application. Defer resolving until the client has picked which instance from the
147 // long list of services is the one they want to use, and then resolve only that one.
148 static void FoundInstance(DNSServiceRef client, DNSServiceFlags flags, uint32_t interface, DNSServiceErrorType errorCode,
149 const char *replyName, const char *replyType, const char *replyDomain, void *context)
150 {
151 #pragma unused(client, interface, errorCode)
152 SearcherServices *services = (SearcherServices *)context;
153 linkedServiceInfo *info;
154
155 if (!services) { DebugStr("\pFoundInstance: services is NULL"); return; }
156
157 info = (linkedServiceInfo *)OTAllocMem(sizeof(linkedServiceInfo));
158 if (!info) { services->lostRecords = true; return; }
159
160 info->services = services;
161 strcpy(info->name, replyName);
162 strcpy(info->type, replyType);
163 strcpy(info->domn, replyDomain);
164 info->text[0] = 0;
165 info->add = (flags & kDNSServiceFlagsAdd) ? true : false;
166 info->dom = false;
167
168 if (!info->add) // If TTL == 0 we're deleting a service,
169 OTLIFOEnqueue(&services->serviceinfolist, &info->link);
170 else // else we're adding a new service
171 DNSServiceResolve(&info->sdRef, 0, 0, info->name, info->type, info->domn, FoundInstanceInfo, info);
172 }
173
174 // YieldSomeTime() just cooperatively yields some time to other processes running on classic Mac OS
175 static Boolean YieldSomeTime(UInt32 milliseconds)
176 {
177 extern Boolean SIOUXQuitting;
178 EventRecord e;
179 WaitNextEvent(everyEvent, &e, milliseconds / 17, NULL);
180 SIOUXHandleOneEvent(&e);
181 return(SIOUXQuitting);
182 }
183
184 int main()
185 {
186 OSStatus err;
187 void *tempmem;
188 DNSServiceRef sdRef;
189 DNSServiceErrorType dse;
190
191 SIOUXSettings.asktosaveonclose = false;
192 SIOUXSettings.userwindowtitle = "\pMulticast DNS Searcher";
193 SIOUXSettings.rows = 40;
194 SIOUXSettings.columns = 160;
195
196 printf("DNS-SD Search Client\n\n");
197 printf("This software reports errors using MacsBug breaks,\n");
198 printf("so if you don't have MacsBug installed your Mac may crash.\n\n");
199 printf("******************************************************************************\n\n");
200
201 if (DNSServiceBrowse == (void*)kUnresolvedCFragSymbolAddress)
202 {
203 printf("Before you can use mDNS/DNS-SD clients, you need to place the \n");
204 printf("\"Multicast DNS & DNS-SD\" Extension in the Extensions Folder and restart\n");
205 return(-1);
206 }
207
208 err = InitOpenTransport();
209 if (err) { printf("InitOpenTransport failed %d", err); return(err); }
210
211 // Make sure OT has a large enough memory pool for us to draw from at OTNotifier (interrupt) time
212 tempmem = OTAllocMem(0x10000);
213 if (tempmem) OTFreeMem(tempmem);
214 else printf("**** Warning: OTAllocMem couldn't pre-allocate 64K for us.\n");
215
216 services.serviceinfolist.fHead = NULL;
217 services.headerPrinted = false;
218 services.lostRecords = false;
219
220 printf("Sending mDNS service lookup queries and waiting for responses...\n\n");
221 dse = DNSServiceBrowse(&sdRef, 0, 0, "_http._tcp", "", FoundInstance, &services);
222 if (dse == kDNSServiceErr_NoError)
223 {
224 while (!YieldSomeTime(35))
225 {
226 if (services.serviceinfolist.fHead)
227 PrintServiceInfo(&services);
228
229 if (services.lostRecords)
230 {
231 services.lostRecords = false;
232 printf("**** Warning: Out of memory: Records have been missed.\n");
233 }
234 }
235 }
236
237 DNSServiceRefDeallocate(sdRef);
238 CloseOpenTransport();
239 return(0);
240 }