12 #define MAX_DEVICEID 18
13 #define MAX_SERVNAME 256
19 # if !defined(EFI32) && !defined(EFI64)
20 # define DNSSD_API __stdcall
25 typedef struct _DNSServiceRef_t
*DNSServiceRef
;
26 typedef union _TXTRecordRef_t
{ char PrivateData
[16]; char *ForceNaturalAlignment
; } TXTRecordRef
;
28 typedef uint32_t DNSServiceFlags
;
29 typedef int32_t DNSServiceErrorType
;
31 typedef void (DNSSD_API
*DNSServiceRegisterReply
)
34 DNSServiceFlags flags
,
35 DNSServiceErrorType errorCode
,
43 typedef DNSServiceErrorType (DNSSD_API
*DNSServiceRegister_t
)
46 DNSServiceFlags flags
,
47 uint32_t interfaceIndex
,
54 const void *txtRecord
,
55 DNSServiceRegisterReply callBack
,
58 typedef void (DNSSD_API
*DNSServiceRefDeallocate_t
)(DNSServiceRef sdRef
);
59 typedef void (DNSSD_API
*TXTRecordCreate_t
)
61 TXTRecordRef
*txtRecord
,
65 typedef void (DNSSD_API
*TXTRecordDeallocate_t
)(TXTRecordRef
*txtRecord
);
66 typedef DNSServiceErrorType (DNSSD_API
*TXTRecordSetValue_t
)
68 TXTRecordRef
*txtRecord
,
73 typedef uint16_t (DNSSD_API
*TXTRecordGetLength_t
)(const TXTRecordRef
*txtRecord
);
74 typedef const void * (DNSSD_API
*TXTRecordGetBytesPtr_t
)(const TXTRecordRef
*txtRecord
);
82 DNSServiceRegister_t DNSServiceRegister
;
83 DNSServiceRefDeallocate_t DNSServiceRefDeallocate
;
84 TXTRecordCreate_t TXTRecordCreate
;
85 TXTRecordSetValue_t TXTRecordSetValue
;
86 TXTRecordGetLength_t TXTRecordGetLength
;
87 TXTRecordGetBytesPtr_t TXTRecordGetBytesPtr
;
88 TXTRecordDeallocate_t TXTRecordDeallocate
;
90 char hwaddr
[MAX_HWADDR_LEN
];
93 DNSServiceRef raopService
;
94 DNSServiceRef airplayService
;
100 dnssd_init(const char *hwaddr
, int hwaddrlen
, int *error
)
104 if (error
) *error
= DNSSD_ERROR_NOERROR
;
105 if (hwaddrlen
> MAX_HWADDR_LEN
) {
106 if (error
) *error
= DNSSD_ERROR_HWADDRLEN
;
110 dnssd
= calloc(1, sizeof(dnssd_t
));
112 if (error
) *error
= DNSSD_ERROR_OUTOFMEM
;
117 dnssd
->module
= LoadLibraryA("dnssd.dll");
118 if (!dnssd
->module
) {
119 if (error
) *error
= DNSSD_ERROR_LIBNOTFOUND
;
123 dnssd
->DNSServiceRegister
= (DNSServiceRegister_t
)GetProcAddress(dnssd
->module
, "DNSServiceRegister");
124 dnssd
->DNSServiceRefDeallocate
= (DNSServiceRefDeallocate_t
)GetProcAddress(dnssd
->module
, "DNSServiceRefDeallocate");
125 dnssd
->TXTRecordCreate
= (TXTRecordCreate_t
)GetProcAddress(dnssd
->module
, "TXTRecordCreate");
126 dnssd
->TXTRecordSetValue
= (TXTRecordSetValue_t
)GetProcAddress(dnssd
->module
, "TXTRecordSetValue");
127 dnssd
->TXTRecordGetLength
= (TXTRecordGetLength_t
)GetProcAddress(dnssd
->module
, "TXTRecordGetLength");
128 dnssd
->TXTRecordGetBytesPtr
= (TXTRecordGetBytesPtr_t
)GetProcAddress(dnssd
->module
, "TXTRecordGetBytesPtr");
129 dnssd
->TXTRecordDeallocate
= (TXTRecordDeallocate_t
)GetProcAddress(dnssd
->module
, "TXTRecordDeallocate");
131 if (!dnssd
->DNSServiceRegister
|| !dnssd
->DNSServiceRefDeallocate
|| !dnssd
->TXTRecordCreate
||
132 !dnssd
->TXTRecordSetValue
|| !dnssd
->TXTRecordGetLength
|| !dnssd
->TXTRecordGetBytesPtr
||
133 !dnssd
->TXTRecordDeallocate
) {
134 if (error
) *error
= DNSSD_ERROR_PROCNOTFOUND
;
135 FreeLibrary(dnssd
->module
);
140 dnssd
->DNSServiceRegister
= &DNSServiceRegister
;
141 dnssd
->DNSServiceRefDeallocate
= &DNSServiceRefDeallocate
;
142 dnssd
->TXTRecordCreate
= &TXTRecordCreate
;
143 dnssd
->TXTRecordSetValue
= &TXTRecordSetValue
;
144 dnssd
->TXTRecordGetLength
= &TXTRecordGetLength
;
145 dnssd
->TXTRecordGetBytesPtr
= &TXTRecordGetBytesPtr
;
146 dnssd
->TXTRecordDeallocate
= &TXTRecordDeallocate
;
149 memcpy(dnssd
->hwaddr
, hwaddr
, hwaddrlen
);
150 dnssd
->hwaddrlen
= hwaddrlen
;
156 dnssd_destroy(dnssd_t
*dnssd
)
160 FreeLibrary(dnssd
->module
);
167 dnssd_register_raop(dnssd_t
*dnssd
, const char *name
, unsigned short port
)
169 TXTRecordRef txtRecord
;
170 char servname
[MAX_SERVNAME
];
175 dnssd
->TXTRecordCreate(&txtRecord
, 0, NULL
);
176 dnssd
->TXTRecordSetValue(&txtRecord
, "txtvers", strlen(RAOP_TXTVERS
), RAOP_TXTVERS
);
177 dnssd
->TXTRecordSetValue(&txtRecord
, "ch", strlen(RAOP_CH
), RAOP_CH
);
178 dnssd
->TXTRecordSetValue(&txtRecord
, "cn", strlen(RAOP_CN
), RAOP_CN
);
179 dnssd
->TXTRecordSetValue(&txtRecord
, "et", strlen(RAOP_ET
), RAOP_ET
);
180 dnssd
->TXTRecordSetValue(&txtRecord
, "sv", strlen(RAOP_SV
), RAOP_SV
);
181 dnssd
->TXTRecordSetValue(&txtRecord
, "da", strlen(RAOP_DA
), RAOP_DA
);
182 dnssd
->TXTRecordSetValue(&txtRecord
, "sr", strlen(RAOP_SR
), RAOP_SR
);
183 dnssd
->TXTRecordSetValue(&txtRecord
, "ss", strlen(RAOP_SS
), RAOP_SS
);
184 dnssd
->TXTRecordSetValue(&txtRecord
, "pw", strlen(RAOP_PW
), RAOP_PW
);
185 dnssd
->TXTRecordSetValue(&txtRecord
, "vn", strlen(RAOP_VN
), RAOP_VN
);
186 dnssd
->TXTRecordSetValue(&txtRecord
, "tp", strlen(RAOP_TP
), RAOP_TP
);
187 dnssd
->TXTRecordSetValue(&txtRecord
, "md", strlen(RAOP_MD
), RAOP_MD
);
188 dnssd
->TXTRecordSetValue(&txtRecord
, "vs", strlen(GLOBAL_VERSION
), GLOBAL_VERSION
);
189 dnssd
->TXTRecordSetValue(&txtRecord
, "am", strlen(RAOP_AM
), RAOP_AM
);
190 dnssd
->TXTRecordSetValue(&txtRecord
, "sf", strlen(RAOP_SF
), RAOP_SF
);
192 /* Convert hardware address to string */
193 ret
= utils_hwaddr_raop(servname
, sizeof(servname
), dnssd
->hwaddr
, dnssd
->hwaddrlen
);
195 /* FIXME: handle better */
199 /* Check that we have bytes for 'hw@name' format */
200 if (sizeof(servname
) < strlen(servname
)+1+strlen(name
)+1) {
201 /* FIXME: handle better */
205 strncat(servname
, "@", sizeof(servname
)-strlen(servname
)-1);
206 strncat(servname
, name
, sizeof(servname
)-strlen(servname
)-1);
208 /* Register the service */
209 dnssd
->DNSServiceRegister(&dnssd
->raopService
, 0, 0,
210 servname
, "_raop._tcp",
213 dnssd
->TXTRecordGetLength(&txtRecord
),
214 dnssd
->TXTRecordGetBytesPtr(&txtRecord
),
217 /* Deallocate TXT record */
218 dnssd
->TXTRecordDeallocate(&txtRecord
);
223 dnssd_register_airplay(dnssd_t
*dnssd
, const char *name
, unsigned short port
)
225 TXTRecordRef txtRecord
;
226 char deviceid
[3*MAX_HWADDR_LEN
];
232 /* Convert hardware address to string */
233 ret
= utils_hwaddr_airplay(deviceid
, sizeof(deviceid
), dnssd
->hwaddr
, dnssd
->hwaddrlen
);
235 /* FIXME: handle better */
239 features
[sizeof(features
)-1] = '\0';
240 snprintf(features
, sizeof(features
)-1, "0x%x", GLOBAL_FEATURES
);
242 dnssd
->TXTRecordCreate(&txtRecord
, 0, NULL
);
243 dnssd
->TXTRecordSetValue(&txtRecord
, "deviceid", strlen(deviceid
), deviceid
);
244 dnssd
->TXTRecordSetValue(&txtRecord
, "features", strlen(features
), features
);
245 dnssd
->TXTRecordSetValue(&txtRecord
, "model", strlen(GLOBAL_MODEL
), GLOBAL_MODEL
);
247 /* Register the service */
248 dnssd
->DNSServiceRegister(&dnssd
->airplayService
, 0, 0,
249 name
, "_airplay._tcp",
252 dnssd
->TXTRecordGetLength(&txtRecord
),
253 dnssd
->TXTRecordGetBytesPtr(&txtRecord
),
256 /* Deallocate TXT record */
257 dnssd
->TXTRecordDeallocate(&txtRecord
);
262 dnssd_unregister_raop(dnssd_t
*dnssd
)
266 if (!dnssd
->raopService
) {
270 dnssd
->DNSServiceRefDeallocate(dnssd
->raopService
);
271 dnssd
->raopService
= NULL
;
275 dnssd_unregister_airplay(dnssd_t
*dnssd
)
279 if (!dnssd
->airplayService
) {
283 dnssd
->DNSServiceRefDeallocate(dnssd
->airplayService
);
284 dnssd
->airplayService
= NULL
;