Пример #1
0
static void prv_backup_objects(lwm2m_context_t * context)
{
    uint16_t i;

    for (i = 0; i < BACKUP_OBJECT_COUNT; i++) {
        if (NULL != backupObjectArray[i]) {
            switch (backupObjectArray[i]->objID)
            {
            case LWM2M_SECURITY_OBJECT_ID:
                clean_security_object(backupObjectArray[i]);
                lwm2m_free(backupObjectArray[i]);
                break;
            case LWM2M_SERVER_OBJECT_ID:
                clean_server_object(backupObjectArray[i]);
                lwm2m_free(backupObjectArray[i]);
                break;
            default:
                break;
            }
        }
        backupObjectArray[i] = (lwm2m_object_t *)lwm2m_malloc(sizeof(lwm2m_object_t));
        if(backupObjectArray[i] != NULL)
            memset(backupObjectArray[i], 0, sizeof(lwm2m_object_t));
    }

    /*
     * Backup content of objects 0 (security) and 1 (server)
     */
    copy_security_object(backupObjectArray[0], (lwm2m_object_t *)LWM2M_LIST_FIND(context->objectList, LWM2M_SECURITY_OBJECT_ID));
    copy_server_object(backupObjectArray[1], (lwm2m_object_t *)LWM2M_LIST_FIND(context->objectList, LWM2M_SERVER_OBJECT_ID));
}
Пример #2
0
static void prv_restore_objects(lwm2m_context_t * context)
{
    uint16_t i;

    /*
     * Restore content  of objects 0 (security) and 1 (server)
     */
    for (i = 0; i < context->numObject; i++) {
        lwm2m_object_t * object = context->objectList[i];
        if (NULL != object) {
            switch (object->objID)
            {
            case LWM2M_SECURITY_OBJECT_ID:
                // first delete internal content
                clean_security_object(object);
                // then restore previous object
                copy_security_object(object, backupObjectArray[0]);
                break;
            case LWM2M_SERVER_OBJECT_ID:
                // first delete internal content
                clean_server_object(object);
                // then restore previous object
                copy_server_object(object, backupObjectArray[1]);
                break;
            default:
                break;
            }
        }
    }

    // restart the old servers
    fprintf(stdout, "[BOOTSTRAP] ObjectList restored\r\n");
}
Пример #3
0
static void close_backup_object()
{
    int i;
    for (i = 0; i < BACKUP_OBJECT_COUNT; i++) {
        if (NULL != backupObjectArray[i]) {
            switch (backupObjectArray[i]->objID)
            {
            case LWM2M_SECURITY_OBJECT_ID:
                clean_security_object(backupObjectArray[i]);
                lwm2m_free(backupObjectArray[i]);
                break;
            case LWM2M_SERVER_OBJECT_ID:
                clean_server_object(backupObjectArray[i]);
                lwm2m_free(backupObjectArray[i]);
                break;
            default:
                break;
            }
        }
    }
}
Пример #4
0
static void prv_restore_objects(lwm2m_context_t * context)
{
    lwm2m_object_t * targetP;

    /*
     * Restore content  of objects 0 (security) and 1 (server)
     */
    targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(context->objectList, LWM2M_SECURITY_OBJECT_ID);
    // first delete internal content
    clean_security_object(targetP);
    // then restore previous object
    copy_security_object(targetP, backupObjectArray[0]);

    targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(context->objectList, LWM2M_SERVER_OBJECT_ID);
    // first delete internal content
    clean_server_object(targetP);
    // then restore previous object
    copy_server_object(targetP, backupObjectArray[1]);

    // restart the old servers
    fprintf(stdout, "[BOOTSTRAP] ObjectList restored\r\n");
}
Пример #5
0
int main(int argc, char *argv[])
{
    client_data_t data;
    int result;
    lwm2m_context_t * lwm2mH = NULL;
    int i;
    const char * localPort = "56830";
    const char * server = NULL;
    const char * serverPort = LWM2M_STANDARD_PORT_STR;
    char * name = "testlwm2mclient";
    int lifetime = 300;
    int batterylevelchanging = 0;
    time_t reboot_time = 0;
    int opt;
    bool bootstrapRequested = false;
    bool serverPortChanged = false;

#ifdef LWM2M_BOOTSTRAP
    lwm2m_client_state_t previousState = STATE_INITIAL;
#endif

    char * pskId = NULL;
    char * psk = NULL;
    uint16_t pskLen = -1;
    char * pskBuffer = NULL;

    /*
     * The function start by setting up the command line interface (which may or not be useful depending on your project)
     *
     * This is an array of commands describes as { name, description, long description, callback, userdata }.
     * The firsts tree are easy to understand, the callback is the function that will be called when this command is typed
     * and in the last one will be stored the lwm2m context (allowing access to the server settings and the objects).
     */
    command_desc_t commands[] =
    {
            {"list", "List known servers.", NULL, prv_output_servers, NULL},
            {"change", "Change the value of resource.", " change URI [DATA]\r\n"
                                                        "   URI: uri of the resource such as /3/0, /3/0/2\r\n"
                                                        "   DATA: (optional) new value\r\n", prv_change, NULL},
            {"update", "Trigger a registration update", " update SERVER\r\n"
                                                        "   SERVER: short server id such as 123\r\n", prv_update, NULL},
#ifdef LWM2M_BOOTSTRAP
            {"bootstrap", "Initiate a DI bootstrap process", NULL, prv_initiate_bootstrap, NULL},
            {"dispb", "Display current backup of objects/instances/resources\r\n"
                    "\t(only security and server objects are backupped)", NULL, prv_display_backup, NULL},
#endif
            {"ls", "List Objects and Instances", NULL, prv_object_list, NULL},
            {"disp", "Display current objects/instances/resources", NULL, prv_display_objects, NULL},
            {"dump", "Dump an Object", "dump URI"
                                       "URI: uri of the Object or Instance such as /3/0, /1\r\n", prv_object_dump, NULL},
            {"add", "Add support of object 1024", NULL, prv_add, NULL},
            {"rm", "Remove support of object 1024", NULL, prv_remove, NULL},
            {"quit", "Quit the client gracefully.", NULL, prv_quit, NULL},
            {"^C", "Quit the client abruptly (without sending a de-register message).", NULL, NULL, NULL},

            COMMAND_END_LIST
    };

    memset(&data, 0, sizeof(client_data_t));
    data.addressFamily = AF_INET6;

    opt = 1;
    while (opt < argc)
    {
        if (argv[opt] == NULL
            || argv[opt][0] != '-'
            || argv[opt][2] != 0)
        {
            print_usage();
            return 0;
        }
        switch (argv[opt][1])
        {
        case 'b':
            bootstrapRequested = true;
            if (!serverPortChanged) serverPort = LWM2M_BSSERVER_PORT_STR;
            break;
        case 'c':
            batterylevelchanging = 1;
            break;
        case 't':
            opt++;
            if (opt >= argc)
            {
                print_usage();
                return 0;
            }
            if (1 != sscanf(argv[opt], "%d", &lifetime))
            {
                print_usage();
                return 0;
            }
            break;
#ifdef WITH_TINYDTLS
        case 'i':
            opt++;
            if (opt >= argc)
            {
                print_usage();
                return 0;
            }
            pskId = argv[opt];
            break;
        case 's':
            opt++;
            if (opt >= argc)
            {
                print_usage();
                return 0;
            }
            psk = argv[opt];
            break;
#endif						
        case 'n':
            opt++;
            if (opt >= argc)
            {
                print_usage();
                return 0;
            }
            name = argv[opt];
            break;
        case 'l':
            opt++;
            if (opt >= argc)
            {
                print_usage();
                return 0;
            }
            localPort = argv[opt];
            break;
        case 'h':
            opt++;
            if (opt >= argc)
            {
                print_usage();
                return 0;
            }
            server = argv[opt];
            break;
        case 'p':
            opt++;
            if (opt >= argc)
            {
                print_usage();
                return 0;
            }
            serverPort = argv[opt];
            serverPortChanged = true;
            break;
        case '4':
            data.addressFamily = AF_INET;
            break;
        default:
            print_usage();
            return 0;
        }
        opt += 1;
    }

    if (!server)
    {
        server = (AF_INET == data.addressFamily ? DEFAULT_SERVER_IPV4 : DEFAULT_SERVER_IPV6);
    }

    /*
     *This call an internal function that create an IPV6 socket on the port 5683.
     */
    fprintf(stderr, "Trying to bind LWM2M Client to port %s\r\n", localPort);
    data.sock = create_socket(localPort, data.addressFamily);
    if (data.sock < 0)
    {
        fprintf(stderr, "Failed to open socket: %d %s\r\n", errno, strerror(errno));
        return -1;
    }

    /*
     * Now the main function fill an array with each object, this list will be later passed to liblwm2m.
     * Those functions are located in their respective object file.
     */
#ifdef WITH_TINYDTLS
    if (psk != NULL)
    {
        pskLen = strlen(psk) / 2;
        pskBuffer = malloc(pskLen);

        if (NULL == pskBuffer)
        {
            fprintf(stderr, "Failed to create PSK binary buffer\r\n");
            return -1;
        }
        // Hex string to binary
        char *h = psk;
        char *b = pskBuffer;
        char xlate[] = "0123456789ABCDEF";

        for ( ; *h; h += 2, ++b)
        {
            char *l = strchr(xlate, toupper(*h));
            char *r = strchr(xlate, toupper(*(h+1)));

            if (!r || !l)
            {
                fprintf(stderr, "Failed to parse Pre-Shared-Key HEXSTRING\r\n");
                return -1;
            }

            *b = ((l - xlate) << 4) + (r - xlate);
        }
    }
#endif

    char serverUri[50];
    int serverId = 123;
    sprintf (serverUri, "coap://%s:%s", server, serverPort);
#ifdef LWM2M_BOOTSTRAP
    objArray[0] = get_security_object(serverId, serverUri, pskId, pskBuffer, pskLen, bootstrapRequested);
#else
    objArray[0] = get_security_object(serverId, serverUri, pskId, pskBuffer, pskLen, false);
#endif
    if (NULL == objArray[0])
    {
        fprintf(stderr, "Failed to create security object\r\n");
        return -1;
    }
    data.securityObjP = objArray[0];

    objArray[1] = get_server_object(serverId, "U", lifetime, false);
    if (NULL == objArray[1])
    {
        fprintf(stderr, "Failed to create server object\r\n");
        return -1;
    }

    objArray[2] = get_object_device();
    if (NULL == objArray[2])
    {
        fprintf(stderr, "Failed to create Device object\r\n");
        return -1;
    }

    objArray[3] = get_object_firmware();
    if (NULL == objArray[3])
    {
        fprintf(stderr, "Failed to create Firmware object\r\n");
        return -1;
    }

    objArray[4] = get_object_location();
    if (NULL == objArray[4])
    {
        fprintf(stderr, "Failed to create location object\r\n");
        return -1;
    }

    objArray[5] = get_test_object();
    if (NULL == objArray[5])
    {
        fprintf(stderr, "Failed to create test object\r\n");
        return -1;
    }

    objArray[6] = get_object_conn_m();
    if (NULL == objArray[6])
    {
        fprintf(stderr, "Failed to create connectivity monitoring object\r\n");
        return -1;
    }

    objArray[7] = get_object_conn_s();
    if (NULL == objArray[7])
    {
        fprintf(stderr, "Failed to create connectivity statistics object\r\n");
        return -1;
    }

    int instId = 0;
    objArray[8] = acc_ctrl_create_object();
    if (NULL == objArray[8])
    {
        fprintf(stderr, "Failed to create Access Control object\r\n");
        return -1;
    }
    else if (acc_ctrl_obj_add_inst(objArray[8], instId, 3, 0, serverId)==false)
    {
        fprintf(stderr, "Failed to create Access Control object instance\r\n");
        return -1;
    }
    else if (acc_ctrl_oi_add_ac_val(objArray[8], instId, 0, 0b000000000001111)==false)
    {
        fprintf(stderr, "Failed to create Access Control ACL default resource\r\n");
        return -1;
    }
    else if (acc_ctrl_oi_add_ac_val(objArray[8], instId, 999, 0b000000000000001)==false)
    {
        fprintf(stderr, "Failed to create Access Control ACL resource for serverId: 999\r\n");
        return -1;
    }
    /*
     * The liblwm2m library is now initialized with the functions that will be in
     * charge of communication
     */
    lwm2mH = lwm2m_init(&data);
    if (NULL == lwm2mH)
    {
        fprintf(stderr, "lwm2m_init() failed\r\n");
        return -1;
    }
	
#ifdef WITH_TINYDTLS
    data.lwm2mH = lwm2mH;
#endif

    /*
     * We configure the liblwm2m library with the name of the client - which shall be unique for each client -
     * the number of objects we will be passing through and the objects array
     */
    result = lwm2m_configure(lwm2mH, name, NULL, NULL, OBJ_COUNT, objArray);
    if (result != 0)
    {
        fprintf(stderr, "lwm2m_configure() failed: 0x%X\r\n", result);
        return -1;
    }

    signal(SIGINT, handle_sigint);

    /**
     * Initialize value changed callback.
     */
    init_value_change(lwm2mH);

    /*
     * As you now have your lwm2m context complete you can pass it as an argument to all the command line functions
     * precedently viewed (first point)
     */
    for (i = 0 ; commands[i].name != NULL ; i++)
    {
        commands[i].userData = (void *)lwm2mH;
    }
    fprintf(stdout, "LWM2M Client \"%s\" started on port %s\r\n", name, localPort);
    fprintf(stdout, "> "); fflush(stdout);
    /*
     * We now enter in a while loop that will handle the communications from the server
     */
    while (0 == g_quit)
    {
        struct timeval tv;
        fd_set readfds;

        if (g_reboot)
        {
            time_t tv_sec;

            tv_sec = lwm2m_gettime();

            if (0 == reboot_time)
            {
                reboot_time = tv_sec + 5;
            }
            if (reboot_time < tv_sec)
            {
                /*
                 * Message should normally be lost with reboot ...
                 */
                fprintf(stderr, "reboot time expired, rebooting ...");
                system_reboot();
            }
            else
            {
                tv.tv_sec = reboot_time - tv_sec;
            }
        }
        else if (batterylevelchanging) 
        {
            update_battery_level(lwm2mH);
            tv.tv_sec = 5;
        }
        else 
        {
            tv.tv_sec = 60;
        }
        tv.tv_usec = 0;

        FD_ZERO(&readfds);
        FD_SET(data.sock, &readfds);
        FD_SET(STDIN_FILENO, &readfds);

        /*
         * This function does two things:
         *  - first it does the work needed by liblwm2m (eg. (re)sending some packets).
         *  - Secondly it adjusts the timeout value (default 60s) depending on the state of the transaction
         *    (eg. retransmission) and the time between the next operation
         */
        result = lwm2m_step(lwm2mH, &(tv.tv_sec));
        if (result != 0)
        {
            fprintf(stderr, "lwm2m_step() failed: 0x%X\r\n", result);
            if(previousState == STATE_BOOTSTRAPPING)
            {
#ifdef WITH_LOGS
                fprintf(stdout, "[BOOTSTRAP] restore security and server objects\r\n");
#endif
                prv_connections_free(lwm2mH);
                prv_restore_objects(lwm2mH);
                lwm2mH->state = STATE_INITIAL;
            }
            else return -1;
        }
#ifdef LWM2M_BOOTSTRAP
        update_bootstrap_info(&previousState, lwm2mH);
#endif
        /*
         * This part will set up an interruption until an event happen on SDTIN or the socket until "tv" timed out (set
         * with the precedent function)
         */
        result = select(FD_SETSIZE, &readfds, NULL, NULL, &tv);

        if (result < 0)
        {
            if (errno != EINTR)
            {
              fprintf(stderr, "Error in select(): %d %s\r\n", errno, strerror(errno));
            }
        }
        else if (result > 0)
        {
            uint8_t buffer[MAX_PACKET_SIZE];
            int numBytes;

            /*
             * If an event happens on the socket
             */
            if (FD_ISSET(data.sock, &readfds))
            {
                struct sockaddr_storage addr;
                socklen_t addrLen;

                addrLen = sizeof(addr);

                /*
                 * We retrieve the data received
                 */
                numBytes = recvfrom(data.sock, buffer, MAX_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrLen);

                if (0 > numBytes)
                {
                    fprintf(stderr, "Error in recvfrom(): %d %s\r\n", errno, strerror(errno));
                }
                else if (0 < numBytes)
                {
                    char s[INET6_ADDRSTRLEN];
                    in_port_t port;

#ifdef WITH_TINYDTLS
                    dtls_connection_t * connP;
#else
                    connection_t * connP;
#endif
                    if (AF_INET == addr.ss_family)
                    {
                        struct sockaddr_in *saddr = (struct sockaddr_in *)&addr;
                        inet_ntop(saddr->sin_family, &saddr->sin_addr, s, INET6_ADDRSTRLEN);
                        port = saddr->sin_port;
                    }
                    else if (AF_INET6 == addr.ss_family)
                    {
                        struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)&addr;
                        inet_ntop(saddr->sin6_family, &saddr->sin6_addr, s, INET6_ADDRSTRLEN);
                        port = saddr->sin6_port;
                    }
                    fprintf(stderr, "%d bytes received from [%s]:%hu\r\n", numBytes, s, ntohs(port));

                    /*
                     * Display it in the STDERR
                     */
                    output_buffer(stderr, buffer, numBytes, 0);

                    connP = connection_find(data.connList, &addr, addrLen);
                    if (connP != NULL)
                    {
                        /*
                         * Let liblwm2m respond to the query depending on the context
                         */
#ifdef WITH_TINYDTLS
                        int result = connection_handle_packet(connP, buffer, numBytes);
						if (0 != result)
                        {
                             printf("error handling message %d\n",result);
                        }
#else
                        lwm2m_handle_packet(lwm2mH, buffer, numBytes, connP);
#endif
                        conn_s_updateRxStatistic(objArray[7], numBytes, false);
                    }
                    else
                    {
                        fprintf(stderr, "received bytes ignored!\r\n");
                    }
                }
            }

            /*
             * If the event happened on the SDTIN
             */
            else if (FD_ISSET(STDIN_FILENO, &readfds))
            {
                numBytes = read(STDIN_FILENO, buffer, MAX_PACKET_SIZE - 1);

                if (numBytes > 1)
                {
                    buffer[numBytes] = 0;
                    /*
                     * We call the corresponding callback of the typed command passing it the buffer for further arguments
                     */
                    handle_command(commands, (char*)buffer);
                }
                if (g_quit == 0)
                {
                    fprintf(stdout, "\r\n> ");
                    fflush(stdout);
                }
                else
                {
                    fprintf(stdout, "\r\n");
                }
            }
        }
    }

    /*
     * Finally when the loop is left smoothly - asked by user in the command line interface - we unregister our client from it
     */
    if (g_quit == 1)
    {
#ifdef LWM2M_BOOTSTRAP
        close_backup_object();
#endif
        lwm2m_close(lwm2mH);
    }
    close(data.sock);
    connection_free(data.connList);

    clean_security_object(objArray[0]);
    lwm2m_free(objArray[0]);
    clean_server_object(objArray[1]);
    lwm2m_free(objArray[1]);
    free_object_device(objArray[2]);
    free_object_firmware(objArray[3]);
    free_object_location(objArray[4]);
    free_test_object(objArray[5]);
    free_object_conn_m(objArray[6]);
    free_object_conn_s(objArray[7]);
    acl_ctrl_free_object(objArray[8]);

