@@ -461,8 +461,13 @@ static void mdns_cb(struct mg_connection *c, int ev, void *ev_data) {
461
461
462
462
void mg_multicast_add(struct mg_connection *c, char *ip);
463
463
struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, char *name) {
464
+ #if MG_ARCH == MG_ARCH_WIN32
465
+ const char *mcast_url = "udp://0.0.0.0:5353";
466
+ #else
467
+ const char *mcast_url = "udp://224.0.0.251:5353";
468
+ #endif
464
469
struct mg_connection *c =
465
- mg_listen(mgr, "udp://224.0.0.251:5353" , mdns_cb, name);
470
+ mg_listen(mgr, mcast_url , mdns_cb, name);
466
471
if (c != NULL) mg_multicast_add(c, (char *)"224.0.0.251");
467
472
return c;
468
473
}
@@ -8418,27 +8423,33 @@ bool mg_open_listener(struct mg_connection *c, const char *url) {
8418
8423
int rc, on = 1, af = c->loc.is_ip6 ? AF_INET6 : AF_INET;
8419
8424
int type = strncmp(url, "udp:", 4) == 0 ? SOCK_DGRAM : SOCK_STREAM;
8420
8425
int proto = type == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
8426
+ int sockopt = -1;
8421
8427
(void) on;
8422
8428
8429
+ #if defined(SO_EXCLUSIVEADDRUSE)
8430
+ // Using SO_REUSEADDR for UDP sockets on Windows (issue #3125)
8431
+ sockopt = proto == IPPROTO_UDP ? SO_REUSEADDR : SO_EXCLUSIVEADDRUSE;
8432
+ // "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE"
8433
+ #elif defined(SO_REUSEADDR) && (!defined(LWIP_SOCKET) || SO_REUSE)
8434
+ sockopt = SO_REUSEADDR;
8435
+ // 1. SO_REUSEADDR semantics on UNIX and Windows is different. On
8436
+ // Windows, SO_REUSEADDR allows to bind a socket to a port without error
8437
+ // even if the port is already open by another program. This is not the
8438
+ // behavior SO_REUSEADDR was designed for, and leads to hard-to-track
8439
+ // failure scenarios.
8440
+ //
8441
+ // 2. For LWIP, SO_REUSEADDR should be explicitly enabled by defining
8442
+ // SO_REUSE = 1 in lwipopts.h, otherwise the code below will compile but
8443
+ // won't work! (setsockopt will return EINVAL)
8444
+ #endif
8445
+
8423
8446
if ((fd = socket(af, type, proto)) == MG_INVALID_SOCKET) {
8424
8447
MG_ERROR(("socket: %d", MG_SOCK_ERR(-1)));
8425
- #if defined(SO_EXCLUSIVEADDRUSE)
8426
- } else if ((rc = setsockopt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
8448
+ } else if ((sockopt != -1) && (rc = setsockopt(fd, SOL_SOCKET, sockopt,
8427
8449
(char *) &on, sizeof(on))) != 0) {
8428
- // "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE"
8450
+ #if defined( SO_EXCLUSIVEADDRUSE)
8429
8451
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)
8452
+ #else
8442
8453
MG_ERROR(("setsockopt(SO_REUSEADDR): %d", MG_SOCK_ERR(rc)));
8443
8454
#endif
8444
8455
#if MG_IPV6_V6ONLY
0 commit comments