-/*
+/* -*- Mode: C; tab-width: 4 -*-
+ *
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
+ * 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
*
- * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
+ * 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.
- *
- * @APPLE_LICENSE_HEADER_END@
* This file defines a simple shim layer between a client calling the "/usr/include/dns_sd.h" APIs
- * and an implementation of mDNSCore ("mDNSClientAPI.h" APIs) in the same address space.
- * When the client calls a dns_sd.h function, the shim calls the corresponding mDNSClientAPI.h
+ * and an implementation of mDNSCore ("mDNSEmbeddedAPI.h" APIs) in the same address space.
+ * When the client calls a dns_sd.h function, the shim calls the corresponding mDNSEmbeddedAPI.h
* function, and when mDNSCore calls the shim's callback, we call through to the client's callback.
* The shim is responsible for two main things:
* - converting string parameters between C string format and native DNS format,
* - and for allocating and freeing memory.
-
- Change History (most recent first):
-
-$Log: dnssd_clientshim.c,v $
-Revision 1.3 2004/05/27 06:26:31 cheshire
-Add shim for DNSServiceQueryRecord()
-
-Revision 1.2 2004/05/20 18:41:24 cheshire
-Fix build broken by removal of 'kDNSServiceFlagsRemove' from dns_sd.h
-
-Revision 1.1 2004/03/12 21:30:29 cheshire
-Build a System-Context Shared Library from mDNSCore, for the benefit of developers
-like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
-
*/
#include "dns_sd.h" // Defines the interface to the client layer above
-#include "mDNSClientAPI.h" // The interface we're building on top of
+#include "mDNSEmbeddedAPI.h" // The interface we're building on top of
extern mDNS mDNSStorage; // We need to pass the address of this storage to the lower-layer functions
#if MDNS_BUILDINGSHAREDLIBRARY || MDNS_BUILDINGSTUBLIBRARY
mDNS_DirectOP_Dispose *disposefn;
DNSServiceRegisterReply callback;
void *context;
- mDNSBool autoname;
- mDNSBool autorename;
+ mDNSBool autoname; // Set if this name is tied to the Computer Name
+ mDNSBool autorename; // Set if we just got a name conflict and now need to automatically pick a new name
domainlabel name;
+ domainname host;
ServiceRecordSet s;
} mDNS_DirectOP_Register;
char namestr[MAX_DOMAIN_LABEL+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL.
char typestr[MAX_ESCAPED_DOMAIN_NAME];
char domstr [MAX_ESCAPED_DOMAIN_NAME];
- if (!DeconstructServiceName(&sr->RR_SRV.resrec.name, &name, &type, &dom)) return;
+ if (!DeconstructServiceName(sr->RR_SRV.resrec.name, &name, &type, &dom)) return;
if (!ConvertDomainLabelToCString_unescaped(&name, namestr)) return;
if (!ConvertDomainNameToCString(&type, typestr)) return;
if (!ConvertDomainNameToCString(&dom, domstr)) return;
(void)interfaceIndex; // Unused
// Check parameters
+ if (!name) name = "";
if (!name[0]) n = mDNSStorage.nicelabel;
else if (!MakeDomainLabelFromLiteralString(&n, name)) { errormsg = "Bad Instance Name"; goto badparam; }
if (!regtype || !*regtype || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Bad Service Type"; goto badparam; }
x->autoname = (!name[0]);
x->autorename = mDNSfalse;
x->name = n;
+ x->host = h;
// Do the operation
err = mDNS_RegisterService(&mDNSStorage, &x->s,
&x->name, &t, &d, // Name, type, domain
- &h, port, // Host and port
+ &x->host, port, // Host and port
txtRecord, txtLen, // TXT data, length
SubTypes, NumSubTypes, // Subtypes
mDNSInterface_Any, // Interface ID
mDNSPlatformMemFree(x);
}
-mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
+mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
{
DNSServiceFlags flags = AddRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0;
domainlabel name;
if (!DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain))
{
LogMsg("FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
- answer->name.c, answer->rdata->u.name.c);
+ answer->name->c, answer->rdata->u.name.c);
return;
}
x->q.QuestionContext = x;
// Do the operation
- err = mDNS_StartBrowse(&mDNSStorage, &x->q, &t, &d, mDNSInterface_Any, FoundInstance, x);
+ err = mDNS_StartBrowse(&mDNSStorage, &x->q, &t, &d, mDNSInterface_Any, (flags & kDNSServiceFlagsForceMulticast) != 0, FoundInstance, x);
if (err) { mDNSPlatformMemFree(x); errormsg = "mDNS_StartBrowse"; goto fail; }
// Succeeded: Wrap up and return
mDNSPlatformMemFree(x);
}
-mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
+mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
{
mDNS_DirectOP_Resolve *x = (mDNS_DirectOP_Resolve*)question->QuestionContext;
(void)m; // Unused
if (x->SRV && x->TXT && x->callback)
{
char fullname[MAX_ESCAPED_DOMAIN_NAME], targethost[MAX_ESCAPED_DOMAIN_NAME];
- ConvertDomainNameToCString(&answer->name, fullname);
+ ConvertDomainNameToCString(answer->name, fullname);
ConvertDomainNameToCString(&x->SRV->rdata->u.srv.target, targethost);
x->callback((DNSServiceRef)x, 0, 0, kDNSServiceErr_NoError, fullname, targethost,
- x->SRV->rdata->u.srv.port.NotAnInteger, x->TXT->rdlength, (char*)x->TXT->rdata->u.txt.c, x->context);
+ x->SRV->rdata->u.srv.port.NotAnInteger, x->TXT->rdlength, (unsigned char*)x->TXT->rdata->u.txt.c, x->context);
}
}
}
x->qSRV.ThisQInterval = -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
x->qSRV.InterfaceID = mDNSInterface_Any;
x->qSRV.Target = zeroAddr;
- AssignDomainName(x->qSRV.qname, srv);
+ AssignDomainName(&x->qSRV.qname, &srv);
x->qSRV.qtype = kDNSType_SRV;
x->qSRV.qclass = kDNSClass_IN;
+ x->qSRV.LongLived = mDNSfalse;
+ x->qSRV.ExpectUnique = mDNStrue;
+ x->qSRV.ForceMCast = mDNSfalse;
+ x->qSRV.ReturnIntermed = mDNSfalse;
x->qSRV.QuestionCallback = FoundServiceInfo;
x->qSRV.QuestionContext = x;
x->qTXT.ThisQInterval = -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
x->qTXT.InterfaceID = mDNSInterface_Any;
x->qTXT.Target = zeroAddr;
- AssignDomainName(x->qTXT.qname, srv);
+ AssignDomainName(&x->qTXT.qname, &srv);
x->qTXT.qtype = kDNSType_TXT;
x->qTXT.qclass = kDNSClass_IN;
+ x->qTXT.LongLived = mDNSfalse;
+ x->qTXT.ExpectUnique = mDNStrue;
+ x->qTXT.ForceMCast = mDNSfalse;
+ x->qTXT.ReturnIntermed = mDNSfalse;
+ x->qTXT.SuppressUnusable = mDNSfalse;
x->qTXT.QuestionCallback = FoundServiceInfo;
x->qTXT.QuestionContext = x;
mDNSPlatformMemFree(x);
}
-mDNSlocal void DNSServiceQueryRecordResponse(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
+mDNSlocal void DNSServiceQueryRecordResponse(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
{
mDNS_DirectOP_QueryRecord *x = (mDNS_DirectOP_QueryRecord*)question->QuestionContext;
char fullname[MAX_ESCAPED_DOMAIN_NAME];
(void)m; // Unused
- ConvertDomainNameToCString(&answer->name, fullname);
+ ConvertDomainNameToCString(answer->name, fullname);
x->callback((DNSServiceRef)x, AddRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0, 0, kDNSServiceErr_NoError,
fullname, answer->rrtype, answer->rrclass, answer->rdlength, answer->rdata->u.data, answer->rroriginalttl, x->context);
}
MakeDomainNameFromDNSNameString(&x->q.qname, fullname);
x->q.qtype = rrtype;
x->q.qclass = rrclass;
+ x->q.LongLived = (flags & kDNSServiceFlagsLongLivedQuery) != 0;
+ x->q.ExpectUnique = mDNSfalse;
+ x->q.ForceMCast = (flags & kDNSServiceFlagsForceMulticast) != 0;
+ x->q.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
+ x->q.SuppressUnsable = (flags & kDNSServiceFlagsSuppressUnusable) != 0;
x->q.QuestionCallback = DNSServiceQueryRecordResponse;
x->q.QuestionContext = x;
*sdRef = (DNSServiceRef)x;
return(mStatus_NoError);
-badparam:
- err = mStatus_BadParamErr;
fail:
LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname, rrtype, rrclass, errormsg, err);
return(err);
}
+//*************************************************************************************************************
+// DNSServiceGetAddrInfo
+
+static void DNSServiceGetAddrInfoDispose(mDNS_DirectOP *op)
+ {
+ mDNS_DirectOP_GetAddrInfo *x = (mDNS_DirectOP_GetAddrInfo*)op;
+ if (x->aQuery) DNSServiceRefDeallocate(x->aQuery);
+ mDNSPlatformMemFree(x);
+ }
+
+static void DNSSD_API DNSServiceGetAddrInfoResponse(
+ DNSServiceRef inRef,
+ DNSServiceFlags inFlags,
+ uint32_t inInterfaceIndex,
+ DNSServiceErrorType inErrorCode,
+ const char * inFullName,
+ uint16_t inRRType,
+ uint16_t inRRClass,
+ uint16_t inRDLen,
+ const void * inRData,
+ uint32_t inTTL,
+ void * inContext )
+ {
+ mDNS_DirectOP_GetAddrInfo * x = (mDNS_DirectOP_GetAddrInfo*)inContext;
+ struct sockaddr_in sa4;
+
+ mDNSPlatformMemZero(&sa4, sizeof(sa4));
+ if (inErrorCode == kDNSServiceErr_NoError && inRRType == kDNSServiceType_A)
+ {
+ sa4.sin_family = AF_INET;
+ mDNSPlatformMemCopy(&sa4.sin_addr.s_addr, inRData, 4);
+ }
+
+ x->callback((DNSServiceRef)x, inFlags, inInterfaceIndex, inErrorCode, inFullName,
+ (const struct sockaddr *) &sa4, inTTL, x->context);
+ }
+
+DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo(
+ DNSServiceRef * outRef,
+ DNSServiceFlags inFlags,
+ uint32_t inInterfaceIndex,
+ DNSServiceProtocol inProtocol,
+ const char * inHostName,
+ DNSServiceGetAddrInfoReply inCallback,
+ void * inContext )
+ {
+ const char * errormsg = "Unknown";
+ DNSServiceErrorType err;
+ mDNS_DirectOP_GetAddrInfo * x;
+
+ // Allocate memory, and handle failure
+ x = (mDNS_DirectOP_GetAddrInfo *)mDNSPlatformMemAllocate(sizeof(*x));
+ if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
+
+ // Set up object
+ x->disposefn = DNSServiceGetAddrInfoDispose;
+ x->callback = inCallback;
+ x->context = inContext;
+ x->aQuery = mDNSNULL;
+
+ // Start the query.
+ // (It would probably be more efficient to code this using mDNS_StartQuery directly,
+ // instead of wrapping DNSServiceQueryRecord, which then unnecessarily allocates
+ // more memory and then just calls through to mDNS_StartQuery. -- SC June 2010)
+ err = DNSServiceQueryRecord(&x->aQuery, inFlags, inInterfaceIndex, inHostName, kDNSServiceType_A,
+ kDNSServiceClass_IN, DNSServiceGetAddrInfoResponse, x);
+ if (err) { DNSServiceGetAddrInfoDispose((mDNS_DirectOP*)x); errormsg = "DNSServiceQueryRecord"; goto fail; }
+
+ *outRef = (DNSServiceRef)x;
+ return(mStatus_NoError);
+
+fail:
+ LogMsg("DNSServiceGetAddrInfo(\"%s\", %d) failed: %s (%ld)", inHostName, inProtocol, errormsg, err);
+ return(err);
+ }
+
//*************************************************************************************************************
// DNSServiceReconfirmRecord
// is run against this Extension, it will get a reasonable error code instead of just
// failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
#if !MDNS_BUILDINGSTUBLIBRARY
-void DNSServiceReconfirmRecord
+DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
(
DNSServiceFlags flags,
uint32_t interfaceIndex,
(void)rrclass; // Unused
(void)rdlen; // Unused
(void)rdata; // Unused
+ return(kDNSServiceErr_Unsupported);
}
#endif