ip parse / to_string / compare util function is ready

This commit is contained in:
lion 2025-09-17 13:07:35 +08:00
parent 0fd0bc59d0
commit 4cff9eb6ee
4 changed files with 252 additions and 78 deletions

Binary file not shown.

View File

@ -9,32 +9,12 @@
#include "stdio.h"
#include "xdb_api.h"
void test_check_ip() {
char *ip_list[] = {
"1.2.3.4", "192.168.2.3", "120.24.78.129", "255.255.255.0",
"256.7.12.9", "12.56.78.320", "32.12.45.192", "222.221.220.219",
"192.168.1.101 ", "132.96.12.98a", "x23.12.2.12"
};
int errcode, i;
unsigned int ip;
char ip_buff[16] = {'\0'};
for (i = 0; i < 11; i++) {
errcode = xdb_check_ip(ip_list[i], &ip);
if (errcode != 0) {
printf("invalid ip address `%s`\n", ip_list[i]);
continue;
}
xdb_long2ip(ip, ip_buff);
printf("long(%-15s)=%-10u, long2ip(%-10u)=%-15s", ip_list[i], ip, ip, ip_buff);
if (strcmp(ip_list[i], ip_buff) != 0) {
printf(" --[Failed]\n");
} else {
printf(" --[Ok]\n");
}
}
}
typedef void (* test_func_ptr) ();
struct test_func_entry {
char *name;
test_func_ptr func;
};
typedef struct test_func_entry test_func_t;
void test_load_header() {
xdb_header_t *header = xdb_load_header_from_file("../../data/ip2region_v4.xdb");
@ -79,23 +59,146 @@ void test_load_content() {
xdb_free_content(content);
}
void test_parse_ip() {
const char *ip_list[] = {
"1.0.0.0", "58.251.30.115", "192.168.1.100",
"::", "2c0f:fff0::", "2fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "240e:982:e617:ffff:ffff:ffff:ffff:ffff",
"219.xx.xx.11", "::xx:ffff",
NULL
};
int errcode;
bytes_ip_t ip_bytes[17] = {'\0'};
string_ip_t ip_string[INET6_ADDRSTRLEN + 1] = {'\0'};
// init the sock env (for windows)
if ((errcode = xdb_init_winsock()) != 0) {
printf("failed to init the winsock");
return;
}
for (int i = 0;; i++) {
if (ip_list[i] == NULL) {
break;
}
errcode = xdb_parse_ip(ip_list[i], ip_bytes, sizeof(ip_bytes));
if (errcode == -1) {
printf("failed to parse ip `%s`\n", ip_list[i]);
continue;
}
xdb_ip_to_string(ip_bytes, errcode, ip_string, sizeof(ip_string));
printf("ip: %s (version=v%d), toString: %s\n", ip_list[i], errcode, ip_string);
}
// clean up the winsock
xdb_clean_winsock();
}
struct ip_pair {
const char *sip;
const char *eip;
};
void test_ip_compare() {
struct ip_pair ip_pair_list[] = {
{"1.0.0.0", "1.0.0.1"},
{"192.168.1.101", "192.168.1.90"},
{"219.133.111.87", "114.114.114.114"},
{"1.0.4.0", "1.0.1.0"},
{"1.0.4.0", "1.0.3.255"},
{"2000::", "2000:ffff:ffff:ffff:ffff:ffff:ffff:ffff"},
{"2001:4:112::", "2001:4:112:ffff:ffff:ffff:ffff:ffff"},
{"ffff::", "2001:4:ffff:ffff:ffff:ffff:ffff:ffff"},
{NULL, NULL}
};
struct ip_pair *pair_ptr = NULL;
bytes_ip_t sip_bytes[16] = {'\0'};
bytes_ip_t eip_bytes[16] = {'\0'};
int sip_version, eip_version, bytes, errcode;
// init the sock env (for windows)
if ((errcode = xdb_init_winsock()) != 0) {
printf("failed to init the winsock");
return;
}
for (int i = 0; ;i++) {
pair_ptr = &ip_pair_list[i];
if (pair_ptr->sip == NULL) {
break;
}
sip_version = xdb_parse_ip(pair_ptr->sip, sip_bytes, sizeof(sip_bytes));
if (sip_version == -1) {
printf("failed to parse sip `%s`", pair_ptr->sip);
continue;
}
eip_version = xdb_parse_ip(pair_ptr->eip, eip_bytes, sizeof(eip_bytes));
if (eip_version == -1) {
printf("failed to parse eip `%s`", pair_ptr->eip);
continue;
}
bytes = sip_version == xdb_ipv4_version_no ? xdb_ipv4_bytes : xdb_ipv6_bytes;
printf(
"ip_sub_compare(%s, %s): %d\n",
pair_ptr->sip, pair_ptr->eip,
xdb_ip_sub_compare(sip_bytes, bytes, eip_bytes, 0)
);
}
// clean up the winsock
xdb_clean_winsock();
}
// please register your function heare
static test_func_t _test_function_list[] = {
// xdb buffer
{"test_load_header", test_load_header},
{"test_load_vector_index", test_load_vector_index},
{"test_load_content", test_load_content},
// ip utils
{"test_parse_ip", test_parse_ip},
{"test_ip_compare", test_ip_compare},
{NULL, NULL}
};
// valgrind --tool=memcheck --leak-check=full ./a.out
int main(int argc, char *argv[]) {
printf("test check ip ... \n");
test_check_ip();
printf("|--done\n\n");
int i;
char *name;
printf("test load header ... \n");
test_load_header();
printf("|--done\n\n");
// check and call the function
if (argc < 2) {
printf("please specified the function name to call\n");
return 1;
}
printf("test load vector index ... \n");
test_load_vector_index();
printf("|--done\n\n");
name = argv[1];
test_func_ptr func = NULL;
for (i = 0; ; i++) {
if (_test_function_list[i].name == NULL) {
break;
}
printf("test load content ... \n");
test_load_content();
printf("|--done\n\n");
if (strcmp(name, _test_function_list[i].name) == 0) {
func = _test_function_list[i].func;
break;
}
}
if (func == NULL) {
printf("can't find test function `%s`\n", name);
return 1;
}
// call the function
func();
return 0;
}

View File

@ -17,10 +17,17 @@
# define XDB_PUBLIC(type) extern __declspec(dllexport) type
# define XDB_PRIVATE(type) static type
# define XDB_WINDOWS
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#elif ( defined(linux) || defined(_UNIX) || defined(__APPLE__) )
# define XDB_PUBLIC(type) extern type
# define XDB_PRIVATE(type) static inline type
# define XDB_LINUX
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#define xdb_calloc( _blocks, _bytes ) calloc( _blocks, _bytes )
@ -37,6 +44,8 @@
// --- ip version info
#define xdb_ipv4_version_no 4
#define xdb_ipv6_version_no 6
#define xdb_ipv4_bytes 4
#define xdb_ipv6_bytes 16
#define XDB_IPV4 4
#define XDB_IPv6 6
@ -49,6 +58,11 @@ typedef unsigned char bytes_ip_t;
// --- xdb util functions
// to compatiable with the windows
// returns: 0 for ok and -1 for failed
XDB_PUBLIC(int) xdb_init_winsock();
XDB_PUBLIC(void) xdb_clean_winsock();
// get the current time in microseconds
XDB_PUBLIC(long) xdb_now();
@ -79,7 +93,7 @@ XDB_PUBLIC(int) xdb_parse_v6_ip(const string_ip_t *, bytes_ip_t *, size_t);
// convert a specified ip bytes to humen-readable string.
// returns: 0 for success or -1 for failed.
XDB_PUBLIC(int) xdb_ip_to_string(const bytes_ip_t *, size_t, char *, size_t);
XDB_PUBLIC(int) xdb_ip_to_string(const bytes_ip_t *, int, char *, size_t);
// ipv4 bytes to string
XDB_PUBLIC(int) xdb_v4_ip_to_string(const bytes_ip_t *, char *, size_t);

View File

@ -15,7 +15,27 @@
// @Note: since 2023/10/13 to compatible with the windows system
#ifdef XDB_WINDOWS
#include <windows.h>
static int winsock_initialized = 0;
XDB_PUBLIC(int) xdb_init_winsock() {
if (winsock_initialized == 1) {
return 0;
}
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
return -1;
}
winsock_initialized = 1;
return 0;
}
XDB_PUBLIC(void) xdb_clean_winsock() {
if (winsock_initialized == 1) {
WSACleanup();
winsock_initialized = 0;
}
}
XDB_PRIVATE(int) gettimeofday(struct timeval* tp, void* tzp) {
time_t clock;
struct tm tm;
@ -33,6 +53,9 @@ XDB_PRIVATE(int) gettimeofday(struct timeval* tp, void* tzp) {
tp->tv_usec = wtm.wMilliseconds * 1000;
return (0);
}
#else
XDB_PUBLIC(int) xdb_init_winsock() {return 0;}
XDB_PUBLIC(void) xdb_clean_winsock() {}
#endif
XDB_PUBLIC(long) xdb_now() {
@ -96,66 +119,100 @@ XDB_PUBLIC(void) xdb_long2ip(unsigned int ip, char *buffer) {
sprintf(buffer, "%d.%d.%d.%d", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF);
}
XDB_PUBLIC(int) xdb_parse_ip(const string_ip_t *ip, bytes_ip_t *buffer, size_t length) {
// where there is a . there is a IPV4 even though there are IPv6 wrapped IPv4 like
// ::ffff:192.168.1.100, lets just keep it in this way.
if (strchr(ip, '.') != NULL) {
return xdb_parse_v4_ip(ip, buffer, length);
} else if (strchr(ip, ':') != NULL) {
return xdb_parse_v6_ip(ip, buffer, length);
XDB_PUBLIC(int) xdb_parse_ip(const string_ip_t *ip_string, bytes_ip_t *buffer, size_t length) {
// version check
if (strchr(ip_string, '.') != NULL && strchr(ip_string, ':') == NULL) {
return xdb_parse_v4_ip(ip_string, buffer, length);
} else if (strchr(ip_string, ':') != NULL) {
return xdb_parse_v6_ip(ip_string, buffer, length);
}
return -1;
}
XDB_PUBLIC(int) xdb_parse_v4_ip(const string_ip_t *ip, bytes_ip_t *buffer, size_t length) {
return 0;
XDB_PUBLIC(int) xdb_parse_v4_ip(const string_ip_t *ip_string, bytes_ip_t *buffer, size_t length) {
struct in_addr addr;
// buffer length checking
if (length < xdb_ipv4_bytes) {
return -1;
}
if (inet_pton(AF_INET, ip_string, &addr) != 1) {
return -1;
}
// encode the address to buffer with big endian byte bufffer.
buffer[0] = (addr.s_addr) & 0xFF;
buffer[1] = (addr.s_addr >> 8) & 0xFF;
buffer[2] = (addr.s_addr >> 16) & 0xFF;
buffer[3] = (addr.s_addr >> 24) & 0xFF;
return xdb_ipv4_version_no;
}
XDB_PUBLIC(int) xdb_parse_v6_ip(const string_ip_t *ip, bytes_ip_t *buffer, size_t length) {
return 0;
XDB_PUBLIC(int) xdb_parse_v6_ip(const string_ip_t *ip_string, bytes_ip_t *buffer, size_t length) {
struct in6_addr addr;
// buffer length checking
if (length < xdb_ipv6_bytes) {
return -1;
}
if (inet_pton(AF_INET6, ip_string, &addr) != 1) {
return -1;
}
memcpy(buffer, addr.s6_addr, xdb_ipv6_bytes);
return xdb_ipv6_version_no;
}
XDB_PUBLIC(int) xdb_ip_to_string(const bytes_ip_t *ip, size_t bytes, char *buffer, size_t length) {
if (bytes == 4) {
return xdb_v4_ip_to_string(ip, buffer, length);
} else if (bytes == 16) {
return xdb_v6_ip_to_string(ip, buffer, length);
XDB_PUBLIC(int) xdb_ip_to_string(const bytes_ip_t *ip_bytes, int version, char *ip_string, size_t length) {
if (version == xdb_ipv4_version_no) {
return xdb_v4_ip_to_string(ip_bytes, ip_string, length);
} else if (version == xdb_ipv6_version_no) {
return xdb_v6_ip_to_string(ip_bytes, ip_string, length);
}
return -1;
}
XDB_PUBLIC(int) xdb_v4_ip_to_string(const bytes_ip_t *ip, char *buffer, size_t length) {
snprintf(
buffer, length,
"%d.%d.%d.%d",
ip[0], ip[1], ip[2], ip[3]
);
XDB_PUBLIC(int) xdb_v4_ip_to_string(const bytes_ip_t *ip_bytes, char *ip_string, size_t length) {
if (!ip_bytes || !ip_string || length == 0) {
return -1;
}
// buffer length checking
if (length < INET_ADDRSTRLEN) {
return -1;
}
if (inet_ntop(AF_INET, ip_bytes, ip_string, length) == NULL) {
return -1;
}
return 0;
}
XDB_PUBLIC(int) xdb_v6_ip_to_string(const bytes_ip_t *ip, char *buffer, size_t length) {
// temp solution for testing ONLY, we will handle the :: later
snprintf(
buffer, length,
"%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x",
ip[0], ip[1],
ip[2], ip[3],
ip[4], ip[5],
ip[6], ip[7],
ip[8], ip[9],
ip[10], ip[11],
ip[12], ip[13],
ip[14], ip[15]
);
XDB_PUBLIC(int) xdb_v6_ip_to_string(const bytes_ip_t *ip_bytes, char *ip_string, size_t length) {
if (!ip_bytes || !ip_string || length == 0) {
return -1;
}
if (length < INET6_ADDRSTRLEN) {
return -1;
}
if (inet_ntop(AF_INET6, ip_bytes, ip_string, length) == NULL) {
return -1;
}
return 0;
}
XDB_PUBLIC(int) xdb_ip_sub_compare(const bytes_ip_t *ip1, size_t length, const char *buffer, int offset) {
int i, i1, i2;
register int i, i1, i2;
for (i = 0; i < length; i++) {
i1 = ip1[i] & 0xFF;
i1 = ip1[i];
i2 = buffer[offset + i] & 0xFF;
if (i1 > i2) {
return 1;