Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,14 @@ add_executable(SpeedTest ${SOURCE_FILES})

INCLUDE (CheckIncludeFiles)
find_package(CURL REQUIRED)
find_package(LibXml2 REQUIRED)

if (NOT (APPLE))
find_package(OpenSSL REQUIRED)
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)
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ It supports the new (undocumented) raw TCP protocol for better accuracy.
2. cmake
3. libcurl
4. libssl
5. libxml2

### On Mac OS X

Expand All @@ -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 .
Expand All @@ -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 .
Expand Down
136 changes: 37 additions & 99 deletions SpeedTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,67 +353,16 @@ std::vector<std::string> SpeedTest::splitString(const std::string &instr, const

}

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) {
Expand Down Expand Up @@ -441,53 +390,42 @@ bool SpeedTest::fetchServers(const std::string& url, std::vector<ServerInfo>& ta
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;
});
Expand Down
2 changes: 0 additions & 2 deletions SpeedTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

#include "SpeedTestConfig.h"
#include "SpeedTestClient.h"
#include <libxml/xmlreader.h>
#include <functional>
#include <cmath>
#include <curl/curl.h>
Expand Down Expand Up @@ -50,7 +49,6 @@ class SpeedTest {
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);
Expand Down