概述:获取虚拟网卡的个数、网卡保活、判断网卡是否存在

int GetNetCardNums()
{
	int nRet = 0;
	CoInitialize(NULL);
	INetConnectionManager* pNetManager;
	INetConnection* pNetConnection;
	IEnumNetConnection* pEnum;
 
	ULONG celtFetched;
	std::string strComGuid;
	NETCON_PROPERTIES* properties = nullptr;
	bool bIsInstalledNcCard = false;
	TapReg setRegGuid = get_tap_reg();
	NcStatusList ncStausList;
 
	if (setRegGuid.size() == 0)
	{
		SP_LOGW("%s Reg Not Found, Re Install", __SP_FUNC__);
		return 0;
	}
 
	if (S_OK != CoCreateInstance(CLSID_ConnectionManager, NULL, CLSCTX_SERVER, IID_INetConnectionManager, (void**)&pNetManager))
	{
		SP_LOGW("%s Com Instance Failed, sleep(5s)", __SP_FUNC__);
 
		return 0;
	}
 
	pNetManager->EnumConnections(NCME_DEFAULT, &pEnum);
	pNetManager->Release();
	if (NULL == pEnum)
	{
		return 0;
	}
 
	while (pEnum->Next(1, &pNetConnection, &celtFetched) == S_OK)
	{
		pNetConnection->GetProperties(&properties);
 
		strComGuid = GUIDToString(properties->guidId);
 
		// 查看当前网卡与注册表的guid一致时的状态
		for (auto& it : setRegGuid)
		{
			// #1 判断是否安装了 虚拟网卡
			if (strComGuid.compare(it) == 0)
			{
				nRet++;
			}
		}
	}
	pEnum->Release();
 
	return nRet;
}

网卡保活

声明

/*
* @fn			keepAlive
* @brief        网络连接保活
*
* @detail		线程,通过COM组件实现
*/
void keepDeviceTAVnicAlive();

实现

 
 
void keepDeviceTAVnicAlive()
{
	std::lock_guard<std::mutex> lock(g_mutex);
 
	bool bRet = false;
	static int iRePtunFlag = 1; // Nc重连标志
	static int iReLoadFlag = 1; // Dll重载标志
 
	// ipc 主要处理nc发送的消息
	TrustSpaceIPCUtil m_ncIpc("trustNcToCore");
	m_ncIpc.Initialize(&HandleIpcCallBack);
 
	do
	{
		CoInitialize(NULL);
		INetConnectionManager* pNetManager = nullptr;
		INetConnection* pNetConnection = nullptr;
		IEnumNetConnection* pEnum = nullptr;
 
		ULONG celtFetched;
		std::string strComGuid;
		bool bIsInstalledNcCard = false;
		TapReg setRegGuid = get_tap_reg();
		NcStatusList ncStausList;
 
		if (setRegGuid.size() == 0)
		{
			SP_LOGW("%s Reg Not Found, Re Install", __SP_FUNC__);
 
			goto __REINSTALL;
		}
 
		if (S_OK != CoCreateInstance(CLSID_ConnectionManager, NULL, CLSCTX_SERVER, IID_INetConnectionManager, (void**)&pNetManager))
		{
			SP_LOGW("%s Com Instance Failed, sleep(5s)", __SP_FUNC__);
 
			std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 5));
 
			continue;
		}
 
		pNetManager->EnumConnections(NCME_DEFAULT, &pEnum);
		if (pNetManager)
		{
			pNetManager->Release();
			pNetManager = nullptr;
		}
 
		if (NULL == pEnum)
		{
			return;
		}
 
		while (pEnum->Next(1, &pNetConnection, &celtFetched) == S_OK)
		{
			NETCON_PROPERTIES* properties = nullptr;
 
			pNetConnection->GetProperties(&properties);
			
			if (properties != nullptr)
			{
				strComGuid = GUIDToString(properties->guidId);
 
				// T1 查看当前网卡与注册表的guid一致时的状态
				for (auto& it : setRegGuid)
				{
					// #1 判断是否安装了 虚拟网卡
					int minSize = min(strComGuid.size(), it.size());
					if (it.compare(0, minSize, strComGuid, 0, minSize) == 0)
					{
						ncStausList[properties->Status] = properties->pszwDeviceName;
 
						// #2 已安装
						bIsInstalledNcCard = true;
 
						// #3 判断是否被禁用
						if (NCS_DISCONNECTED == properties->Status)
						{
							pNetConnection->Connect();
							SP_LOGI("%s [NcCard] ReConnect", __SP_FUNC__);
						}
					}
				}
			}
 
			if (pNetConnection)
			{
				pNetConnection->Release();
				pNetConnection = nullptr;
			}
		}
 
		if (pEnum)
		{
			pEnum->Release();
			pEnum = nullptr;
		}
 
		// T2 网卡启用时,判断是否有业务需要开启
		if (g_sp_trust_model && g_sp_trust_model->Session()->NeedsL3Tunnel() && // 有三层业务
			!g_sp_trust_model->Session()->IsTunnelSvrsEmpty() && // 服务不为空
			g_sp_trust_model->Session()->IsOnline() &&  // 会话在线
			g_bNetWorkOnline) // 必须联网
		{
			iRePtunFlag = (iRePtunFlag > 300) ? 0 : ++iRePtunFlag;
			if (ncStausList.find(NCS_CONNECTED) == ncStausList.end() && (iRePtunFlag % 30 == 0))
			{
				SP_LOGI("%s [NcCard] Auto Detect ReConnect PTUN", __SP_FUNC__);
 
				if (iReLoadFlag == 5)
				{
					SP_LOGI("%s [NcCard] Auto Detect ReConnect PTUN FAILED. RUN TIMES OVER 5, NECT:[NO OPTION]", __SP_FUNC__);
				}
				
				handleReStartNc();
 
				Sleep(5 * 1000);
 
				iReLoadFlag++;
			}
			else if (ncStausList.find(NCS_CONNECTED) != ncStausList.end())
			{
				iReLoadFlag = 0;
			}
		}
 
	__REINSTALL:
 
		CoUninitialize();
 
		if (false == bIsInstalledNcCard) // 未安装,重新安装
		{
			// #1 未安装,重新安装
			if (false == bIsInstalledNcCard)
			{
				SP_DEV_LOGW("[NetCard] Detect Nc Card Not Installed");
 
				// #2 重新安装
				bIsInstalledNcCard = true;
				std::thread installCardThread([] {
					g_sp_trust_model->NotifyUpMessage(SP_TRUST_TOPIC_MSG_NC_INSTALL, SPJSONObject(), 100);
					});
				installCardThread.detach();
 
				// #3 等待客户端安装
				Sleep(15 * 1000);
			}
		}
		else
		{
			Sleep(1 * 1000); // 每一秒检查一次
		}
 
	} while (true);
 
	return;
}

