static lwm2m_client_object_t * prv_decodeRegisterPayload(uint8_t * payload, uint16_t payloadLength) { lwm2m_client_object_t * objList; uint16_t id; uint16_t instance; uint16_t start; uint16_t end; int result; objList = NULL; 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, &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; }
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); }
static uint8_t prv_server_execute(uint16_t instanceId, uint16_t resourceId, uint8_t * buffer, int length, lwm2m_object_t * objectP) { server_instance_t * targetP; targetP = (server_instance_t *)lwm2m_list_find(objectP->instanceList, instanceId); if (NULL == targetP) return COAP_404_NOT_FOUND; switch (resourceId) { case LWM2M_SERVER_DISABLE_ID: // executed in core, if COAP_204_CHANGED is returned return COAP_204_CHANGED; case LWM2M_SERVER_UPDATE_ID: // executed in core, if COAP_204_CHANGED is returned return COAP_204_CHANGED; default: return COAP_405_METHOD_NOT_ALLOWED; } }
static void prv_monitor_callback(uint16_t clientID, lwm2m_uri_t * uriP, int status, uint8_t * data, int dataLength, void * userData) { lwm2m_context_t * lwm2mH = (lwm2m_context_t *) userData; lwm2m_client_t * targetP; lwm2m_client_object_t * objectP; switch (status) { case CREATED_2_01: fprintf(stdout, "\r\nNew client #%d registered.\r\n", clientID); targetP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)lwm2mH->clientList, clientID); prv_dump_client(targetP); break; case DELETED_2_02: fprintf(stdout, "\r\nClient #%d unregistered.\r\n", clientID); break; default: fprintf(stdout, "\r\nMonitor callback called with an unknown status: %d.\r\n", status); break; } fprintf(stdout, "\r\n> "); fflush(stdout); }
static uint8_t prv_exec(uint16_t instanceId, uint16_t resourceId, uint8_t * buffer, int length, lwm2m_object_t * objectP) { if (NULL == lwm2m_list_find(objectP->instanceList, instanceId)) return COAP_404_NOT_FOUND; switch (resourceId) { case 1: return COAP_405_METHOD_NOT_ALLOWED; case 2: fprintf(stdout, "\r\n-----------------\r\n" "Execute on %hu/%d/%d\r\n" " Parameter (%d bytes):\r\n", objectP->objID, instanceId, resourceId, length); prv_output_buffer((uint8_t*)buffer, length); fprintf(stdout, "-----------------\r\n\r\n"); return COAP_204_CHANGED; case 3: return COAP_405_METHOD_NOT_ALLOWED; default: return COAP_404_NOT_FOUND; } }
static uint8_t prv_write(lwm2m_uri_t * uriP, char * buffer, int length, lwm2m_object_t * objectP) { prv_instance_t * targetP; int64_t value; // for write, instance ID is always set targetP = (prv_instance_t *)lwm2m_list_find(objectP->instanceList, uriP->instanceId); if (NULL == targetP) return COAP_404_NOT_FOUND; if (!LWM2M_URI_IS_SET_INSTANCE(uriP)) return COAP_501_NOT_IMPLEMENTED; switch (uriP->resourceId) { case 1: if (1 == lwm2m_PlainTextToInt64(buffer, length, &value)) { if (value >= 0 && value <= 0xFF) { targetP->test = value; return COAP_204_CHANGED; } } return COAP_400_BAD_REQUEST; default: return COAP_404_NOT_FOUND; } }
int ICACHE_FLASH_ATTR lwm2m_observe_cancel(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_result_callback_t callback, void * userData) { lwm2m_client_t * clientP; lwm2m_observation_t * observationP; clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID); if (clientP == NULL) return COAP_404_NOT_FOUND; observationP = prv_findObservationByURI(clientP, uriP); if (observationP == NULL) return COAP_404_NOT_FOUND; switch (observationP->status) { case STATE_REGISTERED: observation_remove(clientP, observationP); break; case STATE_REG_PENDING: observationP->status = STATE_DEREG_PENDING; break; default: // Should not happen break; } return 0; }
uint8_t object_checkReadable(lwm2m_context_t * contextP, lwm2m_uri_t * uriP) { coap_status_t result; lwm2m_object_t * targetP; lwm2m_data_t * dataP = NULL; int size; targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, uriP->objectId); if (NULL == targetP) return COAP_404_NOT_FOUND; if (NULL == targetP->readFunc) return COAP_405_METHOD_NOT_ALLOWED; if (!LWM2M_URI_IS_SET_INSTANCE(uriP)) return COAP_205_CONTENT; if (NULL == lwm2m_list_find(targetP->instanceList, uriP->instanceId)) return COAP_404_NOT_FOUND; if (!LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_205_CONTENT; size = 1; dataP = lwm2m_data_new(1); if (dataP == NULL) return COAP_500_INTERNAL_SERVER_ERROR; dataP->id = uriP->resourceId; result = targetP->readFunc(uriP->instanceId, &size, &dataP, targetP); lwm2m_data_free(1, dataP); return result; }
int lwm2m_observe_cancel(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_result_callback_t callback, void * userData) { lwm2m_client_t * clientP; lwm2m_observation_t * observationP; clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID); if (clientP == NULL) return COAP_404_NOT_FOUND; observationP = prv_findObservationByURI(clientP, uriP); if (observationP == NULL) return COAP_404_NOT_FOUND; switch (observationP->status) { case STATE_REGISTERED: { lwm2m_transaction_t * transactionP; cancellation_data_t * cancelP; transactionP = transaction_new(COAP_TYPE_CON, COAP_GET, clientP->altPath, uriP, contextP->nextMID++, 0, NULL, ENDPOINT_CLIENT, (void *)clientP); if (transactionP == NULL) { return COAP_500_INTERNAL_SERVER_ERROR; } cancelP = (cancellation_data_t *)lwm2m_malloc(sizeof(cancellation_data_t)); if (cancelP == NULL) { lwm2m_free(transactionP); return COAP_500_INTERNAL_SERVER_ERROR; } coap_set_header_observe(transactionP->message, 1); cancelP->observationP = observationP; cancelP->callbackP = callback; cancelP->userDataP = userData; transactionP->callback = prv_obsCancelRequestCallback; transactionP->userData = (void *)cancelP; contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transactionP); return transaction_send(contextP, transactionP); } case STATE_REG_PENDING: observationP->status = STATE_DEREG_PENDING; break; default: // Should not happen break; } return COAP_NO_ERROR; }
coap_status_t object_readData(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, int * sizeP, lwm2m_data_t ** dataP) { coap_status_t result; lwm2m_object_t * targetP; targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, uriP->objectId); if (NULL == targetP) return COAP_404_NOT_FOUND; if (NULL == targetP->readFunc) return COAP_405_METHOD_NOT_ALLOWED; if (targetP->instanceList == NULL) return COAP_404_NOT_FOUND; if (LWM2M_URI_IS_SET_INSTANCE(uriP)) { if (NULL == lwm2m_list_find(targetP->instanceList, uriP->instanceId)) return COAP_404_NOT_FOUND; // single instance read if (LWM2M_URI_IS_SET_RESOURCE(uriP)) { *sizeP = 1; *dataP = lwm2m_data_new(*sizeP); if (*dataP == NULL) return COAP_500_INTERNAL_SERVER_ERROR; (*dataP)->id = uriP->resourceId; } result = targetP->readFunc(uriP->instanceId, sizeP, dataP, targetP); } else { // multiple object instances read lwm2m_list_t * instanceP; int i; *sizeP = 0; for (instanceP = targetP->instanceList; instanceP != NULL ; instanceP = instanceP->next) { (*sizeP)++; } *dataP = lwm2m_data_new(*sizeP); if (*dataP == NULL) return COAP_500_INTERNAL_SERVER_ERROR; result = COAP_205_CONTENT; instanceP = targetP->instanceList; i = 0; while (instanceP != NULL && result == COAP_205_CONTENT) { result = targetP->readFunc(instanceP->id, (int*)&((*dataP)[i].value.asChildren.count), &((*dataP)[i].value.asChildren.array), targetP); (*dataP)[i].type = LWM2M_TYPE_OBJECT_INSTANCE; (*dataP)[i].id = instanceP->id; i++; instanceP = instanceP->next; } } return result; }
coap_status_t object_create(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, lwm2m_media_type_t format, uint8_t * buffer, size_t length) { lwm2m_object_t * targetP; lwm2m_data_t * dataP = NULL; int size = 0; uint8_t result; if (length == 0 || buffer == 0) { return COAP_400_BAD_REQUEST; } targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, uriP->objectId); if (NULL == targetP) return COAP_404_NOT_FOUND; if (NULL == targetP->createFunc) return COAP_405_METHOD_NOT_ALLOWED; size = lwm2m_data_parse(uriP, buffer, length, format, &dataP); if (size <= 0) return COAP_400_BAD_REQUEST; switch (dataP[0].type) { case LWM2M_TYPE_OBJECT: result = COAP_400_BAD_REQUEST; goto exit; case LWM2M_TYPE_OBJECT_INSTANCE: if (size != 1) { result = COAP_400_BAD_REQUEST; goto exit; } if (NULL != lwm2m_list_find(targetP->instanceList, dataP[0].id)) { // Instance already exists result = COAP_406_NOT_ACCEPTABLE; goto exit; } result = targetP->createFunc(dataP[0].id, dataP[0].value.asChildren.count, dataP[0].value.asChildren.array, targetP); uriP->instanceId = dataP[0].id; uriP->flag |= LWM2M_URI_FLAG_INSTANCE_ID; break; default: uriP->instanceId = lwm2m_list_newId(targetP->instanceList); uriP->flag |= LWM2M_URI_FLAG_INSTANCE_ID; result = targetP->createFunc(uriP->instanceId, size, dataP, targetP); break; } exit: lwm2m_data_free(size, dataP); return result; }
bool ICACHE_FLASH_ATTR handle_observe_notify(lwm2m_context_t * contextP, void * fromSessionH, coap_packet_t * message, coap_packet_t * response) { uint8_t * tokenP; int token_len; uint16_t clientID; uint16_t obsID; lwm2m_client_t * clientP; lwm2m_observation_t * observationP; uint32_t count; token_len = coap_get_header_token(message, (const uint8_t **)&tokenP); if (token_len != sizeof(uint32_t)) return false; if (1 != coap_get_header_observe(message, &count)) return false; clientID = (tokenP[0] << 8) | tokenP[1]; obsID = (tokenP[2] << 8) | tokenP[3]; clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID); if (clientP == NULL) return false; observationP = (lwm2m_observation_t *)lwm2m_list_find((lwm2m_list_t *)clientP->observationList, obsID); if (observationP == NULL) { coap_init_message(response, COAP_TYPE_RST, 0, message->mid); message_send(contextP, response, fromSessionH); } else { if (message->type == COAP_TYPE_CON ) { coap_init_message(response, COAP_TYPE_ACK, 0, message->mid); message_send(contextP, response, fromSessionH); } observationP->callback(clientID, &observationP->uri, (int)count, message->content_type, message->payload, message->payload_len, observationP->userData); } return true; }
coap_status_t object_security_delete(lwm2m_context_t * contextP, lwm2m_uri_t * uriP) { lwm2m_server_t * serverP; serverP = (lwm2m_server_t *)lwm2m_list_find((lwm2m_list_t *)contextP->serverList, uriP->instanceId); if (serverP == NULL) return COAP_404_NOT_FOUND; return COAP_501_NOT_IMPLEMENTED; }
void handle_observe_notify(lwm2m_context_t * contextP, uint8_t * fromAddr, size_t fromAddrLen, coap_packet_t * message) { uint8_t * tokenP; int token_len; uint16_t clientID; uint16_t obsID; lwm2m_client_t * clientP; lwm2m_observation_t * observationP; uint32_t count; token_len = coap_get_header_token(message, (const uint8_t **)&tokenP); if (token_len != sizeof(uint32_t)) return; if (1 != coap_get_header_observe(message, &count)) return; clientID = (tokenP[0] << 8) | tokenP[1]; obsID = (tokenP[2] << 8) | tokenP[3]; clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID); if (clientP == NULL) return; observationP = (lwm2m_observation_t *)lwm2m_list_find((lwm2m_list_t *)clientP->observationList, obsID); if (observationP == NULL) { coap_packet_t resetMsg; coap_init_message(&resetMsg, COAP_TYPE_RST, 0, message->mid); message_send(contextP, &resetMsg, fromAddr, fromAddrLen); } else { observationP->callback(clientID, &observationP->uri, (int)count, message->payload, message->payload_len, observationP->userData); } }
coap_status_t object_server_read(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, char ** bufferP, int * lengthP) { if (!LWM2M_URI_IS_SET_INSTANCE(uriP)) { return COAP_501_NOT_IMPLEMENTED; } else { lwm2m_server_t * serverP; serverP = (lwm2m_server_t *)lwm2m_list_find((lwm2m_list_t *)contextP->serverList, uriP->instanceId); if (serverP == NULL) return COAP_404_NOT_FOUND; if (!LWM2M_URI_IS_SET_RESOURCE(uriP)) { return COAP_501_NOT_IMPLEMENTED; } else { switch (uriP->resourceId) { case RESOURCE_SHORTID_ID: *lengthP = lwm2m_int32ToPlainText(serverP->shortID, bufferP); if (0 != *lengthP) { return COAP_205_CONTENT; } else { return COAP_500_INTERNAL_SERVER_ERROR; } break; case RESOURCE_LIFETIME_ID: return COAP_501_NOT_IMPLEMENTED; case RESOURCE_MINPERIOD_ID: return COAP_404_NOT_FOUND; case RESOURCE_MAXPERIOD_ID: return COAP_404_NOT_FOUND; case RESOURCE_TIMEOUT_ID: return COAP_404_NOT_FOUND; case RESOURCE_STORING_ID: return COAP_501_NOT_IMPLEMENTED; case RESOURCE_BINDING_ID: return COAP_501_NOT_IMPLEMENTED; default: return COAP_405_METHOD_NOT_ALLOWED; } } } }
bool acc_ctrl_oi_add_ac_val (lwm2m_object_t* accCtrlObjP, uint16_t instId, uint16_t acResId, uint16_t acValue) { bool ret = false; acc_ctrl_oi_t* accCtrlOiP = (acc_ctrl_oi_t *) lwm2m_list_find(accCtrlObjP->instanceList, instId); if (NULL == accCtrlOiP) return ret; return prv_add_ac_val (accCtrlOiP, acResId, acValue); }
coap_status_t object_server_create(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, char * buffer, int length) { lwm2m_server_t * serverP; serverP = (lwm2m_server_t *)lwm2m_list_find((lwm2m_list_t *)contextP->serverList, uriP->instanceId); if (serverP == NULL) return COAP_404_NOT_FOUND; return COAP_501_NOT_IMPLEMENTED; }
static uint8_t prv_read(uint16_t instanceId, int * numDataP, lwm2m_data_t** dataArrayP, lwm2m_data_cfg_t * dataCfg,lwm2m_object_t * objectP) { uint8_t result; int ri, ni; // multi-instance object: search instance acc_ctrl_oi_t* accCtrlOiP = (acc_ctrl_oi_t *)lwm2m_list_find(objectP->instanceList, instanceId); if (accCtrlOiP == NULL) { return COAP_404_NOT_FOUND ; } // is the server asking for the full object ? if (*numDataP == 0) { uint16_t resList[] = { RES_M_OBJECT_ID, RES_M_OBJECT_INSTANCE_ID, RES_O_ACL, // prv_set_tlv will return COAP_404_NOT_FOUND w/o values! RES_M_ACCESS_CONTROL_OWNER }; int nbRes = sizeof(resList) / sizeof(uint16_t); *dataArrayP = lwm2m_data_new(nbRes); if (*dataArrayP == NULL) return COAP_500_INTERNAL_SERVER_ERROR ; *numDataP = nbRes; for (ri = 0; ri < nbRes; ri++) { (*dataArrayP)[ri].id = resList[ri]; } } ni = ri = 0; do { result = prv_set_tlv((*dataArrayP) + ni, accCtrlOiP); if (result==COAP_404_NOT_FOUND) { ri++; if (*numDataP>1) result = COAP_205_CONTENT; } else if (ri > 0) // copy new one by ri skipped ones in front { (*dataArrayP)[ni-ri] = (*dataArrayP)[ni]; } ni++; } while (ni < *numDataP && result == COAP_205_CONTENT); *numDataP = ni-ri; return result; }
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; }
int ICACHE_FLASH_ATTR lwm2m_observe(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 * transactionP; lwm2m_observation_t * observationP; uint8_t token[4]; if (!LWM2M_URI_IS_SET_INSTANCE(uriP) && LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_400_BAD_REQUEST; clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID); if (clientP == NULL) return COAP_404_NOT_FOUND; observationP = (lwm2m_observation_t *)lwm2m_malloc(sizeof(lwm2m_observation_t)); if (observationP == NULL) return COAP_500_INTERNAL_SERVER_ERROR; c_memset(observationP, 0, sizeof(lwm2m_observation_t)); observationP->id = lwm2m_list_newId((lwm2m_list_t *)clientP->observationList); c_memcpy(&observationP->uri, uriP, sizeof(lwm2m_uri_t)); observationP->clientP = clientP; observationP->status = STATE_REG_PENDING; observationP->callback = callback; observationP->userData = userData; token[0] = clientP->internalID >> 8; token[1] = clientP->internalID & 0xFF; token[2] = observationP->id >> 8; token[3] = observationP->id & 0xFF; transactionP = transaction_new(COAP_TYPE_CON, COAP_GET, clientP->altPath, uriP, contextP->nextMID++, 4, token, ENDPOINT_CLIENT, (void *)clientP); if (transactionP == NULL) { lwm2m_free(observationP); return COAP_500_INTERNAL_SERVER_ERROR; } observationP->clientP->observationList = (lwm2m_observation_t *)LWM2M_LIST_ADD(observationP->clientP->observationList, observationP); coap_set_header_observe(transactionP->message, 0); coap_set_header_token(transactionP->message, token, sizeof(token)); transactionP->callback = prv_obsRequestCallback; transactionP->userData = (void *)observationP; contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transactionP); return transaction_send(contextP, transactionP); }
static int prv_makeOperation(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, coap_method_t method, lwm2m_media_type_t format, uint8_t * buffer, int length, lwm2m_result_callback_t callback, void * userData) { lwm2m_client_t * clientP; lwm2m_transaction_t * transaction; dm_data_t * dataP; 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, method, clientP->altPath, uriP, contextP->nextMID++, 4, NULL); if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR; if (method == COAP_GET) { coap_set_header_accept(transaction->message, format); } else if (buffer != NULL) { coap_set_header_content_type(transaction->message, format); // TODO: Take care of fragmentation coap_set_payload(transaction->message, buffer, length); } 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); }
static uint8_t prv_create(lwm2m_uri_t * uriP, char * buffer, int length, lwm2m_object_t * objectP) { prv_instance_t * targetP; lwm2m_tlv_type_t type; uint16_t newId; uint16_t resID; size_t dataIndex; size_t dataLen; int result; int64_t value; if (LWM2M_URI_IS_SET_INSTANCE(uriP)) { targetP = (prv_instance_t *)lwm2m_list_find(objectP->instanceList, uriP->instanceId); if (targetP != NULL) return COAP_406_NOT_ACCEPTABLE; newId = uriP->instanceId; } else { // determine a new unique ID newId = lwm2m_list_newId(objectP->instanceList); } result = lwm2m_decodeTLV(buffer, length, &type, &resID, &dataIndex, &dataLen); if (result != length) { // decode failure or too much data for our single ressource object return COAP_400_BAD_REQUEST; } if (type != TLV_RESSOURCE || resID != 1) { return COAP_400_BAD_REQUEST; } result = lwm2m_opaqueToInt(buffer + dataIndex, dataLen, &value); if (result == 0 || value < 0 || value > 255) return COAP_400_BAD_REQUEST; targetP = (prv_instance_t *)malloc(sizeof(prv_instance_t)); if (NULL == targetP) return COAP_500_INTERNAL_SERVER_ERROR; memset(targetP, 0, sizeof(prv_instance_t)); targetP->shortID = newId; targetP->test = value; objectP->instanceList = LWM2M_LIST_ADD(objectP->instanceList, targetP); return COAP_201_CREATED; }
coap_status_t ICACHE_FLASH_ATTR object_create(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, lwm2m_media_type_t format, uint8_t * buffer, size_t length) { lwm2m_object_t * targetP; lwm2m_data_t * dataP = NULL; int size = 0; uint8_t result; if (length == 0 || buffer == 0) { return BAD_REQUEST_4_00; } targetP = prv_find_object(contextP, uriP->objectId); if (NULL == targetP) return NOT_FOUND_4_04; if (NULL == targetP->createFunc) return METHOD_NOT_ALLOWED_4_05; if (LWM2M_URI_IS_SET_INSTANCE(uriP)) { if (NULL != lwm2m_list_find(targetP->instanceList, uriP->instanceId)) { // Instance already exists return COAP_406_NOT_ACCEPTABLE; } } else { uriP->instanceId = lwm2m_list_newId(targetP->instanceList); uriP->flag |= LWM2M_URI_FLAG_INSTANCE_ID; } size = lwm2m_data_parse(buffer, length, format, &dataP); if (size == 0) return COAP_500_INTERNAL_SERVER_ERROR; #ifdef ICACHE_FLASH_ATTR if (contextP->bsState == BOOTSTRAP_PENDING) { dataP->flags |= LWM2M_TLV_FLAG_BOOTSTRAPPING; } #endif result = targetP->createFunc(uriP->instanceId, size, dataP, targetP); lwm2m_data_free(size, dataP); return result; }
static uint8_t prv_security_read(uint16_t instanceId, int * numDataP, lwm2m_tlv_t ** dataArrayP, lwm2m_object_t * objectP) { security_instance_t * targetP; uint8_t result; int i; targetP = (security_instance_t *)lwm2m_list_find(objectP->instanceList, instanceId); if (NULL == targetP) return COAP_404_NOT_FOUND; // is the server asking for the full instance ? if (*numDataP == 0) { uint16_t resList[] = {LWM2M_SECURITY_URI_ID, LWM2M_SECURITY_BOOTSTRAP_ID, LWM2M_SECURITY_SECURITY_ID, LWM2M_SECURITY_PUBLIC_KEY_ID, LWM2M_SECURITY_SERVER_PUBLIC_KEY_ID, LWM2M_SECURITY_SECRET_KEY_ID, LWM2M_SECURITY_SMS_SECURITY_ID, LWM2M_SECURITY_SMS_KEY_PARAM_ID, LWM2M_SECURITY_SMS_SECRET_KEY_ID, LWM2M_SECURITY_SMS_SERVER_NUMBER_ID, LWM2M_SECURITY_SHORT_SERVER_ID, LWM2M_SECURITY_HOLD_OFF_ID}; int nbRes = sizeof(resList)/sizeof(uint16_t); *dataArrayP = lwm2m_tlv_new(nbRes); if (*dataArrayP == NULL) return COAP_500_INTERNAL_SERVER_ERROR; *numDataP = nbRes; for (i = 0 ; i < nbRes ; i++) { (*dataArrayP)[i].id = resList[i]; } } i = 0; do { result = prv_get_value((*dataArrayP) + i, targetP); i++; } while (i < *numDataP && result == COAP_205_CONTENT); return result; }
static uint8_t prv_read(uint16_t instanceId, int * numDataP, lwm2m_data_t ** dataArrayP, 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; if (*numDataP == 0) { *dataArrayP = lwm2m_data_new(3); if (*dataArrayP == NULL) return COAP_500_INTERNAL_SERVER_ERROR; *numDataP = 3; (*dataArrayP)[0].id = 1; (*dataArrayP)[1].id = 3; (*dataArrayP)[2].id = 4; } for (i = 0 ; i < *numDataP ; i++) { switch ((*dataArrayP)[i].id) { case 1: (*dataArrayP)[i].type = LWM2M_TYPE_RESOURCE; lwm2m_data_encode_int(targetP->test, *dataArrayP + i); break; case 2: return COAP_405_METHOD_NOT_ALLOWED; case 3: (*dataArrayP)[i].type = LWM2M_TYPE_RESOURCE; lwm2m_data_encode_float(targetP->dec, *dataArrayP + i); break; case 4: (*dataArrayP)[i].type = LWM2M_TYPE_RESOURCE; lwm2m_data_encode_int(targetP->sig, *dataArrayP + i); break; default: return COAP_404_NOT_FOUND; } if ((*dataArrayP)[i].length == 0) return COAP_500_INTERNAL_SERVER_ERROR; } return COAP_205_CONTENT; }
bool object_isInstanceNew(lwm2m_context_t * contextP, uint16_t objectId, uint16_t instanceId) { lwm2m_object_t * targetP; targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, objectId); if (targetP != NULL) { if (NULL != lwm2m_list_find(targetP->instanceList, instanceId)) { return false; } } return true; }
static int prv_make_operation(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, coap_method_t method, char * buffer, int length, lwm2m_result_callback_t callback, void * userData) { lwm2m_client_t * clientP; lwm2m_transaction_t * transaction; dm_data_t * dataP; clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID); if (clientP == NULL) return COAP_404_NOT_FOUND; transaction = transaction_new(method, uriP, contextP->nextMID++, ENDPOINT_CLIENT, (void *)clientP); if (transaction == NULL) return INTERNAL_SERVER_ERROR_5_00; if (buffer != NULL) { // TODO: Take care of fragmentation coap_set_payload(transaction->message, buffer, length); } 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->callback = callback; dataP->userData = userData; transaction->callback = dm_result_callback; transaction->userData = (void *)dataP; } contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction); return transaction_send(contextP, transaction); }
coap_status_t object_create(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, char * buffer, int length) { lwm2m_object_t * targetP; lwm2m_tlv_t * tlvP = NULL; int size = 0; uint8_t result; if (length == 0 || buffer == 0) { return BAD_REQUEST_4_00; } targetP = prv_find_object(contextP, uriP->objectId); if (NULL == targetP) return NOT_FOUND_4_04; if (NULL == targetP->createFunc) return METHOD_NOT_ALLOWED_4_05; if (LWM2M_URI_IS_SET_INSTANCE(uriP)) { if (NULL != lwm2m_list_find(targetP->instanceList, uriP->instanceId)) { // Instance already exists return COAP_406_NOT_ACCEPTABLE; } } else { uriP->instanceId = lwm2m_list_newId(targetP->instanceList); uriP->flag |= LWM2M_URI_FLAG_INSTANCE_ID; } targetP = prv_find_object(contextP, uriP->objectId); if (NULL == targetP) return NOT_FOUND_4_04; if (NULL == targetP->writeFunc) return METHOD_NOT_ALLOWED_4_05; size = lwm2m_tlv_parse(buffer, length, &tlvP); if (size == 0) return COAP_500_INTERNAL_SERVER_ERROR; result = targetP->createFunc(uriP->instanceId, size, tlvP, targetP); lwm2m_tlv_free(size, tlvP); return result; }
bool ICACHE_FLASH_ATTR object_isInstanceNew(lwm2m_context_t * contextP, uint16_t objectId, uint16_t instanceId) { lwm2m_object_t * targetP; targetP = prv_find_object(contextP, objectId); if (targetP != NULL) { if (NULL != lwm2m_list_find(targetP->instanceList, instanceId)) { return false; } } return true; }
int lwm2m_observe_cancel(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_result_callback_t callback, void * userData) { lwm2m_client_t * clientP; lwm2m_observation_t * observationP; clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID); if (clientP == NULL) return COAP_404_NOT_FOUND; observationP = prv_findObservationByURI(clientP, uriP); if (observationP == NULL) return COAP_404_NOT_FOUND; prv_observationRemove(clientP, observationP); return 0; }