From 3e9e6b51e365f29d743cb7dbfeb60d9a6094a730 Mon Sep 17 00:00:00 2001 From: LiuzhouChan Date: Thu, 6 Jun 2019 15:19:31 +0800 Subject: [PATCH 1/5] m1 --- .../libpear_speedtest/libpear_get_server.c | 594 +++++++++++++----- .../libpear_speedtest/libpear_get_server.h | 9 + .../libpear_speedtest/libpear_upload_test.c | 112 ++++ .../libpear_speedtest/libpear_upload_test.h | 2 + pear_build.sh | 20 +- pear_monitor/pear_speed.c | 6 +- 6 files changed, 560 insertions(+), 183 deletions(-) diff --git a/libpear/libpear_speedtest/libpear_get_server.c b/libpear/libpear_speedtest/libpear_get_server.c index e02df75..1fc8ab8 100644 --- a/libpear/libpear_speedtest/libpear_get_server.c +++ b/libpear/libpear_speedtest/libpear_get_server.c @@ -10,70 +10,70 @@ #include "libpear_get_header.h" #include "libpear_get_server.h" - -#define R 6371 -#define PI 3.1415926536 -#define TO_RAD (PI / 180) - +#define R 6371 +#define PI 3.1415926536 +#define TO_RAD (PI / 180) static double pear_speedtest_calc_distance(double lat1, double lon1, double lat2, double lon2) { - double dx, dy, dz, a, b; - lon1 -= lon2; - lon1 *= TO_RAD, lat1 *= TO_RAD, lat2 *= TO_RAD; - - dz = sin(lat1) - sin(lat2); - dx = cos(lon1) * cos(lat1) - cos(lat2); - dy = sin(lon1) * cos(lat1); - a = (dx * dx + dy * dy + dz * dz); - b = sqrt(a) / 2; - #ifdef USE_ASIN - return 2 * R * asin(b); - #else - return 2 * R * atan2(b, sqrt(1 - b * b)); - #endif + double dx, dy, dz, a, b; + lon1 -= lon2; + lon1 *= TO_RAD, lat1 *= TO_RAD, lat2 *= TO_RAD; + + dz = sin(lat1) - sin(lat2); + dx = cos(lon1) * cos(lat1) - cos(lat2); + dy = sin(lon1) * cos(lat1); + a = (dx * dx + dy * dy + dz * dz); + b = sqrt(a) / 2; +#ifdef USE_ASIN + return 2 * R * asin(b); +#else + return 2 * R * atan2(b, sqrt(1 - b * b)); +#endif } - -#define PEAR_SPEEDTEST_COPY_SERVERINFO(dest, src) do { \ - strcpy(dest.sponsor, src.sponsor); \ - strcpy(dest.url_upload, src.url_upload); \ - strcpy(dest.url_download, src.url_download); \ - dest.lat = src.lat; \ - dest.lon = src.lon; \ - dest.dis = src.dis; \ - } while(0) - - -#define PEAR_SPEEDTEST_COPY_SERVERINFO_CN(dest, src) do { \ - strcpy(dest.operator, src.operator); \ - strcpy(dest.url_upload, src.url_upload); \ - strcpy(dest.url_download, src.url_download); \ - dest.lat = src.lat; \ - dest.lon = src.lon; \ - dest.dis = src.dis; \ - } while(0) - +#define PEAR_SPEEDTEST_COPY_SERVERINFO(dest, src) \ + do \ + { \ + strcpy(dest.sponsor, src.sponsor); \ + strcpy(dest.url_upload, src.url_upload); \ + strcpy(dest.url_download, src.url_download); \ + dest.lat = src.lat; \ + dest.lon = src.lon; \ + dest.dis = src.dis; \ + } while (0) + +#define PEAR_SPEEDTEST_COPY_SERVERINFO_CN(dest, src) \ + do \ + { \ + strcpy(dest.operator, src.operator); \ + strcpy(dest.url_upload, src.url_upload); \ + strcpy(dest.url_download, src.url_download); \ + dest.lat = src.lat; \ + dest.lon = src.lon; \ + dest.dis = src.dis; \ + } while (0) // void pear_speedtest_init_server_info(pear_speedtest_server_info_t *server_info, int server_num) // { // memset(server_info, 0, sizeof(pear_speedtest_server_info_t) * server_num); // } - -int pear_speedtest_get_some_server(pear_speedtest_client_info_t *client_info, - pear_speedtest_server_info_t *server_info, int server_num, char *what_is_my_country, int debug) +int pear_speedtest_get_some_server(pear_speedtest_client_info_t *client_info, + pear_speedtest_server_info_t *server_info, int server_num, char *what_is_my_country, int debug) { - char *header[] = { pear_speedtest_header_info.user_agent, "Cache-Control: no-cache", NULL}; + char *header[] = {pear_speedtest_header_info.user_agent, "Cache-Control: no-cache", NULL}; - if (!debug) { - pear_download_file("GET", "http://c.speedtest.net/speedtest-servers-static.php", header, NULL, 0, 30, 300, "/tmp/.pear_speedtest_servers.php"); + if (!debug) + { + pear_download_file("GET", "http://c.speedtest.net/speedtest-servers-static.php", header, NULL, 0, 30, 300, "/tmp/.pear_speedtest_servers.php"); } memset(server_info, 0, sizeof(pear_speedtest_server_info_t) * server_num); node_t *root = roxml_load_doc("/tmp/.pear_speedtest_servers.php"); - if(root == NULL) { + if (root == NULL) + { fprintf(stderr, "roxml_load_doc failed\n"); goto failed_to_release_buffer; } @@ -81,81 +81,102 @@ int pear_speedtest_get_some_server(pear_speedtest_client_info_t *client_info, // find first server node // node_t *server = roxml_get_chld(root, NULL, 0); - while(server != NULL) { + while (server != NULL) + { char server_name[32] = {0}; roxml_get_name(server, server_name, 32); - if (!strcmp(server_name, "server")) { break; } + if (!strcmp(server_name, "server")) + { + break; + } server = roxml_get_chld(server, NULL, 0); } - if(server == NULL) { + if (server == NULL) + { goto failed_to_release_xml; } // country limit // char type_country[16] = {0}; - if (what_is_my_country) { + if (what_is_my_country) + { strcpy(type_country, what_is_my_country); - } else { strcpy(type_country, "China"); } - + } + else + { + strcpy(type_country, "China"); + } // find min distance servers // - while(server != NULL) { + while (server != NULL) + { char country[64] = {0}; node_t *attr_country = roxml_get_attr(server, "country", 0); - if (NULL == attr_country) goto failed_to_release_xml; + if (NULL == attr_country) + goto failed_to_release_xml; char *country_string = roxml_get_content(attr_country, 0, 0, 0); - if (NULL == country_string) goto failed_to_release_xml; + if (NULL == country_string) + goto failed_to_release_xml; strcpy(country, country_string); free(country_string); - if(!strcmp(country, type_country)) { - pear_speedtest_server_info_t *max_distance_server_info = NULL; - pear_speedtest_server_info_t s_info; + if (!strcmp(country, type_country)) + { + pear_speedtest_server_info_t *max_distance_server_info = NULL; + pear_speedtest_server_info_t s_info; // sponsor // node_t *attr_sponsor = roxml_get_attr(server, "sponsor", 0); - if (NULL == attr_sponsor) goto failed_to_release_xml; + if (NULL == attr_sponsor) + goto failed_to_release_xml; char *sponsor_string = roxml_get_content(attr_sponsor, 0, 0, 0); - if (NULL == sponsor_string) goto failed_to_release_xml; + if (NULL == sponsor_string) + goto failed_to_release_xml; strncpy(s_info.sponsor, sponsor_string, PEAR_SPEEDTEST_SPONSOR_LEN); free(sponsor_string); // carrieroperator // (China Mobile Group XinJiang, China Unicom Heilongjiang, China Telecom) // - switch (client_info->isp_n) { - case 1: - if (!strcasestr(s_info.sponsor, "mobile")) { - goto next_one; - } - break; - - case 2: - if (!strcasestr(s_info.sponsor, "unicom")) { - goto next_one; - } - break; - - case 3: - if (!strcasestr(s_info.sponsor, "telecom")) { - goto next_one; - } - break; - - default: - break; + switch (client_info->isp_n) + { + case 1: + if (!strcasestr(s_info.sponsor, "mobile")) + { + goto next_one; + } + break; + + case 2: + if (!strcasestr(s_info.sponsor, "unicom")) + { + goto next_one; + } + break; + + case 3: + if (!strcasestr(s_info.sponsor, "telecom")) + { + goto next_one; + } + break; + + default: + break; } // url // node_t *attr_url = roxml_get_attr(server, "url", 0); - if (NULL == attr_url) goto failed_to_release_xml; + if (NULL == attr_url) + goto failed_to_release_xml; char *url_string = roxml_get_content(attr_url, 0, 0, 0); - if (NULL == url_string) goto failed_to_release_xml; + if (NULL == url_string) + goto failed_to_release_xml; strncpy(s_info.url_upload, url_string, PEAR_SPEEDTEST_URL_LEN); strncpy(s_info.url_download, url_string, PEAR_SPEEDTEST_URL_LEN); free(url_string); @@ -163,30 +184,36 @@ int pear_speedtest_get_some_server(pear_speedtest_client_info_t *client_info, // lat // node_t *attr_lat = roxml_get_attr(server, "lat", 0); - if (NULL == attr_lat) goto failed_to_release_xml; + if (NULL == attr_lat) + goto failed_to_release_xml; char *lat_string = roxml_get_content(attr_lat, 0, 0, 0); - if (NULL == lat_string) goto failed_to_release_xml; + if (NULL == lat_string) + goto failed_to_release_xml; s_info.lat = atof(lat_string); free(lat_string); // lon // node_t *attr_lon = roxml_get_attr(server, "lon", 0); - if (NULL == attr_lon) goto failed_to_release_xml; + if (NULL == attr_lon) + goto failed_to_release_xml; char *lon_string = roxml_get_content(attr_lon, 0, 0, 0); - if (NULL == lon_string) goto failed_to_release_xml; + if (NULL == lon_string) + goto failed_to_release_xml; s_info.lon = atof(lon_string); free(lon_string); // calc distance - // + // s_info.dis = pear_speedtest_calc_distance(client_info->lat, client_info->lon, s_info.lat, s_info.lon); - + // store first server_num service nodes // int i; - for (i = 0; i < server_num; i++) { - if (!server_info[i].set_value_flag) { + for (i = 0; i < server_num; i++) + { + if (!server_info[i].set_value_flag) + { server_info[i].set_value_flag = 1; PEAR_SPEEDTEST_COPY_SERVERINFO(server_info[i], s_info); goto next_one; @@ -195,22 +222,28 @@ int pear_speedtest_get_some_server(pear_speedtest_client_info_t *client_info, // find max distance node from server_num nodes // - for (i = 0; i < server_num; i++) { - if (NULL == max_distance_server_info) { + for (i = 0; i < server_num; i++) + { + if (NULL == max_distance_server_info) + { max_distance_server_info = &server_info[i]; continue; } - if (max_distance_server_info->dis < server_info[i].dis) { max_distance_server_info = &server_info[i]; } + if (max_distance_server_info->dis < server_info[i].dis) + { + max_distance_server_info = &server_info[i]; + } } // knock out max one // - if (max_distance_server_info->dis > s_info.dis) { + if (max_distance_server_info->dis > s_info.dis) + { PEAR_SPEEDTEST_COPY_SERVERINFO((*server_info), s_info); } } -next_one: + next_one: server = roxml_get_next_sibling(server); } roxml_close(root); @@ -223,43 +256,46 @@ failed_to_release_buffer: return -1; } - int __pear_speedtest_cn_get_meta_data(json_t *json_root) { json_t *json_meta; - if (!json_root) { + if (!json_root) + { return 10; } json_meta = json_object_get(json_root, "meta"); - if (json_is_object(json_meta)) { + if (json_is_object(json_meta)) + { json_t *json_last_page = json_object_get(json_meta, "last_page"); - if (json_is_integer(json_last_page)) { + if (json_is_integer(json_last_page)) + { int total_pages = json_integer_value(json_last_page); return total_pages; } - } + } - return 0; + return 0; } - int __pear_speedtest_cn_get_server_data(json_t *json_root, int filter_operator, - pear_speedtest_client_info_t *client_info, - pear_speedtest_server_info_t *server_info, - int server_num, + pear_speedtest_client_info_t *client_info, + pear_speedtest_server_info_t *server_info, + int server_num, char *what_is_my_country) { json_t *json_data = json_object_get(json_root, "data"); - if (json_is_array(json_data)) { - int node = 0; - int array_size = json_array_size(json_data); + if (json_is_array(json_data)) + { + int node = 0; + int array_size = json_array_size(json_data); - for (node = 0; node < array_size; node++) { - pear_speedtest_server_info_t *max_distance_server_info = NULL; - pear_speedtest_server_info_t s_info; + for (node = 0; node < array_size; node++) + { + pear_speedtest_server_info_t *max_distance_server_info = NULL; + pear_speedtest_server_info_t s_info; json_t *json_node = json_array_get(json_data, node); json_t *json_country_code = json_object_get(json_node, "country_code"); @@ -270,7 +306,7 @@ int __pear_speedtest_cn_get_server_data(json_t *json_root, int filter_operator, json_t *json_lon = json_object_get(json_node, "lon"); json_t *json_dis = json_object_get(json_node, "distance"); - // printf("[Pear] %10d , (%s, %s), %s --> %s | %s\n", + // printf("[Pear] %10d , (%s, %s), %s --> %s | %s\n", // node, // json_string_value(json_lat), // json_string_value(json_lon), @@ -280,25 +316,34 @@ int __pear_speedtest_cn_get_server_data(json_t *json_root, int filter_operator, /* filter country */ - if (json_is_string(json_country_code)) { - strncpy(s_info.coutry_code, json_string_value(json_country_code), PEAR_SPEEDTEST_COUNTRY_CODE_LEN - 1); - } else { + if (json_is_string(json_country_code)) + { + strncpy(s_info.coutry_code, json_string_value(json_country_code), PEAR_SPEEDTEST_COUNTRY_CODE_LEN - 1); + } + else + { s_info.coutry_code[0] = 0; } - if (strcmp(s_info.coutry_code, client_info->country) != 0) { + if (strcmp(s_info.coutry_code, client_info->country) != 0) + { continue; } // printf("s_info.coutry_code: %s, client_info->country: %s\n", s_info.coutry_code, client_info->country); /* filter operator */ - if (json_is_string(json_operator)) { - strncpy(s_info.operator, json_string_value(json_operator), PEAR_SPEEDTEST_URL_LEN - 1); - } else { + if (json_is_string(json_operator)) + { + strncpy(s_info.operator, json_string_value(json_operator), PEAR_SPEEDTEST_URL_LEN - 1); + } + else + { s_info.operator[0] = 0; } - if (filter_operator) { - if (!strstr(s_info.operator, client_info->isp)) { + if (filter_operator) + { + if (!strstr(s_info.operator, client_info->isp)) + { continue; } } @@ -309,59 +354,80 @@ int __pear_speedtest_cn_get_server_data(json_t *json_root, int filter_operator, // continue; // } - // upload url - // - if (json_is_string(json_upload)) { + // upload url + // + if (json_is_string(json_upload)) + { strncpy(s_info.url_upload, json_string_value(json_upload), PEAR_SPEEDTEST_URL_LEN - 1); - } else { - continue; + } + else + { + continue; } // download url // - if (json_is_string(json_download)) { + if (json_is_string(json_download)) + { strncpy(s_info.url_download, json_string_value(json_download), PEAR_SPEEDTEST_URL_LEN - 1); - } else { - continue; + } + else + { + continue; } // printf("s_info.url_upload: %s, s_info.url_download: %s\n", s_info.url_upload, s_info.url_download); - // lat + // lat // - if (json_is_string(json_lat)) { + if (json_is_string(json_lat)) + { char *lat = json_string_value(json_lat); - if (lat) { + if (lat) + { s_info.lat = atof(lat); } - } else if (json_is_real(json_lat)) { + } + else if (json_is_real(json_lat)) + { s_info.lat = json_real_value(json_lat); - } else { - continue; + } + else + { + continue; } // lon // - if (json_is_string(json_lon)) { + if (json_is_string(json_lon)) + { char *lon = json_string_value(json_lon); - if (lon) { + if (lon) + { s_info.lon = atof(lon); } - } else if (json_is_real(json_lon)) { + } + else if (json_is_real(json_lon)) + { s_info.lon = json_real_value(json_lon); - } else { - continue; + } + else + { + continue; } // calc distance // - if (json_is_integer(json_dis)) { + if (json_is_integer(json_dis)) + { s_info.dis = json_integer_value(json_dis); // printf("-->distance: %f\n", s_info.dis); - } else { - s_info.dis = pear_speedtest_calc_distance(client_info->lat, - client_info->lon, - s_info.lat, - s_info.lon); + } + else + { + s_info.dis = pear_speedtest_calc_distance(client_info->lat, + client_info->lon, + s_info.lat, + s_info.lon); } // printf("newest: s_info.url_upload: %s\n", s_info.url_upload); @@ -369,8 +435,10 @@ int __pear_speedtest_cn_get_server_data(json_t *json_root, int filter_operator, // store first server_num service nodes // int i = 0; - for (i = 0; i < server_num; i++) { - if (server_info[i].set_value_flag != 1) { + for (i = 0; i < server_num; i++) + { + if (server_info[i].set_value_flag != 1) + { server_info[i].set_value_flag = 1; PEAR_SPEEDTEST_COPY_SERVERINFO_CN(server_info[i], s_info); // printf("insert: %d, s_info.url_upload: %s\n", i, s_info.url_upload); @@ -384,9 +452,11 @@ int __pear_speedtest_cn_get_server_data(json_t *json_root, int filter_operator, // int ii = 0; // printf("distance: "); max_distance_server_info = &server_info[0]; - for (i = 1; i < server_num; i++) { + for (i = 1; i < server_num; i++) + { // printf("%f ", server_info[i].dis); - if (max_distance_server_info->dis < server_info[i].dis) { + if (max_distance_server_info->dis < server_info[i].dis) + { max_distance_server_info = &server_info[i]; // ii = i; } @@ -395,7 +465,8 @@ int __pear_speedtest_cn_get_server_data(json_t *json_root, int filter_operator, // knock out max one // - if (max_distance_server_info->dis > s_info.dis) { + if (max_distance_server_info->dis > s_info.dis) + { PEAR_SPEEDTEST_COPY_SERVERINFO_CN((*max_distance_server_info), s_info); // printf("replace: s_info.url_upload: %s\n\n", s_info.url_upload); // printf("replace: %d, s_info.url_download: %s\n", ii, s_info.url_download); @@ -404,71 +475,252 @@ int __pear_speedtest_cn_get_server_data(json_t *json_root, int filter_operator, next_one: continue; } - } else { return -1; } + } + else + { + return -1; + } - return 0; + return 0; } - int pear_speedtest_cn_count(pear_speedtest_server_info_t *server_info, int server_num) { int i = 0; int count = 0; - for (i = 0; i < server_num; i++) { - if (server_info[i].set_value_flag) { + for (i = 0; i < server_num; i++) + { + if (server_info[i].set_value_flag) + { count++; } } return count; } - int pear_speedtest_cn_get_some_server(pear_speedtest_client_info_t *client_info, pear_speedtest_server_info_t *server_info, int server_num, char *what_is_my_country) { int total_pages = 10; json_error_t error; json_t *json_head = NULL; json_t *json_next = NULL; - char *header[] = { pear_speedtest_header_info.user_agent, "Cache-Control: no-cache", NULL}; + char *header[] = {pear_speedtest_header_info.user_agent, "Cache-Control: no-cache", NULL}; - memset(server_info, 0, sizeof(pear_speedtest_server_info_t) * server_num); + memset(server_info, 0, sizeof(pear_speedtest_server_info_t) * server_num); /* get meta data */ - pear_download_file("GET", "https://forge.speedtest.cn/api/speedtest/nodes", header, NULL, 0, 15, 30, "/tmp/.pear_speedtest_servers_cn.php"); + pear_download_file("GET", "https://forge.speedtest.cn/api/speedtest/nodes", header, NULL, 0, 15, 30, "/tmp/.pear_speedtest_servers_cn.php"); - json_head = json_load_file("/tmp/.pear_speedtest_servers_cn.php", JSON_DECODE_ANY, &error); - if (json_head) { + json_head = json_load_file("/tmp/.pear_speedtest_servers_cn.php", JSON_DECODE_ANY, &error); + if (json_head) + { total_pages = __pear_speedtest_cn_get_meta_data(json_head); // __pear_speedtest_cn_get_server_data(json_head, 1, client_info, server_info, server_num, what_is_my_country); - } + } /* get server data */ int page; - for (page = 1; page <= 10 && page < total_pages; page++) { + for (page = 1; page <= 10 && page < total_pages; page++) + { char url[256]; snprintf(url, 256, "https://forge.speedtest.cn/api/speedtest/nodes?page=%d", page); pear_download_file("GET", url, header, NULL, 0, 15, 30, "/tmp/.pear_speedtest_servers_cn.php"); - json_next = json_load_file("/tmp/.pear_speedtest_servers_cn.php", JSON_DECODE_ANY, &error); - if (!json_next) { - continue; - } + json_next = json_load_file("/tmp/.pear_speedtest_servers_cn.php", JSON_DECODE_ANY, &error); + if (!json_next) + { + continue; + } __pear_speedtest_cn_get_server_data(json_next, 1, client_info, server_info, server_num, what_is_my_country); json_decref(json_next); } /* if nodes less than 10, add some nodes without checking operator */ - if (pear_speedtest_cn_count(server_info, server_num) < 10) { + if (pear_speedtest_cn_count(server_info, server_num) < 10) + { __pear_speedtest_cn_get_server_data(json_head, 0, client_info, server_info, server_num, what_is_my_country); } - if (json_head) { + if (json_head) + { json_decref(json_head); } return 0; } +static char *modify_server_url(char *serverUrl, const char *urlFile) +{ + size_t urlSize = strlen(serverUrl); + char *upload = strstr(serverUrl, "upload.php"); + if (upload == NULL) + { + printf("Download URL parsing error - cannot find upload.php in %s\n", + serverUrl); + exit(1); + } + size_t uploadSize = strlen(upload); + size_t totalSize = (urlSize - uploadSize) + + strlen(urlFile) + 1; + char *result = (char *)malloc(sizeof(char) * totalSize); + result[(urlSize - uploadSize)] = '\0'; + memcpy(result, serverUrl, urlSize - uploadSize); + strcat(result, urlFile); + return result; +} + +char *get_server_download_url(char *serverUrl) +{ + return modify_server_url(serverUrl, "random4000x4000.jpg"); +} + +char *get_latency_url(char *serverUrl) +{ + return modify_server_url(serverUrl, "latency.txt"); +} + +pear_speedtest_server_info_t** pear_speedtest_get_some_server_v2(int* server_cnt, int debug) +{ + char *header[] = {pear_speedtest_header_info.user_agent, "Cache-Control: no-cache", NULL}; + if (!debug) + { + pear_download_file("GET", "http://c.speedtest.net/speedtest-servers-static.php", header, NULL, 0, 30, 300, "/tmp/.pear_speedtest_servers.php"); + } + pear_speedtest_server_info_t** list = NULL; + *server_cnt = 0; + + node_t *root = roxml_load_doc("/tmp/.pear_speedtest_servers.php"); + if (root == NULL) + { + fprintf(stderr, "roxml_load_doc failed\n"); + goto failed_to_release_buffer; + } + + // find first server node + // + node_t *server = roxml_get_chld(root, NULL, 0); + while (server != NULL) + { + char server_name[32] = {0}; + roxml_get_name(server, server_name, 32); + if (!strcmp(server_name, "server")) + { + break; + } + server = roxml_get_chld(server, NULL, 0); + } + + if (server == NULL) + { + goto failed_to_release_xml; + } + + // find min distance servers + // + while (server != NULL) + { + char country[64] = {0}; + node_t *attr_country = roxml_get_attr(server, "country", 0); + if (NULL == attr_country) + goto failed_to_release_xml; + char *country_string = roxml_get_content(attr_country, 0, 0, 0); + if (NULL == country_string) + goto failed_to_release_xml; + strcpy(country, country_string); + free(country_string); + + pear_speedtest_server_info_t s_info; + + // sponsor + // + node_t *attr_sponsor = roxml_get_attr(server, "sponsor", 0); + if (NULL == attr_sponsor) + goto failed_to_release_xml; + char *sponsor_string = roxml_get_content(attr_sponsor, 0, 0, 0); + if (NULL == sponsor_string) + goto failed_to_release_xml; + strncpy(s_info.sponsor, sponsor_string, PEAR_SPEEDTEST_SPONSOR_LEN); + free(sponsor_string); + // carrieroperator + // (China Mobile Group XinJiang, China Unicom Heilongjiang, China Telecom) + // + + // url + // + node_t *attr_url = roxml_get_attr(server, "url", 0); + if (NULL == attr_url) + goto failed_to_release_xml; + char *url_string = roxml_get_content(attr_url, 0, 0, 0); + if (NULL == url_string) + goto failed_to_release_xml; + strncpy(s_info.url_upload, url_string, PEAR_SPEEDTEST_URL_LEN); + strncpy(s_info.url_download, url_string, PEAR_SPEEDTEST_URL_LEN); + free(url_string); + + // lat + // + node_t *attr_lat = roxml_get_attr(server, "lat", 0); + if (NULL == attr_lat) + goto failed_to_release_xml; + char *lat_string = roxml_get_content(attr_lat, 0, 0, 0); + if (NULL == lat_string) + goto failed_to_release_xml; + s_info.lat = atof(lat_string); + free(lat_string); + + // lon + // + node_t *attr_lon = roxml_get_attr(server, "lon", 0); + if (NULL == attr_lon) + goto failed_to_release_xml; + char *lon_string = roxml_get_content(attr_lon, 0, 0, 0); + if (NULL == lon_string) + goto failed_to_release_xml; + s_info.lon = atof(lon_string); + free(lon_string); + // calc distance + // + *server_cnt = *server_cnt+1; + + list = (pear_speedtest_server_info_t**)realloc(list, sizeof(pear_speedtest_server_info_t**)*(*server_cnt)); + + if (list == NULL) { + fprintf(stderr, "unable to allocate memory for servers\n"); + exit(1); + } + printf("the cnt is:%s\n", *server_cnt); + list[*server_cnt -1] = malloc(sizeof(pear_speedtest_server_info_t)); + PEAR_SPEEDTEST_COPY_SERVERINFO((*list[*server_cnt-1]), s_info); + server = roxml_get_next_sibling(server); + } + roxml_close(root); + return list; + +failed_to_release_xml: + roxml_close(root); + +failed_to_release_buffer: + return NULL; +} + +int get_best_server(pear_speedtest_client_info_t *client_info, + pear_speedtest_server_info_t *server_info, int server_num, + char *what_is_my_country, + int debug) +{ + int servernum = 0; + pear_speedtest_server_info_t**list = pear_speedtest_get_some_server_v2(&servernum, debug); + if (list == NULL) return -1; + + printf("the servernum is:%d\n", servernum); + for (int i=0; i < servernum; i++) { + printf("%s\n", list[i]->sponsor); + } + for (int i=0; iups = 0; + + curl = curl_easy_init(); + // set_share_handle(curl); + + /* user options + */ + curl_headers = curl_slist_append(curl_headers, "Content-Type: application/octet-stream"); + if (pear_speedtest_header_info.user_agent) { + curl_headers = curl_slist_append(curl_headers, pear_speedtest_header_info.user_agent); + } + if (pear_speedtest_header_info.origin) { + curl_headers = curl_slist_append(curl_headers, pear_speedtest_header_info.origin); + } + if (pear_speedtest_header_info.referer) { + curl_headers = curl_slist_append(curl_headers, pear_speedtest_header_info.referer); + } + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers); + + /* inner options + */ + curl_easy_setopt(curl, CURLOPT_URL, server_info->url_upload); + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, _read_callback); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20L); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); /* in threads, if set, not signal handle to deal with SIGPIPE */ + + /* perform + */ + struct timeval tval_start; + gettimeofday(&tval_start, NULL); + + double total_bytes = 0; + for(int i = 0; i < 3; i++) { + res = curl_easy_perform(curl); + if(CURLE_OK == res || CURLE_OPERATION_TIMEDOUT == res) { + double val = 0.0; + res = curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &val); + if(CURLE_OK == res && val > 0) { + total_bytes += val; + // printf("val: %f\n", val); + } + } + } + double elapsed_seconds = get_elapsed_time(tval_start); + + server_info->ups = total_bytes / elapsed_seconds; + + curl_easy_cleanup(curl); + curl_slist_free_all(curl_headers); + pthread_exit((void *)(server_info->ups)); +} + +void pear_speedtest_upload_test_v2(pear_speedtest_upload_info_t *upload_info, + pear_speedtest_server_info_t *server_info, int server_num) +{ + #define SPEEDTEST_THREAD_NUM 20 + pthread_t tid[SPEEDTEST_THREAD_NUM]; + + // start thread to download + // + int i; + + for (i = 0; i < server_num; i++) { + strcpy(server_info[i].url_upload, server_info[0].url_upload); + if (!server_info[i].set_value_flag) + continue; + printf("[speedtest v2] upload %s\n", server_info[i].url_upload); + int ret = pthread_create(&tid[i], NULL, __upload_thread, (void *)(server_info + i)); + if(ret != 0) { + server_info[i].set_value_flag = 0; + printf("Couldn't run thread number %d, errno %d\n", i, ret); + } + } + + // wait thread to stop + // + upload_info->speed_bytes_second = 0; + + for (i = 0; i < server_num; i++) { + if (!server_info[i].set_value_flag) { + continue; + } + int ret = pthread_join(tid[i], NULL); + if (ret == 0) { + printf("Upload Thread %d, upload: %ld bytes/sec\n", i, server_info[i].ups); + } + if (server_info[i].ups > 0) { + upload_info->speed_bytes_second += server_info[i].ups; + } + } +} + void pear_speedtest_upload_test(pear_speedtest_upload_info_t *upload_info, pear_speedtest_server_info_t *server_info, int server_num) { diff --git a/libpear/libpear_speedtest/libpear_upload_test.h b/libpear/libpear_speedtest/libpear_upload_test.h index e5f8d84..1486c0f 100644 --- a/libpear/libpear_speedtest/libpear_upload_test.h +++ b/libpear/libpear_speedtest/libpear_upload_test.h @@ -14,6 +14,8 @@ typedef struct { void pear_speedtest_upload_test(pear_speedtest_upload_info_t *upload_info, pear_speedtest_server_info_t *server_info, int server_num); +void pear_speedtest_upload_test_v2(pear_speedtest_upload_info_t *upload_info, pear_speedtest_server_info_t *server_info, int server_num); + void pear_speedtest_cn_upload_test(pear_speedtest_upload_info_t *upload_info, pear_speedtest_server_info_t *server_info, int server_num); diff --git a/pear_build.sh b/pear_build.sh index 2201765..ab0b59c 100755 --- a/pear_build.sh +++ b/pear_build.sh @@ -30,7 +30,7 @@ MONITOR_RELEASE_DIR="${PROJECTS_DIR}/Node-update/update-data" ## toggle to compile ## -PLATFORM_TOGGLE=(0 #PEAR_X64_UBUNTU +PLATFORM_TOGGLE=(1 #PEAR_X64_UBUNTU 0 #PEAR_X86_UBUNTU 0 #PEAR_1200_ARM_LINUX huawei router 0 #PEAR_1300_MT7621_OPENWRT gaoke router @@ -55,20 +55,20 @@ PLATFORM_TOGGLE=(0 #PEAR_X64_UBUNTU 0 #PEAR_1100_X64_OPENWRT nextwifi 0 #PEAR_1400_MIPS_OPENWRT youku router 0 #PEAR_1500_MT7621_PANDVAN panvan router - 1 #PEAR_1600_X64_UBUNTU jack mine ubuntu (must compile in 16.04 ubuntu, docker) + 0 #PEAR_1600_X64_UBUNTU jack mine ubuntu (must compile in 16.04 ubuntu, docker) 0 #PEAR_1700_MIPS_OPENWRT jcg router 0 #PEAR_1800_MIPS_OPENWRT renren_yingshi router - 1 #PEAR_1801_X64_LINUX renren_yingshi ubuntu (must compile in 16.04 ubuntu, docker) - 1 #PEAR_1900_X64_LINUX pear (must compile in 16.04 ubuntu, docker) + 0 #PEAR_1801_X64_LINUX renren_yingshi ubuntu (must compile in 16.04 ubuntu, docker) + 0 #PEAR_1900_X64_LINUX pear (must compile in 16.04 ubuntu, docker) 0 #PEAR_2000_MIPS_OPENWRT fog fan(fork from PEAR_1400_MIPS_OPENWRT) - 1 #PEAR_2100_X64_LINUX pear (must compile in 16.04 ubuntu, docker) - 1 #PEAR_2200_X64_LINUX pear (must compile in 16.04 ubuntu, docker) - 1 #PEAR_2300_X64_LINUX pear (must compile in 16.04 ubuntu, docker) - 1 #PEAR_2400_X64_LINUX pear (must compile in 16.04 ubuntu, docker) - 1 #PEAR_2500_X64_LINUX pear (must compile in 16.04 ubuntu, docker) + 0 #PEAR_2100_X64_LINUX pear (must compile in 16.04 ubuntu, docker) + 0 #PEAR_2200_X64_LINUX pear (must compile in 16.04 ubuntu, docker) + 0 #PEAR_2300_X64_LINUX pear (must compile in 16.04 ubuntu, docker) + 0 #PEAR_2400_X64_LINUX pear (must compile in 16.04 ubuntu, docker) + 0 #PEAR_2500_X64_LINUX pear (must compile in 16.04 ubuntu, docker) 0 #PEAR_3000_MIPS_OPENWRT qihu 360 0 #PEAR_1902_MIPS_OPENWRT newifi - 1 #PEAR_1905_X64_LINUX pear (must compile in 16.04 ubuntu, not docker) + 0 #PEAR_1905_X64_LINUX pear (must compile in 16.04 ubuntu, not docker) ) ## don't break order, just add to tail when have new platform diff --git a/pear_monitor/pear_speed.c b/pear_monitor/pear_speed.c index dec25e3..9b4dfd3 100644 --- a/pear_monitor/pear_speed.c +++ b/pear_monitor/pear_speed.c @@ -69,7 +69,7 @@ static int __get_speed(pear_speedtest_upload_info_t *upload_info, pear_speedtest // record some servers(according to min distance[lat, lon]) // - if (pear_speedtest_get_some_server(&client_info, server_info, threads, "China", pear_speed_info.speed_not_download) < 0) { + if (get_best_server(&client_info, server_info, threads, "China", pear_speed_info.speed_not_download) < 0) { goto speedtest_failed; } int i; @@ -84,10 +84,11 @@ static int __get_speed(pear_speedtest_upload_info_t *upload_info, pear_speedtest server_info[i].dis); } } + exit(0); // upload test // - pear_speedtest_upload_test(upload_info, server_info, threads); + pear_speedtest_upload_test_v2(upload_info, server_info, threads); printf("--> total upload: %f bytes/sec\n\n", upload_info->speed_bytes_second); // download test @@ -305,6 +306,7 @@ int pear_get_speed(int threads) /* do speedtest */ ret1 = __get_speed(upload_info + 0, download_info + 0, threads); + exit(0); ret2 = __get_speed_cn(upload_info + 1, download_info + 1, threads); pear_speed_info.speed_interval = PEAR_SPEEDTEST_NORMAL_INTERVAL; -- Gitee From 30072ee966aa54df21436f0063cf4df859f4faa9 Mon Sep 17 00:00:00 2001 From: LiuzhouChan Date: Thu, 6 Jun 2019 18:02:05 +0800 Subject: [PATCH 2/5] add upload --- .../libpear_speedtest/libpear_get_client.h | 7 + .../libpear_speedtest/libpear_get_server.c | 173 ---- .../libpear_speedtest/libpear_get_server.h | 9 - .../libpear_speedtest/libpear_upload_test.c | 938 ++++++++++++++---- .../libpear_speedtest/libpear_upload_test.h | 4 +- pear_monitor/pear_speed.c | 14 +- 6 files changed, 777 insertions(+), 368 deletions(-) diff --git a/libpear/libpear_speedtest/libpear_get_client.h b/libpear/libpear_speedtest/libpear_get_client.h index eeb71d6..a83b9a0 100644 --- a/libpear/libpear_speedtest/libpear_get_client.h +++ b/libpear/libpear_speedtest/libpear_get_client.h @@ -6,6 +6,11 @@ #define PEAR_SPEEDTEST_ISP_LEN 64 #define PEAR_SPEEDTEST_COUNTRY_LEN 32 +typedef struct ThreadConfig +{ + int threadsCount; /* number of threads */ + int length; /* testlength? */ +} THREADCONFIG_T; typedef struct { char ip[PEAR_SPEEDTEST_IP_LEN]; @@ -14,6 +19,8 @@ typedef struct { int isp_n; // 1->mobile, 2->unicom, 3->telecom char isp[PEAR_SPEEDTEST_ISP_LEN]; char country[PEAR_SPEEDTEST_COUNTRY_LEN]; + THREADCONFIG_T uploadThreadConfig; + THREADCONFIG_T downloadThreadConfig; }pear_speedtest_client_info_t; diff --git a/libpear/libpear_speedtest/libpear_get_server.c b/libpear/libpear_speedtest/libpear_get_server.c index 1fc8ab8..77a7487 100644 --- a/libpear/libpear_speedtest/libpear_get_server.c +++ b/libpear/libpear_speedtest/libpear_get_server.c @@ -551,176 +551,3 @@ int pear_speedtest_cn_get_some_server(pear_speedtest_client_info_t *client_info, return 0; } -static char *modify_server_url(char *serverUrl, const char *urlFile) -{ - size_t urlSize = strlen(serverUrl); - char *upload = strstr(serverUrl, "upload.php"); - if (upload == NULL) - { - printf("Download URL parsing error - cannot find upload.php in %s\n", - serverUrl); - exit(1); - } - size_t uploadSize = strlen(upload); - size_t totalSize = (urlSize - uploadSize) + - strlen(urlFile) + 1; - char *result = (char *)malloc(sizeof(char) * totalSize); - result[(urlSize - uploadSize)] = '\0'; - memcpy(result, serverUrl, urlSize - uploadSize); - strcat(result, urlFile); - return result; -} - -char *get_server_download_url(char *serverUrl) -{ - return modify_server_url(serverUrl, "random4000x4000.jpg"); -} - -char *get_latency_url(char *serverUrl) -{ - return modify_server_url(serverUrl, "latency.txt"); -} - -pear_speedtest_server_info_t** pear_speedtest_get_some_server_v2(int* server_cnt, int debug) -{ - char *header[] = {pear_speedtest_header_info.user_agent, "Cache-Control: no-cache", NULL}; - - if (!debug) - { - pear_download_file("GET", "http://c.speedtest.net/speedtest-servers-static.php", header, NULL, 0, 30, 300, "/tmp/.pear_speedtest_servers.php"); - } - pear_speedtest_server_info_t** list = NULL; - *server_cnt = 0; - - node_t *root = roxml_load_doc("/tmp/.pear_speedtest_servers.php"); - if (root == NULL) - { - fprintf(stderr, "roxml_load_doc failed\n"); - goto failed_to_release_buffer; - } - - // find first server node - // - node_t *server = roxml_get_chld(root, NULL, 0); - while (server != NULL) - { - char server_name[32] = {0}; - roxml_get_name(server, server_name, 32); - if (!strcmp(server_name, "server")) - { - break; - } - server = roxml_get_chld(server, NULL, 0); - } - - if (server == NULL) - { - goto failed_to_release_xml; - } - - // find min distance servers - // - while (server != NULL) - { - char country[64] = {0}; - node_t *attr_country = roxml_get_attr(server, "country", 0); - if (NULL == attr_country) - goto failed_to_release_xml; - char *country_string = roxml_get_content(attr_country, 0, 0, 0); - if (NULL == country_string) - goto failed_to_release_xml; - strcpy(country, country_string); - free(country_string); - - pear_speedtest_server_info_t s_info; - - // sponsor - // - node_t *attr_sponsor = roxml_get_attr(server, "sponsor", 0); - if (NULL == attr_sponsor) - goto failed_to_release_xml; - char *sponsor_string = roxml_get_content(attr_sponsor, 0, 0, 0); - if (NULL == sponsor_string) - goto failed_to_release_xml; - strncpy(s_info.sponsor, sponsor_string, PEAR_SPEEDTEST_SPONSOR_LEN); - free(sponsor_string); - // carrieroperator - // (China Mobile Group XinJiang, China Unicom Heilongjiang, China Telecom) - // - - // url - // - node_t *attr_url = roxml_get_attr(server, "url", 0); - if (NULL == attr_url) - goto failed_to_release_xml; - char *url_string = roxml_get_content(attr_url, 0, 0, 0); - if (NULL == url_string) - goto failed_to_release_xml; - strncpy(s_info.url_upload, url_string, PEAR_SPEEDTEST_URL_LEN); - strncpy(s_info.url_download, url_string, PEAR_SPEEDTEST_URL_LEN); - free(url_string); - - // lat - // - node_t *attr_lat = roxml_get_attr(server, "lat", 0); - if (NULL == attr_lat) - goto failed_to_release_xml; - char *lat_string = roxml_get_content(attr_lat, 0, 0, 0); - if (NULL == lat_string) - goto failed_to_release_xml; - s_info.lat = atof(lat_string); - free(lat_string); - - // lon - // - node_t *attr_lon = roxml_get_attr(server, "lon", 0); - if (NULL == attr_lon) - goto failed_to_release_xml; - char *lon_string = roxml_get_content(attr_lon, 0, 0, 0); - if (NULL == lon_string) - goto failed_to_release_xml; - s_info.lon = atof(lon_string); - free(lon_string); - // calc distance - // - *server_cnt = *server_cnt+1; - - list = (pear_speedtest_server_info_t**)realloc(list, sizeof(pear_speedtest_server_info_t**)*(*server_cnt)); - - if (list == NULL) { - fprintf(stderr, "unable to allocate memory for servers\n"); - exit(1); - } - printf("the cnt is:%s\n", *server_cnt); - list[*server_cnt -1] = malloc(sizeof(pear_speedtest_server_info_t)); - PEAR_SPEEDTEST_COPY_SERVERINFO((*list[*server_cnt-1]), s_info); - server = roxml_get_next_sibling(server); - } - roxml_close(root); - return list; - -failed_to_release_xml: - roxml_close(root); - -failed_to_release_buffer: - return NULL; -} - -int get_best_server(pear_speedtest_client_info_t *client_info, - pear_speedtest_server_info_t *server_info, int server_num, - char *what_is_my_country, - int debug) -{ - int servernum = 0; - pear_speedtest_server_info_t**list = pear_speedtest_get_some_server_v2(&servernum, debug); - if (list == NULL) return -1; - - printf("the servernum is:%d\n", servernum); - for (int i=0; i < servernum; i++) { - printf("%s\n", list[i]->sponsor); - } - for (int i=0; i #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include "libpear_get_header.h" #include "libpear_upload_test.h" - +#include "libpear_get_client.h" // void pear_speedtest_upload_set_prevalue(pear_speedtest_upload_info_t *upload_info, int n, double prevalue) // { @@ -15,27 +23,25 @@ // } // } - -static void pear_speedtest_cn_uuid(char *uuid) -{ - char *e = "0123456789abcdef"; - int temp=0; - int index=0; - for (int i = 0; i < 36; i++) - { - temp=random() % 16; - uuid[i] = e[temp]; - } - uuid[14] = '4'; - uuid[8] = '-'; - uuid[13] ='-'; - uuid[18] ='-'; - uuid[23] = '-'; - index=((3 & uuid[19] ) | 8); - uuid[19] = e[index]; +static void pear_speedtest_cn_uuid(char *uuid) +{ + char *e = "0123456789abcdef"; + int temp = 0; + int index = 0; + for (int i = 0; i < 36; i++) + { + temp = random() % 16; + uuid[i] = e[temp]; + } + uuid[14] = '4'; + uuid[8] = '-'; + uuid[13] = '-'; + uuid[18] = '-'; + uuid[23] = '-'; + index = ((3 & uuid[19]) | 8); + uuid[19] = e[index]; } - static size_t _read_callback(char *buffer, size_t size, size_t nitems, void *userdata) { int i; @@ -43,7 +49,8 @@ static size_t _read_callback(char *buffer, size_t size, size_t nitems, void *use int r = random(); size_t total_size = size * nitems; - for (i = 0; i < total_size; i += 4) { + for (i = 0; i < total_size; i += 4) + { value = (int *)(buffer + i); *value = r + i; } @@ -51,7 +58,6 @@ static size_t _read_callback(char *buffer, size_t size, size_t nitems, void *use return total_size; } - static void __post_one_url(void *para) { CURL *curl; @@ -66,13 +72,16 @@ static void __post_one_url(void *para) /* user options */ curl_headers = curl_slist_append(curl_headers, "Content-Type: application/octet-stream"); - if (pear_speedtest_header_info.user_agent) { + if (pear_speedtest_header_info.user_agent) + { curl_headers = curl_slist_append(curl_headers, pear_speedtest_header_info.user_agent); } - if (pear_speedtest_header_info.origin) { + if (pear_speedtest_header_info.origin) + { curl_headers = curl_slist_append(curl_headers, pear_speedtest_header_info.origin); } - if (pear_speedtest_header_info.referer) { + if (pear_speedtest_header_info.referer) + { curl_headers = curl_slist_append(curl_headers, pear_speedtest_header_info.referer); } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers); @@ -84,154 +93,59 @@ static void __post_one_url(void *para) curl_easy_setopt(curl, CURLOPT_READFUNCTION, _read_callback); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20L); - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); /* in threads, if set, not signal handle to deal with SIGPIPE */ + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); /* in threads, if set, not signal handle to deal with SIGPIPE */ /* perform */ res = curl_easy_perform(curl); - if(CURLE_OK == res || CURLE_OPERATION_TIMEDOUT == res) { + if (CURLE_OK == res || CURLE_OPERATION_TIMEDOUT == res) + { double val = 0.0; res = curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &val); - if(CURLE_OK == res && val > 0) { + if (CURLE_OK == res && val > 0) + { server_info->ups = val; // printf("val: %f\n", val); } } - - curl_easy_cleanup(curl); - curl_slist_free_all(curl_headers); - pthread_exit((void *)(server_info->ups)); -} - - -static double get_elapsed_time(struct timeval tval_start) { - struct timeval tval_end, tval_diff; - gettimeofday(&tval_end, NULL); - tval_diff.tv_sec = tval_end.tv_sec - tval_start.tv_sec; - tval_diff.tv_usec = tval_end.tv_usec - tval_start.tv_usec; - if(tval_diff.tv_usec < 0) { - --tval_diff.tv_sec; - tval_diff.tv_usec += 1000000; - } - return (double)tval_diff.tv_sec + (double)tval_diff.tv_usec / 1000000; -} - - -static void __upload_thread(void* para) { - CURL *curl; - CURLcode res; - struct curl_slist *curl_headers = NULL; - pear_speedtest_server_info_t *server_info = (pear_speedtest_server_info_t *)para; - server_info->ups = 0; - - curl = curl_easy_init(); - // set_share_handle(curl); - - /* user options - */ - curl_headers = curl_slist_append(curl_headers, "Content-Type: application/octet-stream"); - if (pear_speedtest_header_info.user_agent) { - curl_headers = curl_slist_append(curl_headers, pear_speedtest_header_info.user_agent); - } - if (pear_speedtest_header_info.origin) { - curl_headers = curl_slist_append(curl_headers, pear_speedtest_header_info.origin); - } - if (pear_speedtest_header_info.referer) { - curl_headers = curl_slist_append(curl_headers, pear_speedtest_header_info.referer); - } - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers); - - /* inner options - */ - curl_easy_setopt(curl, CURLOPT_URL, server_info->url_upload); - curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); - curl_easy_setopt(curl, CURLOPT_READFUNCTION, _read_callback); - curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L); - curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20L); - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); /* in threads, if set, not signal handle to deal with SIGPIPE */ - - /* perform - */ - struct timeval tval_start; - gettimeofday(&tval_start, NULL); - - double total_bytes = 0; - for(int i = 0; i < 3; i++) { - res = curl_easy_perform(curl); - if(CURLE_OK == res || CURLE_OPERATION_TIMEDOUT == res) { - double val = 0.0; - res = curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &val); - if(CURLE_OK == res && val > 0) { - total_bytes += val; - // printf("val: %f\n", val); - } - } - } - double elapsed_seconds = get_elapsed_time(tval_start); - - server_info->ups = total_bytes / elapsed_seconds; curl_easy_cleanup(curl); curl_slist_free_all(curl_headers); pthread_exit((void *)(server_info->ups)); } -void pear_speedtest_upload_test_v2(pear_speedtest_upload_info_t *upload_info, - pear_speedtest_server_info_t *server_info, int server_num) +static double getElapsedTime(struct timeval tval_start) { - #define SPEEDTEST_THREAD_NUM 20 - pthread_t tid[SPEEDTEST_THREAD_NUM]; - - // start thread to download - // - int i; - - for (i = 0; i < server_num; i++) { - strcpy(server_info[i].url_upload, server_info[0].url_upload); - if (!server_info[i].set_value_flag) - continue; - printf("[speedtest v2] upload %s\n", server_info[i].url_upload); - int ret = pthread_create(&tid[i], NULL, __upload_thread, (void *)(server_info + i)); - if(ret != 0) { - server_info[i].set_value_flag = 0; - printf("Couldn't run thread number %d, errno %d\n", i, ret); - } - } - - // wait thread to stop - // - upload_info->speed_bytes_second = 0; - - for (i = 0; i < server_num; i++) { - if (!server_info[i].set_value_flag) { - continue; - } - int ret = pthread_join(tid[i], NULL); - if (ret == 0) { - printf("Upload Thread %d, upload: %ld bytes/sec\n", i, server_info[i].ups); - } - if (server_info[i].ups > 0) { - upload_info->speed_bytes_second += server_info[i].ups; - } + struct timeval tval_end, tval_diff; + gettimeofday(&tval_end, NULL); + tval_diff.tv_sec = tval_end.tv_sec - tval_start.tv_sec; + tval_diff.tv_usec = tval_end.tv_usec - tval_start.tv_usec; + if (tval_diff.tv_usec < 0) + { + --tval_diff.tv_sec; + tval_diff.tv_usec += 1000000; } + return (double)tval_diff.tv_sec + (double)tval_diff.tv_usec / 1000000; } -void pear_speedtest_upload_test(pear_speedtest_upload_info_t *upload_info, +void pear_speedtest_upload_test(pear_speedtest_upload_info_t *upload_info, pear_speedtest_server_info_t *server_info, int server_num) { - #define SPEEDTEST_THREAD_NUM 20 +#define SPEEDTEST_THREAD_NUM 20 pthread_t tid[SPEEDTEST_THREAD_NUM]; // start thread to download // int i; - for (i = 0; i < server_num; i++) { + for (i = 0; i < server_num; i++) + { if (!server_info[i].set_value_flag) continue; printf("[speedtest] upload %s\n", server_info[i].url_upload); int ret = pthread_create(&tid[i], NULL, __post_one_url, (void *)(server_info + i)); - if(ret != 0) { + if (ret != 0) + { server_info[i].set_value_flag = 0; printf("Couldn't run thread number %d, errno %d\n", i, ret); } @@ -241,34 +155,39 @@ void pear_speedtest_upload_test(pear_speedtest_upload_info_t *upload_info, // upload_info->speed_bytes_second = 0; - for (i = 0; i < server_num; i++) { - if (!server_info[i].set_value_flag) { + for (i = 0; i < server_num; i++) + { + if (!server_info[i].set_value_flag) + { continue; } int ret = pthread_join(tid[i], NULL); - if (ret == 0) { + if (ret == 0) + { printf("Upload Thread %d, upload: %ld bytes/sec\n", i, server_info[i].ups); } - if (server_info[i].ups > 0) { + if (server_info[i].ups > 0) + { upload_info->speed_bytes_second += server_info[i].ups; } } } - -void pear_speedtest_cn_upload_test(pear_speedtest_upload_info_t *upload_info, - pear_speedtest_server_info_t *server_info, - int server_num) +void pear_speedtest_cn_upload_test(pear_speedtest_upload_info_t *upload_info, + pear_speedtest_server_info_t *server_info, + int server_num) { - #define SPEEDTEST_THREAD_NUM 20 +#define SPEEDTEST_THREAD_NUM 20 pthread_t tid[SPEEDTEST_THREAD_NUM] = {0X00}; - char uuid[64] = {0X00}; + char uuid[64] = {0X00}; // start threads to upload // int i; - for (i = 0; i < server_num; i++) { - if (!server_info[i].set_value_flag) { + for (i = 0; i < server_num; i++) + { + if (!server_info[i].set_value_flag) + { continue; } memset(uuid, 0X00, sizeof(uuid)); @@ -280,12 +199,15 @@ void pear_speedtest_cn_upload_test(pear_speedtest_upload_info_t *upload_info, printf("[speedtest.cn] upload %s %s\n", server_info[i].operator, server_info[i].url_upload); } - for (i = 0; i < server_num; i++) { - if (!server_info[i].set_value_flag) { + for (i = 0; i < server_num; i++) + { + if (!server_info[i].set_value_flag) + { continue; } int ret = pthread_create(&tid[i], NULL, __post_one_url, (void *)(server_info + i)); - if(ret != 0) { + if (ret != 0) + { server_info[i].set_value_flag = 0; printf("Couldn't run thread number %d, errno %d\n", i, ret); } @@ -295,21 +217,24 @@ void pear_speedtest_cn_upload_test(pear_speedtest_upload_info_t *upload_info, // upload_info->speed_bytes_second = 0; - for (i = 0; i < server_num; i++) { - if (!server_info[i].set_value_flag) { + for (i = 0; i < server_num; i++) + { + if (!server_info[i].set_value_flag) + { continue; } int ret = pthread_join(tid[i], NULL); - if (ret == 0) { + if (ret == 0) + { printf("Upload Thread %d terminated: %ld bytes/sec\n", i, server_info[i].ups); } - if (server_info[i].ups > 0) { + if (server_info[i].ups > 0) + { upload_info->speed_bytes_second += server_info[i].ups; } } } - int pear_speedtest_upload_optimize(pear_speedtest_server_info_t *server_info, int server_num) { int i; @@ -322,34 +247,44 @@ int pear_speedtest_upload_optimize(pear_speedtest_server_info_t *server_info, in /* calc valid count */ - for (i = 0; i < server_num; i++) { - if(server_info[i].ups > 0) { + for (i = 0; i < server_num; i++) + { + if (server_info[i].ups > 0) + { map[i] = 1; valid_count++; tmp_valid_count++; - } else { + } + else + { map[i] = -1; } } /* check whether need to optimize */ - if ((valid_count > server_num) || (valid_count <= 0)) { + if ((valid_count > server_num) || (valid_count <= 0)) + { return -1; } /* set copy count */ unvalid_count = server_num - valid_count; - average_count = (unvalid_count > valid_count)? (unvalid_count / valid_count):1; - - for (i = 0; i < server_num && unvalid_count > 0; i++) { - if(map[i] > 0) { - if (tmp_valid_count > 0) { + average_count = (unvalid_count > valid_count) ? (unvalid_count / valid_count) : 1; + + for (i = 0; i < server_num && unvalid_count > 0; i++) + { + if (map[i] > 0) + { + if (tmp_valid_count > 0) + { map[i] = average_count; unvalid_count -= average_count; // printf("i = %d, value: %d\n", i, map[i]); - } else { + } + else + { map[i] = unvalid_count; unvalid_count = 0; // printf("i = %d, value: %d\n", i, map[i]); @@ -362,18 +297,25 @@ int pear_speedtest_upload_optimize(pear_speedtest_server_info_t *server_info, in /* */ - for (i = 0, j = 0; i < server_num && j < server_num;) { - if (map[j] < 0) { - if(map[i] > 0) { + for (i = 0, j = 0; i < server_num && j < server_num;) + { + if (map[j] < 0) + { + if (map[i] > 0) + { // printf("(i, j) --> (%d, %d)\n", i, j); // memcpy(server_info + j, server_info + i, sizeof(pear_speedtest_server_info_t)); memcpy(server_info[j].url_upload, server_info[i].url_upload, PEAR_SPEEDTEST_URL_LEN); map[i] -= 1; ++j; - } else { - ++i; } - } else { + else + { + ++i; + } + } + else + { ++j; } } @@ -381,3 +323,645 @@ int pear_speedtest_upload_optimize(pear_speedtest_server_info_t *server_info, in return 0; } +// ---url ------------------------------------------------------------------------- +typedef struct +{ + char *address; + int addressLen; + char *request; + int requestLen; + char *protocol; + int protocolLen; + int port; + int ssl; +} URLPARTS_T; + +/*Breaks apart a url into a port, address and request*/ +void breakUrl(const char *pUrl, URLPARTS_T *pUrlStruct) +{ + char url[2048]; + char *ptr2, *ptr1 = url; + strncpy(url, pUrl, sizeof(url)); + pUrlStruct->port = 80; + pUrlStruct->ssl = 0; + /*find protocol (like http:// or ftp://)*/ + ptr2 = strstr(ptr1, "://"); + if (ptr2 != 0) + { + *ptr2 = 0; + if (pUrlStruct->protocolLen > 0) + strncpy(pUrlStruct->protocol, ptr1, pUrlStruct->protocolLen); + + if (strcmp(ptr1, "ftp") == 0) + pUrlStruct->port = 21; + else if (strcmp(ptr1, "https") == 0) + { + pUrlStruct->port = 443; + pUrlStruct->ssl = 1; + } + ptr1 = ptr2 + 3; + } + else if (pUrlStruct->protocolLen > 0) + *pUrlStruct->protocol = 0; + + /*find request (the part starting at "/" after the address and port)*/ + ptr2 = strchr(ptr1, '/'); + if (ptr2 != 0) + { + if (pUrlStruct->requestLen > 0) + strncpy(pUrlStruct->request, ptr2, pUrlStruct->requestLen); + + *ptr2 = 0; + } + else if (pUrlStruct->requestLen > 1) + strncpy(pUrlStruct->request, "/", pUrlStruct->requestLen); + + /*find port (the part after ":")*/ + ptr2 = strchr(ptr1, ':'); + if (ptr2 != 0) + { + pUrlStruct->port = atoi(ptr2 + 1); + *ptr2 = 0; + } + + /*whats left should only be the address*/ + if (pUrlStruct->addressLen > 0) + strncpy(pUrlStruct->address, ptr1, pUrlStruct->addressLen); +} + +int hexToAscii(char pHex) +{ + if (pHex >= '0' && pHex <= '9') + return pHex - '0'; + if (pHex >= 'A' && pHex <= 'F') + return pHex - 'A' + 10; + if (pHex >= 'a' && pHex <= 'f') + return pHex - 'a' + 10; + return 0; +} +/*Decodes the hex parts of the request (e.g %20 is ' ')*/ +void decodeRequest(const char *pRequest, char *pOut, int pOutSize) +{ + char *ptr1 = (char *)pRequest; + int i; + memset(pOut, 0, pOutSize); + for (i = 0; i < pOutSize - 1; i++) + { + if (*ptr1 == 0) + break; + + switch (*ptr1) + { + case '%': + pOut[i] = hexToAscii(*++ptr1) << 4; + pOut[i] += hexToAscii(*++ptr1); + break; + + default: + pOut[i] = *ptr1; + break; + } + ptr1++; + } +} + +//------------------------------------http------------------------------------ +typedef int sock_t; +#define BAD_SOCKID 0 /* should use -1!! */ +int _httpErrorCode = 0; + +int httpLastError() +{ + return _httpErrorCode; +} + +sock_t httpPut(char *pAddress, int pPort, char *pRequest, unsigned long contentSize, int ssl) +{ + char buffer[0xFFFF]; + int sockId; + struct sockaddr_in addr; + struct hostent *hostEntry; + + if ((sockId = (int)socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == 0) + return 0; + + if ((hostEntry = gethostbyname(pAddress)) == NULL) + return 0; + + addr.sin_family = AF_INET; + addr.sin_addr = *((struct in_addr *)*hostEntry->h_addr_list); + addr.sin_port = htons((unsigned short)pPort); + if (connect(sockId, (struct sockaddr *)&addr, + sizeof(struct sockaddr_in)) == -1) + return 0; + + /* TODO: Content-Length isn't set up, this is some kind of "hack". + I cannot understand, but some servers closes up connection too early + even if we set up Content-Lenght to 10 times more than we actually send. + Leaving it uninitialized gives us random high value.*/ + sprintf(buffer, "POST %s HTTP/1.1\r\n" + "Host: %s\r\n" + "User-Agent: SPEEDTEST_CLIENT\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "Connection: keep-alive\r\n" + "Content-Length: %lu\r\n" + "\r\n", + pRequest, pAddress, 100 * contentSize); + + send(sockId, buffer, strlen(buffer), 0); + + return sockId; +} + +sock_t httpGet(char *pAddress, int pPort, char *pRequest, int ssl) +{ + char buffer[0xFFFF], *token; + sock_t sockId; + int s; + struct sockaddr_in addr; + struct hostent *hostEntry; + int length = 0; + int success = 0; + int i; + if ((s = (int)socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == 0) + return 0; + + if ((hostEntry = gethostbyname(pAddress)) == NULL) + return 0; + + addr.sin_family = AF_INET; + addr.sin_addr = *((struct in_addr *)*hostEntry->h_addr_list); + addr.sin_port = htons((unsigned short)pPort); + if (connect(s, (struct sockaddr *)&addr, + sizeof(struct sockaddr_in)) == -1) + return 0; + + sprintf(buffer, "GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "User-Agent: SPEEDTEST_CLIENT\r\n" + "Connection: close\r\n" + "\r\n", + pRequest, pAddress); + + sockId = s; + send(sockId, buffer, strlen(buffer), 0); + + while ((length = recvLine(sockId, buffer, sizeof(buffer))) > 0) + { + /*trim line*/ + for (i = length - 1; i >= 0; i--) + { + if (buffer[i] < ' ') + buffer[i] = 0; + else + break; + } + /*if end of header*/ + if (!strlen(buffer)) + break; + + /*get first word*/ + token = strtok(buffer, " "); + if (token == NULL) + break; + + /*Check http error code*/ + if (strcmp(token, "HTTP/1.0") == 0 || strcmp(token, "HTTP/1.1") == 0) + { + _httpErrorCode = atoi(strtok(NULL, " ")); + if (_httpErrorCode == 200) + success = 1; + } + } + if (!success) + { + close(sockId); + return 0; + } + else + return sockId; +} + +int httpRecv(sock_t pSockId, char *pOut, int pOutSize) +{ + int size; + if ((size = recv(pSockId, pOut, pOutSize, 0)) > 0) + return size; + + return 0; +} + +int httpSend(sock_t pSockId, char *pOut, int pOutSize) +{ + int size; + + if ((size = send(pSockId, pOut, pOutSize, 0)) > 0) + return size; + return 0; +} + +void httpClose(sock_t pSockId) +{ + close(pSockId); +} + +sock_t httpGetRequestSocket(const char *urlToDownload) +{ + char address[1024]; + char request[1024]; + URLPARTS_T url; + sock_t sockId; + + memset(&url, 0, sizeof(url)); + url.address = address; + url.request = request; + url.addressLen = sizeof(address); + url.requestLen = sizeof(request); + breakUrl(urlToDownload, &url); + + sockId = httpGet(address, url.port, request, url.ssl); + if (sockId) + return sockId; + fprintf(stderr, "Http error while creating GET request socket: %i\n", + httpLastError()); + return 0; +} + +sock_t httpPutRequestSocket(const char *urlToUpload, unsigned long contentSize) +{ + char address[1024]; + char request[1024]; + URLPARTS_T url; + sock_t sockId; + + memset(&url, 0, sizeof(url)); + url.address = address; + url.request = request; + url.addressLen = sizeof(address); + url.requestLen = sizeof(request); + + breakUrl(urlToUpload, &url); + + sockId = httpPut(address, url.port, request, contentSize, url.ssl); + if (sockId != BAD_SOCKID) + return sockId; + fprintf(stderr, "Http error while creating PUT request socket: %i\n", + httpLastError()); + return BAD_SOCKID; +} + +static int sockRecv(sock_t pSockId, char *ptr, int len) +{ + return recv(pSockId, ptr, len, 0); +} + +int recvLine(sock_t pSockId, char *pOut, int pOutSize) +{ + int received = 0; + char letter; + memset(pOut, 0, pOutSize); + for (; received < pOutSize - 1; received++) + { + if (sockRecv(pSockId, (char *)&letter, 1) > 0) + { + pOut[received] = letter; + if (letter == '\n') + break; + } + else + break; + } + return received; +} + +//------------------------------config----------------- +#define R 6371 +#define PI 3.1415926536 +#define TO_RAD (PI / 180) + +#ifndef URL_PROTOCOL +#define URL_PROTOCOL "http" +#endif + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(_x) \ + (sizeof(_x) / sizeof(_x[0])) +#endif /* ARRAY_SIZE */ + + +const char *ConfigLineIdentitier[] = {"url = substr; + break; + case 2: + result->lat = strtof(substr, NULL); + free(substr); + break; + case 3: + result->lon = strtof(substr, NULL); + free(substr); + break; + case 4: + result->name = substr; + break; + case 5: + result->country = substr; + break; + case 7: + result->sponsor = substr; + break; + default: + free(substr); + break; + } + } +} + +SPEEDTESTSERVER_T **getServers(int *serverCount, const char *infraUrl) +{ + char buffer[1500] = {0}; + SPEEDTESTSERVER_T **list = NULL; + sock_t sockId = httpGetRequestSocket(infraUrl); + if (sockId) + { + long size; + while ((size = recvLine(sockId, buffer, sizeof(buffer))) > 0) + { + buffer[size + 1] = '\0'; + if (strlen(buffer) > 25) + { + /*Ommiting XML invocation...*/ + if (strstr(buffer, "') + { + *serverCount = *serverCount + 1; + list = (SPEEDTESTSERVER_T **)realloc(list, + sizeof(SPEEDTESTSERVER_T **) * (*serverCount)); + if (list == NULL) + { + fprintf(stderr, "Unable to allocate memory for servers!\n"); + exit(1); + } + list[*serverCount - 1] = malloc(sizeof(SPEEDTESTSERVER_T)); + if (list[*serverCount - 1]) + parseServer(list[*serverCount - 1], buffer); + } + } + } + httpClose(sockId); + return list; + } + return NULL; +} + +static char *modifyServerUrl(char *serverUrl, const char *urlFile) +{ + size_t urlSize = strlen(serverUrl); + char *upload = strstr(serverUrl, "upload.php"); + if (upload == NULL) + { + printf("Download URL parsing error - cannot find upload.php in %s\n", + serverUrl); + exit(1); + } + size_t uploadSize = strlen(upload); + size_t totalSize = (urlSize - uploadSize) + + strlen(urlFile) + 1; + char *result = (char *)malloc(sizeof(char) * totalSize); + result[(urlSize - uploadSize)] = '\0'; + memcpy(result, serverUrl, urlSize - uploadSize); + strcat(result, urlFile); + return result; +} + +char *getServerDownloadUrl(char *serverUrl) +{ + return modifyServerUrl(serverUrl, "random4000x4000.jpg"); +} + +int sortServers(SPEEDTESTSERVER_T **srv1, SPEEDTESTSERVER_T **srv2) +{ + return ((*srv1)->distance - (*srv2)->distance); +} + +void getBestServer(pear_speedtest_client_info_t *speedTestConfig, char*download_url, char* upload_url) +{ + size_t selectedServer = 0; + printf("Your IP: %s And ISP: %s\n", + speedTestConfig->ip, speedTestConfig->isp); + int serverCount = 0; + SPEEDTESTSERVER_T** serverList = getServers(&serverCount, URL_PROTOCOL "://www.speedtest.net/speedtest-servers-static.php"); + if (serverCount == 0) + { + // Primary server is not responding. Let's give a try with secondary one. + serverList = getServers(&serverCount, URL_PROTOCOL "://c.speedtest.net/speedtest-servers-static.php"); + } + printf("Grabbed %d servers\n", serverCount); + if (serverCount == 0) + { + printf("Cannot download any speedtest.net server. Something is wrong...\n"); + exit(1); + } + for (int i = 0; i < serverCount; i++) + serverList[i]->distance = haversineDistance(speedTestConfig->lat, + speedTestConfig->lon, + serverList[i]->lat, + serverList[i]->lon); + qsort(serverList, serverCount, sizeof(SPEEDTESTSERVER_T *), + (int (*)(const void *, const void *))sortServers); + printf("Best Server URL: %s\n\t Name: %s Country: %s Sponsor: %s Dist: %ld km\n", + serverList[selectedServer]->url, serverList[selectedServer]->name, serverList[selectedServer]->country, + serverList[selectedServer]->sponsor, serverList[selectedServer]->distance); + char* downloadUrl = getServerDownloadUrl(serverList[selectedServer]->url); + strcpy(download_url, downloadUrl); + free(downloadUrl); + strcpy(upload_url, serverList[selectedServer]->url); + + for (int i = 0; i < serverCount; i++) + { + free(serverList[i]->url); + free(serverList[i]->name); + free(serverList[i]->sponsor); + free(serverList[i]->country); + free(serverList[i]); + } +} + +//---------------------------------uploadtest---------------------------------------- +static void __appendTimestamp(const char *url, char *buff, int buff_len) +{ + char delim = '?'; + char *p = strchr(url, '?'); + + if (p) + delim = '&'; + snprintf(buff, buff_len, "%s%cx=%llu", url, delim, (unsigned long long)time(NULL)); +} + +typedef struct thread_args +{ + pthread_t tid; + char *url; + unsigned int testCount; + unsigned long transferedBytes; + float elapsedSecs; +} THREADARGS_T; + +#define BUFFER_SIZE 1500 + +unsigned long totalTransfered = 1024 * 1024; +unsigned long totalToBeTransfered = 1024 * 1024; + +static void *__uploadThread(void *arg) +{ + /* Testing upload... */ + THREADARGS_T *threadConfig = (THREADARGS_T *)arg; + char alphabet[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + char buffer[BUFFER_SIZE] = {0}; + int size; + struct timeval tval_start; + unsigned long totalTransfered = 0; + char uploadUrl[1024]; + /* Build the random buffer */ + srand(time(NULL)); + for (int i = 0; i < BUFFER_SIZE; i++) + { + buffer[i] = alphabet[rand() % ARRAY_SIZE(alphabet)]; + } + gettimeofday(&tval_start, NULL); + for (int i = 0; i < threadConfig->testCount; i++) + { + __appendTimestamp(threadConfig->url, uploadUrl, sizeof(uploadUrl)); + /* FIXME: totalToBeTransfered should be readonly while the upload thread is running */ + totalTransfered = totalToBeTransfered; + sock_t sockId = httpPutRequestSocket(uploadUrl, totalToBeTransfered); + if (sockId == 0) + { + printf("Unable to open socket for Upload!"); + pthread_exit(NULL); + } + while (totalTransfered != 0) + { + if (totalTransfered > BUFFER_SIZE) + { + size = httpSend(sockId, buffer, BUFFER_SIZE); + } + else + { + buffer[totalTransfered - 1] = '\n'; /* Indicate terminated */ + size = httpSend(sockId, buffer, totalTransfered); + } + + totalTransfered -= size; + } + threadConfig->transferedBytes += totalToBeTransfered; + /* Cleanup */ + httpClose(sockId); + } + threadConfig->elapsedSecs = getElapsedTime(tval_start); + return NULL; +} + +float testUpload(pear_speedtest_client_info_t *speedTestConfig, const char *url) +{ + size_t numOfThreads = speedTestConfig->uploadThreadConfig.threadsCount; + THREADARGS_T *param = (THREADARGS_T *)calloc(numOfThreads, sizeof(THREADARGS_T)); + int i; + for (i = 0; i < numOfThreads; i++) + { + /* Initializing some parameters */ + param[i].testCount = speedTestConfig->uploadThreadConfig.length; + if (param[i].testCount == 0) + { + /* At least three test should be run */ + param[i].testCount = 3; + } + param[i].url = strdup(url); + if (param[i].url) + { + pthread_create(¶m[i].tid, NULL, &__uploadThread, ¶m[i]); + } + } + + /* Refresh */ + totalTransfered = 0; + float speed = 0; + + /* Wait for all threads */ + for (i = 0; i < numOfThreads; i++) + { + pthread_join(param[i].tid, NULL); + if (param[i].transferedBytes) + { + /* There's no reason that we transfered nothing except error occured */ + totalTransfered += param[i].transferedBytes; + speed += (param[i].transferedBytes / param[i].elapsedSecs) / 1024; + } + /* Cleanup */ + free(param[i].url); + } + free(param); + printf("Bytes %lu uploaded with a speed %.2f kB/s (%.2f Mbit/s)\n", + totalTransfered, speed, speed * 8 / 1024); + return speed*1024; +} + + +void pear_speedtest_upload_test_v2(pear_speedtest_upload_info_t *upload_info, pear_speedtest_client_info_t *client_info, char* upload_url) +{ + float speed = testUpload(client_info, upload_url); + upload_info->speed_bytes_second = (double)speed; +} diff --git a/libpear/libpear_speedtest/libpear_upload_test.h b/libpear/libpear_speedtest/libpear_upload_test.h index 1486c0f..4af9543 100644 --- a/libpear/libpear_speedtest/libpear_upload_test.h +++ b/libpear/libpear_speedtest/libpear_upload_test.h @@ -14,12 +14,10 @@ typedef struct { void pear_speedtest_upload_test(pear_speedtest_upload_info_t *upload_info, pear_speedtest_server_info_t *server_info, int server_num); -void pear_speedtest_upload_test_v2(pear_speedtest_upload_info_t *upload_info, pear_speedtest_server_info_t *server_info, int server_num); - +void pear_speedtest_upload_test_v2(pear_speedtest_upload_info_t *upload_info, pear_speedtest_client_info_t *client_info, char* upload_url); void pear_speedtest_cn_upload_test(pear_speedtest_upload_info_t *upload_info, pear_speedtest_server_info_t *server_info, int server_num); - int pear_speedtest_upload_optimize(pear_speedtest_server_info_t *server_info, int server_num); #endif \ No newline at end of file diff --git a/pear_monitor/pear_speed.c b/pear_monitor/pear_speed.c index 9b4dfd3..c920f87 100644 --- a/pear_monitor/pear_speed.c +++ b/pear_monitor/pear_speed.c @@ -66,10 +66,11 @@ static int __get_speed(pear_speedtest_upload_info_t *upload_info, pear_speedtest client_info.isp_n, client_info.isp, client_info.country); - + client_info.uploadThreadConfig.threadsCount = 2; + client_info.uploadThreadConfig.length = 3; // record some servers(according to min distance[lat, lon]) // - if (get_best_server(&client_info, server_info, threads, "China", pear_speed_info.speed_not_download) < 0) { + if (pear_speedtest_get_some_server(&client_info, server_info, 10, "China", 0) < 0) { goto speedtest_failed; } int i; @@ -84,11 +85,12 @@ static int __get_speed(pear_speedtest_upload_info_t *upload_info, pear_speedtest server_info[i].dis); } } - exit(0); - // upload test - // - pear_speedtest_upload_test_v2(upload_info, server_info, threads); + char download_url[1024] = {0x00}; + char upload_url[1024] = {0x00}; + getBestServer(&client_info, download_url, upload_url); + + pear_speedtest_upload_test_v2(upload_info, &client_info, upload_url); printf("--> total upload: %f bytes/sec\n\n", upload_info->speed_bytes_second); // download test -- Gitee From 6da9f8de7bf1ca75589ef081dc439446220f115c Mon Sep 17 00:00:00 2001 From: LiuzhouChan Date: Thu, 6 Jun 2019 18:54:55 +0800 Subject: [PATCH 3/5] set the global to local --- libpear/libpear_speedtest/libpear_upload_test.c | 6 ++---- pear_monitor/pear_speed.c | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/libpear/libpear_speedtest/libpear_upload_test.c b/libpear/libpear_speedtest/libpear_upload_test.c index 0d9fa8f..0ea8537 100644 --- a/libpear/libpear_speedtest/libpear_upload_test.c +++ b/libpear/libpear_speedtest/libpear_upload_test.c @@ -862,12 +862,10 @@ typedef struct thread_args #define BUFFER_SIZE 1500 -unsigned long totalTransfered = 1024 * 1024; -unsigned long totalToBeTransfered = 1024 * 1024; - static void *__uploadThread(void *arg) { /* Testing upload... */ + unsigned long totalToBeTransfered = 1024 * 1024; THREADARGS_T *threadConfig = (THREADARGS_T *)arg; char alphabet[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char buffer[BUFFER_SIZE] = {0}; @@ -937,7 +935,7 @@ float testUpload(pear_speedtest_client_info_t *speedTestConfig, const char *url) } /* Refresh */ - totalTransfered = 0; + unsigned long totalTransfered = 0; float speed = 0; /* Wait for all threads */ diff --git a/pear_monitor/pear_speed.c b/pear_monitor/pear_speed.c index c920f87..f05fb51 100644 --- a/pear_monitor/pear_speed.c +++ b/pear_monitor/pear_speed.c @@ -67,7 +67,7 @@ static int __get_speed(pear_speedtest_upload_info_t *upload_info, pear_speedtest client_info.isp, client_info.country); client_info.uploadThreadConfig.threadsCount = 2; - client_info.uploadThreadConfig.length = 3; + client_info.uploadThreadConfig.length = 30; // record some servers(according to min distance[lat, lon]) // if (pear_speedtest_get_some_server(&client_info, server_info, 10, "China", 0) < 0) { -- Gitee From 6990c3f0525dc28a905e190679b09b6669ec091c Mon Sep 17 00:00:00 2001 From: LiuzhouChan Date: Tue, 11 Jun 2019 18:32:46 +0800 Subject: [PATCH 4/5] first version --- .../libpear_speedtest/libpear_get_server.c | 14 +- .../libpear_speedtest/libpear_upload_test.c | 319 +----------------- .../libpear_speedtest/libpear_upload_test.h | 2 + pear_monitor/pear_speed.c | 33 +- 4 files changed, 46 insertions(+), 322 deletions(-) diff --git a/libpear/libpear_speedtest/libpear_get_server.c b/libpear/libpear_speedtest/libpear_get_server.c index 77a7487..55f628b 100644 --- a/libpear/libpear_speedtest/libpear_get_server.c +++ b/libpear/libpear_speedtest/libpear_get_server.c @@ -58,12 +58,11 @@ static double pear_speedtest_calc_distance(double lat1, double lon1, double lat2 // { // memset(server_info, 0, sizeof(pear_speedtest_server_info_t) * server_num); // } - int pear_speedtest_get_some_server(pear_speedtest_client_info_t *client_info, pear_speedtest_server_info_t *server_info, int server_num, char *what_is_my_country, int debug) { char *header[] = {pear_speedtest_header_info.user_agent, "Cache-Control: no-cache", NULL}; - + int real_num = 0; if (!debug) { pear_download_file("GET", "http://c.speedtest.net/speedtest-servers-static.php", header, NULL, 0, 30, 300, "/tmp/.pear_speedtest_servers.php"); @@ -75,7 +74,11 @@ int pear_speedtest_get_some_server(pear_speedtest_client_info_t *client_info, if (root == NULL) { fprintf(stderr, "roxml_load_doc failed\n"); - goto failed_to_release_buffer; + pear_download_file("GET", "https://cdn.jsdelivr.net/gh/PearLab/speedtest@latest/nodes.xml", header, NULL, 0, 30, 300, "/tmp/.pear_speedtest_servers.php"); + root = roxml_load_doc("/tmp/.pear_speedtest_servers.php"); + if (root == NULL) { + goto failed_to_release_buffer; + } } // find first server node @@ -216,6 +219,7 @@ int pear_speedtest_get_some_server(pear_speedtest_client_info_t *client_info, { server_info[i].set_value_flag = 1; PEAR_SPEEDTEST_COPY_SERVERINFO(server_info[i], s_info); + real_num++; goto next_one; } } @@ -247,7 +251,7 @@ int pear_speedtest_get_some_server(pear_speedtest_client_info_t *client_info, server = roxml_get_next_sibling(server); } roxml_close(root); - return 0; + return real_num; failed_to_release_xml: roxml_close(root); @@ -256,6 +260,8 @@ failed_to_release_buffer: return -1; } + + int __pear_speedtest_cn_get_meta_data(json_t *json_root) { json_t *json_meta; diff --git a/libpear/libpear_speedtest/libpear_upload_test.c b/libpear/libpear_speedtest/libpear_upload_test.c index 0ea8537..b93fc78 100644 --- a/libpear/libpear_speedtest/libpear_upload_test.c +++ b/libpear/libpear_speedtest/libpear_upload_test.c @@ -389,42 +389,6 @@ void breakUrl(const char *pUrl, URLPARTS_T *pUrlStruct) strncpy(pUrlStruct->address, ptr1, pUrlStruct->addressLen); } -int hexToAscii(char pHex) -{ - if (pHex >= '0' && pHex <= '9') - return pHex - '0'; - if (pHex >= 'A' && pHex <= 'F') - return pHex - 'A' + 10; - if (pHex >= 'a' && pHex <= 'f') - return pHex - 'a' + 10; - return 0; -} -/*Decodes the hex parts of the request (e.g %20 is ' ')*/ -void decodeRequest(const char *pRequest, char *pOut, int pOutSize) -{ - char *ptr1 = (char *)pRequest; - int i; - memset(pOut, 0, pOutSize); - for (i = 0; i < pOutSize - 1; i++) - { - if (*ptr1 == 0) - break; - - switch (*ptr1) - { - case '%': - pOut[i] = hexToAscii(*++ptr1) << 4; - pOut[i] += hexToAscii(*++ptr1); - break; - - default: - pOut[i] = *ptr1; - break; - } - ptr1++; - } -} - //------------------------------------http------------------------------------ typedef int sock_t; #define BAD_SOCKID 0 /* should use -1!! */ @@ -473,84 +437,6 @@ sock_t httpPut(char *pAddress, int pPort, char *pRequest, unsigned long contentS return sockId; } -sock_t httpGet(char *pAddress, int pPort, char *pRequest, int ssl) -{ - char buffer[0xFFFF], *token; - sock_t sockId; - int s; - struct sockaddr_in addr; - struct hostent *hostEntry; - int length = 0; - int success = 0; - int i; - if ((s = (int)socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == 0) - return 0; - - if ((hostEntry = gethostbyname(pAddress)) == NULL) - return 0; - - addr.sin_family = AF_INET; - addr.sin_addr = *((struct in_addr *)*hostEntry->h_addr_list); - addr.sin_port = htons((unsigned short)pPort); - if (connect(s, (struct sockaddr *)&addr, - sizeof(struct sockaddr_in)) == -1) - return 0; - - sprintf(buffer, "GET %s HTTP/1.1\r\n" - "Host: %s\r\n" - "User-Agent: SPEEDTEST_CLIENT\r\n" - "Connection: close\r\n" - "\r\n", - pRequest, pAddress); - - sockId = s; - send(sockId, buffer, strlen(buffer), 0); - - while ((length = recvLine(sockId, buffer, sizeof(buffer))) > 0) - { - /*trim line*/ - for (i = length - 1; i >= 0; i--) - { - if (buffer[i] < ' ') - buffer[i] = 0; - else - break; - } - /*if end of header*/ - if (!strlen(buffer)) - break; - - /*get first word*/ - token = strtok(buffer, " "); - if (token == NULL) - break; - - /*Check http error code*/ - if (strcmp(token, "HTTP/1.0") == 0 || strcmp(token, "HTTP/1.1") == 0) - { - _httpErrorCode = atoi(strtok(NULL, " ")); - if (_httpErrorCode == 200) - success = 1; - } - } - if (!success) - { - close(sockId); - return 0; - } - else - return sockId; -} - -int httpRecv(sock_t pSockId, char *pOut, int pOutSize) -{ - int size; - if ((size = recv(pSockId, pOut, pOutSize, 0)) > 0) - return size; - - return 0; -} - int httpSend(sock_t pSockId, char *pOut, int pOutSize) { int size; @@ -565,28 +451,6 @@ void httpClose(sock_t pSockId) close(pSockId); } -sock_t httpGetRequestSocket(const char *urlToDownload) -{ - char address[1024]; - char request[1024]; - URLPARTS_T url; - sock_t sockId; - - memset(&url, 0, sizeof(url)); - url.address = address; - url.request = request; - url.addressLen = sizeof(address); - url.requestLen = sizeof(request); - breakUrl(urlToDownload, &url); - - sockId = httpGet(address, url.port, request, url.ssl); - if (sockId) - return sockId; - fprintf(stderr, "Http error while creating GET request socket: %i\n", - httpLastError()); - return 0; -} - sock_t httpPutRequestSocket(const char *urlToUpload, unsigned long contentSize) { char address[1024]; @@ -651,24 +515,6 @@ int recvLine(sock_t pSockId, char *pOut, int pOutSize) const char *ConfigLineIdentitier[] = {"url = substr; - break; - case 2: - result->lat = strtof(substr, NULL); - free(substr); - break; - case 3: - result->lon = strtof(substr, NULL); - free(substr); - break; - case 4: - result->name = substr; - break; - case 5: - result->country = substr; - break; - case 7: - result->sponsor = substr; - break; - default: - free(substr); - break; - } - } -} - -SPEEDTESTSERVER_T **getServers(int *serverCount, const char *infraUrl) -{ - char buffer[1500] = {0}; - SPEEDTESTSERVER_T **list = NULL; - sock_t sockId = httpGetRequestSocket(infraUrl); - if (sockId) - { - long size; - while ((size = recvLine(sockId, buffer, sizeof(buffer))) > 0) - { - buffer[size + 1] = '\0'; - if (strlen(buffer) > 25) - { - /*Ommiting XML invocation...*/ - if (strstr(buffer, "') - { - *serverCount = *serverCount + 1; - list = (SPEEDTESTSERVER_T **)realloc(list, - sizeof(SPEEDTESTSERVER_T **) * (*serverCount)); - if (list == NULL) - { - fprintf(stderr, "Unable to allocate memory for servers!\n"); - exit(1); - } - list[*serverCount - 1] = malloc(sizeof(SPEEDTESTSERVER_T)); - if (list[*serverCount - 1]) - parseServer(list[*serverCount - 1], buffer); - } - } - } - httpClose(sockId); - return list; - } - return NULL; -} - -static char *modifyServerUrl(char *serverUrl, const char *urlFile) -{ - size_t urlSize = strlen(serverUrl); - char *upload = strstr(serverUrl, "upload.php"); - if (upload == NULL) - { - printf("Download URL parsing error - cannot find upload.php in %s\n", - serverUrl); - exit(1); - } - size_t uploadSize = strlen(upload); - size_t totalSize = (urlSize - uploadSize) + - strlen(urlFile) + 1; - char *result = (char *)malloc(sizeof(char) * totalSize); - result[(urlSize - uploadSize)] = '\0'; - memcpy(result, serverUrl, urlSize - uploadSize); - strcat(result, urlFile); - return result; -} - -char *getServerDownloadUrl(char *serverUrl) -{ - return modifyServerUrl(serverUrl, "random4000x4000.jpg"); -} - -int sortServers(SPEEDTESTSERVER_T **srv1, SPEEDTESTSERVER_T **srv2) -{ - return ((*srv1)->distance - (*srv2)->distance); -} - -void getBestServer(pear_speedtest_client_info_t *speedTestConfig, char*download_url, char* upload_url) +void getBestServer_v2(pear_speedtest_client_info_t *speedTestConfig, pear_speedtest_server_info_t *server_info, int server_cnt, char*download_url, char* upload_url) { size_t selectedServer = 0; - printf("Your IP: %s And ISP: %s\n", - speedTestConfig->ip, speedTestConfig->isp); - int serverCount = 0; - SPEEDTESTSERVER_T** serverList = getServers(&serverCount, URL_PROTOCOL "://www.speedtest.net/speedtest-servers-static.php"); - if (serverCount == 0) - { - // Primary server is not responding. Let's give a try with secondary one. - serverList = getServers(&serverCount, URL_PROTOCOL "://c.speedtest.net/speedtest-servers-static.php"); - } - printf("Grabbed %d servers\n", serverCount); - if (serverCount == 0) - { - printf("Cannot download any speedtest.net server. Something is wrong...\n"); - exit(1); - } - for (int i = 0; i < serverCount; i++) - serverList[i]->distance = haversineDistance(speedTestConfig->lat, - speedTestConfig->lon, - serverList[i]->lat, - serverList[i]->lon); - qsort(serverList, serverCount, sizeof(SPEEDTESTSERVER_T *), - (int (*)(const void *, const void *))sortServers); - printf("Best Server URL: %s\n\t Name: %s Country: %s Sponsor: %s Dist: %ld km\n", - serverList[selectedServer]->url, serverList[selectedServer]->name, serverList[selectedServer]->country, - serverList[selectedServer]->sponsor, serverList[selectedServer]->distance); - char* downloadUrl = getServerDownloadUrl(serverList[selectedServer]->url); - strcpy(download_url, downloadUrl); - free(downloadUrl); - strcpy(upload_url, serverList[selectedServer]->url); - - for (int i = 0; i < serverCount; i++) - { - free(serverList[i]->url); - free(serverList[i]->name); - free(serverList[i]->sponsor); - free(serverList[i]->country); - free(serverList[i]); + printf("Your IP: %s And ISP: %s\n", speedTestConfig->ip, speedTestConfig->isp); + for (int i = 1; i < server_cnt; i++) { + if (server_info[i].dis < server_info[selectedServer].dis) { + selectedServer = i; + } } + strcpy(upload_url, server_info[selectedServer].url_upload); + strcpy(download_url, server_info[selectedServer].url_download); } //---------------------------------uploadtest---------------------------------------- @@ -927,7 +627,8 @@ float testUpload(pear_speedtest_client_info_t *speedTestConfig, const char *url) /* At least three test should be run */ param[i].testCount = 3; } - param[i].url = strdup(url); + param[i].url = malloc(strlen(url)+1); + strcpy(param[i].url, url); if (param[i].url) { pthread_create(¶m[i].tid, NULL, &__uploadThread, ¶m[i]); diff --git a/libpear/libpear_speedtest/libpear_upload_test.h b/libpear/libpear_speedtest/libpear_upload_test.h index 4af9543..2b891a4 100644 --- a/libpear/libpear_speedtest/libpear_upload_test.h +++ b/libpear/libpear_speedtest/libpear_upload_test.h @@ -16,6 +16,8 @@ void pear_speedtest_upload_test(pear_speedtest_upload_info_t *upload_info, pear_ void pear_speedtest_upload_test_v2(pear_speedtest_upload_info_t *upload_info, pear_speedtest_client_info_t *client_info, char* upload_url); +void getBestServer_v2(pear_speedtest_client_info_t *speedTestConfig, pear_speedtest_server_info_t *server_info, int server_cnt, char*download_url, char* upload_url); + void pear_speedtest_cn_upload_test(pear_speedtest_upload_info_t *upload_info, pear_speedtest_server_info_t *server_info, int server_num); int pear_speedtest_upload_optimize(pear_speedtest_server_info_t *server_info, int server_num); diff --git a/pear_monitor/pear_speed.c b/pear_monitor/pear_speed.c index f05fb51..b1b1102 100644 --- a/pear_monitor/pear_speed.c +++ b/pear_monitor/pear_speed.c @@ -70,11 +70,13 @@ static int __get_speed(pear_speedtest_upload_info_t *upload_info, pear_speedtest client_info.uploadThreadConfig.length = 30; // record some servers(according to min distance[lat, lon]) // - if (pear_speedtest_get_some_server(&client_info, server_info, 10, "China", 0) < 0) { + int real_num = pear_speedtest_get_some_server(&client_info, server_info, 10, "China", 0); + printf("the real server number is %d\n", real_num); + if (real_num < 0) { goto speedtest_failed; } int i; - for (i = 0; i < threads; i++) { + for (i = 0; i < real_num; i++) { if (server_info[i].set_value_flag) { printf("----> server(%d):\nurl: %s\nisp: %s\nlat: %f\nlon: %f\ndis: %f\n\n", i, @@ -86,18 +88,32 @@ static int __get_speed(pear_speedtest_upload_info_t *upload_info, pear_speedtest } } // upload test - char download_url[1024] = {0x00}; char upload_url[1024] = {0x00}; - getBestServer(&client_info, download_url, upload_url); + double max_upload_speed = 0; + // getBestServer_v2(&client_info, server_info, real_num, download_url, upload_url); + for (int i = 0; i < real_num; i++) { + strcpy(upload_url, server_info[i].url_upload); + printf("the select upload url is:%s\n", upload_url); + pear_speedtest_upload_test_v2(upload_info, &client_info, upload_url); + printf("--> total upload: %f bytes/sec\n\n", upload_info->speed_bytes_second); + if (upload_info->speed_bytes_second > max_upload_speed) { + max_upload_speed = upload_info->speed_bytes_second; + } + } + strcpy(upload_url, "http://csl2.hkspeedtest.com:8080/speedtest/upload.php"); + printf("the select upload url is:%s\n", upload_url); pear_speedtest_upload_test_v2(upload_info, &client_info, upload_url); printf("--> total upload: %f bytes/sec\n\n", upload_info->speed_bytes_second); - // download test - // - pear_speedtest_download_test(download_info, server_info, threads); - printf("--> total download: %f bytes/sec\n\n", download_info->speed_bytes_second); + if (upload_info->speed_bytes_second > max_upload_speed) { + max_upload_speed = upload_info->speed_bytes_second; + } + printf("the max upload speed is %f\n", max_upload_speed); + upload_info->speed_bytes_second = max_upload_speed; + pear_speedtest_download_test(download_info, server_info, real_num); + printf("--> total download: %f bytes/sec\n\n", download_info->speed_bytes_second); // clear tmp files // pear_speed_info.speed_fail &= 0x2; @@ -308,7 +324,6 @@ int pear_get_speed(int threads) /* do speedtest */ ret1 = __get_speed(upload_info + 0, download_info + 0, threads); - exit(0); ret2 = __get_speed_cn(upload_info + 1, download_info + 1, threads); pear_speed_info.speed_interval = PEAR_SPEEDTEST_NORMAL_INTERVAL; -- Gitee From 7003037286e04e1a2cc5ccbcf25f31ebe8ec5083 Mon Sep 17 00:00:00 2001 From: LiuzhouChan Date: Fri, 14 Jun 2019 16:23:54 +0800 Subject: [PATCH 5/5] second version --- .../libpear_speedtest/libpear_get_server.c | 75 ++++---- .../libpear_speedtest/libpear_get_server.h | 2 +- .../libpear_speedtest/libpear_upload_test.c | 173 ++++++++++-------- .../libpear_speedtest/libpear_upload_test.h | 2 + pear_monitor/pear_speed.c | 19 +- 5 files changed, 141 insertions(+), 130 deletions(-) diff --git a/libpear/libpear_speedtest/libpear_get_server.c b/libpear/libpear_speedtest/libpear_get_server.c index 55f628b..7d913e9 100644 --- a/libpear/libpear_speedtest/libpear_get_server.c +++ b/libpear/libpear_speedtest/libpear_get_server.c @@ -3,6 +3,8 @@ #include #include #include +#include + #include "pear_curl.h" #include "pear_json.h" @@ -58,8 +60,17 @@ static double pear_speedtest_calc_distance(double lat1, double lon1, double lat2 // { // memset(server_info, 0, sizeof(pear_speedtest_server_info_t) * server_num); // } +bool pear_str_in(const char* str, char** s, int s_num) { + for (int i = 0; i < s_num; i++) { + if (strcmp(str, s[i]) == 0) { + return true; + } + } + return false; +} + int pear_speedtest_get_some_server(pear_speedtest_client_info_t *client_info, - pear_speedtest_server_info_t *server_info, int server_num, char *what_is_my_country, int debug) + pear_speedtest_server_info_t *server_info, int server_num, char **what_is_my_country, int c_num,int debug) { char *header[] = {pear_speedtest_header_info.user_agent, "Cache-Control: no-cache", NULL}; int real_num = 0; @@ -100,17 +111,6 @@ int pear_speedtest_get_some_server(pear_speedtest_client_info_t *client_info, goto failed_to_release_xml; } - // country limit - // - char type_country[16] = {0}; - if (what_is_my_country) - { - strcpy(type_country, what_is_my_country); - } - else - { - strcpy(type_country, "China"); - } // find min distance servers // @@ -125,8 +125,7 @@ int pear_speedtest_get_some_server(pear_speedtest_client_info_t *client_info, goto failed_to_release_xml; strcpy(country, country_string); free(country_string); - - if (!strcmp(country, type_country)) + if (pear_str_in(country, what_is_my_country, c_num)) { pear_speedtest_server_info_t *max_distance_server_info = NULL; pear_speedtest_server_info_t s_info; @@ -145,31 +144,33 @@ int pear_speedtest_get_some_server(pear_speedtest_client_info_t *client_info, // carrieroperator // (China Mobile Group XinJiang, China Unicom Heilongjiang, China Telecom) // - switch (client_info->isp_n) - { - case 1: - if (!strcasestr(s_info.sponsor, "mobile")) - { - goto next_one; - } - break; - - case 2: - if (!strcasestr(s_info.sponsor, "unicom")) + if (strcmp(country, "China") == 0) { + switch (client_info->isp_n) { - goto next_one; + case 1: + if (!strcasestr(s_info.sponsor, "mobile")) + { + goto next_one; + } + break; + + case 2: + if (!strcasestr(s_info.sponsor, "unicom")) + { + goto next_one; + } + break; + + case 3: + if (!strcasestr(s_info.sponsor, "telecom")) + { + goto next_one; + } + break; + + default: + break; } - break; - - case 3: - if (!strcasestr(s_info.sponsor, "telecom")) - { - goto next_one; - } - break; - - default: - break; } // url diff --git a/libpear/libpear_speedtest/libpear_get_server.h b/libpear/libpear_speedtest/libpear_get_server.h index 7a2f892..f22bbc8 100644 --- a/libpear/libpear_speedtest/libpear_get_server.h +++ b/libpear/libpear_speedtest/libpear_get_server.h @@ -28,7 +28,7 @@ typedef struct { int pear_speedtest_get_some_server(pear_speedtest_client_info_t *client_info, pear_speedtest_server_info_t *server_info, int server_num, - char *what_is_my_country, + char **what_is_my_country, int c_num, int debug); diff --git a/libpear/libpear_speedtest/libpear_upload_test.c b/libpear/libpear_speedtest/libpear_upload_test.c index b93fc78..8504e04 100644 --- a/libpear/libpear_speedtest/libpear_upload_test.c +++ b/libpear/libpear_speedtest/libpear_upload_test.c @@ -1,5 +1,3 @@ -#include -#include #include #include #include @@ -10,19 +8,17 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include "libpear_get_header.h" #include "libpear_upload_test.h" #include "libpear_get_client.h" -// void pear_speedtest_upload_set_prevalue(pear_speedtest_upload_info_t *upload_info, int n, double prevalue) -// { -// int i; -// for (i = 0; i < n; ++i) { -// upload_info[i].speed_bytes_second = prevalue; -// } -// } - static void pear_speedtest_cn_uuid(char *uuid) { char *e = "0123456789abcdef"; @@ -437,20 +433,33 @@ sock_t httpPut(char *pAddress, int pPort, char *pRequest, unsigned long contentS return sockId; } -int httpSend(sock_t pSockId, char *pOut, int pOutSize) -{ - int size; +static int timefd_get() { + return timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC|TFD_NONBLOCK); +} - if ((size = send(pSockId, pOut, pOutSize, 0)) > 0) - return size; - return 0; +static int timefd_set(int fd, int sec, long nsec){ + struct itimerspec new_value; + uint64_t exp; + memset(&new_value, 0, sizeof(struct itimerspec)); + new_value.it_value.tv_sec = sec; + new_value.it_value.tv_nsec = nsec; + return timerfd_settime(fd, 0, &new_value, NULL); } -void httpClose(sock_t pSockId) -{ - close(pSockId); +// -1 error, 0 not expired, 1 expired +static int timefd_expired(int fd) { + uint64_t exp; + ssize_t s = read(fd, &exp, sizeof(uint64_t)); + if (s != sizeof(uint64_t)){ + if (errno == EAGAIN) { + return 0; + } + return -1; + } + return 1; } + sock_t httpPutRequestSocket(const char *urlToUpload, unsigned long contentSize) { char address[1024]; @@ -474,30 +483,6 @@ sock_t httpPutRequestSocket(const char *urlToUpload, unsigned long contentSize) return BAD_SOCKID; } -static int sockRecv(sock_t pSockId, char *ptr, int len) -{ - return recv(pSockId, ptr, len, 0); -} - -int recvLine(sock_t pSockId, char *pOut, int pOutSize) -{ - int received = 0; - char letter; - memset(pOut, 0, pOutSize); - for (; received < pOutSize - 1; received++) - { - if (sockRecv(pSockId, (char *)&letter, 1) > 0) - { - pOut[received] = letter; - if (letter == '\n') - break; - } - else - break; - } - return received; -} - //------------------------------config----------------- #define R 6371 #define PI 3.1415926536 @@ -516,16 +501,6 @@ int recvLine(sock_t pSockId, char *pOut, int pOutSize) const char *ConfigLineIdentitier[] = {"transferedBytes = 0; gettimeofday(&tval_start, NULL); for (int i = 0; i < threadConfig->testCount; i++) { __appendTimestamp(threadConfig->url, uploadUrl, sizeof(uploadUrl)); /* FIXME: totalToBeTransfered should be readonly while the upload thread is running */ - totalTransfered = totalToBeTransfered; + remain = totalToBeTransfered; sock_t sockId = httpPutRequestSocket(uploadUrl, totalToBeTransfered); - if (sockId == 0) - { + if (sockId == 0) { printf("Unable to open socket for Upload!"); pthread_exit(NULL); } - while (totalTransfered != 0) + + int timefd = timefd_get(); + if (timefd < 0) { + printf("cannot create the timefd\n"); + pthread_exit(NULL); + } + int ret = timefd_set(timefd, TEST_TIMEOUT_SEC, 0); + if (ret < 0) { + printf("cannot set the timefd\n"); + pthread_exit(NULL); + } + ret = 0; + while (remain > 0 && ret == 0) { - if (totalTransfered > BUFFER_SIZE) + int send_size; + if (remain > BUFFER_SIZE) { - size = httpSend(sockId, buffer, BUFFER_SIZE); + send_size = BUFFER_SIZE; } else { - buffer[totalTransfered - 1] = '\n'; /* Indicate terminated */ - size = httpSend(sockId, buffer, totalTransfered); + send_size = remain; + buffer[remain - 1] = '\n'; /* Indicate terminated */ + } + size = send(sockId, buffer, send_size, 0); + if (size == -1) { + if (errno == EAGAIN || errno == EINTR) { + // re send + goto test_timeout; + } + printf("-------------------------send error------------------------\n"); + break; + } + remain -= size; + +test_timeout: + // test if timeout + ret = timefd_expired(timefd); + if (ret == 1) { + printf("-------------------------send timeout--------------------------\n"); + } else if (ret < 0) { + printf("error\n"); } - - totalTransfered -= size; } - threadConfig->transferedBytes += totalToBeTransfered; + close(timefd); + pthread_mutex_lock(&threadConfig->lock); + threadConfig->transferedBytes += totalToBeTransfered - remain; + pthread_mutex_unlock(&threadConfig->lock); /* Cleanup */ - httpClose(sockId); + close(sockId); + if (ret == 1) { + break; + } } threadConfig->elapsedSecs = getElapsedTime(tval_start); return NULL; @@ -617,9 +623,17 @@ float testUpload(pear_speedtest_client_info_t *speedTestConfig, const char *url) { size_t numOfThreads = speedTestConfig->uploadThreadConfig.threadsCount; THREADARGS_T *param = (THREADARGS_T *)calloc(numOfThreads, sizeof(THREADARGS_T)); - int i; - for (i = 0; i < numOfThreads; i++) + + /* Build the random buffer */ + for (int i = 0; i < BUFFER_SIZE; i++) + { + buffer[i] = 'a'; + } + + for (int i = 0; i < numOfThreads; i++) { + memset(¶m[i], 0, sizeof(THREADARGS_T)); + pthread_mutex_init(¶m[i].lock, NULL); /* Initializing some parameters */ param[i].testCount = speedTestConfig->uploadThreadConfig.length; if (param[i].testCount == 0) @@ -640,7 +654,7 @@ float testUpload(pear_speedtest_client_info_t *speedTestConfig, const char *url) float speed = 0; /* Wait for all threads */ - for (i = 0; i < numOfThreads; i++) + for (int i = 0; i < numOfThreads; i++) { pthread_join(param[i].tid, NULL); if (param[i].transferedBytes) @@ -651,11 +665,12 @@ float testUpload(pear_speedtest_client_info_t *speedTestConfig, const char *url) } /* Cleanup */ free(param[i].url); + pthread_mutex_destroy(¶m[i].lock); } free(param); printf("Bytes %lu uploaded with a speed %.2f kB/s (%.2f Mbit/s)\n", totalTransfered, speed, speed * 8 / 1024); - return speed*1024; + return speed * 1024; } diff --git a/libpear/libpear_speedtest/libpear_upload_test.h b/libpear/libpear_speedtest/libpear_upload_test.h index 2b891a4..dcfb480 100644 --- a/libpear/libpear_speedtest/libpear_upload_test.h +++ b/libpear/libpear_speedtest/libpear_upload_test.h @@ -3,6 +3,8 @@ #include "libpear_get_server.h" +#define TEST_TIMEOUT_SEC 10 +#define BUFFER_SIZE 1500 typedef struct { double speed_bytes_second; diff --git a/pear_monitor/pear_speed.c b/pear_monitor/pear_speed.c index b1b1102..692ef89 100644 --- a/pear_monitor/pear_speed.c +++ b/pear_monitor/pear_speed.c @@ -40,7 +40,7 @@ void pear_speed_calc_refer_bw(void) static int __get_speed(pear_speedtest_upload_info_t *upload_info, pear_speedtest_download_info_t *download_info, int threads) { pear_speedtest_client_info_t client_info; - pear_speedtest_server_info_t server_info[threads]; + pear_speedtest_server_info_t server_info[10]; // select one user agent // @@ -67,10 +67,11 @@ static int __get_speed(pear_speedtest_upload_info_t *upload_info, pear_speedtest client_info.isp, client_info.country); client_info.uploadThreadConfig.threadsCount = 2; - client_info.uploadThreadConfig.length = 30; + client_info.uploadThreadConfig.length = 10; // record some servers(according to min distance[lat, lon]) // - int real_num = pear_speedtest_get_some_server(&client_info, server_info, 10, "China", 0); + char *c[] = {"China", "Hong Kong"}; + int real_num = pear_speedtest_get_some_server(&client_info, server_info, 10, c, sizeof(c)/sizeof(c[0]), 0); printf("the real server number is %d\n", real_num); if (real_num < 0) { goto speedtest_failed; @@ -101,19 +102,11 @@ static int __get_speed(pear_speedtest_upload_info_t *upload_info, pear_speedtest } } - strcpy(upload_url, "http://csl2.hkspeedtest.com:8080/speedtest/upload.php"); - printf("the select upload url is:%s\n", upload_url); - pear_speedtest_upload_test_v2(upload_info, &client_info, upload_url); - printf("--> total upload: %f bytes/sec\n\n", upload_info->speed_bytes_second); - - if (upload_info->speed_bytes_second > max_upload_speed) { - max_upload_speed = upload_info->speed_bytes_second; - } - printf("the max upload speed is %f\n", max_upload_speed); upload_info->speed_bytes_second = max_upload_speed; + printf("---------> total upload: %f bytes/sec\n\n", upload_info->speed_bytes_second); pear_speedtest_download_test(download_info, server_info, real_num); - printf("--> total download: %f bytes/sec\n\n", download_info->speed_bytes_second); + printf("---------> total download: %f bytes/sec\n\n", download_info->speed_bytes_second); // clear tmp files // pear_speed_info.speed_fail &= 0x2; -- Gitee