[prev in list] [next in list] [prev in thread] [next in thread]
List: freedesktop-dbus
Subject: Dbus application consumes full cache memory , during Tx and Rx of message using Dbus API- Memory lea
From: deepak jewargi <djewargi () gmail ! com>
Date: 2023-08-14 10:58:25
Message-ID: CABLtkZcx-Vq-POH255zh97Z3jXreSYCqyDVDt2mH6dNhf0HVCA () mail ! gmail ! com
[Download RAW message or body]
[Attachment #2 (multipart/related)]
[Attachment #4 (multipart/alternative)]
Hi All,
I have implemented a dbus application using dbus-1 API's on the linux
platform.
Facing issues ,when we run continuously in a loop. dbsu Tx (public)and
dbus Rx (subscribe) runs out of cache memory and both Tx and Rx getting
terminated attached source and header files,
[image: image.png]
*1. Publish functions : Tx dbus application *
/*
* method: method name
* payload: data that needs to be sent/published.
* payloadlen: length of payload in bytes.
* return: 0 on success, -1 on failure.
*/
/*
* method: method name
* payload: data that needs to be sent/published.
* payloadlen: length of payload in bytes.
* return: 0 on success, -1 on failure.
*/
int dbus_client_publish (char *method, void *payload, int payloadlen)
{
DBusMessage *msg;
DBusMessageIter args;
DBusMessageIter subiter;
DBusError err;
int returnValue = -1;
int SignalRetryCount = 0;
int SendRetryCount = 0;
int maxRetries = 3;
int successConnect = 0;
int successSend = 0;
char *pload = (char*) payload;
if(pload != NULL)
{
// initialize the errors
dbus_error_init (&err);
while (SignalRetryCount < maxRetries && !successConnect)
{
// create a new method call and check for errors
msg = dbus_message_new_signal (DBUS_OBJECT_NAME, // object name of the
signal
DBUS_INTERFACE_NAME, // interface name of the signal
method); // name of the signal
if(NULL == msg)
{
dbus_error_free (&err);
SignalRetryCount++;
}
else
{
// append arguments
dbus_message_iter_init_append (msg, &args);
// For appending args, doc says to use the following 3 for container types.
// We can view the cmd buffer as a char buffer and send
dbus_message_iter_open_container (&args, DBUS_TYPE_ARRAY, "y", &subiter);
dbus_message_iter_append_fixed_array (&subiter, DBUS_TYPE_BYTE, &pload,
payloadlen);
dbus_message_iter_2. Rx application with multiple functions
close_container (&args, &subiter);
// We probably don't need a reply
flogv("dbustest.log","%s:%d dbus_connection_send called",__func__,__LINE__);
while (SendRetryCount < maxRetries && !successSend)
{
if(!dbus_connection_send (txconn, msg, NULL))
{
flogd("dbustest.log","%s:%d Out Of Memory!",__func__,__LINE__);
SendRetryCount++;
}
else
{
successConnect = 1;
successSend = 1;
returnValue = 0;
break;
}
}
}
}
dbus_connection_flush (txconn);
// free message
dbus_message_unref (msg);
dbus_error_free (&err);
//flogd("dbustest.log","%s:%d Exit (no errors)",__func__,__LINE__);
}
// print ( dbus_client_publish, returnValue)
return returnValue;
}
*2. Rx application - with multiple functions *
/* This API subscribes for a particular busname/interface/method. The
callback would
* be called once the subscribed information is available.
*Note: subscribe = listen => server bus name (e.g.,).
*
* method: method name you want to listen to.
* cb: callback to be called once the subscribed information is available.
* return: 0 on success, -1 on failure.
*/
int dbus_client_subscribe (int num_pairs, ...)
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
int i;
va_list vargs;
rx_thread_args_t *args;
if (num_pairs > 32)
return -1;
args = (rx_thread_args_t *) malloc (sizeof(rx_thread_args_t));
if (args == NULL)
return -1;
args->num_pairs = num_pairs;
va_start(vargs, num_pairs);
for (i = 0; i < num_pairs; i++)
{
char *m = va_arg(vargs, char *);
sprintf (args->mthod_cb[i].method, "%s", m);
args->mthod_cb[i].cb = va_arg(vargs, void *);
}
va_end(vargs);
if (pthread_create (&dbus_client_rx_thread, NULL,
dbus_client_receive_thread, (void *)args) != 0)
{
floge("dbustest.log","%s:%d Client Error: Rx Thread creation failed; errno
= %d (%s)",__func__,__LINE__, errno, strerror(errno));
return -1;
}
// free(args);
flogd("dbustest.log","%s:%d exit",__func__,__LINE__);
return 0;
}
* Receive thread */
static void *dbus_client_receive_thread (void *arg)
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
rx_thread_args_t *args = (rx_thread_args_t *) arg;
DBusError err;
int rc;
dbus_ctx_t *lctx;
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
ev_base = event_base_new ();
// initialise the error
dbus_error_init(&err);
lctx = dbus_init(ev_base);
lctx->args = args;
rc = event_base_dispatch(ev_base);
if (rc == -1)
{
flogd("dbustest.log","%s:%d %s: Exit (rc = %d)\n",__func__,__LINE__, rc);
}
else
{
dbus_error_free(&err);
}
return 0;
}
static dbus_ctx_t *dbus_init(struct event_base *eb)
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
DBusConnection *conn = rxconn;
DBusError err;
dbus_ctx_t *ctx = &gctx;
char match_buffer[255];
int len1;
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
dbus_connection_set_exit_on_disconnect(conn, FALSE);
ctx->conn = conn;
ctx->evbase = eb;
event_assign(&ctx->dispatch_ev, eb, -1, EV_TIMEOUT, dispatch, ctx);
if (!dbus_connection_set_watch_functions(conn, add_watch, remove_watch,
toggle_watch, ctx, NULL)) {
flogd("dbustest.log","%s:%ddbus_connection_set_watch_functions() failed"
,__func__,__LINE__);
goto out;
}
dbus_connection_set_dispatch_status_function(conn, handle_dispatch_status,
ctx, NULL);
// add a rule for which messages we want to see
len1 = strlen("type='signal',interface='");
sprintf (match_buffer, "%s", "type='signal',interface='");
sprintf (match_buffer+len1, "%s", DBUS_INTERFACE_NAME);
sprintf(match_buffer+len1+strlen(DBUS_INTERFACE_NAME), "%s", "'");
dbus_error_init(&err);
dbus_bus_add_match(conn, match_buffer, &err); // see signals from the given
interface
dbus_connection_flush(conn);
if (dbus_error_is_set(&err)) {
flogd("dbustest.log","%s:%d Match Error (%s)",__func__,__LINE__, err.message
);
dbus_error_free(&err);
goto out;
}
dbus_error_free(&err);
if (dbus_connection_register_object_path(conn, DBUS_OBJECT_NAME,
&dbus_vtable,
ctx) != TRUE) {
flogd("dbustest.log","%s:%d failed to register object path\n"
,__func__,__LINE__);
goto out;
}
dbus_connection_unref(conn);
return ctx;
out:
if (conn) {
dbus_connection_close(conn);
dbus_connection_unref(conn);
}
flogd("dbustest.log","%s:%d Exit",__func__,__LINE__);
return NULL;
}
Please suggest to me, Is any dbus API to avoid the above application
consuming lots of system cache memory ?
Regards,
Deepak Jewargi
-------------------------------------------------------------------------------------------------------------------------------------------
[Attachment #7 (text/html)]
<div dir="ltr">Hi All, <div><br></div><div><br></div><div>I have implemented a dbus \
application using dbus-1 API's on the linux platform. \
</div><div><br></div><div>Facing issues ,when we run continuously in a loop. dbsu Tx \
(public)and dbus Rx (subscribe) runs out of cache memory and both Tx and Rx \
getting terminated attached source and header files, </div><div> \
</div><div><img src="cid:ii_llaqjvtf1" alt="image.png" width="562" \
height="315"><br></div><div><br></div><div><br></div><div><br></div><div><b>1. \
Publish functions : Tx dbus application </b></div><div><br></div><div \
style="padding:0px 0px 0px 2px"><div \
style="color:rgb(0,0,0);font-family:monospace;font-size:10pt;white-space:pre"><p \
style="margin:0px"><span style="color:rgb(63,127,95)">/*</span></p><p \
style="margin:0px"><span style="color:rgb(63,127,95)"> * method: method \
name</span></p><p style="margin:0px"><span style="color:rgb(63,127,95)"> * \
</span><span style="color:rgb(63,127,95);text-decoration-line:underline;text-decoration-style:wavy;text-decoration-color:rgb(255,128,64)">payload</span><span \
style="color:rgb(63,127,95)">: data that needs to be sent/published.</span></p><p \
style="margin:0px"><span style="color:rgb(63,127,95)"> * </span><span \
style="color:rgb(63,127,95);text-decoration-line:underline;text-decoration-style:wavy;text-decoration-color:rgb(255,128,64)">payloadlen</span><span \
style="color:rgb(63,127,95)">: length of </span><span \
style="color:rgb(63,127,95);text-decoration-line:underline;text-decoration-style:wavy;text-decoration-color:rgb(255,128,64)">payload</span><span \
style="color:rgb(63,127,95)"> in bytes.</span></p><p style="margin:0px"><span \
style="color:rgb(63,127,95)"> * return: 0 on success, -1 on failure.</span></p><p \
style="margin:0px"><span style="color:rgb(63,127,95)"> */</span></p><p \
style="margin:0px"><span style="color:rgb(63,127,95)">/*</span></p><p \
style="margin:0px"><span style="color:rgb(63,127,95)"> * method: method \
name</span></p><p style="margin:0px"><span style="color:rgb(63,127,95)"> * \
</span><span style="color:rgb(63,127,95);text-decoration-line:underline;text-decoration-style:wavy;text-decoration-color:rgb(255,128,64)">payload</span><span \
style="color:rgb(63,127,95)">: data that needs to be sent/published.</span></p><p \
style="margin:0px"><span style="color:rgb(63,127,95)"> * </span><span \
style="color:rgb(63,127,95);text-decoration-line:underline;text-decoration-style:wavy;text-decoration-color:rgb(255,128,64)">payloadlen</span><span \
style="color:rgb(63,127,95)">: length of </span><span \
style="color:rgb(63,127,95);text-decoration-line:underline;text-decoration-style:wavy;text-decoration-color:rgb(255,128,64)">payload</span><span \
style="color:rgb(63,127,95)"> in bytes.</span></p><p style="margin:0px"><span \
style="color:rgb(63,127,95)"> * return: 0 on success, -1 on failure.</span></p><p \
style="margin:0px"><span style="color:rgb(63,127,95)"> */</span></p><p \
style="margin:0px"><span style="color:rgb(127,0,85);font-weight:bold">int</span> \
<span style="font-weight:bold">dbus_client_publish</span> (<span \
style="color:rgb(127,0,85);font-weight:bold">char</span> *method, <span \
style="color:rgb(127,0,85);font-weight:bold">void</span> *payload, <span \
style="color:rgb(127,0,85);font-weight:bold">int</span> payloadlen)</p><p \
style="margin:0px">{</p><p style="margin:0px"> <span \
style="color:rgb(0,80,50)">DBusMessage</span> *msg;</p><p style="margin:0px"> <span \
style="color:rgb(0,80,50)">DBusMessageIter</span> args;</p><p style="margin:0px"> \
<span style="color:rgb(0,80,50)">DBusMessageIter</span> subiter;</p><p \
style="margin:0px"> <span style="color:rgb(0,80,50)">DBusError</span> err;</p><p \
style="margin:0px"><br></p><p style="margin:0px"> <span \
style="color:rgb(127,0,85);font-weight:bold">int</span> returnValue = -1;</p><p \
style="margin:0px"> <span style="color:rgb(127,0,85);font-weight:bold">int</span> \
SignalRetryCount = 0;</p><p style="margin:0px"> <span \
style="color:rgb(127,0,85);font-weight:bold">int</span> SendRetryCount = 0;</p><p \
style="margin:0px"> <span style="color:rgb(127,0,85);font-weight:bold">int</span> \
maxRetries = 3;</p><p style="margin:0px"> <span \
style="color:rgb(127,0,85);font-weight:bold">int</span> successConnect = 0;</p><p \
style="margin:0px"> <span style="color:rgb(127,0,85);font-weight:bold">int</span> \
successSend = 0;</p><p style="margin:0px"><br></p><p style="margin:0px"> <span \
style="color:rgb(127,0,85);font-weight:bold">char</span> *pload = (<span \
style="color:rgb(127,0,85);font-weight:bold">char</span>*) payload;</p><p \
style="margin:0px"><br></p><p style="margin:0px"> <span \
style="color:rgb(127,0,85);font-weight:bold">if</span>(pload != NULL)</p><p \
style="margin:0px"> {</p><p style="margin:0px"> <span \
style="color:rgb(63,127,95)">// initialize the errors</span></p><p \
style="margin:0px"> <span \
style="color:rgb(100,40,128);font-weight:bold">dbus_error_init</span> \
(&err);</p><p style="margin:0px"><br></p><p style="margin:0px"> <span \
style="color:rgb(127,0,85);font-weight:bold">while</span> (SignalRetryCount < \
maxRetries && !successConnect)</p><p style="margin:0px"> {</p><p \
style="margin:0px"><br></p><p style="margin:0px"> <span \
style="color:rgb(63,127,95)">// create a new method call and check for \
errors</span></p><p style="margin:0px"> msg = <span \
style="color:rgb(100,40,128);font-weight:bold">dbus_message_new_signal</span> \
(DBUS_OBJECT_NAME, <span style="color:rgb(63,127,95)">// object name of the \
signal</span></p><p style="margin:0px"> \
DBUS_INTERFACE_NAME, <span style="color:rgb(63,127,95)">// interface name of the \
signal</span></p><p style="margin:0px"> \
method); <span style="color:rgb(63,127,95)">// name of the signal</span></p><p \
style="margin:0px"><br></p><p style="margin:0px"> <span \
style="color:rgb(127,0,85);font-weight:bold">if</span>(NULL == msg)</p><p \
style="margin:0px"> {</p><p style="margin:0px"> <span \
style="color:rgb(100,40,128);font-weight:bold">dbus_error_free</span> \
(&err);</p><p style="margin:0px"><br></p><p style="margin:0px"> \
SignalRetryCount++;</p><p style="margin:0px"> }</p><p style="margin:0px"> \
<span style="color:rgb(127,0,85);font-weight:bold">else</span></p><p \
style="margin:0px"> {</p><p style="margin:0px"> <span \
style="color:rgb(63,127,95)">// append arguments</span></p><p style="margin:0px"> \
<span style="color:rgb(100,40,128);font-weight:bold">dbus_message_iter_init_append</span> \
(msg, &args);</p><p style="margin:0px"><br></p><p style="margin:0px"> \
<span style="color:rgb(63,127,95)">// For appending </span><span \
style="color:rgb(63,127,95);text-decoration-line:underline;text-decoration-style:wavy;text-decoration-color:rgb(255,128,64)">args</span><span \
style="color:rgb(63,127,95)">, doc says to use the following 3 for container \
types.</span></p><p style="margin:0px"> <span \
style="color:rgb(63,127,95)">// We can view the </span><span \
style="color:rgb(63,127,95);text-decoration-line:underline;text-decoration-style:wavy;text-decoration-color:rgb(255,128,64)">cmd</span><span \
style="color:rgb(63,127,95)"> buffer as a char buffer and send</span></p><p \
style="margin:0px"> <span \
style="color:rgb(100,40,128);font-weight:bold">dbus_message_iter_open_container</span> \
(&args, DBUS_TYPE_ARRAY, <span style="color:rgb(42,0,255)">"y"</span>, \
&subiter);</p><p style="margin:0px"> <span \
style="color:rgb(100,40,128);font-weight:bold">dbus_message_iter_append_fixed_array</span> \
(&subiter, DBUS_TYPE_BYTE, &pload, payloadlen);</p><p \
style="margin:0px"><br></p><p style="margin:0px"> <span \
style="color:rgb(100,40,128);font-weight:bold">dbus_message_iter_</span><span \
style="font-size:10pt">2. Rx application with multiple functions </span></p><p \
style="margin:0px"><span \
style="color:rgb(100,40,128);font-weight:bold">close_container</span> (&args, \
&subiter);</p><p style="margin:0px"><br></p><p style="margin:0px"> \
<span style="color:rgb(63,127,95)">// We probably don't need a reply</span></p><p \
style="margin:0px"> flogv(<span \
style="color:rgb(42,0,255)">"dbustest.log"</span>,<span \
style="color:rgb(42,0,255)">"%s:%d dbus_connection_send \
called"</span>,__func__,__LINE__);</p><p style="margin:0px"><br></p><p \
style="margin:0px"> <span \
style="color:rgb(127,0,85);font-weight:bold">while</span> (SendRetryCount < \
maxRetries && !successSend)</p><p style="margin:0px"> {</p><p \
style="margin:0px"> <span \
style="color:rgb(127,0,85);font-weight:bold">if</span>(!<span \
style="color:rgb(100,40,128);font-weight:bold">dbus_connection_send</span> (txconn, \
msg, NULL))</p><p style="margin:0px"> {</p><p style="margin:0px"> \
flogd(<span style="color:rgb(42,0,255)">"dbustest.log"</span>,<span \
style="color:rgb(42,0,255)">"%s:%d Out Of \
Memory!"</span>,__func__,__LINE__);</p><p style="margin:0px"> \
SendRetryCount++;</p><p style="margin:0px"> }</p><p style="margin:0px"> \
<span style="color:rgb(127,0,85);font-weight:bold">else</span></p><p \
style="margin:0px"> {</p><p style="margin:0px"> \
successConnect = 1;</p><p style="margin:0px"> successSend = 1;</p><p \
style="margin:0px"> returnValue = 0;</p><p style="margin:0px"> \
<span style="color:rgb(127,0,85);font-weight:bold">break</span>;</p><p \
style="margin:0px"> }</p><p style="margin:0px"> }</p><p \
style="margin:0px"> }</p><p style="margin:0px"> }</p><p \
style="margin:0px"><br></p><p style="margin:0px"> <span \
style="color:rgb(100,40,128);font-weight:bold">dbus_connection_flush</span> \
(txconn);</p><p style="margin:0px"><br></p><p style="margin:0px"> <span \
style="color:rgb(63,127,95)">// free message</span></p><p style="margin:0px"> \
<span style="color:rgb(100,40,128);font-weight:bold">dbus_message_unref</span> \
(msg);</p><p style="margin:0px"> <span \
style="color:rgb(100,40,128);font-weight:bold">dbus_error_free</span> \
(&err);</p><p style="margin:0px"><br></p><p style="margin:0px"> <span \
style="color:rgb(63,127,95)">//</span><span \
style="color:rgb(63,127,95);text-decoration-line:underline;text-decoration-style:wavy;text-decoration-color:rgb(255,128,64)">flogd</span><span \
style="color:rgb(63,127,95)">("dbustest.log","%s:%d Exit (no \
errors)",__</span><span \
style="color:rgb(63,127,95);text-decoration-line:underline;text-decoration-style:wavy;text-decoration-color:rgb(255,128,64)">func</span><span \
style="color:rgb(63,127,95)">__,__LINE__);</span></p><p style="margin:0px"> }</p><p \
style="margin:0px"><br></p><p style="margin:0px"> <span \
style="color:rgb(63,127,95)">// print ( dbus_client_publish, \
returnValue)</span></p><p style="margin:0px"><br></p><p style="margin:0px"> <span \
style="color:rgb(127,0,85);font-weight:bold">return</span> returnValue;</p><p \
style="margin:0px">}</p><p style="margin:0px"></p></div></div><div> \
</div><div><br></div><div> </div><div><br></div><div><b>2. Rx application - with \
multiple functions </b></div><div><br></div><div><br></div><div><div \
style="padding:0px 0px 0px 2px"><div \
style="color:rgb(0,0,0);font-family:monospace;font-size:10pt;white-space:pre"><p \
style="margin:0px"><span style="color:rgb(63,127,95)">/* This API subscribes for a \
particular </span><span \
style="color:rgb(63,127,95);text-decoration-line:underline;text-decoration-style:wavy;text-decoration-color:rgb(255,128,64)">busname</span><span \
style="color:rgb(63,127,95)">/interface/method. The callback would</span></p><p \
style="margin:0px"><span style="color:rgb(63,127,95)"> * be called once the \
subscribed information is available.</span></p><p style="margin:0px"><span \
style="color:rgb(63,127,95)"> *Note: subscribe = listen => server bus name \
(e.g.,).</span></p><p style="margin:0px"><span style="color:rgb(63,127,95)"> \
*</span></p><p style="margin:0px"><span style="color:rgb(63,127,95)"> * method: \
method name you want to listen to.</span></p><p style="margin:0px"><span \
style="color:rgb(63,127,95)"> * </span><span \
style="color:rgb(63,127,95);text-decoration-line:underline;text-decoration-style:wavy;text-decoration-color:rgb(255,128,64)">cb</span><span \
style="color:rgb(63,127,95)">: callback to be called once the subscribed \
information is available.</span></p><p style="margin:0px"><span \
style="color:rgb(63,127,95)"> * return: 0 on success, -1 on failure.</span></p><p \
style="margin:0px"><span style="color:rgb(63,127,95)"> */</span></p><p \
style="margin:0px"><span style="color:rgb(127,0,85);font-weight:bold">int</span> \
<span style="background-color:rgb(212,212,212);font-weight:bold">dbus_client_subscribe</span> \
(<span style="color:rgb(127,0,85);font-weight:bold">int</span> num_pairs, ...)</p><p \
style="margin:0px">{</p><p style="margin:0px"> flogd(<span \
style="color:rgb(42,0,255)">"dbustest.log"</span>,<span \
style="color:rgb(42,0,255)">"%s:%d Entry"</span>,__func__,__LINE__);</p><p \
style="margin:0px"> <span style="color:rgb(127,0,85);font-weight:bold">int</span> \
i;</p><p style="margin:0px"> <span style="color:rgb(0,80,50)">va_list</span> \
vargs;</p><p style="margin:0px"> <span \
style="color:rgb(0,80,50)">rx_thread_args_t</span> *args;</p><p \
style="margin:0px"><br></p><p style="margin:0px"> <span \
style="color:rgb(127,0,85);font-weight:bold">if</span> (num_pairs > 32)</p><p \
style="margin:0px"> <span \
style="color:rgb(127,0,85);font-weight:bold">return</span> -1;</p><p \
style="margin:0px"><br></p><p style="margin:0px"> args = (<span \
style="color:rgb(0,80,50)">rx_thread_args_t</span> *) <span \
style="color:rgb(100,40,128);font-weight:bold">malloc</span> (<span \
style="color:rgb(127,0,85);font-weight:bold">sizeof</span>(<span \
style="color:rgb(0,80,50)">rx_thread_args_t</span>));</p><p style="margin:0px"> \
<span style="color:rgb(127,0,85);font-weight:bold">if</span> (args == NULL)</p><p \
style="margin:0px"> <span \
style="color:rgb(127,0,85);font-weight:bold">return</span> -1;</p><p \
style="margin:0px"><br></p><p style="margin:0px"> args-><span \
style="color:rgb(0,0,192)">num_pairs</span> = num_pairs;</p><p style="margin:0px"> \
va_start(vargs, num_pairs);</p><p style="margin:0px"> <span \
style="color:rgb(127,0,85);font-weight:bold">for</span> (i = 0; i < num_pairs; \
i++)</p><p style="margin:0px"> {</p><p style="margin:0px"> <span \
style="color:rgb(127,0,85);font-weight:bold">char</span> *m = va_arg(vargs, <span \
style="color:rgb(127,0,85);font-weight:bold">char</span> *);</p><p \
style="margin:0px"> <span \
style="color:rgb(100,40,128);font-weight:bold">sprintf</span> (args-><span \
style="color:rgb(0,0,192)">mthod_cb</span>[i].<span \
style="color:rgb(0,0,192)">method</span>, <span \
style="color:rgb(42,0,255)">"%s"</span>, m);</p><p style="margin:0px"> \
args-><span style="color:rgb(0,0,192)">mthod_cb</span>[i].<span \
style="color:rgb(0,0,192)">cb</span> = va_arg(vargs, <span \
["image.png" (image/png)]
["dbus-client.c" (text/x-csrc)]
/*
*----------------------------------------------------------------------
* Dbus-client.c
*
* Source file for dbus interface
*
*
* (C)2023 Ametek Process Instruments
*
* The copyright notice above does not evidence any
* actual or intended publication of such source code.
*
*----------------------------------------------------------------------
*/
/*
*----------------------------------------------------------------------
* File: Dbus-client.c
* Created by: Deepak Jewargi
*----------------------------------------------------------------------
*/
#define LOG_TAG "DBUS"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <dbus/dbus.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <ctype.h>
//#include <dbus.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <event2/event.h>
#include <event2/event_struct.h>
//#include "btrkr-log-util.h"
#include "logmodule.h"
#include "dbus-client.h"
#define DBUS_OBJECT_NAME "/open/ametekdbus/object"
#define DBUS_INTERFACE_NAME "com.ametek.data"
#define DBUS_REMOTE_APP_BUS_NAME "proc.rxbus.%s"
#define DEBUG printf("%s:%d\n",__func__,__LINE__);
// macro to convert milliseconds to nano seconds
#define MILLI_SEC 500 // 500 milli seconds
#define MS_TO_NS(milliseconds) (milliseconds * (1000 * 1000))
typedef struct
{
char method[255];
void *cb;
} method_cb_pair_t;
typedef struct
{
method_cb_pair_t mthod_cb[32];
int num_pairs;
} rx_thread_args_t;
typedef struct dbus_ctx
{
DBusConnection *conn;
struct event_base *evbase;
struct event dispatch_ev;
void *extra; // watch
void *extra_t; // timeout
rx_thread_args_t *args;
} dbus_ctx_t;
static pthread_mutex_t init_dbus_mutex = PTHREAD_MUTEX_INITIALIZER;
static bool init_dbus_flag = false;
static DBusConnection *txconn, *rxconn;
static pthread_t dbus_client_rx_thread;
static char txbusname[255] = "proc.txbus.";
static char rxbusname[255] = "proc.rxbus.";
static struct event_base *ev_base = NULL;
static dbus_ctx_t gctx;
typedef void (*callback)(void *data, size_t len);
typedef method_reply_t* (*method_callback)(void *data, size_t len);
/**
* Use this function to initialize the dbus method reply buffer.
* no need to call de-init.
* @param len required buffer legth in bytes.
* @return -ve error code on failure and method_reply on success.
*/
/*method_reply_t *dbus_client_init_reply_buff(int len)
{
method_reply_t *buff= (method_reply_t*)malloc(sizeof(method_reply_t));
buff->data= (char *)calloc(len,1);
buff->len=len;
return buff;
}*/
/**
* Wrapper to call a method of a remote process.This function is a blocking call.
* the remote method must respond with a return value.
* @param appname name of the remote process bus name.
* @param method remote method to be invoked
* @param payload argument to be passed to the remote method.
* @param payloadlen length of the argument
* @param reply buffer to store the reply from remote method.
* @return -ve error code on failure and 0 on success.
*/
int dbus_client_call_remote_method_with_reply(char *appname,char *method,void \
*payload, int payloadlen,void **reply, int *replylen )
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
DBusError err;
DBusMessage* msg,*msg_reply;
DBusMessageIter args,args1;
DBusMessageIter subiter,subiter1;
DBusPendingCall* pending;
int ret=0;
char busname[64]={0};
sprintf(busname,DBUS_REMOTE_APP_BUS_NAME,appname);
char *pload = malloc(payloadlen);
memcpy(pload, payload, payloadlen);
dbus_error_init(&err);
msg = dbus_message_new_method_call(
busname, // target for the method call
DBUS_OBJECT_NAME, // object to call on
DBUS_INTERFACE_NAME, // interface to call
method);//method to call
if (NULL == msg) {
fprintf(stderr, "Message Null\n");
floge("dbustest.log","%s:%d Message Null",__func__,__LINE__);
ret=-1;
goto FAIL;
}
// append arguments
dbus_message_iter_init_append(msg, &args);
dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "y", &subiter);
dbus_message_iter_append_fixed_array(&subiter, DBUS_TYPE_BYTE, &pload, \
payloadlen); dbus_message_iter_close_container(&args, &subiter);
if (!dbus_connection_send_with_reply (txconn, msg, &pending, -1))
{ // Use -1 for default timeout
fprintf(stderr, "Out Of Memory!\n");
floge("dbustest.log","%s:%d Out Of Memory",__func__,__LINE__);
dbus_message_unref(msg);
ret=-2;
goto FAIL;
}
if (NULL == pending)
{
fprintf(stderr, "Pending Call Null\n");
floge("dbustest.log","%s:%d Pending Call Null",__func__,__LINE__);
dbus_message_unref(msg);
ret=-3;
goto FAIL;
}
dbus_connection_flush(txconn);
dbus_message_unref(msg);
dbus_pending_call_block(pending);
msg_reply = dbus_pending_call_steal_reply(pending);
if (NULL == msg_reply) {
fprintf(stderr, "Reply Null\n");
floge("dbustest.log","%s:%d Reply Null",__func__,__LINE__);
dbus_pending_call_unref(pending);
ret=-4;
goto FAIL;
}
dbus_pending_call_unref(pending);
// char *buff="test";
// int leng=0;
// if (dbus_message_get_args(msg, &err,DBUS_TYPE_STRING, &buff,DBUS_TYPE_INVALID))
// printf("The server answered: '%s'\n", buff);
if (!dbus_message_iter_init(msg_reply, &args1))
{
flogd("dbustest.log", "%s:%d Message has no arguments!",__func__,__LINE__);
}
if( dbus_message_get_type (msg_reply) == DBUS_MESSAGE_TYPE_ERROR)
{
floge("dbustest.log","%s:%d Reply is \
DBUS_MESSAGE_TYPE_ERROR",__func__,__LINE__);
*reply=NULL;
replylen=0;
ret=-5;
goto FAIL;
}
dbus_message_iter_recurse(&args1, &subiter1);
dbus_message_iter_get_fixed_array (&subiter1, reply, replylen);
FAIL:
free(pload);
dbus_error_free(&err);
flogd("dbustest.log","%s:%d Exit",__func__,__LINE__);
return ret;
}
/**
* internal function, called on dbus remote method call.
* Note:the user must initialize the method reply buffer using \
dbus_client_init_reply_buff
* and fill the buffer with appropriate data and this function will free the \
method_reply buffer.
* @param msg dbus message handler.
* @param conn dbus connection handler.
* @param cb method to be called.
*/
static void handle_method_call_with_reply (DBusMessage *msg, DBusConnection *conn, \
void *cb) {
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
DBusMessageIter args;
DBusMessageIter subiter;
DBusError err;
DBusMessage *reply = NULL;
method_reply_t *method_reply={NULL};
method_callback mycb = (method_callback)cb;
char *value = NULL;
int len;
dbus_error_init(&err);
// read the arguments
if (!dbus_message_iter_init(msg, &args))
flogd("dbustest.log", "%s:%d Message has no arguments!",__func__,__LINE__);
// TODO: Check these APIs to get the args from the msg.
dbus_message_iter_recurse(&args, &subiter);
dbus_message_iter_get_fixed_array (&subiter, &value, &len);
// dbus_message_iter_close_container(&args, &subiter);
// Now Handle the cmd received
if (mycb != NULL)
{
method_reply=(*mycb)(value, len); // cb MUST copy the data, and don't block for \
long!!!! }
else
{
floge("dbustest.log","%s:%d callback is null, data not passed to \
client",__func__,__LINE__); }
// printf("%s:%d method_reply->len=%d \
data=%s\n",__func__,__LINE__,method_reply->len,(char*)method_reply->data);
if (!(reply = dbus_message_new_method_return(msg))){
goto fail;
}
dbus_message_iter_init_append(reply, &args);
dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "y", &subiter);
// dbus_message_iter_append_fixed_array(&subiter, DBUS_TYPE_BYTE, \
&(method_reply->data), method_reply->len); \
dbus_message_iter_append_fixed_array(&subiter, DBUS_TYPE_BYTE, &(method_reply->data), \
method_reply->len); dbus_message_iter_close_container(&args, &subiter);
// dbus_message_append_args(reply,DBUS_TYPE_STRING, &(method_reply->data), \
DBUS_TYPE_INVALID); fail:
if (dbus_error_is_set(&err)) {
if (reply)
dbus_message_unref(reply);
reply = dbus_message_new_error(msg, err.name, err.message);
dbus_error_free(&err);
}
/*
* In any cases we should have allocated a reply otherwise it
* means that we failed to allocate one.
*/
if (!reply)
{
free(method_reply->data);
free(method_reply);
floge("dbustest.log","%s:%d Out Of Memory!",__func__,__LINE__);
return ;
}
/* Send the reply which might be an error one too. */
if (!dbus_connection_send(conn, reply, NULL))
{
free(method_reply->data);
free(method_reply);
floge("dbustest.log","%s:%d unable to send method reply!",__func__,__LINE__);
return ;
}
dbus_message_unref(reply);
free(method_reply->data);
free(method_reply);
flogd("dbustest.log","%s:%d Exit",__func__,__LINE__);
}
static void handle_method_call (DBusMessage *msg, DBusConnection *conn, void *cb)
{
DBusMessageIter rootIter;
DBusMessageIter subIter;
char *value = NULL;
int len;
callback mycb = (callback)cb;
// read the arguments
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
if (!dbus_message_iter_init(msg, &rootIter))
flogd("dbustest.log", "%s:%d Message has no arguments!",__func__,__LINE__);
// TODO: Check these APIs to get the args from the msg.
dbus_message_iter_recurse(&rootIter, &subIter);
dbus_message_iter_get_fixed_array (&subIter, &value, &len);
// Now Handle the cmd received
if (mycb != NULL)
{
(*mycb)(value, len); // cb MUST copy the data, and don't block for long!!!!
}
else
{
floge("dbustest.log","%s:%d callback is null, data not passed to \
client",__func__,__LINE__); }
flogd("dbustest.log","%s:%d Exit",__func__,__LINE__);
}
static void dispatch(int fd, short ev, void *x)
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
struct dbus_ctx *ctx = x;
DBusConnection *c = ctx->conn;
while (dbus_connection_get_dispatch_status(c) == DBUS_DISPATCH_DATA_REMAINS)
dbus_connection_dispatch(c);
flogd("dbustest.log","%s:%d Exit",__func__,__LINE__);
}
static void handle_dispatch_status(DBusConnection *c,
DBusDispatchStatus status, void *data)
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
struct dbus_ctx *ctx = data;
if (status == DBUS_DISPATCH_DATA_REMAINS) {
struct timeval tv = {
.tv_sec = 0,
.tv_usec = 0,
};
event_add(&ctx->dispatch_ev, &tv);
}
flogd("dbustest.log","%s:%d Exit",__func__,__LINE__);
}
static void handle_watch(int fd, short events, void *x)
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
struct dbus_ctx *ctx = x;
struct DBusWatch *watch = ctx->extra;
unsigned int flags = 0;
if (events & EV_READ)
flags |= DBUS_WATCH_READABLE;
if (events & EV_WRITE)
flags |= DBUS_WATCH_WRITABLE;
/*if (events & HUP)
flags |= DBUS_WATCH_HANGUP;
if (events & ERR)
flags |= DBUS_WATCH_ERROR;*/
if (dbus_watch_handle(watch, flags) == FALSE)
flogd("dbustest.log","%s:%d dbus_watch_handle() failed\n",__func__,__LINE__);
handle_dispatch_status(ctx->conn, DBUS_DISPATCH_DATA_REMAINS, ctx);
flogd("dbustest.log","%s:%d Exit",__func__,__LINE__);
}
static dbus_bool_t add_watch(DBusWatch *w, void *data)
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
if (!dbus_watch_get_enabled(w))
return TRUE;
struct dbus_ctx *ctx = data;
ctx->extra = w;
int fd = dbus_watch_get_unix_fd(w);
unsigned int flags = dbus_watch_get_flags(w);
short cond = EV_PERSIST;
if (flags & DBUS_WATCH_READABLE)
cond |= EV_READ;
if (flags & DBUS_WATCH_WRITABLE)
cond |= EV_WRITE;
struct event *event = event_new(ctx->evbase, fd, cond, handle_watch, ctx);
if (!event)
return FALSE;
event_add(event, NULL);
dbus_watch_set_data(w, event, NULL);
flogv("dbustest.log","%s:%d added dbus watch fd=%d watch=%p \
cond=%d\n",__func__,__LINE__, fd, w, cond); flogd("dbustest.log","%s:%d \
Exit",__func__,__LINE__); return TRUE;
}
static void remove_watch(DBusWatch *w, void *data)
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
struct event *event = dbus_watch_get_data(w);
if (event)
event_free(event);
dbus_watch_set_data(w, NULL, NULL);
flogv("dbustest.log","%s:%d removed dbus watch watch=%p\n",__func__,__LINE__, w);
flogd("dbustest.log","%s:%d Exit",__func__,__LINE__);
}
static void toggle_watch(DBusWatch *w, void *data)
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
flogv("dbustest.log","%s:%d toggling dbus watch watch=%p\n",__func__,__LINE__, \
w);
if (dbus_watch_get_enabled(w))
add_watch(w, data);
else
remove_watch(w, data);
flogd("dbustest.log","%s:%d Exit",__func__,__LINE__);
}
static void unregister_func(DBusConnection *connection, void *data)
{
}
static DBusHandlerResult message_func(DBusConnection *connection,
DBusMessage *message, void *data)
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
struct dbus_ctx *ctx = data;
int i;
/* handle DBus message */
for (i = 0; i < ctx->args->num_pairs; i++)
{
//flogv("dbustest.log","is signal ? method %s", \
ctx->args->mthod_cb[i].method);
if (dbus_message_is_signal(message, DBUS_INTERFACE_NAME, \
ctx->args->mthod_cb[i].method)) {
flogv("dbustest.log","%s:%d handle method call %s",__func__,__LINE__, \
ctx->args->mthod_cb[i].method);
handle_method_call(message, ctx->conn, ctx->args->mthod_cb[i].cb);
}
else if (dbus_message_is_method_call(message, DBUS_INTERFACE_NAME, \
ctx->args->mthod_cb[i].method)) {
flogv("dbustest.log","%s:%d handle method call %s",__func__,__LINE__, \
ctx->args->mthod_cb[i].method);
handle_method_call_with_reply(message, ctx->conn, \
ctx->args->mthod_cb[i].cb); }
}
flogd("dbustest.log","%s:%d Exit",__func__,__LINE__);
return DBUS_HANDLER_RESULT_HANDLED;
}
static DBusObjectPathVTable dbus_vtable = {
.unregister_function = unregister_func,
.message_function = message_func,
};
static dbus_ctx_t *dbus_init(struct event_base *eb)
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
DBusConnection *conn = rxconn;
DBusError err;
dbus_ctx_t *ctx = &gctx;
char match_buffer[255];
int len1;
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
dbus_connection_set_exit_on_disconnect(conn, FALSE);
ctx->conn = conn;
ctx->evbase = eb;
event_assign(&ctx->dispatch_ev, eb, -1, EV_TIMEOUT, dispatch, ctx);
if (!dbus_connection_set_watch_functions(conn, add_watch, remove_watch,
toggle_watch, ctx, NULL)) {
flogd("dbustest.log","%s:%ddbus_connection_set_watch_functions() \
failed",__func__,__LINE__); goto out;
}
dbus_connection_set_dispatch_status_function(conn, handle_dispatch_status,
ctx, NULL);
// add a rule for which messages we want to see
len1 = strlen("type='signal',interface='");
sprintf (match_buffer, "%s", "type='signal',interface='");
sprintf (match_buffer+len1, "%s", DBUS_INTERFACE_NAME);
sprintf(match_buffer+len1+strlen(DBUS_INTERFACE_NAME), "%s", "'");
dbus_error_init(&err);
dbus_bus_add_match(conn, match_buffer, &err); // see signals from the given \
interface dbus_connection_flush(conn);
if (dbus_error_is_set(&err)) {
flogd("dbustest.log","%s:%d Match Error (%s)",__func__,__LINE__, err.message);
dbus_error_free(&err);
goto out;
}
dbus_error_free(&err);
if (dbus_connection_register_object_path(conn, DBUS_OBJECT_NAME, &dbus_vtable,
ctx) != TRUE) {
flogd("dbustest.log","%s:%d failed to register object \
path\n",__func__,__LINE__); goto out;
}
dbus_connection_unref(conn);
return ctx;
out:
if (conn) {
dbus_connection_close(conn);
dbus_connection_unref(conn);
}
flogd("dbustest.log","%s:%d Exit",__func__,__LINE__);
return NULL;
}
void dbus_close(struct dbus_ctx *ctx)
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
if (ctx && ctx->conn) {
dbus_connection_flush(ctx->conn);
dbus_connection_close(ctx->conn);
dbus_connection_unref(ctx->conn);
event_del(&ctx->dispatch_ev);
}
flogd("dbustest.log","%s:%d Exit",__func__,__LINE__);
}
/* Receive thread Main Loop */
static void *dbus_client_receive_thread (void *arg)
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
rx_thread_args_t *args = (rx_thread_args_t *) arg;
DBusError err;
int rc;
dbus_ctx_t *lctx;
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
ev_base = event_base_new ();
// initialise the error
dbus_error_init(&err);
lctx = dbus_init(ev_base);
lctx->args = args;
rc = event_base_dispatch(ev_base);
if (rc == -1)
{
flogd("dbustest.log","%s:%d %s: Exit (rc = %d)\n",__func__,__LINE__, rc);
}
else
{
dbus_error_free(&err);
}
return 0;
}
/***************************** Interface Functions \
***********************************/
/*
* return: 0 on success, -1 on failure.
*/
/**
* Initialize dbus.pass the unique application name as argument. this name will
* be used to identify the dbus object and path name in the later calls.
* @param appname unique application identifier name.
* @return 0 on success error code otherwise.
*/
int dbus_client_init (char *appname)
{
struct timespec wait = {0};
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
DBusError err;
int rc = 0;
printf("appname=%s\n",appname);
// lock mutex
wait.tv_sec = 0;
wait.tv_nsec = MS_TO_NS(MILLI_SEC); // 500 msec
//pthread_mutex_lock (&init_dbus_mutex);
if(pthread_mutex_timedlock(&init_dbus_mutex, &wait) == 0)
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
if (init_dbus_flag == false)
{
// initialize the errors
dbus_error_init(&err);
// connect to the system bus and check for errors
txconn = dbus_bus_get(DBUS_BUS_SESSION, &err);
if (dbus_error_is_set(&err))
{
flogd("dbustest.log","%s:%d txbus: Connection Error \
(%s)",__func__,__LINE__, err.message); dbus_error_free(&err);
pthread_mutex_unlock (&init_dbus_mutex);
return -1;
}
if (NULL == txconn)
{
dbus_error_free(&err);
pthread_mutex_unlock (&init_dbus_mutex);
return -1;
}
// request our name on the bus
sprintf(txbusname + strlen(txbusname), "%s", appname);
rc = dbus_bus_request_name(txconn, txbusname, DBUS_NAME_FLAG_REPLACE_EXISTING \
, &err); if (dbus_error_is_set(&err) || rc == -1)
{
flogd("dbustest.log", "%s:%d txbus: Name Error (%s)",__func__,__LINE__, \
err.message); dbus_error_free(&err);
pthread_mutex_unlock (&init_dbus_mutex);
return -1;
}
// connect to the system bus and check for errors
rxconn = dbus_bus_get(DBUS_BUS_SESSION, &err);
if (dbus_error_is_set(&err))
{
flogd("dbustest.log","%s:%d rxbus: Connection Error \
(%s)",__func__,__LINE__, err.message); dbus_error_free(&err);
pthread_mutex_unlock (&init_dbus_mutex);
return -1;
}
if (NULL == rxconn)
{
dbus_error_free(&err);
pthread_mutex_unlock (&init_dbus_mutex);
return -1;
}
// request our name on the bus
// sprintf(rxbusname + strlen(rxbusname), "%d", getpid());
sprintf(rxbusname + strlen(rxbusname), "%s", appname);
printf("%s\n",rxbusname);
rc = dbus_bus_request_name(rxconn, rxbusname, DBUS_NAME_FLAG_REPLACE_EXISTING \
, &err); if (dbus_error_is_set(&err) || rc == -1)
{
flogd("dbustest.log", "%s:%d rxbus: Name Error (%s)",__func__,__LINE__, \
err.message); dbus_error_free(&err);
pthread_mutex_unlock (&init_dbus_mutex);
return -1;
}
dbus_error_free(&err);
init_dbus_flag = true;
}
else
{
flogv("dbustest.log","%s:%d Dbus was already initialized",__func__,__LINE__);
}
pthread_mutex_unlock (&init_dbus_mutex);
}
else
{
flogd("dbustest.log","%s:%d Exit (no errors)",__func__,__LINE__);
return -1;
}
return 0;
}
/* This API subscribes for a particular busname/interface/method. The callback would
* be called once the subscribed information is available.
*Note: subscribe = listen => server bus name (e.g.,).
*
* method: method name you want to listen to.
* cb: callback to be called once the subscribed information is available.
* return: 0 on success, -1 on failure.
*/
int dbus_client_subscribe (int num_pairs, ...)
{
flogd("dbustest.log","%s:%d Entry",__func__,__LINE__);
int i;
va_list vargs;
rx_thread_args_t *args;
if (num_pairs > 32)
return -1;
args = (rx_thread_args_t *) malloc (sizeof(rx_thread_args_t));
if (args == NULL)
return -1;
args->num_pairs = num_pairs;
va_start(vargs, num_pairs);
for (i = 0; i < num_pairs; i++)
{
char *m = va_arg(vargs, char *);
sprintf (args->mthod_cb[i].method, "%s", m);
args->mthod_cb[i].cb = va_arg(vargs, void *);
}
va_end(vargs);
if (pthread_create (&dbus_client_rx_thread, NULL, dbus_client_receive_thread, \
(void *)args) != 0) {
floge("dbustest.log","%s:%d Client Error: Rx Thread creation failed; errno = \
%d (%s)",__func__,__LINE__, errno, strerror(errno)); return -1;
}
// free(args);
flogd("dbustest.log","%s:%d exit",__func__,__LINE__);
return 0;
}
/*
* method: method name
* payload: data that needs to be sent/published.
* payloadlen: length of payload in bytes.
* return: 0 on success, -1 on failure.
*/
/*
* method: method name
* payload: data that needs to be sent/published.
* payloadlen: length of payload in bytes.
* return: 0 on success, -1 on failure.
*/
int dbus_client_publish (char *method, void *payload, int payloadlen)
{
DBusMessage *msg;
DBusMessageIter args;
DBusMessageIter subiter;
DBusError err;
int returnValue = -1;
int SignalRetryCount = 0;
int SendRetryCount = 0;
int maxRetries = 3;
int successConnect = 0;
int successSend = 0;
char *pload = (char*) payload;
if(pload != NULL)
{
// initialize the errors
dbus_error_init (&err);
while (SignalRetryCount < maxRetries && !successConnect)
{
// create a new method call and check for errors
msg = dbus_message_new_signal (DBUS_OBJECT_NAME, // object name of the \
signal
DBUS_INTERFACE_NAME, // interface name of the \
signal method); // name of the signal
if(NULL == msg)
{
dbus_error_free (&err);
SignalRetryCount++;
}
else
{
// append arguments
dbus_message_iter_init_append (msg, &args);
// For appending args, doc says to use the following 3 for container \
types. // We can view the cmd buffer as a char buffer and send
dbus_message_iter_open_container (&args, DBUS_TYPE_ARRAY, "y", &subiter);
dbus_message_iter_append_fixed_array (&subiter, DBUS_TYPE_BYTE, &pload, \
payloadlen);
dbus_message_iter_close_container (&args, &subiter);
// We probably don't need a reply
flogv("dbustest.log","%s:%d dbus_connection_send \
called",__func__,__LINE__);
while (SendRetryCount < maxRetries && !successSend)
{
if(!dbus_connection_send (txconn, msg, NULL))
{
flogd("dbustest.log","%s:%d Out Of Memory!",__func__,__LINE__);
SendRetryCount++;
}
else
{
successConnect = 1;
successSend = 1;
returnValue = 0;
break;
}
}
}
}
dbus_connection_flush (txconn);
// free message
dbus_message_unref (msg);
dbus_error_free (&err);
//flogd("dbustest.log","%s:%d Exit (no errors)",__func__,__LINE__);
}
// print ( dbus_client_publish, returnValue)
return returnValue;
}
/***************************************************************/
["dbus-client.h" (text/x-chdr)]
#ifndef _DBUS_CLIENT_H
#define _DBUS_CLIENT_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct method_reply
{
void *data;
int len;
}method_reply_t;
/**
* Function to initialize the dbus_client library.which establish a connection with the dbus bus.
* @param appname the unique application name.other processes use this name to communicate.
* @return 0 on success otherwise error code.
*/
extern int dbus_client_init (char *appname);
/**
* Use this function to subscribe signals or methods. pass method/signals and
* call back functions as comma separated pairs.list of pairs can be given with comma
* separation.
* eg dbus_client_subscribe(3,"sig1",sig1_callback,"sig2",sig2_callback,"method1",method1_callback).
* @param num_pairs number of pairs.
* @return 0 on success, -1 on failure.
*/
extern int dbus_client_subscribe (int num_pairs, ...);
/**
* Function to broadcast a signal.
* @param method name of the signal.
* @param payload data to be passed to listeners.
* @param payloadlen length of the data in bytes.
* @return 0 on success, -1 on failure.
*/
extern int dbus_client_publish (char *method,
void *payload,
int payloadlen);
/**
* Use this function to initialize the dbus method reply buffer.
* no need to call de-init.
* @param len required buffer legth in bytes.
* @return -ve error code on failure and method_reply on success.
*/
//extern method_reply_t *dbus_client_init_reply_buff(int len);
/**
* Wrapper to call a method of a remote process.This function is a blocking call.
* the remote method must respond with a return value.
* @param appname name of the remote process bus name.
* @param method remote method to be invoked
* @param payload argument to be passed to the remote method.
* @param payloadlen length of the argument
* @param reply buffer to store the reply from remote method.
* @return -ve error code on failure and 0 on success.
*/
extern int dbus_client_call_remote_method_with_reply(char *busname,
char *method,
void *payload,
int payloadlen,
void **reply,
int *replylen );
#ifdef __cplusplus
}
#endif
#endif // _DBUS_CLIENT_H
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic