#ifndef RVC_MOD_COMM_ENTITY_UTIL_HPP_ #define RVC_MOD_COMM_ENTITY_UTIL_HPP_ #if defined(_MSC_VER) #include #include #include #include #include #include #include #include #pragma comment(lib, "IPHLPAPI.lib") #pragma comment(lib, "Wininet.lib") #else #include #include #include #include #include #include #include #endif //_MSC_VER #include "path.h" #include "toolkit.h" #include "charset.h" #include #include #include #include #include #include "SpBase.h" #include "publicFunExport.h" #define MACSESION 6 typedef unsigned long long ULLINT; namespace SP { namespace Module { namespace Comm { //TODO: CrossPlaform !!!!UOS的实现与winpr_GetTickCount64是一样的,可以直接替换无影响 [Gifur@2025822] inline ULLINT RVCGetTickCount() { #ifdef RVC_OS_WIN return GetTickCount64(); #else struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000); #endif // RVC_OS_WIN } } // comm namespace Util { /** * Need to delete *hexBuf if (*hexBuf) not null */ static int StrBuf2HexBuf(const char* strBuf, PBYTE* hexBuf) { int len = strlen(strBuf); if (len == 0 || len % 2 != 0) return 0; BYTE* buf = new BYTE[len / 2]; if (buf == NULL) return 0; int j = 0; for (int i = 0; i < len;) { int tmpVal; sscanf(strBuf + i, "%2X", &tmpVal); buf[j] = tmpVal; i += 2; j++; } *hexBuf = buf; return j; } static int HexBuf2StrBuf(PBYTE hexBuf, char** strBuf, DWORD len) { char* tmpStr = *strBuf; DWORD count = 0; for (DWORD i = 0; i < len; ++i) { sprintf(tmpStr + count, "%0.2X", hexBuf[i]); count += 2; } return 0; } /* //tips: need to delete result char* static char* ConvertBytesToHexStr(BYTE* pBuf, int nLen) { char* pRet = (char*)new char[nLen * 2 + 1]; memset(pRet, '\0', nLen * 2 + 1); char* p = pRet; for (int i = 0; i < nLen; i++) { BYTE b = pBuf[i]; BYTE l = (b >> 4) & 0x0F; if (l >= 10) *p = l - 10 + 'a'; else *p = l + '0'; p++; BYTE r = b & 0x0F; if (r >= 10) *p = r - 10 + 'a'; else *p = r + '0'; p++; } return pRet; } //same as hex2int ?? static char HexChar2Dec(char c) { if ((c >= '0') && (c <= '9')) return c - '0'; else if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10; else if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10; else return 0x10; } static int Hex2Int(char* s) { int ret = 0; while (*s) { int t = HexChar2Dec(*s); ret = ret * 16 + t; ++s; } return ret; } */ inline static int hex2int(const char c) { if (c >= '0' && c <= '9') return (c - '0'); if (c >= 'A' && c <= 'F') return (c - 'A' + 10); if (c >= 'a' && c <= 'f') return (c - 'a' + 10); return 0xFF; } /* static void ConvAscii(unsigned char* Hex, char* Ascii, unsigned int len) { const unsigned char hextable[] = { "0123456789ABCDEF" }; unsigned int i; for (i = 0; i < len; i++) { Ascii[2 * i] = hextable[Hex[i] >> 4]; Ascii[2 * i + 1] = hextable[Hex[i] & 0xf]; } Ascii[2 * len] = 0; } static void AsciiToHex(char* Ascii, unsigned char* Hex, int len) { int i; unsigned char ch; for (i = 0; i < len; i = i + 2) { ch = (Ascii[i] & 0xf); if (Ascii[i] > '9') ch += 9; Hex[i / 2] = ch << 4; ch = Ascii[i + 1] & 0xf; if (Ascii[i + 1] > '9') ch += 9; Hex[i / 2] += ch; } } static bool IsNoStr(const char* str) { int len = strlen(str); if (len == 0) return true; for (int i = 0; i < len; ++i) { if (*(str + i) != ' ') return false; } return true; }*/ inline static int Char2Int(char* ch) { int num = 0; for (int i = 0; i < strlen(ch); i++) { num += ((int)(ch[i] - '0')) * std::pow((float)10, (float)(strlen(ch) - i - 1)); } return num; } static unsigned char Ch2Hex(char ch) { static const char* hex = "0123456789ABCDEF"; for (unsigned char i = 0; i != 16; ++i) if (ch == hex[i]) return i; return 0; } /** remembe to delete[] return value if not null*/ static char* HexStr2Bytes(const std::string& str) { const int sz = str.length(); char* ret = new char[sz / 2 + 1]; if (ret == NULL) { return NULL; } for (int i = 0; i < sz; i += 2) { ret[i / 2] = (char)(((hex2int(str[i])) << 4) | hex2int(str[i + 1])); } ret[sz / 2] = 0x00; return ret; } /*WARNING: need to delete[] the returned value if it's not null*/ static char* Hex2Str(const char* src, int& dstLen) { int i = 0; int cnt = 0; int len = strlen(src); unsigned char* d = new unsigned char[len]; memset(d, 0, len); while (*src) { if (i & 1) { d[cnt++] |= Ch2Hex(*src); } else { d[cnt] = Ch2Hex(*src) << 4; } src++; i++; } dstLen = cnt; return (char*)d; } /*WARNING: need to delete[] the returned value if it's not null*/ static char* Str2Hex(const char* src, int srcLen) { string ret; static const char* hex = "0123456789ABCDEF"; for (int i = 0; i != srcLen; ++i) { ret.push_back(hex[(src[i] >> 4) & 0xf]); ret.push_back(hex[src[i] & 0xf]); } char* tmp = new char[ret.length() + 1]; memset(tmp, 0, ret.length() + 1); memcpy(tmp, ret.c_str(), ret.length()); return tmp; } /*duplicate with the above one ??*/ static std::string Bytes2HexStr(char* bytes, std::size_t byteLen) { std::string str(""); const std::string conv("0123456789ABCDEF"); for (std::size_t i = 0; i < byteLen; ++i) { int b = 0x0F & (bytes[i] >> 4); str.push_back(conv[b]); b = 0x0F & (bytes[i]); str.push_back(conv[b]); } return str; } static std::string formatTime(const SYSTEMTIME& time) { char tBuf[1024] = ""; sprintf(tBuf, "%04u-%02u-%02u %02u:%02u:%02u:%03u", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds); return tBuf; } static CSimpleStringA generateConsumeTimeJson(const CSimpleStringA& entityName, const CSimpleStringA& startTime, int cost) { return CSimpleStringA::Format("{\"name\":\"%s\",\"time\":\"%s\",\"cost\":%d}", entityName.GetData(), startTime.GetData(), cost); } static bool ShellExecute(const std::string& cmd, std::string& succResult, std::string& errResult) { succResult = errResult = ""; char ps[1024] = { 0 }; strcpy(ps, cmd.c_str()); #if defined(_MSC_VER) STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.wShowWindow = SW_HIDE; ZeroMemory(&pi, sizeof(pi)); if (!CreateProcess(NULL, ps, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { errResult = errResult + "CreateProcess failed with error:" + strerror(GetLastError()); return false; } // 等待程序结束,并获取其退出状态 WaitForSingleObject(pi.hProcess, INFINITE); DWORD exitCode; if (!GetExitCodeProcess(pi.hProcess, &exitCode)) { errResult = errResult + "GetExitCodeProcess failed with error code " + strerror(GetLastError()); return false; } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); if (exitCode != 0) { errResult = errResult + "The program exited with code:" + strerror(exitCode); return false; } return true; #else char buf_ps[1024]; char result[2049] = { 0 }; FILE* ptr; if ((ptr = popen(ps, "r")) != NULL) { while (fgets(buf_ps, 1024, ptr) != NULL) { if (strlen(result) + strlen(buf_ps) > 2048) break; strcat(result, buf_ps); } pclose(ptr); const int len = strlen(result); for (int i = len - 1; i >= 0 && (result[i] == '\r' || result[i] == '\n'); --i) { result[i] = '\0'; } succResult = result; return true; } else { sprintf(result, "popen %s error: %d", ps, errno); errResult = result; return false; } #endif //_MSC_VER } #if defined(_MSC_VER) static void ConvertUtf82GBK(std::string& str) { char* dst = ConvertUtf8ToGBK(str.c_str()); str = dst; if(dst) free(dst); } static void ConvertGBK2Utf8(std::string& str) { int len = 0; char* dst = ConvertGBKToUtf8(str.c_str(), &len); str = dst; if (dst) free(dst); } #endif //_MSC_VER enum DataTypeToMask { DataMask_UNKNOWN, DataMask_IDCard, /*居民身份证*/ DataMask_HKMOTWPermit, /*港澳台居住证*/ DataMask_HKMOPermit, /*港澳往来内地通行证*/ DataMask_TWPass, /*台胞证*/ DataMask_ForeignerPR, /*外国人永久居留证*/ DataMask_Passport, /*外国人护照*/ DataMask_CardAccount, /*卡号*/ }; //to mask data //if data is null or empty or length of data is short than 3, break ; //return the first one and the last two characters by default static CSimpleStringA DataMask(DataTypeToMask eDataType, CSimpleStringA data) { if (data.IsNullOrEmpty()) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("data is null or empty"); return ""; } else if (data.GetLength() < 3) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("data length is %d, too short"); return ""; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("data type is %d, length is %d", eDataType, data.GetLength()); switch (eDataType) { case DataMask_IDCard: case DataMask_HKMOTWPermit: case DataMask_ForeignerPR: if (data.GetLength() < 7) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("data length is %d", data.GetLength()); break; } return CSimpleStringA::Format("%s****%s", data.SubString(0, 6).GetData(), data.SubString(data.GetLength() - 1, 1).GetData()); break; case DataMask_HKMOPermit: if (data.GetLength() < 5) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("data length is %d", data.GetLength()); break; } return CSimpleStringA::Format("%s****%s", data.SubString(0, 1).GetData(), data.SubString(data.GetLength() - 4, 4).GetData()); break; case DataMask_CardAccount: if (data.GetLength() < 5) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("data length is %d", data.GetLength()); break; } if (data.GetLength() < 16) return CSimpleStringA::Format("%s**%s", data.SubString(0, 2).GetData(), data.SubString(data.GetLength() - 2, 2).GetData()); else return CSimpleStringA::Format("%s****%s", data.SubString(0, 4).GetData(), data.SubString(data.GetLength() - 4, 4).GetData()); break; case DataMask_TWPass: case DataMask_Passport: case DataMask_UNKNOWN: default: break; } return CSimpleStringA::Format("%s****%s", data.SubString(0, 1).GetData(), data.SubString(data.GetLength() - 2, 2).GetData()); } } //namespace Util namespace Net{ struct NetworkAdapterItem { int idx; std::string friend_name; std::string adapter_name; std::string description; std::string ip; std::string mask; std::string mac; std::string gateway; std::string dhcp; bool is_physical; DWORD type; int operStatus; bool isLocal; NetworkAdapterItem() :idx(0), friend_name(""), adapter_name(""), description(""), ip(""), mask(""), mac(""), gateway(""), dhcp(""), is_physical(true), type(0), operStatus(0), isLocal(false) { } }; static bool IsLocalAdapter(const std::string& name) { #if defined(_MSC_VER) if (name.length() <= 0) { return false; } std::string key("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"); HKEY h_sub_key = NULL; LONG ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_READ, &h_sub_key); if (ret != 0) { return false; } std::ostringstream str; str << name << "\\Connection"; HKEY h_local_key = NULL; ret = RegOpenKeyEx(h_sub_key, str.str().c_str(), 0, KEY_READ, &h_local_key); if (0 != ret) { RegCloseKey(h_sub_key); return false; } DWORD type = REG_SZ; TCHAR buf[250]; DWORD buf_size = 250; ret = RegQueryValueEx(h_local_key, "PnPInstanceId", 0, &type, (BYTE*)(buf), &buf_size); RegCloseKey(h_sub_key); RegCloseKey(h_local_key); if (0 != ret) { return false; } if (0 == strnicmp(buf, "PCI", strlen("PCI")) || 0 == strnicmp(buf, "USB", strlen("USB"))) { return true; } return false; #else ///*TODO(80374374@3/7/2023): */ return true; #endif //_MSC_VER } static ErrorCodeEnum GetINETMacAddresses(CAutoArray& netLists) { #if defined(RVC_OS_WIN) PIP_ADAPTER_ADDRESSES pAddresses = NULL; ULONG family = AF_INET; ULONG flags = GAA_FLAG_INCLUDE_PREFIX; ULONG outBufLen = sizeof(IP_ADAPTER_ADDRESSES); // Make an initial call to GetAdaptersAddresses to get the // size needed into the outBufLen variable if (GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) { pAddresses = static_cast(HeapAlloc(GetProcessHeap(), 0, outBufLen)); } if (NULL == pAddresses) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("pAddresses = NULL"); return Error_Unexpect; } DWORD dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen); /* MACAddresses vAddress;*/ if (dwRetVal != ERROR_SUCCESS) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("dwRetVal = %d", dwRetVal); return Error_Unexpect; } PIP_ADAPTER_ADDRESSES pFirst = pAddresses; while (pAddresses) { if (pAddresses->FirstUnicastAddress && pAddresses->IfType != IF_TYPE_SOFTWARE_LOOPBACK && pAddresses->OperStatus == IfOperStatusUp && pAddresses->FirstUnicastAddress->Address.lpSockaddr->sa_family == AF_INET ) { NetworkAdapterItem netItem; BYTE* pa = pAddresses->PhysicalAddress; if (!pa) { pAddresses = pAddresses->Next ? pAddresses->Next : NULL; continue; } CSimpleStringA strFriendlyName(true); CSimpleStringA strDescription(true); DWORD dwNum = WideCharToMultiByte(CP_OEMCP, NULL, pAddresses->FriendlyName, -1, NULL, 0, NULL, FALSE); char* psText = new char[dwNum]; if (psText != NULL) { WideCharToMultiByte(CP_OEMCP, NULL, pAddresses->FriendlyName, -1, psText, dwNum, NULL, FALSE); strFriendlyName = psText; delete[] psText; } dwNum = WideCharToMultiByte(CP_OEMCP, NULL, pAddresses->Description, -1, NULL, 0, NULL, FALSE); psText = new char[dwNum]; if (psText != NULL) { WideCharToMultiByte(CP_OEMCP, NULL, pAddresses->Description, -1, psText, dwNum, NULL, FALSE); strDescription = psText; delete[] psText; } char bAddressBytes[MACSESION]; int bAddressInt[MACSESION]; memset(bAddressBytes, 0, MACSESION); size_t nAddressSize = pAddresses->PhysicalAddressLength; memcpy(bAddressBytes, pa, (nAddressSize < MACSESION ? nAddressSize : MACSESION)); for (int i = 0; i < MACSESION; ++i) { bAddressInt[i] = bAddressBytes[i]; bAddressInt[i] &= 0x000000ff; // avoid "ff" leading bytes when "char" is lager then 0x7f } CSimpleStringA tmpmac = CSimpleStringA::Format("%02x:%02x:%02x:%02x:%02x:%02x", bAddressInt[0], bAddressInt[1], bAddressInt[2], bAddressInt[3], bAddressInt[4], bAddressInt[5]); sockaddr_in* sa_in = (sockaddr_in*)pAddresses->FirstUnicastAddress->Address.lpSockaddr; char buf_addr[100] = { 0 }; CSimpleStringA tmpip = CSimpleStringA(inet_ntop(AF_INET, &(sa_in->sin_addr), buf_addr, 100)); if (tmpip.Compare("127.0.0.1") == 0 && tmpmac.Compare("00:00:00:00:00:00") == 0) { //skip } else { netItem.friend_name = strFriendlyName; netItem.description = strDescription; netItem.mac = tmpmac; netItem.ip = tmpip; netItem.operStatus = (pAddresses->OperStatus == IfOperStatusUp) ? 1 : 0;//stay the same value with Linux/UOS netItem.type = pAddresses->IfType; netLists.Append(&netItem, 0, 1); } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("%s, %s: OperStatus: %d, IfType = %d, ip=%s, mac=%s" , strFriendlyName.GetData(), strDescription.GetData() , pAddresses->OperStatus, pAddresses->IfType, tmpip.GetData(), tmpmac.GetData()); } pAddresses = pAddresses->Next ? pAddresses->Next : NULL; } HeapFree(GetProcessHeap(), 0, pFirst); return Error_Succeed; #else std::map inteIPs; std::map inteMacs; std::map inteStatus; char buf[512]; toolkit_interface_address_t* info; int count, i; toolkit_interface_addresses(&info, &count); i = count; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Number of interfaces: %d", count); while (i--) { toolkit_interface_address_t interface = info[i]; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Name: %s", interface.name); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Internal? %s", interface.is_internal ? "Yes" : "No"); if (interface.address.address4.sin_family == AF_INET) { toolkit_ip4_name(&interface.address.address4, buf, sizeof(buf)); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("IPv4 address: %s", buf); inteIPs[interface.name] = buf; } else if (interface.address.address4.sin_family == AF_INET6) { toolkit_ip6_name(&interface.address.address6, buf, sizeof(buf)); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("IPv6 address: %s", buf); //inteIPs[interface.name] = buf; } } toolkit_free_interface_addresses(info, count); int fd, interface; struct ifreq bufIfreq[16]; struct ifconf ifc; char mac[32] = { 0 }; if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) { int i = 0; ifc.ifc_len = sizeof(bufIfreq); ifc.ifc_buf = (caddr_t)bufIfreq; if (!ioctl(fd, SIOCGIFCONF, (char*)& ifc)) { interface = ifc.ifc_len / sizeof(struct ifreq); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("interface num is %d", interface); while (i < interface) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Name: %s", bufIfreq[i].ifr_name); if (!(ioctl(fd, SIOCGIFHWADDR, (char*)& bufIfreq[i]))) { sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", (unsigned char)bufIfreq[i].ifr_hwaddr.sa_data[0], (unsigned char)bufIfreq[i].ifr_hwaddr.sa_data[1], (unsigned char)bufIfreq[i].ifr_hwaddr.sa_data[2], (unsigned char)bufIfreq[i].ifr_hwaddr.sa_data[3], (unsigned char)bufIfreq[i].ifr_hwaddr.sa_data[4], (unsigned char)bufIfreq[i].ifr_hwaddr.sa_data[5]); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("HWaddr %s", mac); inteMacs[bufIfreq[i].ifr_name] = mac; } struct ethtool_value edata; edata.cmd = ETHTOOL_GLINK; edata.data = 0; bufIfreq[i].ifr_data = (char*)& edata; //oiltmp@20231026 只检测了以太网卡 if (ioctl(fd, SIOCETHTOOL, (char*)& bufIfreq[i]) == -1) { //up down DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Name: %s is down", bufIfreq[i].ifr_name); inteStatus[bufIfreq[i].ifr_name] = 0; } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Name: %s is up", bufIfreq[i].ifr_name); inteStatus[bufIfreq[i].ifr_name] = 1; } i++; } } close(fd); } std::map::const_iterator map_it = inteIPs.begin(); while (map_it != inteIPs.end()) { NetworkAdapterItem netItem; CSimpleStringA tmpip(map_it->second.c_str()); CSimpleStringA tmpmac(true); CSimpleStringA tmpname(true); auto it = inteMacs.find(std::string(map_it->first)); if (it != inteMacs.end()) { tmpmac = it->second.c_str(); } if (tmpip.Compare("127.0.0.1") == 0 && tmpmac.Compare("00:00:00:00:00:00") == 0) { //skip } else { tmpname = map_it->first.c_str(); netItem.friend_name = "";//oiltmp netItem.description = tmpname; netItem.mac = tmpmac; netItem.ip = tmpip; netItem.operStatus = inteStatus[map_it->first]; netItem.type = 6;//oiltest haven't find the in linux netLists.Append(&netItem, 0, 1); } ++map_it; } return Error_Succeed; #endif //RVC_OS_WIN } }//Net } // mod } // sp #endif //RVC_MOD_COMM_ENTITY_UTIL_HPP_