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; } }
// 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; }
/** * vrrp_context() - dump vrrp info */ static void vrrp_context(struct vrrp *vrrp) { log_notice("===================="); log_notice("VRID %d", vrrp->vrid); log_notice("current_state %s", STR_STATE(vrrp->state)); log_notice("adv_int %d", vrrp->adv_int); if (vrrp->version == RFC5798) log_notice("master_adv_int %d", vrrp->master_adv_int); log_notice("preempt %s", STR_PREEMPT(vrrp->preempt)); log_notice("naddr %d", vrrp->naddr); log_notice("===================="); }
/* * 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; }
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; }
int lwm2m_step(lwm2m_context_t * contextP, time_t * timeoutP) { time_t tv_sec; int result; LOG_ARG("timeoutP: %" PRId64, *timeoutP); tv_sec = lwm2m_gettime(); if (tv_sec < 0) return COAP_500_INTERNAL_SERVER_ERROR; #ifdef LWM2M_CLIENT_MODE LOG_ARG("State: %s", STR_STATE(contextP->state)); // state can also be modified in bootstrap_handleCommand(). next_step: switch (contextP->state) { case STATE_INITIAL: if (0 != prv_refreshServerList(contextP)) return COAP_503_SERVICE_UNAVAILABLE; if (contextP->serverList != NULL) { contextP->state = STATE_REGISTER_REQUIRED; } else { // Bootstrapping contextP->state = STATE_BOOTSTRAP_REQUIRED; } goto next_step; break; case STATE_BOOTSTRAP_REQUIRED: #ifdef LWM2M_BOOTSTRAP if (contextP->bootstrapServerList != NULL) { bootstrap_start(contextP); contextP->state = STATE_BOOTSTRAPPING; bootstrap_step(contextP, tv_sec, timeoutP); } else #endif { return COAP_503_SERVICE_UNAVAILABLE; } break; #ifdef LWM2M_BOOTSTRAP case STATE_BOOTSTRAPPING: switch (bootstrap_getStatus(contextP)) { case STATE_BS_FINISHED: contextP->state = STATE_INITIAL; goto next_step; break; case STATE_BS_FAILED: return COAP_503_SERVICE_UNAVAILABLE; default: // keep on waiting bootstrap_step(contextP, tv_sec, timeoutP); break; } break; #endif case STATE_REGISTER_REQUIRED: result = registration_start(contextP); if (COAP_NO_ERROR != result) return result; contextP->state = STATE_REGISTERING; break; case STATE_REGISTERING: { switch (registration_getStatus(contextP)) { case STATE_REGISTERED: contextP->state = STATE_READY; break; case STATE_REG_FAILED: // TODO avoid infinite loop by checking the bootstrap info is different contextP->state = STATE_BOOTSTRAP_REQUIRED; goto next_step; break; case STATE_REG_PENDING: default: // keep on waiting break; } } break; case STATE_READY: if (registration_getStatus(contextP) == STATE_REG_FAILED) { // TODO avoid infinite loop by checking the bootstrap info is different contextP->state = STATE_BOOTSTRAP_REQUIRED; goto next_step; break; } break; default: // do nothing break; } observe_step(contextP, tv_sec, timeoutP); #endif registration_step(contextP, tv_sec, timeoutP); transaction_step(contextP, tv_sec, timeoutP); LOG_ARG("Final timeoutP: %" PRId64, *timeoutP); #ifdef LWM2M_CLIENT_MODE LOG_ARG("Final state: %s", STR_STATE(contextP->state)); #endif return 0; }
// 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; LOG_ARG("State: %s", STR_STATE(contextP->state)); 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"); 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; LOG("Entering"); // 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 }