/*---------------------------------------------------------------------------*/ PROCESS_THREAD(rd_client_process, ev, data) { static struct etimer et; static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */ static char query_buffer[200]; static char rd_client_name[64]; PROCESS_BEGIN(); PROCESS_PAUSE(); PRINTF("RD client started\n"); sprintf(rd_client_name, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", uip_lladdr.addr[0], uip_lladdr.addr[1], uip_lladdr.addr[2], uip_lladdr.addr[3], uip_lladdr.addr[4], uip_lladdr.addr[5], uip_lladdr.addr[6], uip_lladdr.addr[7]); while(1) { new_address = 0; while(!registered) { while(uip_is_addr_unspecified(&rd_server_ipaddr)) { status = RD_CLIENT_UNCONFIGURED; PROCESS_YIELD(); } status = RD_CLIENT_REGISTERING; etimer_set(&et, CLOCK_SECOND); PROCESS_YIELD_UNTIL(etimer_expired(&et)); PRINTF("Registering to "); PRINT6ADDR(&rd_server_ipaddr); PRINTF(" %d with %s\n", rd_server_port, resources_list); coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); coap_set_header_uri_path(request, "rd"); sprintf(query_buffer, "ep=%s&b=U<=%d", rd_client_name, RD_CLIENT_LIFETIME); coap_set_header_uri_query(request, query_buffer); coap_set_payload(request, (uint8_t *) resources_list, resources_list_size); COAP_BLOCKING_REQUEST_BLOCK_RESPONSE(coap_default_context, &rd_server_ipaddr, UIP_HTONS(rd_server_port), request, client_registration_request_handler, client_registration_response_handler); } status = RD_CLIENT_REGISTERED; etimer_set(&et, RD_CLIENT_LIFETIME * CLOCK_SECOND / 10 * 9); PROCESS_YIELD_UNTIL(etimer_expired(&et) || new_address); registered = 0; if(!new_address) { PRINTF("Update endpoint %s\n", registration_name); coap_init_message(request, COAP_TYPE_CON, COAP_PUT, 0); coap_set_header_uri_path(request, registration_name); sprintf(query_buffer, "b=U<=%d", RD_CLIENT_LIFETIME); coap_set_header_uri_query(request, query_buffer); COAP_BLOCKING_REQUEST(coap_default_context, &rd_server_ipaddr, UIP_HTONS(rd_server_port), request, client_update_response_handler); } } PROCESS_END(); }
void coap_createCoapRequest(void * context, coap_method_t method, const char * uri, ContentType contentType, const char * payload, int payloadLen, TransactionCallback callback) { coap_packet_t request; uip_ipaddr_t * remote_ipaddr = coap_getIpFromURI(uri); int remote_port = coap_getPortFromURI(uri); coap_transaction_t *transaction; char path[128] = {0}; char query[128] = {0}; coap_getPathQueryFromURI(uri, path, query); Lwm2m_Debug("Coap request: %s\n", uri); Lwm2m_Debug("Coap IPv6 request address: " PRINT6ADDR(remote_ipaddr)); Lwm2m_Debug("Coap request port: %d\n", remote_port); Lwm2m_Debug("Coap request path: %s\n", path); Lwm2m_Debug("Coap request query: %s\n", query); coap_init_message(&request, COAP_TYPE_CON, method, coap_get_mid()); coap_set_header_uri_path(&request, path); coap_set_header_uri_query(&request, query); if (contentType != ContentType_None) { coap_set_header_content_format(&request, contentType); coap_set_payload(&request, payload, payloadLen); } if (CurrentTransaction[CurrentTransactionIndex].TransactionUsed && CurrentTransaction[CurrentTransactionIndex].TransactionPtr) { Lwm2m_Warning("Canceled previous transaction [%d]: %p\n", CurrentTransactionIndex, CurrentTransaction[CurrentTransactionIndex].TransactionPtr); coap_clear_transaction(CurrentTransaction[CurrentTransactionIndex].TransactionPtr); } if ((transaction = coap_new_transaction(request.mid, remote_ipaddr, uip_htons(remote_port)))) { transaction->callback = coap_CoapRequestCallback; CurrentTransaction[CurrentTransactionIndex].Callback = callback; CurrentTransaction[CurrentTransactionIndex].Context = context; CurrentTransaction[CurrentTransactionIndex].TransactionUsed = true; CurrentTransaction[CurrentTransactionIndex].TransactionPtr = transaction; memcpy(&CurrentTransaction[CurrentTransactionIndex].Address.Addr, remote_ipaddr, sizeof(uip_ipaddr_t)); CurrentTransaction[CurrentTransactionIndex].Address.Port = uip_htons(remote_port); transaction->callback_data = &CurrentTransaction[CurrentTransactionIndex]; transaction->packet_len = coap_serialize_message(&request, transaction->packet); Lwm2m_Debug("Sending transaction [%d]: %p\n", CurrentTransactionIndex, CurrentTransaction[CurrentTransactionIndex].TransactionPtr); coap_send_transaction(transaction); CurrentTransactionIndex++; if(CurrentTransactionIndex >= MAX_COAP_TRANSACTIONS) { CurrentTransactionIndex = 0; } } }
// 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; } }
// 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; }
// 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; }
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; }
void coap_createCoapRequest(coap_method_t method, const char * uri, ContentType contentType, ObserveState observeState, const char * payload, int payloadLen, TransactionCallback callback, void * context) { coap_packet_t request; char path[MAX_COAP_PATH] = { 0 }; char query[128] = { 0 }; coap_transaction_t *transaction; NetworkAddress * remoteAddress = NetworkAddress_New(uri, strlen(uri)); coap_getPathQueryFromURI(uri, path, query); Lwm2m_Info("Coap request: %s\n", uri); //Lwm2m_Debug("Coap request path: %s\n", path); //Lwm2m_Debug("Coap request query: %s\n", query); coap_init_message(&request, COAP_TYPE_CON, method, coap_get_mid()); coap_set_header_uri_path(&request, path); if (strlen(query) > 0) coap_set_header_uri_query(&request, query); // TODO - REVIEW: Erbium must copy path/query from request - else mem out of scope if (contentType != ContentType_None) { if ((method == COAP_POST) || (method == COAP_PUT)) { coap_set_header_content_format(&request, contentType); coap_set_payload(&request, payload, payloadLen); } else { coap_set_header_accept(&request, contentType); } } if (method == COAP_GET) { if (observeState == ObserveState_Establish) { coap_set_header_observe(&request, 0); int token = addObserve(remoteAddress, path, callback, context); if (token != 0) coap_set_token(&request, (const uint8_t *) &token, sizeof(token)); } else if (observeState == ObserveState_Cancel) { coap_set_header_observe(&request, 1); int token = removeObserve(remoteAddress, path); if (token != 0) coap_set_token(&request, (const uint8_t *) &token, sizeof(token)); } } if (CurrentTransaction[CurrentTransactionIndex].TransactionUsed && CurrentTransaction[CurrentTransactionIndex].TransactionPtr) { Lwm2m_Warning("Canceled previous transaction [%d]: %p\n", CurrentTransactionIndex, CurrentTransaction[CurrentTransactionIndex].TransactionPtr); coap_clear_transaction(&CurrentTransaction[CurrentTransactionIndex].TransactionPtr); } //if ((transaction = coap_new_transaction(request.mid, remote_ipaddr, uip_htons(remote_port)))) if ((transaction = coap_new_transaction(networkSocket, request.mid, remoteAddress))) { transaction->callback = coap_CoapRequestCallback; memcpy(CurrentTransaction[CurrentTransactionIndex].Path, path, MAX_COAP_PATH); CurrentTransaction[CurrentTransactionIndex].Callback = callback; CurrentTransaction[CurrentTransactionIndex].Context = context; CurrentTransaction[CurrentTransactionIndex].TransactionUsed = true; CurrentTransaction[CurrentTransactionIndex].TransactionPtr = transaction; NetworkAddress_SetAddressType(remoteAddress, &CurrentTransaction[CurrentTransactionIndex].Address); transaction->callback_data = &CurrentTransaction[CurrentTransactionIndex]; transaction->packet_len = coap_serialize_message(&request, transaction->packet); Lwm2m_Debug("Sending transaction [%d]: %p\n", CurrentTransactionIndex, CurrentTransaction[CurrentTransactionIndex].TransactionPtr); coap_send_transaction(transaction); CurrentTransactionIndex++; if (CurrentTransactionIndex >= MAX_COAP_TRANSACTIONS) { CurrentTransactionIndex = 0; } } }