*
* @APPLE_LICENSE_HEADER_START@
*
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
+ *
* 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
Change History (most recent first):
$Log: mDNSMacOS9.c,v $
+Revision 1.29 2004/05/26 20:53:16 cheshire
+Remove unncecessary "return( -1 );" at the end of mDNSPlatformUTC()
+
+Revision 1.28 2004/05/20 18:39:06 cheshire
+Fix build broken by addition of mDNSPlatformUTC requirement
+
+Revision 1.27 2004/04/21 02:49:11 cheshire
+To reduce future confusion, renamed 'TxAndRx' to 'McastTxRx'
+
+Revision 1.26 2004/04/09 17:43:03 cheshire
+Make sure to set the McastTxRx field so that duplicate suppression works correctly
+
+Revision 1.25 2004/03/15 18:55:38 cheshire
+Comment out debugging message
+
+Revision 1.24 2004/03/12 21:30:26 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.
+
+Revision 1.23 2004/02/09 23:24:43 cheshire
+Need to set TTL 255 to interoperate with peers that check TTL (oops!)
+
+Revision 1.22 2004/01/27 20:15:23 cheshire
+<rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
+
+Revision 1.21 2004/01/24 04:59:16 cheshire
+Fixes so that Posix/Linux, OS9, Windows, and VxWorks targets build again
+
+Revision 1.20 2003/11/14 20:59:09 cheshire
+Clients can't use AssignDomainName macro because mDNSPlatformMemCopy is defined in mDNSPlatformFunctions.h.
+Best solution is just to combine mDNSClientAPI.h and mDNSPlatformFunctions.h into a single file.
+
Revision 1.19 2003/08/18 23:09:20 cheshire
<rdar://problem/3382647> mDNSResponder divide by zero in mDNSPlatformTimeNow()
*/
+#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 <stdio.h>
-#include <stdarg.h> // For va_list support
-
#include "mDNSClientAPI.h" // Defines the interface provided to the client layer above
-#include "mDNSPlatformFunctions.h" // Defines the interface to the supporting layer below
#include "mDNSMacOS9.h" // Defines the specific types needed to run mDNS on this platform
// Constants
static const TSetBooleanOption kReusePortOption =
- { sizeof(TSetBooleanOption), INET_IP, IP_REUSEPORT, 0, true };
+ { 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 };
-// IP_RCVDSTADDR gives error #-3151 (kOTBadOptionErr)
-static const TSetBooleanOption kRcvDestAddrOption =
- { sizeof(TSetBooleanOption), INET_IP, IP_REUSEPORT, 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 } };
+//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.
// ***************************************************************************
// 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, ...)
{
va_start(ptr,format);
buffer[0] = (unsigned char)mDNS_vsnprintf((char*)buffer+1, 255, format, ptr);
va_end(ptr);
-#if __ONLYSYSTEMTASK__
+#if MDNS_ONLYSYSTEMTASK
buffer[1+buffer[0]] = 0;
fprintf(stderr, "%s\n", buffer+1);
fflush(stderr);
#else
- DebugStr(buffer);
+ 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_start(ptr,format);
buffer[0] = (unsigned char)mDNS_vsnprintf((char*)buffer+1, 255, format, ptr);
va_end(ptr);
-#if __ONLYSYSTEMTASK__
+#if MDNS_ONLYSYSTEMTASK
buffer[1+buffer[0]] = 0;
fprintf(stderr, "%s\n", buffer+1);
fflush(stderr);
#else
- DebugStr(buffer);
+ SafeDebugStr(buffer);
#endif
}
+#endif
mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
- mDNSInterfaceID InterfaceID, mDNSIPPort srcPort, const mDNSAddr *dst, mDNSIPPort dstPort)
+ 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, srcPort)
+ #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;
mDNSInterfaceID interface;
mDNSIPPort senderport;
InetAddress sender;
- char options[512];
+ char options[256];
DNSMessage packet;
TUnitData recvdata;
OTFlags flags = 0;
senderaddr.type = mDNSAddrType_IPv4;
senderaddr.ip.v4.NotAnInteger = sender.fHost;
senderport.NotAnInteger = sender.fPort;
+
destaddr.type = mDNSAddrType_IPv4;
- destaddr.ip.v4 = AllDNSLinkGroup; // For now, until I work out how to get the dest address, assume it was sent to AllDNSLinkGroup
+ destaddr.ip.v4 = zeroIPAddr;
+
+ #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;
+ #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(c->value, &destaddr.ip.v4, sizeof(destaddr.ip.v4));
+ }
+ }
+
interface = m->HostInterfaces->InterfaceID;
-
- if (recvdata.opt.len) debugf("readpacket: got some option data at %X, len %d", options, recvdata.opt.len);
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);
return(err);
}
+mDNSexport mStatus mDNSPlatformTCPConnect(const mDNSAddr *dst, mDNSOpaque16 dstport, mDNSInterfaceID InterfaceID,
+ TCPConnectionCallback callback, void *context, int *descriptor)
+ {
+ (void)dst; // Unused
+ (void)dstport; // Unused
+ (void)InterfaceID; // Unused
+ (void)callback; // Unused
+ (void)context; // Unused
+ (void)descriptor; // Unused
+ return(mStatus_UnsupportedErr);
+ }
+
+mDNSexport void mDNSPlatformTCPCloseConnection(int sd)
+ {
+ (void)sd; // Unused
+ }
+
+mDNSexport int mDNSPlatformReadTCP(int sd, void *buf, int buflen)
+ {
+ (void)sd; // Unused
+ (void)buf; // Unused
+ (void)buflen; // Unused
+ return(0);
+ }
+
+mDNSexport int mDNSPlatformWriteTCP(int sd, const char *msg, int len)
+ {
+ (void)sd; // Unused
+ (void)msg; // Unused
+ (void)len; // Unused
+ return(0);
+ }
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.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) debugf("OTOptionManagement failed %d", err);
+ if (err) LogMsg("OTOptionManagement failed %d", err);
}
mDNSlocal void mDNSinitComplete(mDNS *const m, mStatus result)
{
OSStatus err;
InetInterfaceInfo interfaceinfo;
- if (result) { debugf("T_OPENCOMPLETE failed %d", result); mDNSinitComplete(m, result); return; }
+ 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) { debugf("OTInetGetInterfaceInfo failed %d", err); mDNSinitComplete(m, err); return; }
+ 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.Advertise = m->AdvertiseLocalAddresses;
- m->p->interface.InterfaceID = (mDNSInterfaceID)&m->p->interface;
- mDNS_RegisterInterface(m, &m->p->interface);
+ m->p->interface.McastTxRx = mDNStrue;
}
case T_OPTMGMTCOMPLETE:
- if (result) { debugf("T_OPTMGMTCOMPLETE failed %d", result); mDNSinitComplete(m, result); return; }
- //debugf("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.b = kRcvDestAddrOption; 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_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);
+ break;
+ default: LogMsg("Unexpected m->p->mOTstate %d", m->p->mOTstate-1);
}
break;
- case T_BINDCOMPLETE:
- if (result) { debugf("T_BINDCOMPLETE failed %d", result); return; }
- if (m->p->mOTstate != mOT_Bind) { debugf("T_BINDCOMPLETE in wrong mDNS state %d", m->p->mOTstate); return; }
- m->p->mOTstate++;
- //debugf("T_BINDCOMPLETE");
- mDNSinitComplete(m, mStatus_NoError);
- break;
-
case T_DATA:
//debugf("T_DATA");
while (readpacket(m) == kOTNoError) continue; // Read packets until we run out
break;
- case kOTProviderWillClose:
+ 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);
+ }
if (m->p->ep) { OTCloseProvider(m->p->ep); m->p->ep = NULL; }
break; // Do we need to do anything?
}
}
-#if __ONLYSYSTEMTASK__
+#if MDNS_ONLYSYSTEMTASK
static Boolean ONLYSYSTEMTASKevent;
static void *ONLYSYSTEMTASKcontextPtr;
{
mDNS *const m = (mDNS *const)contextPtr;
if (!m) debugf("mDNSNotifier FATAL ERROR! No context");
-
- // Increment m->p->nesting to indicate to mDNSPlatformLock that there's no need
- // to call OTEnterNotifier() (because we're already in OTNotifier context)
- if (m->p->nesting) DebugStr("\pCallmDNSNotifier ERROR! OTEnterNotifier is supposed to suppress notifier callbacks");
- m->p->nesting++;
+ if (m->p->nesting) LogMsg("CallmDNSNotifier ERROR! OTEnterNotifier is supposed to suppress notifier callbacks");
mDNSNotifier(contextPtr, code, result, cookie);
- m->p->nesting--;
- ScheduleNextTimerCallback(m);
}
#endif
+static OTNotifyUPP CallmDNSNotifierUPP;
+
mDNSlocal OSStatus mDNSOpenEndpoint(const mDNS *const m)
{
OSStatus err;
- TEndpointInfo endpointinfo;
// 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);
//printf("Opening endpoint now...\n");
m->p->ep = NULL;
m->p->mOTstate = mOT_Start;
-// err = OTAsyncOpenEndpoint(OTCreateConfiguration("udp(RxICMP=1)"), 0, &endpointinfo, CallmDNSNotifier, (void*)m); // works
-// err = OTAsyncOpenEndpoint(OTCreateConfiguration("udp(RxICMP)"), 0, &endpointinfo, CallmDNSNotifier, (void*)m); // -3151 bad option
-// err = OTAsyncOpenEndpoint(OTCreateConfiguration("udp,ip(RxICMP=1)"), 0, &endpointinfo, CallmDNSNotifier, (void*)m); // -3151
-// err = OTAsyncOpenEndpoint(OTCreateConfiguration("udp,ip"), 0, &endpointinfo, CallmDNSNotifier, (void*)m); // works
-// err = OTAsyncOpenEndpoint(OTCreateConfiguration("udp,rawip"), 0, &endpointinfo, CallmDNSNotifier, (void*)m); // -3221 invalid arg
- err = OTAsyncOpenEndpoint(OTCreateConfiguration(kUDPName), 0, &endpointinfo, NewOTNotifyUPP(CallmDNSNotifier), (void*)m);
- if (err) { debugf("ERROR: OTAsyncOpenEndpoint(UDP) failed with error <%d>", err); return(err); }
-
+ err = OTAsyncOpenEndpoint(OTCreateConfiguration(kUDPName), 0, NULL, CallmDNSNotifierUPP, (void*)m);
+ if (err) { LogMsg("ERROR: OTAsyncOpenEndpoint(UDP) failed with error <%d>", err); return(err); }
return(kOTNoError);
}
switch (code)
{
- case xOTStackIsLoading: break;
- case xOTStackWasLoaded: m->mDNSPlatformStatus = mStatus_Waiting; m->p->mOTstate = mOT_Reset; break;
- case xOTStackIsUnloading: break;
- case kOTPortNetworkChange: break;
+ 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;
}
}
static pascal void mDNSTimerTask(void *arg)
{
-#if __ONLYSYSTEMTASK__
+#if MDNS_ONLYSYSTEMTASK
#pragma unused(arg)
ONLYSYSTEMTASKevent = true;
#else
mDNS *const m = (mDNS *const)arg;
- // Increment m->p->nesting to indicate to mDNSPlatformLock that there's no need
- // to call OTEnterNotifier() (because we're already in OTNotifier context)
- if (m->p->nesting) DebugStr("\pmDNSTimerTask ERROR! OTEnterNotifier is supposed to suppress timer callbacks too");
- m->p->nesting++;
- mDNS_Execute(m);
- m->p->nesting--;
- ScheduleNextTimerCallback(m);
+ 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
}
mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
{
- OSStatus err;
+ 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);
mDNS_GenerateFQDN(m);
- ClientNotifierContext = m;
-
-#if !TARGET_API_MAC_CARBON
- err = OTRegisterAsClient(LMGetCurApName(), NewOTNotifyUPP(ClientNotifier));
- if (err) debugf("OTRegisterAsClient failed %d", err);
-#endif
-
+ // When it's finished mDNSOpenEndpoint asynchronously calls mDNSinitComplete() and then mDNS_RegisterInterface()
+ CallmDNSNotifierUPP = NewOTNotifyUPP(CallmDNSNotifier);
err = mDNSOpenEndpoint(m);
- if (err) { debugf("mDNSOpenEndpoint failed %d", err); return(err); }
-
- m->p->OTTimerTask = OTCreateTimerTask(NewOTProcessUPP(mDNSTimerTask), m);
- m->p->nesting = 0;
-
-#if TEST_SLEEP
- sleep = TickCount() + 600;
- wake = TickCount() + 1200;
- mode = 0;
-#endif
-
+ 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->OTTimerTask) { OTDestroyTimerTask(m->p->OTTimerTask); m->p->OTTimerTask = 0; }
+ if (m->p->mOTstate == mOT_Ready)
+ {
+ m->p->mOTstate = mOT_Closed;
+ mDNS_DeregisterInterface(m, &m->p->interface);
+ }
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)
{
-#if __ONLYSYSTEMTASK__
while (ONLYSYSTEMTASKcontextPtr)
{
void *contextPtr = ONLYSYSTEMTASKcontextPtr;
ONLYSYSTEMTASKevent = false;
mDNS_Execute(m);
}
-#endif
if (m->p->mOTstate == mOT_Reset)
{
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 (!m->p->ep) { DebugStr("\pmDNSPlatformLock m->p->ep 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 (m->p->nesting || OTEnterNotifier(m->p->ep) == false) m->p->nesting++;
+ // 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)
{
- SInt32 interval;
- interval = m->NextScheduledEvent - mDNSPlatformTimeNow();
- if (interval < 0) interval = 0;
- else if (interval > 0x7FFFFFFF / 1000) interval = 0x7FFFFFFF / mDNSPlatformOneSecond;
- else interval = interval * 1000 / mDNSPlatformOneSecond;
- //debugf("mDNSPlatformScheduleTask Interval %d", interval);
- OTScheduleTimerTask(m->p->OTTimerTask, (OTTimeout)interval);
+ if (m->mDNSPlatformStatus == mStatus_NoError)
+ {
+ SInt32 interval = m->NextScheduledEvent - mDNSPlatformTimeNow();
+ 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) { DebugStr("\pmDNSPlatformUnlock m->p->ep NULL!"); return; }
+
+ if (m->p->ep && m->mDNS_busy == 0) ScheduleNextTimerCallback(m);
+
if (m->p->nesting) m->p->nesting--;
- else
- {
- ScheduleNextTimerCallback(m);
- OTLeaveNotifier(m->p->ep);
- }
+ else OTLeaveNotifier(m->p->ep);
}
mDNSexport void mDNSPlatformStrCopy(const void *src, void *dst) { OTStrCopy((char*)dst, (char*)src); }
mDNSexport mStatus mDNSPlatformTimeInit(mDNSs32 *timenow) { *timenow = mDNSPlatformTimeNow(); return(mStatus_NoError); }
mDNSexport SInt32 mDNSPlatformTimeNow() { 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));
+ }