libprelude/master: Initial prelude-log C++/Python/Ruby/Perl/Lua bindings support.
[email protected] Wed, 8 Jul 2009 16:51:57 +0200 (CEST)
| Newsgroups | gmane.comp.security.ids.prelude.cvs |
|---|---|
| Message-ID | <[email protected]> |
commit dfed1bc7fb7dbb3eaeac20b36f7738ea582378d2 Author: Yoann Vandoorselaere <[email protected]> Date: Fri Jun 19 00:33:19 2009 +0200 Initial prelude-log C++/Python/Ruby/Perl/Lua bindings support. This implement language bindings for the PreludeLog interface. High level language use a specific check so that the log callback is not called from a different thread than the initialisation thread, since we cannot efficiently protect SWIG generated object. ======================================== bindings/c++/Makefile.am | 3 +- bindings/c++/include/Makefile.am | 3 +- bindings/c++/include/prelude-log.hxx | 56 ++++++++++++++++++++++++++++++++ bindings/c++/prelude-log.cxx | 42 ++++++++++++++++++++++++ bindings/libpreludecpp-perl.i | 41 ++++++++++++++++++++++- bindings/libpreludecpp.i | 5 +++ bindings/lua/Makefile.am | 2 +- bindings/lua/libpreludecpp-lua.i | 35 +++++++++++++++++++- bindings/perl/Makefile.PL.in | 2 +- bindings/python/libpreludecpp-python.i | 34 +++++++++++++++++++ bindings/python/setup.py.in | 2 +- bindings/ruby/Makefile.am | 2 +- bindings/ruby/libpreludecpp-ruby.i | 31 +++++++++++++++++- bindings/tests/test.lua | 5 +++ bindings/tests/test.pl | 9 +++++ bindings/tests/test.py | 6 +++ bindings/tests/test.rb | 1 + 17 files changed, 268 insertions(+), 11 deletions(-) ======================================== diff --git a/bindings/c++/Makefile.am b/bindings/c++/Makefile.am index 5bffc88..d4519cd 100644 --- a/bindings/c++/Makefile.am +++ b/bindings/c++/Makefile.am @@ -16,7 +16,8 @@ libpreludecpp_la_SOURCES = \ prelude-client-easy.cxx \ prelude-client-profile.cxx \ prelude-connection.cxx \ - prelude-connection-pool.cxx + prelude-connection-pool.cxx \ + prelude-log.cxx libpreludecpp_la_LDFLAGS = -no-undefined -version-info @LIBPRELUDECPP_SONAME@ libpreludecpp_la_LIBADD = $(top_builddir)/src/.libs/libprelude.la diff --git a/bindings/c++/include/Makefile.am b/bindings/c++/include/Makefile.am index 596ce78..17cc572 100644 --- a/bindings/c++/include/Makefile.am +++ b/bindings/c++/include/Makefile.am @@ -12,7 +12,8 @@ include_HEADERS = \ prelude-client-easy.hxx \ prelude-client-profile.hxx \ prelude-connection.hxx \ - prelude-connection-pool.hxx + prelude-connection-pool.hxx \ + prelude-log.hxx -include $(top_srcdir)/git.mk diff --git a/bindings/c++/include/prelude-log.hxx b/bindings/c++/include/prelude-log.hxx new file mode 100644 index 0000000..328f2e8 --- /dev/null +++ b/bindings/c++/include/prelude-log.hxx @@ -0,0 +1,56 @@ +/***** +* +* Copyright (C) 2009 PreludeIDS Technologies. All Rights Reserved. +* Author: Yoann Vandoorselaere <[email protected]> +* +* This file is part of the Prelude library. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + +#ifndef _LIBPRELUDE_PRELUDE_LOG_HXX +#define _LIBPRELUDE_PRELUDE_LOG_HXX + +#include "prelude.h" +#include "idmef-path.h" + + +namespace Prelude { + class PreludeLog { + public: + enum LogLevelEnum { + DEBUG = PRELUDE_LOG_DEBUG, + INFO = PRELUDE_LOG_INFO, + WARNING = PRELUDE_LOG_WARN, + ERROR = PRELUDE_LOG_ERR, + CRITICAL = PRELUDE_LOG_CRIT + }; + + enum LogFlagsEnum { + QUIET = PRELUDE_LOG_FLAGS_QUIET, + SYSLOG = PRELUDE_LOG_FLAGS_SYSLOG + }; + + static void SetLevel(int level); + static void SetDebugLevel(int level); + static void SetFlags(int flags); + static int GetFlags(void); + static void SetLogfile(const char *filename); + static void SetCallback(void (*log_cb)(int level, const char *log)); + }; +}; + +#endif diff --git a/bindings/c++/prelude-log.cxx b/bindings/c++/prelude-log.cxx new file mode 100644 index 0000000..d2d729d --- /dev/null +++ b/bindings/c++/prelude-log.cxx @@ -0,0 +1,42 @@ +#include <prelude.h> + +#include <prelude-log.hxx> + + +using namespace Prelude; + +void PreludeLog::SetLevel(int level) +{ + prelude_log_set_level((prelude_log_t) level); +} + + +void PreludeLog::SetDebugLevel(int level) +{ + prelude_log_set_debug_level(level); +} + + +void PreludeLog::SetFlags(int flags) +{ + prelude_log_set_flags((prelude_log_flags_t) flags); +} + + +int PreludeLog::GetFlags() +{ + return prelude_log_get_flags(); +} + + +void PreludeLog::SetLogfile(const char *filename) +{ + prelude_log_set_logfile(filename); +} + + +void PreludeLog::SetCallback(void (*log_cb)(int level, const char *log)) +{ + + prelude_log_set_callback((void (*)(prelude_log_t level, const char *log)) log_cb); +} diff --git a/bindings/libpreludecpp-perl.i b/bindings/libpreludecpp-perl.i index caa8f85..2b7488c 100644 --- a/bindings/libpreludecpp-perl.i +++ b/bindings/libpreludecpp-perl.i @@ -55,7 +55,32 @@ SV *IDMEFValueList_to_SWIG(const Prelude::IDMEFValue &value) $1 = $input; } -%{ +%fragment("TransitionFunc", "header") { +static SV *__prelude_log_func; +static gl_thread_t __initial_thread; + + +static void _cb_perl_log(int level, const char *str) +{ + if ( (gl_thread_t) gl_thread_self() != __initial_thread ) + return; + + dSP; + ENTER; + SAVETMPS; + + PUSHMARK(SP); + XPUSHs(SWIG_From_int(level)); + XPUSHs(SWIG_FromCharPtr(str)); + PUTBACK; + + perl_call_sv(__prelude_log_func, G_VOID); + + FREETMPS; + LEAVE; +} + + static int _cb_perl_write(prelude_msgbuf_t *fd, prelude_msg_t *msg) { int ret; @@ -85,7 +110,17 @@ static ssize_t _cb_perl_read(prelude_io_t *fd, void *buf, size_t size) return ret; } -%} +}; + +%typemap(in, fragment="TransitionFunc") void (*log_cb)(int level, const char *log) { + if ( __prelude_log_func ) + SvREFCNT_dec(__prelude_log_func); + + __prelude_log_func = $input; + SvREFCNT_inc($input); + + $1 = _cb_perl_log; +}; %extend Prelude::IDMEF { void Write(void *nocast_p) { @@ -129,6 +164,8 @@ static ssize_t _cb_perl_read(prelude_io_t *fd, void *buf, size_t size) int j, argc = 1, ret; AV *pargv = get_av("ARGV", FALSE); + __initial_thread = (gl_thread_t) gl_thread_self(); + ret = av_len(pargv); if ( ret >= 0 ) argc += ret + 1; diff --git a/bindings/libpreludecpp.i b/bindings/libpreludecpp.i index b01f0e8..8057685 100644 --- a/bindings/libpreludecpp.i +++ b/bindings/libpreludecpp.i @@ -8,7 +8,10 @@ #include <list> #include <sstream> +#include "config.h" + #include "prelude.hxx" +#include "prelude-log.hxx" #include "prelude-error.hxx" #include "prelude-connection.hxx" #include "prelude-connection-pool.hxx" @@ -20,6 +23,7 @@ #include "idmef-path.hxx" #include "idmef-time.hxx" #include "idmef.hxx" +#include "glthread/thread.h" using namespace Prelude; %} @@ -207,6 +211,7 @@ int IDMEFValue_to_SWIG(const IDMEFValue &result, TARGET_LANGUAGE_OUTPUT_TYPE ret %ignore operator prelude_client_profile_t *() const; %include prelude.hxx +%include prelude-log.hxx %include prelude-error.hxx %include prelude-connection.hxx %include prelude-connection-pool.hxx diff --git a/bindings/lua/Makefile.am b/bindings/lua/Makefile.am index 168a581..0a1ad9b 100644 --- a/bindings/lua/Makefile.am +++ b/bindings/lua/Makefile.am @@ -4,7 +4,7 @@ EXTRA_DIST = libpreludecpp-lua.i PreludeEasy.cxx if HAVE_LUA -AM_CPPFLAGS = -I@top_srcdir@ -I@top_builddir@/src/include -I@top_srcdir@/src/include -I@top_builddir@/src/libprelude-error -I@top_srcdir@/bindings/c++/include @LUA_CFLAGS@ +AM_CPPFLAGS = -I@top_srcdir@ -I@top_builddir@/src/include -I@top_srcdir@/src/include -I@top_builddir@/src/libprelude-error -I@top_srcdir@/bindings/c++/include @LUA_CFLAGS@ -I@top_srcdir@/libmissing -I@top_builddir@/libmissing PreludeEasy_la_LDFLAGS = -module -avoid-version @LUA_LIBS@ PreludeEasy_la_LIBADD = $(top_builddir)/bindings/c++/.libs/libpreludecpp.la diff --git a/bindings/lua/libpreludecpp-lua.i b/bindings/lua/libpreludecpp-lua.i index 58c0b03..b762d2d 100644 --- a/bindings/lua/libpreludecpp-lua.i +++ b/bindings/lua/libpreludecpp-lua.i @@ -110,7 +110,23 @@ int IDMEFValue_to_SWIG(lua_State* L, const IDMEFValue &result); $1 = *pf; } -%{ +%fragment("TransitionFunc", "header") { +static int __prelude_log_func; +static lua_State *__lua_state = NULL; +static gl_thread_t __initial_thread; + +static void _cb_lua_log(int level, const char *str) +{ + if ( (gl_thread_t) gl_thread_self() != __initial_thread ) + return; + + lua_rawgeti(__lua_state, LUA_REGISTRYINDEX, __prelude_log_func); + lua_pushnumber(__lua_state, level); + lua_pushstring(__lua_state, str); + lua_call(__lua_state, 2, 0); +} + + static int _cb_lua_write(prelude_msgbuf_t *fd, prelude_msg_t *msg) { size_t ret; @@ -140,7 +156,20 @@ static ssize_t _cb_lua_read(prelude_io_t *fd, void *buf, size_t size) return ret; } -%} +}; + + +%typemap(in, fragment="TransitionFunc") void (*log_cb)(int level, const char *log) { + if ( ! lua_isfunction(L, -1) ) + SWIG_exception(SWIG_ValueError, "Argument should be a function"); + + if ( __lua_state ) + luaL_unref(L, LUA_REGISTRYINDEX, __prelude_log_func); + + __prelude_log_func = luaL_ref(L, LUA_REGISTRYINDEX); + $1 = _cb_lua_log; + __lua_state = L; +}; %extend Prelude::IDMEF { @@ -291,6 +320,8 @@ int IDMEFValue_to_SWIG(lua_State* L, const IDMEFValue &result) int argc = 0, ret; static char *argv[1024]; + __initial_thread = (gl_thread_t) gl_thread_self(); + lua_getglobal(L, "arg"); lua_pushnil(L); diff --git a/bindings/perl/Makefile.PL.in b/bindings/perl/Makefile.PL.in index d2182e2..912ed2b 100644 --- a/bindings/perl/Makefile.PL.in +++ b/bindings/perl/Makefile.PL.in @@ -5,7 +5,7 @@ use File::Copy; use Cwd "abs_path"; my %attributs = (NAME => 'PreludeEasy', - INC => '-I@top_srcdir@ -I@top_builddir@/src/include -I@top_srcdir@/src/include -I@top_builddir@/src/libprelude-error -I@top_srcdir@/bindings/c++/include', + INC => '-I@top_srcdir@ -I@top_builddir@/src/include -I@top_srcdir@/src/include -I@top_builddir@/src/libprelude-error -I@top_srcdir@/bindings/c++/include -I@top_srcdir@/libmissing -I@top_builddir@/libmissing', LIBS => ["-L@top_builddir@/src/.libs -lprelude -L@top_builddir@/bindings/c++/.libs -lpreludecpp", "-L$ENV{LIBDIR} -lprelude @LIBPRELUDE_LIBS@ @LIBADD_DL@ @LTLIBTHREAD@" ], LDDLFLAGS => "-L@top_builddir@/src/.libs $Config{lddlflags}"); diff --git a/bindings/python/libpreludecpp-python.i b/bindings/python/libpreludecpp-python.i index d8f9e02..afa0fd6 100644 --- a/bindings/python/libpreludecpp-python.i +++ b/bindings/python/libpreludecpp-python.i @@ -15,6 +15,25 @@ int IDMEFValue_to_SWIG(const IDMEFValue &result, TARGET_LANGUAGE_OUTPUT_TYPE ret %{ +static gl_thread_t __initial_thread; +PyObject *__prelude_log_func = NULL; + +static void _cb_python_log(int level, const char *str) +{ + PyObject *arglist, *result; + + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + + arglist = Py_BuildValue("(i,s)", level, str); + result = PyEval_CallObject(__prelude_log_func, arglist); + + Py_DECREF(arglist); + Py_XDECREF(result); + + SWIG_PYTHON_THREAD_END_BLOCK; +} + + static int _cb_python_write(prelude_msgbuf_t *fd, prelude_msg_t *msg) { size_t ret; @@ -48,6 +67,19 @@ static ssize_t _cb_python_read(prelude_io_t *fd, void *buf, size_t size) } %} +%typemap(in) void (*log_cb)(int level, const char *log) { + if ( ! PyCallable_Check($input) ) + SWIG_exception_fail(SWIG_ValueError, "Argument is not a callable object"); + + if ( __prelude_log_func ) + Py_DECREF(__prelude_log_func); + + __prelude_log_func = $input; + Py_INCREF($input); + + $1 = _cb_python_log; +}; + /* tell squid not to cast void * value */ %typemap(in) void *nocast_file_p { @@ -128,6 +160,8 @@ PyObject *IDMEFValueList_to_SWIG(const Prelude::IDMEFValue &value) PyObject *sys = PyImport_ImportModule("sys"); PyObject *pyargv = PyObject_GetAttrString(sys, "argv"); + __initial_thread = (gl_thread_t) gl_thread_self(); + argc = PyObject_Length(pyargv); assert(argc >= 1); assert(PyList_Check(pyargv)); diff --git a/bindings/python/setup.py.in b/bindings/python/setup.py.in index 85f0437..ec053f8 100644 --- a/bindings/python/setup.py.in +++ b/bindings/python/setup.py.in @@ -84,6 +84,6 @@ setup(name="PreludeEasy", py_modules=["PreludeEasy"], ext_modules=[Extension("_PreludeEasy", ["_PreludeEasy.cxx"], - extra_compile_args=split_args("-I@top_builddir@ -I@top_srcdir@/src/include -I@top_builddir@/src/include -I@top_builddir@/src/libprelude-error -I@top_srcdir@/bindings/c++/include"), + extra_compile_args=split_args("-I@top_builddir@ -I@top_srcdir@/src/include -I@top_builddir@/src/include -I@top_builddir@/src/libprelude-error -I@top_srcdir@/bindings/c++/include -I@top_srcdir@/libmissing -I@top_builddir@/libmissing"), library_dirs=[ "@top_builddir@/src/.libs/", "@top_builddir@/bindings/c++/.libs/" ], extra_link_args=split_args("-lpreludecpp -lprelude @LIBPRELUDE_LIBS@ @LIBADD_DL@ @LTLIBTHREAD@"))]) diff --git a/bindings/ruby/Makefile.am b/bindings/ruby/Makefile.am index 4796152..d8351fc 100644 --- a/bindings/ruby/Makefile.am +++ b/bindings/ruby/Makefile.am @@ -4,7 +4,7 @@ if HAVE_RUBY EXTRA_DIST = libpreludecpp-ruby.i PreludeEasy.cxx rbexec_LTLIBRARIES = PreludeEasy.la -PreludeEasy_la_CPPFLAGS = $(RUBY_INCLUDES) $(RUBY_CCFLAGS) -I@top_builddir@ -I$(top_srcdir)/src/include -I$(top_builddir)/src/include -I@top_builddir@/src/libprelude-error -I$(top_srcdir)/bindings/c++/include +PreludeEasy_la_CPPFLAGS = $(RUBY_INCLUDES) $(RUBY_CCFLAGS) -I@top_builddir@ -I$(top_srcdir)/src/include -I$(top_builddir)/src/include -I@top_builddir@/src/libprelude-error -I$(top_srcdir)/bindings/c++/include -I@top_srcdir@/libmissing -I@top_builddir@/libmissing PreludeEasy_la_LDFLAGS = -module -avoid-version PreludeEasy_la_LIBADD = $(top_builddir)/bindings/c++/.libs/libpreludecpp.la $(RUBY_LIBS) nodist_PreludeEasy_la_SOURCES = PreludeEasy.cxx diff --git a/bindings/ruby/libpreludecpp-ruby.i b/bindings/ruby/libpreludecpp-ruby.i index d533b91..7b7fe01 100644 --- a/bindings/ruby/libpreludecpp-ruby.i +++ b/bindings/ruby/libpreludecpp-ruby.i @@ -23,6 +23,23 @@ int IDMEFValue_to_SWIG(const IDMEFValue &result, TARGET_LANGUAGE_OUTPUT_TYPE ret extern "C" { #include "rubyio.h" } +%}; + + +%fragment("TransitionFunc", "header") { +static gl_thread_t __initial_thread; +static VALUE __prelude_log_func = Qnil; + +static void _cb_ruby_log(int level, const char *str) +{ + static int cid = rb_intern("call"); + + if ( (gl_thread_t) gl_thread_self() != __initial_thread ) + return; + + rb_funcall(__prelude_log_func, cid, 2, SWIG_From_int(level), SWIG_FromCharPtr(str)); +} + static int _cb_ruby_write(prelude_msgbuf_t *fd, prelude_msg_t *msg) { @@ -63,8 +80,18 @@ static ssize_t _cb_ruby_read(prelude_io_t *fd, void *buf, size_t size) return ret; } +}; -%} + +%typemap(in, fragment="TransitionFunc") void (*log_cb)(int level, const char *log) { + if ( ! SWIG_Ruby_isCallable($input) ) + SWIG_exception_fail(SWIG_ValueError, "Argument is not a callable object"); + + __prelude_log_func = $input; + rb_global_variable(&$input); + + $1 = _cb_ruby_log; +}; %extend Prelude::IDMEF { @@ -136,6 +163,8 @@ VALUE IDMEFValueList_to_SWIG(const Prelude::IDMEFValue &value) int _i, argc; VALUE rbargv, *ptr; + __initial_thread = (gl_thread_t) gl_thread_self(); + rbargv = rb_const_get(rb_cObject, rb_intern("ARGV")); argc = RARRAY(rbargv)->len + 1; diff --git a/bindings/tests/test.lua b/bindings/tests/test.lua index d2ef641..38e176f 100755 --- a/bindings/tests/test.lua +++ b/bindings/tests/test.lua @@ -2,6 +2,11 @@ require("PreludeEasy") +function my_cb(level, log) + io.write("log: " .. log) +end +PreludeEasy.PreludeLog_SetCallback(my_cb) + idmef = PreludeEasy.IDMEF() print("*** IDMEF->Set() ***") diff --git a/bindings/tests/test.pl b/bindings/tests/test.pl index 937c298..3eaabd7 100755 --- a/bindings/tests/test.pl +++ b/bindings/tests/test.pl @@ -2,7 +2,16 @@ use PreludeEasy; +sub log_func { + ($level, $str) = @_; + print("log: " . $str); +} + +PreludeEasy::PreludeLog::SetCallback(\&log_func); + $idmef = new PreludeEasy::IDMEF; +$client = new PreludeEasy::ClientEasy("abc"); +$client->Start(); print "*** IDMEF->Set() ***\n"; $idmef->Set("alert.classification.text", "My Message"); diff --git a/bindings/tests/test.py b/bindings/tests/test.py index 770617a..fe68e32 100755 --- a/bindings/tests/test.py +++ b/bindings/tests/test.py @@ -1,7 +1,13 @@ #!/usr/bin/env python +import sys import PreludeEasy +def log_cb(level, str): + sys.stdout.write("log: " + str) + +PreludeEasy.PreludeLog.SetCallback(log_cb) + idmef = PreludeEasy.IDMEF() print "*** IDMEF->Set() ***" diff --git a/bindings/tests/test.rb b/bindings/tests/test.rb index a6cbea2..1998ebe 100755 --- a/bindings/tests/test.rb +++ b/bindings/tests/test.rb @@ -2,6 +2,7 @@ require("PreludeEasy") +PreludeEasy::PreludeLog::SetCallback(lambda{|level,str|print "log: " + str}) idmef = PreludeEasy::IDMEF.new() print "*** IDMEF->Set() ***\n" _______________________________________________ Prelude-cvslog site list [email protected] http://lists.prelude-ids.org/mailman/listinfo/prelude-cvslog