update on dbus
[profile/ivi/genivi/genivi-audio-manager.git] / PluginRoutingInterfaceDbus / DBUSMessageHandler.cpp
1
2
3 #include "headers.h"
4 #include <stdlib.h>
5
6 DBUSMessageHandler::DBUSMessageHandler(DBusObjectPathVTable* vtable, DBusConnection* conn, void* reference)
7 : m_MessageIter()
8 , m_pReply(0)
9 , m_serial(0)
10 , m_pConnection(conn)
11 {
12     dbus_error_init(&m_err);
13
14     string nodeString =std::string(DBUS_SERVICE_ROOT)+"/"+std::string(MY_NODE);
15         dbus_bool_t b=dbus_connection_register_object_path(m_pConnection, nodeString.c_str(), vtable, reference);
16         if(!b) {
17                 DLT_LOG(DLT_CONTEXT, DLT_LOG_INFO, DLT_STRING("Registering of node"), DLT_STRING(MY_NODE),DLT_STRING("failed"));
18         }
19 }
20
21 DBUSMessageHandler::~DBUSMessageHandler()
22 {
23     DBusError err;
24     dbus_error_init(&err);
25     bool errorset = dbus_error_is_set(&err);
26     if (errorset)
27     {
28         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("there was an dbus error"));
29     }
30     dbus_bus_name_has_owner(m_pConnection, DBUS_SERVICE_SERVICE, &err);
31     errorset = dbus_error_is_set(&err);
32     if (errorset)
33     {
34         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("there was an dbus error"));
35     }
36     dbus_error_init(&err);
37     dbus_bus_release_name(m_pConnection, DBUS_SERVICE_SERVICE, &err);
38 }
39
40 void DBUSMessageHandler::initReceive(DBusMessage* msg)
41 {
42     if (!dbus_message_iter_init(msg, &m_MessageIter))
43     {
44         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS Message has no arguments!"));
45     }
46 }
47
48 void DBUSMessageHandler::initReply(DBusMessage* msg)
49 {
50     // create a reply from the message
51     m_pReply = dbus_message_new_method_return(msg);
52     dbus_message_iter_init_append(m_pReply, &m_MessageIter);
53 }
54
55 void DBUSMessageHandler::closeReply()
56 {
57     // send the reply && flush the connection
58     if (!dbus_connection_send(m_pConnection, m_pReply, &m_serial))
59     {
60         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler Out Of Memory!"));
61         exit(1);
62     }
63         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler sending reply!"));
64     dbus_connection_flush(m_pConnection);
65
66     // free the reply
67     dbus_message_unref(m_pReply);
68     m_pReply = NULL;
69 }
70
71 void DBUSMessageHandler::ReplyError(DBusMessage* msg, const char* errorname, const char* errorMsg)
72 {
73     m_pReply = dbus_message_new_error(msg, errorname, errorMsg);
74     // send the reply && flush the connection
75     if (!dbus_connection_send(m_pConnection, m_pReply, &m_serial))
76     {
77         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler Out Of Memory!"));
78         exit(1);
79     }
80         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler sending reply with error!"));
81     dbus_connection_flush(m_pConnection);
82
83     // free the reply
84     dbus_message_unref(m_pReply);
85 }
86
87 char* DBUSMessageHandler::getString()
88 {
89     char* param;
90
91     if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&m_MessageIter))
92     {
93         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler argument is no string!"));
94     }
95     else
96     {
97         dbus_message_iter_get_basic(&m_MessageIter, &param);
98         dbus_message_iter_next(&m_MessageIter);
99     }
100     return param;
101 }
102
103 dbus_bool_t DBUSMessageHandler::getBool()
104 {
105     dbus_bool_t boolparam;
106
107     if (DBUS_TYPE_BOOLEAN != dbus_message_iter_get_arg_type(&m_MessageIter))
108     {
109         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler argument is no bool!"));
110     }
111     else
112     {
113         dbus_message_iter_get_basic(&m_MessageIter, &boolparam);
114         dbus_message_iter_next(&m_MessageIter);
115     }
116     return boolparam;
117 }
118
119 char DBUSMessageHandler::getByte()
120 {
121     char param;
122
123     if (DBUS_TYPE_BYTE != dbus_message_iter_get_arg_type(&m_MessageIter))
124     {
125         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler argument is no byte!"));
126     }
127     else
128     {
129         dbus_message_iter_get_basic(&m_MessageIter, &param);
130         dbus_message_iter_next(&m_MessageIter);
131     }
132     return param;
133 }
134
135 dbus_uint32_t DBUSMessageHandler::getUInt()
136 {
137     dbus_uint32_t param;
138
139     if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&m_MessageIter))
140     {
141         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler argument is no uint32_t!"));
142     }
143     else
144     {
145         dbus_message_iter_get_basic(&m_MessageIter, &param);
146         dbus_message_iter_next(&m_MessageIter);
147     }
148     return param;
149 }
150
151 double DBUSMessageHandler::getDouble()
152 {
153     double param;
154
155     if (DBUS_TYPE_DOUBLE != dbus_message_iter_get_arg_type(&m_MessageIter))
156     {
157         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler argument is no double!"));
158     }
159     else
160     {
161         dbus_message_iter_get_basic(&m_MessageIter, &param);
162         dbus_message_iter_next(&m_MessageIter);
163     }
164     return param;
165 }
166
167 void DBUSMessageHandler::getArrayOfUInt(int* pLength, unsigned int** ppArray)
168 {
169     if (DBUS_TYPE_ARRAY != dbus_message_iter_get_arg_type(&m_MessageIter))
170     {
171         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler argument is no array!"));
172         return;
173     }
174
175     DBusMessageIter arrayIter;
176     dbus_message_iter_recurse(&m_MessageIter, &arrayIter);
177
178     uint* localArray;
179     dbus_message_iter_get_fixed_array(&arrayIter, &localArray, pLength);
180
181     *ppArray = new uint[*pLength];
182     for (int i = 0; i < *pLength; i++)
183     {
184         (*ppArray)[i] = localArray[i];
185     }
186 }
187
188 void DBUSMessageHandler::getArrayOfString(std::vector<std::string>* stringVector)
189 {
190     if (DBUS_TYPE_ARRAY != dbus_message_iter_get_arg_type(&m_MessageIter))
191     {
192         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler argument is no array!"));
193         return;
194     }
195
196     DBusMessageIter arrayIter;
197     dbus_message_iter_recurse(&m_MessageIter, &arrayIter);
198     bool hasNext = true;
199     while (hasNext)
200     {
201         if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&arrayIter))
202         {
203                 DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler argument is no string!"));
204         }
205         char* param;
206         dbus_message_iter_get_basic(&arrayIter, &param);
207
208         stringVector->push_back(std::string(param));
209
210         if (dbus_message_iter_has_next(&arrayIter))
211         {
212             dbus_message_iter_next(&arrayIter);
213         }
214         else
215         {
216             hasNext = false;
217         }
218     }
219 }
220
221 void DBUSMessageHandler::append(bool toAppend)
222 {
223         dbus_bool_t mybool=toAppend;
224     if (!dbus_message_iter_append_basic(&m_MessageIter, DBUS_TYPE_BOOLEAN, &mybool))
225     {
226         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler Out Of Memory!"));
227         exit(1);
228     }
229 }
230
231 void DBUSMessageHandler::append(dbus_uint32_t toAppend)
232 {
233     if (!dbus_message_iter_append_basic(&m_MessageIter, DBUS_TYPE_UINT32, &toAppend))
234     {
235         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler Out Of Memory!"));
236         exit(1);
237     }
238 }
239
240 void DBUSMessageHandler::append(double toAppend)
241 {
242     if (!dbus_message_iter_append_basic(&m_MessageIter, DBUS_TYPE_DOUBLE, &toAppend))
243     {
244         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler Out Of Memory!"));
245         exit(1);
246     }
247 }
248
249 void DBUSMessageHandler::append(char toAppend)
250 {
251     if (!dbus_message_iter_append_basic(&m_MessageIter, DBUS_TYPE_BYTE, &toAppend))
252     {
253         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler Out Of Memory!"));
254         exit(1);
255     }
256 }
257
258 void DBUSMessageHandler::append(unsigned int length, unsigned int *IDs)
259 {
260     DBusMessageIter arrayIter;
261     dbus_message_iter_open_container(&m_MessageIter, DBUS_TYPE_ARRAY, "u", &arrayIter);
262     for(unsigned int i = 0; i < length; i++)
263     {
264         dbus_message_iter_append_basic(&arrayIter, DBUS_TYPE_UINT32, &IDs[i]);
265     }
266     dbus_message_iter_close_container(&m_MessageIter, &arrayIter);
267 }
268
269 void DBUSMessageHandler::sendSignal(const char* signalname) {
270         dbus_uint32_t serial = 0;
271         DBusMessage* msg;
272
273     string nodeString =std::string(DBUS_SERVICE_ROOT)+"/"+std::string(MY_NODE);
274         msg =dbus_message_new_signal(nodeString.c_str(),DBUS_SERVICE_SERVICE,signalname);
275
276         if (NULL == msg)
277         {
278                 DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("Message null!"));
279                 this->~DBUSMessageHandler();
280         }
281
282         if (!dbus_connection_send(m_pConnection, msg, &serial)) {
283                 DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler Out Of Memory!"));
284                 this->~DBUSMessageHandler();
285         }
286
287         dbus_connection_flush(m_pConnection);
288
289         // free the message
290         dbus_message_unref(msg);
291 }
292
293 void DBUSMessageHandler::append(std::list<ConnectionType> list){
294     DBusMessageIter arrayIter;
295     dbus_message_iter_open_container(&m_MessageIter, DBUS_TYPE_ARRAY, "uu", &arrayIter);
296
297     std::list<ConnectionType>::iterator Ilist;
298     std::list<ConnectionType>::iterator Ibegin=list.begin();
299     std::list<ConnectionType>::iterator Iend=list.end();
300     for(Ilist=Ibegin;Ilist!=Iend; Ilist++)
301     {
302         dbus_message_iter_append_basic(&arrayIter, DBUS_TYPE_UINT32, &Ilist->Sink_ID);
303         dbus_message_iter_append_basic(&arrayIter, DBUS_TYPE_UINT32, &Ilist->Source_ID);
304     }
305     dbus_message_iter_close_container(&m_MessageIter, &arrayIter);
306 }
307
308 void DBUSMessageHandler::append(std::list<SinkType> list){
309     DBusMessageIter arrayIter;
310     dbus_message_iter_open_container(&m_MessageIter, DBUS_TYPE_ARRAY, "su", &arrayIter);
311
312     std::list<SinkType>::iterator Ilist;
313     std::list<SinkType>::iterator Ibegin=list.begin();
314     std::list<SinkType>::iterator Iend=list.end();
315     for(Ilist=Ibegin;Ilist!=Iend; Ilist++)
316     {
317         dbus_message_iter_append_basic(&arrayIter, DBUS_TYPE_STRING, &Ilist->name);
318         dbus_message_iter_append_basic(&arrayIter, DBUS_TYPE_UINT32, &Ilist->ID);
319     }
320     dbus_message_iter_close_container(&m_MessageIter, &arrayIter);
321
322 }
323
324 void DBUSMessageHandler::append(std::list<SourceType> list){
325     DBusMessageIter arrayIter;
326     dbus_message_iter_open_container(&m_MessageIter, DBUS_TYPE_ARRAY, "su", &arrayIter);
327
328     std::list<SourceType>::iterator Ilist;
329     std::list<SourceType>::iterator Ibegin=list.begin();
330     std::list<SourceType>::iterator Iend=list.end();
331     for(Ilist=Ibegin;Ilist!=Iend; Ilist++)
332     {
333         dbus_message_iter_append_basic(&arrayIter, DBUS_TYPE_STRING, &Ilist->name);
334         dbus_message_iter_append_basic(&arrayIter, DBUS_TYPE_UINT32, &Ilist->ID);
335     }
336     dbus_message_iter_close_container(&m_MessageIter, &arrayIter);
337 }
338
339
340
341 DBUSIntrospection::DBUSIntrospection(MethodTable* methodTable, SignalTable* signalTable,std::string nodename)
342 : m_methodTable(methodTable), m_signalTable(signalTable), m_nodename(nodename)
343 {
344     generateString();
345 }
346
347 void DBUSIntrospection::generateString()
348 {
349         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("Generating instrospection data!"));
350
351     addHeader();
352     openNode(m_nodename);
353     openInterface("org.freedesktop.DBus.Introspectable");
354     openMethod("Introspect");
355     addArgument("data", "out", "s");
356     closeMethod();
357     closeInterface();
358     openInterface(DBUS_SERVICE_SERVICE);
359
360     int index = 0;
361
362     while (strcmp(m_methodTable[index].name, "") != 0)
363     {
364         MethodTable entry = m_methodTable[index];
365         addEntry(entry);
366         ++index;
367     }
368
369     index=0;
370     if (m_signalTable) {
371         while (strcmp(m_signalTable[index].name, "") != 0)
372         {
373             SignalTable entry = m_signalTable[index];
374             addEntry(entry);
375             ++index;
376         }
377     }
378     closeInterface();
379     closeNode();
380
381 }
382
383 void DBUSIntrospection::addHeader(void)
384 {
385     m_introspectionString << "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS"
386         << "Object Introspection 1.0//EN\"\n \"http://www.freedesktop.org/standards/"
387         << "dbus/1.0/introspect.dtd\"> \n";
388 }
389
390 void DBUSIntrospection::openNode(string nodename)
391 {
392     m_introspectionString << "<node name=\"" << nodename << "\">  \n";
393 }
394
395 void DBUSIntrospection::openInterface(string interfacename)
396 {
397     m_introspectionString << "<interface name=\"" << interfacename << "\">  \n";
398 }
399
400 void DBUSIntrospection::openMethod(string methodname)
401 {
402     m_introspectionString << "<method name=\"" << methodname << "\">  \n";
403 }
404
405 void DBUSIntrospection::openSignal(string signalname) {
406         m_introspectionString<<"<signal name=\"" << signalname << "\">  \n";
407 }
408
409 void DBUSIntrospection::addArgument(string argname, string direction, string type)
410 {
411     m_introspectionString << "<arg name=\"" << argname << "\" direction=\""
412         << direction << "\" type=\"" << type << "\"/>  \n";
413 }
414
415
416 void DBUSIntrospection::addSignalArgument(string argname, string type){
417     m_introspectionString << "<arg name=\"" << argname << "\" type=\"" << type << "\"/>  \n";
418 }
419
420 void DBUSIntrospection::closeMethod(void)
421 {
422     m_introspectionString << "</method>  \n";
423 }
424
425 void DBUSIntrospection::closeInterface(void)
426 {
427     m_introspectionString << "</interface>  \n";
428 }
429
430 void DBUSIntrospection::closeNode(void)
431 {
432     m_introspectionString << "</node>  \n";
433 }
434
435 void DBUSIntrospection::closeSignal(void){
436         m_introspectionString<<"</signal>  \n";
437 }
438
439 void DBUSIntrospection::addEntry(MethodTable entry)
440 {
441     string methodName = entry.name;
442     string parameterArray = entry.signature;
443     string returnValueArray = string(entry.reply);
444
445     openMethod(methodName);
446
447     for(uint parameterIndex = 0; parameterIndex < parameterArray.length(); ++parameterIndex)
448     {
449         switch (parameterArray.at(parameterIndex))
450         {
451                         case 'a':
452                         if (parameterArray.at(parameterIndex+1)=='(') {
453                                 int size=parameterArray.find((')'),parameterIndex);
454                                 addArgument("","in",parameterArray.substr(parameterIndex,size+1));
455                                 parameterIndex+=size;
456                         } else {
457                                 addArgument("","in", parameterArray.substr(parameterIndex,2));
458                                 parameterIndex+=2;
459                         }
460                         break;
461                 default:
462                         addArgument("","in", parameterArray.substr(parameterIndex,1));
463                         break;
464         }
465     }
466
467
468     for(uint returnValueIndex = 0; returnValueIndex < returnValueArray.length(); ++returnValueIndex)
469     {
470         switch (returnValueArray.at(returnValueIndex))
471         {
472                         case 'a':
473                         if (returnValueArray.at(returnValueIndex+1)=='(') {
474                                 int size=returnValueArray.find((')'),returnValueIndex);
475                                 addArgument("","out",returnValueArray.substr(returnValueIndex,size+1));
476                                 returnValueIndex+=size;
477                         } else {
478                                 addArgument("","out", returnValueArray.substr(returnValueIndex,2));
479                                 returnValueIndex+=2;
480                         }
481                         break;
482                 default:
483                         addArgument("","out", returnValueArray.substr(returnValueIndex,1));
484                         break;
485         }
486     }
487
488     closeMethod();
489 }
490
491 void DBUSIntrospection::addEntry(SignalTable entry)
492 {
493     string methodName = entry.name;
494     string parameterArray = entry.signature;
495
496     openSignal(methodName);
497
498     for(uint parameterIndex = 0; parameterIndex < parameterArray.length(); ++parameterIndex)
499     {
500         switch (parameterArray.at(parameterIndex))
501         {
502             case 'a':
503                 if (parameterArray.at(parameterIndex+1)=='{') {
504                         int size=parameterArray.find(('}'),parameterIndex);
505                         addSignalArgument("",parameterArray.substr(parameterIndex,size+1));
506                         parameterIndex+=size;
507                 } else {
508                         parameterIndex++;
509                     addSignalArgument("", "a" + parameterArray.at(parameterIndex));
510                 }
511                 break;
512             default:
513                 addSignalArgument("", parameterArray.substr(parameterIndex,1));
514                 break;
515         }
516     }
517
518     closeSignal();
519 }
520
521 void DBUSIntrospection::process(DBusConnection* conn, DBusMessage* msg)
522 {
523     DBusMessage * reply;
524     DBusMessageIter args;
525     dbus_uint32_t serial = 0;
526
527     // create a reply from the message
528     reply = dbus_message_new_method_return(msg);
529
530     string introspect = m_introspectionString.str();
531     const char* string = introspect.c_str();
532
533     // add the arguments to the reply
534     dbus_message_iter_init_append(reply, &args);
535     if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &string))
536     {
537         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler Out Of Memory!"));
538     }
539
540     // send the reply && flush the connection
541     if (!dbus_connection_send(conn, reply, &serial))
542     {
543         DLT_LOG(DLT_CONTEXT,DLT_LOG_ERROR, DLT_STRING("DBUS handler Out Of Memory!"));
544     }
545     dbus_connection_flush(conn);
546
547     // free the reply
548     dbus_message_unref(reply);
549 }
550
551
552
553
554
555