Skip to content

Commit

Permalink
Merge pull request #245 from Sean-Der/master
Browse files Browse the repository at this point in the history
If socket allocations fails try again without IPv6
  • Loading branch information
paullouisageneau authored May 13, 2024
2 parents 1f5cd70 + edd1705 commit 9d35168
Showing 1 changed file with 44 additions and 46 deletions.
90 changes: 44 additions & 46 deletions src/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,47 +44,15 @@ static uint16_t get_next_port_in_range(uint16_t begin, uint16_t end) {
return next;
}

socket_t udp_create_socket(const udp_socket_config_t *config) {
socket_t sock = INVALID_SOCKET;

// Obtain local Address
struct addrinfo *ai_list = NULL;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
if (getaddrinfo(config->bind_address, "0", &hints, &ai_list) != 0) {
JLOG_ERROR("getaddrinfo for binding address failed, errno=%d", sockerrno);
return INVALID_SOCKET;
}

static socket_t create_socket_for_addrinfo(const udp_socket_config_t *config,
const struct addrinfo *ai) {
// Create socket
struct addrinfo *ai = NULL;
const int families[2] = {AF_INET6, AF_INET}; // Prefer IPv6
const char *names[2] = {"IPv6", "IPv4"};
for (int i = 0; i < 2; ++i) {
ai = find_family(ai_list, families[i]);
if (!ai)
continue;

sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sock == INVALID_SOCKET) {
JLOG_WARN("UDP socket creation for %s family failed, errno=%d", names[i], sockerrno);
continue;
}

break;
}

socket_t sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sock == INVALID_SOCKET) {
JLOG_ERROR("UDP socket creation failed: no suitable address family");
goto error;
JLOG_WARN("UDP socket creation failed, errno=%d", sockerrno);
return INVALID_SOCKET;
}

assert(ai != NULL);

// Listen on both IPv6 and IPv4
const sockopt_t disabled = 0;
if (ai->ai_family == AF_INET6)
Expand Down Expand Up @@ -126,11 +94,10 @@ socket_t udp_create_socket(const udp_socket_config_t *config) {
if (bind(sock, ai->ai_addr, (socklen_t)ai->ai_addrlen) == 0) {
JLOG_DEBUG("UDP socket bound to %s:%hu",
config->bind_address ? config->bind_address : "any", udp_get_port(sock));
freeaddrinfo(ai_list);
return sock;
}

JLOG_ERROR("UDP socket binding failed, errno=%d", sockerrno);
JLOG_WARN("UDP socket binding failed, errno=%d", sockerrno);

} else if (config->port_begin == config->port_end) {
uint16_t port = config->port_begin;
Expand All @@ -142,11 +109,10 @@ socket_t udp_create_socket(const udp_socket_config_t *config) {
if (bind(sock, (struct sockaddr *)&addr, addrlen) == 0) {
JLOG_DEBUG("UDP socket bound to %s:%hu",
config->bind_address ? config->bind_address : "any", port);
freeaddrinfo(ai_list);
return sock;
}

JLOG_ERROR("UDP socket binding failed on port %hu, errno=%d", port, sockerrno);
JLOG_WARN("UDP socket binding failed on port %hu, errno=%d", port, sockerrno);

} else {
struct sockaddr_storage addr;
Expand All @@ -160,24 +126,56 @@ socket_t udp_create_socket(const udp_socket_config_t *config) {
if (bind(sock, (struct sockaddr *)&addr, addrlen) == 0) {
JLOG_DEBUG("UDP socket bound to %s:%hu",
config->bind_address ? config->bind_address : "any", port);
freeaddrinfo(ai_list);
return sock;
}
} while ((sockerrno == SEADDRINUSE || sockerrno == SEACCES) && retries-- > 0);

JLOG_ERROR("UDP socket binding failed on port range %s:[%hu,%hu], errno=%d",
config->bind_address ? config->bind_address : "any", config->port_begin,
config->port_end, sockerrno);
JLOG_WARN("UDP socket binding failed on port range %s:[%hu,%hu], errno=%d",
config->bind_address ? config->bind_address : "any", config->port_begin,
config->port_end, sockerrno);
}

error:
freeaddrinfo(ai_list);
if (sock != INVALID_SOCKET)
closesocket(sock);

return INVALID_SOCKET;
}

socket_t udp_create_socket(const udp_socket_config_t *config) {
// Obtain local Address
struct addrinfo *ai_list = NULL;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
if (getaddrinfo(config->bind_address, "0", &hints, &ai_list) != 0) {
JLOG_ERROR("getaddrinfo for binding address failed, errno=%d", sockerrno);
return INVALID_SOCKET;
}

const int families[2] = {AF_INET6, AF_INET}; // Prefer IPv6
const char *names[2] = {"IPv6", "IPv4"};
for (int i = 0; i < 2; ++i) {
const struct addrinfo *ai = find_family(ai_list, families[i]);
if (!ai)
continue;

JLOG_DEBUG("Opening UDP socket for %s family", names[i]);
socket_t sock = create_socket_for_addrinfo(config, ai);
if (sock != INVALID_SOCKET) {
freeaddrinfo(ai_list);
return sock;
}
}

JLOG_ERROR("UDP socket opening failed");
freeaddrinfo(ai_list);
return INVALID_SOCKET;
}

int udp_recvfrom(socket_t sock, char *buffer, size_t size, addr_record_t *src) {
while (true) {
src->len = sizeof(src->addr);
Expand Down

0 comments on commit 9d35168

Please sign in to comment.