diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index d8b9d7f..9c601f1 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -1,2 +1,4 @@ * [Scott McWhirter](https://github.com/konobi) * Facilities to do in-memory db lookups, mmap and file update checks +* [Theo Schlossnagle](https://github.com/postwait) + * Update to use 0.8.0 APIs diff --git a/binding.gyp b/binding.gyp new file mode 100644 index 0000000..ac015e4 --- /dev/null +++ b/binding.gyp @@ -0,0 +1,33 @@ +{ + 'conditions': [ + ['OS=="solaris"', { + 'targets': [ + { + 'target_name': 'ceoip', + 'sources': [ 'src/ceoip.cc' ], + 'libraries': [ '-lGeoIP', '-liconv' ], + 'conditions': [ + ['target_arch=="ia32"', { + 'cflags': [ '-fpermissive', '-I/opt/omni/include' ], + 'ldflags': [ '-L/opt/omni/lib -R/opt/omni/lib' ] + }], + ['target_arch=="x64"', { + 'cflags': [ '-fpermissive', '-I/opt/omni/include/amd64' ], + 'ldflags': [ '-L/opt/omni/lib/amd64 -R/opt/omni/lib/amd64' ] + }] + ] + } + ] + }], + ['OS!="solaris"', { + 'targets': [ + { + 'target_name': 'ceoip', + 'sources': [ 'src/ceoip.cc' ], + 'libraries': [ '-lGeoIP' ], + 'cflags': [ '-I/opt/omni/include' ], + } + ] + }] + ] +} diff --git a/lib/ceoip.js b/lib/ceoip.js new file mode 100644 index 0000000..7b8ca86 --- /dev/null +++ b/lib/ceoip.js @@ -0,0 +1,17 @@ +// Copyright 2012 Circonus, Inc. All rights reserved. + +var ceoip = require('../build/Release/ceoip'); +var events = require('events'); + +inherits(ceoip.Connection, events.EventEmitter); +exports.Connection = ceoip.Connection; +exports.GEOIP_STANDARD = ceoip.GEOIP_STANDARD; +exports.GEOIP_MEMORY_CACHE = ceoip.GEOIP_MEMORY_CACHE; +exports.GEOIP_CHECK_CACHE = ceoip.GEOIP_CHECK_CACHE; +exports.GEOIP_INDEX_CACHE = ceoip.GEOIP_INDEX_CACHE; +exports.GEOIP_MMAP_CACHE = ceoip.GEOIP_MMAP_CACHE; + +function inherits(target, source) { + for (var k in source.prototype) + target.prototype[k] = source.prototype[k]; +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..9fec4ef --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "author": "strange (https://github.com/strange)", + "name": "geoip", + "description": "Geoip for node", + "version": "0.2.0", + "repository": { + "type": "git", + "url": "git://github.com/postwait/node-geoip.git" + }, + "main": "./lib/geoip", + "engines": { + "node": ">0.10.0" + }, + "script":{"install": "npm install"}, + "dependencies": {}, + "devDependencies": {} +} diff --git a/src/ceoip.cc b/src/ceoip.cc index 8f25d13..70a3cad 100644 --- a/src/ceoip.cc +++ b/src/ceoip.cc @@ -1,11 +1,12 @@ // Copyright 2010 Gustaf Sjöberg +// Copyright 2012 Circonus, Inc. All rights reserved. #include #include #include #include -#include #include +#include using namespace v8; using namespace node; @@ -14,15 +15,17 @@ static Persistent connected_symbol; static Persistent closed_symbol; static Persistent error_symbol; static Persistent result_symbol; +static iconv_t cd; -class Connection : public EventEmitter { +class Connection : ObjectWrap { public: static void Initialize(v8::Handle target) { Local t = FunctionTemplate::New(Connection::New); - t->Inherit(EventEmitter::constructor_template); t->InstanceTemplate()->SetInternalFieldCount(1); + t->SetClassName(String::New("ceoip.Connection")); + cd = iconv_open("utf-8", "ISO-8859-1"); closed_symbol = NODE_PSYMBOL("closed"); connected_symbol = NODE_PSYMBOL("connected"); error_symbol = NODE_PSYMBOL("error"); @@ -41,7 +44,7 @@ class Connection : public EventEmitter { target->Set(String::NewSymbol("Connection"), t->GetFunction()); } - void Connect(const char *dbpath, int db_opts_bitmask) { + void Connect(const Arguments &args, const char *dbpath, int db_opts_bitmask) { HandleScope scope; if(db_opts_bitmask == 0){ @@ -49,21 +52,22 @@ class Connection : public EventEmitter { } gi = GeoIP_open(dbpath, db_opts_bitmask); - Emit((gi ? connected_symbol : error_symbol), 0, NULL); + Handle argv[1] = { gi ? connected_symbol : error_symbol }; + MakeCallback(args.This(), "emit", 1, argv); } - void Close() { + void CloseHandle(const Arguments &args) { HandleScope scope; if (gi != NULL) { GeoIP_delete(gi); gi = NULL; } - - Emit(closed_symbol, 0, NULL); + Handle argv[1] = { closed_symbol }; + MakeCallback(args.This(), "emit", 1, argv); } - void Query(const char *query) { + void Query(const Arguments &args, const char *query) { HandleScope scope; assert(gi); @@ -73,9 +77,11 @@ class Connection : public EventEmitter { if (record) { Local result = BuildResult(record); GeoIPRecord_delete(record); - Emit(result_symbol, 1, &result); + Handle argv[2] = { result_symbol, result }; + MakeCallback(args.This(), "emit", 2, argv); } else { - Emit(result_symbol, 0, NULL); + Handle argv[1] = { result_symbol }; + MakeCallback(args.This(), "emit", 1, argv); } } @@ -107,7 +113,7 @@ class Connection : public EventEmitter { Connection *connection = ObjectWrap::Unwrap(args.This()); - connection->Connect(*dbpath, args[1]->ToUint32()->Value()); + connection->Connect(args, *dbpath, args[1]->ToUint32()->Value()); return Undefined(); } @@ -116,7 +122,7 @@ class Connection : public EventEmitter { HandleScope scope; Connection *connection = ObjectWrap::Unwrap(args.This()); - connection->Close(); + connection->CloseHandle(args); return Undefined(); } @@ -133,24 +139,38 @@ class Connection : public EventEmitter { String::Utf8Value query(args[0]->ToString()); Connection *connection = ObjectWrap::Unwrap(args.This()); - connection->Query(*query); + connection->Query(args, *query); return Undefined(); } private: + +#ifndef ICONV_SRC_CONST +#define ICONV_SRC_CONST +#endif +#define icv(a,b,blen) do { \ + ICONV_SRC_CONST char *in = a; \ + char *out = b; \ + size_t inlen = strlen(a); \ + size_t outlen = blen; \ + if(iconv(cd, &in, &inlen, &out, &outlen) == -1) b[0] = '\0'; \ + else *out = '\0'; \ +} while(0) + LocalBuildResult(GeoIPRecord *record) { HandleScope scope; + char outputbuff[1024]; Local result = Array::New(); - if (record->longitude != NULL) { + if (record->longitude != (int)NULL) { result->Set( String::New("longitude"), Number::New(record->longitude) ); } - if (record->latitude != NULL) { + if (record->latitude != (int)NULL) { result->Set( String::New("latitude"), Number::New(record->latitude) @@ -168,34 +188,37 @@ class Connection : public EventEmitter { String::New(record->continent_code) ); } - if (record->metro_code != NULL) { + if (record->metro_code != (int)NULL) { result->Set( String::New("metro_code"), Number::New(record->metro_code) ); } if (record->country_name != NULL) { + icv(record->country_name, outputbuff, sizeof(outputbuff)); result->Set( String::New("country"), - String::New(record->country_name) + String::New(outputbuff) ); } if (record->city != NULL) { + icv(record->city, outputbuff, sizeof(outputbuff)); result->Set( String::New("city"), - String::New(record->city) + String::New(outputbuff) ); } - if (record->area_code != NULL) { + if (record->area_code != (int)NULL) { result->Set( String::New("area_code"), Number::New(record->area_code) ); } if (record->region != NULL) { + icv(record->region, outputbuff, sizeof(outputbuff)); result->Set( String::New("region"), - String::New(record->region) + String::New(outputbuff) ); } @@ -210,3 +233,5 @@ init(Handle target) { HandleScope scope; Connection::Initialize(target); } + +NODE_MODULE(ceoip, init) diff --git a/wscript b/wscript index 91941c9..602d51b 100644 --- a/wscript +++ b/wscript @@ -1,4 +1,5 @@ import os +import sys srcdir = os.path.abspath('.') blddir = 'build' @@ -12,6 +13,8 @@ def configure(conf): conf.check_tool('compiler_cxx') conf.check_tool('node_addon') conf.check_cxx(lib='GeoIP', mandatory=True, uselib_store='GeoIP') + if not sys.platform.startswith("linux"): + conf.check_cxx(lib='iconv', mandatory=True, uselib_store='GeoIP') def build(context, target=target): obj = context.new_task_gen('cxx', 'shlib', 'node_addon')