result dns_selector::on_switch_dns(unsigned int adapter_id, const std::wstring& str_ip) { std::wstring str_dns_2 = str_ip; std::vector<adapter_info> vec_adapter_info; if (result_success == get_adapter_list(vec_adapter_info)) { do { if (vec_adapter_info.empty()) { break; } auto it = std::find_if(vec_adapter_info.begin(), vec_adapter_info.end(), [&adapter_id](const adapter_info& r)->bool { return adapter_id == r._id; } ); if (it == vec_adapter_info.end()) { break; } adapter_info& info = *it; if (info._str_dns_1.empty()) { break; } if (info._str_dns_1 != str_ip) { str_dns_2 = info._str_dns_1; } else { if (info._str_dns_2.empty()) { break; } if (info._str_dns_2 != str_ip) { str_dns_2 = info._str_dns_2; } } } while (false); } return switch_adapter_dns(adapter_id, str_ip, str_dns_2); }
/** Get the index of an adapter by its GUID * * @param adapter_guid GUID of the adapter * @return index of the adapter or negative on error */ int get_adapter_index(const char* adapter_guid) { char *AdapterList[MAX_NUM_ADAPTERS]; int i; char AdapterName[ADAPTER_NAME_LEN]; /* string that contains a list of the network adapters */ int AdapterNum; if ((adapter_guid != NULL) && (adapter_guid[0] != 0)) { AdapterNum = get_adapter_list(AdapterList, MAX_NUM_ADAPTERS, AdapterName, ADAPTER_NAME_LEN); if (AdapterNum > 0) { for (i = 0; i < AdapterNum; i++) { if(strstr((char*)AdapterList[i], adapter_guid)) { return i; } } } } return -1; }
result dns_selector::on_freshen_adapter_info(freshen_adapter_info_result_data& res_data) { DWORD tick_count = GetTickCount(); std::vector<adapter_info> vec; result res = get_adapter_list(vec); if (res != result_success) { return res; } for (auto inf : vec) { ui_adapter_info ui_info; ui_info._id = inf._id; ui_info._str_description = inf._str_description; ui_info._str_dns_1 = inf._dhcp ? L"自动获取" : inf._str_dns_1; ui_info._str_dns_2 = inf._dhcp ? L"自动获取" : inf._str_dns_2; res_data._vec_adapter_info.push_back(ui_info); } tick_count = GetTickCount() - tick_count; res_data._str_freshen_take_time = std::to_wstring(tick_count) + L"ms"; return res; }
/** * Open a network adapter and set it up for packet input * * @param adapter_num the index of the adapter to use * @param mac_addr the MAC address of the adapter is stored here (if != NULL) * @param input a function to call to receive a packet * @param arg argument to pass to input * @param linkstate the initial link state * @return an adapter handle on success, NULL on failure */ void* init_adapter(int adapter_num, char *mac_addr, input_fn input, void *arg, enum link_adapter_event *linkstate) { char *AdapterList[MAX_NUM_ADAPTERS]; #ifndef PACKET_LIB_QUIET int i; #endif /* PACKET_LIB_QUIET */ char AdapterName[ADAPTER_NAME_LEN]; /* string that contains a list of the network adapters */ int AdapterNum; PPACKET_OID_DATA ppacket_oid_data; unsigned char ethaddr[ETHARP_HWADDR_LEN]; struct packet_adapter *pa; NDIS_MEDIA_STATE mediastate; pa = (struct packet_adapter *)malloc(sizeof(struct packet_adapter)); if (!pa) { printf("Unable to alloc the adapter!\n"); return NULL; } memset(pa, 0, sizeof(struct packet_adapter)); pa->input = input; pa->input_fn_arg = arg; AdapterNum = get_adapter_list(AdapterList, MAX_NUM_ADAPTERS, AdapterName, ADAPTER_NAME_LEN); /* print all adapter names */ if (AdapterNum <= 0) { free(pa); return NULL; /* no adapters found */ } #ifndef PACKET_LIB_QUIET for (i = 0; i < AdapterNum; i++) { LPADAPTER lpAdapter; printf("%2i: %s\n", i, AdapterList[i]); /* set up the selected adapter */ lpAdapter = PacketOpenAdapter(AdapterList[i]); if (lpAdapter && (lpAdapter->hFile != INVALID_HANDLE_VALUE)) { ppacket_oid_data = (PPACKET_OID_DATA)malloc(sizeof(PACKET_OID_DATA) + PACKET_OID_DATA_SIZE); if (ppacket_oid_data) { ppacket_oid_data->Oid = OID_GEN_VENDOR_DESCRIPTION; ppacket_oid_data->Length = PACKET_OID_DATA_SIZE; if (PacketRequest(lpAdapter, FALSE, ppacket_oid_data)) { printf(" Name: \"%s\"\n", ppacket_oid_data->Data); } free(ppacket_oid_data); } PacketCloseAdapter(lpAdapter); lpAdapter = NULL; } } #endif /* PACKET_LIB_QUIET */ /* invalid adapter index -> check this after printing the adapters */ if (adapter_num < 0) { printf("Invalid adapter_num: %d\n", adapter_num); free(pa); return NULL; } /* adapter index out of range */ if (adapter_num >= AdapterNum) { printf("Invalid adapter_num: %d\n", adapter_num); free(pa); return NULL; } #ifndef PACKET_LIB_QUIET printf("Using adapter_num: %d\n", adapter_num); #endif /* PACKET_LIB_QUIET */ /* set up the selected adapter */ pa->lpAdapter = PacketOpenAdapter(AdapterList[adapter_num]); if (!pa->lpAdapter || (pa->lpAdapter->hFile == INVALID_HANDLE_VALUE)) { free(pa); return NULL; } /* alloc the OID packet */ ppacket_oid_data = (PPACKET_OID_DATA)malloc(sizeof(PACKET_OID_DATA) + PACKET_OID_DATA_SIZE); if (!ppacket_oid_data) { PacketCloseAdapter(pa->lpAdapter); free(pa); return NULL; } /* get the description of the selected adapter */ ppacket_oid_data->Oid = OID_GEN_VENDOR_DESCRIPTION; ppacket_oid_data->Length = PACKET_OID_DATA_SIZE; if (PacketRequest(pa->lpAdapter, FALSE, ppacket_oid_data)) { printf("Using adapter: \"%s\"", ppacket_oid_data->Data); } /* get the MAC address of the selected adapter */ ppacket_oid_data->Oid = OID_802_3_PERMANENT_ADDRESS; ppacket_oid_data->Length = ETHARP_HWADDR_LEN; if (!PacketRequest(pa->lpAdapter, FALSE, ppacket_oid_data)) { printf("ERROR getting the adapter's HWADDR, maybe it's not an ethernet adapter?\n"); PacketCloseAdapter(pa->lpAdapter); free(pa); return NULL; } /* copy the MAC address */ memcpy(ðaddr, ppacket_oid_data->Data, ETHARP_HWADDR_LEN); free(ppacket_oid_data); if (mac_addr != NULL) { /* copy the MAC address to the user supplied buffer, also */ memcpy(mac_addr, ðaddr, ETHARP_HWADDR_LEN); } printf(" [MAC: %02X:%02X:%02X:%02X:%02X:%02X]\n", ethaddr[0], ethaddr[1], ethaddr[2], ethaddr[3], ethaddr[4], ethaddr[5]); /* some more adapter settings */ PacketSetBuff(pa->lpAdapter, PACKET_ADAPTER_BUFSIZE); PacketSetReadTimeout(pa->lpAdapter, 1); PacketSetHwFilter(pa->lpAdapter, NDIS_PACKET_TYPE_ALL_LOCAL | NDIS_PACKET_TYPE_PROMISCUOUS); /* set up packet descriptor (the application input buffer) */ if ((pa->lpPacket = PacketAllocatePacket()) == NULL) { printf("ERROR setting up a packet descriptor\n"); PacketCloseAdapter(pa->lpAdapter); free(pa); return NULL; } PacketInitPacket(pa->lpPacket,(char*)pa->buffer, sizeof(pa->buffer)); if(get_link_state(pa, &mediastate)) { *linkstate = (mediastate == NdisMediaStateConnected ? LINKEVENT_UP : LINKEVENT_DOWN); } return pa; }
result dns_selector::auto_select_dns() { std::unordered_map<std::wstring, std::unordered_map<std::wstring, std::wstring>> map_dns_info; ui::instance()->showlog("开始自动优化DNS..."); result res = result_success; for (auto n = 0; n != NET_WORK_INTERFACE_REQUEST_MAX_TIME; n++) { map_dns_info.clear(); res = fetch_dns_info(map_dns_info); if (res == result_success) { break; } if (res != result_network_interface_http_request_fail) { return res; } ui::instance()->showwarning("请求DNS列表失败-->[网络异常],重试[%d/%d次]后将自动切换成公共DNS再次拉取...", n + 1, NET_WORK_INTERFACE_REQUEST_MAX_TIME); Sleep(1000); } if (res != result_success) { do { if (res != result_network_interface_http_request_fail) { break; } ui::instance()->showlog("正在切换公共DNS..."); ui::instance()->showlog("检测可以切换的网卡..."); std::vector<adapter_info> vec; res = get_adapter_list(vec); if (res != result_success) { break; } if (vec.empty()) { res = result_no_valid_adapter_for_switching; break; } ui::instance()->showlog("切换网卡[%ws]到公共DNS...", vec[0]._str_description.c_str()); res = switch_adapter_dns(vec[0]._id, DEFAULT_DNS_1, DEFAULT_DNS_2); if (res != result_success) { break; } ui::instance()->showlog("切换公共DNS成功,重新请求DNS列表..."); res = fetch_dns_info(map_dns_info); if (res != result_success) { break; } res = result_success; } while (false); if (res != result_success) { return res; } } unsigned int dns_count = 0; for (auto it : map_dns_info) { for (auto itx : it.second) { dns_count++; } } ui::instance()->showlog("获取到[%d个]DNS,开始测速...", dns_count); std::vector<std::tuple<unsigned int, std::wstring>> vec_tp_ping_t_ms_vip; for (auto it : map_dns_info) { std::wstring str_view_name = it.first; unsigned int time_out = 9999999; for (auto it_item : it.second) { std::wstring str_vip = it_item.first; std::wstring str_uptime = it_item.second; unsigned int time_ms; ui::instance()->showlog("正在测速 [%ws]...", str_vip.c_str()); if (result_success == ping_time(str_vip, time_ms)) { ui::instance()->showlog("ping [%ws]-->[%ws]", str_vip.c_str(), (std::to_wstring(time_ms) + L"ms").c_str()); } else { time_ms = time_out; ui::instance()->showwarning("ping [%ws] 超时", str_vip.c_str()); } vec_tp_ping_t_ms_vip.push_back(std::make_tuple(time_ms, str_vip)); } } ui::instance()->showlog("正在选择最优DNS..."); std::sort(vec_tp_ping_t_ms_vip.begin(), vec_tp_ping_t_ms_vip.end(), [](const std::tuple<unsigned int, std::wstring>& l, const std::tuple<unsigned int, std::wstring>& r)->bool { return std::get<0>(l) < std::get<0>(r); } ); std::wstring str_pre_switch_dns_1; std::wstring str_pre_switch_dns_2; res = result_no_valid_dns_for_switching; do { if (vec_tp_ping_t_ms_vip.size() == 0) { break; } unsigned int ping_t_ms = std::get<0>(vec_tp_ping_t_ms_vip[0]); if (ping_t_ms == PING_TIMEOUT) { break; } str_pre_switch_dns_1 = std::get<1>(vec_tp_ping_t_ms_vip[0]); ui::instance()->showlog("最优DNS为[%ws]...", str_pre_switch_dns_1.c_str()); if (vec_tp_ping_t_ms_vip.size() > 1) { unsigned int ping_t_ms = std::get<0>(vec_tp_ping_t_ms_vip[1]); if (ping_t_ms != PING_TIMEOUT) { str_pre_switch_dns_2 = std::get<1>(vec_tp_ping_t_ms_vip[1]); ui::instance()->showlog("最优备用DNS为[%ws]...", str_pre_switch_dns_2.c_str()); } } if (str_pre_switch_dns_2.empty()) { ui::instance()->showwarning("未能找到最优备用DNS,将使用原始DNS代替..."); } res = result_success; } while (false); if (res != result_success) { return res; } ui::instance()->showlog("正在检测可切换的网卡..."); std::vector<adapter_info> vec_adapter_info; res = get_adapter_list(vec_adapter_info); if (res != result_success) { return res; } if (vec_adapter_info.empty()) { return result_no_valid_adapter_for_switching; } std::wstring str_pre_switch_adapter_description = vec_adapter_info[0]._str_description; std::wstring str_pre_switch_adapter_dns_1 = vec_adapter_info[0]._str_dns_1; std::wstring str_pre_switch_adapter_dns_2 = vec_adapter_info[0]._str_dns_2; ui::instance()->showlog("检测到可切换的网卡[%ws]-->DNS[%ws] 备用DNS[%ws]...", str_pre_switch_adapter_description.c_str(), str_pre_switch_adapter_dns_1.c_str(), str_pre_switch_adapter_dns_2.c_str()); unsigned int pre_switch_adapter_id = vec_adapter_info[0]._id; if (str_pre_switch_dns_2.empty()) { adapter_info& info = vec_adapter_info[0]; do { if (info._dhcp) { if (str_pre_switch_dns_1 != DEFAULT_DNS_1) { str_pre_switch_dns_2 = DEFAULT_DNS_1; ui::instance()->showlog("未能找到最优备用DNS,使用默认DNS[%ws]作为备用DNS...", str_pre_switch_dns_2.c_str()); break; } if (str_pre_switch_dns_1 != DEFAULT_DNS_2) { str_pre_switch_dns_2 = DEFAULT_DNS_2; ui::instance()->showlog("未能找到最优备用DNS,使用默认备用DNS[%ws]作为备用DNS...", str_pre_switch_dns_2.c_str()); break; } Assert(false); } if (info._str_dns_1 != str_pre_switch_dns_1) { str_pre_switch_dns_2 = info._str_dns_1; ui::instance()->showlog("未能找到最优备用DNS,使用原始DNS[%ws]作为备用DNS...", str_pre_switch_dns_2.c_str()); break; } if (info._str_dns_2 != str_pre_switch_dns_1) { str_pre_switch_dns_2 = info._str_dns_2; ui::instance()->showlog("未能找到最优备用DNS,继续使用原始备用DNS[%ws]作为备用DNS...", str_pre_switch_dns_2.c_str()); break; } } while (false); } ui::instance()->showlog("开始切换DNS_1[%ws] DNS_2[%ws] --> 网卡[%ws]...", str_pre_switch_dns_1.c_str(), str_pre_switch_dns_2.c_str(), str_pre_switch_adapter_description.c_str()); res = switch_adapter_dns(pre_switch_adapter_id, str_pre_switch_dns_1, str_pre_switch_dns_2); if (res != result_success) { return res; } return result_success; }