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; }
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 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; }
coap_status_t object_createInstance(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, lwm2m_data_t * dataP) { 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->createFunc) { return COAP_405_METHOD_NOT_ALLOWED; } return targetP->createFunc(lwm2m_list_newId(targetP->instanceList), dataP->value.asChildren.count, dataP->value.asChildren.array, targetP); }
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; }
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; 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(uriP, buffer, length, format, &dataP); if (size == 0) return COAP_500_INTERNAL_SERVER_ERROR; result = targetP->createFunc(uriP->instanceId, size, dataP, targetP); lwm2m_data_free(size, dataP); return result; }
coap_status_t handle_registration_request(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, void * fromSessionH, coap_packet_t * message, coap_packet_t * response) { coap_status_t result; time_t tv_sec; tv_sec = lwm2m_gettime(); if (tv_sec < 0) return COAP_500_INTERNAL_SERVER_ERROR; switch(message->code) { case COAP_POST: { char * name = NULL; uint32_t lifetime; char * msisdn; char * altPath; lwm2m_binding_t binding; lwm2m_client_object_t * objects; lwm2m_client_t * clientP; char location[MAX_LOCATION_LENGTH]; if (0 != prv_getParameters(message->uri_query, &name, &lifetime, &msisdn, &binding)) { return COAP_400_BAD_REQUEST; } objects = prv_decodeRegisterPayload(message->payload, message->payload_len, &altPath); switch (uriP->flag & LWM2M_URI_MASK_ID) { case 0: // Register operation if (objects == NULL) { lwm2m_free(name); if (msisdn != NULL) lwm2m_free(msisdn); return COAP_400_BAD_REQUEST; } // Endpoint client name is mandatory if (name == NULL) { if (msisdn != NULL) lwm2m_free(msisdn); return COAP_400_BAD_REQUEST; } if (lifetime == 0) { lifetime = LWM2M_DEFAULT_LIFETIME; } clientP = prv_getClientByName(contextP, name); if (clientP != NULL) { // we reset this registration lwm2m_free(clientP->name); if (clientP->msisdn != NULL) lwm2m_free(clientP->msisdn); if (clientP->altPath != NULL) lwm2m_free(clientP->altPath); prv_freeClientObjectList(clientP->objectList); clientP->objectList = NULL; } else { clientP = (lwm2m_client_t *)lwm2m_malloc(sizeof(lwm2m_client_t)); if (clientP == NULL) { lwm2m_free(name); lwm2m_free(altPath); if (msisdn != NULL) lwm2m_free(msisdn); prv_freeClientObjectList(objects); return COAP_500_INTERNAL_SERVER_ERROR; } memset(clientP, 0, sizeof(lwm2m_client_t)); clientP->internalID = lwm2m_list_newId((lwm2m_list_t *)contextP->clientList); contextP->clientList = (lwm2m_client_t *)LWM2M_LIST_ADD(contextP->clientList, clientP); } clientP->name = name; clientP->binding = binding; clientP->msisdn = msisdn; clientP->altPath = altPath; clientP->lifetime = lifetime; clientP->endOfLife = tv_sec + lifetime; clientP->objectList = objects; clientP->sessionH = fromSessionH; if (prv_getLocationString(clientP->internalID, location) == 0) { prv_freeClient(clientP); return COAP_500_INTERNAL_SERVER_ERROR; } if (coap_set_header_location_path(response, location) == 0) { prv_freeClient(clientP); return COAP_500_INTERNAL_SERVER_ERROR; } if (contextP->monitorCallback != NULL) { contextP->monitorCallback(clientP->internalID, NULL, CREATED_2_01, NULL, 0, contextP->monitorUserData); } result = COAP_201_CREATED; break; case LWM2M_URI_FLAG_OBJECT_ID: clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, uriP->objectId); if (clientP == NULL) return COAP_404_NOT_FOUND; // Endpoint client name MUST NOT be present if (name != NULL) { lwm2m_free(name); if (msisdn != NULL) lwm2m_free(msisdn); return COAP_400_BAD_REQUEST; } if (binding != BINDING_UNKNOWN) { clientP->binding = binding; } if (msisdn != NULL) { if (clientP->msisdn != NULL) lwm2m_free(clientP->msisdn); clientP->msisdn = msisdn; } if (lifetime != 0) { clientP->lifetime = lifetime; } // client IP address, port or MSISDN may have changed clientP->sessionH = fromSessionH; if (objects != NULL) { lwm2m_observation_t * observationP; // remove observations on object/instance no longer existing observationP = clientP->observationList; while (observationP != NULL) { lwm2m_client_object_t * objP; lwm2m_observation_t * nextP; nextP = observationP->next; objP = (lwm2m_client_object_t *)lwm2m_list_find((lwm2m_list_t *)objects, observationP->uri.objectId); if (objP == NULL) { observationP->callback(clientP->internalID, &observationP->uri, COAP_202_DELETED, NULL, 0, observationP->userData); observation_remove(clientP, observationP); } else { if ((observationP->uri.flag & LWM2M_URI_FLAG_INSTANCE_ID) != 0) { if (lwm2m_list_find((lwm2m_list_t *)objP->instanceList, observationP->uri.instanceId) == NULL) { observationP->callback(clientP->internalID, &observationP->uri, COAP_202_DELETED, NULL, 0, observationP->userData); observation_remove(clientP, observationP); } } } observationP = nextP; } prv_freeClientObjectList(clientP->objectList); clientP->objectList = objects; } clientP->endOfLife = tv_sec + clientP->lifetime; if (contextP->monitorCallback != NULL) { contextP->monitorCallback(clientP->internalID, NULL, COAP_204_CHANGED, NULL, 0, contextP->monitorUserData); } result = COAP_204_CHANGED; break; default: return COAP_400_BAD_REQUEST; } } break; case COAP_DELETE: { lwm2m_client_t * clientP; if ((uriP->flag & LWM2M_URI_MASK_ID) != LWM2M_URI_FLAG_OBJECT_ID) return COAP_400_BAD_REQUEST; contextP->clientList = (lwm2m_client_t *)LWM2M_LIST_RM(contextP->clientList, uriP->objectId, &clientP); if (clientP == NULL) return COAP_400_BAD_REQUEST; if (contextP->monitorCallback != NULL) { contextP->monitorCallback(clientP->internalID, NULL, DELETED_2_02, NULL, 0, contextP->monitorUserData); } prv_freeClient(clientP); result = COAP_202_DELETED; } break; default: return COAP_400_BAD_REQUEST; } return result; }
coap_status_t handle_registration_request(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, struct sockaddr * fromAddr, socklen_t fromAddrLen, coap_packet_t * message, coap_packet_t * response) { coap_status_t result; switch(message->code) { case COAP_POST: { char * name = NULL; lwm2m_client_object_t * objects; lwm2m_client_t * clientP; char location[MAX_LOCATION_LENGTH]; if (uriP->flag & LWM2M_URI_MASK_ID != 0) return COAP_400_BAD_REQUEST; prv_getParameters(message->uri_query, &name); if (name == NULL) return COAP_400_BAD_REQUEST; objects = prv_decodeRegisterPayload(message->payload, message->payload_len); if (objects == NULL) { free(name); return COAP_400_BAD_REQUEST; } clientP = prv_getClientByName(contextP, name); if (clientP != NULL) { // we reset this registration free(clientP->name); free(clientP->addr); prv_freeClientObjectList(clientP->objectList); clientP->objectList = NULL; } else { clientP = (lwm2m_client_t *)malloc(sizeof(lwm2m_client_t)); if (clientP == NULL) { free(name); prv_freeClientObjectList(objects); return COAP_500_INTERNAL_SERVER_ERROR; } memset(clientP, 0, sizeof(lwm2m_client_t)); clientP->internalID = lwm2m_list_newId((lwm2m_list_t *)contextP->clientList); contextP->clientList = (lwm2m_client_t *)LWM2M_LIST_ADD(contextP->clientList, clientP); } clientP->name = name; clientP->objectList = objects; clientP->addr = (struct sockaddr *)malloc(fromAddrLen); if (clientP->addr == NULL) { prv_freeClient(clientP); return COAP_500_INTERNAL_SERVER_ERROR; } memcpy(clientP->addr, fromAddr, fromAddrLen); clientP->addrLen = fromAddrLen; if (prv_getLocationString(clientP->internalID, location) == 0) { prv_freeClient(clientP); return COAP_500_INTERNAL_SERVER_ERROR; } coap_set_header_location_path(response, location); result = CREATED_2_01; } break; case COAP_PUT: result = COAP_501_NOT_IMPLEMENTED; break; case COAP_DELETE: { lwm2m_client_t * clientP; if (uriP->flag & LWM2M_URI_MASK_ID != LWM2M_URI_FLAG_OBJECT_ID) return COAP_400_BAD_REQUEST; contextP->clientList = (lwm2m_client_t *)LWM2M_LIST_RM(contextP->clientList, uriP->objectId, &clientP); if (clientP == NULL) return COAP_400_BAD_REQUEST; prv_freeClient(clientP); result = DELETED_2_02; } break; default: return COAP_400_BAD_REQUEST; } return result; }
int 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]; 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; clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID); if (clientP == NULL) return COAP_404_NOT_FOUND; for (observationP = clientP->observationList; observationP != NULL; observationP = observationP->next) { if (uriP->objectId == observationP->uri.objectId && (LWM2M_URI_IS_SET_INSTANCE(uriP) == false || observationP->uri.instanceId == uriP->instanceId) && (LWM2M_URI_IS_SET_INSTANCE(uriP) == false || observationP->uri.instanceId == uriP->instanceId)) { break; } } if (observationP == NULL) { observationP = (lwm2m_observation_t *)lwm2m_malloc(sizeof(lwm2m_observation_t)); if (observationP == NULL) return COAP_500_INTERNAL_SERVER_ERROR; memset(observationP, 0, sizeof(lwm2m_observation_t)); observationP->id = lwm2m_list_newId((lwm2m_list_t *)clientP->observationList); memcpy(&observationP->uri, uriP, sizeof(lwm2m_uri_t)); observationP->clientP = clientP; observationP->clientP->observationList = (lwm2m_observation_t *)LWM2M_LIST_ADD(observationP->clientP->observationList, observationP); } 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(clientP->sessionH, COAP_GET, clientP->altPath, uriP, contextP->nextMID++, 4, token); if (transactionP == NULL) { observationP->clientP->observationList = (lwm2m_observation_t *)LWM2M_LIST_RM(observationP->clientP->observationList, observationP->id, NULL); lwm2m_free(observationP); return COAP_500_INTERNAL_SERVER_ERROR; } coap_set_header_observe(transactionP->message, 0); if (clientP->supportJSON == true) { coap_set_header_accept(transactionP->message, LWM2M_CONTENT_JSON); } else { coap_set_header_accept(transactionP->message, LWM2M_CONTENT_TLV); } transactionP->callback = prv_obsRequestCallback; transactionP->userData = (void *)observationP; contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transactionP); return transaction_send(contextP, transactionP); }