Support setting outgoing interface for multicast.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 26 Apr 2014 18:01:00 +0000 (20:01 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 26 Apr 2014 18:01:00 +0000 (20:01 +0200)
This should complete multicast output support.

config.cpp
config.h
cubemap.config.sample
main.cpp
serverpool.cpp
serverpool.h
udpstream.cpp
udpstream.h

index 57bf10a..f474f8c 100644 (file)
@@ -5,6 +5,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <net/if.h>
 #include <sys/socket.h>
 #include <map>
 #include <string>
@@ -298,6 +299,18 @@ bool parse_udpstream(const ConfigLine &line, Config *config)
                udpstream.ttl = atoi(ttl_it->second.c_str());
        }
 
+       // Parse the multicast interface index.
+       map<string, string>::const_iterator multicast_iface_it = line.parameters.find("multicast_output_interface");
+       if (multicast_iface_it == line.parameters.end()) {
+               udpstream.multicast_iface_index = -1;
+       } else {
+               udpstream.multicast_iface_index = if_nametoindex(multicast_iface_it->second.c_str());
+               if (udpstream.multicast_iface_index == 0) {
+                       log(ERROR, "Interface '%s' does not exist", multicast_iface_it->second.c_str());
+                       return false;
+               }
+       }
+
        config->udpstreams.push_back(udpstream);
        return true;
 }
index d5b0411..3014b48 100644 (file)
--- a/config.h
+++ b/config.h
@@ -22,6 +22,7 @@ struct UDPStreamConfig {
        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).
+       int multicast_iface_index;  // Default is -1 (use operating system default).
 };
 
 struct AcceptorConfig {
index a68bfb8..6378642 100644 (file)
@@ -38,4 +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
+udpstream 233.252.0.1:5002 src=http://pannekake.samfundet.no:9094/frikanalen.ts.metacube ttl=32 multicast_output_interface=eth1
index eaec887..14f6323 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -204,7 +204,8 @@ void create_streams(const Config &config,
                int stream_index = servers->add_udpstream(
                        udpstream_config.dst,
                        udpstream_config.pacing_rate,
-                       udpstream_config.ttl);
+                       udpstream_config.ttl,
+                       udpstream_config.multicast_iface_index);
 
                string src = udpstream_config.src;
                if (!src.empty()) {
index 021cf1d..4684d8c 100644 (file)
@@ -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 ttl)
+int ServerPool::add_udpstream(const sockaddr_in6 &dst, int pacing_rate, int ttl, int multicast_iface_index)
 {
-       udp_streams.push_back(new UDPStream(dst, pacing_rate, ttl));
+       udp_streams.push_back(new UDPStream(dst, pacing_rate, ttl, multicast_iface_index));
        return num_http_streams + udp_streams.size() - 1;
 }
 
index 07d9a5d..8fa46e2 100644 (file)
@@ -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<int> &data_fds);
        void delete_stream(const std::string &url);
-       int add_udpstream(const sockaddr_in6 &dst, int pacing_rate, int ttl);
+       int add_udpstream(const sockaddr_in6 &dst, int pacing_rate, int ttl, int multicast_iface_index);
 
        // 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;
index 74d6ef0..7747649 100644 (file)
@@ -1,3 +1,4 @@
+#include <string.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 
@@ -9,7 +10,7 @@
 #define SO_MAX_PACING_RATE 47
 #endif
 
-UDPStream::UDPStream(const sockaddr_in6 &dst, uint32_t pacing_rate, int ttl)
+UDPStream::UDPStream(const sockaddr_in6 &dst, uint32_t pacing_rate, int ttl, int multicast_iface_index)
        : dst(dst)
 {
        sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
@@ -41,6 +42,18 @@ UDPStream::UDPStream(const sockaddr_in6 &dst, uint32_t pacing_rate, int ttl)
                        log_perror("setsockopt(IPV6_MULTICAST_HOPS)");
                }
        }
+
+       if (multicast_iface_index != -1) {
+               ip_mreqn mr;
+               memset(&mr, 0, sizeof(mr));
+               mr.imr_ifindex = multicast_iface_index;
+               if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &mr, sizeof(mr)) == -1) {
+                       log_perror("setsockopt(IP_MULTICAST_IF)");
+               }
+               if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_iface_index, sizeof(multicast_iface_index)) == -1) {
+                       log_perror("setsockopt(IPV6_MULTICAST_IF)");
+               }
+       }
 }
 
 UDPStream::~UDPStream()
index 4a2de65..ede738e 100644 (file)
@@ -16,7 +16,7 @@ class MarkPool;
 
 class UDPStream {
 public:
-       UDPStream(const sockaddr_in6 &dst, uint32_t pacing_rate, int ttl);
+       UDPStream(const sockaddr_in6 &dst, uint32_t pacing_rate, int ttl, int multicast_iface_index);
        ~UDPStream();
 
        void send(const char *data, size_t bytes);