speedtestcpp: add new package

speedtestcpp is a fork of Taganaka's speedtest, rewritten.

It has some improvements such as
 - interactive result show
 - use server recommended profiles, which makes it faster (can be disabled)
 - and more..

It also provides it's functions in shared and static libraries
and offers development headers for integrating speedtest to
features to another projects.

This commit replaces speedtestpp since this fork has
all the same features + more.

Signed-off-by: Oskari Rauta <oskari.rauta@gmail.com>
This commit is contained in:
Oskari Rauta 2023-05-28 13:47:30 +03:00 committed by Tianling Shen
parent fc8cc7aa8f
commit c5bf970241
3 changed files with 66 additions and 281 deletions

66
net/speedtestcpp/Makefile Normal file
View File

@ -0,0 +1,66 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=speedtestcpp
PKG_VERSION:=1.20.2
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/oskarirauta/speedtestcpp/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=7d5c85f1d9a46f7d8a3ac4261ef1f92e53c511430bae096f7ec6f12a33d38904
PKG_MAINTAINER:=Oskari Rauta <oskari.rauta@gmail.com>
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE
include $(INCLUDE_DIR)/package.mk
define Package/libspeedtestcpp
SECTION:=libs
CATEGORY:=Libraries
TITLE:=library for ookla's speedtest
DEPENDS:=+libcurl +libstdcpp
URL:=https://github.com/oskarirauta/speedtestcpp
endef
define Package/libspeedtestcpp/description
Shared library that provides support for ookla's speedtest
endef
define Package/speedtestcpp
SECTION:=net
CATEGORY:=Network
TITLE:=SpeedTest++
DEPENDS:=+libspeedtestcpp +libstdcpp
URL:=https://github.com/oskarirauta/speedtestcpp
PROVIDES:=speedtestpp
endef
define Package/speedtestcpp/description
Yet another unofficial speedtest.net client cli interface
forked from taganaka's SpeedTest with few improments and
lesser depends.
endef
TARGET_CXXFLAGS += --std=c++23 -fPIC
define Build/Configure
endef
define Package/libspeedtestcpp/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_BUILD_DIR)/libspeedtestcpp.so* $(1)/usr/lib/
endef
define Package/speedtestcpp/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/speedtest $(1)/usr/bin/
endef
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/lib $(1)/usr/include/speedtest
$(CP) $(PKG_BUILD_DIR)/libspeedtestcpp.{so*,a} $(1)/usr/lib/
$(CP) $(PKG_BUILD_DIR)/include/speedtest/*.hpp $(1)/usr/include/speedtest/
endef
$(eval $(call BuildPackage,libspeedtestcpp))
$(eval $(call BuildPackage,speedtestcpp))

View File

@ -1,42 +0,0 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=speedtestpp
PKG_VERSION:=1.14
PKG_RELEASE:=2
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/taganaka/SpeedTest.git
PKG_SOURCE_DATE:=2021-12-06
PKG_SOURCE_VERSION:=0f63cfbf7ce8d64ea803bf143b957eae76323405
PKG_MIRROR_HASH:=4221584dc3e1e31f2560ef347298a2bcca3ac2331049970b7bd7d742e4e1825f
PKG_MAINTAINER:=Oskari Rauta <oskari.rauta@gmail.com>
PKG_LICENSE:=MIT
CMAKE_INSTALL:=1
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/nls.mk
include $(INCLUDE_DIR)/cmake.mk
CMAKE_OPTIONS += -DCMAKE_BUILD_TYPE=Release .
define Package/speedtestpp
SECTION:=net
CATEGORY:=Network
TITLE:=speedtest++
DEPENDS:=+libcurl +libopenssl +libstdcpp $(ICONV_DEPENDS)
CONFLICTS:=python3-speedtest-cli
URL:=https://github.com/taganaka/SpeedTest
endef
define Package/speedtestpp/description
Yet another unofficial speedtest.net client cli interface
endef
define Package/speedtestpp/install
$(INSTALL_DIR) $(1)/usr/bin
$(CP) $(PKG_INSTALL_DIR)/usr/bin/SpeedTest $(1)/usr/bin/speedtest
endef
$(eval $(call BuildPackage,speedtestpp))

View File

@ -1,239 +0,0 @@
From b7db370449cfe2b453c22b74a660701f78bd7ce3 Mon Sep 17 00:00:00 2001
From: Anatolii Lapytskyi <ala@allunite.com>
Date: Tue, 6 Sep 2022 15:59:27 +0200
Subject: [PATCH] Remove dependency on libxml2
---
CMakeLists.txt | 5 +-
README.md | 5 +-
SpeedTest.cpp | 136 ++++++++++++++-----------------------------------
SpeedTest.h | 2 -
4 files changed, 41 insertions(+), 107 deletions(-)
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -44,7 +44,6 @@ add_executable(SpeedTest ${SOURCE_FILES}
INCLUDE (CheckIncludeFiles)
find_package(CURL REQUIRED)
-find_package(LibXml2 REQUIRED)
if (NOT (APPLE))
find_package(OpenSSL REQUIRED)
@@ -52,7 +51,7 @@ else()
CHECK_INCLUDE_FILES("CommonCrypto/CommonDigest.h" HAVE_COMMON_DIGEST_H)
endif()
-include_directories(${CURL_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIR})
-target_link_libraries(SpeedTest ${CURL_LIBRARIES} ${LIBXML2_LIBRARIES} -lpthread ${OPENSSL_LIBRARIES})
+include_directories(${CURL_INCLUDE_DIRS})
+target_link_libraries(SpeedTest ${CURL_LIBRARIES} -lpthread ${OPENSSL_LIBRARIES})
install(TARGETS SpeedTest RUNTIME DESTINATION bin)
--- a/README.md
+++ b/README.md
@@ -26,7 +26,6 @@ It supports the new (undocumented) raw T
2. cmake
3. libcurl
4. libssl
-5. libxml2
### On Mac OS X
@@ -40,7 +39,7 @@ $ make install
### On Ubuntu/Debian
```
-$ sudo apt-get install build-essential libcurl4-openssl-dev libxml2-dev libssl-dev cmake
+$ sudo apt-get install build-essential libcurl4-openssl-dev libssl-dev cmake
$ git clone https://github.com/taganaka/SpeedTest
$ cd SpeedTest
$ cmake -DCMAKE_BUILD_TYPE=Release .
@@ -50,7 +49,7 @@ $ sudo make install
### On OpenSuse
```
-$ sudo zypper install cmake gcc-c++ libcurl-devel libxml2-devel libopenssl-devel git
+$ sudo zypper install cmake gcc-c++ libcurl-devel libopenssl-devel git
$ git clone https://github.com/taganaka/SpeedTest
$ cd SpeedTest
$ cmake -DCMAKE_BUILD_TYPE=Release .
--- a/SpeedTest.cpp
+++ b/SpeedTest.cpp
@@ -353,67 +353,16 @@ std::vector<std::string> SpeedTest::spli
}
-ServerInfo SpeedTest::processServerXMLNode(xmlTextReaderPtr reader) {
-
- auto name = xmlTextReaderConstName(reader);
- auto nodeName = std::string((char*)name);
-
- if (!name || nodeName != "server"){
- return ServerInfo();
- }
-
- if (xmlTextReaderAttributeCount(reader) > 0){
- auto info = ServerInfo();
- auto server_url = xmlTextReaderGetAttribute(reader, BAD_CAST "url");
- auto server_lat = xmlTextReaderGetAttribute(reader, BAD_CAST "lat");
- auto server_lon = xmlTextReaderGetAttribute(reader, BAD_CAST "lon");
- auto server_name = xmlTextReaderGetAttribute(reader, BAD_CAST "name");
- auto server_county = xmlTextReaderGetAttribute(reader, BAD_CAST "country");
- auto server_cc = xmlTextReaderGetAttribute(reader, BAD_CAST "cc");
- auto server_host = xmlTextReaderGetAttribute(reader, BAD_CAST "host");
- auto server_id = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
- auto server_sponsor = xmlTextReaderGetAttribute(reader, BAD_CAST "sponsor");
-
- if (server_name)
- info.name.append((char*)server_name);
-
- if (server_url)
- info.url.append((char*)server_url);
-
- if (server_county)
- info.country.append((char*)server_county);
-
- if (server_cc)
- info.country_code.append((char*)server_cc);
-
- if (server_host)
- info.host.append((char*)server_host);
-
- if (server_sponsor)
- info.sponsor.append((char*)server_sponsor);
-
- if (server_id)
- info.id = std::atoi((char*)server_id);
-
- if (server_lat)
- info.lat = std::stof((char*)server_lat);
-
- if (server_lon)
- info.lon = std::stof((char*)server_lon);
-
- xmlFree(server_url);
- xmlFree(server_lat);
- xmlFree(server_lon);
- xmlFree(server_name);
- xmlFree(server_county);
- xmlFree(server_cc);
- xmlFree(server_host);
- xmlFree(server_id);
- xmlFree(server_sponsor);
- return info;
- }
-
- return ServerInfo();
+std::string getAttributeValue(const std::string& data, const size_t offset, const size_t max_pos, const std::string& attribute_name) {
+ size_t pos = data.find(attribute_name + "=\"", offset);
+ if (pos == std::string::npos)
+ return "";
+ if (pos >= max_pos)
+ return "";
+ size_t value_pos = pos + attribute_name.length() + 2;
+ size_t end = data.find("\"", value_pos);
+ std::string s = data.substr(pos + attribute_name.length() + 2, end - value_pos);
+ return s;
}
bool SpeedTest::fetchServers(const std::string& url, std::vector<ServerInfo>& target, int &http_code) {
@@ -441,53 +390,42 @@ bool SpeedTest::fetchServers(const std::
http_code = 200;
}
- size_t len = oss.str().length();
- auto *xmlbuff = (char*)calloc(len + 1, sizeof(char));
- if (!xmlbuff){
- std::cerr << "Unable to calloc" << std::endl;
+ IPInfo ipInfo;
+ if (!SpeedTest::ipInfo(ipInfo)){
curl_easy_cleanup(curl);
+ std::cerr << "OOPS!" <<std::endl;
return false;
}
- memcpy(xmlbuff, oss.str().c_str(), len);
- oss.str("");
- xmlTextReaderPtr reader = xmlReaderForMemory(xmlbuff, static_cast<int>(len), nullptr, nullptr, 0);
+ std::string data = oss.str();
- if (reader != nullptr) {
- IPInfo ipInfo;
- if (!SpeedTest::ipInfo(ipInfo)){
- curl_easy_cleanup(curl);
- free(xmlbuff);
- xmlFreeTextReader(reader);
- std::cerr << "OOPS!" <<std::endl;
- return false;
- }
- auto ret = xmlTextReaderRead(reader);
- while (ret == 1) {
- ServerInfo info = processServerXMLNode(reader);
- if (!info.url.empty()){
- info.distance = harversine(std::make_pair(ipInfo.lat, ipInfo.lon), std::make_pair(info.lat, info.lon));
- target.push_back(info);
- }
- ret = xmlTextReaderRead(reader);
- }
- xmlFreeTextReader(reader);
- if (ret != 0) {
- curl_easy_cleanup(curl);
- free(xmlbuff);
- std::cerr << "Failed to parse" << std::endl;
- return false;
+ const std::string server_tag_start = "<server ";
+
+ size_t server_tag_begin = data.find(server_tag_start);
+ while (server_tag_begin != std::string::npos) {
+ size_t server_tag_end = data.find("/>", server_tag_begin);
+
+ auto info = ServerInfo();
+ info.name = getAttributeValue(data, server_tag_begin, server_tag_end, "name");
+ info.url = getAttributeValue(data, server_tag_begin, server_tag_end, "url");
+ info.country = getAttributeValue(data, server_tag_begin, server_tag_end, "country");
+ info.country_code = getAttributeValue(data, server_tag_begin, server_tag_end, "cc");
+ info.host = getAttributeValue(data, server_tag_begin, server_tag_end, "host");
+ info.sponsor = getAttributeValue(data, server_tag_begin, server_tag_end, "sponsor");
+ info.id = atoi(getAttributeValue(data, server_tag_begin, server_tag_end, "id").c_str());
+ info.lat = std::stof(getAttributeValue(data, server_tag_begin, server_tag_end, "lat"));
+ info.lon = std::stof(getAttributeValue(data, server_tag_begin, server_tag_end, "lon"));
+
+ if (!info.url.empty()){
+ info.distance = harversine(std::make_pair(ipInfo.lat, ipInfo.lon), std::make_pair(info.lat, info.lon));
+ target.push_back(info);
}
- } else {
- std::cerr << "Unable to initialize xml parser" << std::endl;
- curl_easy_cleanup(curl);
- free(xmlbuff);
- return false;
+
+ server_tag_begin = data.find(server_tag_start, server_tag_begin + 1);
}
+
curl_easy_cleanup(curl);
- free(xmlbuff);
- xmlCleanupParser();
std::sort(target.begin(), target.end(), [](const ServerInfo &a, const ServerInfo &b) -> bool {
return a.distance < b.distance;
});
--- a/SpeedTest.h
+++ b/SpeedTest.h
@@ -7,7 +7,6 @@
#include "SpeedTestConfig.h"
#include "SpeedTestClient.h"
-#include <libxml/xmlreader.h>
#include <functional>
#include <cmath>
#include <curl/curl.h>
@@ -50,7 +49,6 @@ private:
const ServerInfo findBestServerWithin(const std::vector<ServerInfo>& serverList, long& latency, int sample_size = 5, std::function<void(bool)> cb = nullptr);
static CURL* curl_setup(CURL* curl = nullptr);
static size_t writeFunc(void* buf, size_t size, size_t nmemb, void* userp);
- static ServerInfo processServerXMLNode(xmlTextReaderPtr reader);
double execute(const ServerInfo &server, const TestConfig &config, const opFn &fnc, std::function<void(bool)> cb = nullptr);
template <typename T>
static T deg2rad(T n);