Skip to content

Commit 38e514d

Browse files
authored
Merge pull request #83 from monome/windows-native-service-discovery
replace bonjour with native DNS-SD API on windows
2 parents 68a4a0a + 88d03be commit 38e514d

6 files changed

Lines changed: 128 additions & 52 deletions

File tree

CMakeLists.txt

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -143,16 +143,12 @@ if(NOT WIN32)
143143
endif()
144144

145145
if(WIN32)
146-
set(CMAKE_REQUIRED_INCLUDES "C:\\Program Files\\Bonjour SDK\\include")
147-
check_include_file("dns_sd.h" HAVE_DNS_SD_H)
148-
if(HAVE_DNS_SD_H)
149-
include_directories(SYSTEM "C:\\Program Files\\Bonjour SDK\\include")
150-
endif()
146+
set(HAVE_DNS_SD ON)
151147
else()
152-
check_include_file("dns_sd.h" HAVE_DNS_SD_H)
148+
check_include_file("dns_sd.h" HAVE_DNS_SD)
153149
endif()
154150

155-
cmake_dependent_option(build_with_zeroconf "enable zeroconf support" ON HAVE_DNS_SD_H OFF)
151+
cmake_dependent_option(build_with_zeroconf "enable zeroconf support" ON HAVE_DNS_SD OFF)
156152

