From 9fc07962c1c46763b8dcf58524b008fa70708184 Mon Sep 17 00:00:00 2001 From: Joe Ferner Date: Thu, 19 Jan 2012 13:07:39 -0500 Subject: [PATCH] first commit --- .gitignore | 7 +++ LICENSE | 20 ++++++++ README.md | 97 +++++++++++++++++++++++++++++++++++ index.js | 2 + lib/nodeJavaBridge.js | 4 ++ package.json | 24 +++++++++ src/java.cpp | 114 +++++++++++++++++++++++++++++++++++++++++ src/java.h | 43 ++++++++++++++++ src/nodeJavaBridge.cpp | 10 ++++ test/simple-test.js | 14 +++++ wscript | 40 +++++++++++++++ 11 files changed, 375 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 index.js create mode 100644 lib/nodeJavaBridge.js create mode 100644 package.json create mode 100644 src/java.cpp create mode 100644 src/java.h create mode 100644 src/nodeJavaBridge.cpp create mode 100644 test/simple-test.js create mode 100644 wscript diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..47e56317 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/build/* +node_modules +*.node +*.sh +*.swp +.lock* +npm-debug.log diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..644621ba --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2012 Near Infinity Corporation + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..97aaa43f --- /dev/null +++ b/README.md @@ -0,0 +1,97 @@ +# nodeshark + +Wrapper around libwireshark providing network packet dissection for [node.js](http://nodejs.org/). + +## Installation + + $ npm install nodeshark + +### Build + +```bash +$ svn co http://anonsvn.wireshark.org/wireshark/trunk/ wireshark +$ cd wireshark +$ ./autogen.sh +$ ./configure +$ make +$ sudo make install +$ export WIRESHARK_INCLUDE_DIR=[wireshark source directory] +$ node-waf configure build +``` + +## Usage + +```javascript +var nodeshark = require("nodeshark"); + +var dissector = new nodeshark.Dissector(nodeshark.LINK_LAYER_TYPE_ETHERNET); + +var rawPacket = { + header: { + timestampSeconds: 10, + timestampMicroseconds: 20, + capturedLength: buffer.length, + originalLength: buffer.length + }, + data: new Buffer([ + 0x58, 0x6d, 0x8f, 0x67, 0x8a, 0x4d, 0x00, 0x1b, 0x21, 0xcf, 0xa1, 0x00, 0x08, 0x00, 0x45, 0x00, + 0x00, 0x3b, 0xd1, 0xb0, 0x40, 0x00, 0x40, 0x11, 0xc5, 0xde, 0x0a, 0x14, 0x08, 0x65, 0xc0, 0xa8, + 0xd0, 0x01, 0xc5, 0x32, 0x00, 0x35, 0x00, 0x27, 0xa3, 0x5b, 0x65, 0x89, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6d, 0x61, 0x69, 0x6c, 0x04, 0x6c, 0x69, 0x76, 0x65, + 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 + ]); +}; +var packet = dissector.dissect(rawPacket); + +// OR + +var buffer = new Buffer([ + 0x58, 0x6d, 0x8f, 0x67, 0x8a, 0x4d, 0x00, 0x1b, 0x21, 0xcf, 0xa1, 0x00, 0x08, 0x00, 0x45, 0x00, + 0x00, 0x3b, 0xd1, 0xb0, 0x40, 0x00, 0x40, 0x11, 0xc5, 0xde, 0x0a, 0x14, 0x08, 0x65, 0xc0, 0xa8, + 0xd0, 0x01, 0xc5, 0x32, 0x00, 0x35, 0x00, 0x27, 0xa3, 0x5b, 0x65, 0x89, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6d, 0x61, 0x69, 0x6c, 0x04, 0x6c, 0x69, 0x76, 0x65, + 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 +]); +var packet = dissector.dissect(buffer); +``` + +You can also use it it conjunction with [pcap-parser](https://github.com/nearinfinity/node-pcap-parser). + +```javascript +var pcapp = require('pcap-parser'); + +var parser = new pcapp.Parser('/path/to/file.pcap'); +var dissector; +parser.on('globalHeader', function(globalHeader) { + dissector = new nodeshark.Dissector(globalHeader.linkLayerType); +}); +parser.on('packet', function(rawPacket) { + var packet = dissector.dissect(rawPacket); +}); +parser.parse(); +``` + +## License + +(The MIT License) + +Copyright (c) 2012 Near Infinity Corporation + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/index.js b/index.js new file mode 100644 index 00000000..f9e0d85a --- /dev/null +++ b/index.js @@ -0,0 +1,2 @@ + +module.exports = require("./lib/nodeJavaBridge"); diff --git a/lib/nodeJavaBridge.js b/lib/nodeJavaBridge.js new file mode 100644 index 00000000..83476b6e --- /dev/null +++ b/lib/nodeJavaBridge.js @@ -0,0 +1,4 @@ + +var bindings = require("../build/Release/nodejavabridge_bindings"); + +module.exports = new bindings.Java(); diff --git a/package.json b/package.json new file mode 100644 index 00000000..5a269135 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "nodejavabridge", + "description": "Bridge API to connect with existing Java APIs", + "keywords": ["java", "jvm", "bridge"], + "homepage": "https://github.com/nearinfinity/node-java-bridge", + "version": "0.0.1", + "engines": { "node" : ">=0.6.0" }, + "maintainers": [ + { "name": "Jeff Kunkle", "email": "jeff.kunkle@nearinfinity.com" }, + { "name": "Joe Ferner", "email": "joe.ferner@nearinfinity.com" } + ], + "bugs": { "url": "https://github.com/nearinfinity/node-java-bridge/issues" }, + "licenses": [ { "type" : "MIT" } ], + "repositories": [ + { "type": "git", "url": "https://github.com/nearinfinity/node-java-bridge.git" } + ], + "devDependencies": { + "nodeunit": "~0.6.4" + }, + "scripts": { + "test": "nodeunit test", + "install": "node-waf configure build" + } +} diff --git a/src/java.cpp b/src/java.cpp new file mode 100644 index 00000000..be9ef933 --- /dev/null +++ b/src/java.cpp @@ -0,0 +1,114 @@ + +#include "java.h" +#include + +/*static*/ v8::Persistent Java::s_ct; + +/*static*/ void Java::Init(v8::Handle target) { + v8::HandleScope scope; + + v8::Local t = v8::FunctionTemplate::New(New); + s_ct = v8::Persistent::New(t); + s_ct->InstanceTemplate()->SetInternalFieldCount(1); + s_ct->SetClassName(v8::String::NewSymbol("Java")); + + NODE_SET_PROTOTYPE_METHOD(s_ct, "newInstance", newInstance); + + target->Set(v8::String::NewSymbol("Java"), s_ct->GetFunction()); +} + +/*static*/ v8::Handle Java::New(const v8::Arguments& args) { + v8::HandleScope scope; + + Java *self = new Java(); + self->Wrap(args.This()); + return args.This(); +} + +Java::Java() { + this->m_env = createJVM(); +} + +Java::~Java() { + +} + +/*static*/ JNIEnv* Java::createJVM() { + JavaVM* jvm; + JNIEnv* env; + JavaVMInitArgs args; + JavaVMOption options[0]; + + /* There is a new JNI_VERSION_1_4, but it doesn't add anything for the purposes of our example. */ + args.version = JNI_VERSION_1_2; + args.nOptions = 0; + args.options = options; + args.ignoreUnrecognized = JNI_FALSE; + + JNI_CreateJavaVM(&jvm, (void **)&env, &args); + + return env; +} + +/*static*/ v8::Handle Java::newInstance(const v8::Arguments& args) { + v8::HandleScope scope; + Java* self = node::ObjectWrap::Unwrap(args.This()); + + // argument - className + if(args.Length() < 1 || !args[0]->IsString()) { + return ThrowException(v8::Exception::TypeError(v8::String::New("Argument 0 must be a string"))); + } + v8::Local classNameObj = v8::Local::Cast(args[0]); + v8::String::AsciiValue className(classNameObj); + + // argument - callback + v8::Handle callback; + if(args[args.Length()-1]->IsFunction()) { + callback = args[args.Length()-1]; + } else { + callback = v8::Null(); + } + + // run + NewInstanceBaton* baton = new NewInstanceBaton(self, *className, callback); + eio_custom(EIO_NewInstance, EIO_PRI_DEFAULT, EIO_AfterNewInstance, baton); + ev_ref(EV_DEFAULT_UC); + + return v8::Undefined(); +} + +/*static*/ void Java::EIO_NewInstance(eio_req* req) { + NewInstanceBaton* baton = static_cast(req->data); +} + +/*static*/ int Java::EIO_AfterNewInstance(eio_req* req) { + NewInstanceBaton* baton = static_cast(req->data); + ev_unref(EV_DEFAULT_UC); + + baton->doCallback(); + + delete baton; + return 0; +} + +NewInstanceBaton::NewInstanceBaton(Java* java, const char *className, v8::Handle &callback) { + this->m_java = java; + this->m_className = strdup(className); + this->m_callback = v8::Persistent::New(callback); + this->m_java->Ref(); +} + +NewInstanceBaton::~NewInstanceBaton() { + this->m_callback.Dispose(); + this->m_java->Unref(); +} + +void NewInstanceBaton::doCallback() { + v8::Handle argv[2]; + argv[0] = v8::Undefined(); + argv[1] = v8::Undefined(); + + if(this->m_callback->IsFunction()) { + v8::Function::Cast(*this->m_callback)->Call(v8::Context::GetCurrent()->Global(), 2, argv); + } +} diff --git a/src/java.h b/src/java.h new file mode 100644 index 00000000..140db487 --- /dev/null +++ b/src/java.h @@ -0,0 +1,43 @@ + +#ifndef _node_java_h_ +#define _node_java_h_ + +#include +#include +#include + +class NewInstanceBaton; + +class Java : public node::ObjectWrap { +public: + static void Init(v8::Handle target); + + friend class NewInstanceBaton; + +private: + Java(); + ~Java(); + static JNIEnv* createJVM(); + + static v8::Handle New(const v8::Arguments& args); + static v8::Handle newInstance(const v8::Arguments& args); + static void EIO_NewInstance(eio_req* req); + static int EIO_AfterNewInstance(eio_req* req); + + static v8::Persistent s_ct; + JNIEnv* m_env; +}; + +class NewInstanceBaton { +public: + NewInstanceBaton(Java* java, const char *className, v8::Handle &callback); + ~NewInstanceBaton(); + void doCallback(); + +private: + Java* m_java; + v8::Persistent m_callback; + char* m_className; +}; + +#endif diff --git a/src/nodeJavaBridge.cpp b/src/nodeJavaBridge.cpp new file mode 100644 index 00000000..13b437ff --- /dev/null +++ b/src/nodeJavaBridge.cpp @@ -0,0 +1,10 @@ + +#include "java.h" + +extern "C" { + static void init(v8::Handle target) { + Java::Init(target); + } + + NODE_MODULE(nodejavabridge_bindings, init); +} diff --git a/test/simple-test.js b/test/simple-test.js new file mode 100644 index 00000000..99bc1a7c --- /dev/null +++ b/test/simple-test.js @@ -0,0 +1,14 @@ + + +var java = require("../"); +var nodeunit = require("nodeunit"); +var util = require("util"); + +exports['Simple'] = nodeunit.testCase({ + "create an instance of a class (async)": function(test) { + java.newInstance("java.util.ArrayList", function(list) { + test.ok(list); + test.done(); + }); + } +}); diff --git a/wscript b/wscript new file mode 100644 index 00000000..a886d887 --- /dev/null +++ b/wscript @@ -0,0 +1,40 @@ +import Options, Utils +from os import unlink, symlink, chdir, environ +from os.path import exists + +def set_options(opt): + opt.tool_options("compiler_cxx") + +def configure(conf): + conf.check_tool("compiler_cxx") + conf.check_tool("node_addon") + + # Enables all the warnings that are easy to avoid + conf.env.append_unique('CXXFLAGS', ["-Wall"]) + conf.env.append_unique('CXXFLAGS', ['-Isrc/']) + conf.env.append_unique('CXXFLAGS', ['-g']) + conf.env.append_unique('CXXFLAGS', ['-D_FILE_OFFSET_BITS=64']) + conf.env.append_unique('CXXFLAGS', ['-D_LARGEFILE_SOURCE']) + conf.env.append_unique('CXXFLAGS', ['-DHAVE_CONFIG_H']) + + jdk_include_dir = environ.get("JDK_INCLUDE_DIR", "/usr/local/share/jdk1.6.0_30/include/") + if jdk_include_dir: + conf.env.append_unique('CXXFLAGS', [ '-I' + jdk_include_dir ]) + + jdk_additional_include_dir = environ.get("JDK_INCLUDE_DIR", "/usr/local/share/jdk1.6.0_30/include/linux/") + if jdk_additional_include_dir: + conf.env.append_unique('CXXFLAGS', [ '-I' + jdk_additional_include_dir ]) + + jdk_lib_dir = environ.get("JDK_LIB_DIR", "/usr/local/share/jdk1.6.0_30/jre/lib/i386/client/") + if jdk_lib_dir: + conf.env.append_unique('LINKFLAGS', [ '-L' + jdk_lib_dir ]) + + conf.env.append_unique('LINKFLAGS', ['-ljvm']) + +def build(bld): + obj = bld.new_task_gen("cxx", "shlib", "node_addon") + obj.target = "nodejavabridge_bindings" + obj.source = " ".join([ + "src/nodeJavaBridge.cpp", + "src/java.cpp"]) + obj.includes = "src/"