网卡是否存在

 
bool IsExistNcCard()
{
	bool bIsExist = false;
	int nNetCardSize = 20;
 
	std::shared_ptr<IP_ADAPTER_INFO> pIpAdapterInfo(new IP_ADAPTER_INFO[nNetCardSize]);
	unsigned long stSize = sizeof(IP_ADAPTER_INFO) * nNetCardSize;
	//获取所有网卡信息,参数二为输入输出参数 
	int nRel = GetAdaptersInfo(pIpAdapterInfo.get(), &stSize);
	// 空间不足
	if (ERROR_BUFFER_OVERFLOW == nRel) {
 
		pIpAdapterInfo.reset(new IP_ADAPTER_INFO[stSize]);
		if (GetAdaptersInfo(pIpAdapterInfo.get(), &stSize) != NO_ERROR)
		{
			std::cout << "Failed to get adapter info" << std::endl;
			return false;
		}
	}
 
	PIP_ADAPTER_INFO cur = pIpAdapterInfo.get();
	// 多个网卡 通过链表形式链接起来的
	std::string netdesc;
	std::string netip;
	while (cur) {
 
		netdesc = cur->Description;
		switch (cur->Type) {
		case MIB_IF_TYPE_OTHER:
			break;
		case MIB_IF_TYPE_ETHERNET:
		{
			IP_ADDR_STRING* pIpAddrString = &(cur->IpAddressList);
			netip = pIpAddrString->IpAddress.String;
		}
		break;
		case MIB_IF_TYPE_TOKENRING:
			break;
		case MIB_IF_TYPE_FDDI:
			break;
		case MIB_IF_TYPE_PPP:
			break;
		case MIB_IF_TYPE_LOOPBACK:
			break;
		case MIB_IF_TYPE_SLIP:
			break;
		default://无线网卡,Unknown type
		{
			IP_ADDR_STRING* pIpAddrString = &(cur->IpAddressList);
			netip = pIpAddrString->IpAddress.String;
		}
		break;
		}
		char hex[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
 
		// mac 地址一般6个字节 
		// mac 二进制转16进制字符串
		char macStr[18] = { 0 };//12+5+1
		int k = 0;
		for (UINT j = 0; j < cur->AddressLength; j++) {
			macStr[k++] = hex[(cur->Address[j] & 0xf0) >> 4];
			macStr[k++] = hex[cur->Address[j] & 0x0f];
			macStr[k++] = '-';
		}
 
		if (k < 18 && k > 0)
		{
			macStr[k - 1] = 0;
		}
 
		cur = cur->Next;
 
		// 找到 "TrustAgent VNIC"
		if (netdesc.find("TrustAgent VNIC") != std::string::npos)
		{
			bIsExist = true;
			goto _END_;
		}
	}
 
_END_:
 
	return bIsExist;
}