@@ -34,7 +34,7 @@ const privateRange4 = [
3434const conf4 = {
3535 firstIP : null ,
3636 lastIP : null ,
37- lastLine : 0 ,
37+ lastRecordIdx : 0 ,
3838 locationBuffer : null ,
3939 locationRecordSize : 88 ,
4040 mainBuffer : null ,
@@ -44,7 +44,7 @@ const conf4 = {
4444const conf6 = {
4545 firstIP : null ,
4646 lastIP : null ,
47- lastLine : 0 ,
47+ lastRecordIdx : 0 ,
4848 mainBuffer : null ,
4949 recordSize : 48 ,
5050} ;
@@ -56,8 +56,10 @@ const RECORD_SIZE = 10;
5656const RECORD_SIZE6 = 34 ;
5757
5858const lookup4 = ip => {
59+ if ( ! cache4 . mainBuffer ) return null ;
60+
5961 let fline = 0 ;
60- let cline = cache4 . lastLine ;
62+ let cline = cache4 . lastRecordIdx ;
6163 let floor ;
6264 let ceil ;
6365 let line , locId ;
@@ -68,12 +70,13 @@ const lookup4 = ip => {
6870 const recordSize = cache4 . recordSize ;
6971 const locRecordSize = cache4 . locationRecordSize ;
7072
71- const geoData = createGeoData ( ) ;
7273 if ( ip > cache4 . lastIP || ip < cache4 . firstIP ) return null ;
7374 for ( let i = 0 ; i < privateRange . length ; i ++ ) {
7475 if ( ip >= privateRange [ i ] [ 0 ] && ip <= privateRange [ i ] [ 1 ] ) return null ;
7576 }
7677
78+ const geoData = createGeoData ( ) ;
79+
7780 while ( true ) {
7881 line = Math . round ( ( cline - fline ) / 2 ) + fline ;
7982 const offset = line * recordSize ;
@@ -82,7 +85,7 @@ const lookup4 = ip => {
8285
8386 if ( floor <= ip && ceil >= ip ) {
8487 if ( recordSize === RECORD_SIZE ) {
85- geoData . country = buffer . toString ( 'utf8' , offset + 8 , offset + 10 ) ;
88+ geoData . country = removeNullTerminator ( buffer . toString ( 'utf8' , offset + 8 , offset + 10 ) ) ;
8689 } else {
8790 locId = buffer . readUInt32BE ( offset + 8 ) ;
8891 populateGeoDataFromLocation ( {
@@ -115,21 +118,23 @@ const lookup4 = ip => {
115118} ;
116119
117120const lookup6 = ip => {
121+ if ( ! cache6 . mainBuffer ) return null ;
122+
118123 const buffer = cache6 . mainBuffer ;
119124 const recordSize = cache6 . recordSize ;
120125 const locBuffer = cache4 . locationBuffer ;
121126 const locRecordSize = cache4 . locationRecordSize ;
122127
123- const geoData = createGeoData ( ) ;
124-
125128 let fline = 0 ;
126- let cline = cache6 . lastLine ;
129+ let cline = cache6 . lastRecordIdx ;
127130 let floor ;
128131 let ceil ;
129132 let line , locId ;
130133
131134 if ( cmp6 ( ip , cache6 . lastIP ) > 0 || cmp6 ( ip , cache6 . firstIP ) < 0 ) return null ;
132135
136+ const geoData = createGeoData ( ) ;
137+
133138 while ( true ) {
134139 line = Math . round ( ( cline - fline ) / 2 ) + fline ;
135140 floor = readIp6 ( buffer , line , recordSize , 0 ) ;
@@ -179,17 +184,8 @@ const get4mapped = ip => {
179184} ;
180185
181186const readFileBuffer = async filePath => {
182- const fileHandle = await fsPromises . open ( filePath , 'r' ) ;
183- try {
184- const { size } = await fileHandle . stat ( ) ;
185- const buffer = Buffer . alloc ( size ) ;
186- if ( size > 0 ) {
187- await fileHandle . read ( buffer , 0 , size , 0 ) ;
188- }
189- return { buffer, size } ;
190- } finally {
191- await fileHandle . close ( ) ;
192- }
187+ const buffer = await fsPromises . readFile ( filePath ) ;
188+ return { buffer, size : buffer . length } ;
193189} ;
194190
195191const isExpectedMissingDataError = err => err ?. code === 'ENOENT' || err ?. code === 'EBADF' ;
@@ -210,13 +206,14 @@ const preloadAsync = async () => {
210206 mainData = await readFileBuffer ( dataFiles . city ) ;
211207 } catch ( err ) {
212208 if ( ! isExpectedMissingDataError ( err ) ) throw err ;
209+ asyncCache . locationBuffer = null ;
213210 mainData = await readFileBuffer ( dataFiles . country ) ;
214211 asyncCache . recordSize = RECORD_SIZE ;
215212 }
216213
217214 asyncCache . mainBuffer = mainData . buffer ;
218- asyncCache . lastLine = ( mainData . size / asyncCache . recordSize ) - 1 ;
219- asyncCache . lastIP = asyncCache . mainBuffer . readUInt32BE ( ( asyncCache . lastLine * asyncCache . recordSize ) + 4 ) ;
215+ asyncCache . lastRecordIdx = ( mainData . size / asyncCache . recordSize ) - 1 ;
216+ asyncCache . lastIP = asyncCache . mainBuffer . readUInt32BE ( ( asyncCache . lastRecordIdx * asyncCache . recordSize ) + 4 ) ;
220217 asyncCache . firstIP = asyncCache . mainBuffer . readUInt32BE ( 0 ) ;
221218 cache4 = asyncCache ;
222219} ;
@@ -248,6 +245,7 @@ const preload = callback => {
248245 throw err ;
249246 }
250247
248+ cache4 . locationBuffer = null ;
251249 datFile = openSync ( dataFiles . country , 'r' ) ;
252250 datSize = fstatSync ( datFile ) . size ;
253251 cache4 . recordSize = RECORD_SIZE ;
@@ -257,8 +255,8 @@ const preload = callback => {
257255 readSync ( datFile , cache4 . mainBuffer , 0 , datSize , 0 ) ;
258256 closeSync ( datFile ) ;
259257
260- cache4 . lastLine = ( datSize / cache4 . recordSize ) - 1 ;
261- cache4 . lastIP = cache4 . mainBuffer . readUInt32BE ( ( cache4 . lastLine * cache4 . recordSize ) + 4 ) ;
258+ cache4 . lastRecordIdx = ( datSize / cache4 . recordSize ) - 1 ;
259+ cache4 . lastIP = cache4 . mainBuffer . readUInt32BE ( ( cache4 . lastRecordIdx * cache4 . recordSize ) + 4 ) ;
262260 cache4 . firstIP = cache4 . mainBuffer . readUInt32BE ( 0 ) ;
263261 }
264262} ;
@@ -283,8 +281,8 @@ const preload6Async = async () => {
283281 }
284282
285283 asyncCache6 . mainBuffer = mainData . buffer ;
286- asyncCache6 . lastLine = ( mainData . size / asyncCache6 . recordSize ) - 1 ;
287- asyncCache6 . lastIP = readIp6 ( asyncCache6 . mainBuffer , asyncCache6 . lastLine , asyncCache6 . recordSize , 1 ) ;
284+ asyncCache6 . lastRecordIdx = ( mainData . size / asyncCache6 . recordSize ) - 1 ;
285+ asyncCache6 . lastIP = readIp6 ( asyncCache6 . mainBuffer , asyncCache6 . lastRecordIdx , asyncCache6 . recordSize , 1 ) ;
288286 asyncCache6 . firstIP = readIp6 ( asyncCache6 . mainBuffer , 0 , asyncCache6 . recordSize , 0 ) ;
289287 cache6 = asyncCache6 ;
290288} ;
@@ -319,23 +317,25 @@ const preload6 = callback => {
319317 readSync ( datFile , cache6 . mainBuffer , 0 , datSize , 0 ) ;
320318 closeSync ( datFile ) ;
321319
322- cache6 . lastLine = ( datSize / cache6 . recordSize ) - 1 ;
323- cache6 . lastIP = readIp6 ( cache6 . mainBuffer , cache6 . lastLine , cache6 . recordSize , 1 ) ;
320+ cache6 . lastRecordIdx = ( datSize / cache6 . recordSize ) - 1 ;
321+ cache6 . lastIP = readIp6 ( cache6 . mainBuffer , cache6 . lastRecordIdx , cache6 . recordSize , 1 ) ;
324322 cache6 . firstIP = readIp6 ( cache6 . mainBuffer , 0 , cache6 . recordSize , 0 ) ;
325323 }
326324} ;
327325
328326const runAsyncReload = callback => {
329- preloadAsync ( )
330- . then ( ( ) => preload6Async ( ) )
327+ Promise . all ( [ preloadAsync ( ) , preload6Async ( ) ] )
331328 . then ( ( ) => callback ( ) )
332329 . catch ( callback ) ;
333330} ;
334331
335332module . exports = {
336333 lookup : ip => {
337334 if ( ip === undefined || ip === null ) throw new TypeError ( 'lookup(ip) requires an IP address' ) ;
338- if ( typeof ip === 'number' ) return lookup4 ( ip ) ;
335+ if ( typeof ip === 'number' ) {
336+ if ( ! Number . isFinite ( ip ) || ! Number . isInteger ( ip ) || ip < 0 ) return null ;
337+ return lookup4 ( ip ) ;
338+ }
339339
340340 const ipVersion = isIP ( ip ) ;
341341 if ( ipVersion === 4 ) {
@@ -394,4 +394,3 @@ module.exports = {
394394
395395preload ( ) ;
396396preload6 ( ) ;
397-
0 commit comments