From b08dc2a81825a298a03f2dee2ae7dd7045e72739 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sat, 26 Apr 2014 19:00:37 +0200 Subject: [PATCH 1/1] Support setting TTL on outgoing UDP streams. Especially useful for multicast. --- config.cpp | 8 ++++++++ config.h | 1 + cubemap.config.sample | 1 + main.cpp | 5 ++++- serverpool.cpp | 4 ++-- serverpool.h | 2 +- udpstream.cpp | 21 +++++++++++++++++++-- udpstream.h | 2 +- 8 files changed, 37 insertions(+), 7 deletions(-) diff --git a/config.cpp b/config.cpp index f1b05c1..57bf10a 100644 --- a/config.cpp +++ b/config.cpp @@ -290,6 +290,14 @@ bool parse_udpstream(const ConfigLine &line, Config *config) udpstream.pacing_rate = atoi(pacing_rate_it->second.c_str()) * 1024 / 8; } + // Parse the TTL. The same value is used for unicast and multicast. + map::const_iterator ttl_it = line.parameters.find("ttl"); + if (ttl_it == line.parameters.end()) { + udpstream.ttl = -1; + } else { + udpstream.ttl = atoi(ttl_it->second.c_str()); + } + config->udpstreams.push_back(udpstream); return true; } diff --git a/config.h b/config.h index 6053148..d5b0411 100644 --- a/config.h +++ b/config.h @@ -21,6 +21,7 @@ struct UDPStreamConfig { sockaddr_in6 dst; std::string src; // Can be empty. uint32_t pacing_rate; // In bytes per second. Default is ~0U (no limit). + int ttl; // Default is -1 (use operating system default). }; struct AcceptorConfig { diff --git a/cubemap.config.sample b/cubemap.config.sample index 9b3c22b..a68bfb8 100644 --- a/cubemap.config.sample +++ b/cubemap.config.sample @@ -38,3 +38,4 @@ stream /test.flv.metacube src=http://gruessi.zrh.sesse.net:4013/test.flv encodin stream /udp.ts src=udp://@:1234 backlog_size=1048576 pacing_rate_kbit=2000 udpstream [2001:67c:29f4::50]:5000 src=http://pannekake.samfundet.no:9094/frikanalen.ts.metacube udpstream 193.35.52.50:5001 src=http://pannekake.samfundet.no:9094/frikanalen.ts.metacube +udpstream 233.252.0.1:5002 src=http://pannekake.samfundet.no:9094/frikanalen.ts.metacube ttl=32 diff --git a/main.cpp b/main.cpp index 5ba79f9..eaec887 100644 --- a/main.cpp +++ b/main.cpp @@ -201,7 +201,10 @@ void create_streams(const Config &config, // UDP streams. for (unsigned i = 0; i < config.udpstreams.size(); ++i) { const UDPStreamConfig &udpstream_config = config.udpstreams[i]; - int stream_index = servers->add_udpstream(udpstream_config.dst, udpstream_config.pacing_rate); + int stream_index = servers->add_udpstream( + udpstream_config.dst, + udpstream_config.pacing_rate, + udpstream_config.ttl); string src = udpstream_config.src; if (!src.empty()) { diff --git a/serverpool.cpp b/serverpool.cpp index 70f8658..021cf1d 100644 --- a/serverpool.cpp +++ b/serverpool.cpp @@ -121,9 +121,9 @@ int ServerPool::add_stream_from_serialized(const StreamProto &stream, const vect return num_http_streams++; } -int ServerPool::add_udpstream(const sockaddr_in6 &dst, int pacing_rate) +int ServerPool::add_udpstream(const sockaddr_in6 &dst, int pacing_rate, int ttl) { - udp_streams.push_back(new UDPStream(dst, pacing_rate)); + udp_streams.push_back(new UDPStream(dst, pacing_rate, ttl)); return num_http_streams + udp_streams.size() - 1; } diff --git a/serverpool.h b/serverpool.h index 2c2c537..07d9a5d 100644 --- a/serverpool.h +++ b/serverpool.h @@ -32,7 +32,7 @@ public: int add_stream(const std::string &url, size_t backlog_size, Stream::Encoding encoding); int add_stream_from_serialized(const StreamProto &stream, const std::vector &data_fds); void delete_stream(const std::string &url); - int add_udpstream(const sockaddr_in6 &dst, int pacing_rate); + int add_udpstream(const sockaddr_in6 &dst, int pacing_rate, int ttl); // Returns the stream index for the given URL (e.g. /foo.ts). Returns -1 on failure. int lookup_stream_by_url(const std::string &url) const; diff --git a/udpstream.cpp b/udpstream.cpp index 1e79494..74d6ef0 100644 --- a/udpstream.cpp +++ b/udpstream.cpp @@ -9,8 +9,8 @@ #define SO_MAX_PACING_RATE 47 #endif -UDPStream::UDPStream(const sockaddr_in6 &dst, uint32_t pacing_rate) - : dst(dst) +UDPStream::UDPStream(const sockaddr_in6 &dst, uint32_t pacing_rate, int ttl) + : dst(dst) { sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (sock == -1) { @@ -24,6 +24,23 @@ UDPStream::UDPStream(const sockaddr_in6 &dst, uint32_t pacing_rate) log_perror("setsockopt(SO_MAX_PACING_RATE)"); } } + + if (ttl != -1) { + // Seemingly the IPv4 parameters are used for sending to IPv4, + // even on an AF_INET6 socket, so we need to set both. + if (setsockopt(sock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) == -1) { + log_perror("setsockopt(IP_TTL)"); + } + if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1) { + log_perror("setsockopt(IP_MULTICAST_TTL)"); + } + if (setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)) == -1) { + log_perror("setsockopt(IPV6_UNICAST_HOPS)"); + } + if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) == -1) { + log_perror("setsockopt(IPV6_MULTICAST_HOPS)"); + } + } } UDPStream::~UDPStream() diff --git a/udpstream.h b/udpstream.h index ebc8ebc..4a2de65 100644 --- a/udpstream.h +++ b/udpstream.h @@ -16,7 +16,7 @@ class MarkPool; class UDPStream { public: - UDPStream(const sockaddr_in6 &dst, uint32_t pacing_rate); + UDPStream(const sockaddr_in6 &dst, uint32_t pacing_rate, int ttl); ~UDPStream(); void send(const char *data, size_t bytes); -- 2.39.2