ts-ip2region2 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -0
- package/README_CN.md +119 -0
- package/addon.cpp +258 -0
- package/binding.gyp +30 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/ip2region/Makefile +27 -0
- package/ip2region/ReadMe.md +341 -0
- package/ip2region/main.c +428 -0
- package/ip2region/test_util +0 -0
- package/ip2region/test_util.c +213 -0
- package/ip2region/xdb_api.h +272 -0
- package/ip2region/xdb_searcher.c +242 -0
- package/ip2region/xdb_util.c +496 -0
- package/package.json +78 -0
package/ip2region/main.c
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
// Copyright 2022 The Ip2Region Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a Apache2.0-style
|
|
3
|
+
// license that can be found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
// ---
|
|
6
|
+
// @Author Lion <chenxin619315@gmail.com>
|
|
7
|
+
// @Date 2022/06/28
|
|
8
|
+
|
|
9
|
+
#include "stdio.h"
|
|
10
|
+
#include "xdb_api.h"
|
|
11
|
+
|
|
12
|
+
struct searcher_test_entry {
|
|
13
|
+
xdb_searcher_t searcher;
|
|
14
|
+
xdb_vector_index_t *v_index;
|
|
15
|
+
xdb_content_t *c_buffer;
|
|
16
|
+
|
|
17
|
+
// xdb region buffer
|
|
18
|
+
// char region_buffer[256];
|
|
19
|
+
xdb_region_buffer_t region;
|
|
20
|
+
};
|
|
21
|
+
typedef struct searcher_test_entry searcher_test_t;
|
|
22
|
+
|
|
23
|
+
int init_searcher_test(searcher_test_t *test, char *db_path, char *cache_policy) {
|
|
24
|
+
int err, errcode = 0;
|
|
25
|
+
FILE *handle = fopen(db_path, "rb");
|
|
26
|
+
if (handle == NULL) {
|
|
27
|
+
return -1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// auto detect the version from the xdb header
|
|
31
|
+
xdb_header_t *header = xdb_load_header(handle);
|
|
32
|
+
if (header == NULL) {
|
|
33
|
+
printf("failed to load header from `%s`\n", db_path);
|
|
34
|
+
errcode = 1;
|
|
35
|
+
goto defer;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// verify the current xdb
|
|
39
|
+
err = xdb_verify_from_header(handle, header);
|
|
40
|
+
if (err != 0) {
|
|
41
|
+
printf("failed to verify xdb file `%s` with errno=%d\n", db_path, err);
|
|
42
|
+
errcode = 2;
|
|
43
|
+
goto defer;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
xdb_version_t *version = xdb_version_from_header(header);
|
|
47
|
+
if (version == NULL) {
|
|
48
|
+
printf("failed to load version from header\n");
|
|
49
|
+
errcode = 3;
|
|
50
|
+
goto defer;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
test->v_index = NULL;
|
|
54
|
+
test->c_buffer = NULL;
|
|
55
|
+
|
|
56
|
+
if (strcmp(cache_policy, "file") == 0) {
|
|
57
|
+
err = xdb_new_with_file_only(version, &test->searcher, db_path);
|
|
58
|
+
if (err != 0) {
|
|
59
|
+
printf("failed to create searcher with errcode=%d\n", err);
|
|
60
|
+
errcode = 4;
|
|
61
|
+
goto defer;
|
|
62
|
+
}
|
|
63
|
+
} else if (strcmp(cache_policy, "vectorIndex") == 0) {
|
|
64
|
+
test->v_index = xdb_load_vector_index_from_file(db_path);
|
|
65
|
+
if (test->v_index == NULL) {
|
|
66
|
+
printf("failed to load vector index from `%s`\n", db_path);
|
|
67
|
+
errcode = 4;
|
|
68
|
+
goto defer;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
err = xdb_new_with_vector_index(version, &test->searcher, db_path, test->v_index);
|
|
72
|
+
if (err != 0) {
|
|
73
|
+
printf("failed to create vector index cached searcher with errcode=%d\n", err);
|
|
74
|
+
errcode = 5;
|
|
75
|
+
goto defer;
|
|
76
|
+
}
|
|
77
|
+
} else if (strcmp(cache_policy, "content") == 0) {
|
|
78
|
+
test->c_buffer = xdb_load_content_from_file(db_path);
|
|
79
|
+
if (test->c_buffer == NULL) {
|
|
80
|
+
printf("failed to load xdb content from `%s`\n", db_path);
|
|
81
|
+
errcode = 4;
|
|
82
|
+
goto defer;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
err = xdb_new_with_buffer(version, &test->searcher, test->c_buffer);
|
|
86
|
+
if (err != 0) {
|
|
87
|
+
printf("failed to create content cached searcher with errcode=%d\n", err);
|
|
88
|
+
errcode = 5;
|
|
89
|
+
goto defer;
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
printf("invalid cache policy `%s`, options: file/vectorIndex/content\n", cache_policy);
|
|
93
|
+
errcode = 6;
|
|
94
|
+
goto defer;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// init the region buffer
|
|
98
|
+
// err = xdb_region_buffer_init(&test->region, test->region_buffer, sizeof(test->region_buffer));
|
|
99
|
+
err = xdb_region_buffer_init(&test->region, NULL, 0);
|
|
100
|
+
if (err != 0) {
|
|
101
|
+
printf("failed to init the region buffer with err=%d\n", err);
|
|
102
|
+
errcode = 7;
|
|
103
|
+
goto defer;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
defer:
|
|
107
|
+
if (header != NULL) {
|
|
108
|
+
xdb_free_header(header);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (handle != NULL) {
|
|
112
|
+
fclose(handle);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return errcode;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
void destroy_searcher_test(searcher_test_t *test) {
|
|
119
|
+
xdb_close(&test->searcher);
|
|
120
|
+
|
|
121
|
+
// check and free the vector index
|
|
122
|
+
if (test->v_index != NULL) {
|
|
123
|
+
xdb_free_vector_index(test->v_index);
|
|
124
|
+
test->v_index = NULL;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// check and free the content buffer
|
|
128
|
+
if (test->c_buffer != NULL) {
|
|
129
|
+
xdb_free_content(test->c_buffer);
|
|
130
|
+
test->c_buffer = NULL;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
//read a line from a command line.
|
|
135
|
+
static char *get_line(FILE *fp, char *__dst) {
|
|
136
|
+
register int c;
|
|
137
|
+
register char *cs;
|
|
138
|
+
|
|
139
|
+
cs = __dst;
|
|
140
|
+
while ( ( c = getc( fp ) ) != EOF ) {
|
|
141
|
+
if ( c == '\n' ) break;
|
|
142
|
+
*cs++ = c;
|
|
143
|
+
}
|
|
144
|
+
*cs = '\0';
|
|
145
|
+
|
|
146
|
+
return ( c == EOF && cs == __dst ) ? NULL : __dst;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
void print_help(char *argv[]) {
|
|
150
|
+
printf("ip2region xdb searcher\n");
|
|
151
|
+
printf("%s [command] [command options]\n", argv[0]);
|
|
152
|
+
printf("Command: \n");
|
|
153
|
+
printf(" search search input test\n");
|
|
154
|
+
printf(" bench search bench test\n");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
void test_search(int argc, char *argv[]) {
|
|
158
|
+
int i, n, err;
|
|
159
|
+
|
|
160
|
+
// for args parse
|
|
161
|
+
char *r, key[33] = {'\0'}, val[256] = {'\0'};
|
|
162
|
+
char db_file[256] = {'\0'}, cache_policy[16] = {"vectorIndex"};
|
|
163
|
+
|
|
164
|
+
// for search
|
|
165
|
+
long s_time, c_time;
|
|
166
|
+
char line[512] = {'\0'};
|
|
167
|
+
|
|
168
|
+
// ip parse
|
|
169
|
+
xdb_version_t *version;
|
|
170
|
+
bytes_ip_t ip_bytes[16] = {'\0'};
|
|
171
|
+
|
|
172
|
+
searcher_test_t test;
|
|
173
|
+
|
|
174
|
+
for (i = 2; i < argc; i++) {
|
|
175
|
+
r = argv[i];
|
|
176
|
+
if (strlen(r) < 5) {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (r[0] != '-' || r[1] != '-') {
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (strchr(r, '=') == NULL) {
|
|
185
|
+
printf("missing = for args pair '%s'\n", r);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
n = sscanf(r+2, "%32[^=]=%255[^\n]", key, val);
|
|
190
|
+
if (n != 2) {
|
|
191
|
+
printf("invalid option flag `%s`\n", r);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// printf("key=%s, val=%s\n", key, val);
|
|
196
|
+
if (strcmp(key, "db") == 0) {
|
|
197
|
+
snprintf(db_file, sizeof(db_file), "%s", val);
|
|
198
|
+
} else if (strcmp(key, "cache-policy") == 0) {
|
|
199
|
+
memcpy(cache_policy, val, sizeof(cache_policy) - 1);
|
|
200
|
+
// snprintf(cache_policy, sizeof(cache_policy), "%s", val);
|
|
201
|
+
} else {
|
|
202
|
+
printf("undefined option `%s`\n", r);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (strlen(db_file) < 1) {
|
|
208
|
+
printf("%s search [command options]\n", argv[0]);
|
|
209
|
+
printf("options:\n");
|
|
210
|
+
printf(" --db string ip2region binary xdb file path\n");
|
|
211
|
+
printf(" --cache-policy string cache policy: file/vectorIndex/content\n");
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// init the win sock
|
|
216
|
+
err = xdb_init_winsock();
|
|
217
|
+
if (err != 0) {
|
|
218
|
+
printf("failed to init the winsock with errno=%d\n", err);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// printf("db_file=%s, cache_policy=%s\n", db_file, cache_policy);
|
|
223
|
+
err = init_searcher_test(&test, db_file, cache_policy);
|
|
224
|
+
if (err != 0) {
|
|
225
|
+
// init program will print the error reasons;
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
printf("ip2region xdb searcher test program\n"
|
|
230
|
+
"source xdb: %s (%s, %s)\n"
|
|
231
|
+
"type 'quit' to exit\n", db_file, xdb_get_version(&test.searcher)->name, cache_policy);
|
|
232
|
+
while ( 1 ) {
|
|
233
|
+
printf("ip2region>> ");
|
|
234
|
+
get_line(stdin, line);
|
|
235
|
+
if ( strlen(line) < 2 ) {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (strcasecmp( line, "quit") == 0 ) {
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
version = xdb_parse_ip(line, ip_bytes, sizeof(ip_bytes));
|
|
244
|
+
if (version == NULL) {
|
|
245
|
+
printf("invalid ip address `%s`\n", line);
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
s_time = xdb_now();
|
|
250
|
+
err = xdb_search(&test.searcher, ip_bytes, version->bytes, &test.region);
|
|
251
|
+
if (err != 0) {
|
|
252
|
+
printf("{err: %d, io_count: %d}\n", err, xdb_get_io_count(&test.searcher));
|
|
253
|
+
} else {
|
|
254
|
+
c_time = xdb_now() - s_time;
|
|
255
|
+
printf("{region: %s, io_count: %d, took: %ld μs}\n", test.region.value, xdb_get_io_count(&test.searcher), c_time);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// free the region
|
|
259
|
+
xdb_region_buffer_free(&test.region);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
destroy_searcher_test(&test);
|
|
263
|
+
xdb_clean_winsock();
|
|
264
|
+
printf("searcher test program exited, thanks for trying\n");
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
void test_bench(int argc, char *argv[]) {
|
|
268
|
+
int i, n, err;
|
|
269
|
+
char *r, key[33] = {'\0'}, val[256] = {'\0'};
|
|
270
|
+
char db_file[256] = {'\0'}, src_file[256] = {'\0'}, cache_policy[16] = {"vectorIndex"};
|
|
271
|
+
|
|
272
|
+
FILE *handle;
|
|
273
|
+
char line[1024] = {'\0'}, sip_str[INET6_ADDRSTRLEN+1] = {'\0'}, eip_str[INET6_ADDRSTRLEN+1] = {'\0'};
|
|
274
|
+
char src_region[512] = {'\0'};
|
|
275
|
+
int count = 0, took;
|
|
276
|
+
long s_time, t_time, c_time = 0;
|
|
277
|
+
|
|
278
|
+
// ip parse
|
|
279
|
+
xdb_version_t *s_version, *e_version;
|
|
280
|
+
bytes_ip_t sip_bytes[16] = {'\0'}, eip_bytes[16] = {'\0'};
|
|
281
|
+
string_ip_t ip_string[INET6_ADDRSTRLEN] = {'\0'};
|
|
282
|
+
bytes_ip_t *ip_list[2];
|
|
283
|
+
|
|
284
|
+
searcher_test_t test;
|
|
285
|
+
for (i = 2; i < argc; i++) {
|
|
286
|
+
r = argv[i];
|
|
287
|
+
if (strlen(r) < 5) {
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (r[0] != '-' || r[1] != '-') {
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (strchr(r, '=') == NULL) {
|
|
296
|
+
printf("missing = for args pair '%s'\n", r);
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
n = sscanf(r+2, "%32[^=]=%255[^\n]", key, val);
|
|
301
|
+
if (n != 2) {
|
|
302
|
+
printf("invalid option flag `%s`\n", r);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (strcmp(key, "db") == 0) {
|
|
307
|
+
snprintf(db_file, sizeof(db_file), "%s", val);
|
|
308
|
+
} else if (strcmp(key, "src") == 0) {
|
|
309
|
+
snprintf(src_file, sizeof(src_file), "%s", val);
|
|
310
|
+
} else if (strcmp(key, "cache-policy") == 0) {
|
|
311
|
+
memcpy(cache_policy, val, sizeof(cache_policy) - 1);
|
|
312
|
+
} else {
|
|
313
|
+
printf("undefined option `%s`\n", r);
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (strlen(db_file) < 1 || strlen(src_file) < 1) {
|
|
319
|
+
printf("%s bench [command options]\n", argv[0]);
|
|
320
|
+
printf("options:\n");
|
|
321
|
+
printf(" --db string ip2region binary xdb file path\n");
|
|
322
|
+
printf(" --src string source ip text file path\n");
|
|
323
|
+
printf(" --cache-policy string cache policy: file/vectorIndex/content\n");
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// init the win sock
|
|
328
|
+
err = xdb_init_winsock();
|
|
329
|
+
if (err != 0) {
|
|
330
|
+
printf("failed to init the winsock with errno=%d\n", err);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// printf("db_file=%s, src_file=%s, cache_policy=%s\n", db_file, src_file, cache_policy);
|
|
335
|
+
s_time = xdb_now();
|
|
336
|
+
err = init_searcher_test(&test, db_file, cache_policy);
|
|
337
|
+
if (err != 0) {
|
|
338
|
+
// the init function will print the details;
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// open the source file
|
|
343
|
+
handle = fopen(src_file, "r");
|
|
344
|
+
if (handle == NULL) {
|
|
345
|
+
printf("failed to open source text file `%s`\n", src_file);
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
while(fgets(line, sizeof(line), handle) != NULL) {
|
|
350
|
+
n = sscanf(line, "%46[^|]|%46[^|]|%511[^\n]", sip_str, eip_str, src_region);
|
|
351
|
+
if (n != 3) {
|
|
352
|
+
printf("invalid ip segment line `%s`\n", line);
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
s_version = xdb_parse_ip(sip_str, sip_bytes, sizeof(sip_bytes));
|
|
357
|
+
if (s_version == NULL) {
|
|
358
|
+
printf("invalid start ip `%s`\n", sip_str);
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
e_version = xdb_parse_ip(eip_str, eip_bytes, sizeof(eip_bytes));
|
|
363
|
+
if (e_version == NULL) {
|
|
364
|
+
printf("invalid end ip `%s`\n", sip_str);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (s_version->id != e_version->id) {
|
|
369
|
+
printf("start ip and end ip version not match for line `%s`\n", line);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (xdb_ip_sub_compare(sip_bytes, s_version->bytes, (string_ip_t *) eip_bytes, 0) > 0) {
|
|
374
|
+
printf("start ip(%s) should not be greater than end ip(%s)\n", sip_str, eip_str);
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
ip_list[0] = sip_bytes;
|
|
379
|
+
ip_list[1] = eip_bytes;
|
|
380
|
+
for (i = 0; i < 2; i++) {
|
|
381
|
+
t_time = xdb_now();
|
|
382
|
+
err = xdb_search(&test.searcher, ip_list[i], s_version->bytes, &test.region);
|
|
383
|
+
c_time += xdb_now() - t_time;
|
|
384
|
+
if (err != 0) {
|
|
385
|
+
xdb_ip_to_string(ip_list[i], s_version->bytes, ip_string, sizeof(ip_string));
|
|
386
|
+
printf("failed to search ip `%s` with errno=%d\n", ip_string, err);
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// check the region info
|
|
391
|
+
if (strcmp(test.region.value, src_region) != 0) {
|
|
392
|
+
xdb_ip_to_string(ip_list[i], s_version->bytes, ip_string, sizeof(ip_string));
|
|
393
|
+
printf("failed to search(%s) with (%s != %s)\n", ip_string, test.region.value, src_region);
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// free the region buffer
|
|
398
|
+
xdb_region_buffer_free(&test.region);
|
|
399
|
+
|
|
400
|
+
count++;
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
took = xdb_now() - s_time;
|
|
405
|
+
destroy_searcher_test(&test);
|
|
406
|
+
xdb_clean_winsock();
|
|
407
|
+
fclose(handle);
|
|
408
|
+
printf("Bench finished, {cache_policy: %s, total: %d, took: %.3fs, cost: %d μs/op}\n",
|
|
409
|
+
cache_policy, count, took/1e6, count == 0 ? 0 : (int)(c_time/count));
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
int main(int argc, char *argv[]) {
|
|
413
|
+
if (argc < 2) {
|
|
414
|
+
print_help(argv);
|
|
415
|
+
return 0;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
char *opt = argv[1];
|
|
419
|
+
if (strcmp(opt, "search") == 0) {
|
|
420
|
+
test_search(argc, argv);
|
|
421
|
+
} else if (strcmp(opt, "bench") == 0) {
|
|
422
|
+
test_bench(argc, argv);
|
|
423
|
+
} else {
|
|
424
|
+
print_help(argv);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return 0;
|
|
428
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// Copyright 2022 The Ip2Region Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a Apache2.0-style
|
|
3
|
+
// license that can be found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
// ---
|
|
6
|
+
// @Author Lion <chenxin619315@gmail.com>
|
|
7
|
+
// @Date 2022/06/27
|
|
8
|
+
|
|
9
|
+
#include "stdio.h"
|
|
10
|
+
#include "xdb_api.h"
|
|
11
|
+
|
|
12
|
+
typedef void (* test_func_ptr) ();
|
|
13
|
+
struct test_func_entry {
|
|
14
|
+
char *name;
|
|
15
|
+
test_func_ptr func;
|
|
16
|
+
};
|
|
17
|
+
typedef struct test_func_entry test_func_t;
|
|
18
|
+
|
|
19
|
+
void test_load_header() {
|
|
20
|
+
xdb_header_t *header = xdb_load_header_from_file("../data/ip2region_v4.xdb");
|
|
21
|
+
if (header == NULL) {
|
|
22
|
+
printf("failed to load header");
|
|
23
|
+
} else {
|
|
24
|
+
printf("header loaded: {\n"
|
|
25
|
+
" version: %d, \n"
|
|
26
|
+
" index_policy: %d, \n"
|
|
27
|
+
" created_at: %u, \n"
|
|
28
|
+
" start_index_ptr: %d, \n"
|
|
29
|
+
" end_index_ptr: %d\n"
|
|
30
|
+
" ip_version: %d\n"
|
|
31
|
+
" runtime_ptr_bytes: %d\n"
|
|
32
|
+
" length: %d\n"
|
|
33
|
+
"}\n",
|
|
34
|
+
header->version, header->index_policy, header->created_at,
|
|
35
|
+
header->start_index_ptr, header->end_index_ptr,
|
|
36
|
+
header->ip_version, header->runtime_ptr_bytes, header->length
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
xdb_free_header(header);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
void test_load_vector_index() {
|
|
44
|
+
xdb_vector_index_t *v_index = xdb_load_vector_index_from_file("../data/ip2region_v4.xdb");
|
|
45
|
+
if (v_index == NULL) {
|
|
46
|
+
printf("failed to load vector index from file\n");
|
|
47
|
+
} else {
|
|
48
|
+
printf("vector index loaded from file, length=%d\n", v_index->length);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
xdb_free_vector_index(v_index);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
void test_load_content() {
|
|
55
|
+
xdb_content_t *content = xdb_load_content_from_file("../data/ip2region_v4.xdb");
|
|
56
|
+
if (content == NULL) {
|
|
57
|
+
printf("failed to load content from file\n");
|
|
58
|
+
} else {
|
|
59
|
+
printf("content loaded from file, length=%d\n", content->length);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
xdb_free_content(content);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
void test_parse_ip() {
|
|
66
|
+
const char *ip_list[] = {
|
|
67
|
+
"1.0.0.0", "58.251.30.115", "192.168.1.100",
|
|
68
|
+
"::", "2c0f:fff0::", "2fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "240e:982:e617:ffff:ffff:ffff:ffff:ffff",
|
|
69
|
+
"219.xx.xx.11", "::xx:ffff",
|
|
70
|
+
NULL
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
int errcode;
|
|
74
|
+
xdb_version_t *version;
|
|
75
|
+
bytes_ip_t ip_bytes[16] = {'\0'};
|
|
76
|
+
string_ip_t ip_string[INET6_ADDRSTRLEN] = {'\0'};
|
|
77
|
+
|
|
78
|
+
// init the sock env (for windows)
|
|
79
|
+
if ((errcode = xdb_init_winsock()) != 0) {
|
|
80
|
+
printf("failed to init the winsock");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
for (int i = 0;; i++) {
|
|
85
|
+
if (ip_list[i] == NULL) {
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
version = xdb_parse_ip(ip_list[i], ip_bytes, sizeof(ip_bytes));
|
|
90
|
+
if (version == NULL) {
|
|
91
|
+
printf("failed to parse ip `%s`\n", ip_list[i]);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
xdb_ip_to_string(ip_bytes, version->bytes, ip_string, sizeof(ip_string));
|
|
96
|
+
printf("ip: %s (version=v%d), toString: %s\n", ip_list[i], version->id, ip_string);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// clean up the winsock
|
|
100
|
+
xdb_clean_winsock();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
struct ip_pair {
|
|
104
|
+
const char *sip;
|
|
105
|
+
const char *eip;
|
|
106
|
+
};
|
|
107
|
+
void test_ip_compare() {
|
|
108
|
+
struct ip_pair ip_pair_list[] = {
|
|
109
|
+
{"1.0.0.0", "1.0.0.1"},
|
|
110
|
+
{"192.168.1.101", "192.168.1.90"},
|
|
111
|
+
{"219.133.111.87", "114.114.114.114"},
|
|
112
|
+
{"1.0.4.0", "1.0.1.0"},
|
|
113
|
+
{"1.0.4.0", "1.0.3.255"},
|
|
114
|
+
{"2000::", "2000:ffff:ffff:ffff:ffff:ffff:ffff:ffff"},
|
|
115
|
+
{"2001:4:112::", "2001:4:112:ffff:ffff:ffff:ffff:ffff"},
|
|
116
|
+
{"ffff::", "2001:4:ffff:ffff:ffff:ffff:ffff:ffff"},
|
|
117
|
+
{NULL, NULL}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
struct ip_pair *pair_ptr = NULL;
|
|
121
|
+
bytes_ip_t sip_bytes[16] = {'\0'};
|
|
122
|
+
bytes_ip_t eip_bytes[16] = {'\0'};
|
|
123
|
+
xdb_version_t *s_version, *e_version;
|
|
124
|
+
int errcode;
|
|
125
|
+
|
|
126
|
+
// init the sock env (for windows)
|
|
127
|
+
if ((errcode = xdb_init_winsock()) != 0) {
|
|
128
|
+
printf("failed to init the winsock");
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
for (int i = 0; ;i++) {
|
|
133
|
+
pair_ptr = &ip_pair_list[i];
|
|
134
|
+
if (pair_ptr->sip == NULL) {
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
s_version = xdb_parse_ip(pair_ptr->sip, sip_bytes, sizeof(sip_bytes));
|
|
139
|
+
if (s_version == NULL) {
|
|
140
|
+
printf("failed to parse sip `%s`", pair_ptr->sip);
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
e_version = xdb_parse_ip(pair_ptr->eip, eip_bytes, sizeof(eip_bytes));
|
|
145
|
+
if (e_version == NULL) {
|
|
146
|
+
printf("failed to parse eip `%s`", pair_ptr->eip);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (s_version->id != e_version->id) {
|
|
151
|
+
printf("sip and eip version not match `%s` != `%s`\n", s_version->name, e_version->name);
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
printf(
|
|
156
|
+
"ip_sub_compare(%s, %s): %d\n",
|
|
157
|
+
pair_ptr->sip, pair_ptr->eip,
|
|
158
|
+
xdb_ip_sub_compare(sip_bytes, s_version->bytes, (string_ip_t *) eip_bytes, 0)
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// clean up the winsock
|
|
163
|
+
xdb_clean_winsock();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// please register your function heare
|
|
167
|
+
static test_func_t _test_function_list[] = {
|
|
168
|
+
// xdb buffer
|
|
169
|
+
{"test_load_header", test_load_header},
|
|
170
|
+
{"test_load_vector_index", test_load_vector_index},
|
|
171
|
+
{"test_load_content", test_load_content},
|
|
172
|
+
|
|
173
|
+
// ip utils
|
|
174
|
+
{"test_parse_ip", test_parse_ip},
|
|
175
|
+
{"test_ip_compare", test_ip_compare},
|
|
176
|
+
|
|
177
|
+
{NULL, NULL}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// valgrind --tool=memcheck --leak-check=full ./a.out
|
|
181
|
+
int main(int argc, char *argv[]) {
|
|
182
|
+
int i;
|
|
183
|
+
char *name;
|
|
184
|
+
|
|
185
|
+
// check and call the function
|
|
186
|
+
if (argc < 2) {
|
|
187
|
+
printf("please specified the function name to call\n");
|
|
188
|
+
return 1;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
name = argv[1];
|
|
192
|
+
test_func_ptr func = NULL;
|
|
193
|
+
for (i = 0; ; i++) {
|
|
194
|
+
if (_test_function_list[i].name == NULL) {
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (strcmp(name, _test_function_list[i].name) == 0) {
|
|
199
|
+
func = _test_function_list[i].func;
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (func == NULL) {
|
|
205
|
+
printf("can't find test function `%s`\n", name);
|
|
206
|
+
return 1;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// call the function
|
|
210
|
+
func();
|
|
211
|
+
|
|
212
|
+
return 0;
|
|
213
|
+
}
|