2 Copyright 2019 Chris Tallon
4 This file is part of VOMP.
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.
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.
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/>.
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
44 Log* logger = Log::getInstance();
46 if (pipe2(pfds, O_NONBLOCK) == -1)
48 logger->log("VDP6", Log::ERR, "pipe2 error");
52 sock = socket(AF_INET6, SOCK_DGRAM, 0);
55 logger->log("VDP6", Log::ERR, "socket error");
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);
65 receiveThread = std::thread( [this, logger]
67 socklen_t addrlen = sizeof(struct sockaddr_in6);
70 struct timeval timeout;
72 timeout.tv_usec = 500000;
77 FD_SET(sock, &readfds);
78 FD_SET(pfds[0], &readfds);
80 int sresult = select(((sock > pfds[0]) ? sock : pfds[0]) + 1, &readfds, NULL, NULL, &timeout);
81 if (sresult < 1) break;
83 if (FD_ISSET(pfds[0], &readfds)) break;
86 struct sockaddr_in6 theirAddr;
87 mlength = recvfrom(sock, vdpreply, 1000, 0, (struct sockaddr *)&theirAddr, &addrlen);
90 logger->log("VDP6", Log::ERR, "recvfrom error");
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));
100 memcpy(&tempPort, &vdpreply[26], 2);
101 newServer.port = ntohs(tempPort);
103 ULONG newServerVersion;
104 memcpy(&newServerVersion, &vdpreply[28], 4);
105 newServer.version = ntohl(newServerVersion);
107 int newServerNameLength = mlength - 32;
108 newServer.name = new char[newServerNameLength];
109 strcpy(newServer.name, &vdpreply[32]);
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);
117 memset(message, 0, 15);
118 strcpy(message, "VDP-0001");
120 struct if_nameindex* ifs = if_nameindex();
123 for(int i = 0; ifs[i].if_index > 0; i++)
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);
131 if_freenameindex(ifs);
136 return servers.size();
141 write(pfds[1], "X", 1);
142 receiveThread.join();