From 46f636afe5ad22567351391155da76f8a2e00bc6 Mon Sep 17 00:00:00 2001
From: Manuel Traut <manut@linutronix.de>
Date: Tue, 23 Jun 2009 21:31:19 +0100
Subject: middleware: added dbus example

Signed-off-by: Manuel Traut <manut@linutronix.de>
---
 frameworks/middleware/handout_middleware.tex | 191 ++++++++++++++++++++++++++-
 1 file changed, 190 insertions(+), 1 deletion(-)

(limited to 'frameworks/middleware/handout_middleware.tex')

diff --git a/frameworks/middleware/handout_middleware.tex b/frameworks/middleware/handout_middleware.tex
index c6e3145..39967ba 100644
--- a/frameworks/middleware/handout_middleware.tex
+++ b/frameworks/middleware/handout_middleware.tex
@@ -4,6 +4,26 @@
 \usepackage{lxheaders}
 \usepackage{lxextras}
 
+\lstset{
+	language=C++,
+	numbers=left,
+	stepnumber=1,
+	numbersep=5pt,
+	numberstyle=\tiny,
+	breaklines=true,
+	breakautoindent=true,
+	postbreak=\space,
+	tabsize=2,
+	basicstyle=\ttfamily\footnotesize,
+	showspaces=false,
+	showstringspaces=false,
+	extendedchars=true,
+	%backgroundcolor=\color{lbcolor},
+	keywordstyle=\bf ,
+	commentstyle=\color{green},
+	stringstyle=\color{red}
+}
+
 \begin{document}
 
 \section*{Middleware}
@@ -225,9 +245,178 @@ On the other hand, the framework is complex and difficult to learn.
 
 \subsection*{Exercises}
 
+An application should be created, to send a message to the 'server' with a
+variable payload, that the time needed for the call / return of the call can be
+measured in the client.
+
+The above described application will be implemented with ACE/TAO RTCORBA and
+the D-Bus glib bindings:
+
 \subsubsection*{ACE/TAO RTCORBA ping-pong}
 
-\subsubsection*{D-Bus GLib bindings ping-pong}
+\subsubsection*{D-Bus glib bindings ping-pong}
+
+First \cmd{ping-server.c} will be created to host the ping object:
+
+\begin{lstlisting}
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <time.h>
+
+static DBusHandlerResult signal_filter
+		(DBusConnection *connection, DBusMessage *message, void *user_data);
+
+int main(int argc, char **argv)
+{
+	GMainLoop *loop;
+	DBusConnection *bus;
+	DBusError error;
+
+	loop = g_main_loop_new (NULL, FALSE);
+	dbus_error_init (&error);
+	bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
+
+	if (!bus) {
+		g_warning ("Failed to connect to the D-BUS daemon: %s", error.message);
+		dbus_error_free (&error);
+		return 1;
+	}
+
+	dbus_connection_setup_with_g_main (bus, NULL);
+	/* listening to messages from all objects as no path is specified */
+	dbus_bus_add_match (bus, "type='signal',interface='de.linutronix.Ping'",
+		&error);
+	dbus_connection_add_filter (bus, signal_filter, loop, NULL);
+	g_main_loop_run (loop);
+
+	return 0;
+}
+
+static DBusHandlerResult signal_filter
+		(DBusConnection *connection, DBusMessage *message, void *user_data)
+{
+	/* User data is the event loop we are running in */
+	GMainLoop *loop = user_data;
+
+	/* A signal from the bus saying we are about to be disconnected */
+	if (dbus_message_is_signal(message, "org.freedesktop.Local",
+		"Disconnected"))
+	{
+		/* Tell the main loop to quit */
+		g_main_loop_quit (loop);
+		/* We have handled this message, don't pass it on */
+		return DBUS_HANDLER_RESULT_HANDLED;
+	}
+	else if (dbus_message_is_signal (message, "de.linutronix.Ping", "Ping"))
+	{
+		DBusError error;
+		char *s;
+
+		dbus_error_init (&error);
+
+		if (dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &s,
+			DBUS_TYPE_INVALID))
+		{
+			struct timespec rx_time;
+			clock_gettime(CLOCK_MONOTONIC, &rx_time);
+			g_print("ping received: %s - %d:%d\n", s, rx_time.tv_sec,
+				rx_time.tv_nsec/1000);
+			// dbus_free (s);
+		} else {
+			g_print("ping received, but error getting message: %s\n", error.message);
+			dbus_error_free (&error);
+		}
+		return DBUS_HANDLER_RESULT_HANDLED;
+	}
+	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+\end{lstlisting}
+
+The server application will be compiled with the following command:
+
+\cmd{gcc -o server `pkg-config --libs --cflags dbus-glib-1` -lrt ping-server.c}
+
+Next a file \cmd{ping-client.c} with the following content is created:
+
+\begin{lstlisting}
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <time.h>
+
+static gboolean send_ping (DBusConnection *bus);
+static const char *v_STRING;
+
+int main (int argc, char **argv)
+{
+	GMainLoop *loop;
+	DBusConnection *bus;
+	DBusError error;
+
+	if (argc > 1)
+		v_STRING = argv[1];
+	else
+		v_STRING = "no arg given";
+
+	/* Create a new event loop to run in */
+	loop = g_main_loop_new (NULL, FALSE);
+
+	/* Get a connection to the session bus */
+	dbus_error_init (&error);
+	bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
+	if (!bus) {
+		g_warning ("Failed to connect to the D-BUS daemon: %s", error.message);
+		dbus_error_free (&error);
+		return 1;
+	}
+
+	/* Set up this connection to work in a GLib event loop */
+	dbus_connection_setup_with_g_main (bus, NULL);
+	/* Every second call send_ping() with the bus as an argument*/
+	g_timeout_add (1000, (GSourceFunc)send_ping, bus);
+
+	/* Start the event loop */
+	g_main_loop_run (loop);
+	return 0;
+}
+
+static gboolean send_ping (DBusConnection *bus)
+{
+	DBusMessage *message;
+	struct timespec tx_time;
+	struct timespec done_time;
+
+	message = dbus_message_new_signal ("/de/linutronix/Ping",
+                                   "de.linutronix.Ping", "Ping");
+	/* Append the string to the signal */
+	dbus_message_append_args (message,
+														DBUS_TYPE_STRING, &v_STRING,
+														DBUS_TYPE_INVALID);
+	clock_gettime(CLOCK_MONOTONIC, &tx_time);
+	/* Send the signal */
+	dbus_connection_send (bus, message, NULL);
+	clock_gettime(CLOCK_MONOTONIC, &done_time);
+	g_print("%d:%d\n%d:%d\n\n", tx_time.tv_sec, tx_time.tv_nsec/1000,
+		done_time.tv_sec, done_time.tv_nsec/1000);
+	/* Free the signal now we have finished with it */
+	dbus_message_unref (message);
+	/* Return TRUE to tell the event loop we want to be called again */
+	return TRUE;
+}
+\end{lstlisting}
+
+The client application will be compiled with the following command:
+
+\cmd{gcc -o client `pkg-config --libs --cflags dbus-glib-1` -lrt ping-client.c}
+
+To run the applications start them with:
+\begin{itemize}
+\item \cmd{./client WhatEverYouWantAsPayLoad}
+\item \cmd{./server}
+\end{itemize}
+
+The order, which application is started first doesn't matter. Take care that
+the \cmd{dbus-daemon} is running.
 
 \begin{thebibliography}{9}%use this if you have <=9 bib refs
 %\begin{thebibliography}{99}%use this if you have >9 bib refs
-- 
cgit v1.2.3

