As for service, it keeps track of pending DBus calls and so on.
---
src/peer.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 116 insertions(+), 2 deletions(-)
diff --git a/src/peer.c b/src/peer.c
index 0ff312f..a532a57 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -48,13 +48,25 @@ struct connman_peer {
char *path;
enum connman_peer_state state;
struct connman_ipconfig *ipconfig;
+ DBusMessage *pending;
bool registered;
};
+static void reply_pending(struct connman_peer *peer, int error)
+{
+ if (!peer->pending)
+ return;
+
+ connman_dbus_reply_pending(peer->pending, error, NULL);
+ peer->pending = NULL;
+}
+
static void peer_free(gpointer data)
{
struct connman_peer *peer = data;
+ reply_pending(peer, ENOENT);
+
connman_peer_unregister(peer);
if (peer->path) {
@@ -102,6 +114,24 @@ static const char *state2string(enum connman_peer_state
state)
return NULL;
}
+static bool is_connecting(struct connman_peer *peer)
+{
+ if (peer->state == CONNMAN_PEER_STATE_ASSOCIATION ||
+ peer->state == CONNMAN_PEER_STATE_CONFIGURATION ||
+ peer->pending)
+ return true;
+
+ return false;
+}
+
+static bool is_connected(struct connman_peer *peer)
+{
+ if (peer->state == CONNMAN_PEER_STATE_READY)
+ return true;
+
+ return false;
+}
+
static bool allow_property_changed(struct connman_peer *peer)
{
if (g_hash_table_lookup_extended(peers_notify->add, peer->path,
@@ -293,6 +323,86 @@ static void peer_removed(struct connman_peer *peer)
peer_schedule_changed();
}
+static int peer_connect(struct connman_peer *peer)
+{
+ int err = -ENOTSUP;
+
+ if (peer_driver->connect)
+ err = peer_driver->connect(peer);
+
+ return err;
+}
+
+static int peer_disconnect(struct connman_peer *peer)
+{
+ int err = -ENOTSUP;
+
+ reply_pending(peer, ECONNABORTED);
+
+ if (peer_driver->disconnect)
+ err = peer_driver->disconnect(peer);
+
+ __connman_dhcp_stop(peer->ipconfig);
+
+ return err;
+}
+
+static DBusMessage *connect_peer(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ struct connman_peer *peer = user_data;
+ GList *list;
+ int err;
+
+ DBG("peer %p", peer);
+
+ if (peer->pending)
+ return __connman_error_in_progress(msg);
+
+ list = g_hash_table_get_values(peers_table);
+ for (; list; list = list->next) {
+ struct connman_peer *temp = list->data;
+
+ if (temp == peer || temp->device != peer->device)
+ continue;
+
+ if (is_connecting(temp) || is_connected(temp)) {
+ if (peer_disconnect(temp) == -EINPROGRESS)
+ return __connman_error_in_progress(msg);
+ }
+ }
+
+ peer->pending = dbus_message_ref(msg);
+
+ err = peer_connect(peer);
+ if (err == -EINPROGRESS)
+ return NULL;
+
+ if (err < 0) {
+ dbus_message_unref(peer->pending);
+ peer->pending = NULL;
+
+ return __connman_error_failed(msg, -err);
+ }
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static DBusMessage *disconnect_peer(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ struct connman_peer *peer = user_data;
+ int err;
+
+ DBG("peer %p", peer);
+
+ err = peer_disconnect(peer);
+ if (err < 0 && err != -EINPROGRESS)
+ return __connman_error_failed(msg, -err);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
struct connman_peer *connman_peer_create(const char *identifier)
{
struct connman_peer *peer;
@@ -412,10 +522,12 @@ int connman_peer_set_state(struct connman_peer *peer,
CONNMAN_PEER_STATE_FAILURE);
break;
case CONNMAN_PEER_STATE_READY:
+ reply_pending(peer, 0);
break;
case CONNMAN_PEER_STATE_DISCONNECT:
break;
case CONNMAN_PEER_STATE_FAILURE:
+ reply_pending(peer, ENOTCONN);
__connman_dhcp_stop(peer->ipconfig);
__connman_ipconfig_disable(peer->ipconfig);
@@ -507,8 +619,8 @@ static const GDBusMethodTable peer_methods[] = {
{ GDBUS_METHOD("GetProperties",
NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
get_peer_properties) },
- { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, NULL) },
- { GDBUS_METHOD("Disconnect", NULL, NULL, NULL) },
+ { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, connect_peer) },
+ { GDBUS_METHOD("Disconnect", NULL, NULL, disconnect_peer) },
{ },
};
@@ -561,6 +673,8 @@ void connman_peer_unregister(struct connman_peer *peer)
if (!peer->path || !peer->registered)
return;
+ reply_pending(peer, EIO);
+
g_dbus_unregister_interface(connection, peer->path,
CONNMAN_PEER_INTERFACE);
peer->registered = false;
--
1.8.5.5
_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman