File: udpstream.cpp

package info (click to toggle)
cubemap 1.3.2-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 428 kB
  • sloc: cpp: 4,431; sh: 114; perl: 102; makefile: 60
file content (75 lines) | stat: -rw-r--r-- 2,030 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>

#include "log.h"
#include "udpstream.h"
#include "util.h"

#ifndef SO_MAX_PACING_RATE
#define SO_MAX_PACING_RATE 47
#endif

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);
	if (sock == -1) {
		// Oops. Ignore this output, then.
		log_perror("socket");
		return;
	}

	if (setsockopt(sock, SOL_SOCKET, SO_MAX_PACING_RATE, &pacing_rate, sizeof(pacing_rate)) == -1) {
		if (pacing_rate != ~0U) {
			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)");
		}
	}

	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()
{
	if (sock != -1) {
		safe_close(sock);
	}
}

void UDPStream::send(const char *data, size_t bytes)
{
	if (sock == -1) {
		return;
	}
	ssize_t err = sendto(sock, data, bytes, 0, reinterpret_cast<sockaddr *>(&dst), sizeof(dst));
	if (err == -1) {
		log_perror("sendto");
	}
}