/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ /* * SAD_Client is used for ServerAutoDetection (SAD). * * File: ServerAutoDetetc_Client.cpp * Author: Hagi * * Created on 16. April 2019, 08:57 */ #include "SAD_Client.h" //----- initialze static members ----- bool SAD_Client::s_StopSAD = true; mutex SAD_Client::s_MutexSAD; condition_variable SAD_Client::s_ConditionStopSAD; thread* SAD_Client::s_ThreadSend = NULL; thread* SAD_Client::s_ThreadReceiveIP4 = NULL; thread* SAD_Client::s_ThreadReceiveIP6 = NULL; recursive_mutex SAD_Client::s_MutexClientInterface; SAD_ClientInterface* SAD_Client::s_SADClientInterface = NULL; recursive_mutex SAD_Client::s_MutexSocket; SPITSocket* SAD_Client::s_SPITSocket = NULL; void SAD_Client::startAutoDetectServer(SAD_ClientInterface* p_SADClientInterface, SPITSocket* p_SpitSocket) { if (p_SADClientInterface == NULL) return; if (p_SpitSocket == NULL) return; { unique_lock o_LockClient(s_MutexClientInterface); s_SADClientInterface = p_SADClientInterface; } { unique_lock o_UniqueLock(s_MutexSAD); if (s_StopSAD == false) return; s_StopSAD = false; SAD_DetectedServer::clearDetectedServers(); } s_SPITSocket = p_SpitSocket; s_ThreadSend = new thread(&SAD_Client::sendAutoDetectServer); s_ThreadReceiveIP4 = new thread(&SAD_Client::receiveAutoDetectServer_IP4); s_ThreadReceiveIP6 = new thread(&SAD_Client::receiveAutoDetectServer_IP6); } void SAD_Client::stopAutoDetectServer(SAD_ClientInterface* p_SADClientInterface) { bool boolStopDetection = false; { unique_lock o_LockClient(s_MutexClientInterface); if (s_SADClientInterface != p_SADClientInterface) { return; } } { unique_lock o_UniqueLock(s_MutexSAD); if (s_StopSAD == true) return; s_StopSAD = true; } s_ConditionStopSAD.notify_one(); if (s_ThreadSend != NULL) { if (this_thread::get_id() != s_ThreadSend->get_id()) { if (s_ThreadSend->joinable()) { s_ThreadSend->join(); } } s_ThreadSend = NULL; } //wait for receiving threads if (s_ThreadReceiveIP4 != NULL) { if (this_thread::get_id() != s_ThreadReceiveIP4->get_id()) { if (s_ThreadReceiveIP4->joinable()) { s_ThreadReceiveIP4->join(); } } s_ThreadReceiveIP4 = NULL; } if (s_ThreadReceiveIP6 != NULL) { if (this_thread::get_id() != s_ThreadReceiveIP6->get_id()) { if (s_ThreadReceiveIP6->joinable()) { s_ThreadReceiveIP6->join(); } } s_ThreadReceiveIP6 = NULL; } { unique_lock o_LockSocket(s_MutexSocket); if (s_SPITSocket != NULL) { delete s_SPITSocket; s_SPITSocket = NULL; } } { unique_lock o_UniqueLock(s_MutexSAD); SAD_DetectedServer::clearDetectedServers(); } } void SAD_Client::sendAutoDetectServer() { SPITSocket::IPAddress* o_IPAddress; string stringBroadcastIP4; string stringBroadcastIP6; string stringBroadcastIP6_loopback; string stringDatagram; int intDatagramLength; bool boolDone; stringDatagram = SERVERAUTODETECT_PRECODE; stringDatagram.append(SERVERAUTODETECT_SEPERATOR); stringDatagram.append(SERVERAUTODETECT_TASKID); intDatagramLength = stringDatagram.length(); stringBroadcastIP6 = "ff02::1"; stringBroadcastIP6_loopback = "::1"; while(s_StopSAD == false) { //---- IP4 --- cycleStart(); { unique_lock o_LockSocket(s_MutexSocket); if (s_SPITSocket == NULL) { return; } s_SPITSocket->getAdaptersInfo(); for (int i = 0; i < SPITSocket::getIPAddressCount(); i++) { o_IPAddress = SPITSocket::getIPAddress(i); if (o_IPAddress == NULL) break; stringBroadcastIP4 = s_SPITSocket->getBroadcastIP4(o_IPAddress); if (s_SPITSocket->sendMessageTo(SPITSocket::FAMILY_IP4, stringBroadcastIP4, SERVERAUTODETECT_PORT, stringDatagram.data(), intDatagramLength) < 0) { } else { } } //---- IP6 --- send to "ff02::1" and to the loopback address "::1" because MAC OSX seems to to need the loopback over IP6 //"ff02::1" if (s_SPITSocket->sendMessageTo(SPITSocket::FAMILY_IP6, stringBroadcastIP6, SERVERAUTODETECT_PORT, stringDatagram.data(), stringDatagram.length()) < 0) { } else { } //"::1" loopback if (s_SPITSocket->sendMessageTo(SPITSocket::FAMILY_IP6, stringBroadcastIP6_loopback, SERVERAUTODETECT_PORT, stringDatagram.data(), stringDatagram.length()) < 0) { } else { } } { if (s_StopSAD == true) { return; } //wait for 3000 milliseconds or //s_StopAutoDetectServer == true see stopAutoDetectServer unique_lock o_LockWait(s_MutexSAD); boolDone = s_ConditionStopSAD.wait_for(o_LockWait, chrono::milliseconds(3000),[]{return s_StopSAD;}); if (s_StopSAD == true) { return; } } cycleEnd(); } int intTest = 0; } void SAD_Client::receiveAutoDetectServer_IP4() { char buffer[512+1]; int intReceivedByteCount; string stringMessage; string stringServerIP; int intIndex = 0; int intPos = 0; int intOldPos = 0; string stringPart; string stringParts[9]; //sendAutoDetectServer will bind the socket to a port //wait a while to be sendAutoDetectServer first this_thread::sleep_for(chrono::milliseconds(500)); while (s_StopSAD == false) { { unique_lock o_LockIP4(s_MutexSocket); if (s_SPITSocket == NULL) { return; } } intReceivedByteCount = s_SPITSocket->receiveMessage(SPITSocket::FAMILY_IP4, buffer, 512, &stringServerIP); if (intReceivedByteCount <= 0) { if (s_StopSAD == false) { //To reduce the processor load if a socket error occurs, we let the thread sleep a bit. this_thread::sleep_for(chrono::milliseconds(100)); } continue; } if (s_StopSAD == true) { return; } //add null chararcter if (intReceivedByteCount < 512) { buffer[intReceivedByteCount] = '\0'; } else { buffer[512] = '\0'; } stringMessage = buffer; //Check if precode is ok if (stringMessage.find(SERVERAUTODETECT_PRECODE.data(),0) != 0) { return; } intIndex = 0; intPos = 0; intOldPos = 0; while(intIndex < 8) { intPos = stringMessage.find(SERVERAUTODETECT_SEPERATOR.data(),intOldPos); if (intPos == string::npos) { stringPart = ""; } else { stringPart = stringMessage.substr(intOldPos, intPos-intOldPos); intOldPos = intPos + SERVERAUTODETECT_SEPERATOR.length(); } stringParts[intIndex] = stringPart; intIndex++; } stringParts[8] = stringServerIP; SAD_DetectedServer::addDetectedServer(true, stringParts[SAD_DetectedServer::PARAMINDEX_ID], stringParts); } int inTest = 0; } void SAD_Client::receiveAutoDetectServer_IP6() { char buffer[512+1]; int intReceivedByteCount; string stringMessage; string stringServerIP; int intIndex = 0; int intPos = 0; int intOldPos = 0; string stringPart; string stringParts[9]; //sendto will bind the socket to a port //wait a while to be sendto first this_thread::sleep_for(chrono::milliseconds(500)); while (s_StopSAD == false) { { unique_lock o_LockIP6(s_MutexSocket); if (s_SPITSocket == NULL) { return; } } intReceivedByteCount = s_SPITSocket->receiveMessage(SPITSocket::FAMILY_IP6, buffer, 512, &stringServerIP); if (intReceivedByteCount <= 0) { if (s_StopSAD == false) { //To reduce the processor load if a socket error occurs, we let the thread sleep a bit. this_thread::sleep_for(chrono::milliseconds(100)); } continue; } if (s_StopSAD == true) { return; } //add null chararcter if (intReceivedByteCount < 512) { buffer[intReceivedByteCount] = '\0'; } else { buffer[512] = '\0'; } stringMessage = buffer; //Check if precode is ok if (stringMessage.find(SERVERAUTODETECT_PRECODE.data(),0) != 0) { return; } intIndex = 0; intPos = 0; intOldPos = 0; while(intIndex < 8) { intPos = stringMessage.find(SERVERAUTODETECT_SEPERATOR.data(),intOldPos); if (intPos == string::npos) { stringPart = ""; } else { stringPart = stringMessage.substr(intOldPos, intPos-intOldPos); intOldPos = intPos + SERVERAUTODETECT_SEPERATOR.length(); } stringParts[intIndex] = stringPart; intIndex++; } stringParts[8] = stringServerIP; SAD_DetectedServer::addDetectedServer(false, stringParts[SAD_DetectedServer::PARAMINDEX_ID], stringParts); } int inTest = 0; } void SAD_Client::cycleStart() { { unique_lock o_UniqueLock(s_MutexSAD); if (s_StopSAD == true) return; } // printf("SAD CYCLE START\n"); SAD_DetectedServer::cycleStart(); } void SAD_Client::cycleEnd() { { unique_lock o_UniqueLock(s_MutexSAD); if (s_StopSAD == true) return; } SAD_DetectedServer::cycleEnd(s_SADClientInterface); // printf("SAD CYCLE END\n"); }