Files
GdCpp12/include/IpHelper.h

329 lines
7.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include "GdCPP_Exports.h"
#include "spdlog/fmt/fmt.h"
#include "spdlog/fmt/xchar.h"
#include "StringHelper.h"
#include <WS2tcpip.h>
#include <vector>
#include <ifdef.h> //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; // 常见IfOperStatusUpIfOperStatusDown
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<std::wstring> 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<std::wstring>&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<typename Func>
void forEachAdapter(Func&& func) const {
// 使用 const auto& 确保只读访问
for (const auto& adapter : d) {
func(adapter); // 调用传入的函数,传入 const sAdapter&
}
}
//protected:
std::vector<sAdapter> d;
};
GDCPP_API int getIPFromHostname(const char* hostname, std::vector<ipv4addr>& 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