2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
25 Change History (most recent first):
28 Revision 1.2 2004/05/20 18:38:31 cheshire
29 Fix build broken by removal of 'kDNSServiceFlagsAutoRename' from dns_sd.h
31 Revision 1.1 2004/03/12 21:30:25 cheshire
32 Build a System-Context Shared Library from mDNSCore, for the benefit of developers
33 like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
37 #include <stdio.h> // For printf()
38 #include <string.h> // For strcpy()
40 #include <Events.h> // For WaitNextEvent()
42 #include <OpenTransport.h>
43 #include <OpenTptInternet.h>
45 #include <SIOUX.h> // For SIOUXHandleOneEvent()
49 typedef union { UInt8 b
[2]; UInt16 NotAnInteger
; } mDNSOpaque16
;
50 static UInt16
mDNSVal16(mDNSOpaque16 x
) { return((UInt16
)(x
.b
[0]<<8 | x
.b
[1])); }
51 static mDNSOpaque16
mDNSOpaque16fromIntVal(UInt16 v
)
52 { mDNSOpaque16 x
; x
.b
[0] = (UInt8
)(v
>> 8); x
.b
[1] = (UInt8
)(v
& 0xFF); return(x
); }
54 typedef struct RegisteredService_struct RegisteredService
;
55 struct RegisteredService_struct
57 RegisteredService
*next
;
60 DNSServiceErrorType errorCode
;
62 char typestr
[kDNSServiceMaxDomainName
];
63 char domstr
[kDNSServiceMaxDomainName
];
66 static RegisteredService p1
, p2
, afp
, http
, njp
;
67 static RegisteredService
*services
= NULL
, **nextservice
= &services
;
69 static void RegCallback(DNSServiceRef sdRef
, DNSServiceFlags flags
, DNSServiceErrorType errorCode
,
70 const char *name
, const char *regtype
, const char *domain
, void *context
)
72 RegisteredService
*rs
= (RegisteredService
*)context
;
73 (void)sdRef
; // Unused
74 (void)flags
; // Unused
76 rs
->errorCode
= errorCode
;
77 strcpy(rs
->namestr
, name
);
78 strcpy(rs
->typestr
, regtype
);
79 strcpy(rs
->domstr
, domain
);
82 static DNSServiceErrorType
RegisterService(RegisteredService
*rs
, mDNSOpaque16 OpaquePort
,
83 const char name
[], const char type
[], const char domain
[], const char txtinfo
[])
85 DNSServiceErrorType err
;
86 unsigned char txtbuffer
[257];
87 strncpy((char*)txtbuffer
+1, txtinfo
, 255);
89 txtbuffer
[0] = (unsigned char)strlen((char*)txtbuffer
);
91 rs
->errorCode
= kDNSServiceErr_NoError
;
92 err
= DNSServiceRegister(&rs
->sdRef
, /* kDNSServiceFlagsAutoRename*/ 0, 0,
93 name
, type
, domain
, NULL
, OpaquePort
.NotAnInteger
, (unsigned short)(1+txtbuffer
[0]), txtbuffer
, RegCallback
, rs
);
95 printf("RegisterService(%s %s %s) failed %d\n", name
, type
, domain
, err
);
97 { *nextservice
= rs
; nextservice
= &rs
->next
; }
101 // RegisterFakeServiceForTesting() simulates the effect of services being registered on
102 // dynamically-allocated port numbers. No real service exists on that port -- this is just for testing.
103 static DNSServiceErrorType
RegisterFakeServiceForTesting(RegisteredService
*rs
,
104 const char name
[], const char type
[], const char domain
[], const char txtinfo
[])
106 static UInt16 NextPort
= 0xF000;
107 return RegisterService(rs
, mDNSOpaque16fromIntVal(NextPort
++), name
, type
, domain
, txtinfo
);
110 // CreateProxyRegistrationForRealService() checks to see if the given port is currently
111 // in use, and if so, advertises the specified service as present on that port.
112 // This is useful for advertising existing real services (Personal Web Sharing, Personal
113 // File Sharing, etc.) that currently don't register with mDNS Service Discovery themselves.
114 static DNSServiceErrorType
CreateProxyRegistrationForRealService(RegisteredService
*rs
,
115 const char *servicetype
, UInt16 PortAsNumber
, const char txtinfo
[])
117 mDNSOpaque16 OpaquePort
= mDNSOpaque16fromIntVal(PortAsNumber
);
121 TEndpointInfo endpointinfo
;
122 EndpointRef ep
= OTOpenEndpoint(OTCreateConfiguration(kTCPName
), 0, &endpointinfo
, &err
);
123 if (!ep
|| err
) { printf("OTOpenEndpoint (CreateProxyRegistrationForRealService) failed %d", err
); return(err
); }
125 ia
.fAddressType
= AF_INET
;
126 ia
.fPort
= OpaquePort
.NotAnInteger
;
128 bindReq
.addr
.maxlen
= sizeof(ia
);
129 bindReq
.addr
.len
= sizeof(ia
);
130 bindReq
.addr
.buf
= (UInt8
*)&ia
;
132 err
= OTBind(ep
, &bindReq
, NULL
);
134 if (err
== kOTBadAddressErr
)
135 err
= RegisterService(rs
, OpaquePort
, "", servicetype
, "local.", txtinfo
);
137 printf("OTBind failed %d", err
);
143 // YieldSomeTime() just cooperatively yields some time to other processes running on classic Mac OS
144 static Boolean
YieldSomeTime(UInt32 milliseconds
)
146 extern Boolean SIOUXQuitting
;
148 WaitNextEvent(everyEvent
, &e
, milliseconds
/ 17, NULL
);
149 SIOUXHandleOneEvent(&e
);
150 return(SIOUXQuitting
);
156 RegisteredService
*s
;
158 SIOUXSettings
.asktosaveonclose
= false;
159 SIOUXSettings
.userwindowtitle
= "\pMulticast DNS Responder";
161 printf("Multicast DNS Responder\n\n");
162 printf("This software reports errors using MacsBug breaks,\n");
163 printf("so if you don't have MacsBug installed your Mac may crash.\n\n");
164 printf("******************************************************************************\n\n");
166 err
= InitOpenTransport();
167 if (err
) { printf("InitOpenTransport failed %d", err
); return(err
); }
169 printf("Advertising Services...\n");
173 RegisterFakeServiceForTesting(&p1
, "Web Server One", "_http._tcp.", "local.", "path=/index.html");
174 RegisterFakeServiceForTesting(&p2
, "Web Server Two", "_http._tcp.", "local.", "path=/path.html");
176 RegisterFakeServiceForTesting(&p1
, "Epson Stylus 900N", "_printer._tcp.", "local.", "rn=lpq1");
177 RegisterFakeServiceForTesting(&p2
, "HP LaserJet", "_printer._tcp.", "local.", "rn=lpq2");
179 RegisterFakeServiceForTesting(&p1
, "My Printer", "_printer._tcp.", "local.", "rn=lpq3");
180 RegisterFakeServiceForTesting(&p2
, "My Other Printer", "_printer._tcp.", "local.", "lrn=pq4");
183 // If AFP Server is running, register a record for it
184 CreateProxyRegistrationForRealService(&afp
, "_afpovertcp._tcp.", 548, "");
186 // If Web Server is running, register a record for it
187 CreateProxyRegistrationForRealService(&http
, "_http._tcp.", 80, "path=/index.html");
189 while (!YieldSomeTime(35))
190 for (s
= services
; s
; s
= s
->next
)
193 printf("%s %s %s registered\n", s
->namestr
, s
->typestr
, s
->domstr
);
194 s
->gotresult
= false;
197 for (s
= services
; s
; s
= s
->next
)
198 if (s
->sdRef
) DNSServiceRefDeallocate(s
->sdRef
);
200 CloseOpenTransport();