All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH_v9] connman: add plugin in oFono to request/release private network
@ 2011-07-12  9:31 Guillaume Zajac
  2011-07-12 16:23 ` Denis Kenzior
  0 siblings, 1 reply; 2+ messages in thread
From: Guillaume Zajac @ 2011-07-12  9:31 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 8613 bytes --]

While requesting private network, object path returned
by ConnMan is stored to use it later on.

While releasing private network,  pass stored object path in
argument in order ConnMan to release accordingly private network.

Don't check in release function if call get completed, only
check if pending call is not null. It might happens that pending
call is not null and creates a crash while testing call completion.
Force pending call to be set to NULL when request_reply is invoked.

Don't call the application CB when a call is marked as redundant,
it might create a crash.
---
 Makefile.am       |    3 +
 plugins/connman.c |  287 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 290 insertions(+), 0 deletions(-)
 create mode 100644 plugins/connman.c

diff --git a/Makefile.am b/Makefile.am
index c08e09f..efb1118 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -346,6 +346,9 @@ builtin_sources += plugins/hfp_ag.c plugins/bluetooth.h
 builtin_modules += dun_gw
 builtin_sources += plugins/dun_gw.c plugins/bluetooth.h
 
+builtin_modules += connman
+builtin_sources += plugins/connman.c
+
 builtin_sources += $(btio_sources)
 builtin_cflags += @BLUEZ_CFLAGS@
 builtin_libadd += @BLUEZ_LIBS@
diff --git a/plugins/connman.c b/plugins/connman.c
new file mode 100644
index 0000000..caa9aab
--- /dev/null
+++ b/plugins/connman.c
@@ -0,0 +1,287 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <gdbus.h>
+#include <string.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/log.h>
+#include <ofono/dbus.h>
+#include <ofono/plugin.h>
+#include <ofono/private-network.h>
+
+#define CONNMAN_SERVICE			"net.connman"
+#define CONNMAN_PATH			"/net/connman"
+
+#define CONNMAN_MANAGER_INTERFACE	CONNMAN_SERVICE ".Manager"
+#define CONNMAN_MANAGER_PATH		"/"
+
+static DBusConnection *connection;
+static GHashTable *requests;
+static unsigned int id;
+
+struct pns_req {
+	int uid;
+	DBusPendingCall *pending;
+	ofono_private_network_cb_t cb;
+	void *data;
+	gboolean redundant;
+	char *path;
+};
+
+static void pns_release(int uid)
+{
+	DBusMessage *message = NULL;
+	struct pns_req *req;
+
+	DBG("");
+
+	req = g_hash_table_lookup(requests, &uid);
+	if (!req)
+		return;
+
+	if (req->pending) {
+		/*
+		* We want to cancel the request but we have to wait
+		* the response of ConnMan. So we mark request as
+		* redundant until we get the response, then we remove
+		* it from hash table.
+		*/
+		req->redundant = TRUE;
+		return;
+	}
+
+	message = dbus_message_new_method_call(CONNMAN_SERVICE,
+						CONNMAN_MANAGER_PATH,
+						CONNMAN_MANAGER_INTERFACE,
+						"ReleasePrivateNetwork");
+
+	if (message == NULL)
+		goto error;
+
+	dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &req->path,
+							DBUS_TYPE_INVALID);
+	dbus_message_set_no_reply(message, TRUE);
+	dbus_connection_send(connection, message, NULL);
+	dbus_message_unref(message);
+
+error:
+	g_hash_table_remove(requests, &req->uid);
+}
+
+static void request_reply(DBusPendingCall *call, void *user_data)
+{
+	struct pns_req *req = user_data;
+	struct ofono_private_network_settings pns;
+	DBusMessageIter array, dict, entry;
+	DBusMessage *reply;
+	const char *path;
+
+	DBG("");
+
+	pns.fd = -1;
+	pns.server_ip = NULL;
+	pns.peer_ip = NULL;
+	pns.primary_dns = NULL;
+	pns.secondary_dns = NULL;
+
+	req->pending = NULL;
+
+	reply = dbus_pending_call_steal_reply(call);
+	if (!reply)
+		goto error;
+
+	if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
+		goto error;
+
+	if (dbus_message_iter_init(reply, &array) == FALSE)
+		goto error;
+
+	if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_OBJECT_PATH)
+		goto error;
+
+	dbus_message_iter_get_basic(&array, &path);
+
+	dbus_message_iter_next(&array);
+	if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
+		goto error;
+
+	if (req->redundant == TRUE)
+		goto release;
+
+	dbus_message_iter_recurse(&array, &dict);
+
+	while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+		DBusMessageIter iter;
+		const char *key;
+		int type;
+
+		dbus_message_iter_recurse(&dict, &entry);
+
+		dbus_message_iter_get_basic(&entry, &key);
+
+		dbus_message_iter_next(&entry);
+		dbus_message_iter_recurse(&entry, &iter);
+
+		type = dbus_message_iter_get_arg_type(&iter);
+		if (type != DBUS_TYPE_STRING)
+			break;
+
+		if (g_str_equal(key, "ServerIPv4") &&
+				type == DBUS_TYPE_STRING)
+			dbus_message_iter_get_basic(&iter, &pns.server_ip);
+		else if (g_str_equal(key, "PeerIPv4") &&
+				type == DBUS_TYPE_STRING)
+			dbus_message_iter_get_basic(&iter, &pns.peer_ip);
+		else if (g_str_equal(key, "PrimaryDNS") &&
+				type == DBUS_TYPE_STRING)
+			dbus_message_iter_get_basic(&iter, &pns.primary_dns);
+		else if (g_str_equal(key, "SecondaryDNS") &&
+				type == DBUS_TYPE_STRING)
+			dbus_message_iter_get_basic(&iter, &pns.secondary_dns);
+
+		dbus_message_iter_next(&dict);
+	}
+
+	dbus_message_iter_next(&array);
+	if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_UNIX_FD)
+		goto error;
+
+	dbus_message_iter_get_basic(&array, &pns.fd);
+	DBG("Fildescriptor = %d\n", pns.fd);
+
+	req->path = g_strdup(path);
+	DBG("Object path = %s\n", req->path);
+
+	if (pns.server_ip == NULL || pns.peer_ip == NULL ||
+			pns.primary_dns == NULL || pns.secondary_dns == NULL ||
+			pns.fd < 0) {
+		ofono_error("Error while reading dictionnary...\n");
+		goto release;
+	}
+
+	req->cb(&pns, req->data);
+
+	dbus_message_unref(reply);
+	dbus_pending_call_unref(call);
+
+	return;
+
+release:
+	pns_release(req->uid);
+error:
+	if (pns.fd >= 0)
+		close(pns.fd);
+
+	if (req->redundant == FALSE)
+		req->cb(NULL, req->data);
+
+	if (reply)
+		dbus_message_unref(reply);
+
+	dbus_pending_call_unref(call);
+}
+
+static int pns_request(ofono_private_network_cb_t cb, void *data)
+{
+	DBusMessage *message;
+	DBusPendingCall *call;
+	struct pns_req *req;
+
+	DBG("");
+
+	req = g_try_new(struct pns_req, 1);
+
+	if (req == NULL)
+		return -ENOMEM;
+
+	message = dbus_message_new_method_call(CONNMAN_SERVICE,
+						CONNMAN_MANAGER_PATH,
+						CONNMAN_MANAGER_INTERFACE,
+						"RequestPrivateNetwork");
+
+	if (message == NULL) {
+		g_free(req);
+		return -ENOMEM;
+	}
+
+	if (dbus_connection_send_with_reply(connection, message,
+						&call, 5000) == FALSE) {
+		g_free(req);
+		dbus_message_unref(message);
+		return -EIO;
+	}
+
+	id++;
+	req->pending = call;
+	req->cb = cb;
+	req->data = data;
+	req->uid = id;
+	req->redundant = FALSE;
+
+	dbus_pending_call_set_notify(call, request_reply, req, NULL);
+	g_hash_table_insert(requests, &req->uid, req);
+	dbus_message_unref(message);
+
+	return req->uid;
+}
+
+static struct ofono_private_network_driver pn_driver = {
+	.name		= "ConnMan Private Network",
+	.request	= pns_request,
+	.release	= pns_release,
+};
+
+static void remove_requests(gpointer user_data)
+{
+	struct pns_req *req = user_data;
+
+	g_free(req->path);
+	g_free(req);
+}
+
+static int connman_init(void)
+{
+	DBG("");
+
+	connection = ofono_dbus_get_connection();
+	requests = g_hash_table_new_full(g_int_hash, g_int_equal, NULL,
+						remove_requests);
+
+	return ofono_private_network_driver_register(&pn_driver);
+}
+
+static void connman_exit(void)
+{
+	g_hash_table_destroy(requests);
+	ofono_private_network_driver_unregister(&pn_driver);
+}
+
+OFONO_PLUGIN_DEFINE(connman, "ConnMan plugin", VERSION,
+		OFONO_PLUGIN_PRIORITY_DEFAULT, connman_init, connman_exit)
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH_v9] connman: add plugin in oFono to request/release private network
  2011-07-12  9:31 [PATCH_v9] connman: add plugin in oFono to request/release private network Guillaume Zajac
@ 2011-07-12 16:23 ` Denis Kenzior
  0 siblings, 0 replies; 2+ messages in thread
