static uint8_t prv_get_value(lwm2m_data_t * dataP, security_instance_t * targetP) { switch (dataP->id) { case LWM2M_SECURITY_URI_ID: lwm2m_data_encode_string(targetP->uri, dataP); return COAP_205_CONTENT; case LWM2M_SECURITY_BOOTSTRAP_ID: lwm2m_data_encode_bool(targetP->isBootstrap, dataP); return COAP_205_CONTENT; case LWM2M_SECURITY_SECURITY_ID: lwm2m_data_encode_int(targetP->securityMode, dataP); return COAP_205_CONTENT; case LWM2M_SECURITY_PUBLIC_KEY_ID: lwm2m_data_encode_opaque(targetP->publicIdentity, targetP->publicIdLen, dataP); return COAP_205_CONTENT; case LWM2M_SECURITY_SERVER_PUBLIC_KEY_ID: lwm2m_data_encode_opaque(targetP->serverPublicKey, targetP->serverPublicKeyLen, dataP); return COAP_205_CONTENT; case LWM2M_SECURITY_SECRET_KEY_ID: lwm2m_data_encode_opaque(targetP->secretKey, targetP->secretKeyLen, dataP); return COAP_205_CONTENT; case LWM2M_SECURITY_SMS_SECURITY_ID: lwm2m_data_encode_int(targetP->smsSecurityMode, dataP); return COAP_205_CONTENT; case LWM2M_SECURITY_SMS_KEY_PARAM_ID: lwm2m_data_encode_opaque(targetP->smsParams, targetP->smsParamsLen, dataP); return COAP_205_CONTENT; case LWM2M_SECURITY_SMS_SECRET_KEY_ID: lwm2m_data_encode_opaque(targetP->smsSecret, targetP->smsSecretLen, dataP); return COAP_205_CONTENT; case LWM2M_SECURITY_SMS_SERVER_NUMBER_ID: lwm2m_data_encode_int(0, dataP); return COAP_205_CONTENT; case LWM2M_SECURITY_SHORT_SERVER_ID: lwm2m_data_encode_int(targetP->shortID, dataP); return COAP_205_CONTENT; case LWM2M_SECURITY_HOLD_OFF_ID: lwm2m_data_encode_int(targetP->clientHoldOffTime, dataP); return COAP_205_CONTENT; default: return COAP_404_NOT_FOUND; } }
static uint8_t prv_get_value(lwm2m_data_t * dataP, server_instance_t * targetP) { // There are no multiple instance resources dataP->type = LWM2M_TYPE_RESOURCE; switch (dataP->id) { case LWM2M_SERVER_SHORT_ID_ID: lwm2m_data_encode_int(targetP->shortServerId, dataP); if (0 != dataP->length) return COAP_205_CONTENT; else return COAP_500_INTERNAL_SERVER_ERROR; case LWM2M_SERVER_LIFETIME_ID: lwm2m_data_encode_int(targetP->lifetime, dataP); if (0 != dataP->length) return COAP_205_CONTENT; else return COAP_500_INTERNAL_SERVER_ERROR; case LWM2M_SERVER_MIN_PERIOD_ID: lwm2m_data_encode_int(targetP->minPeriod, dataP); if (0 != dataP->length) return COAP_205_CONTENT; else return COAP_500_INTERNAL_SERVER_ERROR; case LWM2M_SERVER_MAX_PERIOD_ID: lwm2m_data_encode_int(targetP->maxPeriod, dataP); if (0 != dataP->length) return COAP_205_CONTENT; else return COAP_500_INTERNAL_SERVER_ERROR; case LWM2M_SERVER_DISABLE_ID: return COAP_405_METHOD_NOT_ALLOWED; case LWM2M_SERVER_STORING_ID: lwm2m_data_encode_bool(targetP->storing, dataP); if (0 != dataP->length) return COAP_205_CONTENT; else return COAP_500_INTERNAL_SERVER_ERROR; case LWM2M_SERVER_BINDING_ID: dataP->value = (uint8_t*)targetP->binding; dataP->length = strlen(targetP->binding); dataP->flags = LWM2M_TLV_FLAG_STATIC_DATA; dataP->dataType = LWM2M_TYPE_STRING; return COAP_205_CONTENT; case LWM2M_SERVER_UPDATE_ID: return COAP_405_METHOD_NOT_ALLOWED; default: return COAP_404_NOT_FOUND; } }
static int prv_convertRecord(_record_t * recordArray, int count, lwm2m_data_t ** dataP) { int index; int tlvIndex; lwm2m_data_t * tlvP; // may be overkill tlvP = lwm2m_data_new(count); if (NULL == tlvP) return -1; tlvIndex = 0; for (index = 0 ; index < count ; index++) { lwm2m_data_t * targetP; if (recordArray[index].resInstId == LWM2M_MAX_ID) { targetP = tlvP + tlvIndex; targetP->type = LWM2M_TYPE_RESOURCE; targetP->id = recordArray[index].resId; tlvIndex++; } else { int resIndex; resIndex = 0; while (resIndex < tlvIndex && tlvP[resIndex].id != recordArray[index].resId) { resIndex++; } if (resIndex == tlvIndex) { targetP = lwm2m_data_new(1); if (NULL == targetP) goto error; tlvP[resIndex].type = LWM2M_TYPE_MULTIPLE_RESOURCE; tlvP[resIndex].id = recordArray[index].resId; tlvP[resIndex].length = 1; tlvP[resIndex].value = (uint8_t *)targetP; tlvIndex++; } else { targetP = lwm2m_data_new(tlvP[resIndex].length + 1); if (NULL == targetP) goto error; memcpy(targetP + 1, tlvP[resIndex].value, tlvP[resIndex].length * sizeof(lwm2m_data_t)); lwm2m_free(tlvP[resIndex].value); // do not use lwm2m_data_free() to preserve value pointers tlvP[resIndex].value = (uint8_t *)targetP; tlvP[resIndex].length++; } targetP->type = LWM2M_TYPE_RESOURCE_INSTANCE; targetP->id = recordArray[index].resInstId; } switch (recordArray[index].type) { case _TYPE_FALSE: lwm2m_data_encode_bool(false, targetP); break; case _TYPE_TRUE: lwm2m_data_encode_bool(true, targetP); break; case _TYPE_FLOAT: { size_t i; i = 0; while (i < recordArray[index].valueLen && recordArray[index].value[i] != '.') { i++; } if (i == recordArray[index].valueLen) { int64_t value; if ( 1 != lwm2m_PlainTextToInt64(recordArray[index].value, recordArray[index].valueLen, &value)) { goto error; } lwm2m_data_encode_int(value, targetP); } else { double value; if ( 1 != lwm2m_PlainTextToFloat64(recordArray[index].value, recordArray[index].valueLen, &value)) { goto error; } lwm2m_data_encode_float(value, targetP); } } break; // TODO: Copy string instead of pointing to it case _TYPE_STRING: targetP->flags = LWM2M_TLV_FLAG_STATIC_DATA | LWM2M_TLV_FLAG_TEXT_FORMAT; targetP->dataType = LWM2M_TYPE_STRING; // or opaque ? targetP->length = recordArray[index].valueLen; targetP->value = recordArray[index].value; break; case _TYPE_UNSET: default: goto error; } } *dataP = tlvP; return tlvIndex; error: lwm2m_data_free(count, tlvP); return -1; }
static int prv_add_server(bs_info_t * infoP, read_server_t * dataP) { lwm2m_data_t * tlvP; int size; bs_server_tlv_t * serverP; lwm2m_media_type_t format; switch (dataP->securityMode) { case LWM2M_SECURITY_MODE_NONE: size = 4; break; case LWM2M_SECURITY_MODE_PRE_SHARED_KEY: size = 6; break; case LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY: case LWM2M_SECURITY_MODE_CERTIFICATE: size = 7; break; default: return -1; } serverP = (bs_server_tlv_t *)lwm2m_malloc(sizeof(bs_server_tlv_t)); if (serverP == NULL) return -1; memset(serverP, 0, sizeof(bs_server_tlv_t)); serverP->id = dataP->id; tlvP = lwm2m_data_new(size); if (tlvP == NULL) goto error; // LWM2M Server URI tlvP[0].id = LWM2M_SECURITY_URI_ID; lwm2m_data_encode_string(dataP->uri, tlvP); // Bootstrap Server tlvP[1].id = LWM2M_SECURITY_BOOTSTRAP_ID; lwm2m_data_encode_bool(dataP->isBootstrap, tlvP + 1); // Short Server ID tlvP[2].id = LWM2M_SECURITY_SHORT_SERVER_ID; lwm2m_data_encode_int(dataP->id, tlvP + 2); // Security Mode tlvP[3].id = LWM2M_SECURITY_SECURITY_ID; lwm2m_data_encode_int(dataP->securityMode, tlvP + 3); if (size > 4) { tlvP[4].id = LWM2M_SECURITY_PUBLIC_KEY_ID; lwm2m_data_encode_opaque(dataP->publicKey, dataP->publicKeyLen, tlvP + 4); tlvP[5].id = LWM2M_SECURITY_SECRET_KEY_ID; lwm2m_data_encode_opaque(dataP->secretKey, dataP->secretKeyLen, tlvP + 5); if (size == 7) { tlvP[6].id = LWM2M_SECURITY_SERVER_PUBLIC_KEY_ID; lwm2m_data_encode_opaque(dataP->serverKey, dataP->serverKeyLen, tlvP + 5); } } format = LWM2M_CONTENT_TLV; serverP->securityLen = lwm2m_data_serialize(NULL, size, tlvP, &format, &(serverP->securityData)); if (serverP->securityLen <= 0) goto error; lwm2m_data_free(size, tlvP); if (dataP->isBootstrap == false) { size = 4; tlvP = lwm2m_data_new(size); if (tlvP == NULL) goto error; // Short Server ID tlvP[0].id = LWM2M_SERVER_SHORT_ID_ID; lwm2m_data_encode_int(dataP->id, tlvP); // Lifetime tlvP[1].id = LWM2M_SERVER_LIFETIME_ID; lwm2m_data_encode_int(dataP->lifetime, tlvP + 1); // Notification Storing tlvP[2].id = LWM2M_SERVER_STORING_ID; lwm2m_data_encode_bool(false, tlvP + 2); // Binding tlvP[3].id = LWM2M_SERVER_BINDING_ID; lwm2m_data_encode_string("U", tlvP + 3); serverP->serverLen = lwm2m_data_serialize(NULL, size, tlvP, &format, &(serverP->serverData)); if (serverP->serverLen <= 0) goto error; lwm2m_data_free(size, tlvP); } infoP->serverList = (bs_server_tlv_t *)LWM2M_LIST_ADD(infoP->serverList, serverP); return 0; error: if (tlvP != NULL) lwm2m_data_free(size, tlvP); if (serverP->securityData != NULL) lwm2m_free(serverP->securityData); if (serverP->serverData != NULL) lwm2m_free(serverP->serverData); lwm2m_free(serverP); return -1; }
static uint8_t prv_get_value(lwm2m_data_t * dataP, server_instance_t * targetP) { switch (dataP->id) { case LWM2M_SERVER_SHORT_ID_ID: lwm2m_data_encode_int(targetP->shortServerId, dataP); return COAP_205_CONTENT; case LWM2M_SERVER_LIFETIME_ID: lwm2m_data_encode_int(targetP->lifetime, dataP); return COAP_205_CONTENT; case LWM2M_SERVER_MIN_PERIOD_ID: lwm2m_data_encode_int(targetP->defaultMinPeriod, dataP); return COAP_205_CONTENT; case LWM2M_SERVER_MAX_PERIOD_ID: lwm2m_data_encode_int(targetP->defaultMaxPeriod, dataP); return COAP_205_CONTENT; case LWM2M_SERVER_DISABLE_ID: return COAP_405_METHOD_NOT_ALLOWED; case LWM2M_SERVER_TIMEOUT_ID: lwm2m_data_encode_int(targetP->disableTimeout, dataP); return COAP_205_CONTENT; case LWM2M_SERVER_STORING_ID: lwm2m_data_encode_bool(targetP->storing, dataP); return COAP_205_CONTENT; case LWM2M_SERVER_BINDING_ID: lwm2m_data_encode_string(targetP->binding, dataP); return COAP_205_CONTENT; case LWM2M_SERVER_UPDATE_ID: return COAP_405_METHOD_NOT_ALLOWED; #ifndef LWM2M_VERSION_1_0 case LWM2M_SERVER_REG_ORDER_ID: if (targetP->registrationPriorityOrder >= 0) { lwm2m_data_encode_uint(targetP->registrationPriorityOrder, dataP); return COAP_205_CONTENT; } else { return COAP_404_NOT_FOUND; } case LWM2M_SERVER_INITIAL_REG_DELAY_ID: if (targetP->initialRegistrationDelayTimer >= 0) { lwm2m_data_encode_uint(targetP->initialRegistrationDelayTimer, dataP); return COAP_205_CONTENT; } else { return COAP_404_NOT_FOUND; } case LWM2M_SERVER_REG_FAIL_BLOCK_ID: if (targetP->registrationFailureBlock >= 0) { lwm2m_data_encode_bool(targetP->registrationFailureBlock > 0, dataP); return COAP_205_CONTENT; } else { return COAP_404_NOT_FOUND; } case LWM2M_SERVER_REG_FAIL_BOOTSTRAP_ID: if (targetP->bootstrapOnRegistrationFailure >= 0) { lwm2m_data_encode_bool(targetP->bootstrapOnRegistrationFailure > 0, dataP); return COAP_205_CONTENT; } else { return COAP_404_NOT_FOUND; } case LWM2M_SERVER_COMM_RETRY_COUNT_ID: if (targetP->communicationRetryCount >= 0) { lwm2m_data_encode_uint(targetP->communicationRetryCount, dataP); return COAP_205_CONTENT; } else { return COAP_404_NOT_FOUND; } case LWM2M_SERVER_COMM_RETRY_TIMER_ID: if (targetP->communicationRetryTimer >= 0) { lwm2m_data_encode_uint(targetP->communicationRetryTimer, dataP); return COAP_205_CONTENT; } else { return COAP_404_NOT_FOUND; } case LWM2M_SERVER_SEQ_DELAY_TIMER_ID: if (targetP->communicationSequenceDelayTimer >= 0) { lwm2m_data_encode_uint(targetP->communicationSequenceDelayTimer, dataP); return COAP_205_CONTENT; } else { return COAP_404_NOT_FOUND; } case LWM2M_SERVER_SEQ_RETRY_COUNT_ID: if (targetP->communicationSequenceRetryCount >= 0) { lwm2m_data_encode_uint(targetP->communicationSequenceRetryCount, dataP); return COAP_205_CONTENT; } else { return COAP_404_NOT_FOUND; } #endif default: return COAP_404_NOT_FOUND; } }
static bool prv_convertValue(_record_t * recordP, lwm2m_data_t * targetP) { switch (recordP->type) { case _TYPE_FALSE: lwm2m_data_encode_bool(false, targetP); break; case _TYPE_TRUE: lwm2m_data_encode_bool(true, targetP); break; case _TYPE_FLOAT: { size_t i; i = 0; while (i < recordP->valueLen && recordP->value[i] != '.') { i++; } if (i == recordP->valueLen) { int64_t value; if ( 1 != utils_textToInt(recordP->value, recordP->valueLen, &value)) { return false; } lwm2m_data_encode_int(value, targetP); } else { double value; if ( 1 != utils_textToFloat(recordP->value, recordP->valueLen, &value)) { return false; } lwm2m_data_encode_float(value, targetP); } } break; case _TYPE_STRING: lwm2m_data_encode_opaque(recordP->value, recordP->valueLen, targetP); targetP->type = LWM2M_TYPE_STRING; break; case _TYPE_UNSET: default: return false; } return true; }
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; }