#pragma once #include "GdCPP_Exports.h" #include "spdlog/fmt/fmt.h" #include "spdlog/fmt/xchar.h" #include "StringHelper.h" #include #include #include //for IF_OPER_STATUS /// @brief ipv4地址类,在sockaddr_in基础上增加字符与ip互转的函数 struct GDCPP_API ipv4addr : public sockaddr_in { ipv4addr() { zero(); } // 复制构造函数 ipv4addr(const ipv4addr &src) { memcpy(this, &src, sizeof(sockaddr_in)); } ipv4addr(const sockaddr_in* src) { if (src) { if (src->sin_family == AF_INET) { //确认src是ipv4地址 memcpy(this, src, sizeof(sockaddr_in)); return; } } zero(); } ipv4addr(const sockaddr* src) { if (src) { if (src->sa_family == AF_INET) { //确认src是ipv4地址 memcpy(this, src, sizeof(sockaddr_in)); return; } } zero(); } ipv4addr(uint32_t ip, uint16_t port=0) { sin_family = AF_INET; sin_addr.S_un.S_addr = ip; sin_port = htons(port); } ipv4addr(const char* ip, uint16_t port = 0) { sin_family = AF_INET; inet_pton(AF_INET, ip, &sin_addr); sin_port = htons(port); } ipv4addr(const std::string& ip, uint16_t port = 0) { sin_family = AF_INET; inet_pton(AF_INET, ip.c_str(), &sin_addr); sin_port = htons(port); } /// @brief 设置ipv4地址 /// @param ip 192.168.0.1 32位数值是0x0100A8C0,字节循序是C0 A8 00 01 /// @param port void set(uint32_t ip, uint16_t port = 0) { sin_family = AF_INET; sin_addr.S_un.S_addr = ip; sin_port = htons(port); } void set(const char* ip, uint16_t port = 0) { sin_family = AF_INET; inet_pton(AF_INET, ip, &sin_addr); sin_port = htons(port); } void set(const std::string& ip, uint16_t port = 0) { sin_family = AF_INET; inet_pton(AF_INET, ip.c_str(), &sin_addr); sin_port = htons(port); } // 仅设置端口 void setPort(uint16_t port) { sin_port = htons(port); } //改成广播地址 void toBoradcast() { sin_addr.S_un.S_addr &= 0x00FFFFFF; sin_addr.S_un.S_addr |= 0xFF000000; } void toBoradcast(ipv4addr &dst) { dst = *this; dst.toBoradcast(); } void zero() { sin_family = AF_INET; sin_port = 0; sin_addr.s_addr = 0; for (auto& i : sin_zero) i = 0; } uint32_t ip() const { return sin_addr.s_addr; } uint32_t port() const { return htons(sin_port); } std::string ipStr() const { const auto& b = sin_addr.S_un.S_un_b; return fmt::format("{:d}.{:d}.{:d}.{:d}", b.s_b1, b.s_b2, b.s_b3, b.s_b4); } std::wstring ipWStr() const { const auto& b = sin_addr.S_un.S_un_b; return fmt::format(L"{:d}.{:d}.{:d}.{:d}", b.s_b1, b.s_b2, b.s_b3, b.s_b4); } std::string addrStr() const { const auto& b = sin_addr.S_un.S_un_b; return fmt::format("{:d}.{:d}.{:d}.{:d}:{}", b.s_b1, b.s_b2, b.s_b3, b.s_b4, htons(sin_port)); } std::wstring addrWStr() const { const auto& b = sin_addr.S_un.S_un_b; return fmt::format(L"{:d}.{:d}.{:d}.{:d}:{}", b.s_b1, b.s_b2, b.s_b3, b.s_b4, htons(sin_port)); } operator const sockaddr* () const { return (const sockaddr*)this; } operator sockaddr* () { return (sockaddr*)this; } bool operator == (const ipv4addr & src) const { return (src.sin_family== AF_INET && sin_port == src.sin_port && sin_addr.s_addr == src.sin_addr.s_addr); } bool operator != (const ipv4addr& src) const { return !(*this == src); } bool operator < (const ipv4addr& src) const { return (sin_addr.s_addr < src.sin_addr.s_addr) || (sin_addr.s_addr == src.sin_addr.s_addr && sin_port < src.sin_port); } }; struct GDCPP_API sAdapter { IF_OPER_STATUS OperStatus; // 常见IfOperStatusUp,IfOperStatusDown std::wstring Description; // 例:Realtek PCIe GbE Family Controller std::wstring FriendlyName; // 例:WLAN,以太网 ipv4addr IpAddr; sAdapter(const wchar_t* desc = nullptr, const wchar_t* name = nullptr) : Description(desc == nullptr ? L"" : desc) , FriendlyName(name == nullptr ? L"" : name) { } sAdapter(const sAdapter& s) : OperStatus(s.OperStatus) , Description(s.Description) , FriendlyName(s.FriendlyName) , IpAddr(s.IpAddr) { } }; class GDCPP_API CAdapterList { public: CAdapterList() = default; // 排除ExcludedNetAdpter列举的网卡(蓝牙、vmware等) static std::vector gExcludedList; enum { // 排除Software Loopback Interface 1 Exclude_Loopback = 0x00000001, // 排除vmware网卡 Exclude_Vmware = 0x00000002, // 排除蓝牙网卡 Exclude_BlueTeeth = 0x00000004, // 排除Microsoft Wi-Fi Direct Virtual Adapter Exclude_MicrosoftWifi = 0x00000008, // Exclude_ZeroTier = 0x00000010, }; // 设置排除列表 static void _SetExcludedList(std::vector&list, uint32_t flag) { list.clear(); if (flag & Exclude_BlueTeeth) { list.push_back(L"Bluetooth Device"); } if (flag & Exclude_MicrosoftWifi) { list.push_back(L"Microsoft Wi-Fi"); } if (flag & Exclude_Vmware) { list.push_back(L"VMware Virtual"); } if (flag & Exclude_Loopback) { list.push_back(L"Software Loopback"); } if (flag & Exclude_Loopback) { list.push_back(L"ZeroTier"); } } // 设置全局排除列表 static void SetExcludedList(uint32_t flag = Exclude_Loopback | Exclude_Vmware | Exclude_BlueTeeth | Exclude_MicrosoftWifi) { _SetExcludedList(gExcludedList, flag); } /// 枚举网卡列表 /// @param exclude_flag 在全局排除列表的基础上额外要排除的网卡 void Enum(uint32_t exclude_flag); /// @brief /// @param box /// @param def //void toComboBox(CComboBox* box, const std::wstring& def); const sAdapter* FindIp(uint32_t ip) { for (auto& i : d) { if (i.IpAddr.ip() == ip) { return &i; } } return nullptr; } const sAdapter* FindName(const std::wstring &name) { for (auto& i : d) { if (i.FriendlyName == name) { return &i; } } return nullptr; } const sAdapter* FindName(const std::string& name) { auto n = utf8_16(name); for (auto& i : d) { if (i.FriendlyName == n) { return &i; } } return nullptr; } sAdapter* operator [](uint32_t index) { if (index >= d.size()) return nullptr; return &d[index]; } bool isUp(uint32_t index) { if (index >= d.size()) return false; return (d[index].OperStatus == IfOperStatusUp); } uint32_t size() const { return uint32_t(d.size()); } template void forEachAdapter(Func&& func) const { // 使用 const auto& 确保只读访问 for (const auto& adapter : d) { func(adapter); // 调用传入的函数,传入 const sAdapter& } } //protected: std::vector d; }; GDCPP_API int getIPFromHostname(const char* hostname, std::vector& foundIp); #ifdef _AFXDLL class CComboBox; static inline void toComboBox(CAdapterList& list, CComboBox* box, const std::wstring& def) { if (box == nullptr) return; for (int i = 0; i < list.d.size(); i++) { const auto& b = list.d[i].IpAddr.sin_addr.S_un.S_un_b; auto str = fmt::format(L"{}, {:03d}.{:03d}.{:03d}.{:03d}, {}" , list.d[i].OperStatus == IfOperStatusUp ? L"已连接" : L"未连接" , b.s_b1, b.s_b2, b.s_b3, b.s_b4 , list.d[i].FriendlyName); auto index = box->AddString(str.c_str()); box->SetItemData(index, i); if (list.d[i].FriendlyName == def) { box->SetCurSel(index); } } } #endif