static uint8_t prv_exec(uint16_t instanceId, uint16_t resourceId, uint8_t * buffer, int length, lwm2m_object_t * objectP) { if (NULL == lwm2m_list_find(objectP->instanceList, instanceId)) return COAP_404_NOT_FOUND; switch (resourceId) { case 1: return COAP_405_METHOD_NOT_ALLOWED; case 2: fprintf(stdout, "\r\n-----------------\r\n" "Execute on %hu/%d/%d\r\n" " Parameter (%d bytes):\r\n", objectP->objID, instanceId, resourceId, length); prv_output_buffer((uint8_t*)buffer, length); fprintf(stdout, "-----------------\r\n\r\n"); return COAP_204_CHANGED; case 3: return COAP_405_METHOD_NOT_ALLOWED; default: return COAP_404_NOT_FOUND; } }
static void prv_result_callback(uint16_t clientID, lwm2m_uri_t * uriP, int status, uint8_t * data, int dataLength, void * userData) { fprintf(stdout, "\r\nClient #%d %d", clientID, uriP->objectId); if (LWM2M_URI_IS_SET_INSTANCE(uriP)) fprintf(stdout, "/%d", uriP->instanceId); else if (LWM2M_URI_IS_SET_RESOURCE(uriP)) fprintf(stdout, "/"); if (LWM2M_URI_IS_SET_RESOURCE(uriP)) fprintf(stdout, "/%d", uriP->resourceId); fprintf(stdout, " returned status %d.%2d\r\n", (status&0xE0)>>5, status&0x1F); if (data != NULL) { fprintf(stdout, "%d bytes received:\r\n", dataLength); prv_output_buffer(stdout, data, dataLength); } fprintf(stdout, "\r\n> "); fflush(stdout); }
void decode(char * buffer, size_t buffer_len, int indent) { lwm2m_tlv_type_t type; uint16_t id; size_t dataIndex; size_t dataLen; int length = 0; int result; while (0 != (result = lwm2m_decodeTLV(buffer + length, buffer_len - length, &type, &id, &dataIndex, &dataLen))) { print_indent(indent); printf("type: "); switch (type) { case LWM2M_TYPE_OBJECT_INSTANCE: printf("LWM2M_TYPE_OBJECT_INSTANCE\r\n"); break; case LWM2M_TYPE_RESOURCE_INSTANCE: printf("LWM2M_TYPE_RESOURCE_INSTANCE\r\n"); break; case LWM2M_TYPE_MULTIPLE_RESOURCE: printf("LWM2M_TYPE_MULTIPLE_RESOURCE\r\n"); break; case LWM2M_TYPE_RESOURCE: printf("LWM2M_TYPE_RESOURCE\r\n"); break; default: printf("unknown (%d)\r\n", (int)type); break; } print_indent(indent); printf("id: %d\r\n", id); print_indent(indent); printf("data (%d bytes): ", dataLen); prv_output_buffer(buffer + length + dataIndex, dataLen); if (type == LWM2M_TYPE_OBJECT_INSTANCE || type == LWM2M_TYPE_MULTIPLE_RESOURCE) { decode(buffer + length + dataIndex, dataLen, indent+1); } else if (dataLen <= 8) { int64_t value; if (0 != lwm2m_opaqueToInt(buffer + length + dataIndex, dataLen, &value)) { print_indent(indent); printf(" as int: %ld\r\n", value); } } length += result; } }
void dump_tlv(int size, lwm2m_tlv_t * tlvP, int indent) { int i; for(i= 0 ; i < size ; i++) { print_indent(indent); printf("type: "); switch (tlvP[i].type) { case LWM2M_TYPE_OBJECT_INSTANCE: printf("LWM2M_TYPE_OBJECT_INSTANCE\r\n"); break; case LWM2M_TYPE_RESOURCE_INSTANCE: printf("LWM2M_TYPE_RESOURCE_INSTANCE\r\n"); break; case LWM2M_TYPE_MULTIPLE_RESOURCE: printf("LWM2M_TYPE_MULTIPLE_RESOURCE\r\n"); break; case LWM2M_TYPE_RESOURCE: printf("LWM2M_TYPE_RESOURCE\r\n"); break; default: printf("unknown (%d)\r\n", (int)tlvP[i].type); break; } print_indent(indent); printf("id: %d\r\n", tlvP[i].id); print_indent(indent); printf("data (%d bytes): ", tlvP[i].length); prv_output_buffer(tlvP[i].value, tlvP[i].length); if (tlvP[i].type == LWM2M_TYPE_OBJECT_INSTANCE || tlvP[i].type == LWM2M_TYPE_MULTIPLE_RESOURCE) { dump_tlv(tlvP[i].length, (lwm2m_tlv_t *)(tlvP[i].value), indent+1); } else if (tlvP[i].length <= 8) { int64_t value; if (0 != lwm2m_opaqueToInt(tlvP[i].value, tlvP[i].length, &value)) { print_indent(indent); printf(" as int: %ld\r\n", value); } } } }
static int prv_get_object_tlv(char ** bufferP, firmware_data_t* dataP) { int length = 0; int result; char temp_buffer[16]; int temp_length; *bufferP = (uint8_t *)malloc(PRV_TLV_BUFFER_SIZE); if (NULL == *bufferP) return 0; result = lwm2m_intToTLV(TLV_RESSOURCE, dataP->state, 3, *bufferP, PRV_TLV_BUFFER_SIZE); if (0 == result) goto error; length += result; result = lwm2m_boolToTLV(TLV_RESSOURCE, dataP->supported, 4, *bufferP + length, PRV_TLV_BUFFER_SIZE - length); if (0 == result) goto error; length += result; result = lwm2m_intToTLV(TLV_RESSOURCE, dataP->result, 5, *bufferP + length, PRV_TLV_BUFFER_SIZE - length); if (0 == result) goto error; length += result; fprintf(stderr, "TLV (%d bytes):\r\n", length); prv_output_buffer(*bufferP, length); return length; error: fprintf(stderr, "TLV generation failed:\r\n"); free(*bufferP); *bufferP = NULL; return 0; }
int main(int argc, char *argv[]) { lwm2m_tlv_t * tlvP; int size; int length; char * buffer; char buffer1[] = {0x03, 0x0A, 0xC1, 0x01, 0x14, 0x03, 0x0B, 0xC1, 0x01, 0x15, 0x03, 0x0C, 0xC1, 0x01, 0x16}; char buffer2[] = {0xC8, 0x00, 0x14, 0x4F, 0x70, 0x65, 0x6E, 0x20, 0x4D, 0x6F, 0x62, 0x69, 0x6C, 0x65, 0x20, 0x41, 0x6C, 0x6C, 0x69, 0x61, 0x6E, 0x63, 0x65, 0xC8, 0x01, 0x16, 0x4C, 0x69, 0x67, 0x68, 0x74, 0x77 , 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x4D, 0x32, 0x4D, 0x20, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74 , 0xC8, 0x02, 0x09, 0x33, 0x34, 0x35, 0x30, 0x30, 0x30, 0x31, 0x32, 0x33, 0xC3, 0x03, 0x31, 0x2E , 0x30, 0x86, 0x06, 0x41, 0x00, 0x01, 0x41, 0x01, 0x05, 0x88, 0x07, 0x08, 0x42, 0x00, 0x0E, 0xD8 , 0x42, 0x01, 0x13, 0x88, 0x87, 0x08, 0x41, 0x00, 0x7D, 0x42, 0x01, 0x03, 0x84, 0xC1, 0x09, 0x64 , 0xC1, 0x0A, 0x0F, 0x83, 0x0B, 0x41, 0x00, 0x00, 0xC4, 0x0D, 0x51, 0x82, 0x42, 0x8F, 0xC6, 0x0E, 0x2B, 0x30, 0x32, 0x3A, 0x30, 0x30, 0xC1, 0x0F, 0x55}; printf("Buffer 1:\n"); decode(buffer1, sizeof(buffer1), 0); printf("\n\nBuffer 1 using lwm2m_tlv_t:\n"); size = lwm2m_tlv_parse(buffer1, sizeof(buffer1), &tlvP); dump_tlv(size, tlvP, 0); length = lwm2m_tlv_serialize(size, tlvP, &buffer); if (length != sizeof(buffer1)) { printf("\n\nSerialize Buffer 1 failed: %d bytes instead of %d\n", length, sizeof(buffer1)); } else if (memcmp(buffer, buffer1, length) != 0) { printf("\n\nSerialize Buffer 1 failed:\n"); prv_output_buffer(buffer, length); printf("\ninstead of:\n"); prv_output_buffer(buffer1, length); } else { printf("\n\nSerialize Buffer 1 OK\n"); } lwm2m_tlv_free(size, tlvP); printf("\n\n============\n\nBuffer 2: \r\r\n"); decode(buffer2, sizeof(buffer2), 0); printf("\n\nBuffer 2 using lwm2m_tlv_t: \r\r\n"); size = lwm2m_tlv_parse(buffer2, sizeof(buffer2), &tlvP); dump_tlv(size, tlvP, 0); length = lwm2m_tlv_serialize(size, tlvP, &buffer); if (length != sizeof(buffer2)) { printf("\n\nSerialize Buffer 2 failed: %d bytes instead of %d\n", length, sizeof(buffer2)); } else if (memcmp(buffer, buffer2, length) != 0) { printf("\n\nSerialize Buffer 2 failed:\n"); prv_output_buffer(buffer, length); printf("\ninstead of:\n"); prv_output_buffer(buffer2, length); } else { printf("\n\nSerialize Buffer 2 OK\n\n"); } lwm2m_tlv_free(size, tlvP); }
int main(int argc, char *argv[]) { int socket; fd_set readfds; struct timeval tv; int result; lwm2m_context_t * lwm2mH = NULL; int i; command_desc_t commands[] = { {"list", "List registered clients.", NULL, prv_output_clients, NULL}, {"read", "Read from a client.", " read CLIENT# URI\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri to read such as /3, /3//2, /3/0/2, /1024/11, /1024//1\r\n" "Result will be displayed asynchronously.", prv_read_client, NULL}, {"write", "Write to a client.", " write CLIENT# URI DATA\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri to write to such as /3, /3//2, /3/0/2, /1024/11, /1024//1\r\n" " DATA: data to write\r\n" "Result will be displayed asynchronously.", prv_write_client, NULL}, {"exec", "Execute a client resource.", " exec CLIENT# URI\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri of the resource to execute such as /3/0/2\r\n" "Result will be displayed asynchronously.", prv_exec_client, NULL}, {"del", "Delete a client Object instance.", " del CLIENT# URI\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri of the instance to delete such as /1024/11\r\n" "Result will be displayed asynchronously.", prv_delete_client, NULL}, {"observe", "Observe from a client.", " observe CLIENT# URI\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri to observe such as /3, /3/0/2, /1024/11\r\n" "Result will be displayed asynchronously.", prv_observe_client, NULL}, {"cancel", "Cancel an observe.", " cancel CLIENT# URI\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri on which to cancel an observe such as /3, /3/0/2, /1024/11\r\n" "Result will be displayed asynchronously.", prv_cancel_client, NULL}, {"quit", "Quit the server.", NULL, prv_quit, NULL}, COMMAND_END_LIST }; socket = get_socket(); if (socket < 0) { fprintf(stderr, "Error opening socket: %d\r\n", errno); return -1; } lwm2mH = lwm2m_init(socket, "testlwm2mserver", 0, NULL, prv_buffer_send); if (NULL == lwm2mH) { fprintf(stderr, "lwm2m_init() failed\r\n"); return -1; } signal(SIGINT, handle_sigint); for (i = 0 ; commands[i].name != NULL ; i++) { commands[i].userData = (void *)lwm2mH; } fprintf(stdout, "> "); fflush(stdout); lwm2m_set_monitoring_callback(lwm2mH, prv_monitor_callback, lwm2mH); while (0 == g_quit) { FD_ZERO(&readfds); FD_SET(socket, &readfds); FD_SET(STDIN_FILENO, &readfds); tv.tv_sec = 60; tv.tv_usec = 0; result = lwm2m_step(lwm2mH, &tv); if (result != 0) { fprintf(stderr, "lwm2m_step() failed: 0x%X\r\n", result); return -1; } result = select(FD_SETSIZE, &readfds, 0, 0, &tv); if ( result < 0 ) { if (errno != EINTR) { fprintf(stderr, "Error in select(): %d\r\n", errno); } } else if (result > 0) { uint8_t buffer[MAX_PACKET_SIZE]; int numBytes; if (FD_ISSET(socket, &readfds)) { struct sockaddr_storage addr; socklen_t addrLen; addrLen = sizeof(addr); numBytes = recvfrom(socket, buffer, MAX_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrLen); if (numBytes == -1) { fprintf(stderr, "Error in recvfrom(): %d\r\n", errno); } else { char s[INET6_ADDRSTRLEN]; coap_status_t coap_error_code = NO_ERROR; static coap_packet_t message[1]; fprintf(stderr, "%d bytes received from [%s]:%hu\r\n", numBytes, inet_ntop(addr.ss_family, &(((struct sockaddr_in6*)&addr)->sin6_addr), s, INET6_ADDRSTRLEN), ntohs(((struct sockaddr_in6*)&addr)->sin6_port)); prv_output_buffer(stderr, buffer, numBytes); lwm2m_handle_packet(lwm2mH, buffer, numBytes, (uint8_t *)&addr, addrLen); } } else if (FD_ISSET(STDIN_FILENO, &readfds)) { numBytes = read(STDIN_FILENO, buffer, MAX_PACKET_SIZE); if (numBytes > 1) { buffer[numBytes - 1] = 0; handle_command(commands, buffer); } if (g_quit == 0) { fprintf(stdout, "\r\n> "); fflush(stdout); } else { fprintf(stdout, "\r\n"); } } } } lwm2m_close(lwm2mH); close(socket); return 0; }
static uint8_t prv_read(lwm2m_uri_t * uriP, char ** bufferP, int * lengthP, lwm2m_object_t * objectP) { prv_instance_t * targetP; *bufferP = NULL; *lengthP = 0; if (!LWM2M_URI_IS_SET_INSTANCE(uriP)) { *bufferP = (char *)malloc(PRV_TLV_BUFFER_SIZE); if (NULL == *bufferP) return COAP_500_INTERNAL_SERVER_ERROR; // TLV for (targetP = (prv_instance_t *)(objectP->instanceList); targetP != NULL ; targetP = targetP->next) { char temp_buffer[16]; int temp_length = 0; int result; result = lwm2m_intToTLV(TLV_RESSOURCE, targetP->test, 1, temp_buffer, 16); if (0 == result) { *lengthP = 0; break; } temp_length += result; result = lwm2m_opaqueToTLV(TLV_OBJECT_INSTANCE, temp_buffer, temp_length, targetP->shortID, *bufferP + *lengthP, PRV_TLV_BUFFER_SIZE - *lengthP); if (0 == result) { *lengthP = 0; break; } *lengthP += result; } if (*lengthP == 0) { free(*bufferP); *bufferP = NULL; return COAP_500_INTERNAL_SERVER_ERROR; } prv_output_buffer(*bufferP, *lengthP); return COAP_205_CONTENT; } else { targetP = (prv_instance_t *)lwm2m_list_find(objectP->instanceList, uriP->instanceId); if (NULL == targetP) return COAP_404_NOT_FOUND; if (!LWM2M_URI_IS_SET_RESOURCE(uriP)) { // TLV *bufferP = (char *)malloc(PRV_TLV_BUFFER_SIZE); if (NULL == *bufferP) return COAP_500_INTERNAL_SERVER_ERROR; *lengthP = lwm2m_intToTLV(TLV_RESSOURCE, targetP->test, 1, *bufferP, PRV_TLV_BUFFER_SIZE); if (0 == *lengthP) { free(*bufferP); *bufferP = NULL; return COAP_500_INTERNAL_SERVER_ERROR; } prv_output_buffer(*bufferP, *lengthP); return COAP_205_CONTENT; } switch (uriP->resourceId) { case 1: // we use int16 because value is unsigned *lengthP = lwm2m_int16ToPlainText(targetP->test, bufferP); if (*lengthP <= 0) return COAP_500_INTERNAL_SERVER_ERROR; return COAP_205_CONTENT; default: return COAP_404_NOT_FOUND; } } }