]> git.vomp.tv Git - vompclient.git/blob - vdp6.cc
Fix text corruption in channel number display on live tv
[vompclient.git] / vdp6.cc
1 /*
2     Copyright 2019 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #if IPV6
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 #include <net/if.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32
33 #include "defines.h"
34 #include "vdr.h"
35 #include "log.h"
36 #include "vdp6.h"
37
38 VDP6::VDP6()
39 {
40 }
41
42 void VDP6::run()
43 {
44   Log* logger = Log::getInstance();
45
46   if (pipe2(pfds, O_NONBLOCK) == -1)
47   {
48     logger->log("VDP6", Log::ERR, "pipe2 error");
49     return;
50   }
51   
52   sock = socket(AF_INET6, SOCK_DGRAM, 0);
53   if (sock < 0)
54   {
55     logger->log("VDP6", Log::ERR, "socket error");
56     return;
57   }
58
59   struct sockaddr_in6 saddr;
60   memset(&saddr, 0, sizeof(saddr));
61   saddr.sin6_family = AF_INET6;
62   inet_pton(AF_INET6, "ff15:766f:6d70:2064:6973:636f:7665:7279", &saddr.sin6_addr);
63   saddr.sin6_port = htons(51056);
64
65   receiveThread = std::thread( [this, logger]
66   {
67     socklen_t addrlen = sizeof(struct sockaddr_in6);
68     char vdpreply[1000];
69     fd_set readfds;
70     struct timeval timeout;
71     timeout.tv_sec = 1;
72     timeout.tv_usec = 500000;
73
74     while(1)
75     {
76       FD_ZERO(&readfds);
77       FD_SET(sock, &readfds);
78       FD_SET(pfds[0], &readfds);
79
80       int sresult = select(((sock > pfds[0]) ? sock : pfds[0]) + 1, &readfds, NULL, NULL, &timeout);
81       if (sresult < 1) break;
82
83       if (FD_ISSET(pfds[0], &readfds)) break;                        
84                               
85       int mlength;
86       struct sockaddr_in6 theirAddr;
87       mlength = recvfrom(sock, vdpreply, 1000, 0, (struct sockaddr *)&theirAddr, &addrlen);
88       if (mlength == -1)
89       {
90         logger->log("VDP6", Log::ERR, "recvfrom error");
91         break;
92       }
93       
94       VDRServer newServer;
95       // FIXME upgrade this to look for a return IP in the reply packet
96       newServer.ip = new char[40];
97       inet_ntop(AF_INET6, &theirAddr.sin6_addr, newServer.ip, sizeof(theirAddr));
98
99       USHORT tempPort;
100       memcpy(&tempPort, &vdpreply[26], 2);
101       newServer.port = ntohs(tempPort);
102
103       ULONG newServerVersion;
104       memcpy(&newServerVersion, &vdpreply[28], 4);
105       newServer.version = ntohl(newServerVersion);
106
107       int newServerNameLength = mlength - 32;
108       newServer.name = new char[newServerNameLength];
109       strcpy(newServer.name, &vdpreply[32]);
110
111       logger->log("VDP6", Log::INFO, "Got response: %s %u %s %lx", newServer.ip, newServer.port, newServer.name, newServer.version);
112       servers.push_back(newServer);
113     }
114   });
115
116   char message[15];
117   memset(message, 0, 15);
118   strcpy(message, "VDP-0001");
119
120   struct if_nameindex* ifs = if_nameindex();
121   int ifIndex;
122
123   for(int i = 0; ifs[i].if_index > 0; i++)
124   {
125     ifIndex = ifs[i].if_index;
126     int d = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifIndex, sizeof(ifIndex));
127     d = sendto(sock, message, 15, 0, (struct sockaddr*)&saddr, sizeof(saddr));
128     if (d > 0) logger->log("VDP6", Log::DEBUG, "Transmitted IPv6 MC UDP on %s", ifs[i].if_name);
129   }
130
131   if_freenameindex(ifs);
132 }
133
134 int VDP6::numFound()
135 {
136   return servers.size();
137 }
138
139 void VDP6::stop()
140 {
141   write(pfds[1], "X", 1);
142   receiveThread.join();
143   
144   close(pfds[0]);
145   close(pfds[1]);
146   close(sock);
147 }
148
149 #endif