329 lines
8.6 KiB
C++
329 lines
8.6 KiB
C++
/*
|
|
* 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<recursive_mutex> o_LockClient(s_MutexClientInterface);
|
|
s_SADClientInterface = p_SADClientInterface;
|
|
}
|
|
{
|
|
unique_lock<mutex> 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<recursive_mutex> o_LockClient(s_MutexClientInterface);
|
|
if (s_SADClientInterface != p_SADClientInterface) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
{
|
|
unique_lock<mutex> 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<recursive_mutex> o_LockSocket(s_MutexSocket);
|
|
if (s_SPITSocket != NULL) {
|
|
delete s_SPITSocket;
|
|
s_SPITSocket = NULL;
|
|
}
|
|
}
|
|
{
|
|
unique_lock<mutex> 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<recursive_mutex> 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<mutex> 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<recursive_mutex> 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<recursive_mutex> 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<mutex> o_UniqueLock(s_MutexSAD);
|
|
if (s_StopSAD == true) return;
|
|
}
|
|
// printf("SAD CYCLE START\n");
|
|
SAD_DetectedServer::cycleStart();
|
|
}
|
|
void SAD_Client::cycleEnd() {
|
|
{
|
|
unique_lock<mutex> o_UniqueLock(s_MutexSAD);
|
|
if (s_StopSAD == true) return;
|
|
}
|
|
SAD_DetectedServer::cycleEnd(s_SADClientInterface);
|
|
// printf("SAD CYCLE END\n");
|
|
}
|