static uint8_t prv_checkServerStatus(lwm2m_server_t * serverP) { LOG_ARG("Initial status: %s", STR_STATUS(serverP->status)); switch (serverP->status) { case STATE_BS_HOLD_OFF: serverP->status = STATE_BS_PENDING; LOG_ARG("Status changed to: %s", STR_STATUS(serverP->status)); break; case STATE_BS_INITIATED: // The ACK was probably lost serverP->status = STATE_BS_PENDING; LOG_ARG("Status changed to: %s", STR_STATUS(serverP->status)); break; case STATE_DEREGISTERED: // server initiated bootstrap case STATE_BS_PENDING: serverP->registration = lwm2m_gettime() + COAP_EXCHANGE_LIFETIME; break; case STATE_BS_FINISHED: case STATE_BS_FINISHING: case STATE_BS_FAILING: case STATE_BS_FAILED: default: LOG("Returning COAP_IGNORE"); return COAP_IGNORE; } return COAP_NO_ERROR; }
int uri_toString(lwm2m_uri_t * uriP, uint8_t * buffer, size_t bufferLen, uri_depth_t * depthP) { size_t head; int res; LOG_ARG("bufferLen: %u", bufferLen); LOG_URI(uriP); buffer[0] = '/'; if (uriP == NULL) { if (depthP) *depthP = URI_DEPTH_OBJECT; return 1; } head = 1; res = utils_intToText(uriP->objectId, buffer + head, bufferLen - head); if (res <= 0) return -1; head += res; if (head >= bufferLen - 1) return -1; if (depthP) *depthP = URI_DEPTH_OBJECT_INSTANCE; if (LWM2M_URI_IS_SET_INSTANCE(uriP)) { buffer[head] = '/'; head++; res = utils_intToText(uriP->instanceId, buffer + head, bufferLen - head); if (res <= 0) return -1; head += res; if (head >= bufferLen - 1) return -1; if (depthP) *depthP = URI_DEPTH_RESOURCE; if (LWM2M_URI_IS_SET_RESOURCE(uriP)) { buffer[head] = '/'; head++; res = utils_intToText(uriP->resourceId, buffer + head, bufferLen - head); if (res <= 0) return -1; head += res; if (head >= bufferLen - 1) return -1; if (depthP) *depthP = URI_DEPTH_RESOURCE_INSTANCE; } } buffer[head] = '/'; head++; LOG_ARG("length: %u, buffer: \"%.*s\"", head, head, buffer); return head; }
void transaction_remove(lwm2m_context_t * contextP, lwm2m_transaction_t * transacP) { LOG_ARG("Entering. transaction=%p", transacP); contextP->transactionList = (lwm2m_transaction_t *) LWM2M_LIST_RM(contextP->transactionList, transacP->mID, NULL); transaction_free(transacP); }
void lwm2m_data_include(lwm2m_data_t * subDataP, size_t count, lwm2m_data_t * dataP) { LOG_ARG("count: %d", count); if (subDataP == NULL || count == 0) return; switch (subDataP[0].type) { case LWM2M_TYPE_STRING: case LWM2M_TYPE_OPAQUE: case LWM2M_TYPE_INTEGER: case LWM2M_TYPE_FLOAT: case LWM2M_TYPE_BOOLEAN: case LWM2M_TYPE_OBJECT_LINK: case LWM2M_TYPE_MULTIPLE_RESOURCE: dataP->type = LWM2M_TYPE_OBJECT_INSTANCE; break; case LWM2M_TYPE_OBJECT_INSTANCE: dataP->type = LWM2M_TYPE_OBJECT; break; default: return; } dataP->value.asChildren.count = count; dataP->value.asChildren.array = subDataP; }
void lwm2m_data_encode_opaque(uint8_t * buffer, size_t length, lwm2m_data_t * dataP) { int res; LOG_ARG("length: %d", length); if (length == 0) { dataP->value.asBuffer.length = 0; dataP->value.asBuffer.buffer = NULL; res = 1; } else { res = prv_setBuffer(dataP, buffer, length); } if (res == 1) { dataP->type = LWM2M_TYPE_OPAQUE; } else { dataP->type = LWM2M_TYPE_UNDEFINED; } }
void lwm2m_data_free(int size, lwm2m_data_t * dataP) { int i; LOG_ARG("size: %d", size); if (size == 0 || dataP == NULL) return; for (i = 0; i < size; i++) { switch (dataP[i].type) { case LWM2M_TYPE_MULTIPLE_RESOURCE: case LWM2M_TYPE_OBJECT_INSTANCE: case LWM2M_TYPE_OBJECT: lwm2m_data_free(dataP[i].value.asChildren.count, dataP[i].value.asChildren.array); break; case LWM2M_TYPE_STRING: case LWM2M_TYPE_OPAQUE: if (dataP[i].value.asBuffer.buffer != NULL) { lwm2m_free(dataP[i].value.asBuffer.buffer); } default: // do nothing break; } } lwm2m_free(dataP); }
int lwm2m_data_decode_bool(const lwm2m_data_t * dataP, bool * valueP) { int result; LOG("Entering"); switch (dataP->type) { case LWM2M_TYPE_BOOLEAN: *valueP = dataP->value.asBoolean; result = 1; break; case LWM2M_TYPE_STRING: if (dataP->value.asBuffer.length != 1) return 0; switch (dataP->value.asBuffer.buffer[0]) { case '0': *valueP = false; result = 1; break; case '1': *valueP = true; result = 1; break; default: result = 0; break; } break; case LWM2M_TYPE_OPAQUE: if (dataP->value.asBuffer.length != 1) return 0; switch (dataP->value.asBuffer.buffer[0]) { case 0: *valueP = false; result = 1; break; case 1: *valueP = true; result = 1; break; default: result = 0; break; } break; default: result = 0; break; } LOG_ARG("result: %d, value: %s", result, *valueP ? "true" : "false"); return result; }
void registration_deregister(lwm2m_context_t * contextP, lwm2m_server_t * serverP) { lwm2m_transaction_t * transaction; LOG_ARG("State: %s, serverP->status: %s", STR_STATE(contextP->state), STR_STATUS(serverP->status)); if (serverP->status == STATE_DEREGISTERED || serverP->status == STATE_REG_PENDING || serverP->status == STATE_DEREG_PENDING || serverP->status == STATE_REG_FAILED || serverP->location == NULL) { return; } transaction = transaction_new(COAP_TYPE_CON, COAP_DELETE, NULL, NULL, contextP->nextMID++, 4, NULL, ENDPOINT_SERVER, (void *)serverP); if (transaction == NULL) return; coap_set_header_uri_path(transaction->message, serverP->location); transaction->callback = prv_handleDeregistrationReply; transaction->userData = (void *) contextP; contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction); if (transaction_send(contextP, transaction) == 0) { serverP->status = STATE_DEREG_PENDING; } }
int lwm2m_dm_write(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_media_type_t format, uint8_t * buffer, int length, lwm2m_result_callback_t callback, void * userData) { LOG_ARG("clientID: %d, format: %s, length: %d", clientID, STR_MEDIA_TYPE(format), length); LOG_URI(uriP); if (!LWM2M_URI_IS_SET_INSTANCE(uriP) || length == 0) { return COAP_400_BAD_REQUEST; } if (LWM2M_URI_IS_SET_RESOURCE(uriP)) { return prv_makeOperation(contextP, clientID, uriP, COAP_PUT, format, buffer, length, callback, userData); } else { return prv_makeOperation(contextP, clientID, uriP, COAP_POST, format, buffer, length, callback, userData); } }
lwm2m_observed_t * observe_findByUri(lwm2m_context_t * contextP, lwm2m_uri_t * uriP) { lwm2m_observed_t * targetP; LOG_URI(uriP); targetP = contextP->observedList; while (targetP != NULL) { if (targetP->uri.objectId == uriP->objectId) { if ((!LWM2M_URI_IS_SET_INSTANCE(uriP) && !LWM2M_URI_IS_SET_INSTANCE(&(targetP->uri))) || (LWM2M_URI_IS_SET_INSTANCE(uriP) && LWM2M_URI_IS_SET_INSTANCE(&(targetP->uri)) && (uriP->instanceId == targetP->uri.instanceId))) { if ((!LWM2M_URI_IS_SET_RESOURCE(uriP) && !LWM2M_URI_IS_SET_RESOURCE(&(targetP->uri))) || (LWM2M_URI_IS_SET_RESOURCE(uriP) && LWM2M_URI_IS_SET_RESOURCE(&(targetP->uri)) && (uriP->resourceId == targetP->uri.resourceId))) { LOG_ARG("Found one with%s observers.", targetP->watcherList ? "" : " no"); LOG_URI(&(targetP->uri)); return targetP; } } } targetP = targetP->next; } LOG("Found nothing"); return NULL; }
int lwm2m_dm_read(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_result_callback_t callback, void * userData) { lwm2m_client_t * clientP; lwm2m_media_type_t format; LOG_ARG("clientID: %d", clientID); LOG_URI(uriP); clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID); if (clientP == NULL) return COAP_404_NOT_FOUND; if (clientP->supportJSON == true) { format = LWM2M_CONTENT_JSON; } else { format = LWM2M_CONTENT_TLV; } return prv_makeOperation(contextP, clientID, uriP, COAP_GET, format, NULL, 0, callback, userData); }
void lwm2m_data_encode_bool(bool value, lwm2m_data_t * dataP) { LOG_ARG("value: %s", value?"true":"false"); dataP->type = LWM2M_TYPE_BOOLEAN; dataP->value.asBoolean = value; }
void lwm2m_data_encode_float(double value, lwm2m_data_t * dataP) { LOG_ARG("value: %f", value); dataP->type = LWM2M_TYPE_FLOAT; dataP->value.asFloat = value; }
void lwm2m_data_encode_int(int64_t value, lwm2m_data_t * dataP) { LOG_ARG("value: %" PRId64 "", value); dataP->type = LWM2M_TYPE_INTEGER; dataP->value.asInteger = value; }
void lwm2m_data_encode_instances(lwm2m_data_t * subDataP, size_t count, lwm2m_data_t * dataP) { LOG_ARG("count: %d", count); lwm2m_data_include(subDataP, count, dataP); dataP->type = LWM2M_TYPE_MULTIPLE_RESOURCE; }
int lwm2m_data_parse(lwm2m_uri_t * uriP, uint8_t * buffer, size_t bufferLen, lwm2m_media_type_t format, lwm2m_data_t ** dataP) { int res; LOG_ARG("format: %s, bufferLen: %d", STR_MEDIA_TYPE(format), bufferLen); LOG_URI(uriP); switch (format) { case LWM2M_CONTENT_TEXT: if (!LWM2M_URI_IS_SET_RESOURCE(uriP)) return 0; *dataP = lwm2m_data_new(1); if (*dataP == NULL) return 0; (*dataP)->id = uriP->resourceId; (*dataP)->type = LWM2M_TYPE_STRING; res = prv_setBuffer(*dataP, buffer, bufferLen); if (res == 0) { lwm2m_data_free(1, *dataP); *dataP = NULL; } return res; case LWM2M_CONTENT_OPAQUE: if (!LWM2M_URI_IS_SET_RESOURCE(uriP)) return 0; *dataP = lwm2m_data_new(1); if (*dataP == NULL) return 0; (*dataP)->id = uriP->resourceId; (*dataP)->type = LWM2M_TYPE_OPAQUE; res = prv_setBuffer(*dataP, buffer, bufferLen); if (res == 0) { lwm2m_data_free(1, *dataP); *dataP = NULL; } return res; #ifdef LWM2M_OLD_CONTENT_FORMAT_SUPPORT case LWM2M_CONTENT_TLV_OLD: #endif case LWM2M_CONTENT_TLV: return tlv_parse(buffer, bufferLen, dataP); #ifdef LWM2M_SUPPORT_JSON #ifdef LWM2M_OLD_CONTENT_FORMAT_SUPPORT case LWM2M_CONTENT_JSON_OLD: #endif case LWM2M_CONTENT_JSON: return json_parse(uriP, buffer, bufferLen, dataP); #endif default: return 0; } }
void lwm2m_data_encode_objlink(uint16_t objectId, uint16_t objectInstanceId, lwm2m_data_t * dataP) { LOG_ARG("value: %d/%d", objectId, objectInstanceId); dataP->type = LWM2M_TYPE_OBJECT_LINK; dataP->value.asObjLink.objectId = objectId; dataP->value.asObjLink.objectInstanceId = objectInstanceId; }
// update the registration of a given server int lwm2m_update_registration(lwm2m_context_t * contextP, uint16_t shortServerID, bool withObjects) { lwm2m_server_t * targetP; uint8_t result; LOG_ARG("State: %s, shortServerID: %d", STR_STATE(contextP->state), shortServerID); result = COAP_NO_ERROR; targetP = contextP->serverList; if (targetP == NULL) { if (object_getServers(contextP) == -1) { LOG("No server found"); return COAP_404_NOT_FOUND; } } while (targetP != NULL && result == COAP_NO_ERROR) { if (shortServerID != 0) { if (targetP->shortID == shortServerID) { // found the server, trigger the update transaction if (targetP->status == STATE_REGISTERED) { return prv_updateRegistration(contextP, targetP, withObjects); } else { return COAP_400_BAD_REQUEST; } } } else { if (targetP->status == STATE_REGISTERED) { result = prv_updateRegistration(contextP, targetP, withObjects); } } targetP = targetP->next; } if (shortServerID != 0 && targetP == NULL) { // no server found result = COAP_404_NOT_FOUND; } return result; }
int lwm2m_data_decode_float(const lwm2m_data_t * dataP, double * valueP) { int result; LOG("Entering"); switch (dataP->type) { case LWM2M_TYPE_FLOAT: *valueP = dataP->value.asFloat; result = 1; break; case LWM2M_TYPE_INTEGER: *valueP = (double)dataP->value.asInteger; result = 1; break; case LWM2M_TYPE_STRING: result = utils_textToFloat(dataP->value.asBuffer.buffer, dataP->value.asBuffer.length, valueP); break; case LWM2M_TYPE_OPAQUE: switch (dataP->value.asBuffer.length) { case 4: { float temp; utils_copyValue(&temp, dataP->value.asBuffer.buffer, dataP->value.asBuffer.length); *valueP = temp; result = 1; } break; case 8: utils_copyValue(valueP, dataP->value.asBuffer.buffer, dataP->value.asBuffer.length); result = 1; break; default: result = 0; } break; default: result = 0; } LOG_ARG("result: %d, value: %f", result, *valueP); return result; }
void transaction_free(lwm2m_transaction_t * transacP) { LOG_ARG("Entering. transaction=%p", transacP); if (transacP->message) { coap_free_header(transacP->message); lwm2m_free(transacP->message); } if (transacP->buffer) lwm2m_free(transacP->buffer); lwm2m_free(transacP); }
void lwm2m_data_encode_nstring(const char * string, size_t length, lwm2m_data_t * dataP) { LOG_ARG("length: %d, string: \"%s\"", length, string); lwm2m_data_encode_opaque((uint8_t *)string, length, dataP); if (dataP->type == LWM2M_TYPE_OPAQUE) { dataP->type = LWM2M_TYPE_STRING; } }
/* * Returns STATE_REG_PENDING if at least one registration is still pending * Returns STATE_REGISTERED if no registration is pending and there is at least one server the client is registered to * Returns STATE_REG_FAILED if all registration failed. */ lwm2m_status_t registration_getStatus(lwm2m_context_t * contextP) { lwm2m_server_t * targetP; lwm2m_status_t reg_status; LOG_ARG("State: %s", STR_STATE(contextP->state)); targetP = contextP->serverList; reg_status = STATE_REG_FAILED; while (targetP != NULL) { LOG_ARG("targetP->status: %s", STR_STATUS(targetP->status)); switch (targetP->status) { case STATE_REGISTERED: case STATE_REG_UPDATE_PENDING: if (reg_status == STATE_REG_FAILED) { reg_status = STATE_REGISTERED; } break; case STATE_REG_PENDING: reg_status = STATE_REG_PENDING; break; case STATE_REG_FAILED: case STATE_DEREG_PENDING: case STATE_DEREGISTERED: default: break; } LOG_ARG("reg_status: %s", STR_STATUS(reg_status)); targetP = targetP->next; } return reg_status; }
void observe_cancel(lwm2m_context_t * contextP, uint16_t mid, void * fromSessionH) { lwm2m_observed_t * observedP; LOG_ARG("mid: %d", mid); for (observedP = contextP->observedList; observedP != NULL; observedP = observedP->next) { lwm2m_watcher_t * targetP = NULL; if ((LWM2M_MAX_ID == mid || observedP->watcherList->lastMid == mid) && lwm2m_session_is_equal(observedP->watcherList->server->sessionH, fromSessionH, contextP->userData)) { targetP = observedP->watcherList; observedP->watcherList = observedP->watcherList->next; } else { lwm2m_watcher_t * parentP; parentP = observedP->watcherList; while (parentP->next != NULL && (parentP->next->lastMid != mid || lwm2m_session_is_equal(parentP->next->server->sessionH, fromSessionH, contextP->userData))) { parentP = parentP->next; } if (parentP->next != NULL) { targetP = parentP->next; parentP->next = parentP->next->next; } } if (targetP != NULL) { if (targetP->parameters != NULL) lwm2m_free(targetP->parameters); lwm2m_free(targetP); if (observedP->watcherList == NULL) { prv_unlinkObserved(contextP, observedP); lwm2m_free(observedP); } return; } } }
lwm2m_data_t * lwm2m_data_new(int size) { lwm2m_data_t * dataP; LOG_ARG("size: %d", size); if (size <= 0) return NULL; dataP = (lwm2m_data_t *)lwm2m_malloc(size * sizeof(lwm2m_data_t)); if (dataP != NULL) { memset(dataP, 0, size * sizeof(lwm2m_data_t)); } return dataP; }
int lwm2m_remove_object(lwm2m_context_t * contextP, uint16_t id) { lwm2m_object_t * targetP; LOG_ARG("ID: %d", id); contextP->objectList = (lwm2m_object_t *)LWM2M_LIST_RM(contextP->objectList, id, &targetP); if (targetP == NULL) return COAP_404_NOT_FOUND; if (contextP->state == STATE_READY) { return lwm2m_update_registration(contextP, 0, true); } return 0; }
int lwm2m_dm_delete(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_result_callback_t callback, void * userData) { LOG_ARG("clientID: %d", clientID); LOG_URI(uriP); if (!LWM2M_URI_IS_SET_INSTANCE(uriP) || LWM2M_URI_IS_SET_RESOURCE(uriP)) { return COAP_400_BAD_REQUEST; } return prv_makeOperation(contextP, clientID, uriP, COAP_DELETE, LWM2M_CONTENT_TEXT, NULL, 0, callback, userData); }
int lwm2m_add_object(lwm2m_context_t * contextP, lwm2m_object_t * objectP) { lwm2m_object_t * targetP; LOG_ARG("ID: %d", objectP->objID); targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, objectP->objID); if (targetP != NULL) return COAP_406_NOT_ACCEPTABLE; objectP->next = NULL; contextP->objectList = (lwm2m_object_t *)LWM2M_LIST_ADD(contextP->objectList, objectP); if (contextP->state == STATE_READY) { return lwm2m_update_registration(contextP, 0, true); } return COAP_NO_ERROR; }
int lwm2m_dm_read(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_result_callback_t callback, void * userData) { lwm2m_client_t * clientP; LOG_ARG("clientID: %d", clientID); LOG_URI(uriP); clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID); if (clientP == NULL) return COAP_404_NOT_FOUND; return prv_makeOperation(contextP, clientID, uriP, COAP_GET, clientP->format, NULL, 0, callback, userData); }
int lwm2m_dm_discover(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_result_callback_t callback, void * userData) { lwm2m_client_t * clientP; lwm2m_transaction_t * transaction; dm_data_t * dataP; LOG_ARG("clientID: %d", clientID); LOG_URI(uriP); clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID); if (clientP == NULL) return COAP_404_NOT_FOUND; transaction = transaction_new(clientP->sessionH, COAP_GET, clientP->altPath, uriP, contextP->nextMID++, 4, NULL); if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR; coap_set_header_accept(transaction->message, LWM2M_CONTENT_LINK); if (callback != NULL) { dataP = (dm_data_t *)lwm2m_malloc(sizeof(dm_data_t)); if (dataP == NULL) { transaction_free(transaction); return COAP_500_INTERNAL_SERVER_ERROR; } memcpy(&dataP->uri, uriP, sizeof(lwm2m_uri_t)); dataP->clientID = clientP->internalID; dataP->callback = callback; dataP->userData = userData; transaction->callback = prv_resultCallback; transaction->userData = (void *)dataP; } contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction); return transaction_send(contextP, transaction); }
uint8_t registration_start(lwm2m_context_t * contextP) { lwm2m_server_t * targetP; uint8_t result; LOG_ARG("State: %s", STR_STATE(contextP->state)); result = COAP_NO_ERROR; targetP = contextP->serverList; while (targetP != NULL && result == COAP_NO_ERROR) { if (targetP->status == STATE_DEREGISTERED || targetP->status == STATE_REG_FAILED) { result = prv_register(contextP, targetP); } targetP = targetP->next; } return result; }