diff --git a/src/plugins/dbus/Makefile.in b/src/plugins/dbus/Makefile.in index e1c2fdf..1cfa98a 100644 --- a/src/plugins/dbus/Makefile.in +++ b/src/plugins/dbus/Makefile.in @@ -30,8 +30,8 @@ MODULE_NAME=pw3270dbus DEPENDS=Makefile dbus-glue.h -PLUGIN_SRC=main.c -DAEMON_SRC=daemon.c gobject.c +PLUGIN_SRC=main.c gobject.c +DAEMON_SRC=daemon.c gobject.c iocallback.c #---[ Paths ]------------------------------------------------------------------ diff --git a/src/plugins/dbus/daemon.c b/src/plugins/dbus/daemon.c index 3580c96..0e4b9f0 100644 --- a/src/plugins/dbus/daemon.c +++ b/src/plugins/dbus/daemon.c @@ -38,13 +38,17 @@ #include #include -#include "service.h" +#include "daemon.h" #include "dbus-glue.h" /*---[ Globals ]---------------------------------------------------------------------------------*/ static DBusGConnection * connection = NULL; static DBusGProxy * proxy = NULL; + static H3270 * hSession = NULL; + + GMainLoop * main_loop = NULL; + /*---[ Implement ]-------------------------------------------------------------------------------*/ @@ -80,8 +84,6 @@ static int initialize(void) int main(int numpar, char *param[]) { - GMainLoop *loop; - g_type_init (); if (!g_thread_supported ()) @@ -89,16 +91,31 @@ int main(int numpar, char *param[]) dbus_g_thread_init (); - loop = g_main_loop_new (NULL, FALSE); + pw3270_dbus_register_io_handlers(); + + hSession = lib3270_session_new(""); + + main_loop = g_main_loop_new (NULL, FALSE); if(initialize()) return -1; - g_main_loop_run(loop); + g_main_loop_run(main_loop); + + lib3270_session_free(hSession); return 0; } +void pw3270_dbus_quit(PW3270Dbus *object, DBusGMethodInvocation *context) +{ + g_main_loop_quit(main_loop); + dbus_g_method_return(context,0); +} +H3270 * pw3270_dbus_get_session_handle(PW3270Dbus *object) +{ + return hSession; +} diff --git a/src/plugins/dbus/daemon.h b/src/plugins/dbus/daemon.h new file mode 100644 index 0000000..152a618 --- /dev/null +++ b/src/plugins/dbus/daemon.h @@ -0,0 +1,46 @@ +/* + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a + * aplicativos mainframe. Registro no INPI sob o nome G3270. + * + * Copyright (C) <2008> + * + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela + * Free Software Foundation. + * + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para + * obter mais detalhes. + * + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Este programa está nomeado como daemon.c e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) + * licinio@bb.com.br (Licínio Luis Branco) + * kraucer@bb.com.br (Kraucer Fernandes Mazuco) + * + * Referencias: + * + * https://live.gnome.org/DBusGlibBindings + * + */ + + #include "service.h" + +/*---[ Globals ]---------------------------------------------------------------------------------*/ + + G_GNUC_INTERNAL GMainLoop * main_loop; + + +/*---[ Prototipes ]------------------------------------------------------------------------------*/ + + G_GNUC_INTERNAL void pw3270_dbus_register_io_handlers(void); + diff --git a/src/plugins/dbus/gobject.c b/src/plugins/dbus/gobject.c index 9e995eb..378186e 100644 --- a/src/plugins/dbus/gobject.c +++ b/src/plugins/dbus/gobject.c @@ -57,9 +57,9 @@ static void pw3270_dbus_finalize(GObject *object) static void pw3270_dbus_class_init(PW3270DbusClass *klass) { - GObjectClass *object_class; - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = pw3270_dbus_finalize; + GObjectClass *object_class; + object_class = G_OBJECT_CLASS (klass); + object_class->finalize = pw3270_dbus_finalize; } static void pw3270_dbus_init(PW3270Dbus *object) @@ -76,3 +76,17 @@ void pw3270_dbus_get_revision(PW3270Dbus *object, DBusGMethodInvocation *context { dbus_g_method_return(context,PACKAGE_REVISION); } + +void pw3270_dbus_connect(PW3270Dbus *object, const gchar *uri, DBusGMethodInvocation *context) +{ + g_message("Connecting to \"%s\" by remote request",uri); + dbus_g_method_return(context,lib3270_connect(pw3270_dbus_get_session_handle(PW3270_DBUS(object)),uri,0)); +} + +void pw3270_dbus_disconnect(PW3270Dbus *object, DBusGMethodInvocation *context) +{ + g_message("Disconnecting by remote request"); + lib3270_disconnect(pw3270_dbus_get_session_handle(PW3270_DBUS(object))); + dbus_g_method_return(context,0); +} + diff --git a/src/plugins/dbus/iocallback.c b/src/plugins/dbus/iocallback.c new file mode 100644 index 0000000..cd6b4a8 --- /dev/null +++ b/src/plugins/dbus/iocallback.c @@ -0,0 +1,349 @@ +/* + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a + * aplicativos mainframe. Registro no INPI sob o nome G3270. + * + * Copyright (C) <2008> + * + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela + * Free Software Foundation. + * + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para + * obter mais detalhes. + * + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Este programa está nomeado como iocallback.c e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) + * licinio@bb.com.br (Licínio Luis Branco) + * kraucer@bb.com.br (Kraucer Fernandes Mazuco) + * + */ + +#if defined(_WIN32) /*[*/ + #include +#elif defined(__APPLE__) + #include + #include +#else + #include + #include +#endif /*]*/ + +#include +#include +#include "daemon.h" + +static int static_CallAndWait(int(*callback)(H3270 *session, void *), H3270 *session, void *parm); +static void static_RemoveSource(void *id); + +#ifdef WIN32 +static void * static_AddInput(HANDLE source, H3270 *session, void (*fn)(H3270 *session)); +static void * static_AddExcept(HANDLE source, H3270 *session, void (*fn)(H3270 *session)); +#else +static void * static_AddInput(int source, H3270 *session, void (*fn)(H3270 *session)); +static void * static_AddExcept(int source, H3270 *session, void (*fn)(H3270 *session)); +#endif // WIN32 + +static void * static_AddTimeOut(unsigned long interval_ms, H3270 *session, void (*proc)(H3270 *session)); +static void static_RemoveTimeOut(void * timer); +static int static_Sleep(H3270 *hSession, int seconds); +static int static_RunPendingEvents(H3270 *hSession, int wait); + +static gboolean IO_prepare(GSource *source, gint *timeout); +static gboolean IO_check(GSource *source); +static gboolean IO_dispatch(GSource *source, GSourceFunc callback, gpointer user_data); +static void IO_finalize(GSource *source); /* Can be NULL */ +static gboolean IO_closure(gpointer data); + +/*---[ Structs ]-------------------------------------------------------------------------------------------*/ + + typedef struct _IO_Source + { + GSource gsrc; + GPollFD poll; +#if defined(_WIN32) + HANDLE source; +#else + int source; +#endif // WIN32 + void (*fn)(H3270 *session); + H3270 *session; + } IO_Source; + + typedef struct _timer + { + unsigned char remove; + void (*fn)(H3270 *session); + H3270 *session; + } TIMER; + + static GSourceFuncs IOSources = + { + IO_prepare, + IO_check, + IO_dispatch, + IO_finalize, + IO_closure, + NULL + }; + +/*---[ Implement ]-----------------------------------------------------------------------------------------*/ + +#ifdef WIN32 +static void * AddSource(HANDLE source, H3270 *session, gushort events, void (*fn)(H3270 *session)) +#else +static void * AddSource(int source, H3270 *session, gushort events, void (*fn)(H3270 *session)) +#endif // WIN32 +{ + IO_Source *src = (IO_Source *) g_source_new(&IOSources,sizeof(IO_Source)); + + src->source = source; + src->fn = fn; + src->poll.fd = (int) source; + src->poll.events = events; + src->session = session; + + g_source_attach((GSource *) src,NULL); + g_source_add_poll((GSource *) src,&src->poll); + + return src; +} + +#ifdef WIN32 +static void * static_AddInput(HANDLE source, H3270 *session, void (*fn)(H3270 *session)) +#else +static void * static_AddInput(int source, H3270 *session, void (*fn)(H3270 *session)) +#endif // WIN32 +{ + return AddSource(source,session,G_IO_IN|G_IO_HUP|G_IO_ERR,fn); +} + +static void static_RemoveSource(void *id) +{ + if(id) + g_source_destroy((GSource *) id); +} + +#if defined(WIN32) +static void * static_AddExcept(HANDLE source, H3270 *session, void (*fn)(H3270 *session)) +{ + return 0; +} +#else +static void * static_AddExcept(int source, H3270 *session, void (*fn)(H3270 *session)) +{ + return AddSource(source,session,G_IO_HUP|G_IO_ERR,fn); +} +#endif // WIN32 + +static gboolean do_timer(TIMER *t) +{ + if(!t->remove) + t->fn(t->session); + return FALSE; +} + +static void * static_AddTimeOut(unsigned long interval, H3270 *session, void (*proc)(H3270 *session)) +{ + TIMER *t = g_malloc0(sizeof(TIMER)); + + t->fn = proc; + t->session = session; + + g_timeout_add_full(G_PRIORITY_DEFAULT, (guint) interval, (GSourceFunc) do_timer, t, g_free); + + return t; +} + +static void static_RemoveTimeOut(void * timer) +{ + ((TIMER *) timer)->remove++; +} + +static gboolean IO_prepare(GSource *source, gint *timeout) +{ + /* + * Called before all the file descriptors are polled. + * If the source can determine that it is ready here + * (without waiting for the results of the poll() call) + * it should return TRUE. + * + * It can also return a timeout_ value which should be the maximum + * timeout (in milliseconds) which should be passed to the poll() call. + * The actual timeout used will be -1 if all sources returned -1, + * or it will be the minimum of all the timeout_ values + * returned which were >= 0. + * + */ + return 0; +} + +static gboolean IO_check(GSource *source) +{ + /* + * Called after all the file descriptors are polled. + * The source should return TRUE if it is ready to be dispatched. + * Note that some time may have passed since the previous prepare + * function was called, so the source should be checked again here. + * + */ +#if defined(_WIN32) /*[*/ + + if(WaitForSingleObject(((IO_Source *) source)->source,0) == WAIT_OBJECT_0) + return TRUE; + +#else /*][*/ + + struct pollfd fds; + + memset(&fds,0,sizeof(fds)); + + fds.fd = ((IO_Source *) source)->poll.fd; + fds.events = ((IO_Source *) source)->poll.events; + + if(poll(&fds,1,0) > 0) + return TRUE; + +#endif /*]*/ + + return FALSE; +} + +static gboolean IO_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) +{ + /* + * Called to dispatch the event source, + * after it has returned TRUE in either its prepare or its check function. + * The dispatch function is passed in a callback function and data. + * The callback function may be NULL if the source was never connected + * to a callback using g_source_set_callback(). The dispatch function + * should call the callback function with user_data and whatever additional + * parameters are needed for this type of event source. + */ + ((IO_Source *) source)->fn(((IO_Source *) source)->session); + return TRUE; +} + +static void IO_finalize(GSource *source) +{ + +} + +static gboolean IO_closure(gpointer data) +{ + return 0; +} + +struct bgParameter +{ + gboolean running; + H3270 *session; + int rc; + int(*callback)(H3270 *session, void *); + void *parm; + +}; + +gpointer BgCall(struct bgParameter *p) +{ +// trace("%s starts",__FUNCTION__); + p->rc = p->callback(p->session, p->parm); + p->running = FALSE; +// trace("%s ends",__FUNCTION__); + return 0; +} + +static int static_CallAndWait(int(*callback)(H3270 *session, void *), H3270 *session, void *parm) +{ + struct bgParameter p = { TRUE, session, -1, callback, parm }; + GThread *thread; + +// trace("Starting auxiliary thread for callback %p",callback); + + p.running = TRUE; + thread = g_thread_create( (GThreadFunc) BgCall, &p, 0, NULL); + + if(!thread) + { + g_error("Can't start background thread"); + return -1; + } + + while(p.running) + g_main_context_iteration(g_main_loop_get_context(main_loop),TRUE); + + return p.rc; +} + +static int static_Sleep(H3270 *hSession, int seconds) +{ + time_t end = time(0) + seconds; + + while(time(0) < end) + g_main_iteration(TRUE); + + return 0; +} + +static int static_RunPendingEvents(H3270 *hSession, int wait) +{ + GMainContext *context = g_main_loop_get_context(main_loop); + int rc = 0; + while(g_main_context_pending(context)) + { + rc = 1; + g_main_context_iteration(context,FALSE); + } + + if(wait) + g_main_context_iteration(context,TRUE); + + return rc; +} + +static void beep(H3270 *session) +{ +} + +void pw3270_dbus_register_io_handlers(void) +{ + static const struct lib3270_callbacks hdl = + { + sizeof(struct lib3270_callbacks), + + static_AddTimeOut, + static_RemoveTimeOut, + + static_AddInput, + static_RemoveSource, + + static_AddExcept, + +#ifdef G_THREADS_ENABLED + static_CallAndWait, +#else + NULL, +#endif + + static_Sleep, + static_RunPendingEvents, + beep + + }; + + if(lib3270_register_handlers(&hdl)) + { + g_error("%s","Can't set lib3270 I/O handlers"); + } + +} diff --git a/src/plugins/dbus/pw3270dbus.cbp b/src/plugins/dbus/pw3270dbus.cbp index b1e0614..eff236b 100644 --- a/src/plugins/dbus/pw3270dbus.cbp +++ b/src/plugins/dbus/pw3270dbus.cbp @@ -42,6 +42,9 @@ + + - - + diff --git a/src/plugins/dbus/pw3270dbus.xml b/src/plugins/dbus/pw3270dbus.xml index 5de6d0c..068caaa 100644 --- a/src/plugins/dbus/pw3270dbus.xml +++ b/src/plugins/dbus/pw3270dbus.xml @@ -5,5 +5,18 @@ + + + + + + + + + + + + + diff --git a/src/plugins/dbus/service.h b/src/plugins/dbus/service.h index 934e086..334f443 100644 --- a/src/plugins/dbus/service.h +++ b/src/plugins/dbus/service.h @@ -1,7 +1,8 @@ #ifndef _PW3270_DBUS_SERVICE_H - #define _PW3270_DBUS_SERVICE_H + #define _PW3270_DBUS_SERVICE_H 1 + #include #include #include #include @@ -36,6 +37,10 @@ GType pw3270_dbus_get_type (void); void pw3270_dbus_get_revision(PW3270Dbus *object, DBusGMethodInvocation *context); + void pw3270_dbus_quit(PW3270Dbus *object, DBusGMethodInvocation *context); + void pw3270_dbus_connect(PW3270Dbus *object, const gchar *uri, DBusGMethodInvocation *context); + void pw3270_dbus_disconnect(PW3270Dbus *object, DBusGMethodInvocation *context); + H3270 * pw3270_dbus_get_session_handle(PW3270Dbus *object); G_END_DECLS diff --git a/src/plugins/dbus/test.sh b/src/plugins/dbus/test.sh index 564b808..26acfe8 100755 --- a/src/plugins/dbus/test.sh +++ b/src/plugins/dbus/test.sh @@ -1,3 +1,26 @@ #!/bin/bash -dbus-send --session --print-reply --dest=br.com.bb.pw3270 /br/com/bb/pw3270 br.com.bb.pw3270.getRevision + +case $1 in + + revision) + dbus-send --session --print-reply --dest=br.com.bb.pw3270 /br/com/bb/pw3270 br.com.bb.pw3270.getRevision + ;; + + connect) + dbus-send --session --print-reply --dest=br.com.bb.pw3270 /br/com/bb/pw3270 br.com.bb.pw3270.connect string:$2 + ;; + + disconnect) + dbus-send --session --print-reply --dest=br.com.bb.pw3270 /br/com/bb/pw3270 br.com.bb.pw3270.disconnect + ;; + + quit) + dbus-send --session --print-reply --dest=br.com.bb.pw3270 /br/com/bb/pw3270 br.com.bb.pw3270.quit + ;; + + *) + dbus-send --session --print-reply --dest=br.com.bb.pw3270 /br/com/bb/pw3270 br.com.bb.pw3270.getRevision + ;; + +esac -- libgit2 0.21.2