static uint8_t prv_write(uint16_t instanceId, int numData, lwm2m_data_t * dataArray, lwm2m_object_t * objectP) { prv_instance_t * targetP; int i; targetP = (prv_instance_t *)lwm2m_list_find(objectP->instanceList, instanceId); if (NULL == targetP) return COAP_404_NOT_FOUND; for (i = 0 ; i < numData ; i++) { switch (dataArray[i].id) { case 1: { int64_t value; if (1 != lwm2m_data_decode_int(dataArray + i, &value) || value < 0 || value > 0xFF) { return COAP_400_BAD_REQUEST; } targetP->test = (uint8_t)value; } break; case 2: return COAP_405_METHOD_NOT_ALLOWED; case 3: if (1 != lwm2m_data_decode_float(dataArray + i, &(targetP->dec))) { return COAP_400_BAD_REQUEST; } break; case 4: { int64_t value; if (1 != lwm2m_data_decode_int(dataArray + i, &value) || value < INT16_MIN || value > INT16_MAX) { return COAP_400_BAD_REQUEST; } targetP->sig = (int16_t)value; } break; default: return COAP_404_NOT_FOUND; } } return COAP_204_CHANGED; }
coap_status_t observe_handleRequest(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, lwm2m_server_t * serverP, int size, lwm2m_data_t * dataP, coap_packet_t * message, coap_packet_t * response) { lwm2m_watcher_t * watcherP; uint32_t count; LOG("observe_handleRequest()\r\n"); coap_get_header_observe(message, &count); switch (count) { case 0: if (!LWM2M_URI_IS_SET_INSTANCE(uriP) && LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_400_BAD_REQUEST; if (message->token_len == 0) return COAP_400_BAD_REQUEST; watcherP = prv_getWatcher(contextP, uriP, serverP); if (watcherP == NULL) return COAP_500_INTERNAL_SERVER_ERROR; watcherP->tokenLen = message->token_len; memcpy(watcherP->token, message->token, message->token_len); watcherP->active = true; watcherP->lastTime = lwm2m_gettime(); if (LWM2M_URI_IS_SET_RESOURCE(uriP)) { switch (dataP->type) { case LWM2M_TYPE_INTEGER: if (1 != lwm2m_data_decode_int(dataP, &(watcherP->lastValue.asInteger))) return COAP_500_INTERNAL_SERVER_ERROR; break; case LWM2M_TYPE_FLOAT: if (1 != lwm2m_data_decode_float(dataP, &(watcherP->lastValue.asFloat))) return COAP_500_INTERNAL_SERVER_ERROR; break; default: break; } } coap_set_header_observe(response, watcherP->counter++); return COAP_205_CONTENT; case 1: // cancellation observe_cancel(contextP, LWM2M_MAX_ID, serverP->sessionH); return COAP_205_CONTENT; default: return COAP_400_BAD_REQUEST; } }
int64_t security_get_mode(lwm2m_object_t * obj, int instanceId){ int64_t mode; int size = 1; lwm2m_data_t * dataP = lwm2m_data_new(size); dataP->id = 2; // security mode obj->readFunc(instanceId, &size, &dataP, obj); if (0 != lwm2m_data_decode_int(dataP,&mode)) { lwm2m_data_free(size, dataP); return mode; } lwm2m_data_free(size, dataP); fprintf(stderr, "Unable to get security mode : use not secure mode"); return LWM2M_SECURITY_MODE_NONE; }
// Read the resource of the instance on the top of the stack. static uint8_t prv_write_resource(lua_State * L, uint16_t resourceid, lwm2m_data_t data) { // get resource type int type = prv_get_type(L,resourceid); // Get the write function lua_getfield(L, -1, "write"); // stack: ..., instance, writeFunc if (!lua_isfunction(L, -1)) { lua_pop(L, 1); // clean the stack return COAP_500_INTERNAL_SERVER_ERROR ; } // Push instance and resource id on the stack and call the writeFunc lua_pushvalue(L, -2); // stack: ..., instance, writeFunc, instance lua_pushinteger(L, resourceid); // stack: ..., instance, writeFunc, instance, resourceId // decode and push value if (type == LWM2M_STRING) lua_pushlstring(L, data.value, data.length); else{ int64_t val = 0; int res = lwm2m_data_decode_int(&data, &val); if (res != 1){ // unable to decode int lua_pop(L,3); return COAP_400_BAD_REQUEST; } if (type == LWM2M_BOOLEAN){ lua_pushboolean(L,val); }else if (type == LWM2M_NUMBER){ lua_pushinteger(L,val); }else{ lua_pop(L,3); return COAP_500_INTERNAL_SERVER_ERROR; } }// stack: ..., instance, writeFunc, instance, resourceId, value lua_call(L, 3, 1); // stack: ..., instance, return_code // Get return code int ret = lua_tointeger(L, -1); // Clean the stack lua_pop(L, 1); return ret; }
static int ICACHE_FLASH_ATTR prv_getMandatoryInfo(lwm2m_object_t * objectP, uint16_t instanceID, lwm2m_server_t * targetP) { lwm2m_data_t * dataP; int size; int64_t value; size = 2; dataP = lwm2m_data_new(size); if (dataP == NULL) return -1; dataP[0].id = LWM2M_SERVER_LIFETIME_ID; dataP[1].id = LWM2M_SERVER_BINDING_ID; if (objectP->readFunc(instanceID, &size, &dataP, objectP) != COAP_205_CONTENT) { lwm2m_data_free(size, dataP); return -1; } if (0 == lwm2m_data_decode_int(dataP, &value) || value < 0 || value >0xFFFFFFFF) // This is an implementation limit { lwm2m_data_free(size, dataP); return -1; } targetP->lifetime = value; targetP->binding = lwm2m_stringToBinding(dataP[1].value, dataP[1].length); lwm2m_data_free(size, dataP); if (targetP->binding == BINDING_UNKNOWN) { return -1; } return 0; }
static uint8_t prv_set_int_value(lwm2m_data_t * dataArray, uint32_t * data) { uint8_t result; int64_t value; if (1 == lwm2m_data_decode_int(dataArray, &value)) { if (value >= 0 && value <= 0xFFFFFFFF) { *data = value; result = COAP_204_CHANGED; } else { result = COAP_406_NOT_ACCEPTABLE; } } else { result = COAP_400_BAD_REQUEST; } return result; }
static lwm2m_list_t * ICACHE_FLASH_ATTR prv_findServerInstance(lwm2m_object_t * objectP, uint16_t shortID) { lwm2m_list_t * instanceP; instanceP = objectP->instanceList; while (NULL != instanceP) { int64_t value; lwm2m_data_t * dataP; int size; size = 1; dataP = lwm2m_data_new(size); if (dataP == NULL) return NULL; dataP->id = LWM2M_SERVER_SHORT_ID_ID; if (objectP->readFunc(instanceP->id, &size, &dataP, objectP) != COAP_205_CONTENT) { lwm2m_data_free(size, dataP); return NULL; } if (1 == lwm2m_data_decode_int(dataP, &value)) { if (value == shortID) { lwm2m_data_free(size, dataP); break; } } lwm2m_data_free(size, dataP); instanceP = instanceP->next; } return instanceP; }
int64_t security_get_mode(lwm2m_object_t * obj, int instanceId){ int size = 1; lwm2m_data_t * dataP = lwm2m_data_new(size); dataP->id = 2; // security mode obj->readFunc(instanceId, &size, &dataP, obj); if (dataP != NULL && dataP->dataType == LWM2M_TYPE_INTEGER && dataP->type == LWM2M_TYPE_RESOURCE && dataP->length > 0) { int64_t mode; if (0 != lwm2m_data_decode_int(dataP,&mode)) { lwm2m_data_free(size, dataP); return mode; } } lwm2m_data_free(size, dataP); printf("Unable to get security mode : use not secure mode"); return LWM2M_SECURITY_MODE_NONE; }
int object_getServers(lwm2m_context_t * contextP) { lwm2m_object_t * objectP; lwm2m_object_t * securityObjP = NULL; lwm2m_object_t * serverObjP = NULL; lwm2m_list_t * securityInstP; // instanceID of the server in the LWM2M Security Object for (objectP = contextP->objectList; objectP != NULL; objectP = objectP->next) { if (objectP->objID == LWM2M_SECURITY_OBJECT_ID) { securityObjP = objectP; } else if (objectP->objID == LWM2M_SERVER_OBJECT_ID) { serverObjP = objectP; } } if (NULL == securityObjP) return -1; securityInstP = securityObjP->instanceList; while (securityInstP != NULL) { if (LWM2M_LIST_FIND(contextP->bootstrapServerList, securityInstP->id) == NULL && LWM2M_LIST_FIND(contextP->serverList, securityInstP->id) == NULL) { // This server is new. eg created by last bootstrap lwm2m_data_t * dataP; int size; lwm2m_server_t * targetP; bool isBootstrap; int64_t value = 0; size = 3; dataP = lwm2m_data_new(size); if (dataP == NULL) return -1; dataP[0].id = LWM2M_SECURITY_BOOTSTRAP_ID; dataP[1].id = LWM2M_SECURITY_SHORT_SERVER_ID; dataP[2].id = LWM2M_SECURITY_HOLD_OFF_ID; if (securityObjP->readFunc(securityInstP->id, &size, &dataP, securityObjP) != COAP_205_CONTENT) { lwm2m_data_free(size, dataP); return -1; } targetP = (lwm2m_server_t *)lwm2m_malloc(sizeof(lwm2m_server_t)); if (targetP == NULL) { lwm2m_data_free(size, dataP); return -1; } memset(targetP, 0, sizeof(lwm2m_server_t)); targetP->secObjInstID = securityInstP->id; if (0 == lwm2m_data_decode_bool(dataP + 0, &isBootstrap)) { lwm2m_free(targetP); lwm2m_data_free(size, dataP); return -1; } if (0 == lwm2m_data_decode_int(dataP + 1, &value) || value < (isBootstrap ? 0 : 1) || value > 0xFFFF) // 0 is forbidden as a Short Server ID { lwm2m_free(targetP); lwm2m_data_free(size, dataP); return -1; } targetP->shortID = value; if (isBootstrap == true) { if (0 == lwm2m_data_decode_int(dataP + 2, &value) || value < 0 || value > 0xFFFFFFFF) // This is an implementation limit { lwm2m_free(targetP); lwm2m_data_free(size, dataP); return -1; } // lifetime of a bootstrap server is set to ClientHoldOffTime targetP->lifetime = value; contextP->bootstrapServerList = (lwm2m_server_t*)LWM2M_LIST_ADD(contextP->bootstrapServerList, targetP); } else { lwm2m_list_t * serverInstP; // instanceID of the server in the LWM2M Server Object serverInstP = prv_findServerInstance(serverObjP, targetP->shortID); if (serverInstP == NULL) { lwm2m_free(targetP); lwm2m_data_free(size, dataP); return -1; } if (0 != prv_getMandatoryInfo(serverObjP, serverInstP->id, targetP)) { lwm2m_free(targetP); lwm2m_data_free(size, dataP); return -1; } targetP->status = STATE_DEREGISTERED; contextP->serverList = (lwm2m_server_t*)LWM2M_LIST_ADD(contextP->serverList, targetP); } lwm2m_data_free(size, dataP); } securityInstP = securityInstP->next; } return 0; }
static uint8_t prv_write_resources(uint16_t instanceId, int numData, lwm2m_data_t* tlvArray, lwm2m_object_t* objectP, bool doCreate) { int i; uint8_t result = COAP_NO_ERROR; int64_t value; lwm2m_data_t* subTlvArray; int ri; acc_ctrl_oi_t* accCtrlOiP = (acc_ctrl_oi_t *) lwm2m_list_find(objectP->instanceList, instanceId); if (NULL == accCtrlOiP) return COAP_404_NOT_FOUND ; i = 0; do { switch (tlvArray[i].id) { case RES_M_OBJECT_ID: if (doCreate==false) { result = COAP_405_METHOD_NOT_ALLOWED; } else { if (1 != lwm2m_data_decode_int(&tlvArray[i], &value)) { result = COAP_400_BAD_REQUEST; } else if (value < 1 || value > 65534) { result = COAP_406_NOT_ACCEPTABLE; } else { accCtrlOiP->objectId = value; result = COAP_204_CHANGED; } } break; case RES_M_OBJECT_INSTANCE_ID: if (doCreate==false) { result = COAP_405_METHOD_NOT_ALLOWED; } else { if (1 != lwm2m_data_decode_int(&tlvArray[i], &value)) { result = COAP_400_BAD_REQUEST; } else if (value < 0 || value > MAX_DATA_VAL) { result = COAP_406_NOT_ACCEPTABLE; } else { accCtrlOiP->objectInstId = value; result = COAP_204_CHANGED; } } break; case RES_O_ACL: { if (tlvArray[i].type!= LWM2M_TYPE_MULTIPLE_RESOURCE) { result = COAP_400_BAD_REQUEST; } else { // MR-Write: Replace-implementation variant only // see LWM2M-TS:5.4.3 (wakaama has no part-update switch) // 1st: save accValueList! acc_ctrl_ri_t* acValListSave = accCtrlOiP->accCtrlValList; accCtrlOiP->accCtrlValList = NULL; subTlvArray = tlvArray[i].value.asChildren.array; if (tlvArray[i].value.asChildren.count == 0) { result = COAP_204_CHANGED; } else if (subTlvArray==NULL) { result = COAP_400_BAD_REQUEST; } else { for (ri=0; ri < tlvArray[i].value.asChildren.count; ri++) { if (1 != lwm2m_data_decode_int(&subTlvArray[ri], &value)) { result = COAP_400_BAD_REQUEST; break; } else if (value < 0 || value > 0xFFFF) { result = COAP_406_NOT_ACCEPTABLE; break; } else if (!prv_add_ac_val(accCtrlOiP, subTlvArray[ri].id, (uint16_t)value)) { result = COAP_500_INTERNAL_SERVER_ERROR; break; } else { result = COAP_204_CHANGED; } } } if (result != COAP_204_CHANGED) { // free pot. partial created new ones LWM2M_LIST_FREE(accCtrlOiP->accCtrlValList); // restore old values: accCtrlOiP->accCtrlValList = acValListSave; } else { // final free saved value list LWM2M_LIST_FREE(acValListSave); } } } break; case RES_M_ACCESS_CONTROL_OWNER: { if (1 == lwm2m_data_decode_int(tlvArray + i, &value)) { if (value >= 0 && value <= MAX_DATA_VAL) { accCtrlOiP->accCtrlOwner = value; result = COAP_204_CHANGED; } else { result = COAP_406_NOT_ACCEPTABLE; } } else { result = COAP_400_BAD_REQUEST; } } break; default: return COAP_404_NOT_FOUND ; } i++; } while (i < numData && result == COAP_204_CHANGED ); return result; }
void observe_step(lwm2m_context_t * contextP, time_t currentTime, time_t * timeoutP) { lwm2m_observed_t * targetP; for (targetP = contextP->observedList ; targetP != NULL ; targetP = targetP->next) { lwm2m_watcher_t * watcherP; uint8_t * buffer = NULL; size_t length = 0; lwm2m_data_t * dataP = NULL; int size = 0; double floatValue = 0; int64_t integerValue = 0; bool storeValue = false; lwm2m_media_type_t format = LWM2M_CONTENT_TEXT; coap_packet_t message[1]; time_t interval; if (LWM2M_URI_IS_SET_RESOURCE(&targetP->uri)) { if (COAP_205_CONTENT != object_readData(contextP, &targetP->uri, &size, &dataP)) continue; switch (dataP->type) { case LWM2M_TYPE_INTEGER: if (1 != lwm2m_data_decode_int(dataP, &integerValue)) continue; storeValue = true; break; case LWM2M_TYPE_FLOAT: if (1 != lwm2m_data_decode_float(dataP, &floatValue)) continue; storeValue = true; break; default: break; } } for (watcherP = targetP->watcherList ; watcherP != NULL ; watcherP = watcherP->next) { if (watcherP->active == true) { bool notify = false; if (watcherP->update == true) { // value changed, should we notify the server ? if (watcherP->parameters == NULL || watcherP->parameters->toSet == 0) { // no conditions notify = true; LOG("observation_step(/%d/%d/%d) notify[1] = TRUE\n", targetP->uri.objectId, targetP->uri.instanceId, targetP->uri.resourceId); } if (notify == false && watcherP->parameters != NULL && (watcherP->parameters->toSet & ATTR_FLAG_NUMERIC) != 0) { if ((watcherP->parameters->toSet & LWM2M_ATTR_FLAG_LESS_THAN) != 0) { // Did we cross the lower treshold ? switch (dataP->type) { case LWM2M_TYPE_INTEGER: if ((integerValue <= watcherP->parameters->lessThan && watcherP->lastValue.asInteger > watcherP->parameters->lessThan) || (integerValue >= watcherP->parameters->lessThan && watcherP->lastValue.asInteger < watcherP->parameters->lessThan)) { notify = true; } break; case LWM2M_TYPE_FLOAT: if ((floatValue <= watcherP->parameters->lessThan && watcherP->lastValue.asFloat > watcherP->parameters->lessThan) || (floatValue >= watcherP->parameters->lessThan && watcherP->lastValue.asFloat < watcherP->parameters->lessThan)) { notify = true; } break; default: break; } LOG("observation_step(/%d/%d/%d) notify[2] = %s\n", targetP->uri.objectId, targetP->uri.instanceId, targetP->uri.resourceId, notify ? "TRUE" : "FALSE"); } if ((watcherP->parameters->toSet & LWM2M_ATTR_FLAG_GREATER_THAN) != 0) { // Did we cross the upper treshold ? switch (dataP->type) { case LWM2M_TYPE_INTEGER: if ((integerValue <= watcherP->parameters->greaterThan && watcherP->lastValue.asInteger > watcherP->parameters->greaterThan) || (integerValue >= watcherP->parameters->greaterThan && watcherP->lastValue.asInteger < watcherP->parameters->greaterThan)) { notify = true; } break; case LWM2M_TYPE_FLOAT: if ((floatValue <= watcherP->parameters->greaterThan && watcherP->lastValue.asFloat > watcherP->parameters->greaterThan) || (floatValue >= watcherP->parameters->greaterThan && watcherP->lastValue.asFloat < watcherP->parameters->greaterThan)) { notify = true; } break; default: break; } LOG("observation_step(/%d/%d/%d) notify[3] = %s\n", targetP->uri.objectId, targetP->uri.instanceId, targetP->uri.resourceId, notify ? "TRUE" : "FALSE"); } if ((watcherP->parameters->toSet & LWM2M_ATTR_FLAG_STEP) != 0) { switch (dataP->type) { case LWM2M_TYPE_INTEGER: { int64_t diff; diff = integerValue - watcherP->lastValue.asInteger; if ((diff < 0 && (0 - diff) >= watcherP->parameters->step) || (diff >= 0 && diff >= watcherP->parameters->step)) { notify = true; } } break; case LWM2M_TYPE_FLOAT: { double diff; diff = floatValue - watcherP->lastValue.asFloat; if ((diff < 0 && (0 - diff) >= watcherP->parameters->step) || (diff >= 0 && diff >= watcherP->parameters->step)) { notify = true; } } break; default: break; } LOG("observation_step(/%d/%d/%d) notify[4] = %s\n", targetP->uri.objectId, targetP->uri.instanceId, targetP->uri.resourceId, notify? "TRUE" : "FALSE"); } } if (watcherP->parameters != NULL && (watcherP->parameters->toSet & LWM2M_ATTR_FLAG_MIN_PERIOD) != 0) { if (watcherP->lastTime + watcherP->parameters->minPeriod > currentTime) { // Minimum Period did not elapse yet interval = watcherP->lastTime + watcherP->parameters->minPeriod - currentTime; if (*timeoutP > interval) *timeoutP = interval; notify = false; } else { notify = true; } LOG("observation_step(/%d/%d/%d) notify[5] = %s\n", targetP->uri.objectId, targetP->uri.instanceId, targetP->uri.resourceId, notify ? "TRUE" : "FALSE"); } } // Is the Maximum Period reached ? if (notify == false && watcherP->parameters != NULL && (watcherP->parameters->toSet & LWM2M_ATTR_FLAG_MAX_PERIOD) != 0) { if (watcherP->lastTime + watcherP->parameters->maxPeriod <= currentTime) { notify = true; } LOG("observation_step(/%d/%d/%d) notify[6] = %s\n", targetP->uri.objectId, targetP->uri.instanceId, targetP->uri.resourceId, notify ? "TRUE" : "FALSE"); } if (notify == true) { if (buffer == NULL) { if (dataP != NULL) { length = lwm2m_data_serialize(&targetP->uri, size, dataP, &format, &buffer); if (length == 0) break; } else { if (COAP_205_CONTENT != object_read(contextP, &targetP->uri, &format, &buffer, &length)) { buffer = NULL; break; } } coap_init_message(message, COAP_TYPE_NON, COAP_205_CONTENT, 0); coap_set_header_content_type(message, format); coap_set_payload(message, buffer, length); LOG("Observe Update[/%d/%d/%d]: %.*s\n", targetP->uri.objectId, targetP->uri.instanceId, targetP->uri.resourceId, length, buffer); } watcherP->lastTime = currentTime; watcherP->lastMid = contextP->nextMID++; message->mid = watcherP->lastMid; coap_set_header_token(message, watcherP->token, watcherP->tokenLen); coap_set_header_observe(message, watcherP->counter++); (void)message_send(contextP, message, watcherP->server->sessionH); watcherP->update = false; } // Store this value if (notify == true && storeValue == true) { switch (dataP->type) { case LWM2M_TYPE_INTEGER: watcherP->lastValue.asInteger = integerValue; break; case LWM2M_TYPE_FLOAT: watcherP->lastValue.asFloat = floatValue; break; default: break; } } if (watcherP->parameters != NULL && (watcherP->parameters->toSet & LWM2M_ATTR_FLAG_MAX_PERIOD) != 0) { // update timers interval = watcherP->lastTime + watcherP->parameters->maxPeriod - currentTime; if (*timeoutP > interval) *timeoutP = interval; } } } if (dataP != NULL) lwm2m_data_free(size, dataP); if (buffer != NULL) lwm2m_free(buffer); } }
static int prv_serializeValue(lwm2m_data_t * tlvP, uint8_t * buffer, size_t bufferLen) { int res; int head; res = lwm2m_snprintf((char *)(char *)buffer, bufferLen, JSON_RES_ITEM_TEMPLATE, tlvP->id); if (res <= 0 || res >= bufferLen) return -1; switch (tlvP->dataType) { case LWM2M_TYPE_STRING: res = lwm2m_snprintf((char *)buffer, bufferLen, JSON_ITEM_STRING_BEGIN); if (res <= 0 || res >= bufferLen) return -1; head = res; if (tlvP->length >= bufferLen - head) return -1; memcpy(buffer + head, tlvP->value, tlvP->length); head += tlvP->length; res = lwm2m_snprintf((char *)buffer + head, bufferLen - head, JSON_ITEM_STRING_END); if (res <= 0 || res >= bufferLen - head) return -1; res += head; break; case LWM2M_TYPE_INTEGER: case LWM2M_TYPE_TIME: { int64_t value; if (0 == lwm2m_data_decode_int(tlvP, &value)) return -1; res = lwm2m_snprintf((char *)buffer, bufferLen, JSON_ITEM_INTEGER_TEMPLATE, value); if (res <= 0 || res >= bufferLen) return -1; } break; case LWM2M_TYPE_FLOAT: { double value; if (0 == lwm2m_data_decode_float(tlvP, &value)) return -1; res = lwm2m_snprintf((char *)buffer, bufferLen, JSON_ITEM_FLOAT_TEMPLATE, value); if (res <= 0 || res >= bufferLen) return -1; } break; case LWM2M_TYPE_BOOLEAN: { bool value; if (0 == lwm2m_data_decode_bool(tlvP, &value)) return -1; res = lwm2m_snprintf((char *)buffer, bufferLen, value?JSON_ITEM_BOOL_TRUE:JSON_ITEM_BOOL_FALSE); if (res <= 0 || res >= bufferLen) return -1; } break; case LWM2M_TYPE_OPAQUE: // TODO: base64 encoding res = lwm2m_snprintf((char *)buffer, bufferLen, JSON_ITEM_STRING_BEGIN); if (res <= 0 || res >= bufferLen) return -1; head = res; if (tlvP->length >= bufferLen - head) return -1; memcpy(buffer + head, tlvP->value, tlvP->length); head += tlvP->length; res = lwm2m_snprintf((char *)buffer + head, bufferLen - head, JSON_ITEM_STRING_END); if (res <= 0 || res >= bufferLen - head) return -1; res += head; break; case LWM2M_TYPE_OBJECT_LINK: // TODO: implement return -1; case LWM2M_TYPE_UNDEFINED: if ((tlvP->flags & LWM2M_TLV_FLAG_TEXT_FORMAT) != 0) { res = lwm2m_snprintf((char *)buffer, bufferLen, JSON_ITEM_STRING_BEGIN); if (res <= 0 || res >= bufferLen) return -1; head = res; if (tlvP->length >= bufferLen - head) return -1; memcpy(buffer + head, tlvP->value, tlvP->length); head += tlvP->length; res = lwm2m_snprintf((char *)buffer + head, bufferLen - head, JSON_ITEM_STRING_END); if (res <= 0 || res >= bufferLen - head) return -1; res += head; } else { return -1; } break; default: break; } return res; }
static uint8_t prv_security_write(uint16_t instanceId, int numData, lwm2m_data_t * dataArray, lwm2m_object_t * objectP) { security_instance_t * targetP; int i; uint8_t result = COAP_204_CHANGED; targetP = (security_instance_t *)lwm2m_list_find(objectP->instanceList, instanceId); if (NULL == targetP) { return COAP_404_NOT_FOUND; } i = 0; do { switch (dataArray[i].id) { case LWM2M_SECURITY_URI_ID: if (targetP->uri != NULL) lwm2m_free(targetP->uri); targetP->uri = (char *)lwm2m_malloc(dataArray[i].value.asBuffer.length + 1); memset(targetP->uri, 0, dataArray[i].value.asBuffer.length + 1); if (targetP->uri != NULL) { strncpy(targetP->uri, (char*)dataArray[i].value.asBuffer.buffer, dataArray[i].value.asBuffer.length); result = COAP_204_CHANGED; } else { result = COAP_500_INTERNAL_SERVER_ERROR; } break; case LWM2M_SECURITY_BOOTSTRAP_ID: if (1 == lwm2m_data_decode_bool(dataArray + i, &(targetP->isBootstrap))) { result = COAP_204_CHANGED; } else { result = COAP_400_BAD_REQUEST; } break; case LWM2M_SECURITY_SECURITY_ID: { int64_t value; if (1 == lwm2m_data_decode_int(dataArray + i, &value)) { if (value >= 0 && value <= 3) { targetP->securityMode = value; result = COAP_204_CHANGED; } else { result = COAP_406_NOT_ACCEPTABLE; } } else { result = COAP_400_BAD_REQUEST; } } break; case LWM2M_SECURITY_PUBLIC_KEY_ID: if (targetP->publicIdentity != NULL) lwm2m_free(targetP->publicIdentity); targetP->publicIdentity = (char *)lwm2m_malloc(dataArray[i].value.asBuffer.length +1); memset(targetP->publicIdentity, 0, dataArray[i].value.asBuffer.length + 1); if (targetP->publicIdentity != NULL) { memcpy(targetP->publicIdentity, (char*)dataArray[i].value.asBuffer.buffer, dataArray[i].value.asBuffer.length); targetP->publicIdLen = dataArray[i].value.asBuffer.length; result = COAP_204_CHANGED; } else { result = COAP_500_INTERNAL_SERVER_ERROR; } break; case LWM2M_SECURITY_SERVER_PUBLIC_KEY_ID: if (targetP->serverPublicKey != NULL) lwm2m_free(targetP->serverPublicKey); targetP->serverPublicKey = (char *)lwm2m_malloc(dataArray[i].value.asBuffer.length +1); memset(targetP->serverPublicKey, 0, dataArray[i].value.asBuffer.length + 1); if (targetP->serverPublicKey != NULL) { memcpy(targetP->serverPublicKey, (char*)dataArray[i].value.asBuffer.buffer, dataArray[i].value.asBuffer.length); targetP->serverPublicKeyLen = dataArray[i].value.asBuffer.length; result = COAP_204_CHANGED; } else { result = COAP_500_INTERNAL_SERVER_ERROR; } break; case LWM2M_SECURITY_SECRET_KEY_ID: if (targetP->secretKey != NULL) lwm2m_free(targetP->secretKey); targetP->secretKey = (char *)lwm2m_malloc(dataArray[i].value.asBuffer.length +1); memset(targetP->secretKey, 0, dataArray[i].value.asBuffer.length + 1); if (targetP->secretKey != NULL) { memcpy(targetP->secretKey, (char*)dataArray[i].value.asBuffer.buffer, dataArray[i].value.asBuffer.length); targetP->secretKeyLen = dataArray[i].value.asBuffer.length; result = COAP_204_CHANGED; } else { result = COAP_500_INTERNAL_SERVER_ERROR; } break; case LWM2M_SECURITY_SMS_SECURITY_ID: // Let just ignore this result = COAP_204_CHANGED; break; case LWM2M_SECURITY_SMS_KEY_PARAM_ID: // Let just ignore this result = COAP_204_CHANGED; break; case LWM2M_SECURITY_SMS_SECRET_KEY_ID: // Let just ignore this result = COAP_204_CHANGED; break; case LWM2M_SECURITY_SMS_SERVER_NUMBER_ID: // Let just ignore this result = COAP_204_CHANGED; break; case LWM2M_SECURITY_SHORT_SERVER_ID: { int64_t value; if (1 == lwm2m_data_decode_int(dataArray + i, &value)) { if (value >= 0 && value <= 0xFFFF) { targetP->shortID = value; result = COAP_204_CHANGED; } else { result = COAP_406_NOT_ACCEPTABLE; } } else { result = COAP_400_BAD_REQUEST; } } break; case LWM2M_SECURITY_HOLD_OFF_ID: { int64_t value; if (1 == lwm2m_data_decode_int(dataArray + i, &value)) { if (value >= 0 && value <= 0xFFFF) { targetP->clientHoldOffTime = value; result = COAP_204_CHANGED; } else { result = COAP_406_NOT_ACCEPTABLE; } } else { result = COAP_400_BAD_REQUEST; } break; } default: return COAP_404_NOT_FOUND; } i++; } while (i < numData && result == COAP_204_CHANGED); return result; }
uint8_t connectivity_moni_change(lwm2m_data_t * dataArray, lwm2m_object_t * objectP) { int64_t value; uint8_t result; conn_m_data_t * data; data = (conn_m_data_t*) (objectP->userData); switch (dataArray->id) { case RES_M_RADIO_SIGNAL_STRENGTH: if (1 == lwm2m_data_decode_int(dataArray, &value)) { data->signalStrength = value; result = COAP_204_CHANGED; } else { result = COAP_400_BAD_REQUEST; } break; case RES_O_LINK_QUALITY: if (1 == lwm2m_data_decode_int(dataArray, &value)) { data->linkQuality = value; result = COAP_204_CHANGED; } else { result = COAP_400_BAD_REQUEST; } break; case RES_M_IP_ADDRESSES: if (sizeof(data->ipAddresses[0]) <= dataArray->value.asBuffer.length) { result = COAP_400_BAD_REQUEST; } else { memset(data->ipAddresses[0], 0, sizeof(data->ipAddresses[0])); memcpy(data->ipAddresses[0], dataArray->value.asBuffer.buffer, dataArray->value.asBuffer.length); data->ipAddresses[0][dataArray->value.asBuffer.length] = 0; result = COAP_204_CHANGED; } break; case RES_O_ROUTER_IP_ADDRESS: if (sizeof(data->routerIpAddresses[0]) <= dataArray->value.asBuffer.length) { result = COAP_400_BAD_REQUEST; } else { memset(data->routerIpAddresses[0], 0, sizeof(data->routerIpAddresses[0])); memcpy(data->routerIpAddresses[0], dataArray->value.asBuffer.buffer, dataArray->value.asBuffer.length); data->routerIpAddresses[0][dataArray->value.asBuffer.length] = 0; result = COAP_204_CHANGED; } break; case RES_O_CELL_ID: if (1 == lwm2m_data_decode_int(dataArray, &value)) { data->cellId = value; result = COAP_204_CHANGED; } else { result = COAP_400_BAD_REQUEST; } break; default: result = COAP_405_METHOD_NOT_ALLOWED; } return result; }
static int prv_serializeValue(lwm2m_data_t * tlvP, uint8_t * buffer, size_t bufferLen) { int res; int head; switch (tlvP->type) { case LWM2M_TYPE_STRING: if (bufferLen < JSON_ITEM_STRING_BEGIN_SIZE) return -1; memcpy(buffer, JSON_ITEM_STRING_BEGIN, JSON_ITEM_STRING_BEGIN_SIZE); head = JSON_ITEM_STRING_BEGIN_SIZE; if (bufferLen - head < tlvP->value.asBuffer.length) return -1; memcpy(buffer + head, tlvP->value.asBuffer.buffer, tlvP->value.asBuffer.length); head += tlvP->value.asBuffer.length; if (bufferLen - head < JSON_ITEM_STRING_END_SIZE) return -1; memcpy(buffer + head, JSON_ITEM_STRING_END, JSON_ITEM_STRING_END_SIZE); head += JSON_ITEM_STRING_END_SIZE; break; case LWM2M_TYPE_INTEGER: { int64_t value; if (0 == lwm2m_data_decode_int(tlvP, &value)) return -1; if (bufferLen < JSON_ITEM_NUM_SIZE) return -1; memcpy(buffer, JSON_ITEM_NUM, JSON_ITEM_NUM_SIZE); head = JSON_ITEM_NUM_SIZE; res = utils_intToText(value, buffer + head, bufferLen - head); if (res <= 0) return -1; head += res; if (bufferLen - head < JSON_ITEM_NUM_END_SIZE) return -1; memcpy(buffer + head, JSON_ITEM_NUM_END, JSON_ITEM_NUM_END_SIZE); head += JSON_ITEM_NUM_END_SIZE; } break; case LWM2M_TYPE_FLOAT: { double value; if (0 == lwm2m_data_decode_float(tlvP, &value)) return -1; if (bufferLen < JSON_ITEM_NUM_SIZE) return -1; memcpy(buffer, JSON_ITEM_NUM, JSON_ITEM_NUM_SIZE); head = JSON_ITEM_NUM_SIZE; res = utils_floatToText(value, buffer + head, bufferLen - head); if (res <= 0) return -1; head += res; if (bufferLen - head < JSON_ITEM_NUM_END_SIZE) return -1; memcpy(buffer + head, JSON_ITEM_NUM_END, JSON_ITEM_NUM_END_SIZE); head += JSON_ITEM_NUM_END_SIZE; } break; case LWM2M_TYPE_BOOLEAN: { bool value; if (0 == lwm2m_data_decode_bool(tlvP, &value)) return -1; if (value == true) { if (bufferLen < JSON_ITEM_BOOL_TRUE_SIZE) return -1; memcpy(buffer, JSON_ITEM_BOOL_TRUE, JSON_ITEM_BOOL_TRUE_SIZE); head = JSON_ITEM_BOOL_TRUE_SIZE; } else { if (bufferLen < JSON_ITEM_BOOL_FALSE_SIZE) return -1; memcpy(buffer, JSON_ITEM_BOOL_FALSE, JSON_ITEM_BOOL_FALSE_SIZE); head = JSON_ITEM_BOOL_FALSE_SIZE; } } break; case LWM2M_TYPE_OPAQUE: if (bufferLen < JSON_ITEM_STRING_BEGIN_SIZE) return -1; memcpy(buffer, JSON_ITEM_STRING_BEGIN, JSON_ITEM_STRING_BEGIN_SIZE); head = JSON_ITEM_STRING_BEGIN_SIZE; res = utils_base64Encode(tlvP->value.asBuffer.buffer, tlvP->value.asBuffer.length, buffer+head, bufferLen - head); if (tlvP->value.asBuffer.length != 0 && res == 0) return -1; head += res; if (bufferLen - head < JSON_ITEM_STRING_END_SIZE) return -1; memcpy(buffer + head, JSON_ITEM_STRING_END, JSON_ITEM_STRING_END_SIZE); head += JSON_ITEM_STRING_END_SIZE; break; case LWM2M_TYPE_OBJECT_LINK: // TODO: implement return -1; default: return -1; } return head; }
static int prv_serializeValue(const lwm2m_data_t * tlvP, uint8_t * buffer, size_t bufferLen) { size_t res; size_t head; switch (tlvP->type) { case LWM2M_TYPE_STRING: case LWM2M_TYPE_CORE_LINK: if (bufferLen < JSON_ITEM_STRING_BEGIN_SIZE) return -1; memcpy(buffer, JSON_ITEM_STRING_BEGIN, JSON_ITEM_STRING_BEGIN_SIZE); head = JSON_ITEM_STRING_BEGIN_SIZE; res = json_escapeString(buffer + head, bufferLen - head, tlvP->value.asBuffer.buffer, tlvP->value.asBuffer.length); if (!res) return -1; head += res; if (bufferLen - head < 1) return -1; buffer[head++] = JSON_ITEM_STRING_END; break; case LWM2M_TYPE_INTEGER: { int64_t value; if (0 == lwm2m_data_decode_int(tlvP, &value)) return -1; if (bufferLen < JSON_ITEM_NUM_SIZE) return -1; memcpy(buffer, JSON_ITEM_NUM, JSON_ITEM_NUM_SIZE); head = JSON_ITEM_NUM_SIZE; res = utils_intToText(value, buffer + head, bufferLen - head); if (!res) return -1; head += res; } break; case LWM2M_TYPE_UNSIGNED_INTEGER: { uint64_t value; if (0 == lwm2m_data_decode_uint(tlvP, &value)) return -1; if (bufferLen < JSON_ITEM_NUM_SIZE) return -1; memcpy(buffer, JSON_ITEM_NUM, JSON_ITEM_NUM_SIZE); head = JSON_ITEM_NUM_SIZE; res = utils_uintToText(value, buffer + head, bufferLen - head); if (!res) return -1; head += res; } break; case LWM2M_TYPE_FLOAT: { double value; if (0 == lwm2m_data_decode_float(tlvP, &value)) return -1; if (bufferLen < JSON_ITEM_NUM_SIZE) return -1; memcpy(buffer, JSON_ITEM_NUM, JSON_ITEM_NUM_SIZE); head = JSON_ITEM_NUM_SIZE; res = utils_floatToText(value, buffer + head, bufferLen - head); if (!res) return -1; head += res; } break; case LWM2M_TYPE_BOOLEAN: { bool value; if (0 == lwm2m_data_decode_bool(tlvP, &value)) return -1; if (value) { if (bufferLen < JSON_ITEM_BOOL_SIZE + JSON_TRUE_STRING_SIZE) return -1; memcpy(buffer, JSON_ITEM_BOOL JSON_TRUE_STRING, JSON_ITEM_BOOL_SIZE + JSON_TRUE_STRING_SIZE); head = JSON_ITEM_BOOL_SIZE + JSON_TRUE_STRING_SIZE; } else { if (bufferLen < JSON_ITEM_BOOL_SIZE + JSON_FALSE_STRING_SIZE) return -1; memcpy(buffer, JSON_ITEM_BOOL JSON_FALSE_STRING, JSON_ITEM_BOOL_SIZE + JSON_FALSE_STRING_SIZE); head = JSON_ITEM_BOOL_SIZE + JSON_FALSE_STRING_SIZE; } } break; case LWM2M_TYPE_OPAQUE: if (bufferLen < JSON_ITEM_OPAQUE_BEGIN_SIZE) return -1; memcpy(buffer, JSON_ITEM_OPAQUE_BEGIN, JSON_ITEM_OPAQUE_BEGIN_SIZE); head = JSON_ITEM_OPAQUE_BEGIN_SIZE; if (tlvP->value.asBuffer.length > 0) { res = utils_base64Encode(tlvP->value.asBuffer.buffer, tlvP->value.asBuffer.length, buffer+head, bufferLen - head); if (!res) return -1; head += res; } if (bufferLen - head < 1) return -1; buffer[head++] = JSON_ITEM_OPAQUE_END; break; case LWM2M_TYPE_OBJECT_LINK: if (bufferLen < JSON_ITEM_OBJECT_LINK_BEGIN_SIZE) return -1; memcpy(buffer, JSON_ITEM_OBJECT_LINK_BEGIN, JSON_ITEM_OBJECT_LINK_BEGIN_SIZE); head = JSON_ITEM_OBJECT_LINK_BEGIN_SIZE; res = utils_objLinkToText(tlvP->value.asObjLink.objectId, tlvP->value.asObjLink.objectInstanceId, buffer + head, bufferLen - head); if (!res) return -1; head += res; if (bufferLen - head < 1) return -1; buffer[head++] = JSON_ITEM_OBJECT_LINK_END; break; default: return -1; } return (int)head; }