mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-06-06 16:33:00 +08:00

The sources can be obtained via: http://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-544.tar.gz
241 lines
9.0 KiB
C
241 lines
9.0 KiB
C
/* -*- 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);
|
|
}
|