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
|
@@ -0,0 +1,496 @@
|
|
|
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 "xdb_api.h"
|
|
10
|
+
#include <ctype.h>
|
|
11
|
+
|
|
12
|
+
// for Linux
|
|
13
|
+
#ifdef XDB_LINUX
|
|
14
|
+
#include "sys/time.h"
|
|
15
|
+
#endif
|
|
16
|
+
|
|
17
|
+
#ifdef XDB_WINDOWS
|
|
18
|
+
#include <time.h>
|
|
19
|
+
#endif
|
|
20
|
+
|
|
21
|
+
// @Note: since 2023/10/13 to compatible with the windows system
|
|
22
|
+
#ifdef XDB_WINDOWS
|
|
23
|
+
static int winsock_initialized = 0;
|
|
24
|
+
XDB_PUBLIC(int) xdb_init_winsock() {
|
|
25
|
+
if (winsock_initialized == 1) {
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
WSADATA wsaData;
|
|
30
|
+
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
|
|
31
|
+
return -1;
|
|
32
|
+
}
|
|
33
|
+
winsock_initialized = 1;
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
XDB_PUBLIC(void) xdb_clean_winsock() {
|
|
38
|
+
if (winsock_initialized == 1) {
|
|
39
|
+
WSACleanup();
|
|
40
|
+
winsock_initialized = 0;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
XDB_PRIVATE(int) gettimeofday(struct timeval* tp, void* tzp) {
|
|
45
|
+
time_t clock;
|
|
46
|
+
struct tm tm;
|
|
47
|
+
SYSTEMTIME wtm;
|
|
48
|
+
GetLocalTime(&wtm);
|
|
49
|
+
tm.tm_year = wtm.wYear - 1900;
|
|
50
|
+
tm.tm_mon = wtm.wMonth - 1;
|
|
51
|
+
tm.tm_mday = wtm.wDay;
|
|
52
|
+
tm.tm_hour = wtm.wHour;
|
|
53
|
+
tm.tm_min = wtm.wMinute;
|
|
54
|
+
tm.tm_sec = wtm.wSecond;
|
|
55
|
+
tm.tm_isdst = -1;
|
|
56
|
+
clock = mktime(&tm);
|
|
57
|
+
tp->tv_sec = clock;
|
|
58
|
+
tp->tv_usec = wtm.wMilliseconds * 1000;
|
|
59
|
+
return (0);
|
|
60
|
+
}
|
|
61
|
+
#else
|
|
62
|
+
XDB_PUBLIC(int) xdb_init_winsock() {return 0;}
|
|
63
|
+
XDB_PUBLIC(void) xdb_clean_winsock() {}
|
|
64
|
+
#endif
|
|
65
|
+
|
|
66
|
+
// --- xdb buffer function implementations
|
|
67
|
+
|
|
68
|
+
XDB_PUBLIC(xdb_header_t *) xdb_load_header(FILE *handle) {
|
|
69
|
+
xdb_header_t *header;
|
|
70
|
+
unsigned int size = xdb_header_info_length;
|
|
71
|
+
|
|
72
|
+
// entry alloc
|
|
73
|
+
header = (xdb_header_t *) xdb_malloc(sizeof(xdb_header_t));
|
|
74
|
+
if (header == NULL) {
|
|
75
|
+
return NULL;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (fseek(handle, 0, SEEK_SET) == -1) {
|
|
79
|
+
xdb_free(header);
|
|
80
|
+
return NULL;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (fread(header->buffer, 1,size, handle) != size) {
|
|
84
|
+
xdb_free(header);
|
|
85
|
+
return NULL;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// fill the fields
|
|
89
|
+
header->length = size;
|
|
90
|
+
header->version = (unsigned short) xdb_le_get_uint16(header->buffer, 0);
|
|
91
|
+
header->index_policy = (unsigned short) xdb_le_get_uint16(header->buffer, 2);
|
|
92
|
+
header->created_at = xdb_le_get_uint32(header->buffer, 4);
|
|
93
|
+
header->start_index_ptr = xdb_le_get_uint32(header->buffer, 8);
|
|
94
|
+
header->end_index_ptr = xdb_le_get_uint32(header->buffer,12);
|
|
95
|
+
|
|
96
|
+
// since IPv6 supporting
|
|
97
|
+
header->ip_version = xdb_le_get_uint16(header->buffer, 16);
|
|
98
|
+
header->runtime_ptr_bytes = xdb_le_get_uint16(header->buffer, 18);
|
|
99
|
+
|
|
100
|
+
return header;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
XDB_PUBLIC(xdb_header_t *) xdb_load_header_from_file(const char *db_path) {
|
|
104
|
+
xdb_header_t *header;
|
|
105
|
+
FILE *handle = fopen(db_path, "rb");
|
|
106
|
+
if (handle == NULL) {
|
|
107
|
+
return NULL;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
header = xdb_load_header(handle);
|
|
111
|
+
fclose(handle);
|
|
112
|
+
return header;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
XDB_PUBLIC(void) xdb_free_header(void *ptr) {
|
|
116
|
+
xdb_header_t *header = (xdb_header_t *) ptr;
|
|
117
|
+
if (header->length > 0) {
|
|
118
|
+
header->length = 0;
|
|
119
|
+
xdb_free(header);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// --- vector index
|
|
124
|
+
|
|
125
|
+
XDB_PUBLIC(xdb_vector_index_t *) xdb_load_vector_index(FILE *handle) {
|
|
126
|
+
xdb_vector_index_t *v_index;
|
|
127
|
+
unsigned int size = xdb_vector_index_length;
|
|
128
|
+
|
|
129
|
+
// seek to the vector index offset
|
|
130
|
+
if (fseek(handle, xdb_header_info_length, SEEK_SET) == -1) {
|
|
131
|
+
return NULL;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// do the buffer read
|
|
135
|
+
v_index = (xdb_vector_index_t *) xdb_malloc(sizeof(xdb_vector_index_t));
|
|
136
|
+
if (v_index == NULL) {
|
|
137
|
+
return NULL;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
v_index->length = size;
|
|
141
|
+
if (fread(v_index->buffer, 1, size, handle) != size) {
|
|
142
|
+
xdb_free(v_index);
|
|
143
|
+
return NULL;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return v_index;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
XDB_PUBLIC(xdb_vector_index_t *) xdb_load_vector_index_from_file(const char *db_path) {
|
|
150
|
+
xdb_vector_index_t *v_index;
|
|
151
|
+
FILE *handle = fopen(db_path, "rb");
|
|
152
|
+
if (handle == NULL) {
|
|
153
|
+
return NULL;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
v_index = xdb_load_vector_index(handle);
|
|
157
|
+
fclose(handle);
|
|
158
|
+
return v_index;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
XDB_PUBLIC(void) xdb_free_vector_index(void *ptr) {
|
|
162
|
+
xdb_vector_index_t *v_index = (xdb_vector_index_t *) ptr;
|
|
163
|
+
if (v_index->length > 0) {
|
|
164
|
+
v_index->length = 0;
|
|
165
|
+
xdb_free(v_index);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// --- content buffer
|
|
170
|
+
|
|
171
|
+
XDB_PUBLIC(xdb_content_t *) xdb_load_content(FILE *handle) {
|
|
172
|
+
unsigned int size;
|
|
173
|
+
xdb_content_t *content;
|
|
174
|
+
|
|
175
|
+
// determine the file size
|
|
176
|
+
if (fseek(handle, 0, SEEK_END) == -1) {
|
|
177
|
+
return NULL;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
size = (unsigned int) ftell(handle);
|
|
181
|
+
if (fseek(handle, 0, SEEK_SET) == -1) {
|
|
182
|
+
return NULL;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// do the file read
|
|
186
|
+
content = (xdb_content_t *) xdb_malloc(sizeof(xdb_content_t));
|
|
187
|
+
if (content == NULL) {
|
|
188
|
+
return NULL;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// do the buffer alloc
|
|
192
|
+
content->buffer = (char *) xdb_malloc(size);
|
|
193
|
+
if (content->buffer == NULL) {
|
|
194
|
+
xdb_free(content);
|
|
195
|
+
return NULL;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// read the content into the buffer
|
|
199
|
+
content->length = size;
|
|
200
|
+
if (fread(content->buffer, 1, size, handle) != size) {
|
|
201
|
+
xdb_free(content);
|
|
202
|
+
return NULL;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return content;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
XDB_PUBLIC(xdb_content_t *) xdb_load_content_from_file(const char *db_path) {
|
|
209
|
+
xdb_content_t *content;
|
|
210
|
+
FILE *handle = fopen(db_path, "rb");
|
|
211
|
+
if (handle == NULL) {
|
|
212
|
+
return NULL;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
content = xdb_load_content(handle);
|
|
216
|
+
fclose(handle);
|
|
217
|
+
return content;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
XDB_PUBLIC(void) xdb_free_content(void *ptr) {
|
|
221
|
+
xdb_content_t *content = (xdb_content_t *) ptr;
|
|
222
|
+
if (content->length > 0) {
|
|
223
|
+
content->length = 0;
|
|
224
|
+
xdb_free(content->buffer);
|
|
225
|
+
content->buffer = NULL;
|
|
226
|
+
xdb_free(content);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
XDB_PUBLIC(int) xdb_verify_from_header(FILE *handle, xdb_header_t *header) {
|
|
231
|
+
int runtime_ptr_bytes = 0; // runtime ptr bytes
|
|
232
|
+
if (header->version == xdb_structure_20) {
|
|
233
|
+
runtime_ptr_bytes = 4;
|
|
234
|
+
} else if (header->version == xdb_structure_30) {
|
|
235
|
+
runtime_ptr_bytes = header->runtime_ptr_bytes;
|
|
236
|
+
} else {
|
|
237
|
+
return 2;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// 1, confirm the xdb file size.
|
|
241
|
+
// to ensure that the maximum file pointer does not overflow.
|
|
242
|
+
int err = fseek(handle, 0L, SEEK_END);
|
|
243
|
+
if (err != 0) {
|
|
244
|
+
return 3;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
long int fileBytes = ftell(handle);
|
|
248
|
+
long int maxFilePtr = (1L << (runtime_ptr_bytes * 8)) - 1;
|
|
249
|
+
// printf("fileBytes: %ld, maxFilePtr: %ld\n", fileBytes, maxFilePtr);
|
|
250
|
+
if (fileBytes > maxFilePtr) {
|
|
251
|
+
return 4;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return 0;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
XDB_PUBLIC(int) xdb_verify(FILE *handle) {
|
|
258
|
+
xdb_header_t *header = xdb_load_header(handle);
|
|
259
|
+
if (header == NULL) {
|
|
260
|
+
return 1;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
int errcode = xdb_verify_from_header(handle, header);
|
|
264
|
+
if (errcode != 0) {
|
|
265
|
+
goto done;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// what next ?
|
|
269
|
+
done:
|
|
270
|
+
xdb_free_header(header);
|
|
271
|
+
return errcode;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
XDB_PUBLIC(int) xdb_verify_from_file(const char *db_path) {
|
|
275
|
+
FILE *handle = fopen(db_path, "rb");
|
|
276
|
+
if (handle == NULL) {
|
|
277
|
+
return -1;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
int r = xdb_verify(handle);
|
|
281
|
+
fclose(handle);
|
|
282
|
+
return r;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// --- End content buffer
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
// --- ip version
|
|
289
|
+
|
|
290
|
+
// ip compare for IPv4
|
|
291
|
+
// ip1 - with Big endian byte order parsed from an input
|
|
292
|
+
// ip2 - with Little endian byte order read from the xdb index.
|
|
293
|
+
// to compatiable with the Little Endian encoded IPv4 on xdb 2.0.
|
|
294
|
+
XDB_PRIVATE(int) _ipv4_sub_compare(const bytes_ip_t *ip_bytes, int bytes, const char *buffer, int offset) {
|
|
295
|
+
register int i0, i1;
|
|
296
|
+
for (int i = 0, j = offset + bytes - 1; i < bytes; i++, j--) {
|
|
297
|
+
i0 = ip_bytes[i];
|
|
298
|
+
i1 = buffer[j] & 0xFF;
|
|
299
|
+
if (i0 > i1) {
|
|
300
|
+
return 1;
|
|
301
|
+
} else if (i0 < i1) {
|
|
302
|
+
return -1;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return 0;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
static xdb_version_t _ip_version_list[] = {
|
|
309
|
+
// 14 = 4 + 4 + 2 + 4
|
|
310
|
+
{xdb_ipv4_id, "IPv4", xdb_ipv4_bytes, xdb_v4_index_size, _ipv4_sub_compare},
|
|
311
|
+
|
|
312
|
+
// 38 = 16 + 16 + 2 + 4
|
|
313
|
+
{xdb_ipv6_id, "IPv6", xdb_ipv6_bytes, xdb_v6_index_size, xdb_ip_sub_compare},
|
|
314
|
+
|
|
315
|
+
// END
|
|
316
|
+
{0, NULL, 0, 0, NULL}
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
XDB_PUBLIC(xdb_version_t *) xdb_version_v4() {
|
|
320
|
+
return &_ip_version_list[0];
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
XDB_PUBLIC(xdb_version_t *) xdb_version_v6() {
|
|
324
|
+
return &_ip_version_list[1];
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
XDB_PUBLIC(int) xdb_version_is_v4(const xdb_version_t *version) {
|
|
328
|
+
return version->id == xdb_ipv4_id;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
XDB_PUBLIC(int) xdb_version_is_v6(const xdb_version_t *version) {
|
|
332
|
+
return version->id == xdb_ipv6_id;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
XDB_PUBLIC(xdb_version_t *) xdb_version_from_name(char *name) {
|
|
336
|
+
// to upper case the name
|
|
337
|
+
for (int i = 0; name[i] != '\0'; i++) {
|
|
338
|
+
name[i] = toupper((unsigned char) name[i]);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (strcmp(name, "V4") == 0 || strcmp(name, "IPV4") == 0) {
|
|
342
|
+
return xdb_version_v4();
|
|
343
|
+
} else if (strcmp(name, "V6") == 0 || strcmp(name, "IPV6") == 0) {
|
|
344
|
+
return xdb_version_v6();
|
|
345
|
+
} else {
|
|
346
|
+
return NULL;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
XDB_PUBLIC(xdb_version_t *) xdb_version_from_header(xdb_header_t *header) {
|
|
351
|
+
// Old structure with ONLY IPv4 supports
|
|
352
|
+
if (header->version == xdb_structure_20) {
|
|
353
|
+
return xdb_version_v4();
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// structure 3.0 with IPv6 supporting
|
|
357
|
+
if (header->version != xdb_structure_30) {
|
|
358
|
+
return NULL;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (header->ip_version == xdb_ipv4_id) {
|
|
362
|
+
return xdb_version_v4();
|
|
363
|
+
} else if (header->ip_version == xdb_ipv6_id) {
|
|
364
|
+
return xdb_version_v6();
|
|
365
|
+
} else {
|
|
366
|
+
return NULL;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// --- END ip version
|
|
371
|
+
|
|
372
|
+
XDB_PUBLIC(long) xdb_now() {
|
|
373
|
+
struct timeval c_time;
|
|
374
|
+
gettimeofday(&c_time, NULL);
|
|
375
|
+
return c_time.tv_sec * (int)1e6 + c_time.tv_usec;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
XDB_PUBLIC(unsigned int) xdb_le_get_uint32(const char *buffer, int offset) {
|
|
379
|
+
return (
|
|
380
|
+
((buffer[offset ]) & 0x000000FF) |
|
|
381
|
+
((buffer[offset+1] << 8) & 0x0000FF00) |
|
|
382
|
+
((buffer[offset+2] << 16) & 0x00FF0000) |
|
|
383
|
+
((buffer[offset+3] << 24) & 0xFF000000)
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
XDB_PUBLIC(int) xdb_le_get_uint16(const char *buffer, int offset) {
|
|
388
|
+
return (
|
|
389
|
+
((buffer[offset ]) & 0x000000FF) |
|
|
390
|
+
((buffer[offset+1] << 8) & 0x0000FF00)
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
XDB_PUBLIC(xdb_version_t *) xdb_parse_ip(const string_ip_t *ip_string, bytes_ip_t *buffer, size_t length) {
|
|
395
|
+
// version check
|
|
396
|
+
if (strchr(ip_string, '.') != NULL && strchr(ip_string, ':') == NULL) {
|
|
397
|
+
return xdb_parse_v4_ip(ip_string, buffer, length);
|
|
398
|
+
} else if (strchr(ip_string, ':') != NULL) {
|
|
399
|
+
return xdb_parse_v6_ip(ip_string, buffer, length);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
return NULL;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
XDB_PUBLIC(xdb_version_t *) xdb_parse_v4_ip(const string_ip_t *ip_string, bytes_ip_t *buffer, size_t length) {
|
|
406
|
+
struct in_addr addr;
|
|
407
|
+
|
|
408
|
+
// buffer length checking
|
|
409
|
+
if (length < xdb_ipv4_bytes) {
|
|
410
|
+
return NULL;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (inet_pton(AF_INET, ip_string, &addr) != 1) {
|
|
414
|
+
return NULL;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// encode the address to buffer with big endian byte bufffer.
|
|
418
|
+
buffer[0] = (addr.s_addr) & 0xFF;
|
|
419
|
+
buffer[1] = (addr.s_addr >> 8) & 0xFF;
|
|
420
|
+
buffer[2] = (addr.s_addr >> 16) & 0xFF;
|
|
421
|
+
buffer[3] = (addr.s_addr >> 24) & 0xFF;
|
|
422
|
+
return XDB_IPv4;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
XDB_PUBLIC(xdb_version_t *) xdb_parse_v6_ip(const string_ip_t *ip_string, bytes_ip_t *buffer, size_t length) {
|
|
426
|
+
struct in6_addr addr;
|
|
427
|
+
|
|
428
|
+
// buffer length checking
|
|
429
|
+
if (length < xdb_ipv6_bytes) {
|
|
430
|
+
return NULL;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
if (inet_pton(AF_INET6, ip_string, &addr) != 1) {
|
|
434
|
+
return NULL;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
memcpy(buffer, addr.s6_addr, xdb_ipv6_bytes);
|
|
438
|
+
return XDB_IPv6;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
XDB_PUBLIC(int) xdb_ip_to_string(const bytes_ip_t *ip_bytes, int bytes, char *ip_string, size_t length) {
|
|
442
|
+
if (bytes == xdb_ipv4_bytes) {
|
|
443
|
+
return xdb_v4_ip_to_string(ip_bytes, ip_string, length);
|
|
444
|
+
} else if (bytes == xdb_ipv6_bytes) {
|
|
445
|
+
return xdb_v6_ip_to_string(ip_bytes, ip_string, length);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return -1;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
XDB_PUBLIC(int) xdb_v4_ip_to_string(const bytes_ip_t *ip_bytes, char *ip_string, size_t length) {
|
|
452
|
+
if (!ip_bytes || !ip_string || length == 0) {
|
|
453
|
+
return -1;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// buffer length checking
|
|
457
|
+
if (length < INET_ADDRSTRLEN) {
|
|
458
|
+
return -1;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (inet_ntop(AF_INET, ip_bytes, ip_string, length) == NULL) {
|
|
462
|
+
return -1;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return 0;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
XDB_PUBLIC(int) xdb_v6_ip_to_string(const bytes_ip_t *ip_bytes, char *ip_string, size_t length) {
|
|
469
|
+
if (!ip_bytes || !ip_string || length == 0) {
|
|
470
|
+
return -1;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
if (length < INET6_ADDRSTRLEN) {
|
|
474
|
+
return -1;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
if (inet_ntop(AF_INET6, ip_bytes, ip_string, length) == NULL) {
|
|
478
|
+
return -1;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
return 0;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
XDB_PUBLIC(int) xdb_ip_sub_compare(const bytes_ip_t *ip1, int bytes, const char *buffer, int offset) {
|
|
485
|
+
register int i, i1, i2;
|
|
486
|
+
for (i = 0; i < bytes; i++) {
|
|
487
|
+
i1 = ip1[i];
|
|
488
|
+
i2 = buffer[offset + i] & 0xFF;
|
|
489
|
+
if (i1 > i2) {
|
|
490
|
+
return 1;
|
|
491
|
+
} else if (i1 < i2) {
|
|
492
|
+
return -1;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return 0;
|
|
496
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ts-ip2region2",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "TypeScript-first ip2region implementation with native Node.js addon. Ultra-fast IPv4/IPv6 geolocation queries.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "node-gyp rebuild",
|
|
9
|
+
"compile": "tsc",
|
|
10
|
+
"build:all": "npm run build && npm run compile",
|
|
11
|
+
"rebuild": "node-gyp rebuild",
|
|
12
|
+
"clean": "node-gyp clean",
|
|
13
|
+
"test": "npm run build:all && node test.js",
|
|
14
|
+
"example": "npm run build:all && node example.js",
|
|
15
|
+
"prepublishOnly": "npm run build:all",
|
|
16
|
+
"semantic-release": "semantic-release"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"typescript",
|
|
20
|
+
"ip2region",
|
|
21
|
+
"geolocation",
|
|
22
|
+
"ipv4",
|
|
23
|
+
"ipv6",
|
|
24
|
+
"native-addon",
|
|
25
|
+
"high-performance",
|
|
26
|
+
"xdb",
|
|
27
|
+
"ip-lookup"
|
|
28
|
+
],
|
|
29
|
+
"author": "Steven Qiang <git@qiangmou.ren>",
|
|
30
|
+
"license": "Apache-2.0",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/Steven-Qiang/ts-ip2region2.git"
|
|
34
|
+
},
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/Steven-Qiang/ts-ip2region2/issues"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/Steven-Qiang/ts-ip2region2#readme",
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"node-addon-api": "^7.0.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^20.19.19",
|
|
44
|
+
"node-gyp": "^10.0.0",
|
|
45
|
+
"typescript": "^5.9.3",
|
|
46
|
+
"semantic-release": "^22.0.0",
|
|
47
|
+
"@semantic-release/changelog": "^6.0.0",
|
|
48
|
+
"@semantic-release/commit-analyzer": "^11.0.0",
|
|
49
|
+
"@semantic-release/git": "^10.0.0",
|
|
50
|
+
"@semantic-release/github": "^9.0.0",
|
|
51
|
+
"@semantic-release/npm": "^11.0.0",
|
|
52
|
+
"@semantic-release/release-notes-generator": "^12.0.0"
|
|
53
|
+
},
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=16.0.0"
|
|
56
|
+
},
|
|
57
|
+
"os": [
|
|
58
|
+
"darwin",
|
|
59
|
+
"linux",
|
|
60
|
+
"win32"
|
|
61
|
+
],
|
|
62
|
+
"cpu": [
|
|
63
|
+
"x64",
|
|
64
|
+
"arm64"
|
|
65
|
+
],
|
|
66
|
+
"files": [
|
|
67
|
+
"dist/**/*",
|
|
68
|
+
"addon.cpp",
|
|
69
|
+
"ip2region/**/*",
|
|
70
|
+
"binding.gyp",
|
|
71
|
+
"README.md",
|
|
72
|
+
"README_CN.md"
|
|
73
|
+
],
|
|
74
|
+
"gypfile": true,
|
|
75
|
+
"publishConfig": {
|
|
76
|
+
"access": "public"
|
|
77
|
+
}
|
|
78
|
+
}
|