Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Initial commit.
- Loading branch information
0 parents
commit e52b6cf
Showing
6 changed files
with
283 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
build/* | ||
lib/ceoip.node |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
var sys = require('sys'), | ||
ceoip = require('../lib/ceoip'); | ||
|
||
con = new ceoip.Connection(); | ||
con.addListener('connected', function () { | ||
con.addListener('result', function(result) { | ||
for (var attr in result) { | ||
sys.puts(attr + ' : ' + result[attr]); | ||
} | ||
}); | ||
con.query('216.236.135.152'); | ||
}); | ||
con.connect('/usr/local/share/GeoIP/GeoLiteCity.dat'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
var sys = require('sys'), | ||
geoip = require('../lib/geoip'); | ||
|
||
con = new geoip.Connection('/usr/local/share/GeoIP/GeoLiteCity.dat'); | ||
|
||
con.query('216.236.135.152').addCallback(function (result) { | ||
for (var attr in result) { | ||
sys.puts(attr + ' : ' + result[attr]); | ||
} | ||
}); | ||
|
||
con.close(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
var sys = require('sys'), | ||
ceoip = require('./ceoip'); | ||
|
||
function Connection(dbpath) { | ||
this.con = new ceoip.Connection(); | ||
this.queue = []; | ||
this.connected = false; | ||
this.currentQuery = null; | ||
|
||
var self = this; | ||
|
||
this.con.addListener('closed', function() { | ||
self.connected = false; | ||
self.emit('closed'); | ||
}); | ||
|
||
this.con.addListener('connected', function() { | ||
self.connected = true; | ||
self.processQueue(); | ||
}); | ||
|
||
this.con.addListener('result', function(result) { | ||
self.currentQuery[0].emitSuccess(result); | ||
self.currentQuery = null; | ||
self.processQueue(); | ||
}); | ||
|
||
this.con.connect(dbpath); | ||
} | ||
|
||
sys.inherits(Connection, process.EventEmitter); | ||
|
||
Connection.prototype.addJob = function(promise, ipAddress) { | ||
this.queue.push([promise, ipAddress]); | ||
this.processQueue(); | ||
}; | ||
|
||
Connection.prototype.query = function(ipAddress) { | ||
var promise = new process.Promise; | ||
this.addJob(promise, ipAddress); | ||
return promise; | ||
}; | ||
|
||
Connection.prototype.processQueue = function () { | ||
if (!this.queue.length || !this.connected || this.currentQuery) { | ||
return; | ||
} | ||
this.currentQuery = this.queue.shift(); | ||
this.con.query(this.currentQuery[1]); | ||
}; | ||
|
||
Connection.prototype.close = function () { | ||
// Emit failure on all promises in queue? | ||
this.con.close(); | ||
}; | ||
|
||
exports.Connection = Connection; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
#include <GeoIP.h> | ||
#include <GeoIPCity.h> | ||
|
||
#include <v8.h> | ||
#include <node.h> | ||
#include <node_events.h> | ||
#include <assert.h> | ||
|
||
using namespace v8; | ||
using namespace node; | ||
|
||
static Persistent<String> connected_symbol; | ||
static Persistent<String> closed_symbol; | ||
static Persistent<String> error_symbol; | ||
static Persistent<String> result_symbol; | ||
|
||
class Connection : public EventEmitter { | ||
public: | ||
static void | ||
Initialize (v8::Handle<v8::Object> target) | ||
{ | ||
Local<FunctionTemplate> t = FunctionTemplate::New(Connection::New); | ||
t->Inherit(EventEmitter::constructor_template); | ||
t->InstanceTemplate()->SetInternalFieldCount(1); | ||
|
||
closed_symbol = NODE_PSYMBOL("closed"); | ||
connected_symbol = NODE_PSYMBOL("connected"); | ||
error_symbol = NODE_PSYMBOL("error"); | ||
result_symbol = NODE_PSYMBOL("result"); | ||
|
||
NODE_SET_PROTOTYPE_METHOD(t, "connect", Connect); | ||
NODE_SET_PROTOTYPE_METHOD(t, "close", Close); | ||
NODE_SET_PROTOTYPE_METHOD(t, "query", Query); | ||
|
||
target->Set(String::NewSymbol("Connection"), t->GetFunction()); | ||
} | ||
|
||
void Connect(const char *dbpath) | ||
{ | ||
HandleScope scope; | ||
|
||
gi = GeoIP_open(dbpath, GEOIP_INDEX_CACHE); | ||
|
||
Emit((gi ? connected_symbol : error_symbol), 0, NULL); | ||
} | ||
|
||
void Close() | ||
{ | ||
HandleScope scope; | ||
|
||
if (gi != NULL) { | ||
GeoIP_delete(gi); | ||
gi = NULL; | ||
} | ||
|
||
Emit(closed_symbol, 0, NULL); | ||
} | ||
|
||
void Query(const char *query) | ||
{ | ||
HandleScope scope; | ||
|
||
assert(gi); | ||
GeoIPRecord *record; | ||
record = GeoIP_record_by_addr(gi, query); | ||
|
||
|
||
if (record) { | ||
Local<Value> result = BuildResult(record); | ||
GeoIPRecord_delete(record); | ||
Emit(result_symbol, 1, &result); | ||
} else { | ||
Emit(result_symbol, 0, NULL); | ||
} | ||
} | ||
|
||
protected: | ||
static Handle<Value> New(const Arguments& args) | ||
{ | ||
HandleScope scope; | ||
|
||
Connection *connection = new Connection(); | ||
connection->Wrap(args.This()); | ||
|
||
return args.This(); | ||
} | ||
|
||
static Handle<Value> Connect(const Arguments &args) | ||
{ | ||
HandleScope scope; | ||
|
||
if (args.Length() < 1 || !args[0]->IsString()) { | ||
return ThrowException( | ||
Exception::TypeError( | ||
String::New("Required argument: path to database."))); | ||
} | ||
|
||
String::Utf8Value dbpath(args[0]->ToString()); | ||
|
||
Connection *connection = ObjectWrap::Unwrap<Connection>(args.This()); | ||
connection->Connect(*dbpath); | ||
|
||
return Undefined(); | ||
} | ||
|
||
static Handle<Value> Close(const Arguments &args) | ||
{ | ||
HandleScope scope; | ||
|
||
Connection *connection = ObjectWrap::Unwrap<Connection>(args.This()); | ||
connection->Close(); | ||
|
||
return Undefined(); | ||
} | ||
|
||
static Handle<Value> Query(const Arguments &args) | ||
{ | ||
HandleScope scope; | ||
|
||
if (args.Length() < 1 || !args[0]->IsString()) { | ||
return ThrowException( | ||
Exception::TypeError( | ||
String::New("Required argument: ip address."))); | ||
} | ||
|
||
String::Utf8Value query(args[0]->ToString()); | ||
|
||
Connection *connection = ObjectWrap::Unwrap<Connection>(args.This()); | ||
connection->Query(*query); | ||
|
||
return Undefined(); | ||
} | ||
|
||
private: | ||
Local<Value>BuildResult(GeoIPRecord *record) | ||
{ | ||
HandleScope scope; | ||
|
||
Local<Array> result = Array::New(8); | ||
|
||
result->Set(String::New("longitude"), Number::New(record->longitude)); | ||
result->Set(String::New("latitude"), Number::New(record->latitude)); | ||
result->Set(String::New("country_code"), | ||
String::New(record->country_code)); | ||
result->Set(String::New("continent_code"), | ||
String::New(record->continent_code)); | ||
result->Set(String::New("metro_code"), | ||
Number::New(record->metro_code)); | ||
result->Set(String::New("country"), String::New(record->country_name)); | ||
result->Set(String::New("city"), String::New(record->city)); | ||
result->Set(String::New("area_code"), Number::New(record->area_code)); | ||
|
||
return scope.Close(result); | ||
} | ||
|
||
GeoIP *gi; | ||
}; | ||
|
||
extern "C" void | ||
init (Handle<Object> target) | ||
{ | ||
HandleScope scope; | ||
Connection::Initialize(target); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import os | ||
|
||
srcdir = os.path.abspath('.') | ||
blddir = 'build' | ||
target = 'ceoip' | ||
VERSION = '0.0.1' | ||
|
||
def set_options(opt): | ||
opt.tool_options('compiler_cxx') | ||
|
||
def configure(conf): | ||
conf.check_tool('compiler_cxx') | ||
conf.check_tool('node_addon') | ||
conf.check_cxx(lib='GeoIP', mandatory=True, uselib_store='GeoIP') | ||
|
||
def build(context, target=target): | ||
obj = context.new_task_gen('cxx', 'shlib', 'node_addon') | ||
|
||
obj.uselib = 'GeoIP' | ||
obj.source = 'src/ceoip.cc' | ||
obj.target = target | ||
|
||
context.add_post_fun(move_addon) | ||
|
||
def move_addon(context, target=target): | ||
"""Move the compiled addon to the local lib directory. Previously compiled | ||
versions of the addon are overwritten. | ||
""" | ||
filename = '%s.node' % target | ||
from_path = os.path.join(srcdir, blddir, 'default', filename) | ||
to_path = os.path.join(srcdir, 'lib', filename) | ||
|
||
if os.path.exists(from_path): | ||
os.rename(from_path, to_path) |