summaryrefslogtreecommitdiffstats
path: root/mDNSResponder/mDNSMacOS9/mDNSMacOS9.c
diff options
context:
space:
mode:
Diffstat (limited to 'mDNSResponder/mDNSMacOS9/mDNSMacOS9.c')
-rw-r--r--mDNSResponder/mDNSMacOS9/mDNSMacOS9.c687
1 files changed, 687 insertions, 0 deletions
diff --git a/mDNSResponder/mDNSMacOS9/mDNSMacOS9.c b/mDNSResponder/mDNSMacOS9/mDNSMacOS9.c
new file mode 100644
index 00000000..24b03f22
--- /dev/null
+++ b/mDNSResponder/mDNSMacOS9/mDNSMacOS9.c
@@ -0,0 +1,687 @@
+/* -*- 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>
+#include <stdarg.h> // For va_list support
+
+#include <LowMem.h> // For LMGetCurApName()
+#include <TextUtils.h> // For smSystemScript
+#include <UnicodeConverter.h> // For ConvertFromPStringToUnicode()
+
+#include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
+
+#include "mDNSMacOS9.h" // Defines the specific types needed to run mDNS on this platform
+
+// ***************************************************************************
+// Constants
+
+static const TSetBooleanOption kReusePortOption =
+{ kOTBooleanOptionSize, INET_IP, IP_REUSEPORT, 0, true };
+
+// IP_RCVDSTADDR with TSetByteOption/kOTOneByteOptionSize works on OS 9, OS X Classic, and OS 9 Carbon,
+// but gives error #-3151 (kOTBadOptionErr) on OS X Carbon.
+// If we instead use TSetBooleanOption/kOTBooleanOptionSize then OTOptionManagement on OS X Carbon
+// no longer returns -3151 but it still doesn't actually work -- no destination addresses
+// are delivered by OTRcvUData. I think it's just a bug in OS X Carbon.
+static const TSetByteOption kRcvDestAddrOption =
+{ kOTOneByteOptionSize, INET_IP, IP_RCVDSTADDR, 0, true };
+//static const TSetBooleanOption kRcvDestAddrOption =
+// { kOTBooleanOptionSize, INET_IP, IP_RCVDSTADDR, 0, true };
+
+static const TSetByteOption kSetUnicastTTLOption =
+{ kOTOneByteOptionSize, INET_IP, IP_TTL, 0, 255 };
+
+static const TSetByteOption kSetMulticastTTLOption =
+{ kOTOneByteOptionSize, INET_IP, IP_MULTICAST_TTL, 0, 255 };
+
+static const TIPAddMulticastOption kAddLinkMulticastOption =
+{ sizeof(TIPAddMulticastOption), INET_IP, IP_ADD_MEMBERSHIP, 0, { 224, 0, 0,251 }, { 0,0,0,0 } };
+
+//static const TIPAddMulticastOption kAddAdminMulticastOption =
+// { sizeof(TIPAddMulticastOption), INET_IP, IP_ADD_MEMBERSHIP, 0, { 239,255,255,251 }, { 0,0,0,0 } };
+
+// Bind endpoint to port number. Don't specify any specific IP address --
+// we want to receive unicasts on all interfaces, as well as multicasts.
+typedef struct { OTAddressType fAddressType; mDNSIPPort fPort; mDNSv4Addr fHost; UInt8 fUnused[8]; } mDNSInetAddress;
+//static const mDNSInetAddress mDNSPortInetAddress = { AF_INET, { 0,0 }, { 0,0,0,0 } }; // For testing legacy client support
+#define MulticastDNSPortAsNumber 5353
+static const mDNSInetAddress mDNSPortInetAddress = { AF_INET, { MulticastDNSPortAsNumber >> 8, MulticastDNSPortAsNumber & 0xFF }, { 0,0,0,0 } };
+static const TBind mDNSbindReq = { sizeof(mDNSPortInetAddress), sizeof(mDNSPortInetAddress), (UInt8*)&mDNSPortInetAddress, 0 };
+
+static const TNetbuf zeroTNetbuf = { 0 };
+
+// ***************************************************************************
+// Functions
+
+mDNSlocal void SafeDebugStr(unsigned char *buffer)
+{
+ int i;
+ // Don't want semicolons in MacsBug messages -- they signify commands to execute
+ for (i=1; i<= buffer[0]; i++) if (buffer[i] == ';') buffer[i] = '.';
+ DebugStr(buffer);
+}
+
+#if MDNS_DEBUGMSGS
+mDNSexport void debugf_(const char *format, ...)
+{
+ unsigned char buffer[256];
+ va_list ptr;
+ va_start(ptr,format);
+ buffer[0] = (unsigned char)mDNS_vsnprintf((char*)buffer+1, 255, format, ptr);
+ va_end(ptr);
+#if MDNS_ONLYSYSTEMTASK
+ buffer[1+buffer[0]] = 0;
+ fprintf(stderr, "%s\n", buffer+1);
+ fflush(stderr);
+#else
+ SafeDebugStr(buffer);
+#endif
+}
+#endif
+
+#if MDNS_BUILDINGSHAREDLIBRARY >= 2
+// When building the non-debug version of the Extension, intended to go on end-user systems, we don't want
+// MacsBug breaks for *anything*, not even for the serious LogMsg messages that on OS X would be written to syslog
+mDNSexport void LogMsg(const char *format, ...) { (void)format; }
+#else
+mDNSexport void LogMsg(const char *format, ...)
+{
+ unsigned char buffer[256];
+ va_list ptr;
+ va_start(ptr,format);
+ buffer[0] = (unsigned char)mDNS_vsnprintf((char*)buffer+1, 255, format, ptr);
+ va_end(ptr);
+#if MDNS_ONLYSYSTEMTASK
+ buffer[1+buffer[0]] = 0;
+ fprintf(stderr, "%s\n", buffer+1);
+ fflush(stderr);
+#else
+ SafeDebugStr(buffer);
+#endif
+}
+#endif
+
+mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
+ mDNSInterfaceID InterfaceID, const mDNSAddr *dst, mDNSIPPort dstPort)
+{
+ // Note: If we did multi-homing, we'd have to use the InterfaceID parameter to specify from which interface to send this response
+ #pragma unused(InterfaceID)
+
+ InetAddress InetDest;
+ TUnitData senddata;
+
+ if (dst->type != mDNSAddrType_IPv4) return(mStatus_NoError);
+
+ InetDest.fAddressType = AF_INET;
+ InetDest.fPort = dstPort.NotAnInteger;
+ InetDest.fHost = dst->ip.v4.NotAnInteger;
+
+ senddata.addr.maxlen = sizeof(InetDest);
+ senddata.addr.len = sizeof(InetDest);
+ senddata.addr.buf = (UInt8*)&InetDest;
+ senddata.opt = zeroTNetbuf;
+ senddata.udata.maxlen = (UInt32)((UInt8*)end - (UInt8*)msg);
+ senddata.udata.len = (UInt32)((UInt8*)end - (UInt8*)msg);
+ senddata.udata.buf = (UInt8*)msg;
+
+ return(OTSndUData(m->p->ep, &senddata));
+}
+
+mDNSlocal OSStatus readpacket(mDNS *m)
+{
+ mDNSAddr senderaddr, destaddr;
+ mDNSInterfaceID interface;
+ mDNSIPPort senderport;
+ InetAddress sender;
+ char options[256];
+ DNSMessage packet;
+ TUnitData recvdata;
+ OTFlags flags = 0;
+ OSStatus err;
+
+ recvdata.addr.maxlen = sizeof(sender);
+ recvdata.addr.len = 0;
+ recvdata.addr.buf = (UInt8*)&sender;
+ recvdata.opt.maxlen = sizeof(options);
+ recvdata.opt.len = 0;
+ recvdata.opt.buf = (UInt8*)&options;
+ recvdata.udata.maxlen = sizeof(packet);
+ recvdata.udata.len = 0;
+ recvdata.udata.buf = (UInt8*)&packet;
+
+ err = OTRcvUData(m->p->ep, &recvdata, &flags);
+ if (err && err != kOTNoDataErr) debugf("OTRcvUData error %d", err);
+
+ if (err) return(err);
+
+ senderaddr.type = mDNSAddrType_IPv4;
+ senderaddr.ip.v4.NotAnInteger = sender.fHost;
+ senderport.NotAnInteger = sender.fPort;
+
+ destaddr.type = mDNSAddrType_IPv4;
+ destaddr.ip.v4 = zerov4Addr;
+
+ #if OTCARBONAPPLICATION
+ // IP_RCVDSTADDR is known to fail on OS X Carbon, so we'll just assume the packet was probably multicast
+ destaddr.ip.v4 = AllDNSLinkGroup_v4.ip.v4;
+ #endif
+
+ if (recvdata.opt.len)
+ {
+ TOption *c = nil;
+ while (1)
+ {
+ err = OTNextOption(recvdata.opt.buf, recvdata.opt.len, &c);
+ if (err || !c) break;
+ if (c->level == INET_IP && c->name == IP_RCVDSTADDR && c->len - kOTOptionHeaderSize == sizeof(destaddr.ip.v4))
+ mDNSPlatformMemCopy(&destaddr.ip.v4, c->value, sizeof(destaddr.ip.v4));
+ }
+ }
+
+ interface = m->HostInterfaces->InterfaceID;
+
+ if (flags & T_MORE) debugf("ERROR: OTRcvUData() buffer too small (T_MORE set)");
+ else if (recvdata.addr.len < sizeof(InetAddress)) debugf("ERROR: recvdata.addr.len (%d) too short", recvdata.addr.len);
+ else mDNSCoreReceive(m, &packet, recvdata.udata.buf + recvdata.udata.len, &senderaddr, senderport, &destaddr, MulticastDNSPort, interface);
+
+ return(err);
+}
+
+mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS * const m, TCPSocketFlags flags, mDNSIPPort * port)
+{
+ (void)m; // Unused
+ (void)flags; // Unused
+ (void)port; // Unused
+ return NULL;
+}
+
+mDNSexport TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int sd)
+{
+ (void)flags; // Unused
+ (void)sd; // Unused
+ return NULL;
+}
+
+mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock)
+{
+ (void)sock; // Unused
+ return -1;
+}
+
+mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr * dst, mDNSOpaque16 dstport, mDNSInterfaceID InterfaceID,
+ TCPConnectionCallback callback, void * context)
+{
+ (void)sock; // Unused
+ (void)dst; // Unused
+ (void)dstport; // Unused
+ (void)InterfaceID; // Unused
+ (void)callback; // Unused
+ (void)context; // Unused
+ return(mStatus_UnsupportedErr);
+}
+
+mDNSexport void mDNSPlatformTCPCloseConnection(TCPSocket *sd)
+{
+ (void)sd; // Unused
+}
+
+mDNSexport long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed)
+{
+ (void)sock; // Unused
+ (void)buf; // Unused
+ (void)buflen; // Unused
+ (void)closed; // Unused
+ return(0);
+}
+
+mDNSexport long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len)
+{
+ (void)sock; // Unused
+ (void)msg; // Unused
+ (void)len; // Unused
+ return(0);
+}
+
+mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS * const m, mDNSIPPort port)
+{
+ (void)m; // Unused
+ (void)port; // Unused
+ return NULL;
+}
+
+mDNSexport void mDNSPlatformUDPClose(UDPSocket *sock)
+{
+ (void)sock; // Unused
+}
+
+mDNSlocal void mDNSOptionManagement(mDNS *const m)
+{
+ OSStatus err;
+
+ // Make sure the length in the TNetbuf agrees with the length in the TOptionHeader
+ m->p->optReq.opt.len = m->p->optBlock.h.len;
+ m->p->optReq.opt.maxlen = m->p->optBlock.h.len;
+ if (m->p->optReq.opt.maxlen < 4)
+ m->p->optReq.opt.maxlen = 4;
+
+ err = OTOptionManagement(m->p->ep, &m->p->optReq, NULL);
+ if (err) LogMsg("OTOptionManagement failed %d", err);
+}
+
+mDNSlocal void mDNSinitComplete(mDNS *const m, mStatus result)
+{
+ m->mDNSPlatformStatus = result;
+ mDNSCoreInitComplete(m, mStatus_NoError);
+}
+
+mDNSlocal pascal void mDNSNotifier(void *contextPtr, OTEventCode code, OTResult result, void *cookie)
+{
+ mDNS *const m = (mDNS *const)contextPtr;
+ if (!m) debugf("mDNSNotifier FATAL ERROR! No context");
+ switch (code)
+ {
+ case T_OPENCOMPLETE:
+ {
+ OSStatus err;
+ InetInterfaceInfo interfaceinfo;
+ if (result) { LogMsg("T_OPENCOMPLETE failed %d", result); mDNSinitComplete(m, result); return; }
+ //debugf("T_OPENCOMPLETE");
+ m->p->ep = (EndpointRef)cookie;
+ //debugf("OTInetGetInterfaceInfo");
+ // (In future may want to loop over all interfaces instead of just using kDefaultInetInterface)
+ err = OTInetGetInterfaceInfo(&interfaceinfo, kDefaultInetInterface);
+ if (err) { LogMsg("OTInetGetInterfaceInfo failed %d", err); mDNSinitComplete(m, err); return; }
+
+ // Make our basic standard host resource records (address, PTR, etc.)
+ m->p->interface.InterfaceID = (mDNSInterfaceID)&m->p->interface;
+ m->p->interface.ip.type = mDNSAddrType_IPv4;
+ m->p->interface.ip.ip.v4.NotAnInteger = interfaceinfo.fAddress;
+ m->p->interface.mask.type = mDNSAddrType_IPv4;
+ m->p->interface.mask.ip.v4.NotAnInteger = interfaceinfo.fNetmask;
+ m->p->interface.ifname[0] = 0;
+ m->p->interface.Advertise = m->AdvertiseLocalAddresses;
+ m->p->interface.McastTxRx = mDNStrue;
+ }
+
+ case T_OPTMGMTCOMPLETE:
+ case T_BINDCOMPLETE:
+ // IP_RCVDSTADDR is known to fail on OS X Carbon, so we don't want to abort for that error
+ // (see comment above at the definition of kRcvDestAddrOption)
+ #if OTCARBONAPPLICATION
+ if (result && m->p->mOTstate == mOT_RcvDestAddr)
+ LogMsg("Carbon IP_RCVDSTADDR option failed %d; continuing anyway", result);
+ else
+ #endif
+ if (result) { LogMsg("T_OPTMGMTCOMPLETE/T_BINDCOMPLETE %d failed %d", m->p->mOTstate, result); mDNSinitComplete(m, result); return; }
+ //LogMsg("T_OPTMGMTCOMPLETE/T_BINDCOMPLETE %d", m->p->mOTstate);
+ switch (++m->p->mOTstate)
+ {
+ case mOT_ReusePort: m->p->optBlock.b = kReusePortOption; mDNSOptionManagement(m); break;
+ case mOT_RcvDestAddr: m->p->optBlock.i = kRcvDestAddrOption; mDNSOptionManagement(m); break;
+ case mOT_SetUTTL: m->p->optBlock.i = kSetUnicastTTLOption; mDNSOptionManagement(m); break;
+ case mOT_SetMTTL: m->p->optBlock.i = kSetMulticastTTLOption; mDNSOptionManagement(m); break;
+ case mOT_LLScope: m->p->optBlock.m = kAddLinkMulticastOption; mDNSOptionManagement(m); break;
+// case mOT_AdminScope: m->p->optBlock.m = kAddAdminMulticastOption; mDNSOptionManagement(m); break;
+ case mOT_Bind: OTBind(m->p->ep, (TBind*)&mDNSbindReq, NULL); break;
+ case mOT_Ready: mDNSinitComplete(m, mStatus_NoError);
+ // Can't do mDNS_RegisterInterface until *after* mDNSinitComplete has set m->mDNSPlatformStatus to mStatus_NoError
+ mDNS_RegisterInterface(m, &m->p->interface, mDNSfalse);
+ break;
+ default: LogMsg("Unexpected m->p->mOTstate %d", m->p->mOTstate-1);
+ }
+ break;
+
+ case T_DATA:
+ //debugf("T_DATA");
+ while (readpacket(m) == kOTNoError) continue; // Read packets until we run out
+ break;
+
+ case kOTProviderWillClose: LogMsg("kOTProviderWillClose"); break;
+ case kOTProviderIsClosed: // Machine is going to sleep, shutting down, or reconfiguring IP
+ LogMsg("kOTProviderIsClosed");
+ if (m->p->mOTstate == mOT_Ready)
+ {
+ m->p->mOTstate = mOT_Closed;
+ mDNS_DeregisterInterface(m, &m->p->interface, mDNSfalse);
+ }
+ if (m->p->ep) { OTCloseProvider(m->p->ep); m->p->ep = NULL; }
+ break; // Do we need to do anything?
+
+ default: debugf("mDNSNotifier: Unexpected OTEventCode %X", code);
+ break;
+ }
+}
+
+#if MDNS_ONLYSYSTEMTASK
+
+static Boolean ONLYSYSTEMTASKevent;
+static void *ONLYSYSTEMTASKcontextPtr;
+static OTEventCode ONLYSYSTEMTASKcode;
+static OTResult ONLYSYSTEMTASKresult;
+static void *ONLYSYSTEMTASKcookie;
+
+mDNSlocal pascal void CallmDNSNotifier(void *contextPtr, OTEventCode code, OTResult result, void *cookie)
+{
+ ONLYSYSTEMTASKcontextPtr = contextPtr;
+ ONLYSYSTEMTASKcode = code;
+ ONLYSYSTEMTASKresult = result;
+ ONLYSYSTEMTASKcookie = cookie;
+}
+
+#else
+
+mDNSlocal pascal void CallmDNSNotifier(void *contextPtr, OTEventCode code, OTResult result, void *cookie)
+{
+ mDNS *const m = (mDNS *const)contextPtr;
+ if (!m) debugf("mDNSNotifier FATAL ERROR! No context");
+ if (m->p->nesting) LogMsg("CallmDNSNotifier ERROR! OTEnterNotifier is supposed to suppress notifier callbacks");
+ mDNSNotifier(contextPtr, code, result, cookie);
+}
+
+#endif
+
+static OTNotifyUPP CallmDNSNotifierUPP;
+
+mDNSlocal OSStatus mDNSOpenEndpoint(const mDNS *const m)
+{
+ OSStatus err;
+ // m->optReq is pre-set to point to the shared m->optBlock
+ // m->optBlock is filled in by each OTOptionManagement call
+ m->p->optReq.opt.maxlen = sizeof(m->p->optBlock);
+ m->p->optReq.opt.len = sizeof(m->p->optBlock);
+ m->p->optReq.opt.buf = (UInt8*)&m->p->optBlock;
+ m->p->optReq.flags = T_NEGOTIATE;
+
+ // Open an endpoint and start answering queries
+ //printf("Opening endpoint now...\n");
+ m->p->ep = NULL;
+ m->p->mOTstate = mOT_Start;
+ err = OTAsyncOpenEndpoint(OTCreateConfiguration(kUDPName), 0, NULL, CallmDNSNotifierUPP, (void*)m);
+ if (err) { LogMsg("ERROR: OTAsyncOpenEndpoint(UDP) failed with error <%d>", err); return(err); }
+ return(kOTNoError);
+}
+
+// Define these here because they're not in older versions of OpenTransport.h
+enum
+{
+ xOTStackIsLoading = 0x27000001, /* Sent before Open Transport attempts to load the TCP/IP protocol stack.*/
+ xOTStackWasLoaded = 0x27000002, /* Sent after the TCP/IP stack has been successfully loaded.*/
+ xOTStackIsUnloading = 0x27000003 /* Sent before Open Transport unloads the TCP/IP stack.*/
+};
+
+static mDNS *ClientNotifierContext;
+
+mDNSlocal pascal void ClientNotifier(void *contextPtr, OTEventCode code, OTResult result, void *cookie)
+{
+ mDNS *const m = ClientNotifierContext;
+
+ #pragma unused(contextPtr) // Usually zero (except one in the 'xOTStackIsLoading' case)
+ #pragma unused(cookie) // Usually 'ipv4' (except for kOTPortNetworkChange)
+ #pragma unused(result) // Usually zero
+
+ switch (code)
+ {
+ case xOTStackIsLoading: break;
+ case xOTStackWasLoaded: if (m->p->mOTstate == mOT_Closed)
+ {
+ LogMsg("kOTStackWasLoaded: Re-opening endpoint");
+ if (m->p->ep)
+ LogMsg("kOTStackWasLoaded: ERROR: m->p->ep already set");
+ m->mDNSPlatformStatus = mStatus_Waiting;
+ m->p->mOTstate = mOT_Reset;
+ #if !MDNS_ONLYSYSTEMTASK
+ mDNSOpenEndpoint(m);
+ #endif
+ }
+ else
+ LogMsg("kOTStackWasLoaded (no action)");
+ break;
+ case xOTStackIsUnloading: break;
+ case kOTPortNetworkChange: break;
+ default: debugf("ClientNotifier unknown code %X, %X, %d", contextPtr, code, result); break;
+ }
+}
+
+#if TARGET_API_MAC_CARBON
+
+mDNSlocal void GetUserSpecifiedComputerName(domainlabel *const namelabel)
+{
+ CFStringRef cfs = CSCopyMachineName();
+ CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
+ CFRelease(cfs);
+}
+
+#else
+
+mDNSlocal OSStatus ConvertStringHandleToUTF8(const StringHandle machineName, UInt8 *const utf8, ByteCount maxlen)
+{
+ OSStatus status;
+ TextEncoding utf8TextEncoding, SystemTextEncoding;
+ UnicodeMapping theMapping;
+ TextToUnicodeInfo textToUnicodeInfo;
+ ByteCount unicodelen = 0;
+
+ if (maxlen > 255) maxlen = 255; // Can't put more than 255 in a Pascal String
+
+ utf8TextEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault, kTextEncodingDefaultVariant, kUnicodeUTF8Format);
+ UpgradeScriptInfoToTextEncoding(smSystemScript, kTextLanguageDontCare, kTextRegionDontCare, NULL, &SystemTextEncoding);
+ theMapping.unicodeEncoding = utf8TextEncoding;
+ theMapping.otherEncoding = SystemTextEncoding;
+ theMapping.mappingVersion = kUnicodeUseLatestMapping;
+ status = CreateTextToUnicodeInfo(&theMapping, &textToUnicodeInfo);
+ if (status == noErr)
+ {
+ status = ConvertFromPStringToUnicode(textToUnicodeInfo, *machineName, maxlen, &unicodelen, (UniCharArrayPtr)&(utf8[1]));
+ DisposeTextToUnicodeInfo(&textToUnicodeInfo);
+ }
+ utf8[0] = (UInt8)unicodelen;
+ return(status);
+}
+
+mDNSlocal void GetUserSpecifiedComputerName(domainlabel *const namelabel)
+{
+ StringHandle machineName = GetString(-16413); // Get machine name set in file sharing
+ if (machineName)
+ {
+ char machineNameState = HGetState((Handle)machineName);
+ HLock((Handle)machineName);
+ ConvertStringHandleToUTF8(machineName, namelabel->c, MAX_DOMAIN_LABEL);
+ HSetState((Handle)machineName, machineNameState);
+ }
+}
+
+#endif
+
+static pascal void mDNSTimerTask(void *arg)
+{
+#if MDNS_ONLYSYSTEMTASK
+#pragma unused(arg)
+ ONLYSYSTEMTASKevent = true;
+#else
+ mDNS *const m = (mDNS *const)arg;
+ if (!m->p->ep) LogMsg("mDNSTimerTask NO endpoint");
+ if (m->mDNS_busy) LogMsg("mDNS_busy");
+ if (m->p->nesting) LogMsg("mDNSTimerTask ERROR! OTEnterNotifier is supposed to suppress timer callbacks too");
+
+ // If our timer fires at a time when we have no endpoint, ignore it --
+ // once we reopen our endpoint and get our T_BINDCOMPLETE message we'll call
+ // mDNS_RegisterInterface(), which does a lock/unlock, which retriggers the timer.
+ // Likewise, if m->mDNS_busy or m->p->nesting, we'll catch this on the unlock
+ if (m->p->ep && m->mDNS_busy == 0 && m->p->nesting == 0) mDNS_Execute(m);
+#endif
+}
+
+#if TEST_SLEEP
+long sleep, wake, mode;
+#endif
+
+mDNSexport mStatus mDNSPlatformInit (mDNS *const m)
+{
+ OSStatus err = InitOpenTransport();
+
+ ClientNotifierContext = m;
+ // Note: OTRegisterAsClient returns kOTNotSupportedErr when running as Carbon code on OS X
+ // -- but that's okay, we don't need a ClientNotifier when running as Carbon code on OS X
+ OTRegisterAsClient(NULL, NewOTNotifyUPP(ClientNotifier));
+
+ m->p->OTTimerTask = OTCreateTimerTask(NewOTProcessUPP(mDNSTimerTask), m);
+ m->p->nesting = 0;
+
+#if TEST_SLEEP
+ sleep = TickCount() + 600;
+ wake = TickCount() + 1200;
+ mode = 0;
+#endif
+
+ // Set up the nice label
+ m->nicelabel.c[0] = 0;
+ GetUserSpecifiedComputerName(&m->nicelabel);
+// m->nicelabel = *(domainlabel*)"\pStu"; // For conflict testing
+ if (m->nicelabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->nicelabel, "Macintosh");
+
+ // Set up the RFC 1034-compliant label
+ m->hostlabel.c[0] = 0;
+ ConvertUTF8PstringToRFC1034HostLabel(m->nicelabel.c, &m->hostlabel);
+ if (m->hostlabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->hostlabel, "Macintosh");
+
+ mDNS_SetFQDN(m);
+
+ // When it's finished mDNSOpenEndpoint asynchronously calls mDNSinitComplete() and then mDNS_RegisterInterface()
+ CallmDNSNotifierUPP = NewOTNotifyUPP(CallmDNSNotifier);
+ err = mDNSOpenEndpoint(m);
+ if (err)
+ {
+ LogMsg("mDNSOpenEndpoint failed %d", err);
+ if (m->p->OTTimerTask) OTDestroyTimerTask(m->p->OTTimerTask);
+ OTUnregisterAsClient();
+ CloseOpenTransport();
+ }
+ return(err);
+}
+
+extern void mDNSPlatformClose (mDNS *const m)
+{
+ if (m->p->mOTstate == mOT_Ready)
+ {
+ m->p->mOTstate = mOT_Closed;
+ mDNS_DeregisterInterface(m, &m->p->interface, mDNSfalse);
+ }
+ if (m->p->ep) { OTCloseProvider (m->p->ep); m->p->ep = NULL; }
+ if (m->p->OTTimerTask) { OTDestroyTimerTask(m->p->OTTimerTask); m->p->OTTimerTask = 0; }
+
+ OTUnregisterAsClient();
+ CloseOpenTransport();
+}
+
+#if MDNS_ONLYSYSTEMTASK
+extern void mDNSPlatformIdle(mDNS *const m);
+mDNSexport void mDNSPlatformIdle(mDNS *const m)
+{
+ while (ONLYSYSTEMTASKcontextPtr)
+ {
+ void *contextPtr = ONLYSYSTEMTASKcontextPtr;
+ ONLYSYSTEMTASKcontextPtr = NULL;
+ mDNSNotifier(contextPtr, ONLYSYSTEMTASKcode, ONLYSYSTEMTASKresult, ONLYSYSTEMTASKcookie);
+ }
+ if (ONLYSYSTEMTASKevent)
+ {
+ ONLYSYSTEMTASKevent = false;
+ mDNS_Execute(m);
+ }
+
+ if (m->p->mOTstate == mOT_Reset)
+ {
+ printf("\n");
+ printf("******************************************************************************\n");
+ printf("\n");
+ printf("Reopening endpoint\n");
+ mDNSOpenEndpoint(m);
+ m->ResourceRecords = NULL;
+ }
+
+#if TEST_SLEEP
+ switch (mode)
+ {
+ case 0: if ((long)TickCount() - sleep >= 0) { mDNSCoreMachineSleep(m, 1); mode++; }
+ break;
+ case 1: if ((long)TickCount() - wake >= 0) { mDNSCoreMachineSleep(m, 0); mode++; }
+ break;
+ }
+#endif
+}
+#endif
+
+mDNSexport void mDNSPlatformLock(const mDNS *const m)
+{
+ if (!m) { DebugStr("\pmDNSPlatformLock m NULL!"); return; }
+ if (!m->p) { DebugStr("\pmDNSPlatformLock m->p NULL!"); return; }
+
+ // If we try to call OTEnterNotifier and fail because we're already running at
+ // Notifier context, then make sure we don't do the matching OTLeaveNotifier() on exit.
+ // If we haven't even opened our endpoint yet, then just increment m->p->nesting for the same reason
+ if (m->p->mOTstate == mOT_Ready && !m->p->ep) DebugStr("\pmDNSPlatformLock: m->p->mOTstate == mOT_Ready && !m->p->ep");
+ if (!m->p->ep || m->p->nesting || OTEnterNotifier(m->p->ep) == false) m->p->nesting++;
+}
+
+mDNSlocal void ScheduleNextTimerCallback(const mDNS *const m)
+{
+ if (m->mDNSPlatformStatus == mStatus_NoError)
+ {
+ SInt32 interval = m->NextScheduledEvent - mDNS_TimeNow_NoLock(m);
+ if (interval < 1) interval = 1;
+ else if (interval > 0x70000000 / 1000) interval = 0x70000000 / mDNSPlatformOneSecond;
+ else interval = (interval * 1000 + mDNSPlatformOneSecond-1)/ mDNSPlatformOneSecond;
+ OTScheduleTimerTask(m->p->OTTimerTask, (OTTimeout)interval);
+ }
+}
+
+mDNSexport void mDNSPlatformUnlock(const mDNS *const m)
+{
+ if (!m) { DebugStr("\pmDNSPlatformUnlock m NULL!"); return; }
+ if (!m->p) { DebugStr("\pmDNSPlatformUnlock m->p NULL!"); return; }
+
+ if (m->p->ep && m->mDNS_busy == 0) ScheduleNextTimerCallback(m);
+
+ if (m->p->nesting) m->p->nesting--;
+ else OTLeaveNotifier(m->p->ep);
+}
+
+mDNSexport void mDNSPlatformStrCopy( void *dst, const void *src) { OTStrCopy((char*)dst, (char*)src); }
+mDNSexport UInt32 mDNSPlatformStrLen ( const void *src) { return(OTStrLength((char*)src)); }
+mDNSexport void mDNSPlatformMemCopy( void *dst, const void *src, UInt32 len) { OTMemcpy(dst, src, len); }
+mDNSexport mDNSBool mDNSPlatformMemSame(const void *dst, const void *src, UInt32 len) { return(OTMemcmp(dst, src, len)); }
+mDNSexport void mDNSPlatformMemZero( void *dst, UInt32 len) { OTMemzero(dst, len); }
+mDNSexport void * mDNSPlatformMemAllocate(mDNSu32 len) { return(OTAllocMem(len)); }
+mDNSexport void mDNSPlatformMemFree(void *mem) { OTFreeMem(mem); }
+mDNSexport mDNSu32 mDNSPlatformRandomSeed(void) { return(TickCount()); }
+mDNSexport mStatus mDNSPlatformTimeInit(void) { return(mStatus_NoError); }
+mDNSexport SInt32 mDNSPlatformRawTime() { return((SInt32)TickCount()); }
+mDNSexport SInt32 mDNSPlatformOneSecond = 60;
+
+mDNSexport mDNSs32 mDNSPlatformUTC(void)
+{
+ // Classic Mac OS since Midnight, 1st Jan 1904
+ // Standard Unix counts from 1970
+ // This value adjusts for the 66 years and 17 leap-days difference
+ mDNSu32 SecsSince1904;
+ MachineLocation ThisLocation;
+ #define TIME_ADJUST (((1970 - 1904) * 365 + 17) * 24 * 60 * 60)
+ #define ThisLocationGMTdelta ((ThisLocation.u.gmtDelta << 8) >> 8)
+ GetDateTime(&SecsSince1904);
+ ReadLocation(&ThisLocation);
+ return((mDNSs32)(SecsSince1904 - ThisLocationGMTdelta - TIME_ADJUST));
+}