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/>.
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
43 Log* logger = Log::getInstance();
45 if (pipe2(pfds, O_NONBLOCK) == -1)
47 logger->log("VDP6", Log::ERR, "pipe2 error");
51 sock = socket(AF_INET6, SOCK_DGRAM, 0);
54 logger->log("VDP6", Log::ERR, "socket error");
58 struct sockaddr_in6 saddr;
59 memset(&saddr, 0, sizeof(saddr));
60 saddr.sin6_family = AF_INET6;
61 inet_pton(AF_INET6, "ff15:766f:6d70:2064:6973:636f:7665:7279", &saddr.sin6_addr);
62 saddr.sin6_port = htons(51056);
64 receiveThread = std::thread( [this, logger]
66 socklen_t addrlen = sizeof(struct sockaddr_in6);
69 struct timeval timeout;
71 timeout.tv_usec = 500000;
76 FD_SET(sock, &readfds);
77 FD_SET(pfds[0], &readfds);
79 int sresult = select(((sock > pfds[0]) ? sock : pfds[0]) + 1, &readfds, NULL, NULL, &timeout);
80 if (sresult < 1) break;
82 if (FD_ISSET(pfds[0], &readfds)) break;
85 struct sockaddr_in6 theirAddr;
86 mlength = recvfrom(sock, vdpreply, 1000, 0, reinterpret_cast<struct sockaddr *>(&theirAddr), &addrlen);
89 logger->log("VDP6", Log::ERR, "recvfrom error");
93 // FIXME upgrade this to look for a return IP in the reply packet
94 char tempStringIP[40];
95 inet_ntop(AF_INET6, &theirAddr.sin6_addr, tempStringIP, sizeof(theirAddr));
98 memcpy(&tempPort, &vdpreply[26], 2);
100 ULONG newServerVersion;
101 memcpy(&newServerVersion, &vdpreply[28], 4);
103 //logger->log("VDP6", Log::INFO, "Got response: %s %u %s %lx", newServer.ip, newServer.port, newServer.name, newServer.version);
104 servers.emplace_back(tempStringIP, &vdpreply[32], ntohs(tempPort), ntohl(newServerVersion));
109 memset(message, 0, 15);
110 strcpy(message, "VDP-0001");
112 struct if_nameindex* ifs = if_nameindex();
115 for(int i = 0; ifs[i].if_index > 0; i++)
117 ifIndex = ifs[i].if_index;
118 int d = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifIndex, sizeof(ifIndex));
119 d = sendto(sock, message, 15, 0, reinterpret_cast<struct sockaddr *>(&saddr), sizeof(saddr));
120 if (d > 0) logger->log("VDP6", Log::DEBUG, "Transmitted IPv6 MC UDP on %s", ifs[i].if_name);
123 if_freenameindex(ifs);
126 UINT VDP6::numFound()
128 return servers.size();
133 write(pfds[1], "X", 1);
134 receiveThread.join();