static void update_char_format(guint8 status, const guint8 *pdu, guint16 len, gpointer user_data) { struct query_data *current = user_data; struct gatt_service *gatt = current->gatt; struct characteristic *chr = current->chr; INFO("%s",chr->path); if (status != 0) goto done; if (len < 8) goto done; g_free(chr->format); chr->format = g_new0(struct format, 1); memcpy(chr->format, pdu + 1, 7); store_attribute(gatt, current->handle, GATT_CHARAC_FMT_UUID, (void *) chr->format, sizeof(*chr->format)); done: add_characteristic_descriptor(current, GATT_CHARAC_FMT_UUID); query_list_remove(gatt, current); g_free(current); }
/*! \brief Copies the attributes of another Config object. \param[in] Data Config object used for the source of the attributes to copied. */ void dmz::Config::copy_attributes (const Config &Data) { ConfigIterator it; String name, value; while (Data.get_next_attribute (it, name, value)) { store_attribute (name, value); } }
static void update_char_desc(guint8 status, const guint8 *pdu, guint16 len, gpointer user_data) { struct query_data *current = user_data; struct gatt_service *gatt = current->gatt; struct characteristic *chr = current->chr; INFO("%s",chr->path); if (status == 0) { g_free(chr->desc); chr->desc = g_malloc(len); memcpy(chr->desc, pdu + 1, len - 1); chr->desc[len - 1] = '\0'; store_attribute(gatt, current->handle, GATT_CHARAC_USER_DESC_UUID, (void *) chr->desc, len); } else if (status == ATT_ECODE_INSUFF_ENC) { GIOChannel *io = g_attrib_get_channel(gatt->attrib); BtIOSecLevel level = BT_IO_SEC_HIGH; bt_io_get(io, BT_IO_L2CAP, NULL, BT_IO_OPT_SEC_LEVEL, &level, BT_IO_OPT_INVALID); if (level < BT_IO_SEC_HIGH) level++; if (bt_io_set(io, BT_IO_L2CAP, NULL, BT_IO_OPT_SEC_LEVEL, level, BT_IO_OPT_INVALID)) { gatt_read_char(gatt->attrib, current->handle, 0, update_char_desc, current); return; } } add_characteristic_descriptor(current, GATT_CHARAC_USER_DESC_UUID); query_list_remove(gatt, current); g_free(current); }
static void update_char_ext_props(guint8 status, const guint8 *pdu, guint16 len, gpointer user_data) { struct query_data *current = user_data; struct gatt_service *gatt = current->gatt; struct characteristic *chr = current->chr; INFO("%s",chr->path); if (status != 0) goto done; chr->ext_properties = att_get_u16(pdu + 1); chr->extprops_handle = current->handle; store_attribute(gatt, current->handle, GATT_CHARAC_EXT_PROPER_UUID, (void*)&chr->ext_properties, sizeof(chr->ext_properties)); done: add_characteristic_descriptor(current, GATT_CHARAC_EXT_PROPER_UUID); query_list_remove(gatt, current); g_free(current); }
static void update_char_client_conf(guint8 status, const guint8 *pdu, guint16 len, gpointer user_data) { struct query_data *current = user_data; struct gatt_service *gatt = current->gatt; struct characteristic *chr = current->chr; INFO("%s",chr->path); if (status != 0) goto done; chr->client_config = pdu[1]; chr->ccc_handle = current->handle; store_attribute(gatt, current->handle, GATT_CLIENT_CHARAC_CFG_UUID, (void*)&chr->client_config, sizeof(chr->client_config)); done: add_characteristic_descriptor(current, GATT_CLIENT_CHARAC_CFG_UUID); query_list_remove(gatt, current); g_free(current); }
/** Try to load all the attributes in our rule set. If none are found, or an error occurs, return NULL and move on to the next one. @param rule Resource rule set to use when looking for data @param base Base XPath path to start with. @return New resource if legal or NULL on failure/error */ resource_t * load_resource(resource_rule_t * rule, const char *base) { resource_t *res; char ccspath[1024]; char *attrname, *attr; int x, found = 0, flags; res = malloc(sizeof(*res)); if (!res) { fprintf(stderr, "Out of memory\n"); return NULL; } memset(res, 0, sizeof(*res)); res->r_rule = rule; for (x = 0; res->r_rule->rr_attrs && res->r_rule->rr_attrs[x].ra_name; x++) { flags = rule->rr_attrs[x].ra_flags; attrname = strdup(rule->rr_attrs[x].ra_name); if (!attrname) { destroy_resource(res); return NULL; } /* Ask CCS for the respective attribute */ attr = NULL; /* XXX check */ snprintf(ccspath, sizeof(ccspath), "%s/@%s", base, attrname); if (conf_get(ccspath, &attr) != 0) { if (flags & (RA_REQUIRED | RA_PRIMARY)) { /* Missing required attribute. We're done. */ free(attrname); destroy_resource(res); return NULL; } if (!(flags & RA_INHERIT)) { /* If we don't have the inherit flag, see if we have a value anyway. If we do, this value is the default value, and should be used. */ if (!rule->rr_attrs[x].ra_value) { free(attrname); continue; } /* Copy default value from resource rule */ /* XXX check */ attr = strdup(rule->rr_attrs[x].ra_value); } } found = 1; /* If we are supposed to inherit and we don't have an instance of the specified attribute in CCS, then we keep the inherit flag and use it as the attribute. However, if we _do_ have the attribute for this instance, we drop the inherit flag and use the attribute. */ if (flags & RA_INHERIT) { if (attr) { flags &= ~RA_INHERIT; } else { attr = strdup(rule->rr_attrs[x].ra_value); if (!attr) { destroy_resource(res); free(attrname); return NULL; } } } /* Store the attribute. We'll ensure all required attributes are present soon. */ if (attrname && attr) /* XXX check */ store_attribute(&res->r_attrs, attrname, attr, flags); } if (!found) { destroy_resource(res); return NULL; } /* XXX check, not checking leads to unexpected flow trace */ res->r_actions = act_dup(rule->rr_actions); _get_actions_ccs(base, res); return res; }
/** Get and store attributes for a given instance of a resource rule. @param doc Pre-parsed XML document pointer. @param ctx Pre-allocated XML XPath context pointer. @param base XPath prefix to search @param rr Resource rule to store new information in. @return 0 */ static int _get_rule_attrs(xmlDocPtr doc, xmlXPathContextPtr ctx, const char *base, resource_rule_t * rr) { char *ret, *attrname, *dflt = NULL, xpath[256]; int x, flags, primary_found = 0; for (x = 1; 1; x++) { snprintf(xpath, sizeof(xpath), "%s/parameter[%d]/@name", base, x); ret = xpath_get_one(doc, ctx, xpath); if (!ret) break; flags = 0; attrname = ret; /* See if there's a default value. */ snprintf(xpath, sizeof(xpath), "%s/parameter[%d]/content/@default", base, x); dflt = xpath_get_one(doc, ctx, xpath); /* See if this is either the primary identifier or a required field. */ snprintf(xpath, sizeof(xpath), "%s/parameter[%d]/@required", base, x); if ((ret = xpath_get_one(doc, ctx, xpath))) { if ((atoi(ret) != 0) || (ret[0] == 'y')) flags |= RA_REQUIRED; free(ret); } /* See if this is supposed to be unique */ snprintf(xpath, sizeof(xpath), "%s/parameter[%d]/@unique", base, x); if ((ret = xpath_get_one(doc, ctx, xpath))) { if ((atoi(ret) != 0) || (ret[0] == 'y')) flags |= RA_UNIQUE; free(ret); } snprintf(xpath, sizeof(xpath), "%s/parameter[%d]/@primary", base, x); if ((ret = xpath_get_one(doc, ctx, xpath))) { if ((atoi(ret) != 0) || (ret[0] == 'y')) { if (primary_found) { free(ret); fprintf(stderr, "Multiple primary " "definitions for " "resource type %s\n", rr->rr_type); return -1; } flags |= RA_PRIMARY; primary_found = 1; } free(ret); } /* See if this can be reconfigured on the fly without a stop/start */ snprintf(xpath, sizeof(xpath), "%s/parameter[%d]/@reconfig", base, x); if ((ret = xpath_get_one(doc, ctx, xpath))) { if ((atoi(ret) != 0) || (ret[0] == 'y')) flags |= RA_RECONFIG; free(ret); } /* See if this is supposed to be inherited */ snprintf(xpath, sizeof(xpath), "%s/parameter[%d]/@inherit", base, x); if ((ret = xpath_get_one(doc, ctx, xpath))) { flags |= RA_INHERIT; if (flags & (RA_REQUIRED | RA_PRIMARY | RA_UNIQUE)) { free(ret); fprintf(stderr, "Can not inherit and be primary, " "unique, or required\n"); return -1; } /* don't free ret. Store as attr value. If we had a default value specified from above, free it; inheritance supercedes a specified default value. */ if (dflt) free(dflt); } else { /* Use default value, if specified, as the attribute value. */ ret = dflt; } /* Store the attribute. We'll ensure all required attributes are present soon. */ if (attrname) store_attribute(&rr->rr_attrs, attrname, ret, flags); } return 0; }