157153
add_executable(serialosc-device)
158154
set_target_properties(serialosc-device PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
@@ -176,19 +172,21 @@ else()
176172
endif()
177173

178174
if(build_with_zeroconf)
179-
target_sources(serialosc-device PRIVATE src/serialosc-device/zeroconf/common.c)
175+
add_compile_definitions(SOSC_ZEROCONF)
180176

181-
if(LINUX)
182-
target_sources(serialosc-device PRIVATE src/serialosc-device/zeroconf/not_darwin.c)
183-
endif()
184-
if(APPLE)
185-
target_sources(serialosc-device PRIVATE src/serialosc-device/zeroconf/darwin.c)
186-
endif()
187177
if(WIN32)
188178
target_sources(serialosc-device PRIVATE src/serialosc-device/zeroconf/windows.c)
179+
target_link_libraries(serialosc-device dnsapi)
180+
else()
181+
target_sources(serialosc-device PRIVATE src/serialosc-device/zeroconf/common.c)
182+
if(LINUX)
183+
target_sources(serialosc-device PRIVATE src/serialosc-device/zeroconf/not_darwin.c)
184+
endif()
185+
if(APPLE)
186+
target_sources(serialosc-device PRIVATE src/serialosc-device/zeroconf/darwin.c)
187+
endif()
189188
endif()
190189
else()
191-
add_compile_definitions(SOSC_NO_ZEROCONF)
192190
target_sources(serialosc-device PRIVATE src/serialosc-device/zeroconf/dummy.c)
193191
endif()
194192

include/serialosc/serialosc.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@
1616

1717
#pragma once
1818

19+
#ifdef SOSC_ZEROCONF
1920
#ifdef _WIN32
20-
#include <winsock2.h>
21-
#endif
22-
23-
#ifndef SOSC_NO_ZEROCONF
21+
#include <windows.h>
22+
#include <windns.h>
23+
#else
2424
#include <dns_sd.h>
2525
#endif
26+
#endif
2627

2728
#include <lo/lo.h>
2829
#include <monome.h>
@@ -61,8 +62,12 @@ typedef struct sosc_state {
6162
int ipc_in_fd;
6263
int ipc_out_fd;
6364

64-
#ifndef SOSC_NO_ZEROCONF
65-
DNSServiceRef ref;
65+
#ifdef SOSC_ZEROCONF
66+
#ifdef _WIN32
67+
PDNS_SERVICE_INSTANCE dnssd_service_ref;
68+
#else
69+
DNSServiceRef dnssd_service_ref;
70+
#endif
6671
#endif
6772

6873
sosc_config_t config;

src/serialosc-device/wscript

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ def build(ctx):
66
objs = []
77
obj = lambda src: objs.append(src)
88

9-
if ctx.env.SOSC_NO_ZEROCONF:
10-
obj('zeroconf/dummy.c')
11-
else:
12-
obj('zeroconf/common.c')
13-
9+
if ctx.env.SOSC_ZEROCONF:
1410
if ctx.env.DEST_OS[:3] == "win":
1511
obj('zeroconf/windows.c')
16-
elif ctx.env.DEST_OS == 'linux':
17-
obj('zeroconf/not_darwin.c')
18-
elif ctx.env.DEST_OS == 'darwin':
19-
obj('zeroconf/darwin.c')
12+
else:
13+
obj('zeroconf/common.c')
14+
if ctx.env.DEST_OS == 'linux':
15+
obj('zeroconf/not_darwin.c')
16+
elif ctx.env.DEST_OS == 'darwin':
17+
obj('zeroconf/darwin.c')
18+
else:
19+
obj('zeroconf/dummy.c')
2020

2121
if ctx.env.DEST_OS[:3] == "win":
2222
obj('event_loop/windows.c')

src/serialosc-device/zeroconf/common.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ sosc_zeroconf_register(sosc_state_t *state, const char *svc_name)
4040
return;
4141

4242
sosc_dnssd_registration_func(
43-
/* sdref */ &state->ref,
43+
/* sdref */ &state->dnssd_service_ref,
4444
/* interfaceIndex */ 0,
4545
/* flags */ 0,
4646
/* name */ svc_name,
@@ -60,5 +60,5 @@ sosc_zeroconf_unregister(sosc_state_t *state)
6060
if (!sosc_dnssd_deallocation_func)
6161
return;
6262

63-
sosc_dnssd_deallocation_func(state->ref);
63+
sosc_dnssd_deallocation_func(state->dnssd_service_ref);
6464
}

src/serialosc-device/zeroconf/windows.c

Lines changed: 88 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,34 +16,107 @@
1616

1717
#include <stdio.h>
1818

19-
#include <winsock2.h>
2019
#include <windows.h>
21-
22-
#include <dns_sd.h>
20+
#include <windns.h>
21+
#include <strsafe.h>
2322

2423
#include <serialosc/serialosc.h>
25-
#include <serialosc/zeroconf.h>
24+
25+
static void WINAPI
26+
register_complete(DWORD status, PVOID context, PDNS_SERVICE_INSTANCE instance)
27+
{
28+
if (status != ERROR_SUCCESS) {
29+
fprintf(stderr, "sosc_zeroconf_register(): DnsServiceRegister failed (%lu)\n", status);
30+
}
31+
}
32+
33+
static void WINAPI
34+
deregister_complete(DWORD status, PVOID context, PDNS_SERVICE_INSTANCE instance)
35+
{
36+
if (status != ERROR_SUCCESS) {
37+
fprintf(stderr, "sosc_zeroconf_unregister(): DnsServiceDeRegister failed (%lu)\n", status);
38+
}
39+
}
2640

2741
void
2842
sosc_zeroconf_init(void)
2943
{
30-
FARPROC rfunc, dfunc;
31-
HMODULE ldnssd;
44+
/* dnsapi.dll is linked at build time, no library to load */
45+
return;
46+
}
47+
48+
void
49+
sosc_zeroconf_register(sosc_state_t *state, const char *svc_name)
50+
{
51+
PDNS_SERVICE_INSTANCE instance;
52+
WCHAR w_service_name[256];
53+
WCHAR w_hostname[256];
54+
DWORD w_hostname_len = ARRAYSIZE(w_hostname);
55+
int port;
56+
57+
port = lo_server_get_port(state->server);
58+
59+
MultiByteToWideChar(CP_UTF8, 0, svc_name, -1, w_service_name, ARRAYSIZE(w_service_name));
60+
61+
StringCchCatW(w_service_name, ARRAYSIZE(w_service_name), L"._monome-osc._udp.local");
3262

33-
if (!(ldnssd = LoadLibrary("dnssd.dll"))) {
34-
fprintf(stderr, "sosc_zeroconf_init(): couldn't load dnssd.dll\n");
63+
if (!GetComputerNameExW(ComputerNameDnsHostname, w_hostname, &w_hostname_len)) {
64+
fprintf(stderr, "sosc_zeroconf_register(): GetComputerNameExW failed\n");
3565
return;
3666
}
3767

38-
rfunc = GetProcAddress(ldnssd, "DNSServiceRegister");
39-
dfunc = GetProcAddress(ldnssd, "DNSServiceRefDeallocate");
68+
StringCchCatW(w_hostname, ARRAYSIZE(w_hostname), L".local");
4069

41-
if (!rfunc || !dfunc) {
42-
fprintf(stderr, "sosc_zeroconf_init(): couldn't resolve symbols in dnssd.dll\n");
43-
FreeLibrary(ldnssd);
70+
instance = DnsServiceConstructInstance(
71+
w_service_name,
72+
w_hostname,
73+
NULL, /* ipv4 */
74+
NULL, /* ipv6 */
75+
(WORD) port,
76+
0, /* priority */
77+
0, /* weight */
78+
0, /* properties count */
79+
NULL, /* keys */
80+
NULL /* values */
81+
);
82+
83+
if (!instance) {
84+
fprintf(stderr, "sosc_zeroconf_register(): DnsServiceConstructInstance failed\n");
85+
return;
86+
}
87+
88+
DNS_SERVICE_REGISTER_REQUEST request = {
89+
.Version = DNS_QUERY_REQUEST_VERSION1,
90+
.pServiceInstance = instance,
91+
.pRegisterCompletionCallback = register_complete,
92+
};
93+
94+
if (DnsServiceRegister(&request, NULL) != DNS_REQUEST_PENDING) {
95+
fprintf(stderr, "sosc_zeroconf_register(): DnsServiceRegister failed\n");
96+
DnsServiceFreeInstance(instance);
4497
return;
4598
}
4699

47-
sosc_dnssd_registration_func = (dnssd_registration_func_t) rfunc;
48-
sosc_dnssd_deallocation_func = (dnssd_deallocation_func_t) dfunc;
100+
state->dnssd_service_ref = instance;
101+
}
102+
103+
void
104+
sosc_zeroconf_unregister(sosc_state_t *state)
105+
{
106+
PDNS_SERVICE_INSTANCE instance = state->dnssd_service_ref;
107+
108+
if (!instance) {
109+
return;
110+
}
111+
112+
DNS_SERVICE_REGISTER_REQUEST request = {
113+
.Version = DNS_QUERY_REQUEST_VERSION1,
114+
.pServiceInstance = instance,
115+
.pRegisterCompletionCallback = deregister_complete,
116+
};
117+
118+
DnsServiceDeRegister(&request, NULL);
119+
120+
DnsServiceFreeInstance(instance);
121+
state->dnssd_service_ref = NULL;
49122
}

wscript

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,8 @@ def check_miscfuncs(ctx):
139139
def check_dnssd_win(conf):
140140
conf.check_cc(
141141
mandatory=True,
142-
header_name="dns_sd.h",
143-
includes=["c:/program files/bonjour sdk/include"],
142+
header_name="windns.h",
143+
lib="dnsapi",
144144
uselib_store="DNSSD_INC")
145145

146146

@@ -275,9 +275,9 @@ def configure(conf):
275275
conf.env.append_unique("CFLAGS", ["-mmacosx-version-min=10.13"])
276276
conf.env.append_unique("LINKFLAGS", ["-mmacosx-version-min=10.13"])
277277

278-
if conf.options.disable_zeroconf:
279-
conf.define("SOSC_NO_ZEROCONF", True)
280-
conf.env.SOSC_NO_ZEROCONF = True
278+
if not conf.options.disable_zeroconf:
279+
conf.define("SOSC_ZEROCONF", True)
280+
conf.env.SOSC_ZEROCONF = True
281281

282282

283283
if conf.options.enable_debug:

0 commit comments

Comments
 (0)