* [PATCHv3 0/5] Mobile broadband provider info plugin
@ 2011-08-05 12:25 Oleg Zhurakivskyy
2011-08-05 12:25 ` [PATCHv3 1/5] " Oleg Zhurakivskyy
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: Oleg Zhurakivskyy @ 2011-08-05 12:25 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 956 bytes --]
Hello,
Please find the mobile broadband provider info plugin ("Internet Access Provider database" TODO item).
If enabled, the plugin reads mobile-broadband-provider-info database entries (PROVIDER_DATABASE) and returns GRPS context settings to oFono provisioning module.
Regards,
Oleg
Oleg Zhurakivskyy (5):
Mobile broadband provider info plugin
GPRS context plan support
GPRS provisioning data plan support
Mobile broadband provider info plugin autoconf support
Mobile broadband provider info plugin makefile changes
Makefile.am | 7 +
configure.ac | 19 +-
include/gprs-context.h | 5 +
include/gprs-provision.h | 1 +
plugins/mobile-broadband-provider-info.c | 470 ++++++++++++++++++++++++++++++
5 files changed, 496 insertions(+), 6 deletions(-)
create mode 100644 plugins/mobile-broadband-provider-info.c
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCHv3 1/5] Mobile broadband provider info plugin 2011-08-05 12:25 [PATCHv3 0/5] Mobile broadband provider info plugin Oleg Zhurakivskyy @ 2011-08-05 12:25 ` Oleg Zhurakivskyy 2011-08-12 6:55 ` Denis Kenzior 2011-08-05 12:25 ` [PATCHv3 2/5] GPRS context plan support Oleg Zhurakivskyy ` (3 subsequent siblings) 4 siblings, 1 reply; 10+ messages in thread From: Oleg Zhurakivskyy @ 2011-08-05 12:25 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 12429 bytes --] --- plugins/mobile-broadband-provider-info.c | 470 ++++++++++++++++++++++++++++++ 1 files changed, 470 insertions(+), 0 deletions(-) create mode 100644 plugins/mobile-broadband-provider-info.c diff --git a/plugins/mobile-broadband-provider-info.c b/plugins/mobile-broadband-provider-info.c new file mode 100644 index 0000000..005c526 --- /dev/null +++ b/plugins/mobile-broadband-provider-info.c @@ -0,0 +1,470 @@ +/* + * + * 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 <sys/stat.h> +#include <sys/mman.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <glib.h> + +#define OFONO_API_SUBJECT_TO_CHANGE +#include <ofono/types.h> +#include <ofono/log.h> +#include <ofono/plugin.h> +#include <ofono/modem.h> +#include <ofono/gprs-provision.h> + +#define _(x) case x: return (#x) + +enum element_type { + ELEMENT_APN, + ELEMENT_USAGE, + ELEMENT_PLAN, + ELEMENT_NAME, + ELEMENT_NETWORK_ID, + ELEMENT_USERNAME, + ELEMENT_PASSWORD, + ELEMENT_NONE, +}; + +struct parser_data { + struct ofono_gprs_provision_data **settings; + struct ofono_gprs_provision_data *context; + int count; + const char *match_mcc; + const char *match_mnc; + enum element_type element; + gboolean match_found; +}; + +static const char *element_type_name(enum element_type element) +{ + switch (element) { + _(ELEMENT_APN); + _(ELEMENT_USAGE); + _(ELEMENT_PLAN); + _(ELEMENT_NAME); + _(ELEMENT_NETWORK_ID); + _(ELEMENT_USERNAME); + _(ELEMENT_PASSWORD); + _(ELEMENT_NONE); + } + return "ELEMENT_<UNKNOWN>"; +} + +static const char *context_type_name(enum ofono_gprs_context_type context) +{ + switch (context) { + _(OFONO_GPRS_CONTEXT_TYPE_ANY); + _(OFONO_GPRS_CONTEXT_TYPE_INTERNET); + _(OFONO_GPRS_CONTEXT_TYPE_MMS); + _(OFONO_GPRS_CONTEXT_TYPE_WAP); + _(OFONO_GPRS_CONTEXT_TYPE_IMS); + } + return "OFONO_GPRS_CONTEXT_TYPE_<UNKNOWN>"; +} + +static const char *context_plan_name(enum ofono_gprs_context_plan plan) +{ + switch (plan) { + _(OFONO_GPRS_CONTEXT_PLAN_PREPAID); + _(OFONO_GPRS_CONTEXT_PLAN_POSTPAID); + } + return "OFONO_GPRS_CONTEXT_PLAN_<UNKNOWN>"; +} + +static enum element_type element_type(const gchar *element) +{ + switch (element[0]) { + case 'a': + if (g_str_equal(element, "apn") == TRUE) + return ELEMENT_APN; + break; + case 'n': + if (g_str_equal(element, "name") == TRUE) + return ELEMENT_NAME; + if (g_str_equal(element, "network-id") == TRUE) + return ELEMENT_NETWORK_ID; + break; + case 'p': + if (g_str_equal(element, "plan") == TRUE) + return ELEMENT_PLAN; + if (g_str_equal(element, "password") == TRUE) + return ELEMENT_PASSWORD; + break; + case 'u': + if (g_str_equal(element, "usage") == TRUE) + return ELEMENT_USAGE; + if (g_str_equal(element, "username") == TRUE) + return ELEMENT_USERNAME; + } + + return ELEMENT_NONE; +} + +static void element_network_id_parse(struct parser_data *data, + const gchar **attribute_names, + const gchar **attribute_values) +{ + const char *mcc = NULL, *mnc = NULL; + int i; + + for (i = 0; attribute_names[i]; i++) { + if (g_str_equal(attribute_names[i], "mcc") == TRUE) + mcc = attribute_values[i]; + if (g_str_equal(attribute_names[i], "mnc") == TRUE) + mnc = attribute_values[i]; + } + + if (g_strcmp0(mcc, data->match_mcc) == 0 && + g_strcmp0(mnc, data->match_mnc) == 0) + data->match_found = TRUE; +} + +static struct ofono_gprs_provision_data *apn_try_new(struct parser_data *data) +{ + void *p; + + p = g_try_realloc(*data->settings, + sizeof(struct ofono_gprs_provision_data) * + (data->count + 1)); + if (p == NULL) + return NULL; + + *data->settings = p; + + data->context = *data->settings + data->count++; + + memset(data->context, 0, sizeof(struct ofono_gprs_provision_data)); + + return data->context; +} + +static void element_apn_parse(struct parser_data *data, + const gchar **attribute_names, + const gchar **attribute_values) +{ + const char *apn = NULL; + int i; + + for (i = 0; attribute_names[i]; i++) { + if (g_str_equal(attribute_names[i], "value") == TRUE) + apn = attribute_values[i]; + } + + if (apn_try_new(data) == NULL) { + data->match_found = FALSE; + ofono_error("APN '%s' is ignored, memory exhausted", apn); + return; + } + + data->context->apn = g_strdup(apn); +} + +static void element_usage_parse(struct ofono_gprs_provision_data *context, + const gchar **attribute_names, + const gchar **attribute_values) +{ + const char *usage = NULL; + int i; + + for (i = 0; attribute_names[i]; i++) { + if (g_str_equal(attribute_names[i], "type") == TRUE) + usage = attribute_values[i]; + } + + if (usage == NULL) + return; + + if (g_str_equal(usage, "internet") == TRUE) + context->type = OFONO_GPRS_CONTEXT_TYPE_INTERNET; + else if (g_str_equal(usage, "mms") == TRUE) + context->type = OFONO_GPRS_CONTEXT_TYPE_MMS; + else if (g_str_equal(usage, "wap") == TRUE) + context->type = OFONO_GPRS_CONTEXT_TYPE_WAP; +} + +static void element_plan_parse(struct ofono_gprs_provision_data *context, + const gchar **attribute_names, + const gchar **attribute_values) +{ + const char *plan = NULL; + int i; + + for (i = 0; attribute_names[i]; i++) { + if (g_str_equal(attribute_names[i], "type") == TRUE) + plan = attribute_values[i]; + } + + if (plan == NULL) + return; + + if (g_str_equal(plan, "postpaid") == TRUE) + context->plan = OFONO_GPRS_CONTEXT_PLAN_POSTPAID; + else if (g_str_equal(plan, "prepaid") == TRUE) + context->plan = OFONO_GPRS_CONTEXT_PLAN_PREPAID; +} + +static void element_start_parse(GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, GError **error) +{ + struct parser_data *data = user_data; + + data->element = element_type(element_name); + + if (data->match_found == TRUE) + DBG("%s: '%s'", element_type_name(data->element), element_name); + + if (data->element == ELEMENT_NETWORK_ID) + element_network_id_parse(data, attribute_names, + attribute_values); + if (data->match_found == FALSE) + return; + + switch (data->element) { + case ELEMENT_APN: + element_apn_parse(data, attribute_names, attribute_values); + break; + case ELEMENT_USAGE: + element_usage_parse(data->context, attribute_names, + attribute_values); + break; + case ELEMENT_PLAN: + element_plan_parse(data->context, attribute_names, + attribute_values); + break; + default: + break; + } +} + +static gchar *body_text_parse(const gchar *text, gsize text_len) +{ + gchar *body = g_strndup(text, text_len); + gchar *print = NULL; + int i; + + for (i = 0; body && body[i]; i++) { + if (g_ascii_isprint(body[i])) { + print = g_strescape(body, NULL); + break; + } + } + + if (body) + g_free(body); + + return print; +} + +static void element_body_parse(GMarkupParseContext *context, + const gchar *text, gsize text_len, + gpointer user_data, GError **error) +{ + struct parser_data *data = user_data; + gchar *body; + + if (data->match_found == FALSE || text_len == 0) + return; + + body = body_text_parse(text, text_len); + if (body == NULL) + return; + + DBG("%s: '%s'", element_type_name(data->element), body); + + switch (data->element) { + case ELEMENT_USERNAME: + data->context->username = g_strdup(body); + break; + case ELEMENT_PASSWORD: + data->context->password = g_strdup(body); + break; + case ELEMENT_NAME: + data->context->name = g_strdup(body); + break; + default: + break; + } + + g_free(body); +} + +static void element_end_parse(GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, GError **error) +{ + struct parser_data *data = user_data; + + if (data->match_found == FALSE) + return; + + DBG("%s: '%s'", element_type_name(data->element), element_name); + + if (g_str_equal(element_name, "gsm") == TRUE) + data->match_found = FALSE; +} + +static void parser_error(GMarkupParseContext *context, + GError *error, gpointer user_data) +{ + ofono_error("Error parsing %s: %s", PROVIDER_DATABASE, error->message); +} + +static const GMarkupParser parser = { + element_start_parse, + element_end_parse, + element_body_parse, + NULL, + parser_error, +}; + +static void parse_database(const char *data, ssize_t size, + struct parser_data *parser_data) +{ + GMarkupParseContext *context; + gboolean result; + + parser_data->match_found = FALSE; + + context = g_markup_parse_context_new(&parser, + G_MARKUP_TREAT_CDATA_AS_TEXT, + parser_data, NULL); + + result = g_markup_parse_context_parse(context, data, size, NULL); + if (result == TRUE) + result = g_markup_parse_context_end_parse(context, NULL); + + g_markup_parse_context_free(context); +} + +static int lookup_apn(const char *mcc, const char *mnc, const char *spn, + struct parser_data *data) +{ + struct stat st; + char *map; + int fd; + + if (mcc == NULL || mnc == NULL) + return -1; + + fd = open(PROVIDER_DATABASE, O_RDONLY); + if (fd < 0) + return -1; + + if (fstat(fd, &st) < 0) { + close(fd); + return -1; + } + + map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (map == NULL || map == MAP_FAILED) { + close(fd); + return -1; + } + + data->match_mcc = mcc; + data->match_mnc = mnc; + + parse_database(map, st.st_size, data); + + munmap(map, st.st_size); + + close(fd); + + return data->count; +} + +static int mobile_broadband_provider_info_get(const char *mcc, + const char *mnc, const char *spn, + struct ofono_gprs_provision_data **settings, + int *count) +{ + struct parser_data *data; + int i; + + DBG("Provisioning for MCC %s, MNC %s, SPN '%s'", mcc, mnc, spn); + + *settings = NULL; + *count = 0; + + data = g_try_new0(struct parser_data, 1); + if (data == NULL) + return -ENOMEM; + + data->settings = settings; + + *count = lookup_apn(mcc, mnc, NULL, data); + if (*count <= 0) { + g_free(data); + *settings = NULL; + return -ENOENT; + } + + DBG("settings: %p, count: %d", *settings, *count); + + for (i = 0; i < *count; i++) { + struct ofono_gprs_provision_data *context = *settings + i; + DBG("Name: '%s'", context->name); + DBG("APN: '%s'", context->apn); + DBG("Type: %s", context_type_name(context->type)); + DBG("Plan: %s", context_plan_name(context->plan)); + DBG("Username: '%s'", context->username); + DBG("Password: '%s'", context->password); + } + + g_free(data); + + return 0; +} + +static struct ofono_gprs_provision_driver provider_info = { + .name = "Mobile Broadband Provider Info", + .get_settings = mobile_broadband_provider_info_get +}; + +static int mobile_broadband_provider_info_init(void) +{ + return ofono_gprs_provision_driver_register(&provider_info); +} + +static void mobile_broadband_provider_info_exit(void) +{ + ofono_gprs_provision_driver_unregister(&provider_info); +} + +OFONO_PLUGIN_DEFINE(mobile_broadband_provider_info, + "Mobile Broadband Provider Info Plugin", + VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT, + mobile_broadband_provider_info_init, + mobile_broadband_provider_info_exit) -- 1.7.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCHv3 1/5] Mobile broadband provider info plugin 2011-08-05 12:25 ` [PATCHv3 1/5] " Oleg Zhurakivskyy @ 2011-08-12 6:55 ` Denis Kenzior 2011-08-16 14:11 ` Oleg Zhurakivskyy 0 siblings, 1 reply; 10+ messages in thread From: Denis Kenzior @ 2011-08-12 6:55 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 14388 bytes --] Hi Oleg, On 08/05/2011 07:25 AM, Oleg Zhurakivskyy wrote: > --- > plugins/mobile-broadband-provider-info.c | 470 ++++++++++++++++++++++++++++++ > 1 files changed, 470 insertions(+), 0 deletions(-) > create mode 100644 plugins/mobile-broadband-provider-info.c > > diff --git a/plugins/mobile-broadband-provider-info.c b/plugins/mobile-broadband-provider-info.c > new file mode 100644 > index 0000000..005c526 > --- /dev/null > +++ b/plugins/mobile-broadband-provider-info.c > @@ -0,0 +1,470 @@ > +/* > + * > + * 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 <sys/stat.h> > +#include <sys/mman.h> > + > +#include <errno.h> > +#include <fcntl.h> > +#include <stdlib.h> > +#include <string.h> > +#include <unistd.h> > + > +#include <glib.h> > + > +#define OFONO_API_SUBJECT_TO_CHANGE > +#include <ofono/types.h> > +#include <ofono/log.h> > +#include <ofono/plugin.h> > +#include <ofono/modem.h> > +#include <ofono/gprs-provision.h> > + > +#define _(x) case x: return (#x) > + > +enum element_type { > + ELEMENT_APN, > + ELEMENT_USAGE, > + ELEMENT_PLAN, > + ELEMENT_NAME, > + ELEMENT_NETWORK_ID, > + ELEMENT_USERNAME, > + ELEMENT_PASSWORD, > + ELEMENT_NONE, > +}; > + > +struct parser_data { > + struct ofono_gprs_provision_data **settings; > + struct ofono_gprs_provision_data *context; > + int count; > + const char *match_mcc; > + const char *match_mnc; > + enum element_type element; > + gboolean match_found; > +}; > + > +static const char *element_type_name(enum element_type element) > +{ > + switch (element) { > + _(ELEMENT_APN); > + _(ELEMENT_USAGE); > + _(ELEMENT_PLAN); > + _(ELEMENT_NAME); > + _(ELEMENT_NETWORK_ID); > + _(ELEMENT_USERNAME); > + _(ELEMENT_PASSWORD); > + _(ELEMENT_NONE); > + } > + return "ELEMENT_<UNKNOWN>"; Something is really funky with your whitespace, remember, tabs for indentation, always. > +} > + > +static const char *context_type_name(enum ofono_gprs_context_type context) > +{ > + switch (context) { > + _(OFONO_GPRS_CONTEXT_TYPE_ANY); > + _(OFONO_GPRS_CONTEXT_TYPE_INTERNET); > + _(OFONO_GPRS_CONTEXT_TYPE_MMS); > + _(OFONO_GPRS_CONTEXT_TYPE_WAP); > + _(OFONO_GPRS_CONTEXT_TYPE_IMS); > + } > + return "OFONO_GPRS_CONTEXT_TYPE_<UNKNOWN>"; > +} > + > +static const char *context_plan_name(enum ofono_gprs_context_plan plan) > +{ > + switch (plan) { > + _(OFONO_GPRS_CONTEXT_PLAN_PREPAID); > + _(OFONO_GPRS_CONTEXT_PLAN_POSTPAID); > + } > + return "OFONO_GPRS_CONTEXT_PLAN_<UNKNOWN>"; > +} > + > +static enum element_type element_type(const gchar *element) > +{ > + switch (element[0]) { > + case 'a': > + if (g_str_equal(element, "apn") == TRUE) > + return ELEMENT_APN; > + break; > + case 'n': > + if (g_str_equal(element, "name") == TRUE) > + return ELEMENT_NAME; > + if (g_str_equal(element, "network-id") == TRUE) > + return ELEMENT_NETWORK_ID; > + break; > + case 'p': > + if (g_str_equal(element, "plan") == TRUE) > + return ELEMENT_PLAN; > + if (g_str_equal(element, "password") == TRUE) > + return ELEMENT_PASSWORD; > + break; > + case 'u': > + if (g_str_equal(element, "usage") == TRUE) > + return ELEMENT_USAGE; > + if (g_str_equal(element, "username") == TRUE) > + return ELEMENT_USERNAME; > + } > + > + return ELEMENT_NONE; > +} > + > +static void element_network_id_parse(struct parser_data *data, > + const gchar **attribute_names, > + const gchar **attribute_values) > +{ > + const char *mcc = NULL, *mnc = NULL; > + int i; > + > + for (i = 0; attribute_names[i]; i++) { > + if (g_str_equal(attribute_names[i], "mcc") == TRUE) > + mcc = attribute_values[i]; > + if (g_str_equal(attribute_names[i], "mnc") == TRUE) > + mnc = attribute_values[i]; > + } > + > + if (g_strcmp0(mcc, data->match_mcc) == 0 && > + g_strcmp0(mnc, data->match_mnc) == 0) > + data->match_found = TRUE; > +} > + > +static struct ofono_gprs_provision_data *apn_try_new(struct parser_data *data) > +{ > + void *p; > + > + p = g_try_realloc(*data->settings, > + sizeof(struct ofono_gprs_provision_data) * > + (data->count + 1)); > + if (p == NULL) > + return NULL; > + > + *data->settings = p; > + > + data->context = *data->settings + data->count++; > + > + memset(data->context, 0, sizeof(struct ofono_gprs_provision_data)); This seems like a really big hammer. We have 3 settings we're likely to provision, internet, wap, mms. The function runs synchronously and oFono is not threaded. So in theory you can allocate the context information statically and only copy it to the caller once you have completed the parser. > + > + return data->context; > +} > + > +static void element_apn_parse(struct parser_data *data, > + const gchar **attribute_names, > + const gchar **attribute_values) > +{ > + const char *apn = NULL; > + int i; > + > + for (i = 0; attribute_names[i]; i++) { > + if (g_str_equal(attribute_names[i], "value") == TRUE) > + apn = attribute_values[i]; > + } > + > + if (apn_try_new(data) == NULL) { > + data->match_found = FALSE; > + ofono_error("APN '%s' is ignored, memory exhausted", apn); > + return; > + } > + > + data->context->apn = g_strdup(apn); > +} > + > +static void element_usage_parse(struct ofono_gprs_provision_data *context, > + const gchar **attribute_names, > + const gchar **attribute_values) > +{ > + const char *usage = NULL; > + int i; > + > + for (i = 0; attribute_names[i]; i++) { > + if (g_str_equal(attribute_names[i], "type") == TRUE) > + usage = attribute_values[i]; > + } > + > + if (usage == NULL) > + return; > + > + if (g_str_equal(usage, "internet") == TRUE) > + context->type = OFONO_GPRS_CONTEXT_TYPE_INTERNET; > + else if (g_str_equal(usage, "mms") == TRUE) > + context->type = OFONO_GPRS_CONTEXT_TYPE_MMS; > + else if (g_str_equal(usage, "wap") == TRUE) > + context->type = OFONO_GPRS_CONTEXT_TYPE_WAP; > +} > + > +static void element_plan_parse(struct ofono_gprs_provision_data *context, > + const gchar **attribute_names, > + const gchar **attribute_values) > +{ > + const char *plan = NULL; > + int i; > + > + for (i = 0; attribute_names[i]; i++) { > + if (g_str_equal(attribute_names[i], "type") == TRUE) > + plan = attribute_values[i]; > + } > + > + if (plan == NULL) > + return; > + > + if (g_str_equal(plan, "postpaid") == TRUE) > + context->plan = OFONO_GPRS_CONTEXT_PLAN_POSTPAID; > + else if (g_str_equal(plan, "prepaid") == TRUE) > + context->plan = OFONO_GPRS_CONTEXT_PLAN_PREPAID; > +} > + > +static void element_start_parse(GMarkupParseContext *context, > + const gchar *element_name, > + const gchar **attribute_names, > + const gchar **attribute_values, > + gpointer user_data, GError **error) > +{ > + struct parser_data *data = user_data; > + > + data->element = element_type(element_name); > + > + if (data->match_found == TRUE) > + DBG("%s: '%s'", element_type_name(data->element), element_name); > + > + if (data->element == ELEMENT_NETWORK_ID) > + element_network_id_parse(data, attribute_names, > + attribute_values); > + if (data->match_found == FALSE) > + return; > + > + switch (data->element) { > + case ELEMENT_APN: > + element_apn_parse(data, attribute_names, attribute_values); > + break; > + case ELEMENT_USAGE: > + element_usage_parse(data->context, attribute_names, > + attribute_values); > + break; > + case ELEMENT_PLAN: > + element_plan_parse(data->context, attribute_names, > + attribute_values); > + break; > + default: > + break; > + } > +} > + > +static gchar *body_text_parse(const gchar *text, gsize text_len) > +{ > + gchar *body = g_strndup(text, text_len); > + gchar *print = NULL; > + int i; > + > + for (i = 0; body && body[i]; i++) { > + if (g_ascii_isprint(body[i])) { > + print = g_strescape(body, NULL); > + break; > + } > + } > + > + if (body) > + g_free(body); > + > + return print; > +} > + > +static void element_body_parse(GMarkupParseContext *context, > + const gchar *text, gsize text_len, > + gpointer user_data, GError **error) > +{ > + struct parser_data *data = user_data; > + gchar *body; > + > + if (data->match_found == FALSE || text_len == 0) > + return; > + > + body = body_text_parse(text, text_len); > + if (body == NULL) > + return; > + > + DBG("%s: '%s'", element_type_name(data->element), body); > + > + switch (data->element) { > + case ELEMENT_USERNAME: > + data->context->username = g_strdup(body); > + break; > + case ELEMENT_PASSWORD: > + data->context->password = g_strdup(body); > + break; > + case ELEMENT_NAME: > + data->context->name = g_strdup(body); > + break; > + default: > + break; > + } > + > + g_free(body); > +} > + > +static void element_end_parse(GMarkupParseContext *context, > + const gchar *element_name, > + gpointer user_data, GError **error) > +{ > + struct parser_data *data = user_data; > + > + if (data->match_found == FALSE) > + return; > + > + DBG("%s: '%s'", element_type_name(data->element), element_name); > + > + if (g_str_equal(element_name, "gsm") == TRUE) > + data->match_found = FALSE; > +} > + Maybe I'm just not seeing it, but how are we handling duplicates? E.g. the case where mcc/mncs match but correspond to two different operators. Or where we find multiple matches of the same context type. > +static void parser_error(GMarkupParseContext *context, > + GError *error, gpointer user_data) > +{ > + ofono_error("Error parsing %s: %s", PROVIDER_DATABASE, error->message); > +} > + > +static const GMarkupParser parser = { > + element_start_parse, > + element_end_parse, > + element_body_parse, > + NULL, > + parser_error, > +}; > + > +static void parse_database(const char *data, ssize_t size, > + struct parser_data *parser_data) > +{ > + GMarkupParseContext *context; > + gboolean result; > + > + parser_data->match_found = FALSE; > + > + context = g_markup_parse_context_new(&parser, > + G_MARKUP_TREAT_CDATA_AS_TEXT, > + parser_data, NULL); > + > + result = g_markup_parse_context_parse(context, data, size, NULL); > + if (result == TRUE) > + result = g_markup_parse_context_end_parse(context, NULL); > + > + g_markup_parse_context_free(context); > +} > + > +static int lookup_apn(const char *mcc, const char *mnc, const char *spn, > + struct parser_data *data) > +{ > + struct stat st; > + char *map; > + int fd; > + > + if (mcc == NULL || mnc == NULL) > + return -1; > + > + fd = open(PROVIDER_DATABASE, O_RDONLY); > + if (fd < 0) > + return -1; > + > + if (fstat(fd, &st) < 0) { > + close(fd); > + return -1; > + } > + > + map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); > + if (map == NULL || map == MAP_FAILED) { man mmap tells me that MAP_FAILED is the only error condition. Why are we checking for NULL as well? > + close(fd); > + return -1; > + } > + > + data->match_mcc = mcc; > + data->match_mnc = mnc; > + > + parse_database(map, st.st_size, data); > + > + munmap(map, st.st_size); > + > + close(fd); > + > + return data->count; > +} > + > +static int mobile_broadband_provider_info_get(const char *mcc, > + const char *mnc, const char *spn, > + struct ofono_gprs_provision_data **settings, > + int *count) > +{ > + struct parser_data *data; > + int i; > + > + DBG("Provisioning for MCC %s, MNC %s, SPN '%s'", mcc, mnc, spn); > + > + *settings = NULL; > + *count = 0; In general I like not to modify the output args unless the function is on the success path. > + > + data = g_try_new0(struct parser_data, 1); > + if (data == NULL) > + return -ENOMEM; > + As mentioned before the parser is running synchronously, so this could actually be statically allocated. > + data->settings = settings; > + > + *count = lookup_apn(mcc, mnc, NULL, data); > + if (*count <= 0) { > + g_free(data); > + *settings = NULL; > + return -ENOENT; > + } > + > + DBG("settings: %p, count: %d", *settings, *count); > + > + for (i = 0; i < *count; i++) { > + struct ofono_gprs_provision_data *context = *settings + i; > + DBG("Name: '%s'", context->name); > + DBG("APN: '%s'", context->apn); > + DBG("Type: %s", context_type_name(context->type)); > + DBG("Plan: %s", context_plan_name(context->plan)); > + DBG("Username: '%s'", context->username); > + DBG("Password: '%s'", context->password); > + } > + > + g_free(data); > + > + return 0; > +} > + > +static struct ofono_gprs_provision_driver provider_info = { > + .name = "Mobile Broadband Provider Info", > + .get_settings = mobile_broadband_provider_info_get > +}; > + > +static int mobile_broadband_provider_info_init(void) > +{ > + return ofono_gprs_provision_driver_register(&provider_info); > +} > + > +static void mobile_broadband_provider_info_exit(void) > +{ > + ofono_gprs_provision_driver_unregister(&provider_info); > +} > + > +OFONO_PLUGIN_DEFINE(mobile_broadband_provider_info, > + "Mobile Broadband Provider Info Plugin", > + VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT, > + mobile_broadband_provider_info_init, > + mobile_broadband_provider_info_exit) Regards, -Denis ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCHv3 1/5] Mobile broadband provider info plugin 2011-08-12 6:55 ` Denis Kenzior @ 2011-08-16 14:11 ` Oleg Zhurakivskyy 2011-08-18 18:37 ` Denis Kenzior 0 siblings, 1 reply; 10+ messages in thread From: Oleg Zhurakivskyy @ 2011-08-16 14:11 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 1143 bytes --] Hello Denis, On 08/12/2011 09:55 AM, Denis Kenzior wrote: >> +static struct ofono_gprs_provision_data *apn_try_new(struct parser_data *data) >> +{ >> + void *p; >> + >> + p = g_try_realloc(*data->settings, >> + sizeof(struct ofono_gprs_provision_data) * >> + (data->count + 1)); >> + if (p == NULL) >> + return NULL; >> + >> + *data->settings = p; >> + >> + data->context = *data->settings + data->count++; >> + >> + memset(data->context, 0, sizeof(struct ofono_gprs_provision_data)); > > This seems like a really big hammer. We have 3 settings we're likely to > provision, internet, wap, mms. The function runs synchronously and > oFono is not threaded. So in theory you can allocate the context > information statically and only copy it to the caller once you have > completed the parser. Hmm, statically allocated array of settings was in the previous version. Then the wish was to make it dynamic and to use realloc. Can we settle on an approach here? Regards, Oleg -- Intel Finland Oy Registered Address: PL 281, 00181 Helsinki Business Identity Code: 0357606 - 4 Domiciled in Helsinki ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCHv3 1/5] Mobile broadband provider info plugin 2011-08-16 14:11 ` Oleg Zhurakivskyy @ 2011-08-18 18:37 ` Denis Kenzior 0 siblings, 0 replies; 10+ messages in thread From: Denis Kenzior @ 2011-08-18 18:37 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 1686 bytes --] Hi Oleg, On 08/16/2011 09:11 AM, Oleg Zhurakivskyy wrote: > Hello Denis, > > On 08/12/2011 09:55 AM, Denis Kenzior wrote: >>> +static struct ofono_gprs_provision_data *apn_try_new(struct >>> parser_data *data) >>> +{ >>> + void *p; >>> + >>> + p = g_try_realloc(*data->settings, >>> + sizeof(struct ofono_gprs_provision_data) * >>> + (data->count + 1)); >>> + if (p == NULL) >>> + return NULL; >>> + >>> + *data->settings = p; >>> + >>> + data->context = *data->settings + data->count++; >>> + >>> + memset(data->context, 0, sizeof(struct ofono_gprs_provision_data)); >> >> This seems like a really big hammer. We have 3 settings we're likely to >> provision, internet, wap, mms. The function runs synchronously and >> oFono is not threaded. So in theory you can allocate the context >> information statically and only copy it to the caller once you have >> completed the parser. > > Hmm, statically allocated array of settings was in the previous version. > Then the wish was to make it dynamic and to use realloc. Can we settle > on an approach here? > The preference is to always allocate statically if you can get away with it; if you do not need to use malloc/realloc, then please don't. I do not believe the earlier feedback you received is in conflict here. Using a static array for the parser and only allocating the return array is the preferred approach since we should not be returning more than 1 internet, 1 wap and 1 mms setting. If you have multiple of any of these then you should not provision as it indicates that user's input is required. Regards, -Denis ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCHv3 2/5] GPRS context plan support 2011-08-05 12:25 [PATCHv3 0/5] Mobile broadband provider info plugin Oleg Zhurakivskyy 2011-08-05 12:25 ` [PATCHv3 1/5] " Oleg Zhurakivskyy @ 2011-08-05 12:25 ` Oleg Zhurakivskyy 2011-08-12 6:43 ` Denis Kenzior 2011-08-05 12:26 ` [PATCHv3 3/5] GPRS provisioning data " Oleg Zhurakivskyy ` (2 subsequent siblings) 4 siblings, 1 reply; 10+ messages in thread From: Oleg Zhurakivskyy @ 2011-08-05 12:25 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 545 bytes --] --- include/gprs-context.h | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/include/gprs-context.h b/include/gprs-context.h index f82fcaa..8dfc106 100644 --- a/include/gprs-context.h +++ b/include/gprs-context.h @@ -48,6 +48,11 @@ enum ofono_gprs_context_type { OFONO_GPRS_CONTEXT_TYPE_IMS, }; +enum ofono_gprs_context_plan { + OFONO_GPRS_CONTEXT_PLAN_PREPAID, + OFONO_GPRS_CONTEXT_PLAN_POSTPAID, +}; + struct ofono_gprs_primary_context { unsigned int cid; int direction; -- 1.7.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCHv3 2/5] GPRS context plan support 2011-08-05 12:25 ` [PATCHv3 2/5] GPRS context plan support Oleg Zhurakivskyy @ 2011-08-12 6:43 ` Denis Kenzior 0 siblings, 0 replies; 10+ messages in thread From: Denis Kenzior @ 2011-08-12 6:43 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 889 bytes --] Hi Oleg, On 08/05/2011 07:25 AM, Oleg Zhurakivskyy wrote: > --- > include/gprs-context.h | 5 +++++ > 1 files changed, 5 insertions(+), 0 deletions(-) > Logically this patch is out of order since you make use of these defines in Patch 1. > diff --git a/include/gprs-context.h b/include/gprs-context.h > index f82fcaa..8dfc106 100644 > --- a/include/gprs-context.h > +++ b/include/gprs-context.h > @@ -48,6 +48,11 @@ enum ofono_gprs_context_type { > OFONO_GPRS_CONTEXT_TYPE_IMS, > }; > > +enum ofono_gprs_context_plan { > + OFONO_GPRS_CONTEXT_PLAN_PREPAID, > + OFONO_GPRS_CONTEXT_PLAN_POSTPAID, > +}; > + What exactly is the usecase here? oFono doesn't really care whether a plan is prepaid or postpaid, that is information purely for the UI. > struct ofono_gprs_primary_context { > unsigned int cid; > int direction; Regards, -Denis ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCHv3 3/5] GPRS provisioning data plan support 2011-08-05 12:25 [PATCHv3 0/5] Mobile broadband provider info plugin Oleg Zhurakivskyy 2011-08-05 12:25 ` [PATCHv3 1/5] " Oleg Zhurakivskyy 2011-08-05 12:25 ` [PATCHv3 2/5] GPRS context plan support Oleg Zhurakivskyy @ 2011-08-05 12:26 ` Oleg Zhurakivskyy 2011-08-05 12:26 ` [PATCHv3 4/5] Mobile broadband provider info plugin autoconf support Oleg Zhurakivskyy 2011-08-05 12:26 ` [PATCHv3 5/5] Mobile broadband provider info plugin makefile changes Oleg Zhurakivskyy 4 siblings, 0 replies; 10+ messages in thread From: Oleg Zhurakivskyy @ 2011-08-05 12:26 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 478 bytes --] --- include/gprs-provision.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/include/gprs-provision.h b/include/gprs-provision.h index e9eec61..2273a09 100644 --- a/include/gprs-provision.h +++ b/include/gprs-provision.h @@ -30,6 +30,7 @@ extern "C" { struct ofono_gprs_provision_data { enum ofono_gprs_context_type type; + enum ofono_gprs_context_plan plan; enum ofono_gprs_proto proto; char *name; char *apn; -- 1.7.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCHv3 4/5] Mobile broadband provider info plugin autoconf support 2011-08-05 12:25 [PATCHv3 0/5] Mobile broadband provider info plugin Oleg Zhurakivskyy ` (2 preceding siblings ...) 2011-08-05 12:26 ` [PATCHv3 3/5] GPRS provisioning data " Oleg Zhurakivskyy @ 2011-08-05 12:26 ` Oleg Zhurakivskyy 2011-08-05 12:26 ` [PATCHv3 5/5] Mobile broadband provider info plugin makefile changes Oleg Zhurakivskyy 4 siblings, 0 replies; 10+ messages in thread From: Oleg Zhurakivskyy @ 2011-08-05 12:26 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 1478 bytes --] --- configure.ac | 19 +++++++++++++------ 1 files changed, 13 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index a6b4094..966237c 100644 --- a/configure.ac +++ b/configure.ac @@ -197,14 +197,21 @@ AC_SUBST(BLUEZ_CFLAGS) AC_SUBST(BLUEZ_LIBS) AM_CONDITIONAL(BLUETOOTH, test "${enable_bluetooth}" != "no") -AC_MSG_CHECKING([for mobile-broadband-provider-info]) -PKG_CHECK_EXISTS(mobile-broadband-provider-info, - _PKG_CONFIG(PROVIDER_DATABASE, [variable=database], +AC_ARG_ENABLE(provider-info, AC_HELP_STRING([--enable-provider-info], + [enable mobile provider database support]), + [enable_provider_info=${enableval}]) +if (test "${enable_provider_info}" == "yes"); then + AC_MSG_CHECKING([for mobile-broadband-provider-info]) + PKG_CHECK_EXISTS(mobile-broadband-provider-info, + _PKG_CONFIG(PROVIDER_DATABASE, [variable=database], [mobile-broadband-provider-info]) - AC_DEFINE_UNQUOTED(PROVIDER_DATABASE, "$pkg_cv_PROVIDER_DATABASE", + AC_DEFINE_UNQUOTED(PROVIDER_DATABASE, + "$pkg_cv_PROVIDER_DATABASE", [Mobile provider database]) - AC_MSG_RESULT([yes]), - AC_MSG_RESULT([no])) + AC_MSG_RESULT([yes]), + AC_MSG_ERROR(mobile-broadband-provider-info package is required)) +fi +AM_CONDITIONAL(PROVIDER_INFO, test "${enable_provider_info}" == "yes") AC_ARG_ENABLE(datafiles, AC_HELP_STRING([--disable-datafiles], [don't install configuration and data files]), -- 1.7.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCHv3 5/5] Mobile broadband provider info plugin makefile changes 2011-08-05 12:25 [PATCHv3 0/5] Mobile broadband provider info plugin Oleg Zhurakivskyy ` (3 preceding siblings ...) 2011-08-05 12:26 ` [PATCHv3 4/5] Mobile broadband provider info plugin autoconf support Oleg Zhurakivskyy @ 2011-08-05 12:26 ` Oleg Zhurakivskyy 4 siblings, 0 replies; 10+ messages in thread From: Oleg Zhurakivskyy @ 2011-08-05 12:26 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 855 bytes --] --- Makefile.am | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Makefile.am b/Makefile.am index 6f5d921..7df0fd3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -358,6 +358,11 @@ builtin_libadd += @BLUEZ_LIBS@ endif endif +if PROVIDER_INFO +builtin_modules += mobile_broadband_provider_info +builtin_sources += plugins/mobile-broadband-provider-info.c +endif + if MAINTAINER_MODE builtin_modules += example_history builtin_sources += examples/history.c @@ -365,8 +370,10 @@ builtin_sources += examples/history.c builtin_modules += example_nettime builtin_sources += examples/nettime.c +if !PROVIDER_INFO builtin_modules += example_provision builtin_sources += examples/provision.c +endif builtin_modules += example_emulator builtin_sources += examples/emulator.c -- 1.7.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-08-18 18:37 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-08-05 12:25 [PATCHv3 0/5] Mobile broadband provider info plugin Oleg Zhurakivskyy 2011-08-05 12:25 ` [PATCHv3 1/5] " Oleg Zhurakivskyy 2011-08-12 6:55 ` Denis Kenzior 2011-08-16 14:11 ` Oleg Zhurakivskyy 2011-08-18 18:37 ` Denis Kenzior 2011-08-05 12:25 ` [PATCHv3 2/5] GPRS context plan support Oleg Zhurakivskyy 2011-08-12 6:43 ` Denis Kenzior 2011-08-05 12:26 ` [PATCHv3 3/5] GPRS provisioning data " Oleg Zhurakivskyy 2011-08-05 12:26 ` [PATCHv3 4/5] Mobile broadband provider info plugin autoconf support Oleg Zhurakivskyy 2011-08-05 12:26 ` [PATCHv3 5/5] Mobile broadband provider info plugin makefile changes Oleg Zhurakivskyy
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.