cmp = function (a, b) { if (typeof a === 'number' && typeof b === 'number') { return (a < b ? -1 : (a > b ? 1 : 0)); } if (a instanceof Array && b instanceof Array) { return this.cmp6(a, b); } return null; }
n/a
lookup = function (ip) { if (!ip) { return null; } else if (typeof ip === 'number') { return lookup4(ip); } else if (net.isIP(ip) === 4) { return lookup4(utils.aton4(ip)); } else if (net.isIP(ip) === 6) { var ipv4 = get4mapped(ip); if (ipv4) { return lookup4(utils.aton4(ipv4)); } else { return lookup6(utils.aton6(ip)); } } return null; }
...
synopsis
--------
```javascript
var geoip = require('geoip-lite');
var ip = "207.97.227.239";
var geo = geoip.lookup(ip);
console.log(geo);
{ range: [ 3479297920, 3479301339 ],
country: 'US',
region: 'TX',
city: 'San Antonio',
ll: [ 29.4889, -98.3987 ],
...
pretty = function (n) { if (typeof n === 'string') { return n; } else if (typeof n === 'number') { return utils.ntoa4(n); } else if (n instanceof Array) { return utils.ntoa6(n); } return n; }
...
ll: [<latitude>, <longitude>], // The latitude and longitude of the city
metro: <metro code>, // Metro code
zip: <postal code> // Postal code (IPv4 only)
}
```
The actual values for the `range` array depend on whether the IP is IPv4 or IPv6 and should be
considered internal to `geoip-lite`. To get a human readable format, pass them to `geoip.pretty
()`
If the IP address was not found, the `lookup` returns `null`
### Pretty printing an IP address ###
If you have a 32 bit unsigned integer, or a number returned as part of the `range` array from the `lookup` method,
the `pretty` method can be used to turn it into a human readable string.
...
startWatchingDataUpdate = function (callback) { fsWatcher.makeFsWatchFilter(watcherName, geodatadir, 60*1000, function () { //Reload data async.series([ function (cb) { preload(cb); }, function (cb) { preload6(cb); } ], callback); }); }
...
### Start and stop watching for data updates ###
If you have a server running `geoip-lite`, and you want to update its geo data without a restart, you can enable
the data watcher to automatically refresh in-memory geo data when a file changes in the data directory.
```javascript
geoip.startWatchingDataUpdate();
```
This tool can be used with `npm run-script updatedb` to periodically update geo data on a running server.
Built-in Updater
----------------
...
stopWatchingDataUpdate = function () { fsWatcher.stopWatching(watcherName); }
n/a
function makeFsWatchFilter(name, directory, filename, cooldownDelay, callback) { var cooldownId = null; //Delete the cooldownId and callback the outer function function timeoutCallback() { cooldownId = null; callback(); } //This function is called when there is a change in the data directory //It sets a timer to wait for the change to be completed function onWatchEvent(event, changedFile) { var filePath = path.join(directory, changedFile); if (!filename || filename === changedFile) { fs.exists(filePath, function onExists(exists) { if (!exists) { // if the changed file no longer exists, it was a deletion. // we ignore deleted files return; } //At this point, a new file system activity has been detected, //We have to wait for file transfert to be finished before moving on. //If a cooldownId already exists, we delete it if (cooldownId !== null) { clearTimeout(cooldownId); cooldownId = null; } //Once the cooldownDelay has passed, the timeoutCallback function will be called cooldownId = setTimeout(timeoutCallback, cooldownDelay); }); } } //Manage the case where filename is missing (because it's optionnal) if (typeof cooldownDelay === 'function') { callback = cooldownDelay; cooldownDelay = filename; filename = null; } if (FSWatcher[name]) { stopWatching(name); } FSWatcher[name] = fs.watch(directory, onWatchEvent); }
n/a
function stopWatching(name) { FSWatcher[name].close(); }
n/a
aton4 = function (a) { a = a.split(/\./); return ((parseInt(a[0], 10)<<24)>>>0) + ((parseInt(a[1], 10)<<16)>>>0) + ((parseInt(a[2], 10)<<8)>>>0) + (parseInt(a[3], 10)>>> 0); }
n/a
aton6 = function (a) { a = a.replace(/"/g, '').split(/:/); var l = a.length - 1; var i; if (a[l] === '') { a[l] = 0; } if (l < 7) { a.length = 8; for (i = l; i >= 0 && a[i] !== ''; i--) { a[7-l+i] = a[i]; } } for (i = 0; i < 8; i++) { if (!a[i]) { a[i]=0; } else { a[i] = parseInt(a[i], 16); } } var r = []; for (i = 0; i<4; i++) { r.push(((a[2*i]<<16) + a[2*i+1])>>>0); } return r; }
...
var b;
var bsz;
var i;
if (fields[0].match(/:/)) {
// IPv6
bsz = 34;
sip = utils.aton6(fields[0]);
eip = utils.aton6(fields[1]);
b = new Buffer(bsz);
for (i = 0; i < sip.length; i++) {
b.writeUInt32BE(sip[i], i * 4);
}
...
cmp = function (a, b) { if (typeof a === 'number' && typeof b === 'number') { return (a < b ? -1 : (a > b ? 1 : 0)); } if (a instanceof Array && b instanceof Array) { return this.cmp6(a, b); } return null; }
n/a
cmp6 = function (a, b) { for (var ii = 0; ii < 2; ii++) { if (a[ii] < b[ii]) { return -1; } if (a[ii] > b[ii]) { return 1; } } return 0; }
...
utils.cmp = function(a, b) {
if (typeof a === 'number' && typeof b === 'number') {
return (a < b ? -1 : (a > b ? 1 : 0));
}
if (a instanceof Array && b instanceof Array) {
return this.cmp6(a, b);
}
return null;
};
utils.cmp6 = function(a, b) {
for (var ii = 0; ii < 2; ii++) {
...
isPrivateIP = function (addr) { addr = addr.toString(); return addr.match(/^10\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/) != null || addr.match(/^192\.168\.([0-9]{1,3})\.([0-9]{1,3})/) != null || addr.match(/^172\.16\.([0-9]{1,3})\.([0-9]{1,3})/) != null || addr.match(/^127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/) != null || addr.match(/^169\.254\.([0-9]{1,3})\.([0-9]{1,3})/) != null || addr.match(/^fc00:/) != null || addr.match(/^fe80:/) != null; }
n/a
ntoa4 = function (n) { n = n.toString(); n = '' + (n>>>24&0xff) + '.' + (n>>>16&0xff) + '.' + (n>>>8&0xff) + '.' + (n&0xff); return n; }
n/a
ntoa6 = function (n) { var a = "["; for (var i = 0; i<n.length; i++) { a += (n[i]>>>16).toString(16) + ':'; a += (n[i]&0xffff).toString(16) + ':'; } a = a.replace(/:$/, ']').replace(/:0+/g, ':').replace(/::+/, '::'); return a; }
n/a