2 Copyright 2020 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/>.
32 void VDPC::TEMPaddCLIServer(const std::string& cliServer)
34 std::lock_guard<std::mutex> lg(serversLock);
35 servers.emplace_back(4, cliServer, "", 3024, 0);
40 AddServerCallback addFunc( [this] (int ipVersion, const char* ip, const char* name, USHORT port, ULONG version)
42 std::lock_guard<std::mutex> lg(serversLock);
47 for (; i < servers.size(); i++)
49 if (servers[i].name == name) break;
52 if (i == servers.size())
54 servers.emplace_back(ipVersion, ip, name, port, version);
58 if (ipVersion == preferIPV) // delete the other
60 servers[i].ipVersion = ipVersion;
62 servers[i].name = name;
63 servers[i].port = port;
64 servers[i].version = version;
71 servers.emplace_back(ipVersion, ip, name, port, version);
76 if (!vdpc4.init(addFunc)) return false;
79 if (!vdpc6.init(addFunc)) return false;
87 std::unique_lock<std::mutex> ul(waitMutex);
100 Log::getInstance()->log("VDPC", Log::DEBUG, "Sending broadcasts");
109 waitCond.wait_for(ul, std::chrono::milliseconds(1500), [this]{ return stopNow == true; });
110 Log::getInstance()->log("VDPC", Log::DEBUG, "go() wait finished");
113 if (servers.size() == 0) Wol::getInstance()->doWakeUp();
115 } while(servers.size() < 1);
124 std::sort(servers.begin(), servers.end(), ServerSorter(preferIPV));
125 return servers.size();
130 std::lock_guard<std::mutex> lg(waitMutex);
132 waitCond.notify_one();
135 ULONG VDPC::numServers() const
137 return servers.size();
140 const VDRServer& VDPC::operator[](ULONG index) const
142 if (index >= servers.size()) std::abort();
143 return servers[index];
148 // ======================================= VDPC4
150 bool VDPC::VDPC4::init(AddServerCallback& taddFunc)
152 Log::getInstance()->log("VDPC4", Log::DEBUG, "init");
157 Log::getInstance()->log("VDPC4", Log::CRIT, "Failed to init VDPC4 UDP");
164 void VDPC::VDPC4::run()
166 Log::getInstance()->log("VDPC4", Log::DEBUG, "run");
170 receiveThread = std::thread([this]
173 startProtect.unlock();
176 startProtect.unlock();
179 void VDPC::VDPC4::stop()
181 Log::getInstance()->log("VDPC4", Log::DEBUG, "stop");
184 write(pfdsUDP4[1], "X", 1);
185 receiveThread.join();
191 void VDPC::VDPC4::threadMethod()
193 Log* logger = Log::getInstance();
195 if (pipe2(pfdsUDP4, O_NONBLOCK) == -1)
197 logger->log("VDPC4", Log::ERR, "pipe2 error B");
203 Log::getInstance()->log("VDPC4", Log::DEBUG, "goto waitformessage");
205 UCHAR retval = udp4.waitforMessage(3, pfdsUDP4[0]);
206 Log::getInstance()->log("VDPC4", Log::DEBUG, "backfrom waitformessage");
208 if (retval == 2) // we got a reply
210 const char* vdpreply = static_cast<const char*>(udp4.getData());
211 if ((udp4.getDataLength() >= 24) && !strncmp(vdpreply, "VDP-0002", 8))
213 // FIXME upgrade this to look for a return IP in the reply packet
215 USHORT newServerPort;
216 memcpy(&newServerPort, &vdpreply[26], 2);
218 ULONG newServerVersion;
219 memcpy(&newServerVersion, &vdpreply[28], 4);
221 // FIXME - packet length > 24 not checked, end NULL not checked!!
222 addFunc(4, udp4.getFromIPA(), &vdpreply[32], ntohs(newServerPort), ntohl(newServerVersion));
226 Log::getInstance()->log("VDPC4", Log::DEBUG, "loop stopnow = %i", stopNow);
230 void VDPC::VDPC4::sendRequest()
232 Log::getInstance()->log("VDPC4", Log::DEBUG, "broadcast");
235 memset(message, 0, 15);
236 strcpy(message, "VDP-0001");
237 /*tcp->getMAC(&message[9]); put mac here when TCP modified to do this*/
239 udp4.send("255.255.255.255", 51051U, message, 15);
240 udp4.send("255.255.255.255", 51052U, message, 15);
241 udp4.send("255.255.255.255", 51053U, message, 15);
242 udp4.send("255.255.255.255", 51054U, message, 15);
243 udp4.send("255.255.255.255", 51055U, message, 15);
250 // ======================================= VDPC6
252 bool VDPC::VDPC6::init(AddServerCallback& taddFunc)
254 Log::getInstance()->log("VDPC6", Log::DEBUG, "init");
259 Log::getInstance()->log("VDPC6", Log::CRIT, "Failed to init VDPC6 UDP");
266 void VDPC::VDPC6::run()
268 Log::getInstance()->log("VDPC6", Log::DEBUG, "run");
272 receiveThread = std::thread([this]
275 startProtect.unlock();
278 startProtect.unlock();
281 void VDPC::VDPC6::stop()
283 Log::getInstance()->log("VDPC6", Log::DEBUG, "stop");
286 write(pfdsUDP6[1], "X", 1);
287 receiveThread.join();
293 void VDPC::VDPC6::threadMethod()
295 Log* logger = Log::getInstance();
297 if (pipe2(pfdsUDP6, O_NONBLOCK) == -1)
299 logger->log("VDPC6", Log::ERR, "pipe2 error B");
305 Log::getInstance()->log("VDPC6", Log::DEBUG, "goto waitformessage");
307 UCHAR retval = udp6.waitforMessage(3, pfdsUDP6[0]);
308 Log::getInstance()->log("VDPC6", Log::DEBUG, "backfrom waitformessage");
310 if (retval == 2) // we got a reply
312 const char* vdpreply = static_cast<const char*>(udp6.getData());
313 if ((udp6.getDataLength() >= 24) && !strncmp(vdpreply, "VDP-0002", 8))
315 // FIXME upgrade this to look for a return IP in the reply packet
317 USHORT newServerPort;
318 memcpy(&newServerPort, &vdpreply[26], 2);
320 ULONG newServerVersion;
321 memcpy(&newServerVersion, &vdpreply[28], 4);
323 // FIXME - packet length > 24 not checked, end NULL not checked!!
324 addFunc(6, udp6.getFromIPA(), &vdpreply[32], ntohs(newServerPort), ntohl(newServerVersion));
328 Log::getInstance()->log("VDPC6", Log::DEBUG, "loop stopnow = %i", stopNow);
332 void VDPC::VDPC6::sendRequest()
334 Log::getInstance()->log("VDPC6", Log::DEBUG, "broadcast");
337 memset(message, 0, 15);
338 strcpy(message, "VDP-0001");
339 /*tcp->getMAC(&message[9]); put mac here when TCP modified to do this*/
341 udp6.send("ff15:766f:6d70:2064:6973:636f:7665:7279", 51056U, message, 15, true);