From 4b74871060674d5d50ccb3436478fddfcb866a22 Mon Sep 17 00:00:00 2001 From: Nitin Nair Date: Thu, 20 Apr 2023 09:24:37 -0400 Subject: [PATCH 01/13] added inaternet access detection before version checking is performed --- EmotiBitOscilloscope/src/ofApp.cpp | 258 ++++++++++++++++++----------- src/ofxEmotiBitVersion.h | 2 +- 2 files changed, 165 insertions(+), 95 deletions(-) diff --git a/EmotiBitOscilloscope/src/ofApp.cpp b/EmotiBitOscilloscope/src/ofApp.cpp index 4bbe33b..b2cafbb 100644 --- a/EmotiBitOscilloscope/src/ofApp.cpp +++ b/EmotiBitOscilloscope/src/ofApp.cpp @@ -77,148 +77,218 @@ void ofApp::update() { void ofApp::checkLatestSwVersion() { - bool newVersionAvailable = false; - // system call to curl - std::string latestReleaseUrl = "https://github.com/EmotiBit/ofxEmotiBit/releases/latest"; - std::string latestReleaseApiRequest = "https://api.github.com/repos/EmotiBit/ofxEmotiBit/releases/latest"; - std::string command = "curl " + latestReleaseApiRequest; - std::string response = ""; + + bool isNetworkAvailable = false; + // -n specifies number of tries. we are going to try to detect internet connection by sending 1 packet + // -w specifies timeout period in mS. We are going to wait for a maximum of 3 seconds for a ping response. + // the IP 8.8.8.8 is google's public DNS. We are using ping with a specific IP as that removes undefined wait periods associated with DNS resolution. + std::string command = "ping -n 1 -w 3000 8.8.8.8"; + std::string pingResponse = ""; char buffer[200]; - bool exceptionOccured = false; + ofLogNotice() << "Trying to dtect internet access"; try { #if defined (TARGET_OSX) || defined (TARGET_LINUX) FILE* pipe = popen(command.c_str(), "r"); // returns NULL on fail. refer: https://man7.org/linux/man-pages/man3/popen.3.html#RETURN_VALUE #else FILE* pipe = _popen(command.c_str(), "r"); // returns NULL on fail. refer: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/popen-wpopen?view=msvc-170#return-value -#endif +#endif if (pipe != NULL) { - try + while (fgets(buffer, sizeof buffer, pipe) != NULL) { - while (fgets(buffer, sizeof buffer, pipe) != NULL) + pingResponse += buffer; + } + +#if defined (TARGET_OSX) || defined (TARGET_LINUX) + pclose(pipe); +#else + _pclose(pipe); +#endif + } + else + { + ofLogNotice() << "Failed to open pipe. ping failed"; + } + } + catch (...) + { + ofLogError() << "Ping failed"; + } + ofLogNotice() << pingResponse.c_str(); + + // A successful ping response contains a sumary of round trip times. We are using that do determine if ping was successful + /* A successful ping response + ------------------------------ + Pinging 8.8.8.8 with 32 bytes of data: + Reply from 8.8.8.8: bytes = 32 time = 18ms TTL = 119 + + Ping statistics for 8.8.8.8 : + Packets : Sent = 1, Received = 1, Lost = 0 (0 % loss), + Approximate round trip times in milli - seconds : + Minimum = 18ms, Maximum = 18ms, Average = 18ms + */ + if (pingResponse.find("Approximate round trip times") != std::string::npos) + { + // substring found! + ofLogNotice() << "internet access detected"; + isNetworkAvailable = true; + } + else + { + // failed + ofLogNotice() << "Failed to ping IP"; + } + + if (isNetworkAvailable) + { + bool newVersionAvailable = false; + // system call to curl + std::string latestReleaseUrl = "https://github.com/EmotiBit/ofxEmotiBit/releases/latest"; + std::string latestReleaseApiRequest = "https://api.github.com/repos/EmotiBit/ofxEmotiBit/releases/latest"; + std::string command = "curl --connect-timeout 3 " + latestReleaseApiRequest; + std::string response = ""; + char buffer[200]; + bool exceptionOccured = false; + try + { +#if defined (TARGET_OSX) || defined (TARGET_LINUX) + FILE* pipe = popen(command.c_str(), "r"); // returns NULL on fail. refer: https://man7.org/linux/man-pages/man3/popen.3.html#RETURN_VALUE +#else + FILE* pipe = _popen(command.c_str(), "r"); // returns NULL on fail. refer: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/popen-wpopen?view=msvc-170#return-value +#endif + if (pipe != NULL) + { + try { - response += buffer; + while (fgets(buffer, sizeof buffer, pipe) != NULL) + { + response += buffer; + } + } + catch (...) { + try + { +#if defined (TARGET_OSX) || defined (TARGET_LINUX) + pclose(pipe); +#else + _pclose(pipe); +#endif + } + catch (...) + { + ofLogError("Failed to close pipe"); + } + ofLog(OF_LOG_ERROR, "An exception occured while executing curl"); + exceptionOccured = true; } - } - catch (...) { try { - #if defined (TARGET_OSX) || defined (TARGET_LINUX) +#if defined (TARGET_OSX) || defined (TARGET_LINUX) pclose(pipe); - #else +#else _pclose(pipe); - #endif +#endif } catch (...) { ofLogError("Failed to close pipe"); } - ofLog(OF_LOG_ERROR, "An exception occured while executing curl"); - exceptionOccured = true; - } - try - { - #if defined (TARGET_OSX) || defined (TARGET_LINUX) - pclose(pipe); - #else - _pclose(pipe); - #endif } - catch (...) + else { - ofLogError("Failed to close pipe"); + ofLog(OF_LOG_ERROR, "Failed to check for latest version. Failed to open pipe"); + exceptionOccured = true; } } - else + catch (...) { - ofLog(OF_LOG_ERROR, "Failed to check for latest version. Failed to open pipe"); + ofLogError("Failed to open pipe"); exceptionOccured = true; } - } - catch (...) - { - ofLogError("Failed to open pipe"); - exceptionOccured = true; - } - try - { - if (!exceptionOccured & response != "") + try { - ofxJSONElement jsonResponse; - if (jsonResponse.parse(response)) + if (!exceptionOccured & response != "") { - //ofLog(OF_LOG_NOTICE, jsonResponse.getRawString(true)); // uncomment to print curl output - std::string latestAvailableVersion = jsonResponse["tag_name"].asString(); - ofLogNotice("Latest version") << latestAvailableVersion; - int swVerPrefixLoc = latestAvailableVersion.find(SOFTWARE_VERSION_PREFIX); - if (swVerPrefixLoc != std::string::npos) + ofxJSONElement jsonResponse; + if (jsonResponse.parse(response)) { - latestAvailableVersion.erase(swVerPrefixLoc, 1); // remove leading version char "v" - } - // compare with ofxEmotiBitVersion - std::vector latestVersionSplit = ofSplitString(latestAvailableVersion, "."); - std::vector currentVersionSplit = ofSplitString(ofxEmotiBitVersion, "."); - int versionLength = latestVersionSplit.size() < currentVersionSplit.size() ? latestVersionSplit.size() : currentVersionSplit.size(); - if (versionLength) - { - for (int i = 0; i < versionLength; i++) + //ofLog(OF_LOG_NOTICE, jsonResponse.getRawString(true)); // uncomment to print curl output + std::string latestAvailableVersion = jsonResponse["tag_name"].asString(); + ofLogNotice("Latest version") << latestAvailableVersion; + int swVerPrefixLoc = latestAvailableVersion.find(SOFTWARE_VERSION_PREFIX); + if (swVerPrefixLoc != std::string::npos) { - int latest = ofToInt(latestVersionSplit.at(i)); - int current = ofToInt(currentVersionSplit.at(i)); - if (latest == current) - { - // need to check minor version - continue; - } - else if (latest < current) - { - // current version higher than latest available - break; - } - else // latest > current + latestAvailableVersion.erase(swVerPrefixLoc, 1); // remove leading version char "v" + } + // compare with ofxEmotiBitVersion + std::vector latestVersionSplit = ofSplitString(latestAvailableVersion, "."); + std::vector currentVersionSplit = ofSplitString(ofxEmotiBitVersion, "."); + int versionLength = latestVersionSplit.size() < currentVersionSplit.size() ? latestVersionSplit.size() : currentVersionSplit.size(); + if (versionLength) + { + for (int i = 0; i < versionLength; i++) { - // new version available - newVersionAvailable = true; - break; + int latest = ofToInt(latestVersionSplit.at(i)); + int current = ofToInt(currentVersionSplit.at(i)); + if (latest == current) + { + // need to check minor version + continue; + } + else if (latest < current) + { + // current version higher than latest available + break; + } + else // latest > current + { + // new version available + newVersionAvailable = true; + break; + } } } + else + { + ofLogError("Failed to parse version string"); + } } else { - ofLogError("Failed to parse version string"); + ofLog(OF_LOG_ERROR, "unexpected curl response"); } - } - else - { - ofLog(OF_LOG_ERROR, "unexpected curl response"); - } - // If newer version available, display alert message - if (newVersionAvailable) - { - // create alert dialog box - ofSystemAlertDialog("A new version of EmotiBit Software is available!"); - // open browser to latest version - try + // If newer version available, display alert message + if (newVersionAvailable) { + // create alert dialog box + ofSystemAlertDialog("A new version of EmotiBit Software is available!"); + // open browser to latest version + try + { #ifdef TARGET_WIN32 - std::string command = "start " + latestReleaseUrl; - system(command.c_str()); + std::string command = "start " + latestReleaseUrl; + system(command.c_str()); #else - std::string command = "open " + latestReleaseUrl; - system(command.c_str()); + std::string command = "open " + latestReleaseUrl; + system(command.c_str()); #endif - } - catch (...) - { - ofLogError("Failed to open browser"); + } + catch (...) + { + ofLogError("Failed to open browser"); + } } } } + catch (...) + { + ofLogError("An exception occured while checking latest version of EmotiBit software"); + } } - catch (...) + else { - ofLogError("An exception occured while checking latest version of EmotiBit software"); + ofLogNotice() << "Internet access not detected. Skipping version check."; } } diff --git a/src/ofxEmotiBitVersion.h b/src/ofxEmotiBitVersion.h index 0b35488..16c2343 100644 --- a/src/ofxEmotiBitVersion.h +++ b/src/ofxEmotiBitVersion.h @@ -3,7 +3,7 @@ #include "ofMain.h" -const std::string ofxEmotiBitVersion = "1.8.1"; +const std::string ofxEmotiBitVersion = "1.8.1.fix-swVersionChecker.0"; static const char SOFTWARE_VERSION_PREFIX = 'v'; From dd17f0a4471224bbb6ff190b74379b8fab295930 Mon Sep 17 00:00:00 2001 From: Nitin Nair Date: Thu, 20 Apr 2023 11:30:21 -0400 Subject: [PATCH 02/13] comment update --- EmotiBitOscilloscope/src/ofApp.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/EmotiBitOscilloscope/src/ofApp.cpp b/EmotiBitOscilloscope/src/ofApp.cpp index b2cafbb..caa47b8 100644 --- a/EmotiBitOscilloscope/src/ofApp.cpp +++ b/EmotiBitOscilloscope/src/ofApp.cpp @@ -81,7 +81,7 @@ void ofApp::checkLatestSwVersion() bool isNetworkAvailable = false; // -n specifies number of tries. we are going to try to detect internet connection by sending 1 packet // -w specifies timeout period in mS. We are going to wait for a maximum of 3 seconds for a ping response. - // the IP 8.8.8.8 is google's public DNS. We are using ping with a specific IP as that removes undefined wait periods associated with DNS resolution. + // the IP 8.8.8.8 is google's public DNS. We are using ping with a specific IP as that removes undefined wait periods associated with DNS resolution. More details: https://developers.google.com/speed/public-dns std::string command = "ping -n 1 -w 3000 8.8.8.8"; std::string pingResponse = ""; char buffer[200]; @@ -146,6 +146,7 @@ void ofApp::checkLatestSwVersion() // system call to curl std::string latestReleaseUrl = "https://github.com/EmotiBit/ofxEmotiBit/releases/latest"; std::string latestReleaseApiRequest = "https://api.github.com/repos/EmotiBit/ofxEmotiBit/releases/latest"; + // Calling curl with a 3 second timeout. Timeout tested working with curl version v8.0.1. Older versions of curl have shown a "disregard" for the timeout. std::string command = "curl --connect-timeout 3 " + latestReleaseApiRequest; std::string response = ""; char buffer[200]; From 9c115c92fa40543b43dcef2fc658f98434941fde Mon Sep 17 00:00:00 2001 From: Nitin Nair Date: Thu, 20 Apr 2023 11:31:04 -0400 Subject: [PATCH 03/13] removed creation of version file --- EmotiBitOscilloscope/src/ofApp.cpp | 1 - src/ofxEmotiBitVersion.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/EmotiBitOscilloscope/src/ofApp.cpp b/EmotiBitOscilloscope/src/ofApp.cpp index caa47b8..b43ef68 100644 --- a/EmotiBitOscilloscope/src/ofApp.cpp +++ b/EmotiBitOscilloscope/src/ofApp.cpp @@ -13,7 +13,6 @@ void ofApp::setup() { ofBackground(255, 255, 255); checkLatestSwVersion(); ofSetLogLevel(OF_LOG_NOTICE); - writeOfxEmotiBitVersionFile(); setTypeTagPlotAttributes(); //saveEmotiBitCommSettings(); loadEmotiBitCommSettings(); diff --git a/src/ofxEmotiBitVersion.h b/src/ofxEmotiBitVersion.h index 16c2343..c2d21ac 100644 --- a/src/ofxEmotiBitVersion.h +++ b/src/ofxEmotiBitVersion.h @@ -3,7 +3,7 @@ #include "ofMain.h" -const std::string ofxEmotiBitVersion = "1.8.1.fix-swVersionChecker.0"; +const std::string ofxEmotiBitVersion = "1.8.1.fix-swVersionChecker.1"; static const char SOFTWARE_VERSION_PREFIX = 'v'; From a88f19e8cbb94f99b9ca91daad16dd183731f2f9 Mon Sep 17 00:00:00 2001 From: Nitin Nair Date: Thu, 20 Apr 2023 11:32:15 -0400 Subject: [PATCH 04/13] minor typo in console output fixed. --- EmotiBitOscilloscope/src/ofApp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EmotiBitOscilloscope/src/ofApp.cpp b/EmotiBitOscilloscope/src/ofApp.cpp index b43ef68..5189e37 100644 --- a/EmotiBitOscilloscope/src/ofApp.cpp +++ b/EmotiBitOscilloscope/src/ofApp.cpp @@ -84,7 +84,7 @@ void ofApp::checkLatestSwVersion() std::string command = "ping -n 1 -w 3000 8.8.8.8"; std::string pingResponse = ""; char buffer[200]; - ofLogNotice() << "Trying to dtect internet access"; + ofLogNotice() << "Trying to detect internet access"; try { #if defined (TARGET_OSX) || defined (TARGET_LINUX) From 444f5b2a7f96cd5c9a566f77f415c6ea46631f5e Mon Sep 17 00:00:00 2001 From: Nitin Nair Date: Thu, 30 Nov 2023 14:02:24 -0500 Subject: [PATCH 05/13] testPing response based on sent and received packets --- EmotiBitOscilloscope/src/ofApp.cpp | 137 ++++++++++++++++++++++++----- EmotiBitOscilloscope/src/ofApp.h | 1 + src/ofxEmotiBitVersion.h | 2 +- 3 files changed, 116 insertions(+), 24 deletions(-) diff --git a/EmotiBitOscilloscope/src/ofApp.cpp b/EmotiBitOscilloscope/src/ofApp.cpp index 5189e37..168d39f 100644 --- a/EmotiBitOscilloscope/src/ofApp.cpp +++ b/EmotiBitOscilloscope/src/ofApp.cpp @@ -74,6 +74,99 @@ void ofApp::update() { updateMenuButtons(); } +bool ofApp::testPingResponse(std::string pingResponse) +{ + bool isNetworkAvailable = false; + std::string searchKey("Ping statistics"); +#if not defined (TARGET_OSX) || defined (TARGET_LINUX) + searchKey = "ping statistics"; // define search key for linux/macOS +#endif + int keyLoc = pingResponse.find(searchKey); + const char statDelimiter = '\n'; + + // extract statistsics from ping response + int statStartLoc = pingResponse.find(statDelimiter, keyLoc) + 1; + int statEndLoc = pingResponse.find(statDelimiter, statStartLoc) + 1; + std::string stats = pingResponse.substr(statStartLoc, (statEndLoc - statStartLoc)); + const char commaDelimiter = ','; + int commaLoc = stats.find(commaDelimiter); + const char equalDelimiter = '='; // used only in Windows parsing + struct ParsedStats { + int packetsSent = 0; + int packetsRec = 0; + bool gotSentStats = false; + }parsedStats; + + // Parse ping response + + // LINUX/MACOS + /* A successful ping response + ----------------------------- + PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. + 64 bytes from 8.8.8.8: icmp_seq=1 ttl=54 time=18.2 ms + 64 bytes from 8.8.8.8: icmp_seq=2 ttl=54 time=25.7 ms + 64 bytes from 8.8.8.8: icmp_seq=3 ttl=54 time=14.5 ms + + --- 8.8.8.8 ping statistics --- + 3 packets transmitted, 3 received, 0% packet loss, time 2003ms + rtt min/avg/max/mdev = 14.503/19.471/25.685/4.649 ms + */ + + // WINDOWS + // A successful ping response contains a sumary of round trip times. We are using that do determine if ping was successful + /* A successful ping response + ------------------------------ + Pinging 8.8.8.8 with 32 bytes of data: + Reply from 8.8.8.8: bytes = 32 time = 18ms TTL = 119 + + Ping statistics for 8.8.8.8 : + Packets : Sent = 1, Received = 1, Lost = 0 (0 % loss), + Approximate round trip times in milli - seconds : + Minimum = 18ms, Maximum = 18ms, Average = 18ms + */ + + while (commaLoc != string::npos) + { +#if not defined (TARGET_OSX) || defined (TARGET_LINUX) + std::string numExtract = stats.substr(0, stats.find("packets")); + if (!parsedStats.gotSentStats) + { + parsedStats.packetsSent = atoi(numExtract.c_str()); + parsedStats.gotSentStats = true; // extract packetsRec next + + } + else + { + parsedStats.packetsRec = atoi(numExtract.c_str()); + break; + } +#else + int equalLoc = stats.find(equalDelimiter); + std::string numExtract = stats.substr(equalLoc + 1, commaLoc); + if (parsedStats.gotSentStats == 0) + { + parsedStats.packetsSent = atoi(numExtract.c_str()); + parsedStats.gotSentStats = true; // extract packetsRec next + + } + else + { + parsedStats.packetsRec = atoi(numExtract.c_str()); + parsedStats.gotSentStats = true; // extract packetsRec next + break; + } +#endif + stats.erase(stats.begin(), stats.begin() + commaLoc + 1); + commaLoc = stats.find(commaDelimiter); + } + + if (parsedStats.packetsSent > 0 && (parsedStats.packetsRec == parsedStats.packetsSent)) + { + isNetworkAvailable = true; + } + return isNetworkAvailable; +} + void ofApp::checkLatestSwVersion() { @@ -116,29 +209,27 @@ void ofApp::checkLatestSwVersion() } ofLogNotice() << pingResponse.c_str(); - // A successful ping response contains a sumary of round trip times. We are using that do determine if ping was successful - /* A successful ping response - ------------------------------ - Pinging 8.8.8.8 with 32 bytes of data: - Reply from 8.8.8.8: bytes = 32 time = 18ms TTL = 119 - - Ping statistics for 8.8.8.8 : - Packets : Sent = 1, Received = 1, Lost = 0 (0 % loss), - Approximate round trip times in milli - seconds : - Minimum = 18ms, Maximum = 18ms, Average = 18ms - */ - if (pingResponse.find("Approximate round trip times") != std::string::npos) - { - // substring found! - ofLogNotice() << "internet access detected"; - isNetworkAvailable = true; - } - else - { - // failed - ofLogNotice() << "Failed to ping IP"; - } - + std::string testString = + "PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.\n" + "64 bytes from 8.8.8.8: icmp_seq = 1 ttl = 54 time = 18.2 ms\n" + "64 bytes from 8.8.8.8 : icmp_seq = 2 ttl = 54 time = 25.7 ms\n" + "64 bytes from 8.8.8.8 : icmp_seq = 3 ttl = 54 time = 14.5 ms\n" + "-- - 8.8.8.8 ping statistics-- -\n" + "3 packets transmitted, 3 received, 0 % packet loss, time 2003ms\n" + "rtt min / avg / max / mdev = 14.503 / 19.471 / 25.685 / 4.649 ms"; + + /*testString = + "Pinging 8.8.8.8 with 32 bytes of data:\n" + "Reply from 8.8.8.8: bytes = 32 time = 20ms TTL = 54\n" + "Reply from 8.8.8.8 : bytes = 32 time = 17ms TTL = 54\n" + "Reply from 8.8.8.8 : bytes = 32 time = 15ms TTL = 54\n" + "Ping statistics for 8.8.8.8 :\n" + "Packets : Sent = 3, Received = 3, Lost = 0 (0 % loss),\n" + "Approximate round trip times in milli - seconds :\n" + "Minimum = 15ms, Maximum = 20ms, Average = 17ms";*/ + + isNetworkAvailable = testPingResponse(testString); + //isNetworkAvailable = testPingResponse(pingResponse); if (isNetworkAvailable) { bool newVersionAvailable = false; diff --git a/EmotiBitOscilloscope/src/ofApp.h b/EmotiBitOscilloscope/src/ofApp.h index caca2a9..b4c9794 100644 --- a/EmotiBitOscilloscope/src/ofApp.h +++ b/EmotiBitOscilloscope/src/ofApp.h @@ -84,6 +84,7 @@ class ofApp : public ofBaseApp { // ToDo: This function is marked to be removed when we complete our move to xmlFileSettings. void updateTypeTagList(); void checkLatestSwVersion(); + bool testPingResponse(std::string pingResponse); void loadEmotiBitCommSettings(string settingsFilePath = "emotibitCommSettings.json", bool absolutePath = false); void saveEmotiBitCommSettings(string settingsFilePath = "emotibitCommSettings.json", bool absolutePath = false, bool pretty = true); diff --git a/src/ofxEmotiBitVersion.h b/src/ofxEmotiBitVersion.h index c2d21ac..e1d98bc 100644 --- a/src/ofxEmotiBitVersion.h +++ b/src/ofxEmotiBitVersion.h @@ -3,7 +3,7 @@ #include "ofMain.h" -const std::string ofxEmotiBitVersion = "1.8.1.fix-swVersionChecker.1"; +const std::string ofxEmotiBitVersion = "1.8.1.fix-swVersionChecker.2"; static const char SOFTWARE_VERSION_PREFIX = 'v'; From 08864f613b5ef7504a3cff74415ef638fecd237d Mon Sep 17 00:00:00 2001 From: Nitin Nair Date: Mon, 4 Dec 2023 15:10:40 -0500 Subject: [PATCH 06/13] moved version checker code to separate file --- src/SoftwareVersionChecker.cpp | 240 +++++++++++++++++++++++++++++++++ src/SoftwareVersionChecker.h | 9 ++ 2 files changed, 249 insertions(+) create mode 100644 src/SoftwareVersionChecker.cpp create mode 100644 src/SoftwareVersionChecker.h diff --git a/src/SoftwareVersionChecker.cpp b/src/SoftwareVersionChecker.cpp new file mode 100644 index 0000000..2626535 --- /dev/null +++ b/src/SoftwareVersionChecker.cpp @@ -0,0 +1,240 @@ +#include "SoftwareVersionChecker.h" + + +void SoftwareVersionChecker::checkLatestVersion() +{ + bool newVersionAvailable = false; + // system call to curl + std::string latestReleaseUrl = "https://github.com/EmotiBit/ofxEmotiBit/releases/latest"; + std::string latestReleaseApiRequest = "https://api.github.com/repos/EmotiBit/ofxEmotiBit/releases/latest"; + std::string command = "curl " + latestReleaseApiRequest; + std::string response = ""; + char buffer[200]; + bool exceptionOccured = false; + try + { +#if defined (TARGET_OSX) || defined (TARGET_LINUX) + FILE* pipe = popen(command.c_str(), "r"); // returns NULL on fail. refer: https://man7.org/linux/man-pages/man3/popen.3.html#RETURN_VALUE +#else + FILE* pipe = _popen(command.c_str(), "r"); // returns NULL on fail. refer: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/popen-wpopen?view=msvc-170#return-value +#endif + if (pipe != NULL) + { + try + { + while (fgets(buffer, sizeof buffer, pipe) != NULL) + { + response += buffer; + } + } + catch (...) { + try + { +#if defined (TARGET_OSX) || defined (TARGET_LINUX) + pclose(pipe); +#else + _pclose(pipe); +#endif + } + catch (...) + { + ofLogError("Failed to close pipe"); + } + ofLog(OF_LOG_ERROR, "An exception occured while executing curl"); + exceptionOccured = true; + } + try + { +#if defined (TARGET_OSX) || defined (TARGET_LINUX) + pclose(pipe); +#else + _pclose(pipe); +#endif + } + catch (...) + { + ofLogError("Failed to close pipe"); + } + } + else + { + ofLog(OF_LOG_ERROR, "Failed to check for latest version. Failed to open pipe"); + exceptionOccured = true; + } + } + catch (...) + { + ofLogError("Failed to open pipe"); + exceptionOccured = true; + } + try + { + if (!exceptionOccured & response != "") + { + ofxJSONElement jsonResponse; + if (jsonResponse.parse(response)) + { + //ofLog(OF_LOG_NOTICE, jsonResponse.getRawString(true)); // uncomment to print curl output + std::string latestAvailableVersion = jsonResponse["tag_name"].asString(); + ofLogNotice("Latest version") << latestAvailableVersion; + int swVerPrefixLoc = latestAvailableVersion.find(SOFTWARE_VERSION_PREFIX); + if (swVerPrefixLoc != std::string::npos) + { + latestAvailableVersion.erase(swVerPrefixLoc, 1); // remove leading version char "v" + } + // compare with ofxEmotiBitVersion + std::vector latestVersionSplit = ofSplitString(latestAvailableVersion, "."); + std::vector currentVersionSplit = ofSplitString(ofxEmotiBitVersion, "."); + int versionLength = latestVersionSplit.size() < currentVersionSplit.size() ? latestVersionSplit.size() : currentVersionSplit.size(); + if (versionLength) + { + for (int i = 0; i < versionLength; i++) + { + int latest = ofToInt(latestVersionSplit.at(i)); + int current = ofToInt(currentVersionSplit.at(i)); + if (latest == current) + { + // need to check minor version + continue; + } + else if (latest < current) + { + // current version higher than latest available + break; + } + else // latest > current + { + // new version available + newVersionAvailable = true; + break; + } + } + } + else + { + ofLogError("Failed to parse version string"); + } + } + else + { + ofLog(OF_LOG_ERROR, "unexpected curl response"); + } + // If newer version available, display alert message + if (newVersionAvailable) + { + // create alert dialog box + ofSystemAlertDialog("A new version of EmotiBit Software is available!"); + // open browser to latest version + try + { +#ifdef TARGET_WIN32 + std::string command = "start " + latestReleaseUrl; + system(command.c_str()); +#else + std::string command = "open " + latestReleaseUrl; + system(command.c_str()); +#endif + } + catch (...) + { + ofLogError("Failed to open browser"); + } + } + } + } + catch (...) + { + ofLogError("An exception occured while checking latest version of EmotiBit software"); + } +} + +bool SoftwareVersionChecker::testPingresponse(std::string pingResponse) +{ + bool isNetworkAvailable = false; + std::string searchKey("Ping statistics"); +#if not defined (TARGET_OSX) || defined (TARGET_LINUX) + searchKey = "ping statistics"; // define search key for linux/macOS +#endif + int keyLoc = pingResponse.find(searchKey); + const char statDelimiter = '\n'; + + // extract statistsics from ping response + int statStartLoc = pingResponse.find(statDelimiter, keyLoc) + 1; + int statEndLoc = pingResponse.find(statDelimiter, statStartLoc) + 1; + std::string stats = pingResponse.substr(statStartLoc, (statEndLoc - statStartLoc)); + const char commaDelimiter = ','; + int commaLoc = stats.find(commaDelimiter); + const char equalDelimiter = '='; // used only in Windows parsing + struct ParsedStats { + int packetsSent = 0; + int packetsRec = 0; + bool gotSentStats = false; + }parsedStats; + + // Parse ping response + + // LINUX/MACOS + /* A successful ping response + ----------------------------- + PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. + 64 bytes from 8.8.8.8: icmp_seq=1 ttl=54 time=18.2 ms + 64 bytes from 8.8.8.8: icmp_seq=2 ttl=54 time=25.7 ms + 64 bytes from 8.8.8.8: icmp_seq=3 ttl=54 time=14.5 ms + --- 8.8.8.8 ping statistics --- + 3 packets transmitted, 3 received, 0% packet loss, time 2003ms + rtt min/avg/max/mdev = 14.503/19.471/25.685/4.649 ms + */ + + // WINDOWS + // A successful ping response contains a sumary of round trip times. We are using that do determine if ping was successful + /* A successful ping response + ------------------------------ + Pinging 8.8.8.8 with 32 bytes of data: + Reply from 8.8.8.8: bytes = 32 time = 18ms TTL = 119 + Ping statistics for 8.8.8.8 : + Packets : Sent = 1, Received = 1, Lost = 0 (0 % loss), + Approximate round trip times in milli - seconds : + Minimum = 18ms, Maximum = 18ms, Average = 18ms + */ + + while (commaLoc != string::npos) + { +#if not defined (TARGET_OSX) || defined (TARGET_LINUX) + std::string numExtract = stats.substr(0, stats.find("packets")); + if (!parsedStats.gotSentStats) + { + parsedStats.packetsSent = atoi(numExtract.c_str()); + parsedStats.gotSentStats = true; // extract packetsRec next + + } + else + { + parsedStats.packetsRec = atoi(numExtract.c_str()); + break; + } +#else + int equalLoc = stats.find(equalDelimiter); + std::string numExtract = stats.substr(equalLoc + 1, commaLoc); + if (parsedStats.gotSentStats == 0) + { + parsedStats.packetsSent = atoi(numExtract.c_str()); + parsedStats.gotSentStats = true; // extract packetsRec next + + } + else + { + parsedStats.packetsRec = atoi(numExtract.c_str()); + parsedStats.gotSentStats = true; // extract packetsRec next + break; + } +#endif + stats.erase(stats.begin(), stats.begin() + commaLoc + 1); + commaLoc = stats.find(commaDelimiter); + } + + if (parsedStats.packetsSent > 0 && (parsedStats.packetsRec == parsedStats.packetsSent)) + { + isNetworkAvailable = true; + } + return isNetworkAvailable; +} \ No newline at end of file diff --git a/src/SoftwareVersionChecker.h b/src/SoftwareVersionChecker.h new file mode 100644 index 0000000..dcb40f9 --- /dev/null +++ b/src/SoftwareVersionChecker.h @@ -0,0 +1,9 @@ +#include "ofMain.h" +#include "ofxEmotiBitVersion.h" +#include "ofxJSON.h" + +namespace SoftwareVersionChecker +{ + void checkLatestVersion(); + bool testPingresponse(std::string pingResponse); +} \ No newline at end of file From 21eabb8d78be7451694cfa72fd681f89d3a6c80c Mon Sep 17 00:00:00 2001 From: Nitin Nair Date: Mon, 4 Dec 2023 15:18:21 -0500 Subject: [PATCH 07/13] compiling version checker --- src/SoftwareVersionChecker.cpp | 294 ++++++++++++++++++++------------- 1 file changed, 181 insertions(+), 113 deletions(-) diff --git a/src/SoftwareVersionChecker.cpp b/src/SoftwareVersionChecker.cpp index 2626535..6a0147a 100644 --- a/src/SoftwareVersionChecker.cpp +++ b/src/SoftwareVersionChecker.cpp @@ -3,31 +3,108 @@ void SoftwareVersionChecker::checkLatestVersion() { - bool newVersionAvailable = false; - // system call to curl - std::string latestReleaseUrl = "https://github.com/EmotiBit/ofxEmotiBit/releases/latest"; - std::string latestReleaseApiRequest = "https://api.github.com/repos/EmotiBit/ofxEmotiBit/releases/latest"; - std::string command = "curl " + latestReleaseApiRequest; - std::string response = ""; + bool isNetworkAvailable = false; + // -n specifies number of tries. we are going to try to detect internet connection by sending 1 packet + // -w specifies timeout period in mS. We are going to wait for a maximum of 3 seconds for a ping response. + // the IP 8.8.8.8 is google's public DNS. We are using ping with a specific IP as that removes undefined wait periods associated with DNS resolution. More details: https://developers.google.com/speed/public-dns + std::string command = "ping -n 1 -w 3000 8.8.8.8"; + std::string pingResponse = ""; char buffer[200]; - bool exceptionOccured = false; + ofLogNotice() << "Trying to detect internet access"; try { #if defined (TARGET_OSX) || defined (TARGET_LINUX) FILE* pipe = popen(command.c_str(), "r"); // returns NULL on fail. refer: https://man7.org/linux/man-pages/man3/popen.3.html#RETURN_VALUE #else FILE* pipe = _popen(command.c_str(), "r"); // returns NULL on fail. refer: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/popen-wpopen?view=msvc-170#return-value -#endif +#endif if (pipe != NULL) { - try + while (fgets(buffer, sizeof buffer, pipe) != NULL) + { + pingResponse += buffer; + } +#if defined (TARGET_OSX) || defined (TARGET_LINUX) + pclose(pipe); +#else + _pclose(pipe); +#endif + } + else + { + ofLogNotice() << "Failed to open pipe. ping failed"; + } +} + catch (...) + { + ofLogError() << "Ping failed"; + } + ofLogNotice() << pingResponse.c_str(); + + std::string testString = + "PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.\n" + "64 bytes from 8.8.8.8: icmp_seq = 1 ttl = 54 time = 18.2 ms\n" + "64 bytes from 8.8.8.8 : icmp_seq = 2 ttl = 54 time = 25.7 ms\n" + "64 bytes from 8.8.8.8 : icmp_seq = 3 ttl = 54 time = 14.5 ms\n" + "-- - 8.8.8.8 ping statistics-- -\n" + "3 packets transmitted, 3 received, 0 % packet loss, time 2003ms\n" + "rtt min / avg / max / mdev = 14.503 / 19.471 / 25.685 / 4.649 ms"; + + /*testString = + "Pinging 8.8.8.8 with 32 bytes of data:\n" + "Reply from 8.8.8.8: bytes = 32 time = 20ms TTL = 54\n" + "Reply from 8.8.8.8 : bytes = 32 time = 17ms TTL = 54\n" + "Reply from 8.8.8.8 : bytes = 32 time = 15ms TTL = 54\n" + "Ping statistics for 8.8.8.8 :\n" + "Packets : Sent = 3, Received = 3, Lost = 0 (0 % loss),\n" + "Approximate round trip times in milli - seconds :\n" + "Minimum = 15ms, Maximum = 20ms, Average = 17ms";*/ + + isNetworkAvailable = SoftwareVersionChecker::testPingresponse(testString); + //isNetworkAvailable = testPingResponse(pingResponse); + if (isNetworkAvailable) + { + bool newVersionAvailable = false; + // system call to curl + std::string latestReleaseUrl = "https://github.com/EmotiBit/ofxEmotiBit/releases/latest"; + std::string latestReleaseApiRequest = "https://api.github.com/repos/EmotiBit/ofxEmotiBit/releases/latest"; + // Calling curl with a 3 second timeout. Timeout tested working with curl version v8.0.1. Older versions of curl have shown a "disregard" for the timeout. + std::string command = "curl --connect-timeout 3 " + latestReleaseApiRequest; + std::string response = ""; + char buffer[200]; + bool exceptionOccured = false; + try + { +#if defined (TARGET_OSX) || defined (TARGET_LINUX) + FILE* pipe = popen(command.c_str(), "r"); // returns NULL on fail. refer: https://man7.org/linux/man-pages/man3/popen.3.html#RETURN_VALUE +#else + FILE* pipe = _popen(command.c_str(), "r"); // returns NULL on fail. refer: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/popen-wpopen?view=msvc-170#return-value +#endif + if (pipe != NULL) { - while (fgets(buffer, sizeof buffer, pipe) != NULL) + try { - response += buffer; + while (fgets(buffer, sizeof buffer, pipe) != NULL) + { + response += buffer; + } + } + catch (...) { + try + { +#if defined (TARGET_OSX) || defined (TARGET_LINUX) + pclose(pipe); +#else + _pclose(pipe); +#endif + } + catch (...) + { + ofLogError("Failed to close pipe"); + } + ofLog(OF_LOG_ERROR, "An exception occured while executing curl"); + exceptionOccured = true; } - } - catch (...) { try { #if defined (TARGET_OSX) || defined (TARGET_LINUX) @@ -40,137 +117,106 @@ void SoftwareVersionChecker::checkLatestVersion() { ofLogError("Failed to close pipe"); } - ofLog(OF_LOG_ERROR, "An exception occured while executing curl"); - exceptionOccured = true; } - try - { -#if defined (TARGET_OSX) || defined (TARGET_LINUX) - pclose(pipe); -#else - _pclose(pipe); -#endif - } - catch (...) + else { - ofLogError("Failed to close pipe"); + ofLog(OF_LOG_ERROR, "Failed to check for latest version. Failed to open pipe"); + exceptionOccured = true; } } - else + catch (...) { - ofLog(OF_LOG_ERROR, "Failed to check for latest version. Failed to open pipe"); + ofLogError("Failed to open pipe"); exceptionOccured = true; } - } - catch (...) - { - ofLogError("Failed to open pipe"); - exceptionOccured = true; - } - try - { - if (!exceptionOccured & response != "") + try { - ofxJSONElement jsonResponse; - if (jsonResponse.parse(response)) + if (!exceptionOccured & response != "") { - //ofLog(OF_LOG_NOTICE, jsonResponse.getRawString(true)); // uncomment to print curl output - std::string latestAvailableVersion = jsonResponse["tag_name"].asString(); - ofLogNotice("Latest version") << latestAvailableVersion; - int swVerPrefixLoc = latestAvailableVersion.find(SOFTWARE_VERSION_PREFIX); - if (swVerPrefixLoc != std::string::npos) - { - latestAvailableVersion.erase(swVerPrefixLoc, 1); // remove leading version char "v" - } - // compare with ofxEmotiBitVersion - std::vector latestVersionSplit = ofSplitString(latestAvailableVersion, "."); - std::vector currentVersionSplit = ofSplitString(ofxEmotiBitVersion, "."); - int versionLength = latestVersionSplit.size() < currentVersionSplit.size() ? latestVersionSplit.size() : currentVersionSplit.size(); - if (versionLength) + ofxJSONElement jsonResponse; + if (jsonResponse.parse(response)) { - for (int i = 0; i < versionLength; i++) + //ofLog(OF_LOG_NOTICE, jsonResponse.getRawString(true)); // uncomment to print curl output + std::string latestAvailableVersion = jsonResponse["tag_name"].asString(); + ofLogNotice("Latest version") << latestAvailableVersion; + int swVerPrefixLoc = latestAvailableVersion.find(SOFTWARE_VERSION_PREFIX); + if (swVerPrefixLoc != std::string::npos) { - int latest = ofToInt(latestVersionSplit.at(i)); - int current = ofToInt(currentVersionSplit.at(i)); - if (latest == current) - { - // need to check minor version - continue; - } - else if (latest < current) - { - // current version higher than latest available - break; - } - else // latest > current + latestAvailableVersion.erase(swVerPrefixLoc, 1); // remove leading version char "v" + } + // compare with ofxEmotiBitVersion + std::vector latestVersionSplit = ofSplitString(latestAvailableVersion, "."); + std::vector currentVersionSplit = ofSplitString(ofxEmotiBitVersion, "."); + int versionLength = latestVersionSplit.size() < currentVersionSplit.size() ? latestVersionSplit.size() : currentVersionSplit.size(); + if (versionLength) + { + for (int i = 0; i < versionLength; i++) { - // new version available - newVersionAvailable = true; - break; + int latest = ofToInt(latestVersionSplit.at(i)); + int current = ofToInt(currentVersionSplit.at(i)); + if (latest == current) + { + // need to check minor version + continue; + } + else if (latest < current) + { + // current version higher than latest available + break; + } + else // latest > current + { + // new version available + newVersionAvailable = true; + break; + } } } + else + { + ofLogError("Failed to parse version string"); + } } else { - ofLogError("Failed to parse version string"); + ofLog(OF_LOG_ERROR, "unexpected curl response"); } - } - else - { - ofLog(OF_LOG_ERROR, "unexpected curl response"); - } - // If newer version available, display alert message - if (newVersionAvailable) - { - // create alert dialog box - ofSystemAlertDialog("A new version of EmotiBit Software is available!"); - // open browser to latest version - try + // If newer version available, display alert message + if (newVersionAvailable) { + // create alert dialog box + ofSystemAlertDialog("A new version of EmotiBit Software is available!"); + // open browser to latest version + try + { #ifdef TARGET_WIN32 - std::string command = "start " + latestReleaseUrl; - system(command.c_str()); + std::string command = "start " + latestReleaseUrl; + system(command.c_str()); #else - std::string command = "open " + latestReleaseUrl; - system(command.c_str()); + std::string command = "open " + latestReleaseUrl; + system(command.c_str()); #endif + } + catch (...) + { + ofLogError("Failed to open browser"); + } } - catch (...) - { - ofLogError("Failed to open browser"); - } - } + } + } + catch (...) + { + ofLogError("An exception occured while checking latest version of EmotiBit software"); } } - catch (...) + else { - ofLogError("An exception occured while checking latest version of EmotiBit software"); + ofLogNotice() << "Internet access not detected. Skipping version check."; } } bool SoftwareVersionChecker::testPingresponse(std::string pingResponse) { - bool isNetworkAvailable = false; - std::string searchKey("Ping statistics"); -#if not defined (TARGET_OSX) || defined (TARGET_LINUX) - searchKey = "ping statistics"; // define search key for linux/macOS -#endif - int keyLoc = pingResponse.find(searchKey); - const char statDelimiter = '\n'; - - // extract statistsics from ping response - int statStartLoc = pingResponse.find(statDelimiter, keyLoc) + 1; - int statEndLoc = pingResponse.find(statDelimiter, statStartLoc) + 1; - std::string stats = pingResponse.substr(statStartLoc, (statEndLoc - statStartLoc)); - const char commaDelimiter = ','; - int commaLoc = stats.find(commaDelimiter); - const char equalDelimiter = '='; // used only in Windows parsing - struct ParsedStats { - int packetsSent = 0; - int packetsRec = 0; - bool gotSentStats = false; - }parsedStats; - // Parse ping response // LINUX/MACOS @@ -196,6 +242,28 @@ bool SoftwareVersionChecker::testPingresponse(std::string pingResponse) Approximate round trip times in milli - seconds : Minimum = 18ms, Maximum = 18ms, Average = 18ms */ + bool isNetworkAvailable = false; + std::string searchKey("Ping statistics"); +#if not defined (TARGET_OSX) || defined (TARGET_LINUX) + searchKey = "ping statistics"; // define search key for linux/macOS +#endif + int keyLoc = pingResponse.find(searchKey); + const char statDelimiter = '\n'; + + // extract statistsics from ping response + int statStartLoc = pingResponse.find(statDelimiter, keyLoc) + 1; + int statEndLoc = pingResponse.find(statDelimiter, statStartLoc) + 1; + std::string stats = pingResponse.substr(statStartLoc, (statEndLoc - statStartLoc)); + const char commaDelimiter = ','; + int commaLoc = stats.find(commaDelimiter); + const char equalDelimiter = '='; // used only in Windows parsing + struct ParsedStats { + int packetsSent = 0; + int packetsRec = 0; + bool gotSentStats = false; + }parsedStats; + + while (commaLoc != string::npos) { From 1c5941371ec009f0593576d1c3bf0afb1e85150c Mon Sep 17 00:00:00 2001 From: Nitin Nair Date: Mon, 4 Dec 2023 18:07:55 -0500 Subject: [PATCH 08/13] version checker moved to separate file. tested working --- EmotiBitOscilloscope/src/ofApp.cpp | 310 +---------------------------- EmotiBitOscilloscope/src/ofApp.h | 3 +- src/SoftwareVersionChecker.cpp | 113 ++++------- src/SoftwareVersionChecker.h | 11 +- 4 files changed, 48 insertions(+), 389 deletions(-) diff --git a/EmotiBitOscilloscope/src/ofApp.cpp b/EmotiBitOscilloscope/src/ofApp.cpp index 168d39f..0fc80cd 100644 --- a/EmotiBitOscilloscope/src/ofApp.cpp +++ b/EmotiBitOscilloscope/src/ofApp.cpp @@ -2,6 +2,7 @@ #include "ofxBiquadFilter.h" #include + //-------------------------------------------------------------- void ofApp::setup() { ofLogToConsole(); @@ -11,7 +12,7 @@ void ofApp::setup() { #endif ofSetFrameRate(30); ofBackground(255, 255, 255); - checkLatestSwVersion(); + SoftwareVersionChecker::checkLatestVersion(); ofSetLogLevel(OF_LOG_NOTICE); setTypeTagPlotAttributes(); //saveEmotiBitCommSettings(); @@ -74,314 +75,7 @@ void ofApp::update() { updateMenuButtons(); } -bool ofApp::testPingResponse(std::string pingResponse) -{ - bool isNetworkAvailable = false; - std::string searchKey("Ping statistics"); -#if not defined (TARGET_OSX) || defined (TARGET_LINUX) - searchKey = "ping statistics"; // define search key for linux/macOS -#endif - int keyLoc = pingResponse.find(searchKey); - const char statDelimiter = '\n'; - - // extract statistsics from ping response - int statStartLoc = pingResponse.find(statDelimiter, keyLoc) + 1; - int statEndLoc = pingResponse.find(statDelimiter, statStartLoc) + 1; - std::string stats = pingResponse.substr(statStartLoc, (statEndLoc - statStartLoc)); - const char commaDelimiter = ','; - int commaLoc = stats.find(commaDelimiter); - const char equalDelimiter = '='; // used only in Windows parsing - struct ParsedStats { - int packetsSent = 0; - int packetsRec = 0; - bool gotSentStats = false; - }parsedStats; - - // Parse ping response - - // LINUX/MACOS - /* A successful ping response - ----------------------------- - PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. - 64 bytes from 8.8.8.8: icmp_seq=1 ttl=54 time=18.2 ms - 64 bytes from 8.8.8.8: icmp_seq=2 ttl=54 time=25.7 ms - 64 bytes from 8.8.8.8: icmp_seq=3 ttl=54 time=14.5 ms - - --- 8.8.8.8 ping statistics --- - 3 packets transmitted, 3 received, 0% packet loss, time 2003ms - rtt min/avg/max/mdev = 14.503/19.471/25.685/4.649 ms - */ - - // WINDOWS - // A successful ping response contains a sumary of round trip times. We are using that do determine if ping was successful - /* A successful ping response - ------------------------------ - Pinging 8.8.8.8 with 32 bytes of data: - Reply from 8.8.8.8: bytes = 32 time = 18ms TTL = 119 - - Ping statistics for 8.8.8.8 : - Packets : Sent = 1, Received = 1, Lost = 0 (0 % loss), - Approximate round trip times in milli - seconds : - Minimum = 18ms, Maximum = 18ms, Average = 18ms - */ - - while (commaLoc != string::npos) - { -#if not defined (TARGET_OSX) || defined (TARGET_LINUX) - std::string numExtract = stats.substr(0, stats.find("packets")); - if (!parsedStats.gotSentStats) - { - parsedStats.packetsSent = atoi(numExtract.c_str()); - parsedStats.gotSentStats = true; // extract packetsRec next - - } - else - { - parsedStats.packetsRec = atoi(numExtract.c_str()); - break; - } -#else - int equalLoc = stats.find(equalDelimiter); - std::string numExtract = stats.substr(equalLoc + 1, commaLoc); - if (parsedStats.gotSentStats == 0) - { - parsedStats.packetsSent = atoi(numExtract.c_str()); - parsedStats.gotSentStats = true; // extract packetsRec next - - } - else - { - parsedStats.packetsRec = atoi(numExtract.c_str()); - parsedStats.gotSentStats = true; // extract packetsRec next - break; - } -#endif - stats.erase(stats.begin(), stats.begin() + commaLoc + 1); - commaLoc = stats.find(commaDelimiter); - } - - if (parsedStats.packetsSent > 0 && (parsedStats.packetsRec == parsedStats.packetsSent)) - { - isNetworkAvailable = true; - } - return isNetworkAvailable; -} - -void ofApp::checkLatestSwVersion() -{ - bool isNetworkAvailable = false; - // -n specifies number of tries. we are going to try to detect internet connection by sending 1 packet - // -w specifies timeout period in mS. We are going to wait for a maximum of 3 seconds for a ping response. - // the IP 8.8.8.8 is google's public DNS. We are using ping with a specific IP as that removes undefined wait periods associated with DNS resolution. More details: https://developers.google.com/speed/public-dns - std::string command = "ping -n 1 -w 3000 8.8.8.8"; - std::string pingResponse = ""; - char buffer[200]; - ofLogNotice() << "Trying to detect internet access"; - try - { -#if defined (TARGET_OSX) || defined (TARGET_LINUX) - FILE* pipe = popen(command.c_str(), "r"); // returns NULL on fail. refer: https://man7.org/linux/man-pages/man3/popen.3.html#RETURN_VALUE -#else - FILE* pipe = _popen(command.c_str(), "r"); // returns NULL on fail. refer: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/popen-wpopen?view=msvc-170#return-value -#endif - if (pipe != NULL) - { - while (fgets(buffer, sizeof buffer, pipe) != NULL) - { - pingResponse += buffer; - } - -#if defined (TARGET_OSX) || defined (TARGET_LINUX) - pclose(pipe); -#else - _pclose(pipe); -#endif - } - else - { - ofLogNotice() << "Failed to open pipe. ping failed"; - } - } - catch (...) - { - ofLogError() << "Ping failed"; - } - ofLogNotice() << pingResponse.c_str(); - - std::string testString = - "PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.\n" - "64 bytes from 8.8.8.8: icmp_seq = 1 ttl = 54 time = 18.2 ms\n" - "64 bytes from 8.8.8.8 : icmp_seq = 2 ttl = 54 time = 25.7 ms\n" - "64 bytes from 8.8.8.8 : icmp_seq = 3 ttl = 54 time = 14.5 ms\n" - "-- - 8.8.8.8 ping statistics-- -\n" - "3 packets transmitted, 3 received, 0 % packet loss, time 2003ms\n" - "rtt min / avg / max / mdev = 14.503 / 19.471 / 25.685 / 4.649 ms"; - - /*testString = - "Pinging 8.8.8.8 with 32 bytes of data:\n" - "Reply from 8.8.8.8: bytes = 32 time = 20ms TTL = 54\n" - "Reply from 8.8.8.8 : bytes = 32 time = 17ms TTL = 54\n" - "Reply from 8.8.8.8 : bytes = 32 time = 15ms TTL = 54\n" - "Ping statistics for 8.8.8.8 :\n" - "Packets : Sent = 3, Received = 3, Lost = 0 (0 % loss),\n" - "Approximate round trip times in milli - seconds :\n" - "Minimum = 15ms, Maximum = 20ms, Average = 17ms";*/ - - isNetworkAvailable = testPingResponse(testString); - //isNetworkAvailable = testPingResponse(pingResponse); - if (isNetworkAvailable) - { - bool newVersionAvailable = false; - // system call to curl - std::string latestReleaseUrl = "https://github.com/EmotiBit/ofxEmotiBit/releases/latest"; - std::string latestReleaseApiRequest = "https://api.github.com/repos/EmotiBit/ofxEmotiBit/releases/latest"; - // Calling curl with a 3 second timeout. Timeout tested working with curl version v8.0.1. Older versions of curl have shown a "disregard" for the timeout. - std::string command = "curl --connect-timeout 3 " + latestReleaseApiRequest; - std::string response = ""; - char buffer[200]; - bool exceptionOccured = false; - try - { -#if defined (TARGET_OSX) || defined (TARGET_LINUX) - FILE* pipe = popen(command.c_str(), "r"); // returns NULL on fail. refer: https://man7.org/linux/man-pages/man3/popen.3.html#RETURN_VALUE -#else - FILE* pipe = _popen(command.c_str(), "r"); // returns NULL on fail. refer: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/popen-wpopen?view=msvc-170#return-value -#endif - if (pipe != NULL) - { - try - { - while (fgets(buffer, sizeof buffer, pipe) != NULL) - { - response += buffer; - } - } - catch (...) { - try - { -#if defined (TARGET_OSX) || defined (TARGET_LINUX) - pclose(pipe); -#else - _pclose(pipe); -#endif - } - catch (...) - { - ofLogError("Failed to close pipe"); - } - ofLog(OF_LOG_ERROR, "An exception occured while executing curl"); - exceptionOccured = true; - } - try - { -#if defined (TARGET_OSX) || defined (TARGET_LINUX) - pclose(pipe); -#else - _pclose(pipe); -#endif - } - catch (...) - { - ofLogError("Failed to close pipe"); - } - } - else - { - ofLog(OF_LOG_ERROR, "Failed to check for latest version. Failed to open pipe"); - exceptionOccured = true; - } - } - catch (...) - { - ofLogError("Failed to open pipe"); - exceptionOccured = true; - } - try - { - if (!exceptionOccured & response != "") - { - ofxJSONElement jsonResponse; - if (jsonResponse.parse(response)) - { - //ofLog(OF_LOG_NOTICE, jsonResponse.getRawString(true)); // uncomment to print curl output - std::string latestAvailableVersion = jsonResponse["tag_name"].asString(); - ofLogNotice("Latest version") << latestAvailableVersion; - int swVerPrefixLoc = latestAvailableVersion.find(SOFTWARE_VERSION_PREFIX); - if (swVerPrefixLoc != std::string::npos) - { - latestAvailableVersion.erase(swVerPrefixLoc, 1); // remove leading version char "v" - } - // compare with ofxEmotiBitVersion - std::vector latestVersionSplit = ofSplitString(latestAvailableVersion, "."); - std::vector currentVersionSplit = ofSplitString(ofxEmotiBitVersion, "."); - int versionLength = latestVersionSplit.size() < currentVersionSplit.size() ? latestVersionSplit.size() : currentVersionSplit.size(); - if (versionLength) - { - for (int i = 0; i < versionLength; i++) - { - int latest = ofToInt(latestVersionSplit.at(i)); - int current = ofToInt(currentVersionSplit.at(i)); - if (latest == current) - { - // need to check minor version - continue; - } - else if (latest < current) - { - // current version higher than latest available - break; - } - else // latest > current - { - // new version available - newVersionAvailable = true; - break; - } - } - } - else - { - ofLogError("Failed to parse version string"); - } - } - else - { - ofLog(OF_LOG_ERROR, "unexpected curl response"); - } - // If newer version available, display alert message - if (newVersionAvailable) - { - // create alert dialog box - ofSystemAlertDialog("A new version of EmotiBit Software is available!"); - // open browser to latest version - try - { -#ifdef TARGET_WIN32 - std::string command = "start " + latestReleaseUrl; - system(command.c_str()); -#else - std::string command = "open " + latestReleaseUrl; - system(command.c_str()); -#endif - } - catch (...) - { - ofLogError("Failed to open browser"); - } - } - } - } - catch (...) - { - ofLogError("An exception occured while checking latest version of EmotiBit software"); - } - } - else - { - ofLogNotice() << "Internet access not detected. Skipping version check."; - } -} // ToDo: This function should be removed once we complete our move to xmlFileSettings void ofApp::setTypeTagPlotAttributes() diff --git a/EmotiBitOscilloscope/src/ofApp.h b/EmotiBitOscilloscope/src/ofApp.h index b4c9794..32f4d5c 100644 --- a/EmotiBitOscilloscope/src/ofApp.h +++ b/EmotiBitOscilloscope/src/ofApp.h @@ -17,6 +17,7 @@ #include "patchboard.h" #include "Periodizer.h" #include "ofxJSON.h" +#include "SoftwareVersionChecker.h" class ofApp : public ofBaseApp { public: @@ -83,8 +84,6 @@ class ofApp : public ofBaseApp { void updatePlotAttributeLists(std::string settingsFile = "ofxOscilloscopeSettings.xml"); // ToDo: This function is marked to be removed when we complete our move to xmlFileSettings. void updateTypeTagList(); - void checkLatestSwVersion(); - bool testPingResponse(std::string pingResponse); void loadEmotiBitCommSettings(string settingsFilePath = "emotibitCommSettings.json", bool absolutePath = false); void saveEmotiBitCommSettings(string settingsFilePath = "emotibitCommSettings.json", bool absolutePath = false, bool pretty = true); diff --git a/src/SoftwareVersionChecker.cpp b/src/SoftwareVersionChecker.cpp index 6a0147a..e16902e 100644 --- a/src/SoftwareVersionChecker.cpp +++ b/src/SoftwareVersionChecker.cpp @@ -7,7 +7,11 @@ void SoftwareVersionChecker::checkLatestVersion() // -n specifies number of tries. we are going to try to detect internet connection by sending 1 packet // -w specifies timeout period in mS. We are going to wait for a maximum of 3 seconds for a ping response. // the IP 8.8.8.8 is google's public DNS. We are using ping with a specific IP as that removes undefined wait periods associated with DNS resolution. More details: https://developers.google.com/speed/public-dns - std::string command = "ping -n 1 -w 3000 8.8.8.8"; +#if defined (TARGET_OSX) || defined (TARGET_LINUX) + std::string command = "ping -n 1 -t 1 8.8.8.8"; // ping 1 time with a total timeout of 1 second +#else + std::string command = "ping -n 1 -w 100 8.8.8.8"; // ping 1 time with 100ms max timeout for each try +#endif std::string pingResponse = ""; char buffer[200]; ofLogNotice() << "Trying to detect internet access"; @@ -41,27 +45,7 @@ void SoftwareVersionChecker::checkLatestVersion() } ofLogNotice() << pingResponse.c_str(); - std::string testString = - "PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.\n" - "64 bytes from 8.8.8.8: icmp_seq = 1 ttl = 54 time = 18.2 ms\n" - "64 bytes from 8.8.8.8 : icmp_seq = 2 ttl = 54 time = 25.7 ms\n" - "64 bytes from 8.8.8.8 : icmp_seq = 3 ttl = 54 time = 14.5 ms\n" - "-- - 8.8.8.8 ping statistics-- -\n" - "3 packets transmitted, 3 received, 0 % packet loss, time 2003ms\n" - "rtt min / avg / max / mdev = 14.503 / 19.471 / 25.685 / 4.649 ms"; - - /*testString = - "Pinging 8.8.8.8 with 32 bytes of data:\n" - "Reply from 8.8.8.8: bytes = 32 time = 20ms TTL = 54\n" - "Reply from 8.8.8.8 : bytes = 32 time = 17ms TTL = 54\n" - "Reply from 8.8.8.8 : bytes = 32 time = 15ms TTL = 54\n" - "Ping statistics for 8.8.8.8 :\n" - "Packets : Sent = 3, Received = 3, Lost = 0 (0 % loss),\n" - "Approximate round trip times in milli - seconds :\n" - "Minimum = 15ms, Maximum = 20ms, Average = 17ms";*/ - - isNetworkAvailable = SoftwareVersionChecker::testPingresponse(testString); - //isNetworkAvailable = testPingResponse(pingResponse); + isNetworkAvailable = SoftwareVersionChecker::testPingResponse(pingResponse); if (isNetworkAvailable) { bool newVersionAvailable = false; @@ -215,10 +199,11 @@ void SoftwareVersionChecker::checkLatestVersion() } } -bool SoftwareVersionChecker::testPingresponse(std::string pingResponse) +// ToDo: we can pass another parameter that controls the strictness of checking. Default is low, but a stricter check can be conducted from the dataParser. +// This way, if a weak check results in a false negative, a string check can still make the user aware of a newer software version +bool SoftwareVersionChecker::testPingResponse(std::string pingResponse) { - // Parse ping response - + // Successfull ping responses // LINUX/MACOS /* A successful ping response ----------------------------- @@ -242,67 +227,39 @@ bool SoftwareVersionChecker::testPingresponse(std::string pingResponse) Approximate round trip times in milli - seconds : Minimum = 18ms, Maximum = 18ms, Average = 18ms */ - bool isNetworkAvailable = false; - std::string searchKey("Ping statistics"); -#if not defined (TARGET_OSX) || defined (TARGET_LINUX) - searchKey = "ping statistics"; // define search key for linux/macOS -#endif - int keyLoc = pingResponse.find(searchKey); - const char statDelimiter = '\n'; - // extract statistsics from ping response - int statStartLoc = pingResponse.find(statDelimiter, keyLoc) + 1; - int statEndLoc = pingResponse.find(statDelimiter, statStartLoc) + 1; - std::string stats = pingResponse.substr(statStartLoc, (statEndLoc - statStartLoc)); - const char commaDelimiter = ','; - int commaLoc = stats.find(commaDelimiter); - const char equalDelimiter = '='; // used only in Windows parsing - struct ParsedStats { - int packetsSent = 0; - int packetsRec = 0; - bool gotSentStats = false; - }parsedStats; + // Failed ping responses + /* + // macOS + PING 8.8.8.8 (8.8.8.8): 56 data bytes + ping: sendto: No route to host - + --- 8.8.8.8 ping statistics --- + 1 packets transmitted, 0 packets received, 100.0% packet loss - while (commaLoc != string::npos) - { -#if not defined (TARGET_OSX) || defined (TARGET_LINUX) - std::string numExtract = stats.substr(0, stats.find("packets")); - if (!parsedStats.gotSentStats) - { - parsedStats.packetsSent = atoi(numExtract.c_str()); - parsedStats.gotSentStats = true; // extract packetsRec next + // Linux + ping: connect: Network is unreachable - } - else - { - parsedStats.packetsRec = atoi(numExtract.c_str()); - break; - } -#else - int equalLoc = stats.find(equalDelimiter); - std::string numExtract = stats.substr(equalLoc + 1, commaLoc); - if (parsedStats.gotSentStats == 0) - { - parsedStats.packetsSent = atoi(numExtract.c_str()); - parsedStats.gotSentStats = true; // extract packetsRec next + // Windows + Pinging 8.8.8.8 with 32 bytes of data: + Request timed out. + Request timed out. + Request timed out. - } - else - { - parsedStats.packetsRec = atoi(numExtract.c_str()); - parsedStats.gotSentStats = true; // extract packetsRec next - break; - } -#endif - stats.erase(stats.begin(), stats.begin() + commaLoc + 1); - commaLoc = stats.find(commaDelimiter); - } + Ping statistics for 8.8.8.8: + Packets: Sent = 3, Received = 0, Lost = 3 (100% loss), - if (parsedStats.packetsSent > 0 && (parsedStats.packetsRec == parsedStats.packetsSent)) + */ + bool isNetworkAvailable = false; + + if (pingResponse.find("time") != std::string::npos && (pingResponse.find("TTL") != std::string::npos || pingResponse.find("ttl") != std::string::npos)) { + // response contains the keywords isNetworkAvailable = true; } + else + { + isNetworkAvailable = false; + } return isNetworkAvailable; } \ No newline at end of file diff --git a/src/SoftwareVersionChecker.h b/src/SoftwareVersionChecker.h index dcb40f9..757d0cf 100644 --- a/src/SoftwareVersionChecker.h +++ b/src/SoftwareVersionChecker.h @@ -4,6 +4,15 @@ namespace SoftwareVersionChecker { + /*! + @brief Check if a later version of EmotiBit software is available to download + */ void checkLatestVersion(); - bool testPingresponse(std::string pingResponse); + + /*! + @brief Test if the response ot ping contains keywords + @param response received when pinging an IP + @return True, is network is available, else false + */ + bool testPingResponse(std::string pingResponse); } \ No newline at end of file From 1f3f5f39d6efb30adeebf64a3ea91860fd72125c Mon Sep 17 00:00:00 2001 From: Nitin Nair Date: Mon, 4 Dec 2023 18:10:25 -0500 Subject: [PATCH 09/13] vs project updated to registed new file --- EmotiBitOscilloscope/EmotiBitOscilloscope.vcxproj | 2 ++ EmotiBitOscilloscope/EmotiBitOscilloscope.vcxproj.filters | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/EmotiBitOscilloscope/EmotiBitOscilloscope.vcxproj b/EmotiBitOscilloscope/EmotiBitOscilloscope.vcxproj index 238f833..7036496 100644 --- a/EmotiBitOscilloscope/EmotiBitOscilloscope.vcxproj +++ b/EmotiBitOscilloscope/EmotiBitOscilloscope.vcxproj @@ -107,6 +107,7 @@ + @@ -163,6 +164,7 @@ + diff --git a/EmotiBitOscilloscope/EmotiBitOscilloscope.vcxproj.filters b/EmotiBitOscilloscope/EmotiBitOscilloscope.vcxproj.filters index b5d0c2a..d7c424c 100644 --- a/EmotiBitOscilloscope/EmotiBitOscilloscope.vcxproj.filters +++ b/EmotiBitOscilloscope/EmotiBitOscilloscope.vcxproj.filters @@ -157,6 +157,9 @@ addons\ofxLSL\src + + addons\ofxEmotiBit\src + @@ -524,6 +527,9 @@ addons\ofxLSL\src + + addons\ofxEmotiBit\src + From 0cfa312f4deadab4dac731ad0da96b9e41517aa8 Mon Sep 17 00:00:00 2001 From: Nitin Nair Date: Tue, 5 Dec 2023 11:14:17 -0500 Subject: [PATCH 10/13] fixed ping command options for unix systems. updated xcode proj file to compile softwareVersionChecker file --- .../EmotiBitOscilloscope.xcodeproj/project.pbxproj | 6 ++++++ src/SoftwareVersionChecker.cpp | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/EmotiBitOscilloscope/EmotiBitOscilloscope.xcodeproj/project.pbxproj b/EmotiBitOscilloscope/EmotiBitOscilloscope.xcodeproj/project.pbxproj index 7710f74..0e711c5 100644 --- a/EmotiBitOscilloscope/EmotiBitOscilloscope.xcodeproj/project.pbxproj +++ b/EmotiBitOscilloscope/EmotiBitOscilloscope.xcodeproj/project.pbxproj @@ -45,6 +45,7 @@ 8E016F802832CE28005D7C65 /* EmotiBitFactoryTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E016F782832CE28005D7C65 /* EmotiBitFactoryTest.cpp */; }; 8E016F842832CE82005D7C65 /* Periodizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E016F832832CE82005D7C65 /* Periodizer.cpp */; }; 8E016F862832D594005D7C65 /* emotibitCommSettings.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8E016F852832D594005D7C65 /* emotibitCommSettings.json */; }; + 8E07BBAD2B1F824D00CDD443 /* SoftwareVersionChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E07BBAB2B1F824D00CDD443 /* SoftwareVersionChecker.cpp */; }; 8E6079EA27C978BE00959DDB /* inputSettings.xml in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8E6079E827C978BE00959DDB /* inputSettings.xml */; }; 8E6079EB27C978BE00959DDB /* ofxOscilloscopeSettings.xml in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8E6079E927C978BE00959DDB /* ofxOscilloscopeSettings.xml */; }; 8F5205AEF8861EF234F0651A /* ofxOscSender.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 81967292BFC87A0144BD32C6 /* ofxOscSender.cpp */; }; @@ -207,6 +208,8 @@ 8E016F822832CE82005D7C65 /* Periodizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Periodizer.h; path = ../src/Signal/Periodizer.h; sourceTree = ""; }; 8E016F832832CE82005D7C65 /* Periodizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Periodizer.cpp; path = ../src/Signal/Periodizer.cpp; sourceTree = ""; }; 8E016F852832D594005D7C65 /* emotibitCommSettings.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = emotibitCommSettings.json; path = bin/data/emotibitCommSettings.json; sourceTree = ""; }; + 8E07BBAB2B1F824D00CDD443 /* SoftwareVersionChecker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SoftwareVersionChecker.cpp; path = ../src/SoftwareVersionChecker.cpp; sourceTree = ""; }; + 8E07BBAC2B1F824D00CDD443 /* SoftwareVersionChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SoftwareVersionChecker.h; path = ../src/SoftwareVersionChecker.h; sourceTree = ""; }; 8E6079E827C978BE00959DDB /* inputSettings.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = inputSettings.xml; path = bin/data/inputSettings.xml; sourceTree = ""; }; 8E6079E927C978BE00959DDB /* ofxOscilloscopeSettings.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = ofxOscilloscopeSettings.xml; path = bin/data/ofxOscilloscopeSettings.xml; sourceTree = ""; }; 8F225C97B6ECA8B22FFB4B76 /* rc5.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = rc5.h; path = ../../../addons/ofxPoco/libs/openssl/include/openssl/rc5.h; sourceTree = SOURCE_ROOT; }; @@ -713,6 +716,8 @@ 4CD5C6EA1AEB082DFF01E7BE /* src */ = { isa = PBXGroup; children = ( + 8E07BBAB2B1F824D00CDD443 /* SoftwareVersionChecker.cpp */, + 8E07BBAC2B1F824D00CDD443 /* SoftwareVersionChecker.h */, 8E016F812832CE65005D7C65 /* Signal */, AFB59BF33EDC27D6AF2CC50B /* ArduinoString.h */, B37D59256BC5BDEB408A0B4B /* DoubleBuffer.h */, @@ -1565,6 +1570,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 8E07BBAD2B1F824D00CDD443 /* SoftwareVersionChecker.cpp in Sources */, E4B69E200A3A1BDC003C02F2 /* main.cpp in Sources */, E4B69E210A3A1BDC003C02F2 /* ofApp.cpp in Sources */, D820615CFDD5F497033D7C5A /* ofxBiquadFilter.cpp in Sources */, diff --git a/src/SoftwareVersionChecker.cpp b/src/SoftwareVersionChecker.cpp index e16902e..d90059a 100644 --- a/src/SoftwareVersionChecker.cpp +++ b/src/SoftwareVersionChecker.cpp @@ -8,7 +8,7 @@ void SoftwareVersionChecker::checkLatestVersion() // -w specifies timeout period in mS. We are going to wait for a maximum of 3 seconds for a ping response. // the IP 8.8.8.8 is google's public DNS. We are using ping with a specific IP as that removes undefined wait periods associated with DNS resolution. More details: https://developers.google.com/speed/public-dns #if defined (TARGET_OSX) || defined (TARGET_LINUX) - std::string command = "ping -n 1 -t 1 8.8.8.8"; // ping 1 time with a total timeout of 1 second + std::string command = "ping -c 1 -t 1 8.8.8.8"; // ping 1 time with a total timeout of 1 second #else std::string command = "ping -n 1 -w 100 8.8.8.8"; // ping 1 time with 100ms max timeout for each try #endif @@ -262,4 +262,4 @@ bool SoftwareVersionChecker::testPingResponse(std::string pingResponse) isNetworkAvailable = false; } return isNetworkAvailable; -} \ No newline at end of file +} From 0e0b231783cf84f5247d6d9cc21e02190675981f Mon Sep 17 00:00:00 2001 From: Nitin Nair Date: Tue, 5 Dec 2023 12:34:01 -0500 Subject: [PATCH 11/13] updated ping command for linux --- src/SoftwareVersionChecker.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/SoftwareVersionChecker.cpp b/src/SoftwareVersionChecker.cpp index d90059a..3e9ed08 100644 --- a/src/SoftwareVersionChecker.cpp +++ b/src/SoftwareVersionChecker.cpp @@ -7,8 +7,10 @@ void SoftwareVersionChecker::checkLatestVersion() // -n specifies number of tries. we are going to try to detect internet connection by sending 1 packet // -w specifies timeout period in mS. We are going to wait for a maximum of 3 seconds for a ping response. // the IP 8.8.8.8 is google's public DNS. We are using ping with a specific IP as that removes undefined wait periods associated with DNS resolution. More details: https://developers.google.com/speed/public-dns -#if defined (TARGET_OSX) || defined (TARGET_LINUX) - std::string command = "ping -c 1 -t 1 8.8.8.8"; // ping 1 time with a total timeout of 1 second +#if defined (TARGET_OSX) + std::string command = "ping -c 1 -t 1 8.8.8.8"; // ping 1 time with a total timeout of 1 second +#elif defined (TARGET_LINUX) + std::string command = "ping -c 1 -W 1 8.8.8.8"; // ping 1 time with a total timeout of 1 second #else std::string command = "ping -n 1 -w 100 8.8.8.8"; // ping 1 time with 100ms max timeout for each try #endif From 41ffb2ca1775f860fa20988f279364fefaaf5c46 Mon Sep 17 00:00:00 2001 From: Nitin Nair <31810812+nitin710@users.noreply.github.com> Date: Fri, 8 Dec 2023 13:58:45 -0500 Subject: [PATCH 12/13] comments updated --- src/SoftwareVersionChecker.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SoftwareVersionChecker.h b/src/SoftwareVersionChecker.h index 757d0cf..f9d1b8c 100644 --- a/src/SoftwareVersionChecker.h +++ b/src/SoftwareVersionChecker.h @@ -10,9 +10,9 @@ namespace SoftwareVersionChecker void checkLatestVersion(); /*! - @brief Test if the response ot ping contains keywords + @brief Test if the response to ping contains keywords @param response received when pinging an IP - @return True, is network is available, else false + @return True, if network is available, else false */ bool testPingResponse(std::string pingResponse); -} \ No newline at end of file +} From 4d26c592303c2f115bc440767f64caf66eab7e26 Mon Sep 17 00:00:00 2001 From: Nitin Nair Date: Tue, 5 Mar 2024 14:36:29 -0500 Subject: [PATCH 13/13] removed checking for "time" form ping response based on review comment --- src/SoftwareVersionChecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SoftwareVersionChecker.cpp b/src/SoftwareVersionChecker.cpp index 3e9ed08..73488be 100644 --- a/src/SoftwareVersionChecker.cpp +++ b/src/SoftwareVersionChecker.cpp @@ -254,7 +254,7 @@ bool SoftwareVersionChecker::testPingResponse(std::string pingResponse) */ bool isNetworkAvailable = false; - if (pingResponse.find("time") != std::string::npos && (pingResponse.find("TTL") != std::string::npos || pingResponse.find("ttl") != std::string::npos)) + if (pingResponse.find("TTL") != std::string::npos || pingResponse.find("ttl") != std::string::npos) { // response contains the keywords isNetworkAvailable = true;