void registration_deregister(lwm2m_context_t * contextP, lwm2m_server_t * serverP) { coap_packet_t message[1]; uint8_t pktBuffer[COAP_MAX_PACKET_SIZE+1]; size_t pktBufferLen = 0; if (serverP->status == STATE_UNKNOWN || serverP->status == STATE_REG_PENDING || serverP->status == STATE_DEREG_PENDING) { return; } lwm2m_transaction_t * transaction; transaction = transaction_new(COAP_DELETE, NULL, contextP->nextMID++, 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_REG_PENDING; serverP->mid = transaction->mID; } }
int lwm2m_bootstrap_delete(lwm2m_context_t * contextP, void * sessionH, lwm2m_uri_t * uriP) { lwm2m_transaction_t * transaction; bs_data_t * dataP; transaction = transaction_new(COAP_TYPE_CON, COAP_DELETE, NULL, uriP, contextP->nextMID++, 4, NULL, ENDPOINT_UNKNOWN, sessionH); if (transaction == NULL) return INTERNAL_SERVER_ERROR_5_00; dataP = (bs_data_t *)lwm2m_malloc(sizeof(bs_data_t)); if (dataP == NULL) { transaction_free(transaction); return COAP_500_INTERNAL_SERVER_ERROR; } if (uriP == NULL) { dataP->isUri = false; } else { dataP->isUri = true; memcpy(&dataP->uri, uriP, sizeof(lwm2m_uri_t)); } dataP->callback = contextP->bootstrapCallback; dataP->userData = contextP->bootstrapUserData; transaction->callback = bs_result_callback; transaction->userData = (void *)dataP; contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction); return transaction_send(contextP, transaction); }
int lwm2m_bootstrap_finish(lwm2m_context_t * contextP, void * sessionH) { lwm2m_transaction_t * transaction; bs_data_t * dataP; LOG("Entering"); transaction = transaction_new(sessionH, COAP_POST, NULL, NULL, contextP->nextMID++, 4, NULL); if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR; coap_set_header_uri_path(transaction->message, "/"URI_BOOTSTRAP_SEGMENT); dataP = (bs_data_t *)lwm2m_malloc(sizeof(bs_data_t)); if (dataP == NULL) { transaction_free(transaction); return COAP_500_INTERNAL_SERVER_ERROR; } dataP->isUri = false; dataP->callback = contextP->bootstrapCallback; dataP->userData = contextP->bootstrapUserData; transaction->callback = prv_resultCallback; transaction->userData = (void *)dataP; contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction); return transaction_send(contextP, transaction); }
void registration_deregister(lwm2m_context_t * contextP, lwm2m_server_t * serverP) { if (serverP->status == STATE_DEREGISTERED || serverP->status == STATE_REG_PENDING || serverP->status == STATE_DEREG_PENDING || serverP->status == STATE_REG_FAILED || serverP->location == NULL) { return; } lwm2m_transaction_t * transaction; 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_bootstrap_delete(lwm2m_context_t * contextP, void * sessionH, lwm2m_uri_t * uriP) { lwm2m_transaction_t * transaction; bs_data_t * dataP; LOG_URI(uriP); transaction = transaction_new(sessionH, COAP_DELETE, NULL, uriP, contextP->nextMID++, 4, NULL); if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR; dataP = (bs_data_t *)lwm2m_malloc(sizeof(bs_data_t)); if (dataP == NULL) { transaction_free(transaction); return COAP_500_INTERNAL_SERVER_ERROR; } if (uriP == NULL) { LWM2M_URI_RESET(&dataP->uri); } else { memcpy(&dataP->uri, uriP, sizeof(lwm2m_uri_t)); } dataP->callback = contextP->bootstrapCallback; dataP->userData = contextP->bootstrapUserData; transaction->callback = prv_resultCallback; transaction->userData = (void *)dataP; contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction); return transaction_send(contextP, transaction); }
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; }
// start a device initiated bootstrap static void prv_requestBootstrap(lwm2m_context_t * context, lwm2m_server_t * bootstrapServer) { char query[PRV_QUERY_BUFFER_LENGTH]; int query_length = 0; int res; LOG("Entering"); query_length = utils_stringCopy(query, PRV_QUERY_BUFFER_LENGTH, QUERY_STARTER QUERY_NAME); if (query_length < 0) { bootstrapServer->status = STATE_BS_FAILING; return; } res = utils_stringCopy(query + query_length, PRV_QUERY_BUFFER_LENGTH - query_length, context->endpointName); if (res < 0) { bootstrapServer->status = STATE_BS_FAILING; return; } query_length += res; if (bootstrapServer->sessionH == NULL) { bootstrapServer->sessionH = lwm2m_connect_server(bootstrapServer->secObjInstID, context->userData); } if (bootstrapServer->sessionH != NULL) { lwm2m_transaction_t * transaction = NULL; LOG("Bootstrap server connection opened"); transaction = transaction_new(bootstrapServer->sessionH, COAP_POST, NULL, NULL, context->nextMID++, 4, NULL); if (transaction == NULL) { bootstrapServer->status = STATE_BS_FAILING; return; } coap_set_header_uri_path(transaction->message, "/"URI_BOOTSTRAP_SEGMENT); coap_set_header_uri_query(transaction->message, query); transaction->callback = prv_handleBootstrapReply; transaction->userData = (void *)bootstrapServer; context->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(context->transactionList, transaction); if (transaction_send(context, transaction) == 0) { LOG("CI bootstrap requested to BS server"); bootstrapServer->status = STATE_BS_INITIATED; } } else { LOG("Connecting bootstrap server failed"); bootstrapServer->status = STATE_BS_FAILED; } }
// start a device initiated bootstrap static void bootstrap_initiating_request(lwm2m_context_t * context, lwm2m_server_t * bootstrapServer) { char query[PRV_QUERY_BUFFER_LENGTH]; int query_length = 0; int res; query_length = utils_stringCopy(query, PRV_QUERY_BUFFER_LENGTH, "?ep="); if (query_length < 0) { bootstrapServer->status = STATE_BS_FAILED; return; } res = utils_stringCopy(query + query_length, PRV_QUERY_BUFFER_LENGTH - query_length, context->endpointName); if (res < 0) { bootstrapServer->status = STATE_BS_FAILED; return; } query_length += res; if (bootstrapServer->sessionH == NULL) { bootstrapServer->sessionH = context->connectCallback(bootstrapServer->secObjInstID, context->userData); } if (bootstrapServer->sessionH != NULL) { lwm2m_transaction_t * transaction = NULL; LOG("[BOOTSTRAP] Bootstrap session starting...\r\n"); transaction = transaction_new(COAP_TYPE_CON, COAP_POST, NULL, NULL, context->nextMID++, 4, NULL, ENDPOINT_SERVER, (void *)bootstrapServer); if (transaction == NULL) { bootstrapServer->status = STATE_BS_FAILED; return; } coap_set_header_uri_path(transaction->message, "/"URI_BOOTSTRAP_SEGMENT); coap_set_header_uri_query(transaction->message, query); transaction->callback = prv_handleBootstrapReply; transaction->userData = (void *)bootstrapServer; context->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(context->transactionList, transaction); if (transaction_send(context, transaction) == 0) { LOG("[BOOTSTRAP] CI bootstrap requested to BS server\r\n"); bootstrapServer->status = STATE_BS_INITIATED; } } else { LOG("No bootstrap session handler found\r\n"); bootstrapServer->status = STATE_BS_FAILED; } }
static tcp_client* tcp_client_new() { tcp_client* c; c = malloc(sizeof(tcp_client)); if (c == NULL) return NULL; memset(c, 0, sizeof(tcp_client)); c->id = tcp_client_next_id(); c->t = transaction_new(); evtimer_set(&c->timeout_ev, on_commit_timeout, c); return c; }
// send the registration for a single server static uint8_t prv_register(lwm2m_context_t * contextP, lwm2m_server_t * server) { char query[200]; int query_length; uint8_t payload[512]; int payload_length; lwm2m_transaction_t * transaction; payload_length = object_getRegisterPayload(contextP, payload, sizeof(payload)); if (payload_length == 0) return COAP_500_INTERNAL_SERVER_ERROR; query_length = prv_getRegistrationQuery(contextP, server, query, sizeof(query)); if (query_length == 0) return COAP_500_INTERNAL_SERVER_ERROR; #if !defined(COAP_TCP) if (0 != server->lifetime) { int res; res = utils_stringCopy(query + query_length, PRV_QUERY_BUFFER_LENGTH - query_length, QUERY_DELIMITER QUERY_LIFETIME); if (res < 0) return COAP_500_INTERNAL_SERVER_ERROR; query_length += res; res = utils_intCopy(query + query_length, PRV_QUERY_BUFFER_LENGTH - query_length, server->lifetime); if (res < 0) return COAP_500_INTERNAL_SERVER_ERROR; query_length += res; } #endif if (server->sessionH == NULL) { server->sessionH = lwm2m_connect_server(server->secObjInstID, contextP->userData); } if (NULL == server->sessionH) return COAP_503_SERVICE_UNAVAILABLE; transaction = transaction_new(COAP_TYPE_CON, COAP_POST, NULL, NULL, contextP->nextMID++, 4, NULL, ENDPOINT_SERVER, (void *)server); if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR; coap_set_header_uri_path(transaction->message, "/"URI_REGISTRATION_SEGMENT); coap_set_header_uri_query(transaction->message, query); coap_set_header_content_type(transaction->message, LWM2M_CONTENT_LINK); coap_set_payload(transaction->message, payload, payload_length); transaction->callback = prv_handleRegistrationReply; transaction->userData = (void *) server; contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction); if (transaction_send(contextP, transaction) != 0) return COAP_500_INTERNAL_SERVER_ERROR; server->status = STATE_REG_PENDING; return COAP_NO_ERROR; }
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); }
// send the registration for a single server static void prv_register(lwm2m_context_t * contextP, lwm2m_server_t * server) { char query[200]; int query_length; uint8_t payload[512]; int payload_length; lwm2m_transaction_t * transaction; payload_length = prv_getRegisterPayload(contextP, payload, sizeof(payload)); if (payload_length == 0) return; query_length = prv_getRegistrationQuery(contextP, server, query, sizeof(query)); if (query_length == 0) return; if (0 != server->lifetime) { if (snprintf(query + query_length, PRV_QUERY_BUFFER_LENGTH - query_length, QUERY_DELIMITER QUERY_LIFETIME "%d", (int)server->lifetime) <= 0) { return; } } if (server->sessionH == NULL) { server->sessionH = contextP->connectCallback(server->secObjInstID, contextP->userData); } if (NULL != server->sessionH) { transaction = transaction_new(COAP_TYPE_CON, COAP_POST, NULL, NULL, contextP->nextMID++, 4, NULL, ENDPOINT_SERVER, (void *)server); if (transaction == NULL) return; coap_set_header_uri_path(transaction->message, "/"URI_REGISTRATION_SEGMENT); coap_set_header_uri_query(transaction->message, query); coap_set_payload(transaction->message, payload, payload_length); transaction->callback = prv_handleRegistrationReply; transaction->userData = (void *) server; contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction); if (transaction_send(contextP, transaction) == 0) { server->status = STATE_REG_PENDING; } } }
// start a device initiated bootstrap int bootstrap_initiating_request(lwm2m_context_t * context) { char query[PRV_QUERY_BUFFER_LENGTH]; int query_length = 0; lwm2m_transaction_t * transaction = NULL; query_length = snprintf(query, sizeof(query), "?ep=%s", context->endpointName); if (query_length <= 1) { return INTERNAL_SERVER_ERROR_5_00; } // find the first bootstrap server lwm2m_server_t * bootstrapServer = context->bootstrapServerList; while (bootstrapServer != NULL) { if (bootstrapServer->sessionH == NULL) { bootstrapServer->sessionH = context->connectCallback(bootstrapServer->secObjInstID, context->userData); } if (bootstrapServer->sessionH != NULL) { LOG("[BOOTSTRAP] Bootstrap session starting...\r\n"); transaction = transaction_new(COAP_TYPE_CON, COAP_POST, NULL, NULL, context->nextMID++, 4, NULL, ENDPOINT_SERVER, (void *)bootstrapServer); if (transaction == NULL) { return INTERNAL_SERVER_ERROR_5_00; } coap_set_header_uri_path(transaction->message, "/"URI_BOOTSTRAP_SEGMENT); coap_set_header_uri_query(transaction->message, query); transaction->callback = prv_handleBootstrapReply; transaction->userData = (void *)context; context->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(context->transactionList, transaction); if (transaction_send(context, transaction) == 0) { LOG("[BOOTSTRAP] DI bootstrap requested to BS server\r\n"); context->bsState = BOOTSTRAP_INITIATED; reset_bootstrap_timer(context); } } else { LOG("No bootstrap session handler found\r\n"); } bootstrapServer = bootstrapServer->next; } return NO_ERROR; }
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); }
int lwm2m_register(lwm2m_context_t * contextP) { char * query; char payload[512]; int payload_length; lwm2m_server_t * targetP; payload_length = prv_getRegisterPayload(contextP, payload, sizeof(payload)); if (payload_length == 0) return INTERNAL_SERVER_ERROR_5_00; query = (char*)lwm2m_malloc(QUERY_LENGTH + strlen(contextP->endpointName) + 1); if (query == NULL) return INTERNAL_SERVER_ERROR_5_00; strcpy(query, QUERY_TEMPLATE); strcpy(query + QUERY_LENGTH, contextP->endpointName); targetP = contextP->serverList; while (targetP != NULL) { lwm2m_transaction_t * transaction; transaction = transaction_new(COAP_POST, NULL, contextP->nextMID++, ENDPOINT_SERVER, (void *)targetP); if (transaction == NULL) return INTERNAL_SERVER_ERROR_5_00; coap_set_header_uri_path(transaction->message, "/"URI_REGISTRATION_SEGMENT); coap_set_header_uri_query(transaction->message, query); coap_set_payload(transaction->message, payload, payload_length); transaction->callback = prv_handleRegistrationReply; transaction->userData = (void *) contextP; contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction); if (transaction_send(contextP, transaction) == 0) { targetP->status = STATE_REG_PENDING; targetP->mid = transaction->mID; } targetP = targetP->next; } lwm2m_free(query); return 0; }
int lwm2m_bootstrap_write(lwm2m_context_t * contextP, void * sessionH, lwm2m_uri_t * uriP, lwm2m_media_type_t format, uint8_t * buffer, size_t length) { lwm2m_transaction_t * transaction; bs_data_t * dataP; LOG_URI(uriP); if (uriP == NULL || buffer == NULL || length == 0) { return COAP_400_BAD_REQUEST; } transaction = transaction_new(sessionH, COAP_PUT, NULL, uriP, contextP->nextMID++, 4, NULL); if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR; coap_set_header_content_type(transaction->message, format); coap_set_payload(transaction->message, buffer, length); dataP = (bs_data_t *)lwm2m_malloc(sizeof(bs_data_t)); if (dataP == NULL) { transaction_free(transaction); return COAP_500_INTERNAL_SERVER_ERROR; } dataP->isUri = true; memcpy(&dataP->uri, uriP, sizeof(lwm2m_uri_t)); dataP->callback = contextP->bootstrapCallback; dataP->userData = contextP->bootstrapUserData; 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 int prv_update_registration(lwm2m_context_t * contextP, lwm2m_server_t * server) { lwm2m_transaction_t * transaction; transaction = transaction_new(COAP_PUT, NULL, contextP->nextMID++, ENDPOINT_SERVER, (void *)server); if (transaction == NULL) return INTERNAL_SERVER_ERROR_5_00; coap_set_header_uri_path(transaction->message, server->location); transaction->callback = prv_handleRegistrationUpdateReply; transaction->userData = (void *) server; contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction); if (transaction_send(contextP, transaction) == 0) { server->status = STATE_REG_UPDATE_PENDING; server->mid = transaction->mID; } return 0; }
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); }
int lwm2m_bootstrap_write(lwm2m_context_t * contextP, void * sessionH, lwm2m_uri_t * uriP, uint8_t * buffer, size_t length) { lwm2m_transaction_t * transaction; bs_data_t * dataP; if (uriP == NULL || buffer == NULL || length == 0) { return COAP_400_BAD_REQUEST; } transaction = transaction_new(COAP_TYPE_CON, COAP_PUT, NULL, uriP, contextP->nextMID++, 4, NULL, ENDPOINT_UNKNOWN, sessionH); if (transaction == NULL) return INTERNAL_SERVER_ERROR_5_00; coap_set_payload(transaction->message, buffer, length); dataP = (bs_data_t *)lwm2m_malloc(sizeof(bs_data_t)); if (dataP == NULL) { transaction_free(transaction); return COAP_500_INTERNAL_SERVER_ERROR; } dataP->isUri = true; memcpy(&dataP->uri, uriP, sizeof(lwm2m_uri_t)); dataP->callback = contextP->bootstrapCallback; dataP->userData = contextP->bootstrapUserData; transaction->callback = bs_result_callback; transaction->userData = (void *)dataP; contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction); return transaction_send(contextP, transaction); }
static int prv_updateRegistration(lwm2m_context_t * contextP, lwm2m_server_t * server, bool withObjects) { lwm2m_transaction_t * transaction; uint8_t payload[512]; int payload_length; transaction = transaction_new(COAP_TYPE_CON, COAP_POST, NULL, NULL, contextP->nextMID++, 4, NULL, ENDPOINT_SERVER, (void *)server); if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR; coap_set_header_uri_path(transaction->message, server->location); if (withObjects == true) { payload_length = object_getRegisterPayload(contextP, payload, sizeof(payload)); if (payload_length == 0) { transaction_free(transaction); return COAP_500_INTERNAL_SERVER_ERROR; } coap_set_payload(transaction->message, payload, payload_length); } transaction->callback = prv_handleRegistrationUpdateReply; transaction->userData = (void *) server; contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction); if (transaction_send(contextP, transaction) == 0) { server->status = STATE_REG_UPDATE_PENDING; } return COAP_NO_ERROR; }
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); }
struct transaction* transaction_from_bson(bson_t const* doc) { char key[9]; bson_iter_t iter; bson_iter_t subiter; struct transaction* tx = transaction_new(); if(!bson_iter_init_find(&iter, doc, "version") || !BSON_ITER_HOLDS_INT32(&iter)) goto error; transaction_set_version(tx, bson_iter_int32(&iter)); // Read Inputs if(!bson_iter_init_find(&iter, doc, "inputs") || !BSON_ITER_HOLDS_ARRAY(&iter)) goto error; uint32_t inputs_doc_length; uint8_t const* inputs_doc_data; bson_iter_array(&iter, &inputs_doc_length, &inputs_doc_data); bson_t inputs_doc; bson_init_static(&inputs_doc, inputs_doc_data, inputs_doc_length); size_t index = 0; for(;;) { bson_snprintf(key, sizeof(key), "%u", (unsigned int)index); key[sizeof(key) - 1] = '\0'; // If the array key isn't found, then we reached the end of the array if(!bson_iter_init_find(&subiter, &inputs_doc, key)) break; // If it's not a document, then there's an error if(!BSON_ITER_HOLDS_DOCUMENT(&subiter)) goto error; struct transaction_input* input = transaction_input_new(); struct transaction_output_reference* output_reference = transaction_input_output_reference(input); // Load the input document bson_t element_doc; uint32_t element_doc_length; uint8_t const* element_doc_data; bson_iter_document(&subiter, &element_doc_length, &element_doc_data); bson_init_static(&element_doc, element_doc_data, element_doc_length); bson_iter_t elementiter; // Output reference if(!bson_iter_init_find(&elementiter, &element_doc, "output_reference") || !BSON_ITER_HOLDS_DOCUMENT(&elementiter)) goto error; bson_t output_reference_doc; uint32_t output_reference_doc_length; uint8_t const* output_reference_doc_data; bson_iter_document(&elementiter, &output_reference_doc_length, &output_reference_doc_data); bson_init_static(&output_reference_doc, output_reference_doc_data, output_reference_doc_length); bson_iter_t output_reference_iter; uint8_t const* hash; uint32_t hash_size; if(!bson_iter_init_find(&output_reference_iter, &output_reference_doc, "hash") || !BSON_ITER_HOLDS_BINARY(&output_reference_iter)) goto error; bson_iter_binary(&output_reference_iter, BSON_SUBTYPE_BINARY, &hash_size, &hash); assert(hash_size == 32); transaction_output_reference_set_hash(output_reference, (unsigned char const*)hash); if(!bson_iter_init_find(&output_reference_iter, &output_reference_doc, "index") || !BSON_ITER_HOLDS_INT32(&output_reference_iter)) goto error; transaction_output_reference_set_index(output_reference, bson_iter_int32(&output_reference_iter)); // Script if(!bson_iter_init_find(&elementiter, &element_doc, "script") || !BSON_ITER_HOLDS_BINARY(&elementiter)) goto error; uint32_t script_size; uint8_t const* script_data; bson_iter_binary(&elementiter, BSON_SUBTYPE_BINARY, &script_size, &script_data); struct script* script; size_t script_size_result; script_size_result = unserialize_script((unsigned char const*)script_data, script_size, &script, script_size); assert(script_size_result == script_size); transaction_input_set_script(input, script); // Sequence if(!bson_iter_init_find(&elementiter, &element_doc, "sequence") || !BSON_ITER_HOLDS_INT32(&elementiter)) goto error; transaction_input_set_sequence(input, bson_iter_int32(&elementiter)); transaction_add_input(tx, input); index += 1; } // Read Outputs if(!bson_iter_init_find(&iter, doc, "outputs") || !BSON_ITER_HOLDS_ARRAY(&iter)) goto error; uint32_t outputs_doc_length; uint8_t const* outputs_doc_data; bson_iter_array(&iter, &outputs_doc_length, &outputs_doc_data); bson_t outputs_doc; bson_init_static(&outputs_doc, outputs_doc_data, outputs_doc_length); index = 0; for(;;) { bson_snprintf(key, sizeof(key), "%u", (unsigned int)index); key[sizeof(key) - 1] = '\0'; // If the array key isn't found, then we reached the end of the array if(!bson_iter_init_find(&subiter, &outputs_doc, key)) break; // If it's not a document, then there's an error if(!BSON_ITER_HOLDS_DOCUMENT(&subiter)) goto error; struct transaction_output* output = transaction_output_new(); // Load the output document bson_t element_doc; uint32_t element_doc_length; uint8_t const* element_doc_data; bson_iter_document(&subiter, &element_doc_length, &element_doc_data); bson_init_static(&element_doc, element_doc_data, element_doc_length); bson_iter_t elementiter; // Value if(!bson_iter_init_find(&elementiter, &element_doc, "value") || !BSON_ITER_HOLDS_INT64(&elementiter)) goto error; transaction_output_set_value(output, bson_iter_int64(&elementiter)); // Script if(!bson_iter_init_find(&elementiter, &element_doc, "script") || !BSON_ITER_HOLDS_BINARY(&elementiter)) goto error; uint32_t script_size; uint8_t const* script_data; bson_iter_binary(&elementiter, BSON_SUBTYPE_BINARY, &script_size, &script_data); struct script* script; size_t script_size_result; script_size_result = unserialize_script((unsigned char const*)script_data, script_size, &script, script_size); assert(script_size_result == script_size); transaction_output_set_script(output, script); transaction_add_output(tx, output); index += 1; } if(!bson_iter_init_find(&iter, doc, "lock_time") || !BSON_ITER_HOLDS_INT32(&iter)) goto error; transaction_set_lock_time(tx, bson_iter_int32(&iter)); return tx; error: return NULL; }
int lwm2m_dm_write_attributes(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_attributes_t * attrP, lwm2m_result_callback_t callback, void * userData) { #define _PRV_BUFFER_SIZE 32 lwm2m_client_t * clientP; lwm2m_transaction_t * transaction; coap_packet_t * coap_pkt; uint8_t buffer[_PRV_BUFFER_SIZE]; size_t length; LOG_ARG("clientID: %d", clientID); LOG_URI(uriP); if (attrP == NULL) return COAP_400_BAD_REQUEST; if (0 != (attrP->toSet & attrP->toClear)) return COAP_400_BAD_REQUEST; if (0 != (attrP->toSet & ATTR_FLAG_NUMERIC) && !LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_400_BAD_REQUEST; if (ATTR_FLAG_NUMERIC == (attrP->toSet & ATTR_FLAG_NUMERIC) && (attrP->lessThan + 2 * attrP->step >= attrP->greaterThan)) 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; transaction = transaction_new(clientP->sessionH, COAP_PUT, clientP->altPath, uriP, contextP->nextMID++, 4, NULL); if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR; if (callback != NULL) { dm_data_t * dataP; 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; } coap_pkt = (coap_packet_t *)transaction->message; free_multi_option(coap_pkt->uri_query); if (attrP->toSet & LWM2M_ATTR_FLAG_MIN_PERIOD) { memcpy(buffer, ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN); length = utils_intToText(attrP->minPeriod, buffer + ATTR_MIN_PERIOD_LEN, _PRV_BUFFER_SIZE - ATTR_MIN_PERIOD_LEN); if (length == 0) { transaction_free(transaction); return COAP_500_INTERNAL_SERVER_ERROR; } coap_add_multi_option(&(coap_pkt->uri_query), buffer, ATTR_MIN_PERIOD_LEN + length, 0); SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY); } if (attrP->toSet & LWM2M_ATTR_FLAG_MAX_PERIOD) { memcpy(buffer, ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN); length = utils_intToText(attrP->maxPeriod, buffer + ATTR_MAX_PERIOD_LEN, _PRV_BUFFER_SIZE - ATTR_MAX_PERIOD_LEN); if (length == 0) { transaction_free(transaction); return COAP_500_INTERNAL_SERVER_ERROR; } coap_add_multi_option(&(coap_pkt->uri_query), buffer, ATTR_MAX_PERIOD_LEN + length, 0); SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY); } if (attrP->toSet & LWM2M_ATTR_FLAG_GREATER_THAN) { memcpy(buffer, ATTR_GREATER_THAN_STR, ATTR_GREATER_THAN_LEN); length = utils_floatToText(attrP->greaterThan, buffer + ATTR_GREATER_THAN_LEN, _PRV_BUFFER_SIZE - ATTR_GREATER_THAN_LEN); if (length == 0) { transaction_free(transaction); return COAP_500_INTERNAL_SERVER_ERROR; } coap_add_multi_option(&(coap_pkt->uri_query), buffer, ATTR_GREATER_THAN_LEN + length, 0); SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY); } if (attrP->toSet & LWM2M_ATTR_FLAG_LESS_THAN) { memcpy(buffer, ATTR_LESS_THAN_STR, ATTR_LESS_THAN_LEN); length = utils_floatToText(attrP->lessThan, buffer + ATTR_LESS_THAN_LEN, _PRV_BUFFER_SIZE - ATTR_LESS_THAN_LEN); if (length == 0) { transaction_free(transaction); return COAP_500_INTERNAL_SERVER_ERROR; } coap_add_multi_option(&(coap_pkt->uri_query), buffer, ATTR_LESS_THAN_LEN + length, 0); SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY); } if (attrP->toSet & LWM2M_ATTR_FLAG_STEP) { memcpy(buffer, ATTR_STEP_STR, ATTR_STEP_LEN); length = utils_floatToText(attrP->step, buffer + ATTR_STEP_LEN, _PRV_BUFFER_SIZE - ATTR_STEP_LEN); if (length == 0) { transaction_free(transaction); return COAP_500_INTERNAL_SERVER_ERROR; } coap_add_multi_option(&(coap_pkt->uri_query), buffer, ATTR_STEP_LEN + length, 0); SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY); } if (attrP->toClear & LWM2M_ATTR_FLAG_MIN_PERIOD) { coap_add_multi_option(&(coap_pkt->uri_query), (uint8_t*)ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN -1, 0); SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY); } if (attrP->toClear & LWM2M_ATTR_FLAG_MAX_PERIOD) { coap_add_multi_option(&(coap_pkt->uri_query), (uint8_t*)ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN - 1, 0); SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY); } if (attrP->toClear & LWM2M_ATTR_FLAG_GREATER_THAN) { coap_add_multi_option(&(coap_pkt->uri_query), (uint8_t*)ATTR_GREATER_THAN_STR, ATTR_GREATER_THAN_LEN - 1, 0); SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY); } if (attrP->toClear & LWM2M_ATTR_FLAG_LESS_THAN) { coap_add_multi_option(&(coap_pkt->uri_query), (uint8_t*)ATTR_LESS_THAN_STR, ATTR_LESS_THAN_LEN - 1, 0); SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY); } if (attrP->toClear & LWM2M_ATTR_FLAG_STEP) { coap_add_multi_option(&(coap_pkt->uri_query), (uint8_t*)ATTR_STEP_STR, ATTR_STEP_LEN - 1, 0); SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY); } contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction); return transaction_send(contextP, transaction); }