mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
Support IPv6 link-local addresses
Use `getaddrinfo` in `parse_address` instead of `inet_pton`. Display Ipv6 addresses with scope identifiers correctly in `get_ip` functions using `if_indextoname`.
This commit is contained in:
parent
c3d3e6f48b
commit
4888b35284
9 changed files with 107 additions and 275 deletions
|
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
#include "module-netjack2/packets.h"
|
#include "module-netjack2/packets.h"
|
||||||
#include "module-netjack2/peer.c"
|
#include "module-netjack2/peer.c"
|
||||||
|
#include "network-utils.h"
|
||||||
|
|
||||||
#ifndef IPTOS_DSCP
|
#ifndef IPTOS_DSCP
|
||||||
#define IPTOS_DSCP_MASK 0xfc
|
#define IPTOS_DSCP_MASK 0xfc
|
||||||
|
|
@ -689,26 +690,6 @@ on_data_io(void *data, int fd, uint32_t mask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_address(const char *address, uint16_t port,
|
|
||||||
struct sockaddr_storage *addr, socklen_t *len)
|
|
||||||
{
|
|
||||||
struct sockaddr_in *sa4 = (struct sockaddr_in*)addr;
|
|
||||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr;
|
|
||||||
|
|
||||||
if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) {
|
|
||||||
sa4->sin_family = AF_INET;
|
|
||||||
sa4->sin_port = htons(port);
|
|
||||||
*len = sizeof(*sa4);
|
|
||||||
} else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) {
|
|
||||||
sa6->sin6_family = AF_INET6;
|
|
||||||
sa6->sin6_port = htons(port);
|
|
||||||
*len = sizeof(*sa6);
|
|
||||||
} else
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_multicast(struct sockaddr *sa, socklen_t salen)
|
static bool is_multicast(struct sockaddr *sa, socklen_t salen)
|
||||||
{
|
{
|
||||||
if (sa->sa_family == AF_INET) {
|
if (sa->sa_family == AF_INET) {
|
||||||
|
|
@ -777,19 +758,6 @@ error:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *get_ip(const struct sockaddr_storage *sa, char *ip, size_t len)
|
|
||||||
{
|
|
||||||
if (sa->ss_family == AF_INET) {
|
|
||||||
struct sockaddr_in *in = (struct sockaddr_in*)sa;
|
|
||||||
inet_ntop(sa->ss_family, &in->sin_addr, ip, len);
|
|
||||||
} else if (sa->ss_family == AF_INET6) {
|
|
||||||
struct sockaddr_in6 *in = (struct sockaddr_in6*)sa;
|
|
||||||
inet_ntop(sa->ss_family, &in->sin6_addr, ip, len);
|
|
||||||
} else
|
|
||||||
snprintf(ip, len, "invalid ip");
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void update_timer(struct impl *impl, uint64_t timeout)
|
static void update_timer(struct impl *impl, uint64_t timeout)
|
||||||
{
|
{
|
||||||
struct timespec value, interval;
|
struct timespec value, interval;
|
||||||
|
|
@ -959,7 +927,7 @@ static int send_follower_available(struct impl *impl)
|
||||||
|
|
||||||
pw_loop_update_io(impl->main_loop, impl->setup_socket, SPA_IO_IN);
|
pw_loop_update_io(impl->main_loop, impl->setup_socket, SPA_IO_IN);
|
||||||
|
|
||||||
pw_log_info("sending AVAILABLE to %s", get_ip(&impl->dst_addr, buffer, sizeof(buffer)));
|
pw_log_info("sending AVAILABLE to %s", get_ip_fmt(&impl->dst_addr, buffer, sizeof(buffer)));
|
||||||
|
|
||||||
client_name = pw_properties_get(impl->props, "netjack2.client-name");
|
client_name = pw_properties_get(impl->props, "netjack2.client-name");
|
||||||
if (client_name == NULL)
|
if (client_name == NULL)
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
#include "module-netjack2/packets.h"
|
#include "module-netjack2/packets.h"
|
||||||
|
|
||||||
#include "module-netjack2/peer.c"
|
#include "module-netjack2/peer.c"
|
||||||
|
#include "network-utils.h"
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
#define ifr_ifindex ifr_index
|
#define ifr_ifindex ifr_index
|
||||||
|
|
@ -738,26 +739,6 @@ static int create_filters(struct follower *follower)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_address(const char *address, uint16_t port,
|
|
||||||
struct sockaddr_storage *addr, socklen_t *len)
|
|
||||||
{
|
|
||||||
struct sockaddr_in *sa4 = (struct sockaddr_in*)addr;
|
|
||||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr;
|
|
||||||
|
|
||||||
if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) {
|
|
||||||
sa4->sin_family = AF_INET;
|
|
||||||
sa4->sin_port = htons(port);
|
|
||||||
*len = sizeof(*sa4);
|
|
||||||
} else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) {
|
|
||||||
sa6->sin6_family = AF_INET6;
|
|
||||||
sa6->sin6_port = htons(port);
|
|
||||||
*len = sizeof(*sa6);
|
|
||||||
} else
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_multicast(struct sockaddr *sa, socklen_t salen)
|
static bool is_multicast(struct sockaddr *sa, socklen_t salen)
|
||||||
{
|
{
|
||||||
if (sa->sa_family == AF_INET) {
|
if (sa->sa_family == AF_INET) {
|
||||||
|
|
@ -882,20 +863,6 @@ error:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *get_ip(const struct sockaddr_storage *sa, char *ip, size_t len)
|
|
||||||
{
|
|
||||||
if (sa->ss_family == AF_INET) {
|
|
||||||
struct sockaddr_in *in = (struct sockaddr_in*)sa;
|
|
||||||
inet_ntop(sa->ss_family, &in->sin_addr, ip, len);
|
|
||||||
} else if (sa->ss_family == AF_INET6) {
|
|
||||||
struct sockaddr_in6 *in = (struct sockaddr_in6*)sa;
|
|
||||||
inet_ntop(sa->ss_family, &in->sin6_addr, ip, len);
|
|
||||||
} else {
|
|
||||||
snprintf(ip, len, "invalid address");
|
|
||||||
}
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handle_follower_available(struct impl *impl, struct nj2_session_params *params,
|
static int handle_follower_available(struct impl *impl, struct nj2_session_params *params,
|
||||||
struct sockaddr_storage *addr, socklen_t addr_len)
|
struct sockaddr_storage *addr, socklen_t addr_len)
|
||||||
{
|
{
|
||||||
|
|
@ -1039,8 +1006,7 @@ static int handle_follower_available(struct impl *impl, struct nj2_session_param
|
||||||
|
|
||||||
nj2_session_params_hton(params, &peer->params);
|
nj2_session_params_hton(params, &peer->params);
|
||||||
params->packet_id = htonl(NJ2_ID_FOLLOWER_SETUP);
|
params->packet_id = htonl(NJ2_ID_FOLLOWER_SETUP);
|
||||||
|
pw_log_info("sending follower setup to %s", get_ip_fmt(addr, buffer, sizeof(buffer)));
|
||||||
pw_log_info("sending follower setup to %s", get_ip(addr, buffer, sizeof(buffer)));
|
|
||||||
nj2_dump_session_params(params);
|
nj2_dump_session_params(params);
|
||||||
send(follower->socket->fd, params, sizeof(*params), 0);
|
send(follower->socket->fd, params, sizeof(*params), 0);
|
||||||
|
|
||||||
|
|
@ -1139,7 +1105,7 @@ static int create_netjack2_socket(struct impl *impl)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
pw_log_info("listening for AVAILABLE on %s",
|
pw_log_info("listening for AVAILABLE on %s",
|
||||||
get_ip(&impl->src_addr, buffer, sizeof(buffer)));
|
get_ip_fmt(&impl->src_addr, buffer, sizeof(buffer)));
|
||||||
return 0;
|
return 0;
|
||||||
out:
|
out:
|
||||||
return res;
|
return res;
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include <module-rtp/sap.h>
|
#include <module-rtp/sap.h>
|
||||||
#include <module-rtp/ptp.h>
|
#include <module-rtp/ptp.h>
|
||||||
|
#include "network-utils.h"
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
#define ifr_ifindex ifr_index
|
#define ifr_ifindex ifr_index
|
||||||
|
|
@ -354,26 +355,6 @@ static void session_free(struct session *sess)
|
||||||
free(sess);
|
free(sess);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_address(const char *address, uint16_t port,
|
|
||||||
struct sockaddr_storage *addr, socklen_t *len)
|
|
||||||
{
|
|
||||||
struct sockaddr_in *sa4 = (struct sockaddr_in*)addr;
|
|
||||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr;
|
|
||||||
|
|
||||||
if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) {
|
|
||||||
sa4->sin_family = AF_INET;
|
|
||||||
sa4->sin_port = htons(port);
|
|
||||||
*len = sizeof(*sa4);
|
|
||||||
} else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) {
|
|
||||||
sa6->sin6_family = AF_INET6;
|
|
||||||
sa6->sin6_port = htons(port);
|
|
||||||
*len = sizeof(*sa6);
|
|
||||||
} else
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_multicast(struct sockaddr *sa, socklen_t salen)
|
static bool is_multicast(struct sockaddr *sa, socklen_t salen)
|
||||||
{
|
{
|
||||||
if (sa->sa_family == AF_INET) {
|
if (sa->sa_family == AF_INET) {
|
||||||
|
|
@ -414,21 +395,6 @@ static int make_unix_socket(const char *path) {
|
||||||
return spa_steal_fd(fd);
|
return spa_steal_fd(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_ip(const struct sockaddr_storage *sa, char *ip, size_t len, bool *ip4)
|
|
||||||
{
|
|
||||||
if (sa->ss_family == AF_INET) {
|
|
||||||
struct sockaddr_in *in = (struct sockaddr_in*)sa;
|
|
||||||
inet_ntop(sa->ss_family, &in->sin_addr, ip, len);
|
|
||||||
} else if (sa->ss_family == AF_INET6) {
|
|
||||||
struct sockaddr_in6 *in = (struct sockaddr_in6*)sa;
|
|
||||||
inet_ntop(sa->ss_family, &in->sin6_addr, ip, len);
|
|
||||||
} else
|
|
||||||
return -EIO;
|
|
||||||
if (ip4)
|
|
||||||
*ip4 = sa->ss_family == AF_INET;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int make_send_socket(
|
static int make_send_socket(
|
||||||
struct sockaddr_storage *src, socklen_t src_len,
|
struct sockaddr_storage *src, socklen_t src_len,
|
||||||
struct sockaddr_storage *sa, socklen_t salen,
|
struct sockaddr_storage *sa, socklen_t salen,
|
||||||
|
|
@ -510,7 +476,7 @@ static int make_recv_socket(struct sockaddr_storage *sa, socklen_t salen,
|
||||||
memset(&mr4, 0, sizeof(mr4));
|
memset(&mr4, 0, sizeof(mr4));
|
||||||
mr4.imr_multiaddr = sa4->sin_addr;
|
mr4.imr_multiaddr = sa4->sin_addr;
|
||||||
mr4.imr_ifindex = req.ifr_ifindex;
|
mr4.imr_ifindex = req.ifr_ifindex;
|
||||||
get_ip(sa, addr, sizeof(addr), NULL);
|
get_ip(sa, addr, sizeof(addr), NULL, NULL);
|
||||||
pw_log_info("join IPv4 group: %s iface:%d", addr, req.ifr_ifindex);
|
pw_log_info("join IPv4 group: %s iface:%d", addr, req.ifr_ifindex);
|
||||||
res = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr4, sizeof(mr4));
|
res = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr4, sizeof(mr4));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -523,7 +489,7 @@ static int make_recv_socket(struct sockaddr_storage *sa, socklen_t salen,
|
||||||
memset(&mr6, 0, sizeof(mr6));
|
memset(&mr6, 0, sizeof(mr6));
|
||||||
mr6.ipv6mr_multiaddr = sa6->sin6_addr;
|
mr6.ipv6mr_multiaddr = sa6->sin6_addr;
|
||||||
mr6.ipv6mr_interface = req.ifr_ifindex;
|
mr6.ipv6mr_interface = req.ifr_ifindex;
|
||||||
get_ip(sa, addr, sizeof(addr), NULL);
|
get_ip(sa, addr, sizeof(addr), NULL, NULL);
|
||||||
pw_log_info("join IPv6 group: %s iface:%d", addr, req.ifr_ifindex);
|
pw_log_info("join IPv6 group: %s iface:%d", addr, req.ifr_ifindex);
|
||||||
res = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mr6, sizeof(mr6));
|
res = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mr6, sizeof(mr6));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -687,7 +653,7 @@ static int send_sap(struct impl *impl, struct session *sess, bool bye)
|
||||||
iov[0].iov_base = &header;
|
iov[0].iov_base = &header;
|
||||||
iov[0].iov_len = sizeof(header);
|
iov[0].iov_len = sizeof(header);
|
||||||
|
|
||||||
if ((res = get_ip(&impl->src_addr, src_addr, sizeof(src_addr), &src_ip4)) < 0)
|
if ((res = get_ip(&impl->src_addr, src_addr, sizeof(src_addr), &src_ip4, NULL)) < 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
if (src_ip4) {
|
if (src_ip4) {
|
||||||
|
|
@ -701,7 +667,7 @@ static int send_sap(struct impl *impl, struct session *sess, bool bye)
|
||||||
iov[2].iov_base = SAP_MIME_TYPE;
|
iov[2].iov_base = SAP_MIME_TYPE;
|
||||||
iov[2].iov_len = sizeof(SAP_MIME_TYPE);
|
iov[2].iov_len = sizeof(SAP_MIME_TYPE);
|
||||||
|
|
||||||
if ((res = get_ip(&sdp->dst_addr, dst_addr, sizeof(dst_addr), &dst_ip4)) < 0)
|
if ((res = get_ip(&sdp->dst_addr, dst_addr, sizeof(dst_addr), &dst_ip4, NULL)) < 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
if ((user_name = pw_get_user_name()) == NULL)
|
if ((user_name = pw_get_user_name()) == NULL)
|
||||||
|
|
@ -1141,7 +1107,7 @@ static struct session *session_new(struct impl *impl, struct sdp_info *info)
|
||||||
pw_properties_set(props, PW_KEY_MEDIA_NAME, "RTP Stream");
|
pw_properties_set(props, PW_KEY_MEDIA_NAME, "RTP Stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
get_ip(&info->dst_addr, dst_addr, sizeof(dst_addr), NULL);
|
get_ip(&info->dst_addr, dst_addr, sizeof(dst_addr), NULL, NULL);
|
||||||
pw_properties_setf(props, "rtp.destination.ip", "%s", dst_addr);
|
pw_properties_setf(props, "rtp.destination.ip", "%s", dst_addr);
|
||||||
pw_properties_setf(props, "rtp.destination.port", "%u", info->dst_port);
|
pw_properties_setf(props, "rtp.destination.port", "%u", info->dst_port);
|
||||||
pw_properties_setf(props, "rtp.payload", "%u", info->payload);
|
pw_properties_setf(props, "rtp.payload", "%u", info->payload);
|
||||||
|
|
@ -1511,7 +1477,7 @@ static int start_sap(struct impl *impl)
|
||||||
if ((fd = make_recv_socket(&impl->sap_addr, impl->sap_len, impl->ifname)) < 0)
|
if ((fd = make_recv_socket(&impl->sap_addr, impl->sap_len, impl->ifname)) < 0)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
get_ip(&impl->sap_addr, addr, sizeof(addr), NULL);
|
get_ip(&impl->sap_addr, addr, sizeof(addr), NULL, NULL);
|
||||||
pw_log_info("starting SAP listener on %s", addr);
|
pw_log_info("starting SAP listener on %s", addr);
|
||||||
impl->sap_source = pw_loop_add_io(impl->loop, fd,
|
impl->sap_source = pw_loop_add_io(impl->loop, fd,
|
||||||
SPA_IO_IN, true, on_sap_io, impl);
|
SPA_IO_IN, true, on_sap_io, impl);
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
#include <module-rtp/rtp.h>
|
#include <module-rtp/rtp.h>
|
||||||
#include <module-rtp/apple-midi.h>
|
#include <module-rtp/apple-midi.h>
|
||||||
#include <module-rtp/stream.h>
|
#include <module-rtp/stream.h>
|
||||||
|
#include "network-utils.h"
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
#define ifr_ifindex ifr_index
|
#define ifr_ifindex ifr_index
|
||||||
|
|
@ -603,26 +604,11 @@ static bool cmp_ip(const struct sockaddr_storage *sa, const struct sockaddr_stor
|
||||||
} else if (sa->ss_family == AF_INET6 && sb->ss_family == AF_INET6) {
|
} else if (sa->ss_family == AF_INET6 && sb->ss_family == AF_INET6) {
|
||||||
struct sockaddr_in6 *ia = (struct sockaddr_in6*)sa;
|
struct sockaddr_in6 *ia = (struct sockaddr_in6*)sa;
|
||||||
struct sockaddr_in6 *ib = (struct sockaddr_in6*)sb;
|
struct sockaddr_in6 *ib = (struct sockaddr_in6*)sb;
|
||||||
return ia->sin6_addr.s6_addr == ib->sin6_addr.s6_addr;
|
return ia->sin6_addr.s6_addr == ib->sin6_addr.s6_addr && ia->sin6_scope_id == ib->sin6_scope_id;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_ip(const struct sockaddr_storage *sa, char *ip, size_t len, uint16_t *port)
|
|
||||||
{
|
|
||||||
if (sa->ss_family == AF_INET) {
|
|
||||||
struct sockaddr_in *in = (struct sockaddr_in*)sa;
|
|
||||||
inet_ntop(sa->ss_family, &in->sin_addr, ip, len);
|
|
||||||
*port = ntohs(in->sin_port);
|
|
||||||
} else if (sa->ss_family == AF_INET6) {
|
|
||||||
struct sockaddr_in6 *in = (struct sockaddr_in6*)sa;
|
|
||||||
inet_ntop(sa->ss_family, &in->sin6_addr, ip, len);
|
|
||||||
*port = ntohs(in->sin6_port);
|
|
||||||
} else
|
|
||||||
return -EIO;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct session *make_session(struct impl *impl, struct pw_properties *props)
|
static struct session *make_session(struct impl *impl, struct pw_properties *props)
|
||||||
{
|
{
|
||||||
struct session *sess;
|
struct session *sess;
|
||||||
|
|
@ -729,7 +715,7 @@ static void parse_apple_midi_cmd_in(struct impl *impl, bool ctrl, uint8_t *buffe
|
||||||
initiator = ntohl(hdr->initiator);
|
initiator = ntohl(hdr->initiator);
|
||||||
ssrc = ntohl(hdr->ssrc);
|
ssrc = ntohl(hdr->ssrc);
|
||||||
|
|
||||||
get_ip(sa, addr, sizeof(addr), &port);
|
get_ip(sa, addr, sizeof(addr), NULL, &port);
|
||||||
pw_log_info("IN from %s:%d %s ssrc:%08x initiator:%08x",
|
pw_log_info("IN from %s:%d %s ssrc:%08x initiator:%08x",
|
||||||
addr, port, hdr->name, ssrc, initiator);
|
addr, port, hdr->name, ssrc, initiator);
|
||||||
|
|
||||||
|
|
@ -1269,26 +1255,6 @@ static const struct pw_core_events core_events = {
|
||||||
.error = on_core_error,
|
.error = on_core_error,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int parse_address(const char *address, uint16_t port,
|
|
||||||
struct sockaddr_storage *addr, socklen_t *len)
|
|
||||||
{
|
|
||||||
struct sockaddr_in *sa4 = (struct sockaddr_in*)addr;
|
|
||||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr;
|
|
||||||
|
|
||||||
if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) {
|
|
||||||
sa4->sin_family = AF_INET;
|
|
||||||
sa4->sin_port = htons(port);
|
|
||||||
*len = sizeof(*sa4);
|
|
||||||
} else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) {
|
|
||||||
sa6->sin6_family = AF_INET6;
|
|
||||||
sa6->sin6_port = htons(port);
|
|
||||||
*len = sizeof(*sa6);
|
|
||||||
} else
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_service(struct service *s)
|
static void free_service(struct service *s)
|
||||||
{
|
{
|
||||||
spa_list_remove(&s->link);
|
spa_list_remove(&s->link);
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include <pipewire/impl.h>
|
#include <pipewire/impl.h>
|
||||||
|
|
||||||
#include <module-rtp/stream.h>
|
#include <module-rtp/stream.h>
|
||||||
|
#include "network-utils.h"
|
||||||
|
|
||||||
#ifndef IPTOS_DSCP
|
#ifndef IPTOS_DSCP
|
||||||
#define IPTOS_DSCP_MASK 0xfc
|
#define IPTOS_DSCP_MASK 0xfc
|
||||||
|
|
@ -187,26 +188,6 @@ struct impl {
|
||||||
int rtp_fd;
|
int rtp_fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int parse_address(const char *address, uint16_t port,
|
|
||||||
struct sockaddr_storage *addr, socklen_t *len)
|
|
||||||
{
|
|
||||||
struct sockaddr_in *sa4 = (struct sockaddr_in*)addr;
|
|
||||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr;
|
|
||||||
|
|
||||||
if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) {
|
|
||||||
sa4->sin_family = AF_INET;
|
|
||||||
sa4->sin_port = htons(port);
|
|
||||||
*len = sizeof(*sa4);
|
|
||||||
} else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) {
|
|
||||||
sa6->sin6_family = AF_INET6;
|
|
||||||
sa6->sin6_port = htons(port);
|
|
||||||
*len = sizeof(*sa6);
|
|
||||||
} else
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_multicast(struct sockaddr *sa, socklen_t salen)
|
static bool is_multicast(struct sockaddr *sa, socklen_t salen)
|
||||||
{
|
{
|
||||||
if (sa->sa_family == AF_INET) {
|
if (sa->sa_family == AF_INET) {
|
||||||
|
|
@ -404,19 +385,6 @@ static const struct rtp_stream_events stream_events = {
|
||||||
.send_packet = stream_send_packet,
|
.send_packet = stream_send_packet,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int get_ip(const struct sockaddr_storage *sa, char *ip, size_t len)
|
|
||||||
{
|
|
||||||
if (sa->ss_family == AF_INET) {
|
|
||||||
struct sockaddr_in *in = (struct sockaddr_in*)sa;
|
|
||||||
inet_ntop(sa->ss_family, &in->sin_addr, ip, len);
|
|
||||||
} else if (sa->ss_family == AF_INET6) {
|
|
||||||
struct sockaddr_in6 *in = (struct sockaddr_in6*)sa;
|
|
||||||
inet_ntop(sa->ss_family, &in->sin6_addr, ip, len);
|
|
||||||
} else
|
|
||||||
return -EIO;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void core_destroy(void *d)
|
static void core_destroy(void *d)
|
||||||
{
|
{
|
||||||
struct impl *impl = d;
|
struct impl *impl = d;
|
||||||
|
|
@ -589,9 +557,9 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
|
||||||
ts_offset = pw_rand32();
|
ts_offset = pw_rand32();
|
||||||
pw_properties_setf(stream_props, "rtp.sender-ts-offset", "%u", (uint32_t)ts_offset);
|
pw_properties_setf(stream_props, "rtp.sender-ts-offset", "%u", (uint32_t)ts_offset);
|
||||||
|
|
||||||
get_ip(&impl->src_addr, addr, sizeof(addr));
|
get_ip(&impl->src_addr, addr, sizeof(addr), NULL, NULL);
|
||||||
pw_properties_set(stream_props, "rtp.source.ip", addr);
|
pw_properties_set(stream_props, "rtp.source.ip", addr);
|
||||||
get_ip(&impl->dst_addr, addr, sizeof(addr));
|
get_ip(&impl->dst_addr, addr, sizeof(addr), NULL, NULL);
|
||||||
pw_properties_set(stream_props, "rtp.destination.ip", addr);
|
pw_properties_set(stream_props, "rtp.destination.ip", addr);
|
||||||
pw_properties_setf(stream_props, "rtp.destination.port", "%u", impl->dst_port);
|
pw_properties_setf(stream_props, "rtp.destination.port", "%u", impl->dst_port);
|
||||||
pw_properties_setf(stream_props, "rtp.ttl", "%u", impl->ttl);
|
pw_properties_setf(stream_props, "rtp.ttl", "%u", impl->ttl);
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include <pipewire/impl.h>
|
#include <pipewire/impl.h>
|
||||||
|
|
||||||
#include <module-rtp/stream.h>
|
#include <module-rtp/stream.h>
|
||||||
|
#include "network-utils.h"
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
#define ifr_ifindex ifr_index
|
#define ifr_ifindex ifr_index
|
||||||
|
|
@ -195,39 +196,6 @@ short_packet:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_ip(const struct sockaddr_storage *sa, char *ip, size_t len)
|
|
||||||
{
|
|
||||||
if (sa->ss_family == AF_INET) {
|
|
||||||
struct sockaddr_in *in = (struct sockaddr_in*)sa;
|
|
||||||
inet_ntop(sa->ss_family, &in->sin_addr, ip, len);
|
|
||||||
} else if (sa->ss_family == AF_INET6) {
|
|
||||||
struct sockaddr_in6 *in = (struct sockaddr_in6*)sa;
|
|
||||||
inet_ntop(sa->ss_family, &in->sin6_addr, ip, len);
|
|
||||||
} else
|
|
||||||
return -EIO;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_address(const char *address, uint16_t port,
|
|
||||||
struct sockaddr_storage *addr, socklen_t *len)
|
|
||||||
{
|
|
||||||
struct sockaddr_in *sa4 = (struct sockaddr_in*)addr;
|
|
||||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr;
|
|
||||||
|
|
||||||
if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) {
|
|
||||||
sa4->sin_family = AF_INET;
|
|
||||||
sa4->sin_port = htons(port);
|
|
||||||
*len = sizeof(*sa4);
|
|
||||||
} else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) {
|
|
||||||
sa6->sin6_family = AF_INET6;
|
|
||||||
sa6->sin6_port = htons(port);
|
|
||||||
*len = sizeof(*sa6);
|
|
||||||
} else
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname)
|
static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname)
|
||||||
{
|
{
|
||||||
int af, fd, val, res;
|
int af, fd, val, res;
|
||||||
|
|
@ -272,7 +240,7 @@ static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname)
|
||||||
memset(&mr4, 0, sizeof(mr4));
|
memset(&mr4, 0, sizeof(mr4));
|
||||||
mr4.imr_multiaddr = sa4->sin_addr;
|
mr4.imr_multiaddr = sa4->sin_addr;
|
||||||
mr4.imr_ifindex = req.ifr_ifindex;
|
mr4.imr_ifindex = req.ifr_ifindex;
|
||||||
get_ip((struct sockaddr_storage*)sa, addr, sizeof(addr));
|
get_ip((struct sockaddr_storage*)sa, addr, sizeof(addr), NULL, NULL);
|
||||||
pw_log_info("join IPv4 group: %s", addr);
|
pw_log_info("join IPv4 group: %s", addr);
|
||||||
res = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr4, sizeof(mr4));
|
res = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr4, sizeof(mr4));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -289,7 +257,7 @@ static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname)
|
||||||
memset(&mr6, 0, sizeof(mr6));
|
memset(&mr6, 0, sizeof(mr6));
|
||||||
mr6.ipv6mr_multiaddr = sa6->sin6_addr;
|
mr6.ipv6mr_multiaddr = sa6->sin6_addr;
|
||||||
mr6.ipv6mr_interface = req.ifr_ifindex;
|
mr6.ipv6mr_interface = req.ifr_ifindex;
|
||||||
get_ip((struct sockaddr_storage*)sa, addr, sizeof(addr));
|
get_ip((struct sockaddr_storage*)sa, addr, sizeof(addr), NULL, NULL);
|
||||||
pw_log_info("join IPv6 group: %s", addr);
|
pw_log_info("join IPv6 group: %s", addr);
|
||||||
res = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mr6, sizeof(mr6));
|
res = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mr6, sizeof(mr6));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -617,7 +585,7 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
|
||||||
pw_log_error("invalid source.ip %s: %s", str, spa_strerror(res));
|
pw_log_error("invalid source.ip %s: %s", str, spa_strerror(res));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
get_ip(&impl->src_addr, addr, sizeof(addr));
|
get_ip(&impl->src_addr, addr, sizeof(addr), NULL, NULL);
|
||||||
pw_properties_set(stream_props, "rtp.source.ip", addr);
|
pw_properties_set(stream_props, "rtp.source.ip", addr);
|
||||||
pw_properties_setf(stream_props, "rtp.source.port", "%u", impl->src_port);
|
pw_properties_setf(stream_props, "rtp.source.port", "%u", impl->src_port);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include <pipewire/impl.h>
|
#include <pipewire/impl.h>
|
||||||
|
|
||||||
#include <module-vban/stream.h>
|
#include <module-vban/stream.h>
|
||||||
|
#include "network-utils.h"
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
#define ifr_ifindex ifr_index
|
#define ifr_ifindex ifr_index
|
||||||
|
|
@ -189,26 +190,6 @@ short_packet:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_address(const char *address, uint16_t port,
|
|
||||||
struct sockaddr_storage *addr, socklen_t *len)
|
|
||||||
{
|
|
||||||
struct sockaddr_in *sa4 = (struct sockaddr_in*)addr;
|
|
||||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr;
|
|
||||||
|
|
||||||
if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) {
|
|
||||||
sa4->sin_family = AF_INET;
|
|
||||||
sa4->sin_port = htons(port);
|
|
||||||
*len = sizeof(*sa4);
|
|
||||||
} else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) {
|
|
||||||
sa6->sin6_family = AF_INET6;
|
|
||||||
sa6->sin6_port = htons(port);
|
|
||||||
*len = sizeof(*sa6);
|
|
||||||
} else
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname)
|
static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname)
|
||||||
{
|
{
|
||||||
int af, fd, val, res;
|
int af, fd, val, res;
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include <pipewire/impl.h>
|
#include <pipewire/impl.h>
|
||||||
|
|
||||||
#include <module-vban/stream.h>
|
#include <module-vban/stream.h>
|
||||||
|
#include "network-utils.h"
|
||||||
|
|
||||||
#ifndef IPTOS_DSCP
|
#ifndef IPTOS_DSCP
|
||||||
#define IPTOS_DSCP_MASK 0xfc
|
#define IPTOS_DSCP_MASK 0xfc
|
||||||
|
|
@ -218,26 +219,6 @@ static const struct vban_stream_events stream_events = {
|
||||||
.send_packet = stream_send_packet,
|
.send_packet = stream_send_packet,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int parse_address(const char *address, uint16_t port,
|
|
||||||
struct sockaddr_storage *addr, socklen_t *len)
|
|
||||||
{
|
|
||||||
struct sockaddr_in *sa4 = (struct sockaddr_in*)addr;
|
|
||||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr;
|
|
||||||
|
|
||||||
if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) {
|
|
||||||
sa4->sin_family = AF_INET;
|
|
||||||
sa4->sin_port = htons(port);
|
|
||||||
*len = sizeof(*sa4);
|
|
||||||
} else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) {
|
|
||||||
sa6->sin6_family = AF_INET6;
|
|
||||||
sa6->sin6_port = htons(port);
|
|
||||||
*len = sizeof(*sa6);
|
|
||||||
} else
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_multicast(struct sockaddr *sa, socklen_t salen)
|
static bool is_multicast(struct sockaddr *sa, socklen_t salen)
|
||||||
{
|
{
|
||||||
if (sa->sa_family == AF_INET) {
|
if (sa->sa_family == AF_INET) {
|
||||||
|
|
@ -299,19 +280,6 @@ error:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_ip(const struct sockaddr_storage *sa, char *ip, size_t len)
|
|
||||||
{
|
|
||||||
if (sa->ss_family == AF_INET) {
|
|
||||||
struct sockaddr_in *in = (struct sockaddr_in*)sa;
|
|
||||||
inet_ntop(sa->ss_family, &in->sin_addr, ip, len);
|
|
||||||
} else if (sa->ss_family == AF_INET6) {
|
|
||||||
struct sockaddr_in6 *in = (struct sockaddr_in6*)sa;
|
|
||||||
inet_ntop(sa->ss_family, &in->sin6_addr, ip, len);
|
|
||||||
} else
|
|
||||||
return -EIO;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void core_destroy(void *d)
|
static void core_destroy(void *d)
|
||||||
{
|
{
|
||||||
struct impl *impl = d;
|
struct impl *impl = d;
|
||||||
|
|
@ -477,9 +445,9 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
|
||||||
impl->mcast_loop = pw_properties_get_bool(props, "net.loop", DEFAULT_LOOP);
|
impl->mcast_loop = pw_properties_get_bool(props, "net.loop", DEFAULT_LOOP);
|
||||||
impl->dscp = pw_properties_get_uint32(props, "net.dscp", DEFAULT_DSCP);
|
impl->dscp = pw_properties_get_uint32(props, "net.dscp", DEFAULT_DSCP);
|
||||||
|
|
||||||
get_ip(&impl->src_addr, addr, sizeof(addr));
|
get_ip(&impl->src_addr, addr, sizeof(addr), NULL, NULL);
|
||||||
pw_properties_set(stream_props, "vban.source.ip", addr);
|
pw_properties_set(stream_props, "vban.source.ip", addr);
|
||||||
get_ip(&impl->dst_addr, addr, sizeof(addr));
|
get_ip(&impl->dst_addr, addr, sizeof(addr), NULL, NULL);
|
||||||
pw_properties_set(stream_props, "vban.destination.ip", addr);
|
pw_properties_set(stream_props, "vban.destination.ip", addr);
|
||||||
pw_properties_setf(stream_props, "vban.destination.port", "%u", impl->dst_port);
|
pw_properties_setf(stream_props, "vban.destination.port", "%u", impl->dst_port);
|
||||||
pw_properties_setf(stream_props, "vban.ttl", "%u", impl->ttl);
|
pw_properties_setf(stream_props, "vban.ttl", "%u", impl->ttl);
|
||||||
|
|
|
||||||
81
src/modules/network-utils.h
Normal file
81
src/modules/network-utils.h
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
#ifndef NETWORK_UTILS_H
|
||||||
|
#define NETWORK_UTILS_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
static int parse_address(const char *address, uint16_t port,
|
||||||
|
struct sockaddr_storage *addr, socklen_t *len)
|
||||||
|
{
|
||||||
|
struct addrinfo hints;
|
||||||
|
struct addrinfo *result, *rp;
|
||||||
|
int res;
|
||||||
|
char port_str[6];
|
||||||
|
|
||||||
|
snprintf(port_str, sizeof(port_str), "%u", port);
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_DGRAM;
|
||||||
|
hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
|
||||||
|
|
||||||
|
res = getaddrinfo(address, port_str, &hints, &result);
|
||||||
|
|
||||||
|
if (res != 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||||
|
memcpy(addr, rp->ai_addr, rp->ai_addrlen);
|
||||||
|
*len = rp->ai_addrlen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
freeaddrinfo(result);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_ip(const struct sockaddr_storage *sa, char *ip, size_t len, bool *ip4, uint16_t *port)
|
||||||
|
{
|
||||||
|
if (sa->ss_family == AF_INET) {
|
||||||
|
struct sockaddr_in *in = (struct sockaddr_in*)sa;
|
||||||
|
inet_ntop(sa->ss_family, &in->sin_addr, ip, len);
|
||||||
|
if (port)
|
||||||
|
*port = ntohs(in->sin_port);
|
||||||
|
} else if (sa->ss_family == AF_INET6) {
|
||||||
|
struct sockaddr_in6 *in = (struct sockaddr_in6*)sa;
|
||||||
|
inet_ntop(sa->ss_family, &in->sin6_addr, ip, len);
|
||||||
|
if (port)
|
||||||
|
*port = ntohs(in->sin6_port);
|
||||||
|
if (in->sin6_scope_id == 0 || len <= 1) {
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
size_t curlen = strlen(ip);
|
||||||
|
if (len-(curlen+1) >= IFNAMSIZ) {
|
||||||
|
ip += curlen+1;
|
||||||
|
ip[-1] = '%';
|
||||||
|
if (if_indextoname(in->sin6_scope_id, ip) == NULL) {
|
||||||
|
ip[-1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return -EINVAL;
|
||||||
|
finish:
|
||||||
|
if (ip4)
|
||||||
|
*ip4 = sa->ss_family == AF_INET;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char *get_ip_fmt(const struct sockaddr_storage *sa, char *ip, size_t len)
|
||||||
|
{
|
||||||
|
if (get_ip(sa, ip, len, NULL, NULL) != 0) {
|
||||||
|
snprintf(ip, len, "invalid ip");
|
||||||
|
}
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* NETWORK_UTILS_H */
|
||||||
Loading…
Add table
Add a link
Reference in a new issue