Skip to content

Commit 9da690e

Browse files
author
robert
committed
Fixed mdns bind issue on windows
1 parent 041ec6e commit 9da690e

File tree

3 files changed

+66
-32
lines changed

3 files changed

+66
-32
lines changed

mongoose.c

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -461,8 +461,14 @@ static void mdns_cb(struct mg_connection *c, int ev, void *ev_data) {
461461

462462
void mg_multicast_add(struct mg_connection *c, char *ip);
463463
struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, char *name) {
464+
char *mcast_url;
465+
#if MG_ARCH == MG_ARCH_WIN32
466+
mcast_url = "udp://0.0.0.0:5353";
467+
#else
468+
mcast_url = "udp://224.0.0.251:5353";
469+
#endif
464470
struct mg_connection *c =
465-
mg_listen(mgr, "udp://224.0.0.251:5353", mdns_cb, name);
471+
mg_listen(mgr, mcast_url, mdns_cb, name);
466472
if (c != NULL) mg_multicast_add(c, (char *)"224.0.0.251");
467473
return c;
468474
}
@@ -8418,27 +8424,38 @@ bool mg_open_listener(struct mg_connection *c, const char *url) {
84188424
int rc, on = 1, af = c->loc.is_ip6 ? AF_INET6 : AF_INET;
84198425
int type = strncmp(url, "udp:", 4) == 0 ? SOCK_DGRAM : SOCK_STREAM;
84208426
int proto = type == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
8427+
int sockopt = -1;
84218428
(void) on;
84228429

8430+
#if defined(SO_EXCLUSIVEADDRUSE)
8431+
if (proto == IPPROTO_UDP) {
8432+
sockopt = SO_REUSEADDR;
8433+
} else {
8434+
sockopt = SO_EXCLUSIVEADDRUSE;
8435+
}
8436+
// "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE"
8437+
#elif defined(SO_REUSEADDR) && (!defined(LWIP_SOCKET) || SO_REUSE)
8438+
sockopt = SO_REUSEADDR;
8439+
// 1. SO_REUSEADDR semantics on UNIX and Windows is different. On
8440+
// Windows, SO_REUSEADDR allows to bind a socket to a port without error
8441+
// even if the port is already open by another program. This is not the
8442+
// behavior SO_REUSEADDR was designed for, and leads to hard-to-track
8443+
// failure scenarios.
8444+
//
8445+
// 2. For LWIP, SO_REUSEADDR should be explicitly enabled by defining
8446+
// SO_REUSE = 1 in lwipopts.h, otherwise the code below will compile but
8447+
// won't work! (setsockopt will return EINVAL)
8448+
#endif
8449+
8450+
MG_INFO(("%d %d", proto, IPPROTO_UDP));
8451+
84238452
if ((fd = socket(af, type, proto)) == MG_INVALID_SOCKET) {
84248453
MG_ERROR(("socket: %d", MG_SOCK_ERR(-1)));
8425-
#if defined(SO_EXCLUSIVEADDRUSE)
8426-
} else if ((rc = setsockopt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
8454+
} else if ((sockopt != -1) && (rc = setsockopt(fd, SOL_SOCKET, sockopt,
84278455
(char *) &on, sizeof(on))) != 0) {
8428-
// "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE"
8456+
#if defined(SO_EXCLUSIVEADDRUSE)
84298457
MG_ERROR(("setsockopt(SO_EXCLUSIVEADDRUSE): %d %d", on, MG_SOCK_ERR(rc)));
8430-
#elif defined(SO_REUSEADDR) && (!defined(LWIP_SOCKET) || SO_REUSE)
8431-
} else if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
8432-
sizeof(on))) != 0) {
8433-
// 1. SO_REUSEADDR semantics on UNIX and Windows is different. On
8434-
// Windows, SO_REUSEADDR allows to bind a socket to a port without error
8435-
// even if the port is already open by another program. This is not the
8436-
// behavior SO_REUSEADDR was designed for, and leads to hard-to-track
8437-
// failure scenarios.
8438-
//
8439-
// 2. For LWIP, SO_REUSEADDR should be explicitly enabled by defining
8440-
// SO_REUSE = 1 in lwipopts.h, otherwise the code below will compile but
8441-
// won't work! (setsockopt will return EINVAL)
8458+
#else
84428459
MG_ERROR(("setsockopt(SO_REUSEADDR): %d", MG_SOCK_ERR(rc)));
84438460
#endif
84448461
#if MG_IPV6_V6ONLY

src/dns.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,8 +340,14 @@ static void mdns_cb(struct mg_connection *c, int ev, void *ev_data) {
340340

341341
void mg_multicast_add(struct mg_connection *c, char *ip);
342342
struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, char *name) {
343+
char *mcast_url;
344+
#if MG_ARCH == MG_ARCH_WIN32
345+
mcast_url = "udp://0.0.0.0:5353";
346+
#else
347+
mcast_url = "udp://224.0.0.251:5353";
348+
#endif
343349
struct mg_connection *c =
344-
mg_listen(mgr, "udp://224.0.0.251:5353", mdns_cb, name);
350+
mg_listen(mgr, mcast_url, mdns_cb, name);
345351
if (c != NULL) mg_multicast_add(c, (char *)"224.0.0.251");
346352
return c;
347353
}

src/sock.c

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -207,27 +207,38 @@ bool mg_open_listener(struct mg_connection *c, const char *url) {
207207
int rc, on = 1, af = c->loc.is_ip6 ? AF_INET6 : AF_INET;
208208
int type = strncmp(url, "udp:", 4) == 0 ? SOCK_DGRAM : SOCK_STREAM;
209209
int proto = type == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
210+
int sockopt = -1;
210211
(void) on;
211212

213+
#if defined(SO_EXCLUSIVEADDRUSE)
214+
if (proto == IPPROTO_UDP) {
215+
sockopt = SO_REUSEADDR;
216+
} else {
217+
sockopt = SO_EXCLUSIVEADDRUSE;
218+
}
219+
// "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE"
220+
#elif defined(SO_REUSEADDR) && (!defined(LWIP_SOCKET) || SO_REUSE)
221+
sockopt = SO_REUSEADDR;
222+
// 1. SO_REUSEADDR semantics on UNIX and Windows is different. On
223+
// Windows, SO_REUSEADDR allows to bind a socket to a port without error
224+
// even if the port is already open by another program. This is not the
225+
// behavior SO_REUSEADDR was designed for, and leads to hard-to-track
226+
// failure scenarios.
227+
//
228+
// 2. For LWIP, SO_REUSEADDR should be explicitly enabled by defining
229+
// SO_REUSE = 1 in lwipopts.h, otherwise the code below will compile but
230+
// won't work! (setsockopt will return EINVAL)
231+
#endif
232+
233+
MG_INFO(("%d %d", proto, IPPROTO_UDP));
234+
212235
if ((fd = socket(af, type, proto)) == MG_INVALID_SOCKET) {
213236
MG_ERROR(("socket: %d", MG_SOCK_ERR(-1)));
214-
#if defined(SO_EXCLUSIVEADDRUSE)
215-
} else if ((rc = setsockopt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
237+
} else if ((sockopt != -1) && (rc = setsockopt(fd, SOL_SOCKET, sockopt,
216238
(char *) &on, sizeof(on))) != 0) {
217-
// "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE"
239+
#if defined(SO_EXCLUSIVEADDRUSE)
218240
MG_ERROR(("setsockopt(SO_EXCLUSIVEADDRUSE): %d %d", on, MG_SOCK_ERR(rc)));
219-
#elif defined(SO_REUSEADDR) && (!defined(LWIP_SOCKET) || SO_REUSE)
220-
} else if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
221-
sizeof(on))) != 0) {
222-
// 1. SO_REUSEADDR semantics on UNIX and Windows is different. On
223-
// Windows, SO_REUSEADDR allows to bind a socket to a port without error
224-
// even if the port is already open by another program. This is not the
225-
// behavior SO_REUSEADDR was designed for, and leads to hard-to-track
226-
// failure scenarios.
227-
//
228-
// 2. For LWIP, SO_REUSEADDR should be explicitly enabled by defining
229-
// SO_REUSE = 1 in lwipopts.h, otherwise the code below will compile but
230-
// won't work! (setsockopt will return EINVAL)
241+
#else
231242
MG_ERROR(("setsockopt(SO_REUSEADDR): %d", MG_SOCK_ERR(rc)));
232243
#endif
233244
#if MG_IPV6_V6ONLY

0 commit comments

Comments
 (0)