return;
}
-static void choose_udp_address(meshlink_handle_t *mesh, const node_t *n, const sockaddr_t **sa, int *sock) {
+static void choose_udp_address(meshlink_handle_t *mesh, const node_t *n, const sockaddr_t **sa, int *sock, sockaddr_t *sa_buf) {
/* Latest guess */
*sa = &n->address;
*sock = n->sock;
goto check_socket;
}
+ /* Else, if we have a canonical address, try this once every batch */
+ if(mesh->udp_choice == 1 && n->canonical_address) {
+ char *host = xstrdup(n->canonical_address);
+ char *port = strchr(host, ' ');
+
+ if(port) {
+ *port++ = 0;
+ *sa_buf = str2sockaddr_random(mesh, host, port);
+ *sa = sa_buf;
+ free(host);
+ goto check_socket;
+ }
+
+ free(host);
+ }
+
/* Otherwise, address are found in edges to this node.
So we pick a random edge and a random socket. */
/* Otherwise, send the packet via UDP */
+ sockaddr_t sa_buf;
const sockaddr_t *sa;
int sock;
if(to->status.broadcast) {
choose_broadcast_address(mesh, to, &sa, &sock);
} else {
- choose_udp_address(mesh, to, &sa, &sock);
+ choose_udp_address(mesh, to, &sa, &sock, &sa_buf);
}
if(sendto(mesh->listen_socket[sock].udp.fd, data, len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) {
#include "system.h"
+#include "meshlink_internal.h"
#include "net.h"
#include "netutl.h"
#include "logger.h"
return result;
}
+sockaddr_t str2sockaddr_random(struct meshlink_handle *mesh, const char *address, const char *port) {
+ struct addrinfo *ai;
+ sockaddr_t result;
+ int err;
+
+ memset(&result, 0, sizeof(result));
+
+ struct addrinfo hint = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = NI_NUMERICHOST | NI_NUMERICSERV,
+ .ai_socktype = SOCK_STREAM,
+ };
+
+ err = getaddrinfo(address, port, &hint, &ai);
+
+ if(err || !ai) {
+ logger(NULL, MESHLINK_DEBUG, "Unknown type address %s port %s", address, port);
+ result.sa.sa_family = AF_UNKNOWN;
+ result.unknown.address = xstrdup(address);
+ result.unknown.port = xstrdup(port);
+ return result;
+ }
+
+ int count = 0;
+
+ for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
+ count++;
+ }
+
+ struct addrinfo *aip = ai;
+
+ for(count = prng(mesh, count); count--; aip = aip->ai_next);
+
+ memcpy(&result, aip->ai_addr, aip->ai_addrlen);
+ freeaddrinfo(ai);
+
+ return result;
+}
+
void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) {
char address[NI_MAXHOST];
char port[NI_MAXSERV];
struct addrinfo *str2addrinfo(const char *, const char *, int) __attribute__((__malloc__));
sockaddr_t str2sockaddr(const char *, const char *);
+sockaddr_t str2sockaddr_random(struct meshlink_handle *mesh, const char *, const char *);
void sockaddr2str(const sockaddr_t *, char **, char **);
char *sockaddr2hostname(const sockaddr_t *) __attribute__((__malloc__));
int sockaddrcmp(const sockaddr_t *, const sockaddr_t *) __attribute__((__warn_unused_result__));