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