From: Denis Kenzior @ 2011-07-12 16:23 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 3517 bytes --]

Hi Guillaume,

<snip>

> +static void request_reply(DBusPendingCall *call, void *user_data)
> +{
> +	struct pns_req *req = user_data;
> +	struct ofono_private_network_settings pns;
> +	DBusMessageIter array, dict, entry;
> +	DBusMessage *reply;
> +	const char *path;
> +
> +	DBG("");
> +
> +	pns.fd = -1;
> +	pns.server_ip = NULL;
> +	pns.peer_ip = NULL;
> +	pns.primary_dns = NULL;
> +	pns.secondary_dns = NULL;
> +
> +	req->pending = NULL;
> +
> +	reply = dbus_pending_call_steal_reply(call);
> +	if (!reply)
> +		goto error;
> +
> +	if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
> +		goto error;
> +
> +	if (dbus_message_iter_init(reply, &array) == FALSE)
> +		goto error;
> +
> +	if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_OBJECT_PATH)
> +		goto error;
> +
> +	dbus_message_iter_get_basic(&array, &path);
> +
> +	dbus_message_iter_next(&array);
> +	if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
> +		goto error;
> +
> +	if (req->redundant == TRUE)
> +		goto release;
> +
> +	dbus_message_iter_recurse(&array, &dict);
> +
> +	while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
> +		DBusMessageIter iter;
> +		const char *key;
> +		int type;
> +
> +		dbus_message_iter_recurse(&dict, &entry);
> +
> +		dbus_message_iter_get_basic(&entry, &key);
> +
> +		dbus_message_iter_next(&entry);
> +		dbus_message_iter_recurse(&entry, &iter);
> +
> +		type = dbus_message_iter_get_arg_type(&iter);
> +		if (type != DBUS_TYPE_STRING)
> +			break;
> +
> +		if (g_str_equal(key, "ServerIPv4") &&
> +				type == DBUS_TYPE_STRING)
> +			dbus_message_iter_get_basic(&iter, &pns.server_ip);
> +		else if (g_str_equal(key, "PeerIPv4") &&
> +				type == DBUS_TYPE_STRING)
> +			dbus_message_iter_get_basic(&iter, &pns.peer_ip);
> +		else if (g_str_equal(key, "PrimaryDNS") &&
> +				type == DBUS_TYPE_STRING)
> +			dbus_message_iter_get_basic(&iter, &pns.primary_dns);
> +		else if (g_str_equal(key, "SecondaryDNS") &&
> +				type == DBUS_TYPE_STRING)
> +			dbus_message_iter_get_basic(&iter, &pns.secondary_dns);
> +
> +		dbus_message_iter_next(&dict);
> +	}
> +
> +	dbus_message_iter_next(&array);
> +	if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_UNIX_FD)
> +		goto error;
> +
> +	dbus_message_iter_get_basic(&array, &pns.fd);
> +	DBG("Fildescriptor = %d\n", pns.fd);
> +
> +	req->path = g_strdup(path);
> +	DBG("Object path = %s\n", req->path);
> +
> +	if (pns.server_ip == NULL || pns.peer_ip == NULL ||
> +			pns.primary_dns == NULL || pns.secondary_dns == NULL ||
> +			pns.fd < 0) {
> +		ofono_error("Error while reading dictionnary...\n");
> +		goto release;
> +	}
> +
> +	req->cb(&pns, req->data);
> +
> +	dbus_message_unref(reply);
> +	dbus_pending_call_unref(call);
> +
> +	return;
> +
> +release:
> +	pns_release(req->uid);
> +error:
> +	if (pns.fd >= 0)
> +		close(pns.fd);
> +
> +	if (req->redundant == FALSE)
> +		req->cb(NULL, req->data);

And how do you think you will be using req->redundant when you just
freed req in pns_release above?

> +
> +	if (reply)
> +		dbus_message_unref(reply);
> +
> +	dbus_pending_call_unref(call);
> +}
> +

Anyhow, I applied this patch and refactored it very heavily afterward.
Please test my changes, particularly the error conditions with an older
version of ConnMan.

If things are working nicely please send a patch marking the DUN
emulator task as done.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2011-07-12 16:23 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-12  9:31 [PATCH_v9] connman: add plugin in oFono to request/release private network Guillaume Zajac
2011-07-12 16:23 ` Denis Kenzior

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.