1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <stdarg.h> // For va_list support
21 #include <LowMem.h> // For LMGetCurApName()
22 #include <TextUtils.h> // For smSystemScript
23 #include <UnicodeConverter.h> // For ConvertFromPStringToUnicode()
25 #include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
27 #include "mDNSMacOS9.h" // Defines the specific types needed to run mDNS on this platform
29 // ***************************************************************************
32 static const TSetBooleanOption kReusePortOption
=
33 { kOTBooleanOptionSize
, INET_IP
, IP_REUSEPORT
, 0, true };
35 // IP_RCVDSTADDR with TSetByteOption/kOTOneByteOptionSize works on OS 9, OS X Classic, and OS 9 Carbon,
36 // but gives error #-3151 (kOTBadOptionErr) on OS X Carbon.
37 // If we instead use TSetBooleanOption/kOTBooleanOptionSize then OTOptionManagement on OS X Carbon
38 // no longer returns -3151 but it still doesn't actually work -- no destination addresses
39 // are delivered by OTRcvUData. I think it's just a bug in OS X Carbon.
40 static const TSetByteOption kRcvDestAddrOption
=
41 { kOTOneByteOptionSize
, INET_IP
, IP_RCVDSTADDR
, 0, true };
42 //static const TSetBooleanOption kRcvDestAddrOption =
43 // { kOTBooleanOptionSize, INET_IP, IP_RCVDSTADDR, 0, true };
45 static const TSetByteOption kSetUnicastTTLOption
=
46 { kOTOneByteOptionSize
, INET_IP
, IP_TTL
, 0, 255 };
48 static const TSetByteOption kSetMulticastTTLOption
=
49 { kOTOneByteOptionSize
, INET_IP
, IP_MULTICAST_TTL
, 0, 255 };
51 static const TIPAddMulticastOption kAddLinkMulticastOption
=
52 { sizeof(TIPAddMulticastOption
), INET_IP
, IP_ADD_MEMBERSHIP
, 0, { 224, 0, 0,251 }, { 0,0,0,0 } };
54 //static const TIPAddMulticastOption kAddAdminMulticastOption =
55 // { sizeof(TIPAddMulticastOption), INET_IP, IP_ADD_MEMBERSHIP, 0, { 239,255,255,251 }, { 0,0,0,0 } };
57 // Bind endpoint to port number. Don't specify any specific IP address --
58 // we want to receive unicasts on all interfaces, as well as multicasts.
59 typedef struct { OTAddressType fAddressType
; mDNSIPPort fPort
; mDNSv4Addr fHost
; UInt8 fUnused
[8]; } mDNSInetAddress
;
60 //static const mDNSInetAddress mDNSPortInetAddress = { AF_INET, { 0,0 }, { 0,0,0,0 } }; // For testing legacy client support
61 #define MulticastDNSPortAsNumber 5353
62 static const mDNSInetAddress mDNSPortInetAddress
= { AF_INET
, { MulticastDNSPortAsNumber
>> 8, MulticastDNSPortAsNumber
& 0xFF }, { 0,0,0,0 } };
63 static const TBind mDNSbindReq
= { sizeof(mDNSPortInetAddress
), sizeof(mDNSPortInetAddress
), (UInt8
*)&mDNSPortInetAddress
, 0 };
65 static const TNetbuf zeroTNetbuf
= { 0 };
67 // ***************************************************************************
70 mDNSlocal
void SafeDebugStr(unsigned char *buffer
)
73 // Don't want semicolons in MacsBug messages -- they signify commands to execute
74 for (i
=1; i
<= buffer
[0]; i
++) if (buffer
[i
] == ';') buffer
[i
] = '.';
79 mDNSexport
void debugf_(const char *format
, ...)
81 unsigned char buffer
[256];
84 buffer
[0] = (unsigned char)mDNS_vsnprintf((char*)buffer
+1, 255, format
, ptr
);
86 #if MDNS_ONLYSYSTEMTASK
87 buffer
[1+buffer
[0]] = 0;
88 fprintf(stderr
, "%s\n", buffer
+1);
96 #if MDNS_BUILDINGSHAREDLIBRARY >= 2
97 // When building the non-debug version of the Extension, intended to go on end-user systems, we don't want
98 // MacsBug breaks for *anything*, not even for the serious LogMsg messages that on OS X would be written to syslog
99 mDNSexport
void LogMsg(const char *format
, ...) { (void)format
; }
101 mDNSexport
void LogMsg(const char *format
, ...)
103 unsigned char buffer
[256];
105 va_start(ptr
,format
);
106 buffer
[0] = (unsigned char)mDNS_vsnprintf((char*)buffer
+1, 255, format
, ptr
);
108 #if MDNS_ONLYSYSTEMTASK
109 buffer
[1+buffer
[0]] = 0;
110 fprintf(stderr
, "%s\n", buffer
+1);
113 SafeDebugStr(buffer
);
118 mDNSexport mStatus
mDNSPlatformSendUDP(const mDNS
*const m
, const void *const msg
, const mDNSu8
*const end
,
119 mDNSInterfaceID InterfaceID
, const mDNSAddr
*dst
, mDNSIPPort dstPort
)
121 // Note: If we did multi-homing, we'd have to use the InterfaceID parameter to specify from which interface to send this response
122 #pragma unused(InterfaceID)
124 InetAddress InetDest
;
127 if (dst
->type
!= mDNSAddrType_IPv4
) return(mStatus_NoError
);
129 InetDest
.fAddressType
= AF_INET
;
130 InetDest
.fPort
= dstPort
.NotAnInteger
;
131 InetDest
.fHost
= dst
->ip
.v4
.NotAnInteger
;
133 senddata
.addr
.maxlen
= sizeof(InetDest
);
134 senddata
.addr
.len
= sizeof(InetDest
);
135 senddata
.addr
.buf
= (UInt8
*)&InetDest
;
136 senddata
.opt
= zeroTNetbuf
;
137 senddata
.udata
.maxlen
= (UInt32
)((UInt8
*)end
- (UInt8
*)msg
);
138 senddata
.udata
.len
= (UInt32
)((UInt8
*)end
- (UInt8
*)msg
);
139 senddata
.udata
.buf
= (UInt8
*)msg
;
141 return(OTSndUData(m
->p
->ep
, &senddata
));
144 mDNSlocal OSStatus
readpacket(mDNS
*m
)
146 mDNSAddr senderaddr
, destaddr
;
147 mDNSInterfaceID interface
;
148 mDNSIPPort senderport
;
156 recvdata
.addr
.maxlen
= sizeof(sender
);
157 recvdata
.addr
.len
= 0;
158 recvdata
.addr
.buf
= (UInt8
*)&sender
;
159 recvdata
.opt
.maxlen
= sizeof(options
);
160 recvdata
.opt
.len
= 0;
161 recvdata
.opt
.buf
= (UInt8
*)&options
;
162 recvdata
.udata
.maxlen
= sizeof(packet
);
163 recvdata
.udata
.len
= 0;
164 recvdata
.udata
.buf
= (UInt8
*)&packet
;
166 err
= OTRcvUData(m
->p
->ep
, &recvdata
, &flags
);
167 if (err
&& err
!= kOTNoDataErr
) debugf("OTRcvUData error %d", err
);
169 if (err
) return(err
);
171 senderaddr
.type
= mDNSAddrType_IPv4
;
172 senderaddr
.ip
.v4
.NotAnInteger
= sender
.fHost
;
173 senderport
.NotAnInteger
= sender
.fPort
;
175 destaddr
.type
= mDNSAddrType_IPv4
;
176 destaddr
.ip
.v4
= zerov4Addr
;
178 #if OTCARBONAPPLICATION
179 // IP_RCVDSTADDR is known to fail on OS X Carbon, so we'll just assume the packet was probably multicast
180 destaddr
.ip
.v4
= AllDNSLinkGroup_v4
.ip
.v4
;
183 if (recvdata
.opt
.len
)
188 err
= OTNextOption(recvdata
.opt
.buf
, recvdata
.opt
.len
, &c
);
189 if (err
|| !c
) break;
190 if (c
->level
== INET_IP
&& c
->name
== IP_RCVDSTADDR
&& c
->len
- kOTOptionHeaderSize
== sizeof(destaddr
.ip
.v4
))
191 mDNSPlatformMemCopy(&destaddr
.ip
.v4
, c
->value
, sizeof(destaddr
.ip
.v4
));
195 interface
= m
->HostInterfaces
->InterfaceID
;
197 if (flags
& T_MORE
) debugf("ERROR: OTRcvUData() buffer too small (T_MORE set)");
198 else if (recvdata
.addr
.len
< sizeof(InetAddress
)) debugf("ERROR: recvdata.addr.len (%d) too short", recvdata
.addr
.len
);
199 else mDNSCoreReceive(m
, &packet
, recvdata
.udata
.buf
+ recvdata
.udata
.len
, &senderaddr
, senderport
, &destaddr
, MulticastDNSPort
, interface
);
204 mDNSexport TCPSocket
*mDNSPlatformTCPSocket(mDNS
* const m
, TCPSocketFlags flags
, mDNSIPPort
* port
)
207 (void)flags
; // Unused
208 (void)port
; // Unused
212 mDNSexport TCPSocket
*mDNSPlatformTCPAccept(TCPSocketFlags flags
, int sd
)
214 (void)flags
; // Unused
219 mDNSexport
int mDNSPlatformTCPGetFD(TCPSocket
*sock
)
221 (void)sock
; // Unused
225 mDNSexport mStatus
mDNSPlatformTCPConnect(TCPSocket
*sock
, const mDNSAddr
* dst
, mDNSOpaque16 dstport
, mDNSInterfaceID InterfaceID
,
226 TCPConnectionCallback callback
, void * context
)
228 (void)sock
; // Unused
230 (void)dstport
; // Unused
231 (void)InterfaceID
; // Unused
232 (void)callback
; // Unused
233 (void)context
; // Unused
234 return(mStatus_UnsupportedErr
);
237 mDNSexport
void mDNSPlatformTCPCloseConnection(TCPSocket
*sd
)
242 mDNSexport
long mDNSPlatformReadTCP(TCPSocket
*sock
, void *buf
, unsigned long buflen
, mDNSBool
*closed
)
244 (void)sock
; // Unused
246 (void)buflen
; // Unused
247 (void)closed
; // Unused
251 mDNSexport
long mDNSPlatformWriteTCP(TCPSocket
*sock
, const char *msg
, unsigned long len
)
253 (void)sock
; // Unused
259 mDNSexport UDPSocket
*mDNSPlatformUDPSocket(mDNS
* const m
, mDNSIPPort port
)
262 (void)port
; // Unused
266 mDNSexport
void mDNSPlatformUDPClose(UDPSocket
*sock
)
268 (void)sock
; // Unused
271 mDNSlocal
void mDNSOptionManagement(mDNS
*const m
)
275 // Make sure the length in the TNetbuf agrees with the length in the TOptionHeader
276 m
->p
->optReq
.opt
.len
= m
->p
->optBlock
.h
.len
;
277 m
->p
->optReq
.opt
.maxlen
= m
->p
->optBlock
.h
.len
;
278 if (m
->p
->optReq
.opt
.maxlen
< 4)
279 m
->p
->optReq
.opt
.maxlen
= 4;
281 err
= OTOptionManagement(m
->p
->ep
, &m
->p
->optReq
, NULL
);
282 if (err
) LogMsg("OTOptionManagement failed %d", err
);
285 mDNSlocal
void mDNSinitComplete(mDNS
*const m
, mStatus result
)
287 m
->mDNSPlatformStatus
= result
;
288 mDNSCoreInitComplete(m
, mStatus_NoError
);
291 mDNSlocal
pascal void mDNSNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
293 mDNS
*const m
= (mDNS
*const)contextPtr
;
294 if (!m
) debugf("mDNSNotifier FATAL ERROR! No context");
300 InetInterfaceInfo interfaceinfo
;
301 if (result
) { LogMsg("T_OPENCOMPLETE failed %d", result
); mDNSinitComplete(m
, result
); return; }
302 //debugf("T_OPENCOMPLETE");
303 m
->p
->ep
= (EndpointRef
)cookie
;
304 //debugf("OTInetGetInterfaceInfo");
305 // (In future may want to loop over all interfaces instead of just using kDefaultInetInterface)
306 err
= OTInetGetInterfaceInfo(&interfaceinfo
, kDefaultInetInterface
);
307 if (err
) { LogMsg("OTInetGetInterfaceInfo failed %d", err
); mDNSinitComplete(m
, err
); return; }
309 // Make our basic standard host resource records (address, PTR, etc.)
310 m
->p
->interface
.InterfaceID
= (mDNSInterfaceID
)&m
->p
->interface
;
311 m
->p
->interface
.ip
.type
= mDNSAddrType_IPv4
;
312 m
->p
->interface
.ip
.ip
.v4
.NotAnInteger
= interfaceinfo
.fAddress
;
313 m
->p
->interface
.mask
.type
= mDNSAddrType_IPv4
;
314 m
->p
->interface
.mask
.ip
.v4
.NotAnInteger
= interfaceinfo
.fNetmask
;
315 m
->p
->interface
.ifname
[0] = 0;
316 m
->p
->interface
.Advertise
= m
->AdvertiseLocalAddresses
;
317 m
->p
->interface
.McastTxRx
= mDNStrue
;
320 case T_OPTMGMTCOMPLETE
:
322 // IP_RCVDSTADDR is known to fail on OS X Carbon, so we don't want to abort for that error
323 // (see comment above at the definition of kRcvDestAddrOption)
324 #if OTCARBONAPPLICATION
325 if (result
&& m
->p
->mOTstate
== mOT_RcvDestAddr
)
326 LogMsg("Carbon IP_RCVDSTADDR option failed %d; continuing anyway", result
);
329 if (result
) { LogMsg("T_OPTMGMTCOMPLETE/T_BINDCOMPLETE %d failed %d", m
->p
->mOTstate
, result
); mDNSinitComplete(m
, result
); return; }
330 //LogMsg("T_OPTMGMTCOMPLETE/T_BINDCOMPLETE %d", m->p->mOTstate);
331 switch (++m
->p
->mOTstate
)
333 case mOT_ReusePort
: m
->p
->optBlock
.b
= kReusePortOption
; mDNSOptionManagement(m
); break;
334 case mOT_RcvDestAddr
: m
->p
->optBlock
.i
= kRcvDestAddrOption
; mDNSOptionManagement(m
); break;
335 case mOT_SetUTTL
: m
->p
->optBlock
.i
= kSetUnicastTTLOption
; mDNSOptionManagement(m
); break;
336 case mOT_SetMTTL
: m
->p
->optBlock
.i
= kSetMulticastTTLOption
; mDNSOptionManagement(m
); break;
337 case mOT_LLScope
: m
->p
->optBlock
.m
= kAddLinkMulticastOption
; mDNSOptionManagement(m
); break;
338 // case mOT_AdminScope: m->p->optBlock.m = kAddAdminMulticastOption; mDNSOptionManagement(m); break;
339 case mOT_Bind
: OTBind(m
->p
->ep
, (TBind
*)&mDNSbindReq
, NULL
); break;
340 case mOT_Ready
: mDNSinitComplete(m
, mStatus_NoError
);
341 // Can't do mDNS_RegisterInterface until *after* mDNSinitComplete has set m->mDNSPlatformStatus to mStatus_NoError
342 mDNS_RegisterInterface(m
, &m
->p
->interface
, mDNSfalse
);
344 default: LogMsg("Unexpected m->p->mOTstate %d", m
->p
->mOTstate
-1);
350 while (readpacket(m
) == kOTNoError
) continue; // Read packets until we run out
353 case kOTProviderWillClose
: LogMsg("kOTProviderWillClose"); break;
354 case kOTProviderIsClosed
: // Machine is going to sleep, shutting down, or reconfiguring IP
355 LogMsg("kOTProviderIsClosed");
356 if (m
->p
->mOTstate
== mOT_Ready
)
358 m
->p
->mOTstate
= mOT_Closed
;
359 mDNS_DeregisterInterface(m
, &m
->p
->interface
, mDNSfalse
);
361 if (m
->p
->ep
) { OTCloseProvider(m
->p
->ep
); m
->p
->ep
= NULL
; }
362 break; // Do we need to do anything?
364 default: debugf("mDNSNotifier: Unexpected OTEventCode %X", code
);
369 #if MDNS_ONLYSYSTEMTASK
371 static Boolean ONLYSYSTEMTASKevent
;
372 static void *ONLYSYSTEMTASKcontextPtr
;
373 static OTEventCode ONLYSYSTEMTASKcode
;
374 static OTResult ONLYSYSTEMTASKresult
;
375 static void *ONLYSYSTEMTASKcookie
;
377 mDNSlocal
pascal void CallmDNSNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
379 ONLYSYSTEMTASKcontextPtr
= contextPtr
;
380 ONLYSYSTEMTASKcode
= code
;
381 ONLYSYSTEMTASKresult
= result
;
382 ONLYSYSTEMTASKcookie
= cookie
;
387 mDNSlocal
pascal void CallmDNSNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
389 mDNS
*const m
= (mDNS
*const)contextPtr
;
390 if (!m
) debugf("mDNSNotifier FATAL ERROR! No context");
391 if (m
->p
->nesting
) LogMsg("CallmDNSNotifier ERROR! OTEnterNotifier is supposed to suppress notifier callbacks");
392 mDNSNotifier(contextPtr
, code
, result
, cookie
);
397 static OTNotifyUPP CallmDNSNotifierUPP
;
399 mDNSlocal OSStatus
mDNSOpenEndpoint(const mDNS
*const m
)
402 // m->optReq is pre-set to point to the shared m->optBlock
403 // m->optBlock is filled in by each OTOptionManagement call
404 m
->p
->optReq
.opt
.maxlen
= sizeof(m
->p
->optBlock
);
405 m
->p
->optReq
.opt
.len
= sizeof(m
->p
->optBlock
);
406 m
->p
->optReq
.opt
.buf
= (UInt8
*)&m
->p
->optBlock
;
407 m
->p
->optReq
.flags
= T_NEGOTIATE
;
409 // Open an endpoint and start answering queries
410 //printf("Opening endpoint now...\n");
412 m
->p
->mOTstate
= mOT_Start
;
413 err
= OTAsyncOpenEndpoint(OTCreateConfiguration(kUDPName
), 0, NULL
, CallmDNSNotifierUPP
, (void*)m
);
414 if (err
) { LogMsg("ERROR: OTAsyncOpenEndpoint(UDP) failed with error <%d>", err
); return(err
); }
418 // Define these here because they're not in older versions of OpenTransport.h
421 xOTStackIsLoading
= 0x27000001, /* Sent before Open Transport attempts to load the TCP/IP protocol stack.*/
422 xOTStackWasLoaded
= 0x27000002, /* Sent after the TCP/IP stack has been successfully loaded.*/
423 xOTStackIsUnloading
= 0x27000003 /* Sent before Open Transport unloads the TCP/IP stack.*/
426 static mDNS
*ClientNotifierContext
;
428 mDNSlocal
pascal void ClientNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
430 mDNS
*const m
= ClientNotifierContext
;
432 #pragma unused(contextPtr) // Usually zero (except one in the 'xOTStackIsLoading' case)
433 #pragma unused(cookie) // Usually 'ipv4' (except for kOTPortNetworkChange)
434 #pragma unused(result) // Usually zero
438 case xOTStackIsLoading
: break;
439 case xOTStackWasLoaded
: if (m
->p
->mOTstate
== mOT_Closed
)
441 LogMsg("kOTStackWasLoaded: Re-opening endpoint");
443 LogMsg("kOTStackWasLoaded: ERROR: m->p->ep already set");
444 m
->mDNSPlatformStatus
= mStatus_Waiting
;
445 m
->p
->mOTstate
= mOT_Reset
;
446 #if !MDNS_ONLYSYSTEMTASK
451 LogMsg("kOTStackWasLoaded (no action)");
453 case xOTStackIsUnloading
: break;
454 case kOTPortNetworkChange
: break;
455 default: debugf("ClientNotifier unknown code %X, %X, %d", contextPtr
, code
, result
); break;
459 #if TARGET_API_MAC_CARBON
461 mDNSlocal
void GetUserSpecifiedComputerName(domainlabel
*const namelabel
)
463 CFStringRef cfs
= CSCopyMachineName();
464 CFStringGetPascalString(cfs
, namelabel
->c
, sizeof(*namelabel
), kCFStringEncodingUTF8
);
470 mDNSlocal OSStatus
ConvertStringHandleToUTF8(const StringHandle machineName
, UInt8
*const utf8
, ByteCount maxlen
)
473 TextEncoding utf8TextEncoding
, SystemTextEncoding
;
474 UnicodeMapping theMapping
;
475 TextToUnicodeInfo textToUnicodeInfo
;
476 ByteCount unicodelen
= 0;
478 if (maxlen
> 255) maxlen
= 255; // Can't put more than 255 in a Pascal String
480 utf8TextEncoding
= CreateTextEncoding(kTextEncodingUnicodeDefault
, kTextEncodingDefaultVariant
, kUnicodeUTF8Format
);
481 UpgradeScriptInfoToTextEncoding(smSystemScript
, kTextLanguageDontCare
, kTextRegionDontCare
, NULL
, &SystemTextEncoding
);
482 theMapping
.unicodeEncoding
= utf8TextEncoding
;
483 theMapping
.otherEncoding
= SystemTextEncoding
;
484 theMapping
.mappingVersion
= kUnicodeUseLatestMapping
;
485 status
= CreateTextToUnicodeInfo(&theMapping
, &textToUnicodeInfo
);
488 status
= ConvertFromPStringToUnicode(textToUnicodeInfo
, *machineName
, maxlen
, &unicodelen
, (UniCharArrayPtr
)&(utf8
[1]));
489 DisposeTextToUnicodeInfo(&textToUnicodeInfo
);
491 utf8
[0] = (UInt8
)unicodelen
;
495 mDNSlocal
void GetUserSpecifiedComputerName(domainlabel
*const namelabel
)
497 StringHandle machineName
= GetString(-16413); // Get machine name set in file sharing
500 char machineNameState
= HGetState((Handle
)machineName
);
501 HLock((Handle
)machineName
);
502 ConvertStringHandleToUTF8(machineName
, namelabel
->c
, MAX_DOMAIN_LABEL
);
503 HSetState((Handle
)machineName
, machineNameState
);
509 static pascal void mDNSTimerTask(void *arg
)
511 #if MDNS_ONLYSYSTEMTASK
513 ONLYSYSTEMTASKevent
= true;
515 mDNS
*const m
= (mDNS
*const)arg
;
516 if (!m
->p
->ep
) LogMsg("mDNSTimerTask NO endpoint");
517 if (m
->mDNS_busy
) LogMsg("mDNS_busy");
518 if (m
->p
->nesting
) LogMsg("mDNSTimerTask ERROR! OTEnterNotifier is supposed to suppress timer callbacks too");
520 // If our timer fires at a time when we have no endpoint, ignore it --
521 // once we reopen our endpoint and get our T_BINDCOMPLETE message we'll call
522 // mDNS_RegisterInterface(), which does a lock/unlock, which retriggers the timer.
523 // Likewise, if m->mDNS_busy or m->p->nesting, we'll catch this on the unlock
524 if (m
->p
->ep
&& m
->mDNS_busy
== 0 && m
->p
->nesting
== 0) mDNS_Execute(m
);
529 long sleep
, wake
, mode
;
532 mDNSexport mStatus
mDNSPlatformInit(mDNS
*const m
)
534 OSStatus err
= InitOpenTransport();
536 ClientNotifierContext
= m
;
537 // Note: OTRegisterAsClient returns kOTNotSupportedErr when running as Carbon code on OS X
538 // -- but that's okay, we don't need a ClientNotifier when running as Carbon code on OS X
539 OTRegisterAsClient(NULL
, NewOTNotifyUPP(ClientNotifier
));
541 m
->p
->OTTimerTask
= OTCreateTimerTask(NewOTProcessUPP(mDNSTimerTask
), m
);
545 sleep
= TickCount() + 600;
546 wake
= TickCount() + 1200;
550 // Set up the nice label
551 m
->nicelabel
.c
[0] = 0;
552 GetUserSpecifiedComputerName(&m
->nicelabel
);
553 // m->nicelabel = *(domainlabel*)"\pStu"; // For conflict testing
554 if (m
->nicelabel
.c
[0] == 0) MakeDomainLabelFromLiteralString(&m
->nicelabel
, "Macintosh");
556 // Set up the RFC 1034-compliant label
557 m
->hostlabel
.c
[0] = 0;
558 ConvertUTF8PstringToRFC1034HostLabel(m
->nicelabel
.c
, &m
->hostlabel
);
559 if (m
->hostlabel
.c
[0] == 0) MakeDomainLabelFromLiteralString(&m
->hostlabel
, "Macintosh");
563 // When it's finished mDNSOpenEndpoint asynchronously calls mDNSinitComplete() and then mDNS_RegisterInterface()
564 CallmDNSNotifierUPP
= NewOTNotifyUPP(CallmDNSNotifier
);
565 err
= mDNSOpenEndpoint(m
);
568 LogMsg("mDNSOpenEndpoint failed %d", err
);
569 if (m
->p
->OTTimerTask
) OTDestroyTimerTask(m
->p
->OTTimerTask
);
570 OTUnregisterAsClient();
571 CloseOpenTransport();
576 extern void mDNSPlatformClose (mDNS
*const m
)
578 if (m
->p
->mOTstate
== mOT_Ready
)
580 m
->p
->mOTstate
= mOT_Closed
;
581 mDNS_DeregisterInterface(m
, &m
->p
->interface
, mDNSfalse
);
583 if (m
->p
->ep
) { OTCloseProvider (m
->p
->ep
); m
->p
->ep
= NULL
; }
584 if (m
->p
->OTTimerTask
) { OTDestroyTimerTask(m
->p
->OTTimerTask
); m
->p
->OTTimerTask
= 0; }
586 OTUnregisterAsClient();
587 CloseOpenTransport();
590 #if MDNS_ONLYSYSTEMTASK
591 extern void mDNSPlatformIdle(mDNS
*const m
);
592 mDNSexport
void mDNSPlatformIdle(mDNS
*const m
)
594 while (ONLYSYSTEMTASKcontextPtr
)
596 void *contextPtr
= ONLYSYSTEMTASKcontextPtr
;
597 ONLYSYSTEMTASKcontextPtr
= NULL
;
598 mDNSNotifier(contextPtr
, ONLYSYSTEMTASKcode
, ONLYSYSTEMTASKresult
, ONLYSYSTEMTASKcookie
);
600 if (ONLYSYSTEMTASKevent
)
602 ONLYSYSTEMTASKevent
= false;
606 if (m
->p
->mOTstate
== mOT_Reset
)
609 printf("******************************************************************************\n");
611 printf("Reopening endpoint\n");
613 m
->ResourceRecords
= NULL
;
619 case 0: if ((long)TickCount() - sleep
>= 0) { mDNSCoreMachineSleep(m
, 1); mode
++; }
621 case 1: if ((long)TickCount() - wake
>= 0) { mDNSCoreMachineSleep(m
, 0); mode
++; }
628 mDNSexport
void mDNSPlatformLock(const mDNS
*const m
)
630 if (!m
) { DebugStr("\pmDNSPlatformLock m NULL!"); return; }
631 if (!m
->p
) { DebugStr("\pmDNSPlatformLock m->p NULL!"); return; }
633 // If we try to call OTEnterNotifier and fail because we're already running at
634 // Notifier context, then make sure we don't do the matching OTLeaveNotifier() on exit.
635 // If we haven't even opened our endpoint yet, then just increment m->p->nesting for the same reason
636 if (m
->p
->mOTstate
== mOT_Ready
&& !m
->p
->ep
) DebugStr("\pmDNSPlatformLock: m->p->mOTstate == mOT_Ready && !m->p->ep");
637 if (!m
->p
->ep
|| m
->p
->nesting
|| OTEnterNotifier(m
->p
->ep
) == false) m
->p
->nesting
++;
640 mDNSlocal
void ScheduleNextTimerCallback(const mDNS
*const m
)
642 if (m
->mDNSPlatformStatus
== mStatus_NoError
)
644 SInt32 interval
= m
->NextScheduledEvent
- mDNS_TimeNow_NoLock(m
);
645 if (interval
< 1) interval
= 1;
646 else if (interval
> 0x70000000 / 1000) interval
= 0x70000000 / mDNSPlatformOneSecond
;
647 else interval
= (interval
* 1000 + mDNSPlatformOneSecond
-1)/ mDNSPlatformOneSecond
;
648 OTScheduleTimerTask(m
->p
->OTTimerTask
, (OTTimeout
)interval
);
652 mDNSexport
void mDNSPlatformUnlock(const mDNS
*const m
)
654 if (!m
) { DebugStr("\pmDNSPlatformUnlock m NULL!"); return; }
655 if (!m
->p
) { DebugStr("\pmDNSPlatformUnlock m->p NULL!"); return; }
657 if (m
->p
->ep
&& m
->mDNS_busy
== 0) ScheduleNextTimerCallback(m
);
659 if (m
->p
->nesting
) m
->p
->nesting
--;
660 else OTLeaveNotifier(m
->p
->ep
);
663 mDNSexport
void mDNSPlatformStrCopy( void *dst
, const void *src
) { OTStrCopy((char*)dst
, (char*)src
); }
664 mDNSexport UInt32
mDNSPlatformStrLen ( const void *src
) { return(OTStrLength((char*)src
)); }
665 mDNSexport
void mDNSPlatformMemCopy( void *dst
, const void *src
, UInt32 len
) { OTMemcpy(dst
, src
, len
); }
666 mDNSexport mDNSBool
mDNSPlatformMemSame(const void *dst
, const void *src
, UInt32 len
) { return(OTMemcmp(dst
, src
, len
)); }
667 mDNSexport
void mDNSPlatformMemZero( void *dst
, UInt32 len
) { OTMemzero(dst
, len
); }
668 mDNSexport
void * mDNSPlatformMemAllocate(mDNSu32 len
) { return(OTAllocMem(len
)); }
669 mDNSexport
void mDNSPlatformMemFree(void *mem
) { OTFreeMem(mem
); }
670 mDNSexport mDNSu32
mDNSPlatformRandomSeed(void) { return(TickCount()); }
671 mDNSexport mStatus
mDNSPlatformTimeInit(void) { return(mStatus_NoError
); }
672 mDNSexport SInt32
mDNSPlatformRawTime() { return((SInt32
)TickCount()); }
673 mDNSexport SInt32 mDNSPlatformOneSecond
= 60;
675 mDNSexport mDNSs32
mDNSPlatformUTC(void)
677 // Classic Mac OS since Midnight, 1st Jan 1904
678 // Standard Unix counts from 1970
679 // This value adjusts for the 66 years and 17 leap-days difference
680 mDNSu32 SecsSince1904
;
681 MachineLocation ThisLocation
;
682 #define TIME_ADJUST (((1970 - 1904) * 365 + 17) * 24 * 60 * 60)
683 #define ThisLocationGMTdelta ((ThisLocation.u.gmtDelta << 8) >> 8)
684 GetDateTime(&SecsSince1904
);
685 ReadLocation(&ThisLocation
);
686 return((mDNSs32
)(SecsSince1904
- ThisLocationGMTdelta
- TIME_ADJUST
));