#ifdef MEMORY_TRACE
    if (g_quit == 1)
    {
        trace_print(0, 1);
    }
#endif

    return 0;
}
Пример #6
0
int lwm2m_client_cb(void *args)
{
	int argc;
	char **argv;

	int i;
	int result;
	int opt;
	char *name = "testlwm2mclient";

#ifdef WITH_MBEDTLS
	unsigned char psk[MBEDTLS_PSK_MAX_LEN];

	/* set default tls option */

	/*
	 * if you want to change auth_mode, please change 3rd parameter of tls_opt structure
	 * - auth_mode can be configured (2: mandatory 1: optional, 0: not verify)
	 */
	tls_opt option = {MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_DATAGRAM, 0, 1, NULL, };
	/* set cipher suite to all*/
	option.force_ciphersuites[0] = mbedtls_ssl_get_ciphersuite_id(LWM2M_CIPHERSUIT);
	option.force_ciphersuites[1] = 0;
#endif

	struct timeval tv = {60, 0};
	argc = ((struct pthread_arg *)args)->argc;
	argv = ((struct pthread_arg *)args)->argv;

	lwm2mH = NULL;
	g_quit = 0;
	server = DEFAULT_SERVER_IPV4;
	serverPort = LWM2M_STANDARD_PORT_STR;
	/* Setting up the command line interface. */
	command_desc_t commands[] = {
		{"list", "List known servers.", NULL, prv_output_servers, NULL},
		{
			"change", "Change the value of resource.", " change URI [DATA]\r\n"
			"   URI: uri of the resource such as /3/0, /3/0/2\r\n"
			"   DATA: (optional) new value\r\n", prv_change, NULL
		},
		{
			"update", "Trigger a registration update", " update SERVER\r\n"
			"   SERVER: short server id such as 123\r\n", prv_update, NULL
		},
		{"ls", "List Objects and Instances", NULL, prv_object_list, NULL},
		{
			"dump", "Dump an Object", "dump URI"
			"URI: uri of the Object or Instance such as /3/0, /1\r\n", prv_object_dump, NULL
		},
		{"add", "Add support of object 1024", NULL, prv_add, NULL},
		{"rm", "Remove support of object 1024", NULL, prv_remove, NULL},
		{"quit", "Quit the client gracefully.", NULL, prv_quit, NULL},
		{"^C", "Quit the client abruptly (without sending a de-register message).", NULL, NULL, NULL},
		COMMAND_END_LIST
	};

	memset(&data, 0, sizeof(client_data_t));
	data.addressFamily = AF_INET;

	opt = 1;
	while (opt < argc) {
		if (argv[opt] == NULL
			|| argv[opt][0] != '-'
			|| argv[opt][2] != 0) {
			print_usage();
			return 0;
		}
		switch (argv[opt][1]) {
		case 't':
			opt++;
			if (opt >= argc) {
				print_usage();
				return 0;
			}
			if (1 != sscanf(argv[opt], "%d", &g_lifetime)) {
				print_usage();
				return 0;
			}
			break;
#ifdef WITH_MBEDTLS
		case 'i':
			opt++;
			if (opt >= argc) {
				print_usage();
				return 0;
			}
			g_pskId = argv[opt];
			break;
		case 's':
			opt++;
			if (opt >= argc) {
				print_usage();
				return 0;
			}
			g_pskBuffer = argv[opt];
			break;
#endif
		case 'h':
			opt++;
			if (opt >= argc) {
				print_usage();
				return 0;
			}
			server = argv[opt];
			break;
		default:
			print_usage();
			return 0;
		}
		opt += 1;
	}

	/* Parse server URI to distinguish protocol and server address */
	g_proto = coap_get_protocol_from_uri(server);
	if (g_proto >= COAP_PROTOCOL_MAX) {
		printf("Not supported protocol : %d\n", g_proto);
		return -1;
	}

	/* Move pointer to address field */
	server += strlen(coap_uri_prefix[g_proto]);
	serverPort = coap_get_port_from_proto(g_proto);

	if (lwm2m_init_object() < 0) {
	}

	/* This call an internal function that create an socket. */
	printf("Trying to bind LWM2M Client to port %s\n", serverPort);
	data.sock = create_socket(g_proto, serverPort, data.addressFamily);
	if (data.sock < 0) {
		fprintf(stderr, "Failed to open socket: %d %s\r\n", errno, strerror(errno));
		return -1;
	}

#ifdef WITH_MBEDTLS
	if (g_proto == COAP_TCP_TLS || g_proto == COAP_UDP_DTLS) {

		/* Set Transport layer (TCP or UDP) */
		switch (g_proto) {
		case COAP_TCP_TLS:
			option.transport = MBEDTLS_SSL_TRANSPORT_STREAM;
			break;
		case COAP_UDP_DTLS:
			option.transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM;
			break;
		default:
			break;
		}
		data.tls_opt = &option;

		/* Set credential information */
		tls_cred cred;
		memset(&cred, 0, sizeof(tls_cred));

		if (g_pskBuffer) {
			if (lwm2m_unhexify(psk, g_pskBuffer, &cred.psk_len) == 0) {
				if (g_pskId) {
					cred.psk_identity = g_pskId;
					cred.psk = psk;
				}
			}
			if (cred.psk_identity == NULL && cred.psk == NULL) {
				printf("failed to set psk info\n");
				goto exit;
			}
		} else {
			printf("Please set psk and psk_id\n");
			goto exit;
		}

		data.tls_context = TLSCtx(&cred);
		if (data.tls_context == NULL) {
			printf("TLS context initialize failed\n");
			goto exit;
		}
	}
#endif
	if ((lwm2mH = lwm2m_init(&data)) == NULL) {
		printf("lwm2m_init2() failed\n");
		goto exit;
	}
	lwm2mH->protocol = g_proto;

	if ((result = lwm2m_configure(lwm2mH, name, NULL, NULL, OBJ_COUNT, objArray)) != 0) {
		printf("lwm2m_configure() failed: 0x%X\n", result);
		goto exit;
	}

	/* Register the command line command */
	for (i = 0 ; commands[i].name != NULL ; i++) {
		commands[i].userData = (void *)lwm2mH;
	}
	printf("LWM2M Client \"%s\" started on port %s\n>  ", name, serverPort);

	/* We now enter in a while loop that will handle the communications from the server */
	while (0 == g_quit) {
		tv.tv_sec = 60;
		tv.tv_usec = 0;

		if ((result = lwm2m_step(lwm2mH, &(tv.tv_sec))) != 0) {
			printf("lwm2m_step() failed: 0x%X\n", result);
			goto exit;
		} else {
			printf(" -> State: %s\n", g_step[lwm2mH->state]);
		}

		fd_set readfds;
		FD_ZERO(&readfds);
		FD_SET(data.sock, &readfds);
		FD_SET(STDIN_FILENO, &readfds);

		result = select(FD_SETSIZE, &readfds, NULL, NULL, &tv);
		if (result < 0) {
			if (errno != EINTR) {
				fprintf(stderr, "Error in select(): %d %s\r\n", errno, strerror(errno));
			}
		} else if (result > 0) {
			uint8_t buffer[MAX_PACKET_SIZE];
			int numBytes;

			if (FD_ISSET(data.sock, &readfds)) {
				client_data_t *user_data = lwm2mH->userData;

				numBytes = connection_read(g_proto, user_data->connP, data.sock, buffer, MAX_PACKET_SIZE, NULL, 0);

				if (numBytes > 0) {
					output_buffer(stderr, buffer, numBytes, 0);
					lwm2m_handle_packet(lwm2mH, buffer, numBytes, user_data->connP);
					conn_s_updateRxStatistic(objArray[7], numBytes, false);
				} else {
					printf("received bytes ignored!\n");
				}
				/* If the event happened on the SDTIN */
			} else if (FD_ISSET(STDIN_FILENO, &readfds)) {
				numBytes = read_input_command_line((char *)buffer);
				if (numBytes > 1) {
					buffer[numBytes] = 0;
					handle_command(commands, (char *)buffer);
				}
				if (g_quit == 0) {
					fprintf(stdout, "\r\n> ");
					fflush(stdout);
				}
			}
		}
	}

exit:
	if (g_quit && lwm2mH) {
		lwm2m_close(lwm2mH);
		sleep(1);
	}

#ifdef WITH_MBEDTLS
	if (data.tls_context) {
		TLSCtx_free(data.tls_context);
	}
#endif

	if (data.sock >= 0) {
		printf("Closing %d\n", data.sock);
		shutdown(data.sock, 3);
		if ((i = close(data.sock)) != 0) {
			printf("Fail to close %d\n", errno);
		}
	}

	if (data.connP) {
		connection_free(data.connP);
	}

	clean_security_object(objArray[0]);
	clean_server_object(objArray[1]);
	free_object_device(objArray[2]);
	free_object_firmware(objArray[3]);
	free_object_location(objArray[4]);
	free_test_object(objArray[5]);
	free_object_conn_m(objArray[6]);
	free_object_conn_s(objArray[7]);
	acl_ctrl_free_object(objArray[8]);
	lwm2m_free(objArray[0]);
	lwm2m_free(objArray[1]);

	return 0;
}