uint8_t bootstrap_handleRequest(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, void * fromSessionH, coap_packet_t * message, coap_packet_t * response) { uint8_t result; char * name; LOG_URI(uriP); if (contextP->bootstrapCallback == NULL) return COAP_500_INTERNAL_SERVER_ERROR; if (message->code != COAP_POST) return COAP_400_BAD_REQUEST; if (message->uri_query == NULL) return COAP_400_BAD_REQUEST; if (message->payload != NULL) return COAP_400_BAD_REQUEST; if (lwm2m_strncmp((char *)message->uri_query->data, QUERY_NAME, QUERY_NAME_LEN) != 0) { return COAP_400_BAD_REQUEST; } if (message->uri_query->len == QUERY_NAME_LEN) return COAP_400_BAD_REQUEST; if (message->uri_query->next != NULL) return COAP_400_BAD_REQUEST; name = (char *)lwm2m_malloc(message->uri_query->len - QUERY_NAME_LEN + 1); if (name == NULL) return COAP_500_INTERNAL_SERVER_ERROR; memcpy(name, message->uri_query->data + QUERY_NAME_LEN, message->uri_query->len - QUERY_NAME_LEN); name[message->uri_query->len - QUERY_NAME_LEN] = 0; result = contextP->bootstrapCallback(fromSessionH, COAP_NO_ERROR, NULL, name, contextP->bootstrapUserData); lwm2m_free(name); return result; }
static lwm2m_client_object_t * prv_decodeRegisterPayload(uint8_t * payload, uint16_t payloadLength, char ** altPath) { lwm2m_client_object_t * objList; uint16_t id; uint16_t instance; uint16_t start; uint16_t end; int result; uint16_t altPathStart; uint16_t altPathEnd; uint16_t altPathLen; objList = NULL; start = 0; altPathStart = 0; altPathEnd = 0; altPathLen = 0; *altPath = NULL; // Does the registration payload begin with an alternative path ? while (start < payloadLength && payload[start] == ' ') start++; if (start != payloadLength) { if (payload[start] == '<') { altPathStart = start + 1; } while (start < payloadLength - 1 && payload[start] != '>') start++; if (start != payloadLength - 1) { altPathEnd = start - 1; if ((payloadLength > altPathEnd + REG_LWM2M_RESOURCE_TYPE_LEN) && (0 == lwm2m_strncmp(REG_LWM2M_RESOURCE_TYPE, (char *) payload + altPathEnd + 1, REG_LWM2M_RESOURCE_TYPE_LEN))) { payload[altPathEnd + 1] = 0; *altPath = lwm2m_strdup((char *)payload + altPathStart); if (*altPath == NULL) return NULL; if (0 == prv_isAltPathValid(*altPath)) { return NULL; } altPathLen = altPathEnd - altPathStart + 1; } } } if (altPathLen != 0) { start = altPathEnd + 1 + REG_LWM2M_RESOURCE_TYPE_LEN; // If declared alternative path is "/", use NULL instead if (altPathLen == 1) { lwm2m_free(*altPath); *altPath = NULL; } } else { start = 0; } while (start < payloadLength) { while (start < payloadLength && payload[start] == ' ') start++; if (start == payloadLength) return objList; end = start; while (end < payloadLength && payload[end] != ',') end++; result = prv_getId(payload + start, end - start, *altPath, altPathLen, &id, &instance); if (result != 0) { lwm2m_client_object_t * objectP; objectP = (lwm2m_client_object_t *)lwm2m_list_find((lwm2m_list_t *)objList, id); if (objectP == NULL) { objectP = (lwm2m_client_object_t *)lwm2m_malloc(sizeof(lwm2m_client_object_t)); memset(objectP, 0, sizeof(lwm2m_client_object_t)); if (objectP == NULL) return objList; objectP->id = id; objList = (lwm2m_client_object_t *)LWM2M_LIST_ADD(objList, objectP); } if (result == 2) { lwm2m_list_t * instanceP; instanceP = lwm2m_list_find(objectP->instanceList, instance); if (instanceP == NULL) { instanceP = (lwm2m_list_t *)lwm2m_malloc(sizeof(lwm2m_list_t)); memset(instanceP, 0, sizeof(lwm2m_list_t)); instanceP->id = instance; objectP->instanceList = LWM2M_LIST_ADD(objectP->instanceList, instanceP); } } } start = end + 1; } return objList; }
static int prv_getId(uint8_t * data, uint16_t length, char * altPath, uint16_t altPathLen, uint16_t * objId, uint16_t * instanceId) { int value; uint16_t limit; uint16_t end; // Expecting application/link-format (RFC6690) // strip open and close tags if (length >= 1 && data[0] == '<' && data[length-1] == '>') { data++; length-=2; } else { return 0; } if (altPath != NULL) { if (length <= altPathLen) return 0; if (0 != lwm2m_strncmp((char *)data, altPath, altPathLen)) return 0; data += altPathLen; length -= altPathLen; } // If there is a preceding /, remove it if (length >= 1 && data[0] == '/') { data++; length-=1; } limit = 0; while (limit < length && data[limit] != '/' && data[limit] != ' ') limit++; value = prv_get_number(data, limit); if (value < 0 || value >= LWM2M_MAX_ID) return 0; *objId = value; if (limit != length) { limit += 1; end = limit; while (end < length && data[end] != ' ') end++; if (end != limit) { value = prv_get_number(data + limit, end - limit); if (value >= 0 && value < LWM2M_MAX_ID) { *instanceId = value; return 2; } } } return 1; }
static int prv_getParameters(multi_option_t * query, char ** nameP, uint32_t * lifetimeP, char ** msisdnP, lwm2m_binding_t * bindingP) { *nameP = NULL; *lifetimeP = 0; *msisdnP = NULL; *bindingP = BINDING_UNKNOWN; while (query != NULL) { if (lwm2m_strncmp((char *)query->data, QUERY_TEMPLATE, QUERY_LENGTH) == 0) { if (*nameP != NULL) goto error; if (query->len == QUERY_LENGTH) goto error; *nameP = (char *)lwm2m_malloc(query->len - QUERY_LENGTH + 1); if (*nameP != NULL) { memcpy(*nameP, query->data + QUERY_LENGTH, query->len - QUERY_LENGTH); (*nameP)[query->len - QUERY_LENGTH] = 0; } } else if (lwm2m_strncmp((char *)query->data, QUERY_SMS, QUERY_SMS_LEN) == 0) { if (*msisdnP != NULL) goto error; if (query->len == QUERY_SMS_LEN) goto error; *msisdnP = (char *)lwm2m_malloc(query->len - QUERY_SMS_LEN + 1); if (*msisdnP != NULL) { memcpy(*msisdnP, query->data + QUERY_SMS_LEN, query->len - QUERY_SMS_LEN); (*msisdnP)[query->len - QUERY_SMS_LEN] = 0; } } else if (lwm2m_strncmp((char *)query->data, QUERY_LIFETIME, QUERY_LIFETIME_LEN) == 0) { int i; if (*lifetimeP != 0) goto error; if (query->len == QUERY_LIFETIME_LEN) goto error; for (i = QUERY_LIFETIME_LEN ; i < query->len ; i++) { if (query->data[i] < '0' || query->data[i] > '9') goto error; *lifetimeP = (*lifetimeP * 10) + (query->data[i] - '0'); } } else if (lwm2m_strncmp((char *)query->data, QUERY_VERSION, QUERY_VERSION_LEN) == 0) { if ((query->len != QUERY_VERSION_FULL_LEN) || (lwm2m_strncmp((char *)query->data, QUERY_VERSION_FULL, QUERY_VERSION_FULL_LEN) != 0)) { goto error; } } else if (lwm2m_strncmp((char *)query->data, QUERY_BINDING, QUERY_BINDING_LEN) == 0) { if (*bindingP != BINDING_UNKNOWN) goto error; if (query->len == QUERY_BINDING_LEN) goto error; *bindingP = lwm2m_stringToBinding(query->data + QUERY_BINDING_LEN, query->len - QUERY_BINDING_LEN); } query = query->next; } return 0; error: if (*nameP != NULL) lwm2m_free(*nameP); if (*msisdnP != NULL) lwm2m_free(*msisdnP); return -1; }
static int prv_parseItem(uint8_t * buffer, size_t bufferLen, _record_t * recordP) { size_t index; recordP->resId = LWM2M_MAX_ID; recordP->resInstId = LWM2M_MAX_ID; recordP->type = _TYPE_UNSET; recordP->value = NULL; recordP->valueLen = 0; index = 0; do { int tokenStart; int tokenLen; int valueStart; int valueLen; int next; next = prv_split(buffer+index, bufferLen-index, &tokenStart, &tokenLen, &valueStart, &valueLen); if (next < 0) return -1; switch (tokenLen) { case 1: { switch (buffer[index+tokenStart]) { case 'n': { int i; uint32_t readId; if (recordP->resId != LWM2M_MAX_ID) return -1; // Check for " around URI if (valueLen < 3 || buffer[index+valueStart] != '"' || buffer[index+valueStart+valueLen-1] != '"') { return -1; } i = 1; readId = 0; while (i < valueLen-1 && buffer[index+valueStart+i] != '/') { if (buffer[index+valueStart+i] < '0' || buffer[index+valueStart+i] > '9') { return -1; } readId *= 10; readId += buffer[index+valueStart+i] - '0'; if (readId > LWM2M_MAX_ID) return -1; i++; } recordP->resId = readId; if (buffer[index+valueStart+i] == '/') { int j; if (i == valueLen-1) return -1; j = 1; readId = 0; while (i+j < valueLen-1) { if (buffer[index+valueStart+i+j] < '0' || buffer[index+valueStart+i+j] > '9') { return -1; } readId *= 10; readId += buffer[index+valueStart+i+j] - '0'; if (readId > LWM2M_MAX_ID) return -1; i++; } recordP->resInstId = readId; } // TODO: support more URIs than just res and res/instance } break; case 'v': if (recordP->type != _TYPE_UNSET) return -1; recordP->type = _TYPE_FLOAT; recordP->value = buffer + index + valueStart; recordP->valueLen = valueLen; break; case 't': // TODO: support time break; default: return -1; } } break; case 2: { // "bv", "ov", or "sv" if (buffer[index+tokenStart+1] != 'v') return -1; switch (buffer[index+tokenStart]) { case 'b': if (recordP->type != _TYPE_UNSET) return -1; if (0 == lwm2m_strncmp(JSON_TRUE_STRING, (char *)buffer + index + valueStart, valueLen)) { recordP->type = _TYPE_TRUE; } else if (0 == lwm2m_strncmp(JSON_FALSE_STRING, (char *)buffer + index + valueStart, valueLen)) { recordP->type = _TYPE_FALSE; } else { return -1; } break; case 'o': if (recordP->type != _TYPE_UNSET) return -1; // TODO: support object link break; case 's': if (recordP->type != _TYPE_UNSET) return -1; // Check for " around value if (valueLen < 2 || buffer[index+valueStart] != '"' || buffer[index+valueStart+valueLen-1] != '"') { return -1; } recordP->type = _TYPE_STRING; recordP->value = buffer + index + valueStart + 1; recordP->valueLen = valueLen - 2; break; default: return -1; } } break; default: return -1; } index += next + 1; } while (index < bufferLen); return 0; }
static int prv_readAttributes(multi_option_t * query, lwm2m_attributes_t * attrP) { int64_t intValue; double floatValue; memset(attrP, 0, sizeof(lwm2m_attributes_t)); while (query != NULL) { if (lwm2m_strncmp((char *)query->data, ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN) == 0) { if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_MIN_PERIOD)) return -1; if (query->len == ATTR_MIN_PERIOD_LEN) return -1; if (1 != utils_textToInt(query->data + ATTR_MIN_PERIOD_LEN, query->len - ATTR_MIN_PERIOD_LEN, &intValue)) return -1; if (intValue < 0) return -1; attrP->toSet |= LWM2M_ATTR_FLAG_MIN_PERIOD; attrP->minPeriod = intValue; } else if (lwm2m_strncmp((char *)query->data, ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN - 1) == 0) { if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_MIN_PERIOD)) return -1; if (query->len != ATTR_MIN_PERIOD_LEN - 1) return -1; attrP->toClear |= LWM2M_ATTR_FLAG_MIN_PERIOD; } else if (lwm2m_strncmp((char *)query->data, ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN) == 0) { if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_MAX_PERIOD)) return -1; if (query->len == ATTR_MAX_PERIOD_LEN) return -1; if (1 != utils_textToInt(query->data + ATTR_MAX_PERIOD_LEN, query->len - ATTR_MAX_PERIOD_LEN, &intValue)) return -1; if (intValue < 0) return -1; attrP->toSet |= LWM2M_ATTR_FLAG_MAX_PERIOD; attrP->maxPeriod = intValue; } else if (lwm2m_strncmp((char *)query->data, ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN - 1) == 0) { if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_MAX_PERIOD)) return -1; if (query->len != ATTR_MAX_PERIOD_LEN - 1) return -1; attrP->toClear |= LWM2M_ATTR_FLAG_MAX_PERIOD; } else if (lwm2m_strncmp((char *)query->data, ATTR_GREATER_THAN_STR, ATTR_GREATER_THAN_LEN) == 0) { if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_GREATER_THAN)) return -1; if (query->len == ATTR_GREATER_THAN_LEN) return -1; if (1 != utils_textToFloat(query->data + ATTR_GREATER_THAN_LEN, query->len - ATTR_GREATER_THAN_LEN, &floatValue)) return -1; attrP->toSet |= LWM2M_ATTR_FLAG_GREATER_THAN; attrP->greaterThan = floatValue; } else if (lwm2m_strncmp((char *)query->data, ATTR_GREATER_THAN_STR, ATTR_GREATER_THAN_LEN - 1) == 0) { if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_GREATER_THAN)) return -1; if (query->len != ATTR_GREATER_THAN_LEN - 1) return -1; attrP->toClear |= LWM2M_ATTR_FLAG_GREATER_THAN; } else if (lwm2m_strncmp((char *)query->data, ATTR_LESS_THAN_STR, ATTR_LESS_THAN_LEN) == 0) { if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_LESS_THAN)) return -1; if (query->len == ATTR_LESS_THAN_LEN) return -1; if (1 != utils_textToFloat(query->data + ATTR_LESS_THAN_LEN, query->len - ATTR_LESS_THAN_LEN, &floatValue)) return -1; attrP->toSet |= LWM2M_ATTR_FLAG_LESS_THAN; attrP->lessThan = floatValue; } else if (lwm2m_strncmp((char *)query->data, ATTR_LESS_THAN_STR, ATTR_LESS_THAN_LEN - 1) == 0) { if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_LESS_THAN)) return -1; if (query->len != ATTR_LESS_THAN_LEN - 1) return -1; attrP->toClear |= LWM2M_ATTR_FLAG_LESS_THAN; } else if (lwm2m_strncmp((char *)query->data, ATTR_STEP_STR, ATTR_STEP_LEN) == 0) { if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_STEP)) return -1; if (query->len == ATTR_STEP_LEN) return -1; if (1 != utils_textToFloat(query->data + ATTR_STEP_LEN, query->len - ATTR_STEP_LEN, &floatValue)) return -1; if (floatValue < 0) return -1; attrP->toSet |= LWM2M_ATTR_FLAG_STEP; attrP->step = floatValue; } else if (lwm2m_strncmp((char *)query->data, ATTR_STEP_STR, ATTR_STEP_LEN - 1) == 0) { if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_STEP)) return -1; if (query->len != ATTR_STEP_LEN - 1) return -1; attrP->toClear |= LWM2M_ATTR_FLAG_STEP; } else return -1; query = query->next; } return 0; }
static int prv_parseLinkAttributes(uint8_t * data, uint16_t length, bool * supportJSON, char ** altPath) { uint16_t index; uint16_t pathStart; uint16_t pathLength; bool isValid; isValid = false; // Expecting application/link-format (RFC6690) // leading space were removed before. Remove trailing spaces. while (length > 0 && data[length-1] == ' ') length--; // strip open tag if (length >= 2 && data[0] == REG_URI_START) { data += 1; length -= 1; } else { return 0; } pathStart = 0; index = length - 1; while (index > 0 && data[index] != REG_URI_END) index--; // link attributes are required if (index == 0 || index == length - 1) return 0; // If there is a preceding /, remove it if (data[pathStart] == '/') { pathStart += 1; } pathLength = index - pathStart; index++; if (index >= length || data[index] != REG_ATTR_SEPARATOR) return 0; index++; while (index < length) { uint16_t result; uint16_t keyStart; uint16_t keyLength; uint16_t valueStart; uint16_t valueLength; result = prv_splitLinkAttribute(data + index, length - index, &keyStart, &keyLength, &valueStart, &valueLength); if (result == 0) return 0; if (keyLength == REG_ATTR_TYPE_KEY_LEN && 0 == lwm2m_strncmp(REG_ATTR_TYPE_KEY, data + index + keyStart, keyLength)) { if (isValid == true) return 0; // declared twice if (valueLength != REG_ATTR_TYPE_VALUE_LEN || 0 != lwm2m_strncmp(REG_ATTR_TYPE_VALUE, data + index + valueStart, valueLength)) { return 0; } isValid = true; } else if (keyLength == REG_ATTR_CONTENT_KEY_LEN && 0 == lwm2m_strncmp(REG_ATTR_CONTENT_KEY, data + index + keyStart, keyLength)) { if (*supportJSON == true) return 0; // declared twice if (valueLength == REG_ATTR_CONTENT_JSON_LEN && 0 == lwm2m_strncmp(REG_ATTR_CONTENT_JSON, data + index + valueStart, valueLength)) { *supportJSON = true; } else { return 0; } } // else ignore this one index += result; } if (isValid == false) return 0; if (pathLength != 0) { *altPath = (char *)lwm2m_malloc(pathLength + 1); if (*altPath == NULL) return 0; memcpy(*altPath, data + pathStart, pathLength); (*altPath)[pathLength] = 0; } return 1; }
static int prv_parseItem(uint8_t * buffer, size_t bufferLen, _record_t * recordP) { size_t index; memset(recordP->ids, 0xFF, 4*sizeof(uint16_t)); recordP->type = _TYPE_UNSET; recordP->value = NULL; recordP->valueLen = 0; index = 0; do { int tokenStart; int tokenLen; int valueStart; int valueLen; int next; next = prv_split(buffer+index, bufferLen-index, &tokenStart, &tokenLen, &valueStart, &valueLen); if (next < 0) return -1; switch (tokenLen) { case 1: { switch (buffer[index+tokenStart]) { case 'n': { int i; int j; if (recordP->ids[0] != LWM2M_MAX_ID) return -1; // Check for " around URI if (valueLen < 2 || buffer[index+valueStart] != '"' || buffer[index+valueStart+valueLen-1] != '"') { return -1; } // Ignore starting / if (buffer[index + valueStart + 1] == '/') { if (valueLen < 4) { return -1; } valueStart += 1; valueLen -= 1; } i = 0; j = 0; if (valueLen > 1) { do { uint32_t readId; readId = 0; i++; while (i < valueLen-1 && buffer[index+valueStart+i] != '/') { if (buffer[index+valueStart+i] < '0' || buffer[index+valueStart+i] > '9') { return -1; } readId *= 10; readId += buffer[index+valueStart+i] - '0'; if (readId > LWM2M_MAX_ID) return -1; i++; } recordP->ids[j] = readId; j++; } while (i < valueLen-1 && j < 4 && buffer[index+valueStart+i] == '/'); if (i < valueLen-1 ) return -1; } } break; case 'v': if (recordP->type != _TYPE_UNSET) return -1; recordP->type = _TYPE_FLOAT; recordP->value = buffer + index + valueStart; recordP->valueLen = valueLen; break; case 't': // TODO: support time break; default: return -1; } } break; case 2: { // "bv", "ov", or "sv" if (buffer[index+tokenStart+1] != 'v') return -1; switch (buffer[index+tokenStart]) { case 'b': if (recordP->type != _TYPE_UNSET) return -1; if (0 == lwm2m_strncmp(JSON_TRUE_STRING, (char *)buffer + index + valueStart, valueLen)) { recordP->type = _TYPE_TRUE; } else if (0 == lwm2m_strncmp(JSON_FALSE_STRING, (char *)buffer + index + valueStart, valueLen)) { recordP->type = _TYPE_FALSE; } else { return -1; } break; case 'o': if (recordP->type != _TYPE_UNSET) return -1; // TODO: support object link break; case 's': if (recordP->type != _TYPE_UNSET) return -1; // Check for " around value if (valueLen < 2 || buffer[index+valueStart] != '"' || buffer[index+valueStart+valueLen-1] != '"') { return -1; } recordP->type = _TYPE_STRING; recordP->value = buffer + index + valueStart + 1; recordP->valueLen = valueLen - 2; break; default: return -1; } } break; default: return -1; } index += next + 1; } while (index < bufferLen); return 0; }
static int prv_parseItem(const uint8_t * buffer, size_t bufferLen, _record_t * recordP, char * baseUri, time_t * baseTime, lwm2m_data_t *baseValue) { size_t index; const uint8_t *name = NULL; size_t nameLength = 0; bool timeSeen = false; bool bnSeen = false; bool btSeen = false; bool bvSeen = false; bool bverSeen = false; memset(recordP->ids, 0xFF, 4*sizeof(uint16_t)); memset(&recordP->value, 0, sizeof(recordP->value)); recordP->time = 0; index = 0; do { size_t tokenStart; size_t tokenLen; size_t valueStart; size_t valueLen; int next; next = json_split(buffer+index, bufferLen-index, &tokenStart, &tokenLen, &valueStart, &valueLen); if (next < 0) return -1; if (tokenLen == 0) return -1; switch (buffer[index+tokenStart]) { case 'b': if (tokenLen == 2 && buffer[index+tokenStart+1] == 'n') { if (bnSeen) return -1; bnSeen = true; /* Check for " around URI */ if (valueLen < 2 || buffer[index+valueStart] != '"' || buffer[index+valueStart+valueLen-1] != '"') { return -1; } if (valueLen >= 3) { if (valueLen == 3 && buffer[index+valueStart+1] != '/') return -1; if (valueLen > URI_MAX_STRING_LEN) return -1; memcpy(baseUri, buffer+index+valueStart+1, valueLen-2); baseUri[valueLen-2] = '\0'; } else { baseUri[0] = '\0'; } } else if (tokenLen == 2 && buffer[index+tokenStart+1] == 't') { if (btSeen) return -1; btSeen = true; if (!json_convertTime(buffer+index+valueStart, valueLen, baseTime)) return -1; } else if (tokenLen == 2 && buffer[index+tokenStart+1] == 'v') { if (bvSeen) return -1; bvSeen = true; if (valueLen == 0) { baseValue->type = LWM2M_TYPE_UNDEFINED; } else { if (!json_convertNumeric(buffer+index+valueStart, valueLen, baseValue)) return -1; /* Convert explicit 0 to implicit 0 */ switch (baseValue->type) { case LWM2M_TYPE_INTEGER: if (baseValue->value.asInteger == 0) { baseValue->type = LWM2M_TYPE_UNDEFINED; } break; case LWM2M_TYPE_UNSIGNED_INTEGER: if (baseValue->value.asUnsigned == 0) { baseValue->type = LWM2M_TYPE_UNDEFINED; } break; case LWM2M_TYPE_FLOAT: if (baseValue->value.asFloat == 0.0) { baseValue->type = LWM2M_TYPE_UNDEFINED; } break; default: return -1; } } } else if (tokenLen == 4 && buffer[index+tokenStart+1] == 'v' && buffer[index+tokenStart+2] == 'e' && buffer[index+tokenStart+3] == 'r') { int64_t value; int res; if (bverSeen) return -1; bverSeen = true; res = utils_textToInt(buffer+index+valueStart, valueLen, &value); /* Only the default version (10) is supported */ if (!res || value != 10) { return -1; } } else if (buffer[index+tokenStart+tokenLen-1] == '_') { /* Label ending in _ must be supported or generate error. */ return -1; } break; case 'n': { if (tokenLen == 1) { if (name) return -1; /* Check for " around URI */ if (valueLen < 2 || buffer[index+valueStart] != '"' || buffer[index+valueStart+valueLen-1] != '"') { return -1; } name = buffer + index + valueStart + 1; nameLength = valueLen - 2; } else if (buffer[index+tokenStart+tokenLen-1] == '_') { /* Label ending in _ must be supported or generate error. */ return -1; } break; } case 't': if (tokenLen == 1) { if (timeSeen) return -1; timeSeen = true; if (!json_convertTime(buffer+index+valueStart, valueLen, &recordP->time)) return -1; } else if (buffer[index+tokenStart+tokenLen-1] == '_') { /* Label ending in _ must be supported or generate error. */ return -1; } break; case 'v': if (tokenLen == 1) { if (recordP->value.type != LWM2M_TYPE_UNDEFINED) return -1; if (!json_convertNumeric(buffer+index+valueStart, valueLen, &recordP->value)) return -1; } else if (tokenLen == 2 && buffer[index+tokenStart+1] == 'b') { if (recordP->value.type != LWM2M_TYPE_UNDEFINED) return -1; if (0 == lwm2m_strncmp(JSON_TRUE_STRING, (char *)buffer + index + valueStart, valueLen)) { lwm2m_data_encode_bool(true, &recordP->value); } else if (0 == lwm2m_strncmp(JSON_FALSE_STRING, (char *)buffer + index + valueStart, valueLen)) { lwm2m_data_encode_bool(false, &recordP->value); } else { return -1; } } else if (tokenLen == 2 && (buffer[index+tokenStart+1] == 'd' || buffer[index+tokenStart+1] == 's')) { if (recordP->value.type != LWM2M_TYPE_UNDEFINED) return -1; /* Check for " around value */ if (valueLen < 2 || buffer[index+valueStart] != '"' || buffer[index+valueStart+valueLen-1] != '"') { return -1; } if (buffer[index+tokenStart+1] == 'd') { /* Don't use lwm2m_data_encode_opaque here. It would copy the buffer */ recordP->value.type = LWM2M_TYPE_OPAQUE; } else { /* Don't use lwm2m_data_encode_nstring here. It would copy the buffer */ recordP->value.type = LWM2M_TYPE_STRING; } recordP->value.value.asBuffer.buffer = (uint8_t *)buffer + index + valueStart + 1; recordP->value.value.asBuffer.length = valueLen - 2; } else if (tokenLen == 3 && buffer[index+tokenStart+1] == 'l' && buffer[index+tokenStart+2] == 'o') { if (recordP->value.type != LWM2M_TYPE_UNDEFINED) return -1; /* Check for " around value */ if (valueLen < 2 || buffer[index+valueStart] != '"' || buffer[index+valueStart+valueLen-1] != '"') { return -1; } if (!utils_textToObjLink(buffer + index + valueStart + 1, valueLen - 2, &recordP->value.value.asObjLink.objectId, &recordP->value.value.asObjLink.objectInstanceId)) { return -1; } recordP->value.type = LWM2M_TYPE_OBJECT_LINK; } else if (buffer[index+tokenStart+tokenLen-1] == '_') { /* Label ending in _ must be supported or generate error. */ return -1; } break; default: if (buffer[index+tokenStart+tokenLen-1] == '_') { /* Label ending in _ must be supported or generate error. */ return -1; } break; } index += next + 1; } while (index < bufferLen); /* Combine with base values */ recordP->time += *baseTime; if (baseUri[0] || name) { lwm2m_uri_t uri; size_t length = strlen(baseUri); char uriStr[URI_MAX_STRING_LEN]; if (length > sizeof(uriStr)) return -1; memcpy(uriStr, baseUri, length); if (nameLength) { if (nameLength + length > sizeof(uriStr)) return -1; memcpy(uriStr + length, name, nameLength); length += nameLength; } if (!lwm2m_stringToUri(uriStr, length, &uri)) return -1; if (LWM2M_URI_IS_SET_OBJECT(&uri)) { recordP->ids[0] = uri.objectId; } if (LWM2M_URI_IS_SET_INSTANCE(&uri)) { recordP->ids[1] = uri.instanceId; } if (LWM2M_URI_IS_SET_RESOURCE(&uri)) { recordP->ids[2] = uri.resourceId; } if (LWM2M_URI_IS_SET_RESOURCE_INSTANCE(&uri)) { recordP->ids[3] = uri.resourceInstanceId; } } if (baseValue->type != LWM2M_TYPE_UNDEFINED) { if (recordP->value.type == LWM2M_TYPE_UNDEFINED) { memcpy(&recordP->value, baseValue, sizeof(*baseValue)); } else { switch (recordP->value.type) { case LWM2M_TYPE_INTEGER: switch(baseValue->type) { case LWM2M_TYPE_INTEGER: recordP->value.value.asInteger += baseValue->value.asInteger; break; case LWM2M_TYPE_UNSIGNED_INTEGER: recordP->value.value.asInteger += baseValue->value.asUnsigned; break; case LWM2M_TYPE_FLOAT: recordP->value.value.asInteger += baseValue->value.asFloat; break; default: return -1; } break; case LWM2M_TYPE_UNSIGNED_INTEGER: switch(baseValue->type) { case LWM2M_TYPE_INTEGER: recordP->value.value.asUnsigned += baseValue->value.asInteger; break; case LWM2M_TYPE_UNSIGNED_INTEGER: recordP->value.value.asUnsigned += baseValue->value.asUnsigned; break; case LWM2M_TYPE_FLOAT: recordP->value.value.asUnsigned += baseValue->value.asFloat; break; default: return -1; } break; case LWM2M_TYPE_FLOAT: switch(baseValue->type) { case LWM2M_TYPE_INTEGER: recordP->value.value.asFloat += baseValue->value.asInteger; break; case LWM2M_TYPE_UNSIGNED_INTEGER: recordP->value.value.asFloat += baseValue->value.asUnsigned; break; case LWM2M_TYPE_FLOAT: recordP->value.value.asFloat += baseValue->value.asFloat; break; default: return -1; } break; default: return -1; } } } return 0; }