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");
94 // FIXME upgrade this to look for a return IP in the reply packet
95 newServer.ip = new char[40];
96 inet_ntop(AF_INET6, &theirAddr.sin6_addr, newServer.ip, sizeof(theirAddr));
99 memcpy(&tempPort, &vdpreply[26], 2);
100 newServer.port = ntohs(tempPort);
102 ULONG newServerVersion;
103 memcpy(&newServerVersion, &vdpreply[28], 4);
104 newServer.version = ntohl(newServerVersion);
106 UINT newServerNameLength = static_cast<UINT>(mlength - 32);
107 newServer.name = new char[newServerNameLength];
108 strcpy(newServer.name, &vdpreply[32]);
110 logger->log("VDP6", Log::INFO, "Got response: %s %u %s %lx", newServer.ip, newServer.port, newServer.name, newServer.version);
111 servers.push_back(newServer);
116 memset(message, 0, 15);
117 strcpy(message, "VDP-0001");
119 struct if_nameindex* ifs = if_nameindex();
122 for(int i = 0; ifs[i].if_index > 0; i++)
124 ifIndex = ifs[i].if_index;
125 int d = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifIndex, sizeof(ifIndex));
126 d = sendto(sock, message, 15, 0, reinterpret_cast<struct sockaddr *>(&saddr), sizeof(saddr));
127 if (d > 0) logger->log("VDP6", Log::DEBUG, "Transmitted IPv6 MC UDP on %s", ifs[i].if_name);
130 if_freenameindex(ifs);
133 UINT VDP6::numFound()
135 return servers.size();
140 write(pfds[1], "X", 1);
141 receiveThread.join();