* [PATCH_v6 1/5] gatppp: Add new contructor to use external fd
2011-05-19 9:55 [PATCH_v6 0/5] *** SUBJECT HERE *** Guillaume Zajac
@ 2011-05-19 9:55 ` Guillaume Zajac
2011-05-19 9:55 ` [PATCH_v6 2/5] private-network: add header into include and Makefile.am Guillaume Zajac
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Guillaume Zajac @ 2011-05-19 9:55 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 4859 bytes --]
---
gatchat/gatppp.c | 33 ++++++++++++++++++++++++++++++++-
gatchat/gatppp.h | 1 +
gatchat/ppp.h | 2 +-
gatchat/ppp_net.c | 47 ++++++++++++++++++++++++++++++++---------------
4 files changed, 66 insertions(+), 17 deletions(-)
diff --git a/gatchat/gatppp.c b/gatchat/gatppp.c
index c776811..1f2d227 100644
--- a/gatchat/gatppp.c
+++ b/gatchat/gatppp.c
@@ -78,6 +78,7 @@ struct _GAtPPP {
guint ppp_dead_source;
GAtSuspendFunc suspend_func;
gpointer suspend_data;
+ int fd;
};
void ppp_debug(GAtPPP *ppp, const char *str)
@@ -290,7 +291,7 @@ void ppp_auth_notify(GAtPPP *ppp, gboolean success)
void ppp_ipcp_up_notify(GAtPPP *ppp, const char *local, const char *peer,
const char *dns1, const char *dns2)
{
- ppp->net = ppp_net_new(ppp);
+ ppp->net = ppp_net_new(ppp, ppp->fd);
if (ppp->net == NULL) {
ppp->disconnect_reason = G_AT_PPP_REASON_NET_FAIL;
@@ -316,6 +317,7 @@ void ppp_ipcp_down_notify(GAtPPP *ppp)
return;
ppp_net_free(ppp->net);
+ ppp->fd = -1;
ppp->net = NULL;
}
@@ -522,6 +524,8 @@ void g_at_ppp_unref(GAtPPP *ppp)
if (ppp->net)
ppp_net_free(ppp->net);
+ else if (ppp->fd >= 0)
+ close(ppp->fd);
if (ppp->chap)
ppp_chap_free(ppp->chap);
@@ -565,6 +569,8 @@ static GAtPPP *ppp_init_common(GAtHDLC *hdlc, gboolean is_server, guint32 ip)
ppp->ref_count = 1;
+ ppp->fd = -1;
+
/* set options to defaults */
ppp->mru = DEFAULT_MRU;
ppp->mtu = DEFAULT_MTU;
@@ -657,3 +663,28 @@ GAtPPP *g_at_ppp_server_new_from_io(GAtIO *io, const char *local)
return ppp;
}
+
+GAtPPP *g_at_ppp_server_new_full(GAtIO *io, const char *local, int fd)
+{
+ GAtHDLC *hdlc;
+ GAtPPP *ppp;
+ guint32 ip;
+
+ if (local == NULL)
+ ip = 0;
+ else if (inet_pton(AF_INET, local, &ip) != 1)
+ return NULL;
+
+ hdlc = g_at_hdlc_new_from_io(io);
+ if (hdlc == NULL)
+ return NULL;
+
+ ppp = ppp_init_common(hdlc, TRUE, ip);
+
+ /* Set the fd value returned by ConnMan */
+ ppp->fd = fd;
+
+ g_at_hdlc_unref(hdlc);
+
+ return ppp;
+}
diff --git a/gatchat/gatppp.h b/gatchat/gatppp.h
index 9464ffd..365123a 100644
--- a/gatchat/gatppp.h
+++ b/gatchat/gatppp.h
@@ -54,6 +54,7 @@ GAtPPP *g_at_ppp_new(GIOChannel *modem);
GAtPPP *g_at_ppp_new_from_io(GAtIO *io);
GAtPPP *g_at_ppp_server_new(GIOChannel *modem, const char *local);
GAtPPP *g_at_ppp_server_new_from_io(GAtIO *io, const char *local);
+GAtPPP *g_at_ppp_server_new_full(GAtIO *io, const char *local, int fd);
void g_at_ppp_open(GAtPPP *ppp);
void g_at_ppp_set_connect_function(GAtPPP *ppp, GAtPPPConnectFunc callback,
diff --git a/gatchat/ppp.h b/gatchat/ppp.h
index 22809d8..f866944 100644
--- a/gatchat/ppp.h
+++ b/gatchat/ppp.h
@@ -102,7 +102,7 @@ void ppp_chap_free(struct ppp_chap *chap);
void ppp_chap_process_packet(struct ppp_chap *chap, const guint8 *new_packet);
/* TUN / Network related functions */
-struct ppp_net *ppp_net_new(GAtPPP *ppp);
+struct ppp_net *ppp_net_new(GAtPPP *ppp, int fd);
const char *ppp_net_get_interface(struct ppp_net *net);
void ppp_net_process_packet(struct ppp_net *net, const guint8 *packet);
void ppp_net_free(struct ppp_net *net);
diff --git a/gatchat/ppp_net.c b/gatchat/ppp_net.c
index 25bcfa4..52b3554 100644
--- a/gatchat/ppp_net.c
+++ b/gatchat/ppp_net.c
@@ -123,35 +123,52 @@ const char *ppp_net_get_interface(struct ppp_net *net)
return net->if_name;
}
-struct ppp_net *ppp_net_new(GAtPPP *ppp)
+struct ppp_net *ppp_net_new(GAtPPP *ppp, int fd)
{
struct ppp_net *net;
GIOChannel *channel = NULL;
struct ifreq ifr;
- int fd, err;
+ int err;
net = g_try_new0(struct ppp_net, 1);
- if (net == NULL)
+ if (net == NULL) {
+ if (fd >= 0)
+ close(fd);
+
return NULL;
+ }
net->ppp_packet = ppp_packet_new(MAX_PACKET, PPP_IP_PROTO);
if (net->ppp_packet == NULL) {
+ if (fd >= 0)
+ close(fd);
+
g_free(net);
return NULL;
}
- /* open a tun interface */
- fd = open("/dev/net/tun", O_RDWR);
- if (fd < 0)
- goto error;
-
- memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
- strcpy(ifr.ifr_name, "ppp%d");
-
- err = ioctl(fd, TUNSETIFF, (void *) &ifr);
- if (err < 0)
- goto error;
+ /*
+ * If the fd value is still the default one,
+ * open the tun interface and configure it.
+ */
+ if (fd < 0) {
+ /* open a tun interface */
+ fd = open("/dev/net/tun", O_RDWR);
+ if (fd < 0)
+ goto error;
+
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+ strcpy(ifr.ifr_name, "ppp%d");
+
+ err = ioctl(fd, TUNSETIFF, (void *) &ifr);
+ if (err < 0)
+ goto error;
+ } else {
+ err = ioctl(fd, TUNGETIFF, (void *) &ifr);
+ if (err < 0)
+ goto error;
+ }
net->if_name = strdup(ifr.ifr_name);
--
1.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH_v6 2/5] private-network: add header into include and Makefile.am
2011-05-19 9:55 [PATCH_v6 0/5] *** SUBJECT HERE *** Guillaume Zajac
2011-05-19 9:55 ` [PATCH_v6 1/5] gatppp: Add new contructor to use external fd Guillaume Zajac
@ 2011-05-19 9:55 ` Guillaume Zajac
2011-05-19 9:55 ` [PATCH_v6 3/5] private-network: add request/release functions and new feature to Makefile.am Guillaume Zajac
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Guillaume Zajac @ 2011-05-19 9:55 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 2579 bytes --]
---
Makefile.am | 4 +-
include/private-network.h | 56 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+), 2 deletions(-)
create mode 100644 include/private-network.h
diff --git a/Makefile.am b/Makefile.am
index a413a47..d7e5626 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,8 +16,8 @@ pkginclude_HEADERS = include/log.h include/plugin.h include/history.h \
include/cdma-sms.h include/sim-auth.h \
include/gprs-provision.h include/emulator.h \
include/location-reporting.h \
- include/cdma-connman.h \
- include/gnss.h
+ include/cdma-connman.h include/gnss.h \
+ include/private-network.h
nodist_pkginclude_HEADERS = include/version.h
diff --git a/include/private-network.h b/include/private-network.h
new file mode 100644
index 0000000..983bf5b
--- /dev/null
+++ b/include/private-network.h
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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
+ *
+ */
+
+#ifndef __OFONO_PRIVATE_NETWORK_H
+#define __OFONO_PRIVATE_NETWORK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ofono_private_network_settings {
+ int fd;
+ char *server_ip;
+ char *peer_ip;
+ char *primary_dns;
+ char *secondary_dns;
+};
+
+typedef void (ofono_private_network_cb_t)(
+ void *data,
+ const struct ofono_private_network_settings *settings);
+
+struct ofono_private_network_driver {
+ char *name;
+ int (*request)(ofono_private_network_cb_t cb, void *data);
+ void (*release)(int uid);
+};
+
+int ofono_private_network_driver_register(
+ const struct ofono_private_network_driver *d);
+void ofono_private_network_driver_unregister(
+ const struct ofono_private_network_driver *d);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __OFONO_PRIVATE_NETWORK_H */
--
1.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH_v6 3/5] private-network: add request/release functions and new feature to Makefile.am
2011-05-19 9:55 [PATCH_v6 0/5] *** SUBJECT HERE *** Guillaume Zajac
2011-05-19 9:55 ` [PATCH_v6 1/5] gatppp: Add new contructor to use external fd Guillaume Zajac
2011-05-19 9:55 ` [PATCH_v6 2/5] private-network: add header into include and Makefile.am Guillaume Zajac
@ 2011-05-19 9:55 ` Guillaume Zajac
2011-05-19 9:55 ` [PATCH_v6 4/5] emulator: add request/release private network calls Guillaume Zajac
2011-05-19 9:55 ` [PATCH_v6 5/5] connman: add plugin in oFono to request/release private network Guillaume Zajac
4 siblings, 0 replies; 8+ messages in thread
From: Guillaume Zajac @ 2011-05-19 9:55 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 3548 bytes --]
---
Makefile.am | 3 +-
src/ofono.h | 6 +++
src/private-network.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 99 insertions(+), 1 deletions(-)
create mode 100644 src/private-network.c
diff --git a/Makefile.am b/Makefile.am
index d7e5626..e1eaf15 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -387,7 +387,8 @@ src_ofonod_SOURCES = $(gdbus_sources) $(builtin_sources) src/ofono.ver \
src/message.h src/message.c src/gprs-provision.c \
src/emulator.c src/location-reporting.c \
src/cdma-connman.c src/gnss.c \
- src/gnssagent.c src/gnssagent.h
+ src/gnssagent.c src/gnssagent.h \
+ src/private-network.c
src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ @CAPNG_LIBS@ -ldl
diff --git a/src/ofono.h b/src/ofono.h
index 82d7e34..7353022 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -468,3 +468,9 @@ void __ofono_gprs_provision_free_settings(
#include <ofono/emulator.h>
#include <ofono/gnss.h>
+#include <ofono/private-network.h>
+
+void __ofono_private_network_release(int id);
+ofono_bool_t __ofono_private_network_request(ofono_private_network_cb_t cb,
+ void *data, int *id);
+
diff --git a/src/private-network.c b/src/private-network.c
new file mode 100644
index 0000000..e955656
--- /dev/null
+++ b/src/private-network.c
@@ -0,0 +1,91 @@
+/*
+ *
+ * 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 <string.h>
+#include <glib.h>
+#include "ofono.h"
+
+static GSList *g_drivers = NULL;
+
+void __ofono_private_network_release(int id)
+{
+ GSList *d;
+
+ DBG("");
+
+ for (d = g_drivers; d; d = d->next) {
+ const struct ofono_private_network_driver *driver = d->data;
+
+ if (!driver->release)
+ continue;
+
+ driver->release(id);
+
+ break;
+ }
+}
+
+ofono_bool_t __ofono_private_network_request(ofono_private_network_cb_t cb,
+ void *data, int *id)
+{
+ GSList *d;
+ int uid;
+
+ DBG("");
+
+ for (d = g_drivers; d; d = d->next) {
+ const struct ofono_private_network_driver *driver = d->data;
+
+ if (!driver->request)
+ continue;
+
+ uid = driver->request(cb, data);
+ if (uid <= 0)
+ continue;
+
+ *id = uid;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int ofono_private_network_driver_register(
+ const struct ofono_private_network_driver *d)
+{
+ DBG("driver: %p, name: %s", d, d->name);
+
+ g_drivers = g_slist_prepend(g_drivers, (void *) d);
+
+ return 0;
+}
+
+void ofono_private_network_driver_unregister(
+ const struct ofono_private_network_driver *d)
+{
+ DBG("driver: %p, name: %s", d, d->name);
+
+ g_drivers = g_slist_remove(g_drivers, (void *) d);
+}
--
1.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH_v6 4/5] emulator: add request/release private network calls
2011-05-19 9:55 [PATCH_v6 0/5] *** SUBJECT HERE *** Guillaume Zajac
` (2 preceding siblings ...)
2011-05-19 9:55 ` [PATCH_v6 3/5] private-network: add request/release functions and new feature to Makefile.am Guillaume Zajac
@ 2011-05-19 9:55 ` Guillaume Zajac
2011-05-19 9:55 ` [PATCH_v6 5/5] connman: add plugin in oFono to request/release private network Guillaume Zajac
4 siblings, 0 replies; 8+ messages in thread
From: Guillaume Zajac @ 2011-05-19 9:55 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 4185 bytes --]
---
src/emulator.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 65 insertions(+), 10 deletions(-)
diff --git a/src/emulator.c b/src/emulator.c
index c17b901..0a83403 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
#include <glib.h>
@@ -32,11 +33,7 @@
#include "common.h"
#include "gatserver.h"
#include "gatppp.h"
-
-#define DUN_SERVER_ADDRESS "192.168.1.1"
-#define DUN_PEER_ADDRESS "192.168.1.2"
-#define DUN_DNS_SERVER_1 "10.10.10.10"
-#define DUN_DNS_SERVER_2 "10.10.10.11"
+#include "private-network.h"
#define RING_TIMEOUT 3
@@ -56,6 +53,8 @@ struct ofono_emulator {
guint callsetup_source;
gboolean clip;
gboolean ccwa;
+ int pns_id;
+ struct ofono_private_network_settings *local_pns;
};
struct indicator {
@@ -91,6 +90,18 @@ static void ppp_connect(const char *iface, const char *local,
DBG("Secondary DNS Server: %s\n", dns2);
}
+static void release_pns(struct ofono_emulator *em)
+{
+ g_free(em->local_pns->server_ip);
+ g_free(em->local_pns->peer_ip);
+ g_free(em->local_pns->primary_dns);
+ g_free(em->local_pns->secondary_dns);
+ g_free(em->local_pns);
+
+ __ofono_private_network_release(em->pns_id);
+ em->pns_id = 0;
+}
+
static void ppp_disconnect(GAtPPPDisconnectReason reason, gpointer user_data)
{
struct ofono_emulator *em = user_data;
@@ -100,6 +111,9 @@ static void ppp_disconnect(GAtPPPDisconnectReason reason, gpointer user_data)
g_at_ppp_unref(em->ppp);
em->ppp = NULL;
+ if (em->pns_id > 0)
+ release_pns(em);
+
if (em->server == NULL)
return;
@@ -128,14 +142,21 @@ static gboolean setup_ppp(gpointer user_data)
g_at_server_suspend(em->server);
- em->ppp = g_at_ppp_server_new_from_io(io, DUN_SERVER_ADDRESS);
+ em->ppp = g_at_ppp_server_new_full(io, em->local_pns->server_ip,
+ em->local_pns->fd);
if (em->ppp == NULL) {
+ /* PPP stack hasn't closed fd */
+ close(em->local_pns->fd);
+ if (em->pns_id > 0)
+ release_pns(em);
+
g_at_server_resume(em->server);
return FALSE;
}
- g_at_ppp_set_server_info(em->ppp, DUN_PEER_ADDRESS,
- DUN_DNS_SERVER_1, DUN_DNS_SERVER_2);
+ g_at_ppp_set_server_info(em->ppp, em->local_pns->peer_ip,
+ em->local_pns->primary_dns,
+ em->local_pns->secondary_dns);
g_at_ppp_set_credentials(em->ppp, "", "");
g_at_ppp_set_debug(em->ppp, emulator_debug, "PPP");
@@ -147,6 +168,39 @@ static gboolean setup_ppp(gpointer user_data)
return FALSE;
}
+static void request_private_network_cb(void *data,
+ const struct ofono_private_network_settings *pns)
+{
+ struct ofono_emulator *em = data;
+
+ if (pns == NULL) {
+ __ofono_private_network_release(em->pns_id);
+ em->pns_id = 0;
+ g_at_server_send_final(em->server, G_AT_SERVER_RESULT_ERROR);
+ return;
+ }
+
+ em->local_pns = g_try_new0(struct ofono_private_network_settings, 1);
+ if (em->local_pns == NULL) {
+ close(pns->fd);
+ __ofono_private_network_release(em->pns_id);
+ em->pns_id = 0;
+ g_at_server_send_final(em->server, G_AT_SERVER_RESULT_ERROR);
+ return;
+ }
+
+ em->local_pns->fd = pns->fd;
+ em->local_pns->server_ip = g_strdup(pns->server_ip);
+ em->local_pns->peer_ip = g_strdup(pns->peer_ip);
+ em->local_pns->primary_dns = g_strdup(pns->primary_dns);
+ em->local_pns->secondary_dns = g_strdup(pns->secondary_dns);
+
+ g_at_server_send_intermediate(em->server, "CONNECT");
+ em->source = g_idle_add(setup_ppp, em);
+
+ return;
+}
+
static gboolean dial_call(struct ofono_emulator *em, const char *dial_str)
{
char c = *dial_str;
@@ -154,8 +208,9 @@ static gboolean dial_call(struct ofono_emulator *em, const char *dial_str)
DBG("dial call %s", dial_str);
if (c == '*' || c == '#' || c == 'T' || c == 't') {
- g_at_server_send_intermediate(em->server, "CONNECT");
- em->source = g_idle_add(setup_ppp, em);
+ if (__ofono_private_network_request(request_private_network_cb,
+ em, &em->pns_id) == FALSE)
+ return FALSE;
}
return TRUE;
--
1.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH_v6 5/5] connman: add plugin in oFono to request/release private network
2011-05-19 9:55 [PATCH_v6 0/5] *** SUBJECT HERE *** Guillaume Zajac
` (3 preceding siblings ...)
2011-05-19 9:55 ` [PATCH_v6 4/5] emulator: add request/release private network calls Guillaume Zajac
@ 2011-05-19 9:55 ` Guillaume Zajac
4 siblings, 0 replies; 8+ messages in thread
From: Guillaume Zajac @ 2011-05-19 9:55 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 8568 bytes --]
---
Makefile.am | 3 +
plugins/connman.c | 299 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 302 insertions(+), 0 deletions(-)
create mode 100644 plugins/connman.c
diff --git a/Makefile.am b/Makefile.am
index e1eaf15..ffb85ae 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -339,6 +339,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..5f0ad8a
--- /dev/null
+++ b/plugins/connman.c
@@ -0,0 +1,299 @@
+/*
+ *
+ * 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>
+
+#include <ofono.h>
+#include <private-network.h>
+
+#define CONNMAN_SERVICE "net.connman"
+#define CONNMAN_PATH "/net/connman"
+
+#define CONNMAN_DEBUG_INTERFACE CONNMAN_SERVICE ".Debug"
+#define CONNMAN_ERROR_INTERFACE CONNMAN_SERVICE ".Error"
+#define CONNMAN_AGENT_INTERFACE CONNMAN_SERVICE ".Agent"
+#define CONNMAN_COUNTER_INTERFACE CONNMAN_SERVICE ".Counter"
+
+#define CONNMAN_MANAGER_INTERFACE CONNMAN_SERVICE ".Manager"
+#define CONNMAN_MANAGER_PATH "/"
+
+#define CONNMAN_TASK_INTERFACE CONNMAN_SERVICE ".Task"
+#define CONNMAN_PROFILE_INTERFACE CONNMAN_SERVICE ".Profile"
+#define CONNMAN_SERVICE_INTERFACE CONNMAN_SERVICE ".Service"
+#define CONNMAN_PROVIDER_INTERFACE CONNMAN_SERVICE ".Provider"
+#define CONNMAN_TECHNOLOGY_INTERFACE CONNMAN_SERVICE ".Technology"
+#define CONNMAN_SESSION_INTERFACE CONNMAN_SERVICE ".Session"
+#define CONNMAN_NOTIFICATION_INTERFACE CONNMAN_SERVICE ".Notification"
+
+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;
+ gboolean error;
+};
+
+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;
+
+ DBG("");
+
+ pns.fd = -1;
+ pns.server_ip = NULL;
+ pns.peer_ip = NULL;
+ pns.primary_dns = NULL;
+ pns.secondary_dns = NULL;
+
+ /* request is no more pending */
+ 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_UNIX_FD)
+ goto error;
+
+ dbus_message_iter_get_basic(&array, &pns.fd);
+ DBG("Fildescriptor = %d\n", pns.fd);
+
+ dbus_message_iter_next(&array);
+
+ if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
+ goto error;
+
+ 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);
+ }
+
+ if (req->redundant == TRUE)
+ goto done;
+
+ 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 done;
+ }
+
+ req->cb(req->data, &pns);
+
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(call);
+
+ return;
+
+error:
+ req->error = TRUE;
+done:
+ if (pns.fd >= 0)
+ close(pns.fd);
+
+ req->cb(req->data, NULL);
+
+ 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;
+ req->error = 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 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) {
+ if (dbus_pending_call_get_completed(req->pending) == FALSE) {
+ /*
+ * 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;
+ }
+ }
+
+ /*
+ * There was an error while reading response or transmitted by response
+ * so we don't need to call release DBus method.
+ */
+ if (req->error)
+ goto error;
+
+ message = dbus_message_new_method_call(CONNMAN_SERVICE,
+ CONNMAN_MANAGER_PATH,
+ CONNMAN_MANAGER_INTERFACE,
+ "ReleasePrivateNetwork");
+
+ if (message == NULL)
+ goto error;
+
+ dbus_message_set_no_reply(message, TRUE);
+ dbus_connection_send(connection, message, NULL);
+
+error:
+ if (message)
+ dbus_message_unref(message);
+
+ g_hash_table_remove(requests, &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);
+}
+
+static int connman_init(void)
+{
+ DBG("");
+
+ id = 0;
+ 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] 8+ messages in thread