|
@@ -18,6 +18,44 @@ static void set_sock_nonblock(int sockfd) {
|
18
|
18
|
fcntl(sockfd, F_SETFL, arg);
|
19
|
19
|
}
|
20
|
20
|
|
|
21
|
+int udp_connect_input(struct io *io) {
|
|
22
|
+ int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
|
23
|
+ if (sock < 0) {
|
|
24
|
+ ts_LOGf("socket(SOCK_DGRAM): %s", strerror(errno));
|
|
25
|
+ return -1;
|
|
26
|
+ }
|
|
27
|
+
|
|
28
|
+ ts_LOGf("Connecting input to udp://%s:%d/\n", inet_ntoa(io->addr), io->port);
|
|
29
|
+ int on = 1;
|
|
30
|
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
|
31
|
+
|
|
32
|
+ // subscribe to multicast group
|
|
33
|
+ if (IN_MULTICAST(ntohl(io->addr.s_addr))) {
|
|
34
|
+ struct ip_mreq mreq;
|
|
35
|
+ memcpy(&mreq.imr_multiaddr, &io->addr, sizeof(struct in_addr));
|
|
36
|
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
|
37
|
+ if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
|
|
38
|
+ ts_LOGf("setsockopt(IP_ADD_MEMBERSHIP %s): %s", inet_ntoa(io->addr), strerror(errno));
|
|
39
|
+ return -1;
|
|
40
|
+ }
|
|
41
|
+ }
|
|
42
|
+ // bind to the socket so data can be read
|
|
43
|
+ struct sockaddr_in receiving_from;
|
|
44
|
+ memset(&receiving_from, 0, sizeof(receiving_from));
|
|
45
|
+ receiving_from.sin_family = AF_INET;
|
|
46
|
+ receiving_from.sin_addr = io->addr;
|
|
47
|
+ receiving_from.sin_port = htons(io->port);
|
|
48
|
+ if (bind(sock, (struct sockaddr *) &receiving_from, sizeof(receiving_from)) < 0) {
|
|
49
|
+ ts_LOGf("bind(): %s", strerror(errno));
|
|
50
|
+ return -1;
|
|
51
|
+ }
|
|
52
|
+
|
|
53
|
+ io->fd = sock;
|
|
54
|
+ ts_LOGf("Input connected to fd:%d\n", io->fd);
|
|
55
|
+
|
|
56
|
+ return 1;
|
|
57
|
+}
|
|
58
|
+
|
21
|
59
|
int udp_connect_output(struct io *io) {
|
22
|
60
|
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
23
|
61
|
if (sock < 0) {
|