/*************************************************************************************** * * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. * * By downloading, copying, installing or using the software you agree to this license. * If you do not agree to this license, do not download, install, * copy or use the software. * * Copyright (C) 2014-2024, Happytimesoft Corporation, all rights reserved. * * Redistribution and use in binary forms, with or without modification, are permitted. * * Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific * language governing permissions and limitations under the License. * ****************************************************************************************/ #include "sys_inc.h" #include "util.h" /***************************************************************************************/ HT_API int get_if_nums() { #if __WINDOWS_OS__ char ipt_buf[512]; MIB_IPADDRTABLE * ipt = (MIB_IPADDRTABLE *)ipt_buf; ULONG ipt_len = sizeof(ipt_buf); DWORD fr = GetIpAddrTable(ipt, &ipt_len, FALSE); if (fr != NO_ERROR) { return 0; } return ipt->dwNumEntries; #elif defined(IOS) int count = 0; struct ifaddrs *if_addrs = NULL; struct ifaddrs *if_addr = NULL; if (0 == getifaddrs(&if_addrs)) { for (if_addr = if_addrs; if_addr != NULL; if_addr = if_addr->ifa_next) { if (NULL == if_addr->ifa_addr || if_addr->ifa_addr->sa_family != AF_INET) { continue; } count++; } freeifaddrs(if_addrs); if_addrs = NULL; } return count; #elif __LINUX_OS__ SOCKET socket_fd; struct ifreq *ifr; struct ifconf conf; char buff[BUFSIZ]; int i, num, count = 0; socket_fd = socket(AF_INET, SOCK_DGRAM, 0); if (socket_fd <= 0) { return 0; } conf.ifc_len = BUFSIZ; conf.ifc_buf = buff; ioctl(socket_fd, SIOCGIFCONF, &conf); num = conf.ifc_len / sizeof(struct ifreq); ifr = conf.ifc_req; for (i=0; iifr_addr.sa_family == AF_INET) { count++; } ifr++; } closesocket(socket_fd); return count; #endif return 0; } HT_API uint32 get_if_ip(int index) { #if __WINDOWS_OS__ char ipt_buf[1024]; DWORD i; MIB_IPADDRTABLE * ipt = (MIB_IPADDRTABLE *)ipt_buf; ULONG ipt_len = sizeof(ipt_buf); DWORD fr = GetIpAddrTable(ipt, &ipt_len, FALSE); if (fr != NO_ERROR) { return 0; } for (i=0; idwNumEntries; i++) { if (i == index) { return ipt->table[i].dwAddr; } } #elif defined(IOS) int count = 0; struct ifaddrs *if_addrs = NULL; struct ifaddrs *if_addr = NULL; struct sockaddr_in * sin; uint32 ip_addr = 0; if (0 == getifaddrs(&if_addrs)) { for (if_addr = if_addrs; if_addr != NULL; if_addr = if_addr->ifa_next) { if (NULL == if_addr->ifa_addr || if_addr->ifa_addr->sa_family != AF_INET) { continue; } if (count++ == index) { sin = (struct sockaddr_in *)if_addr->ifa_addr; ip_addr = sin->sin_addr.s_addr; break; } } freeifaddrs(if_addrs); if_addrs = NULL; } return ip_addr; #elif __LINUX_OS__ int i; SOCKET socket_fd; struct ifreq *ifr; struct ifconf conf; char buff[BUFSIZ]; int num, count = 0; uint32 ip_addr = 0; socket_fd = socket(AF_INET, SOCK_DGRAM, 0); conf.ifc_len = BUFSIZ; conf.ifc_buf = buff; ioctl(socket_fd, SIOCGIFCONF, &conf); num = conf.ifc_len / sizeof(struct ifreq); ifr = conf.ifc_req; for (i=0; iifr_addr.sa_family != AF_INET) { ifr++; continue; } if (count++ == index) { struct sockaddr_in *sin = (struct sockaddr_in *)(&ifr->ifr_addr); ip_addr = sin->sin_addr.s_addr; break; } ifr++; } closesocket(socket_fd); return ip_addr; #endif return 0; } HT_API uint32 get_route_if_ip(uint32 dst_ip) { #if __WINDOWS_OS__ DWORD i; DWORD dwIfIndex,fr; char ipt_buf[1024]; MIB_IPADDRTABLE *ipt; ULONG ipt_len; fr = GetBestInterface(dst_ip, &dwIfIndex); if (fr != NO_ERROR) { return 0; } ipt = (MIB_IPADDRTABLE *)ipt_buf; ipt_len = sizeof(ipt_buf); fr = GetIpAddrTable(ipt, &ipt_len, FALSE); if (fr != NO_ERROR) { return 0; } for (i=0; idwNumEntries; i++) { if (ipt->table[i].dwIndex == dwIfIndex) { return ipt->table[i].dwAddr; } } #elif defined(IOS) struct ifaddrs *if_addrs = NULL; struct ifaddrs *if_addr = NULL; struct sockaddr_in * sin; uint32 ip_addr = 0; if (0 == getifaddrs(&if_addrs)) { for (if_addr = if_addrs; if_addr != NULL; if_addr = if_addr->ifa_next) { if (NULL == if_addr->ifa_addr || if_addr->ifa_addr->sa_family != AF_INET) { continue; } sin = (struct sockaddr_in *)if_addr->ifa_addr; if (((if_addr->ifa_flags & IFF_LOOPBACK) == 0) && (if_addr->ifa_flags & IFF_UP)) { ip_addr = sin->sin_addr.s_addr; break; } } freeifaddrs(if_addrs); if_addrs = NULL; } return ip_addr; #elif __LINUX_OS__ int i; SOCKET socket_fd; struct ifreq *ifr; struct ifconf conf; char buff[BUFSIZ]; int num; uint32 ip_addr = 0; socket_fd = socket(AF_INET, SOCK_DGRAM, 0); conf.ifc_len = BUFSIZ; conf.ifc_buf = buff; ioctl(socket_fd, SIOCGIFCONF, &conf); num = conf.ifc_len / sizeof(struct ifreq); ifr = conf.ifc_req; for (i=0; iifr_addr.sa_family != AF_INET) { ifr++; continue; } ioctl(socket_fd, SIOCGIFFLAGS, ifr); if (((ifr->ifr_flags & IFF_LOOPBACK) == 0) && (ifr->ifr_flags & IFF_UP)) { struct sockaddr_in *sin = (struct sockaddr_in *)(&ifr->ifr_addr); ip_addr = sin->sin_addr.s_addr; break; } ifr++; } closesocket(socket_fd); return ip_addr; #endif return 0; } HT_API uint32 get_default_if_ip() { uint32 ip = get_route_if_ip(0); if (ip != 0) { return ip; } else { int i; int nums = get_if_nums(); for (i = 0; i < nums; i++) { ip = get_if_ip(i); if (ip != 0 && ip != inet_addr("127.0.0.l")) { return ip; } } } return 0; } HT_API const char * get_local_ip() { uint32 ip = get_default_if_ip(); if (ip != 0) { return get_ip_str(ip); } return "127.0.0.1"; } HT_API uint32 get_if_mask(int index) { #if __WINDOWS_OS__ char ipt_buf[1024]; DWORD i; MIB_IPADDRTABLE * ipt = (MIB_IPADDRTABLE *)ipt_buf; ULONG ipt_len = sizeof(ipt_buf); DWORD fr = GetIpAddrTable(ipt, &ipt_len, FALSE); if (fr != NO_ERROR) { return inet_addr("255.255.255.255"); } for (i=0; idwNumEntries; i++) { if (i == index) { return ipt->table[i].dwMask; } } #elif defined(IOS) int count = 0; struct ifaddrs *if_addrs = NULL; struct ifaddrs *if_addr = NULL; struct sockaddr_in * sin; uint32 mask = inet_addr("255.255.255.255"); if (0 == getifaddrs(&if_addrs)) { for (if_addr = if_addrs; if_addr != NULL; if_addr = if_addr->ifa_next) { if (NULL == if_addr->ifa_addr || if_addr->ifa_addr->sa_family != AF_INET) { continue; } if (count++ == index) { sin = (struct sockaddr_in *)if_addr->ifa_netmask; mask = sin->sin_addr.s_addr; break; } } freeifaddrs(if_addrs); if_addrs = NULL; } return mask; #elif __LINUX_OS__ int i; SOCKET socket_fd; struct ifreq *ifr; struct ifconf conf; char buff[BUFSIZ]; int num, count = 0; uint32 mask = inet_addr("255.255.255.255"); socket_fd = socket(AF_INET, SOCK_DGRAM, 0); conf.ifc_len = BUFSIZ; conf.ifc_buf = buff; ioctl(socket_fd, SIOCGIFCONF, &conf); num = conf.ifc_len / sizeof(struct ifreq); ifr = conf.ifc_req; for (i=0; iifr_addr.sa_family != AF_INET) { ifr++; continue; } if (count++ == index) { struct sockaddr_in *sin = (struct sockaddr_in *)(&ifr->ifr_netmask); ioctl(socket_fd, SIOCGIFNETMASK, ifr); mask = sin->sin_addr.s_addr; break; } ifr++; } closesocket(socket_fd); return mask; #endif return inet_addr("255.255.255.255"); } HT_API uint32 get_route_if_mask(uint32 dst_ip) { #if __WINDOWS_OS__ DWORD i; DWORD dwIfIndex,fr; char ipt_buf[1024]; MIB_IPADDRTABLE *ipt; ULONG ipt_len; fr = GetBestInterface(dst_ip, &dwIfIndex); if (fr != NO_ERROR) { return inet_addr("255.255.255.255"); } ipt = (MIB_IPADDRTABLE *)ipt_buf; ipt_len = sizeof(ipt_buf); fr = GetIpAddrTable(ipt,&ipt_len,FALSE); if (fr != NO_ERROR) { return inet_addr("255.255.255.255"); } for (i=0; idwNumEntries; i++) { if (ipt->table[i].dwIndex == dwIfIndex) { return ipt->table[i].dwMask; } } #elif defined(IOS) struct ifaddrs *if_addrs = NULL; struct ifaddrs *if_addr = NULL; struct sockaddr_in * sin; uint32 mask = inet_addr("255.255.255.255"); if (0 == getifaddrs(&if_addrs)) { for (if_addr = if_addrs; if_addr != NULL; if_addr = if_addr->ifa_next) { if (NULL == if_addr->ifa_addr || if_addr->ifa_addr->sa_family != AF_INET) { continue; } sin = (struct sockaddr_in *)if_addr->ifa_netmask; if (((if_addr->ifa_flags & IFF_LOOPBACK) == 0) && (if_addr->ifa_flags & IFF_UP)) { mask = sin->sin_addr.s_addr; break; } } freeifaddrs(if_addrs); if_addrs = NULL; } return mask; #elif __LINUX_OS__ int i; SOCKET socket_fd; struct ifreq *ifr; struct ifconf conf; char buff[BUFSIZ]; int num; uint32 mask = inet_addr("255.255.255.255"); socket_fd = socket(AF_INET, SOCK_DGRAM, 0); conf.ifc_len = BUFSIZ; conf.ifc_buf = buff; ioctl(socket_fd, SIOCGIFCONF, &conf); num = conf.ifc_len / sizeof(struct ifreq); ifr = conf.ifc_req; for (i=0; iifr_addr.sa_family != AF_INET) { ifr++; continue; } ioctl(socket_fd, SIOCGIFFLAGS, ifr); if (((ifr->ifr_flags & IFF_LOOPBACK) == 0) && (ifr->ifr_flags & IFF_UP)) { struct sockaddr_in *sin = (struct sockaddr_in *)(&ifr->ifr_netmask); ioctl(socket_fd, SIOCGIFNETMASK, ifr); mask = sin->sin_addr.s_addr; break; } ifr++; } closesocket(socket_fd); return mask; #endif return inet_addr("255.255.255.255"); } HT_API uint32 get_default_if_mask() { return get_route_if_mask(0); } HT_API int is_local_if_net(uint32 destip) { int i; int nums; if (destip == inet_addr("127.0.0.1")) { return 1; } nums = get_if_nums(); for (i = 0; i < nums; i++) { uint32 ip = get_if_ip(i); uint32 mask = get_if_mask(i); if ((ip & mask) == (destip & mask)) { return 1; } } return 0; } HT_API int get_default_if_mac(uint8 * mac) { #ifdef IOS #elif __WINDOWS_OS__ IP_ADAPTER_INFO AdapterInfo[16]; // Allocate information for up to 16 NICs DWORD dwBufLen = sizeof(AdapterInfo); // Save the memory size of buffer DWORD dwStatus = GetAdaptersInfo( // Call GetAdapterInfo AdapterInfo, // [out] buffer to receive data &dwBufLen); // [in] size of receive data buffer PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo;// Contains pointer to current adapter info if (pAdapterInfo) { memcpy(mac, pAdapterInfo->Address, 6); return 0; } #elif __LINUX_OS__ int i; SOCKET socket_fd; struct ifreq *ifr; struct ifreq ifreq; struct ifconf conf; char buff[BUFSIZ]; int num; socket_fd = socket(AF_INET, SOCK_DGRAM, 0); conf.ifc_len = BUFSIZ; conf.ifc_buf = buff; ioctl(socket_fd, SIOCGIFCONF, &conf); num = conf.ifc_len / sizeof(struct ifreq); ifr = conf.ifc_req; for (i=0; iifr_addr.sa_family != AF_INET) { ifr++; continue; } ioctl(socket_fd, SIOCGIFFLAGS, ifr); if ((ifr->ifr_flags & IFF_LOOPBACK) != 0) { ifr++; continue; } strcpy(ifreq.ifr_name, ifr->ifr_name); if (ioctl(socket_fd, SIOCGIFHWADDR, &ifreq) < 0) { ifr++; continue; } memcpy(mac, &ifreq.ifr_hwaddr.sa_data, 6); close(socket_fd); return 0; } close(socket_fd); #endif return -1; } HT_API const char * get_default_gateway() { static char gateway[32]; #if __WINDOWS_OS__ IP_ADAPTER_INFO AdapterInfo[16]; // Allocate information for up to 16 NICs DWORD dwBufLen = sizeof(AdapterInfo); // Save the memory size of buffer DWORD dwStatus = GetAdaptersInfo( // Call GetAdapterInfo AdapterInfo, // [out] buffer to receive data &dwBufLen); // [in] size of receive data buffer PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo;// Contains pointer to current adapter info if (NULL == pAdapterInfo) { return NULL; } memset(gateway, 0, sizeof(gateway)); while (pAdapterInfo) { if (strcmp(pAdapterInfo->GatewayList.IpAddress.String, "0.0.0.0")) { strncpy(gateway, pAdapterInfo->GatewayList.IpAddress.String, sizeof(gateway)-1); break; } pAdapterInfo = pAdapterInfo->Next; } #elif __LINUX_OS__ char line[100], *p, *c, *g, *saveptr; int ret = 0; FILE *fp = fopen("/proc/net/route" , "r"); if (NULL == fp) { return NULL; } memset(gateway, 0, sizeof(gateway)); while (fgets(line, 100, fp)) { p = strtok_r(line, " \t", &saveptr); c = strtok_r(NULL, " \t", &saveptr); g = strtok_r(NULL, " \t", &saveptr); if (p != NULL && c != NULL) { if (strcmp(c, "00000000") == 0) { if (g) { char *p_end; int gw = strtol(g, &p_end, 16); struct in_addr addr; addr.s_addr = gw; strcpy(gateway, inet_ntoa(addr)); ret = 1; } break; } } } fclose(fp); if (ret == 0) { return NULL; } #endif return gateway; } HT_API const char * get_dns_server() { static char dns[32] = {'\0'}; #if __WINDOWS_OS__ IP_ADAPTER_ADDRESSES addr[16], *paddr; DWORD len = sizeof(addr); memset(dns, 0, sizeof(dns)); if (NO_ERROR == GetAdaptersAddresses(AF_INET, 0, 0, addr, &len) && len >= sizeof(IP_ADAPTER_ADDRESSES)) { paddr = addr; while (paddr) { PIP_ADAPTER_DNS_SERVER_ADDRESS p_ipaddr; if (paddr->IfType & IF_TYPE_SOFTWARE_LOOPBACK) { paddr = paddr->Next; continue; } p_ipaddr = paddr->FirstDnsServerAddress; if (p_ipaddr) { struct sockaddr_in * p_inaddr = (struct sockaddr_in *)p_ipaddr->Address.lpSockaddr; strcpy(dns, inet_ntoa(p_inaddr->sin_addr)); break; } paddr = paddr->Next; } } #elif __LINUX_OS__ uint32 i; char line[100] = {'\0'}; char * p; FILE * fp; memset(dns, 0, sizeof(dns)); fp = fopen("/etc/resolv.conf" , "r"); if (NULL == fp) { log_print(HT_LOG_ERR, "open file /etc/resolv.conf failed\r\n"); return dns; } while (fgets(line, 100, fp)) { p = line; while (*p == ' ') p++; // skip space if (strncasecmp(p, "nameserver", 10) != 0) { continue; } p += 10; while (*p == ' ') p++; // skip space i = 0; while (*p != '\0') { if (*p == ' ' || *p == '\n') { break; } if (i < sizeof(dns) - 1) { dns[i++] = *p++; } else { break; } } dns[i] = '\0'; if (is_ip_address(dns)) { break; } else { dns[0] = '\0'; } } #endif return dns; } HT_API const char * get_mask_by_prefix_len(int len) { int i; static char mask_str[32] = {'\0'}; uint32 mask = 0; len = (len > 32 ? 32 : len); for (i = 0; i < len; i++) { mask |= (1 << (31 - i)); } memset(mask_str, 0, sizeof(mask_str)); snprintf(mask_str, sizeof(mask_str), "%u.%u.%u.%u", (mask & 0xFF000000) >> 24, (mask & 0x00FF0000) >> 16, (mask & 0x0000FF00) >> 8, (mask & 0x000000FF)); return mask_str; } HT_API int get_prefix_len_by_mask(const char * mask) { int i; int len = 0; uint32 n = inet_addr(mask); n = ntohl(n); for (i = 0; i < 32; i++) { if (n & ((uint32)1 << (31 - i))) { len++; } else { break; } } return len; } HT_API const char * get_ip_str(uint32 ipaddr /* network byte order */) { struct in_addr addr; addr.s_addr = ipaddr; return inet_ntoa(addr); } HT_API uint32 get_address_by_name(const char * host_name) { uint32 addr = 0; if (is_ip_address(host_name)) { addr = inet_addr(host_name); } else { struct hostent * remoteHost = gethostbyname(host_name); if (remoteHost) { addr = *(unsigned long *)(remoteHost->h_addr); } } return addr; } HT_API char * lowercase(char * str) { uint32 i; for (i = 0; i < strlen(str); ++i) { str[i] = tolower(str[i]); } return str; } HT_API char * uppercase(char * str) { uint32 i; for (i = 0; i < strlen(str); ++i) { str[i] = toupper(str[i]); } return str; } HT_API int unicode(char ** dst, char * src) { char *ret; int l, i; if (!src) { *dst = NULL; return 0; } l = MIN(64, (int)strlen(src)); ret = (char *)malloc(2*l); if (NULL == ret) { *dst = NULL; return 0; } for (i = 0; i < l; ++i) { ret[2*i] = src[i]; ret[2*i+1] = '\0'; } *dst = ret; return 2*l; } HT_API BOOL bin_to_hex_str(uint8 * bin, int binlen, char * hex, int hexlen) { uint16 i; uint8 j; if (hexlen <= binlen*2) { return FALSE; } for (i = 0; i < binlen; i++) { j = (bin[i] >> 4) & 0xf; if (j <= 9) { hex[i*2] = (j + '0'); } else { hex[i*2] = (j + 'a' - 10); } j = bin[i] & 0xf; if (j <= 9) { hex[i*2+1] = (j + '0'); } else { hex[i*2+1] = (j + 'a' - 10); } }; hex[binlen*2] = '\0'; return TRUE; }; HT_API int hex_str_to_bin(char * hex, int hexlen, uint8 * bin, int binlen) { int i; if (binlen < hexlen/2) { return 0; } for (i=0; i= '0' && hex[i*2] <= '9') { bin[i] = (hex[i*2] - '0') << 4; } else if (hex[i*2] >= 'a' && hex[i*2] <= 'z') { bin[i] = (hex[i*2] - 'a' + 10) << 4; } else if (hex[i*2] >= 'A' && hex[i*2] <= 'Z') { bin[i] = (hex[i*2] - 'A' + 10) << 4; } else { return 0; } if (hex[i*2+1] >= '0' && hex[i*2+1] <= '9') { bin[i] |= (hex[i*2+1] - '0'); } else if (hex[i*2+1] >= 'a' && hex[i*2+1] <= 'z') { bin[i] |= hex[i*2+1] - 'a' + 10; } else if (hex[i*2+1] >= 'A' && hex[i*2+1] <= 'Z') { bin[i] |= hex[i*2+1] - 'A' + 10; } else { return 0; } } return i; } static char hextab[17] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 0}; HT_API int url_encode(const char * src, const int srcsize, char * dst, const int dstsize) { int i; int j; char ch; if ((NULL == src) || (NULL == dst) || (srcsize <= 0) || (dstsize <= 0)) { return 0; } for (i = 0, j = 0; i < srcsize && j < dstsize; ++i) { ch = src[i]; if (((ch >= 'A') && (ch <= 'Z')) || ((ch >= 'a') && (ch <= 'z')) || ((ch >= '0') && (ch <= '9')) || ch == '.' || ch == '-' || ch == '_' || ch == '*') { dst[j++] = ch; } else if (ch == ' ') { dst[j++] = '+'; } else { if (j+3 < dstsize) { dst[j] = '%'; dst[j+1] = hextab[ch >> 4]; dst[j+2] = hextab[ch & 15]; j+=3; } else { return 0; } } } dst[j] = '\0'; return j; } HT_API int url_decode(char * dst, char const * src, uint32 len) { char * p_dst = dst; const char * p_src = src; while (len > 0) { int before = 0; int after = 0; if (*p_src == '+') { ++p_src; --len; *p_dst++ = ' '; } else if (*p_src == '%' && len >= 3 && sscanf(p_src+1, "%n%2hhx%n", &before, p_dst, &after) == 1) { uint32 size = after - before; // should be 1 or 2 ++p_dst; p_src += (1 + size); len -= (1 + size); } else { *p_dst++ = *p_src++; --len; } } *p_dst = '\0'; return (int)(p_dst - dst); } void url_split(char const* url, char *proto, int proto_size, char *user, int user_size, char *pass, int pass_size, char *host, int host_size, int *port, char *path, int path_size) { uint32 len; const char *p, *ls, *ls2, *at, *col, *brk; if (port) *port = -1; if (proto_size > 0) proto[0] = 0; if (user_size > 0) user[0] = 0; if (pass_size > 0) pass[0] = 0; if (host_size > 0) host[0] = 0; if (path_size > 0) path[0] = 0; /* parse protocol */ if ((p = strchr(url, ':'))) { if (proto) { len = MIN(proto_size - 1, p - url); strncpy(proto, url, len); proto[len] = '\0'; } p++; /* skip ':' */ if (*p == '/') p++; if (*p == '/') p++; } else if (path) { /* no protocol means plain filename */ len = MIN(path_size - 1, (int)strlen(url)); strncpy(path, url, len); path[len] = '\0'; return; } if (NULL == p) { return; } /* separate path from hostname */ ls = strchr(p, '/'); ls2 = strchr(p, '?'); if (!ls) ls = ls2; else if (ls2) ls = MIN(ls, ls2); if (ls) { if (path) { len = MIN(path_size - 1, (int)strlen(ls)); strncpy(path, ls, len); path[len] = '\0'; } } else { ls = &p[strlen(p)]; // XXX } /* the rest is hostname, use that to parse auth/port */ if (ls != p) { /* authorization (user[:pass]@hostname) */ while ((at = strchr(p, '@')) && at < ls) { if ((brk = strchr(p, ':')) && brk < ls) { if (user) { url_decode(user, p, MIN(user_size-1, brk - p)); } if (pass) { url_decode(pass, brk + 1, MIN(pass_size-1, at - brk - 1)); } } p = at + 1; /* skip '@' */ } if (*p == '[' && (brk = strchr(p, ']')) && brk < ls) { /* [host]:port */ if (host) { len = MIN(host_size - 1, brk - 1 - p); strncpy(host, p + 1, len); host[len] = '\0'; } if (brk[1] == ':' && port) { *port = atoi(brk + 2); } } else if ((col = strchr(p, ':')) && col < ls) { if (host) { len = MIN(host_size - 1, col - p); strncpy(host, p, len); host[len] = '\0'; } if (port) { *port = atoi(col + 1); } } else if (host) { len = MIN(host_size - 1, ls - p); strncpy(host, p, len); host[len] = '\0'; } } } HT_API time_t get_time_by_string(char * p_time_str) { char * ptr_s; struct tm st; memset(&st, 0, sizeof(struct tm)); ptr_s = p_time_str; while (*ptr_s == ' ' || *ptr_s == '\t') { ptr_s++; } sscanf(ptr_s, "%04d-%02d-%02d %02d:%02d:%02d", &st.tm_year, &st.tm_mon, &st.tm_mday, &st.tm_hour, &st.tm_min, &st.tm_sec); st.tm_year -= 1900; st.tm_mon -= 1; return mktime(&st); } HT_API void get_time_str(char * buff, int len) { time_t nowtime; struct tm *t1; time(&nowtime); t1 = localtime(&nowtime); snprintf(buff, len, "%04d-%02d-%02d %02d:%02d:%02d", t1->tm_year+1900, t1->tm_mon+1, t1->tm_mday, t1->tm_hour, t1->tm_min, t1->tm_sec); } HT_API void get_time_str_day_off(time_t nt, char * buff, int len, int dayoff) { struct tm *t1; time_t nt1 = nt + dayoff * 24 * 3600; t1 = localtime(&nt1); snprintf(buff, len, "%04d-%02d-%02d %02d:%02d:%02d", t1->tm_year+1900, t1->tm_mon+1, t1->tm_mday, t1->tm_hour, t1->tm_min, t1->tm_sec); } HT_API void get_time_str_mon_off(time_t nt, char * buff, int len, int moffset) { struct tm *t1; int year; int day_of_month[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; t1 = localtime(&nt); t1->tm_mon += moffset; t1->tm_year += t1->tm_mon / 12; t1->tm_mon = t1->tm_mon % 12; year = t1->tm_year + 1900; if ((year % 400) == 0 || ((year % 100) != 0 && (year % 4) == 0)) { day_of_month[1] = 29; } if (t1->tm_mday > day_of_month[t1->tm_mon]) { t1->tm_mday = day_of_month[t1->tm_mon]; } snprintf(buff, len, "%04d-%02d-%02d %02d:%02d:%02d", t1->tm_year+1900, t1->tm_mon+1, t1->tm_mday, t1->tm_hour, t1->tm_min, t1->tm_sec); } HT_API time_t get_time_by_tstring(const char * p_time_str) { const char * ptr_s; struct tm st; memset(&st, 0, sizeof(struct tm)); ptr_s = p_time_str; while (*ptr_s == ' ' || *ptr_s == '\t') { ptr_s++; } sscanf(ptr_s, "%04d-%02d-%02dT%02d:%02d:%02d", &st.tm_year, &st.tm_mon, &st.tm_mday, &st.tm_hour, &st.tm_min, &st.tm_sec); st.tm_year -= 1900; st.tm_mon -= 1; return mktime(&st); } HT_API void get_tstring_by_time(time_t t, char * buff, int len) { struct tm *t1; t1 = localtime(&t); snprintf(buff, len, "%04d-%02d-%02dT%02d:%02d:%02d", t1->tm_year+1900, t1->tm_mon+1, t1->tm_mday, t1->tm_hour, t1->tm_min, t1->tm_sec); } HT_API SOCKET tcp_connect(const char * hostname, int port, int timeout) { int ret; SOCKET fd; char portstr[10]; struct timeval tv; struct addrinfo hints, *ai, *cur_ai; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", port); ret = getaddrinfo(hostname, portstr, &hints, &ai); if (ret) { log_print(HT_LOG_ERR, "Failed to resolve hostname %s\r\n", hostname); return -1; } fd = -1; for (cur_ai = ai; cur_ai; cur_ai = cur_ai->ai_next) { fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); if (fd <= 0) { continue; } tv.tv_sec = timeout/1000; tv.tv_usec = (timeout%1000) * 1000; setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv)); if (connect(fd, cur_ai->ai_addr, (int)(cur_ai->ai_addrlen)) < 0) { closesocket(fd); fd = -1; log_print(HT_LOG_ERR, "Connect hostname %s failed\r\n", hostname); continue; } break; /* okay we got one */ } freeaddrinfo(ai); return fd; } HT_API SOCKET tcp_connect_timeout(uint32 rip, int port, int timeout) { SOCKET cfd; struct sockaddr_in addr; #if __LINUX_OS__ uint32 starttime = sys_os_get_ms(); struct timeval tv; #elif __WINDOWS_OS__ int flag = 0; unsigned long ul = 1; #endif cfd = socket(AF_INET, SOCK_STREAM, 0); if (cfd <= 0) { log_print(HT_LOG_ERR, "%s, socket failed\n", __FUNCTION__); return 0; } addr.sin_family = AF_INET; addr.sin_addr.s_addr = rip; addr.sin_port = htons((uint16)port); #if __LINUX_OS__ tv.tv_sec = timeout/1000; tv.tv_usec = (timeout%1000) * 1000; setsockopt(cfd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv)); while (connect(cfd, (struct sockaddr *)&addr, sizeof(addr)) == -1 && errno != EISCONN) { if (sys_os_get_ms() > starttime + timeout) { closesocket(cfd); return -1; } if (errno != EINTR) { closesocket(cfd); return -1; } } return cfd; #elif __WINDOWS_OS__ ioctlsocket(cfd, FIONBIO, &ul); if (connect(cfd, (struct sockaddr *)&addr, sizeof(addr)) != 0) { fd_set set; struct timeval tv; tv.tv_sec = timeout/1000; tv.tv_usec = (timeout%1000) * 1000; FD_ZERO(&set); FD_SET(cfd, &set); if (select((int)(cfd+1), NULL, &set, NULL, &tv) > 0) { int err = 0, len = sizeof(int); getsockopt(cfd, SOL_SOCKET, SO_ERROR, (char *)&err, (socklen_t*) &len); if (err == 0) { flag = 1; } } } else { flag = 1; } ul = 0; ioctlsocket(cfd, FIONBIO, &ul); if (flag == 1) { return cfd; } else { closesocket(cfd); return 0; } #endif } static int callCount = 0; HT_API void network_init() { callCount++; log_print(HT_LOG_INFO, "Number of network_init called: %d,\n", callCount); if (callCount == 1) { // Only initialize Winsock on the first call log_print(HT_LOG_INFO, "Initialise network: %d,\n", callCount); WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { // Handle initialization failure log_print(HT_LOG_ERR, "%s, network_init failed\n", __FUNCTION__);//HT_LOG_INFO } } } // Function to deinitialize network resources (e.g., Winsock) HT_API void network_deinit() { if (callCount > 0) { // Ensure network has been initialized before deinitialization callCount--; log_print(HT_LOG_INFO, "Number of network_deinit called: %d,\n", callCount); if (callCount == 0) { // Deinitialize Winsock if it's the last deinitialization log_print(HT_LOG_INFO, "Deinitialize network\n"); if (WSACleanup() != 0) { // Handle deinitialization failure log_print(HT_LOG_ERR, "%s, network_deinit failed\n", __FUNCTION__); } } } } HT_API int daemon_init() { #if __LINUX_OS__ pid_t pid; pid = fork(); if (pid == -1) { return -1; } else if (pid > 0) { exit(0); } setsid(); #endif return 0; } #if __WINDOWS_OS__ #include // used to make sure that static variables in gettimeofday() aren't // initialized simultaneously by multiple threads static long g_gettimeofday_lock = 0; HT_API int gettimeofday(struct timeval * tp, int * tz) { static LARGE_INTEGER tickFrequency, epochOffset; static BOOL isInitialized = FALSE; LARGE_INTEGER tickNow; QueryPerformanceCounter(&tickNow); if (!isInitialized) { if (1 == InterlockedIncrement(&g_gettimeofday_lock)) { // For our first call, use "ftime()", so that we get a time with a proper epoch. // For subsequent calls, use "QueryPerformanceCount()", because it's more fine-grain. struct timeb tb; ftime(&tb); tp->tv_sec = (long)tb.time; tp->tv_usec = 1000*tb.millitm; // Also get our counter frequency: QueryPerformanceFrequency(&tickFrequency); // compute an offset to add to subsequent counter times, so we get a proper epoch: epochOffset.QuadPart = tp->tv_sec * tickFrequency.QuadPart + (tp->tv_usec * tickFrequency.QuadPart) / 1000000L - tickNow.QuadPart; // next caller can use ticks for time calculation isInitialized = TRUE; return 0; } else { InterlockedDecrement(&g_gettimeofday_lock); // wait until first caller has initialized static values while (!isInitialized) { Sleep(1); } } } // adjust our tick count so that we get a proper epoch: tickNow.QuadPart += epochOffset.QuadPart; tp->tv_sec = (long)(tickNow.QuadPart / tickFrequency.QuadPart); tp->tv_usec = (long)(((tickNow.QuadPart % tickFrequency.QuadPart) * 1000000L) / tickFrequency.QuadPart); return 0; } #endif