2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file connection.cpp
18 * @author Zbigniew Kostrzewa (z.kostrzewa@samsung.com)
23 #include <dpl/log/log.h>
24 #include <dpl/dbus/connection.h>
25 #include <dpl/dbus/exception.h>
26 #include <dpl/dbus/object_proxy.h>
33 ConnectionPtr Connection::sessionBus()
35 return connectTo(G_BUS_TYPE_SESSION);
38 ConnectionPtr Connection::systemBus()
40 return connectTo(G_BUS_TYPE_SYSTEM);
43 ConnectionPtr Connection::connectTo(GBusType busType)
47 GDBusConnection* connection = g_bus_get_sync(busType,
50 if (NULL == connection)
55 message = error->message;
58 ThrowMsg(DBus::Exception,
59 "Couldn't connect to bus: " << message);
62 g_dbus_connection_set_exit_on_close(connection, FALSE);
64 return ConnectionPtr(new Connection(connection));
67 ConnectionPtr Connection::connectTo(const std::string& address)
71 GDBusConnection* connection = g_dbus_connection_new_for_address_sync(
73 G_DBUS_CONNECTION_FLAGS_NONE,
77 if (NULL == connection)
82 message = error->message;
85 ThrowMsg(DBus::Exception,
86 "Couldn't connect to " << address << ": " << message);
89 return ConnectionPtr(new Connection(connection));
92 Connection::Connection(GDBusConnection* connection)
93 : m_connection(connection)
95 g_signal_connect(m_connection,
97 G_CALLBACK(onConnectionClosed),
101 Connection::~Connection()
103 std::for_each(m_registeredServices.begin(),
104 m_registeredServices.end(),
105 [] (const RegisteredServices::value_type& value)
107 g_bus_unown_name(value.second);
110 std::for_each(m_registeredObjects.begin(),
111 m_registeredObjects.end(),
112 [m_connection] (const RegisteredObjects::value_type& value)
114 g_dbus_connection_unregister_object(
116 value.second.registrationId);
119 if (!g_dbus_connection_is_closed(m_connection))
121 GError* error = NULL;
123 if (FALSE == g_dbus_connection_flush_sync(m_connection, NULL, &error))
125 LogPedantic("Could not flush the connection"
126 << " <" << error->message << ">");
131 g_object_unref(m_connection);
134 void Connection::registerService(const std::string& serviceName)
136 guint regId = g_bus_own_name_on_connection(m_connection,
138 G_BUS_NAME_OWNER_FLAGS_NONE,
139 onServiceNameAcquired,
145 ThrowMsg(DBus::Exception, "Error while registering service.");
148 m_registeredServices.insert(RegisteredServices::value_type(serviceName,
152 void Connection::unregisterService(const std::string& serviceName)
154 auto it = m_registeredServices.find(serviceName);
155 if (m_registeredServices.end() == it)
157 ThrowMsg(DBus::Exception, "Service not registered.");
160 g_bus_unown_name(it->second);
162 m_registeredServices.erase(it);
165 void Connection::registerObject(const ObjectPtr& object)
167 GError* error = NULL;
169 guint regId = g_dbus_connection_register_object(
171 object->getPath().c_str(),
172 object->getInterface()->getInfo(),
173 object->getInterface()->getVTable(),
174 // TODO This is ugly, fix this!
175 object->getInterface().get(),
183 message = error->message;
184 LogPedantic(error->message << " " << error->code);
187 ThrowMsg(DBus::Exception, "Error while registering an object: "
191 m_registeredObjects.insert(RegisteredObjects::value_type(
193 ObjectRegistration(regId, object)));
196 void Connection::unregisterObject(const std::string& objectPath)
198 auto it = m_registeredObjects.find(objectPath);
199 if (m_registeredObjects.end() == it)
201 ThrowMsg(DBus::Exception, "Object not registered.");
204 gboolean result = g_dbus_connection_unregister_object(
206 it->second.registrationId);
209 ThrowMsg(DBus::Exception, "Unregistering object failed.");
211 m_registeredObjects.erase(it);
214 ObjectProxyPtr Connection::createObjectProxy(const std::string& serviceName,
215 const std::string& objectPath)
217 if (g_dbus_connection_is_closed(m_connection))
219 ThrowMsg(DBus::ConnectionClosedException, "Connection closed.");
222 return ObjectProxyPtr(
223 new ObjectProxy(m_connection, serviceName, objectPath));
226 void Connection::onServiceNameAcquired(GDBusConnection* /*connection*/,
227 const gchar* serviceName,
230 Assert(data && "Connection should not be NULL");
232 Connection* self = static_cast<Connection*>(data);
234 LogPedantic("Emitting service name acquired event: " << serviceName);
236 ConnectionEvents::ServiceNameAcquiredEvent event(serviceName);
237 self->DPL::Event::EventSupport<ConnectionEvents::ServiceNameAcquiredEvent>::
238 EmitEvent(event, DPL::Event::EmitMode::Queued);
241 void Connection::onServiceNameLost(GDBusConnection* /*connection*/,
242 const gchar* serviceName,
245 Assert(data && "Connection should not be NULL");
247 Connection* self = static_cast<Connection*>(data);
249 LogPedantic("Emitting service name lost event: " << serviceName);
251 ConnectionEvents::ServiceNameLostEvent event(serviceName);
252 self->DPL::Event::EventSupport<ConnectionEvents::ServiceNameLostEvent>::
253 EmitEvent(event, DPL::Event::EmitMode::Queued);
256 void Connection::onConnectionClosed(GDBusConnection* /*connection*/,
257 gboolean peerVanished,
261 Assert(NULL != data && "Connection cannot be NULL");
263 Connection* self = static_cast<Connection*>(data);
265 if ((NULL == error) && (FALSE == peerVanished))
267 // Connection closed by this.
269 else if (NULL != error)
271 std::string message = error->message;
275 if (TRUE == peerVanished)
277 // Connection closed by remote host.
278 ConnectionEvents::ConnectionBrokenEvent event(message);
279 self->DPL::Event::EventSupport<ConnectionEvents::ConnectionBrokenEvent>::
280 EmitEvent(event, DPL::Event::EmitMode::Queued);
284 // Invalid or malformed data on connection.
285 ConnectionEvents::ConnectionInvalidEvent event(message);
286 self->DPL::Event::EventSupport<ConnectionEvents::ConnectionInvalidEvent>::
287 EmitEvent(event, DPL::Event::EmitMode::Queued);