void lwm2m_close(lwm2m_context_t * contextP) { #ifdef LWM2M_CLIENT_MODE LOG("Entering"); lwm2m_deregister(contextP); prv_deleteServerList(contextP); prv_deleteBootstrapServerList(contextP); prv_deleteObservedList(contextP); lwm2m_free(contextP->endpointName); if (contextP->msisdn != NULL) { lwm2m_free(contextP->msisdn); } if (contextP->altPath != NULL) { lwm2m_free(contextP->altPath); } #endif #ifdef LWM2M_SERVER_MODE while (NULL != contextP->clientList) { lwm2m_client_t * clientP; clientP = contextP->clientList; contextP->clientList = contextP->clientList->next; registration_freeClient(clientP); } #endif prv_deleteTransactionList(contextP); lwm2m_free(contextP); }
coap_status_t registration_handleRequest(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; bool supportJSON; 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; } if (message->content_type != LWM2M_CONTENT_LINK && message->content_type != LWM2M_CONTENT_TEXT) { return COAP_400_BAD_REQUEST; } objects = prv_decodeRegisterPayload(message->payload, message->payload_len, &supportJSON, &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->supportJSON = supportJSON; clientP->lifetime = lifetime; clientP->endOfLife = tv_sec + lifetime; clientP->objectList = objects; clientP->sessionH = fromSessionH; if (prv_getLocationString(clientP->internalID, location) == 0) { registration_freeClient(clientP); return COAP_500_INTERNAL_SERVER_ERROR; } if (coap_set_header_location_path(response, location) == 0) { registration_freeClient(clientP); return COAP_500_INTERNAL_SERVER_ERROR; } if (contextP->monitorCallback != NULL) { contextP->monitorCallback(clientP->internalID, NULL, COAP_201_CREATED, LWM2M_CONTENT_TEXT, 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, LWM2M_CONTENT_TEXT, NULL, 0, observationP->userData); observe_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, LWM2M_CONTENT_TEXT, NULL, 0, observationP->userData); observe_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, LWM2M_CONTENT_TEXT, 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, COAP_202_DELETED, LWM2M_CONTENT_TEXT, NULL, 0, contextP->monitorUserData); } registration_freeClient(clientP); result = COAP_202_DELETED; } break; default: return COAP_400_BAD_REQUEST; } return result; }
// for each server update the registration if needed // for each client check if the registration expired void registration_step(lwm2m_context_t * contextP, time_t currentTime, time_t * timeoutP) { #ifdef LWM2M_CLIENT_MODE lwm2m_server_t * targetP = contextP->serverList; targetP = contextP->serverList; while (targetP != NULL) { switch (targetP->status) { case STATE_REGISTERED: { time_t nextUpdate; time_t interval; nextUpdate = targetP->lifetime; if (30 < nextUpdate) { nextUpdate -= 15; // update 15s earlier to have a chance to resend } interval = targetP->registration + nextUpdate - currentTime; if (0 >= interval) { LOG("Updating registration...\r\n"); prv_updateRegistration(contextP, targetP, false); } else if (interval < *timeoutP) { *timeoutP = interval; } } break; case STATE_REG_FAILED: if (targetP->sessionH != NULL) { lwm2m_close_connection(targetP->sessionH, contextP->userData); targetP->sessionH = NULL; } break; default: break; } targetP = targetP->next; } #endif #ifdef LWM2M_SERVER_MODE lwm2m_client_t * clientP; // monitor clients lifetime clientP = contextP->clientList; while (clientP != NULL) { lwm2m_client_t * nextP = clientP->next; if (clientP->endOfLife <= currentTime) { contextP->clientList = (lwm2m_client_t *)LWM2M_LIST_RM(contextP->clientList, clientP->internalID, NULL); if (contextP->monitorCallback != NULL) { contextP->monitorCallback(clientP->internalID, NULL, COAP_202_DELETED, LWM2M_CONTENT_TEXT, NULL, 0, contextP->monitorUserData); } registration_freeClient(clientP); } else { time_t interval; interval = clientP->endOfLife - currentTime; if (*timeoutP > interval) { *timeoutP = interval; } } clientP = nextP; } #endif }