]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOS9/mDNSMacOS9.c
mDNSResponder-58.1.tar.gz
[apple/mdnsresponder.git] / mDNSMacOS9 / mDNSMacOS9.c
1 /*
2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24
25 Change History (most recent first):
26
27 $Log: mDNSMacOS9.c,v $
28 Revision 1.19 2003/08/18 23:09:20 cheshire
29 <rdar://problem/3382647> mDNSResponder divide by zero in mDNSPlatformTimeNow()
30
31 Revision 1.18 2003/08/12 19:56:24 cheshire
32 Update to APSL 2.0
33
34 */
35
36 #include <LowMem.h> // For LMGetCurApName()
37 #include <TextUtils.h> // For smSystemScript
38 #include <UnicodeConverter.h> // For ConvertFromPStringToUnicode()
39
40 #include <stdio.h>
41 #include <stdarg.h> // For va_list support
42
43 #include "mDNSClientAPI.h" // Defines the interface provided to the client layer above
44 #include "mDNSPlatformFunctions.h" // Defines the interface to the supporting layer below
45
46 #include "mDNSMacOS9.h" // Defines the specific types needed to run mDNS on this platform
47
48 // ***************************************************************************
49 // Constants
50
51 static const TSetBooleanOption kReusePortOption =
52 { sizeof(TSetBooleanOption), INET_IP, IP_REUSEPORT, 0, true };
53
54 // IP_RCVDSTADDR gives error #-3151 (kOTBadOptionErr)
55 static const TSetBooleanOption kRcvDestAddrOption =
56 { sizeof(TSetBooleanOption), INET_IP, IP_REUSEPORT, 0, true };
57
58 static const TIPAddMulticastOption kAddLinkMulticastOption =
59 { sizeof(TIPAddMulticastOption), INET_IP, IP_ADD_MEMBERSHIP, 0, { 224, 0, 0,251 }, { 0,0,0,0 } };
60
61 static const TIPAddMulticastOption kAddAdminMulticastOption =
62 { sizeof(TIPAddMulticastOption), INET_IP, IP_ADD_MEMBERSHIP, 0, { 239,255,255,251 }, { 0,0,0,0 } };
63
64 // Bind endpoint to port number. Don't specify any specific IP address --
65 // we want to receive unicasts on all interfaces, as well as multicasts.
66 typedef struct { OTAddressType fAddressType; mDNSIPPort fPort; mDNSv4Addr fHost; UInt8 fUnused[8]; } mDNSInetAddress;
67 //static const mDNSInetAddress mDNSPortInetAddress = { AF_INET, { 0,0 }, { 0,0,0,0 } }; // For testing legacy client support
68 #define MulticastDNSPortAsNumber 5353
69 static const mDNSInetAddress mDNSPortInetAddress = { AF_INET, { MulticastDNSPortAsNumber >> 8, MulticastDNSPortAsNumber & 0xFF }, { 0,0,0,0 } };
70 static const TBind mDNSbindReq = { sizeof(mDNSPortInetAddress), sizeof(mDNSPortInetAddress), (UInt8*)&mDNSPortInetAddress, 0 };
71
72 static const TNetbuf zeroTNetbuf = { 0 };
73
74 // ***************************************************************************
75 // Functions
76
77 #if MDNS_DEBUGMSGS
78 mDNSexport void debugf_(const char *format, ...)
79 {
80 unsigned char buffer[256];
81 va_list ptr;
82 va_start(ptr,format);
83 buffer[0] = (unsigned char)mDNS_vsnprintf((char*)buffer+1, 255, format, ptr);
84 va_end(ptr);
85 #if __ONLYSYSTEMTASK__
86 buffer[1+buffer[0]] = 0;
87 fprintf(stderr, "%s\n", buffer+1);
88 fflush(stderr);
89 #else
90 DebugStr(buffer);
91 #endif
92 }
93 #endif
94
95 mDNSexport void LogMsg(const char *format, ...)
96 {
97 unsigned char buffer[256];
98 va_list ptr;
99 va_start(ptr,format);
100 buffer[0] = (unsigned char)mDNS_vsnprintf((char*)buffer+1, 255, format, ptr);
101 va_end(ptr);
102 #if __ONLYSYSTEMTASK__
103 buffer[1+buffer[0]] = 0;
104 fprintf(stderr, "%s\n", buffer+1);
105 fflush(stderr);
106 #else
107 DebugStr(buffer);
108 #endif
109 }
110
111 mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
112 mDNSInterfaceID InterfaceID, mDNSIPPort srcPort, const mDNSAddr *dst, mDNSIPPort dstPort)
113 {
114 // Note: If we did multi-homing, we'd have to use the InterfaceID parameter to specify from which interface to send this response
115 #pragma unused(InterfaceID, srcPort)
116
117 InetAddress InetDest;
118 TUnitData senddata;
119
120 InetDest.fAddressType = AF_INET;
121 InetDest.fPort = dstPort.NotAnInteger;
122 InetDest.fHost = dst->ip.v4.NotAnInteger;
123
124 senddata.addr .maxlen = sizeof(InetDest);
125 senddata.addr .len = sizeof(InetDest);
126 senddata.addr .buf = (UInt8*)&InetDest;
127 senddata.opt = zeroTNetbuf;
128 senddata.udata.maxlen = (UInt32)((UInt8*)end - (UInt8*)msg);
129 senddata.udata.len = (UInt32)((UInt8*)end - (UInt8*)msg);
130 senddata.udata.buf = (UInt8*)msg;
131
132 return(OTSndUData(m->p->ep, &senddata));
133 }
134
135 mDNSlocal OSStatus readpacket(mDNS *m)
136 {
137 mDNSAddr senderaddr, destaddr;
138 mDNSInterfaceID interface;
139 mDNSIPPort senderport;
140 InetAddress sender;
141 char options[512];
142 DNSMessage packet;
143 TUnitData recvdata;
144 OTFlags flags = 0;
145 OSStatus err;
146
147 recvdata.addr .maxlen = sizeof(sender);
148 recvdata.addr .len = 0;
149 recvdata.addr .buf = (UInt8*)&sender;
150 recvdata.opt .maxlen = sizeof(options);
151 recvdata.opt .len = 0;
152 recvdata.opt .buf = (UInt8*)&options;
153 recvdata.udata.maxlen = sizeof(packet);
154 recvdata.udata.len = 0;
155 recvdata.udata.buf = (UInt8*)&packet;
156
157 err = OTRcvUData(m->p->ep, &recvdata, &flags);
158 if (err && err != kOTNoDataErr) debugf("OTRcvUData error %d", err);
159
160 if (err) return(err);
161
162 senderaddr.type = mDNSAddrType_IPv4;
163 senderaddr.ip.v4.NotAnInteger = sender.fHost;
164 senderport.NotAnInteger = sender.fPort;
165 destaddr.type = mDNSAddrType_IPv4;
166 destaddr.ip.v4 = AllDNSLinkGroup; // For now, until I work out how to get the dest address, assume it was sent to AllDNSLinkGroup
167 interface = m->HostInterfaces->InterfaceID;
168
169 if (recvdata.opt.len) debugf("readpacket: got some option data at %X, len %d", options, recvdata.opt.len);
170
171 if (flags & T_MORE) debugf("ERROR: OTRcvUData() buffer too small (T_MORE set)");
172 else if (recvdata.addr.len < sizeof(InetAddress)) debugf("ERROR: recvdata.addr.len (%d) too short", recvdata.addr.len);
173 else if (recvdata.udata.len < sizeof(DNSMessageHeader)) debugf("ERROR: recvdata.udata.len (%d) too short", recvdata.udata.len);
174 else mDNSCoreReceive(m, &packet, recvdata.udata.buf + recvdata.udata.len, &senderaddr, senderport, &destaddr, MulticastDNSPort, interface, 255);
175
176 return(err);
177 }
178
179
180 mDNSlocal void mDNSOptionManagement(mDNS *const m)
181 {
182 OSStatus err;
183
184 // Make sure the length in the TNetbuf agrees with the length in the TOptionHeader
185 m->p->optReq.opt.len = m->p->optBlock.h.len;
186 err = OTOptionManagement(m->p->ep, &m->p->optReq, NULL);
187 if (err) debugf("OTOptionManagement failed %d", err);
188 }
189
190 mDNSlocal void mDNSinitComplete(mDNS *const m, mStatus result)
191 {
192 m->mDNSPlatformStatus = result;
193 mDNSCoreInitComplete(m, mStatus_NoError);
194 }
195
196 mDNSlocal pascal void mDNSNotifier(void *contextPtr, OTEventCode code, OTResult result, void *cookie)
197 {
198 mDNS *const m = (mDNS *const)contextPtr;
199 if (!m) debugf("mDNSNotifier FATAL ERROR! No context");
200 switch (code)
201 {
202 case T_OPENCOMPLETE:
203 {
204 OSStatus err;
205 InetInterfaceInfo interfaceinfo;
206 if (result) { debugf("T_OPENCOMPLETE failed %d", result); mDNSinitComplete(m, result); return; }
207 //debugf("T_OPENCOMPLETE");
208 m->p->ep = (EndpointRef)cookie;
209 //debugf("OTInetGetInterfaceInfo");
210 // (In future may want to loop over all interfaces instead of just using kDefaultInetInterface)
211 err = OTInetGetInterfaceInfo(&interfaceinfo, kDefaultInetInterface);
212 if (err) { debugf("OTInetGetInterfaceInfo failed %d", err); mDNSinitComplete(m, err); return; }
213
214 // Make our basic standard host resource records (address, PTR, etc.)
215 m->p->interface.ip.type = mDNSAddrType_IPv4;
216 m->p->interface.ip.ip.v4.NotAnInteger = interfaceinfo.fAddress;
217 m->p->interface.Advertise = m->AdvertiseLocalAddresses;
218 m->p->interface.InterfaceID = (mDNSInterfaceID)&m->p->interface;
219 mDNS_RegisterInterface(m, &m->p->interface);
220 }
221
222 case T_OPTMGMTCOMPLETE:
223 if (result) { debugf("T_OPTMGMTCOMPLETE failed %d", result); mDNSinitComplete(m, result); return; }
224 //debugf("T_OPTMGMTCOMPLETE");
225 switch (++m->p->mOTstate)
226 {
227 case mOT_ReusePort: m->p->optBlock.b = kReusePortOption; mDNSOptionManagement(m); break;
228 case mOT_RcvDestAddr: m->p->optBlock.b = kRcvDestAddrOption; mDNSOptionManagement(m); break;
229 case mOT_LLScope: m->p->optBlock.m = kAddLinkMulticastOption; mDNSOptionManagement(m); break;
230 case mOT_AdminScope: m->p->optBlock.m = kAddAdminMulticastOption; mDNSOptionManagement(m); break;
231 case mOT_Bind: OTBind(m->p->ep, (TBind*)&mDNSbindReq, NULL); break;
232 }
233 break;
234
235 case T_BINDCOMPLETE:
236 if (result) { debugf("T_BINDCOMPLETE failed %d", result); return; }
237 if (m->p->mOTstate != mOT_Bind) { debugf("T_BINDCOMPLETE in wrong mDNS state %d", m->p->mOTstate); return; }
238 m->p->mOTstate++;
239 //debugf("T_BINDCOMPLETE");
240 mDNSinitComplete(m, mStatus_NoError);
241 break;
242
243 case T_DATA:
244 //debugf("T_DATA");
245 while (readpacket(m) == kOTNoError) continue; // Read packets until we run out
246 break;
247
248 case kOTProviderWillClose:
249 case kOTProviderIsClosed: // Machine is going to sleep, shutting down, or reconfiguring IP
250 if (m->p->ep) { OTCloseProvider(m->p->ep); m->p->ep = NULL; }
251 break; // Do we need to do anything?
252
253 default: debugf("mDNSNotifier: Unexpected OTEventCode %X", code);
254 break;
255 }
256 }
257
258 #if __ONLYSYSTEMTASK__
259
260 static Boolean ONLYSYSTEMTASKevent;
261 static void *ONLYSYSTEMTASKcontextPtr;
262 static OTEventCode ONLYSYSTEMTASKcode;
263 static OTResult ONLYSYSTEMTASKresult;
264 static void *ONLYSYSTEMTASKcookie;
265
266 mDNSlocal pascal void CallmDNSNotifier(void *contextPtr, OTEventCode code, OTResult result, void *cookie)
267 {
268 ONLYSYSTEMTASKcontextPtr = contextPtr;
269 ONLYSYSTEMTASKcode = code;
270 ONLYSYSTEMTASKresult = result;
271 ONLYSYSTEMTASKcookie = cookie;
272 }
273
274 #else
275
276 mDNSlocal pascal void CallmDNSNotifier(void *contextPtr, OTEventCode code, OTResult result, void *cookie)
277 {
278 mDNS *const m = (mDNS *const)contextPtr;
279 if (!m) debugf("mDNSNotifier FATAL ERROR! No context");
280
281 // Increment m->p->nesting to indicate to mDNSPlatformLock that there's no need
282 // to call OTEnterNotifier() (because we're already in OTNotifier context)
283 if (m->p->nesting) DebugStr("\pCallmDNSNotifier ERROR! OTEnterNotifier is supposed to suppress notifier callbacks");
284 m->p->nesting++;
285 mDNSNotifier(contextPtr, code, result, cookie);
286 m->p->nesting--;
287 ScheduleNextTimerCallback(m);
288 }
289
290 #endif
291
292 mDNSlocal OSStatus mDNSOpenEndpoint(const mDNS *const m)
293 {
294 OSStatus err;
295 TEndpointInfo endpointinfo;
296 // m->optReq is pre-set to point to the shared m->optBlock
297 // m->optBlock is filled in by each OTOptionManagement call
298 m->p->optReq.opt.maxlen = sizeof(m->p->optBlock);
299 m->p->optReq.opt.len = sizeof(m->p->optBlock);
300 m->p->optReq.opt.buf = (UInt8*)&m->p->optBlock;
301 m->p->optReq.flags = T_NEGOTIATE;
302
303 // Open an endpoint and start answering queries
304 //printf("Opening endpoint now...\n");
305 m->p->ep = NULL;
306 m->p->mOTstate = mOT_Start;
307 // err = OTAsyncOpenEndpoint(OTCreateConfiguration("udp(RxICMP=1)"), 0, &endpointinfo, CallmDNSNotifier, (void*)m); // works
308 // err = OTAsyncOpenEndpoint(OTCreateConfiguration("udp(RxICMP)"), 0, &endpointinfo, CallmDNSNotifier, (void*)m); // -3151 bad option
309 // err = OTAsyncOpenEndpoint(OTCreateConfiguration("udp,ip(RxICMP=1)"), 0, &endpointinfo, CallmDNSNotifier, (void*)m); // -3151
310 // err = OTAsyncOpenEndpoint(OTCreateConfiguration("udp,ip"), 0, &endpointinfo, CallmDNSNotifier, (void*)m); // works
311 // err = OTAsyncOpenEndpoint(OTCreateConfiguration("udp,rawip"), 0, &endpointinfo, CallmDNSNotifier, (void*)m); // -3221 invalid arg
312 err = OTAsyncOpenEndpoint(OTCreateConfiguration(kUDPName), 0, &endpointinfo, NewOTNotifyUPP(CallmDNSNotifier), (void*)m);
313 if (err) { debugf("ERROR: OTAsyncOpenEndpoint(UDP) failed with error <%d>", err); return(err); }
314
315 return(kOTNoError);
316 }
317
318 // Define these here because they're not in older versions of OpenTransport.h
319 enum
320 {
321 xOTStackIsLoading = 0x27000001, /* Sent before Open Transport attempts to load the TCP/IP protocol stack.*/
322 xOTStackWasLoaded = 0x27000002, /* Sent after the TCP/IP stack has been successfully loaded.*/
323 xOTStackIsUnloading = 0x27000003 /* Sent before Open Transport unloads the TCP/IP stack.*/
324 };
325
326 static mDNS *ClientNotifierContext;
327
328 mDNSlocal pascal void ClientNotifier(void *contextPtr, OTEventCode code, OTResult result, void *cookie)
329 {
330 mDNS *const m = ClientNotifierContext;
331
332 #pragma unused(contextPtr) // Usually zero (except one in the 'xOTStackIsLoading' case)
333 #pragma unused(cookie) // Usually 'ipv4' (except for kOTPortNetworkChange)
334 #pragma unused(result) // Usually zero
335
336 switch (code)
337 {
338 case xOTStackIsLoading: break;
339 case xOTStackWasLoaded: m->mDNSPlatformStatus = mStatus_Waiting; m->p->mOTstate = mOT_Reset; break;
340 case xOTStackIsUnloading: break;
341 case kOTPortNetworkChange: break;
342 default: debugf("ClientNotifier unknown code %X, %X, %d", contextPtr, code, result); break;
343 }
344 }
345
346 #if TARGET_API_MAC_CARBON
347
348 mDNSlocal void GetUserSpecifiedComputerName(domainlabel *const namelabel)
349 {
350 CFStringRef cfs = CSCopyMachineName();
351 CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
352 CFRelease(cfs);
353 }
354
355 #else
356
357 mDNSlocal OSStatus ConvertStringHandleToUTF8(const StringHandle machineName, UInt8 *const utf8, ByteCount maxlen)
358 {
359 OSStatus status;
360 TextEncoding utf8TextEncoding, SystemTextEncoding;
361 UnicodeMapping theMapping;
362 TextToUnicodeInfo textToUnicodeInfo;
363 ByteCount unicodelen = 0;
364
365 if (maxlen > 255) maxlen = 255; // Can't put more than 255 in a Pascal String
366
367 utf8TextEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault, kTextEncodingDefaultVariant, kUnicodeUTF8Format);
368 UpgradeScriptInfoToTextEncoding(smSystemScript, kTextLanguageDontCare, kTextRegionDontCare, NULL, &SystemTextEncoding);
369 theMapping.unicodeEncoding = utf8TextEncoding;
370 theMapping.otherEncoding = SystemTextEncoding;
371 theMapping.mappingVersion = kUnicodeUseLatestMapping;
372 status = CreateTextToUnicodeInfo(&theMapping, &textToUnicodeInfo);
373 if (status == noErr)
374 {
375 status = ConvertFromPStringToUnicode(textToUnicodeInfo, *machineName, maxlen, &unicodelen, (UniCharArrayPtr)&(utf8[1]));
376 DisposeTextToUnicodeInfo(&textToUnicodeInfo);
377 }
378 utf8[0] = (UInt8)unicodelen;
379 return(status);
380 }
381
382 mDNSlocal void GetUserSpecifiedComputerName(domainlabel *const namelabel)
383 {
384 StringHandle machineName = GetString(-16413); // Get machine name set in file sharing
385 if (machineName)
386 {
387 char machineNameState = HGetState((Handle)machineName);
388 HLock((Handle)machineName);
389 ConvertStringHandleToUTF8(machineName, namelabel->c, MAX_DOMAIN_LABEL);
390 HSetState((Handle)machineName, machineNameState);
391 }
392 }
393
394 #endif
395
396 static pascal void mDNSTimerTask(void *arg)
397 {
398 #if __ONLYSYSTEMTASK__
399 #pragma unused(arg)
400 ONLYSYSTEMTASKevent = true;
401 #else
402 mDNS *const m = (mDNS *const)arg;
403 // Increment m->p->nesting to indicate to mDNSPlatformLock that there's no need
404 // to call OTEnterNotifier() (because we're already in OTNotifier context)
405 if (m->p->nesting) DebugStr("\pmDNSTimerTask ERROR! OTEnterNotifier is supposed to suppress timer callbacks too");
406 m->p->nesting++;
407 mDNS_Execute(m);
408 m->p->nesting--;
409 ScheduleNextTimerCallback(m);
410 #endif
411 }
412
413 #if TEST_SLEEP
414 long sleep, wake, mode;
415 #endif
416
417 mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
418 {
419 OSStatus err;
420
421 // Set up the nice label
422 m->nicelabel.c[0] = 0;
423 GetUserSpecifiedComputerName(&m->nicelabel);
424 // m->nicelabel = *(domainlabel*)"\pStu"; // For conflict testing
425 if (m->nicelabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->nicelabel, "Macintosh");
426
427 // Set up the RFC 1034-compliant label
428 m->hostlabel.c[0] = 0;
429 ConvertUTF8PstringToRFC1034HostLabel(m->nicelabel.c, &m->hostlabel);
430 if (m->hostlabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->hostlabel, "Macintosh");
431
432 mDNS_GenerateFQDN(m);
433
434 ClientNotifierContext = m;
435
436 #if !TARGET_API_MAC_CARBON
437 err = OTRegisterAsClient(LMGetCurApName(), NewOTNotifyUPP(ClientNotifier));
438 if (err) debugf("OTRegisterAsClient failed %d", err);
439 #endif
440
441 err = mDNSOpenEndpoint(m);
442 if (err) { debugf("mDNSOpenEndpoint failed %d", err); return(err); }
443
444 m->p->OTTimerTask = OTCreateTimerTask(NewOTProcessUPP(mDNSTimerTask), m);
445 m->p->nesting = 0;
446
447 #if TEST_SLEEP
448 sleep = TickCount() + 600;
449 wake = TickCount() + 1200;
450 mode = 0;
451 #endif
452
453 return(err);
454 }
455
456 extern void mDNSPlatformClose (mDNS *const m)
457 {
458 if (m->p->OTTimerTask) { OTDestroyTimerTask(m->p->OTTimerTask); m->p->OTTimerTask = 0; }
459 if (m->p->ep) { OTCloseProvider (m->p->ep); m->p->ep = NULL; }
460 CloseOpenTransport();
461 }
462
463 extern void mDNSPlatformIdle(mDNS *const m);
464 mDNSexport void mDNSPlatformIdle(mDNS *const m)
465 {
466 #if __ONLYSYSTEMTASK__
467 while (ONLYSYSTEMTASKcontextPtr)
468 {
469 void *contextPtr = ONLYSYSTEMTASKcontextPtr;
470 ONLYSYSTEMTASKcontextPtr = NULL;
471 mDNSNotifier(contextPtr, ONLYSYSTEMTASKcode, ONLYSYSTEMTASKresult, ONLYSYSTEMTASKcookie);
472 }
473 if (ONLYSYSTEMTASKevent)
474 {
475 ONLYSYSTEMTASKevent = false;
476 mDNS_Execute(m);
477 }
478 #endif
479
480 if (m->p->mOTstate == mOT_Reset)
481 {
482 printf("\n");
483 printf("******************************************************************************\n");
484 printf("\n");
485 printf("Reopening endpoint\n");
486 mDNSOpenEndpoint(m);
487 m->ResourceRecords = NULL;
488 }
489
490 #if TEST_SLEEP
491 switch (mode)
492 {
493 case 0: if ((long)TickCount() - sleep >= 0) { mDNSCoreMachineSleep(m, 1); mode++; }
494 break;
495 case 1: if ((long)TickCount() - wake >= 0) { mDNSCoreMachineSleep(m, 0); mode++; }
496 break;
497 }
498 #endif
499
500 }
501
502 mDNSexport void mDNSPlatformLock(const mDNS *const m)
503 {
504 if (!m) { DebugStr("\pmDNSPlatformLock m NULL!"); return; }
505 if (!m->p) { DebugStr("\pmDNSPlatformLock m->p NULL!"); return; }
506 if (!m->p->ep) { DebugStr("\pmDNSPlatformLock m->p->ep NULL!"); return; }
507
508 // If we try to call OTEnterNotifier and fail because we're already running at
509 // Notifier context, then make sure we don't do the matching OTLeaveNotifier() on exit.
510 if (m->p->nesting || OTEnterNotifier(m->p->ep) == false) m->p->nesting++;
511 }
512
513 mDNSlocal void ScheduleNextTimerCallback(const mDNS *const m)
514 {
515 SInt32 interval;
516 interval = m->NextScheduledEvent - mDNSPlatformTimeNow();
517 if (interval < 0) interval = 0;
518 else if (interval > 0x7FFFFFFF / 1000) interval = 0x7FFFFFFF / mDNSPlatformOneSecond;
519 else interval = interval * 1000 / mDNSPlatformOneSecond;
520 //debugf("mDNSPlatformScheduleTask Interval %d", interval);
521 OTScheduleTimerTask(m->p->OTTimerTask, (OTTimeout)interval);
522 }
523
524 mDNSexport void mDNSPlatformUnlock(const mDNS *const m)
525 {
526 if (!m) { DebugStr("\pmDNSPlatformUnlock m NULL!"); return; }
527 if (!m->p) { DebugStr("\pmDNSPlatformUnlock m->p NULL!"); return; }
528 if (!m->p->ep) { DebugStr("\pmDNSPlatformUnlock m->p->ep NULL!"); return; }
529 if (m->p->nesting) m->p->nesting--;
530 else
531 {
532 ScheduleNextTimerCallback(m);
533 OTLeaveNotifier(m->p->ep);
534 }
535 }
536
537 mDNSexport void mDNSPlatformStrCopy(const void *src, void *dst) { OTStrCopy((char*)dst, (char*)src); }
538 mDNSexport UInt32 mDNSPlatformStrLen (const void *src) { return(OTStrLength((char*)src)); }
539 mDNSexport void mDNSPlatformMemCopy(const void *src, void *dst, UInt32 len) { OTMemcpy(dst, src, len); }
540 mDNSexport mDNSBool mDNSPlatformMemSame(const void *src, const void *dst, UInt32 len) { return(OTMemcmp(dst, src, len)); }
541 mDNSexport void mDNSPlatformMemZero( void *dst, UInt32 len) { OTMemzero(dst, len); }
542 mDNSexport void * mDNSPlatformMemAllocate(mDNSu32 len) { return(OTAllocMem(len)); }
543 mDNSexport void mDNSPlatformMemFree (void *mem) { OTFreeMem(mem); }
544 mDNSexport mStatus mDNSPlatformTimeInit(mDNSs32 *timenow) { *timenow = mDNSPlatformTimeNow(); return(mStatus_NoError); }
545 mDNSexport SInt32 mDNSPlatformTimeNow() { return((SInt32)TickCount()); }
546 mDNSexport SInt32 mDNSPlatformOneSecond = 60;