Esempio n. 1
0
int uri_toString(lwm2m_uri_t * uriP,
                 uint8_t * buffer,
                 size_t bufferLen,
                 uri_depth_t * depthP)
{
    size_t head;
    int res;

    LOG_ARG("bufferLen: %u", bufferLen);
    LOG_URI(uriP);

    buffer[0] = '/';

    if (uriP == NULL)
    {
        if (depthP) *depthP = URI_DEPTH_OBJECT;
        return 1;
    }

    head = 1;

    res = utils_intToText(uriP->objectId, buffer + head, bufferLen - head);
    if (res <= 0) return -1;
    head += res;
    if (head >= bufferLen - 1) return -1;
    if (depthP) *depthP = URI_DEPTH_OBJECT_INSTANCE;

    if (LWM2M_URI_IS_SET_INSTANCE(uriP))
    {
        buffer[head] = '/';
        head++;
        res = utils_intToText(uriP->instanceId, buffer + head, bufferLen - head);
        if (res <= 0) return -1;
        head += res;
        if (head >= bufferLen - 1) return -1;
        if (depthP) *depthP = URI_DEPTH_RESOURCE;
        if (LWM2M_URI_IS_SET_RESOURCE(uriP))
        {
            buffer[head] = '/';
            head++;
            res = utils_intToText(uriP->resourceId, buffer + head, bufferLen - head);
            if (res <= 0) return -1;
            head += res;
            if (head >= bufferLen - 1) return -1;
            if (depthP) *depthP = URI_DEPTH_RESOURCE_INSTANCE;
        }
    }

    buffer[head] = '/';
    head++;

    LOG_ARG("length: %u, buffer: \"%.*s\"", head, head, buffer);

    return head;
}
Esempio n. 2
0
int utils_intCopy(char * buffer,
                  size_t length,
                  int32_t value)
{
#define _PRV_INT32_MAX_STR_LEN 11
    uint8_t str[_PRV_INT32_MAX_STR_LEN];
    size_t len;

    len = utils_intToText(value, str, _PRV_INT32_MAX_STR_LEN);
    if (len == 0) return -1;
    if (len > length + 1) return -1;

    memcpy(buffer, str + _PRV_INT32_MAX_STR_LEN - len, len);
    buffer[len] = 0;

    return len;
}
Esempio n. 3
0
size_t lwm2m_int64ToPlainText(int64_t data,
                              uint8_t ** bufferP)
{
#define _PRV_STR_LENGTH 32
    uint8_t string[_PRV_STR_LENGTH];
    size_t length;

    length = utils_intToText(data, string, _PRV_STR_LENGTH);
    if (length == 0) return 0;

    *bufferP = (uint8_t *)lwm2m_malloc(length);
    if (NULL == *bufferP) return 0;

    memcpy(*bufferP, string, length);

    return length;
}
Esempio n. 4
0
static void test_utils_intToText(void)
{
    size_t i;

    for (i = 0 ; i < sizeof(ints)/sizeof(ints[0]); i++)
    {
        char res[24];
        int len;

        len = utils_intToText(ints[i], (uint8_t*)res, sizeof(res));

        CU_ASSERT(len);
        CU_ASSERT_NSTRING_EQUAL(res, ints_text[i], strlen(ints_text[i]));
        if (!len)
            printf("%zu \"%" PRId64 "\" -> fail\n", i, ints[i]);
        else if (strncmp(res, ints_text[i], strlen(ints_text[i])))
            printf("%zu \"%" PRId64 "\" -> fail (%s)\n", i, ints[i], res);
    }
}
Esempio n. 5
0
size_t utils_floatToText(double data,
                         uint8_t * string,
                         size_t length)
{
    size_t intLength;
    size_t decLength;
    int64_t intPart;
    double decPart;

    intPart = (int64_t)data;
    decPart = data - intPart;
    if (decPart < 0)
    {
        decPart = 1 - decPart;
    }
    else
    {
        decPart = 1 + decPart;
    }

    if (decPart <= 1 + FLT_EPSILON)
    {
        decPart = 0;
    }

    if (intPart == 0 && data < 0)
    {
        // deal with numbers between -1 and 0
        if (length < 4) return 0;   // "-0.n"
        string[0] = '-';
        string[1] = '0';
        intLength = 2;
    }
    else
    {
        intLength = utils_intToText(intPart, string, length);
        if (intLength == 0) return 0;
    }
    decLength = 0;
    if (decPart != 0)
    {
        int i;
        double noiseFloor;

        if (intLength >= length - 1) return 0;

        i = 0;
        noiseFloor = FLT_EPSILON;
        do
        {
            decPart *= 10;
            noiseFloor *= 10;
            i++;
        } while (decPart - (int64_t)decPart > noiseFloor);

        decLength = utils_intToText(decPart, string + intLength, length - intLength);
        if (decLength <= 1) return 0;

        // replace the leading 1 with a dot
        string[intLength] = '.';
    }

    return intLength + decLength;
}
Esempio n. 6
0
lwm2m_transaction_t * transaction_new(void * sessionH,
                                      coap_method_t method,
                                      char * altPath,
                                      lwm2m_uri_t * uriP,
                                      uint16_t mID,
                                      uint8_t token_len,
                                      uint8_t* token)
{
    lwm2m_transaction_t * transacP;
    int result;

    LOG_ARG("method: %d, altPath: \"%s\", mID: %d, token_len: %d",
            method, altPath, mID, token_len);
    LOG_URI(uriP);

    // no transactions without peer
    if (NULL == sessionH) return NULL;

    transacP = (lwm2m_transaction_t *)lwm2m_malloc(sizeof(lwm2m_transaction_t));

    if (NULL == transacP) return NULL;
    memset(transacP, 0, sizeof(lwm2m_transaction_t));

    transacP->message = lwm2m_malloc(sizeof(coap_packet_t));
    if (NULL == transacP->message) goto error;

    coap_init_message(transacP->message, COAP_TYPE_CON, method, mID);

    transacP->peerH = sessionH;

    transacP->mID = mID;

    if (altPath != NULL)
    {
        // TODO: Support multi-segment alternative path
        coap_set_header_uri_path_segment(transacP->message, altPath + 1);
    }
    if (NULL != uriP)
    {
        char stringID[LWM2M_STRING_ID_MAX_LEN];

        result = utils_intToText(uriP->objectId, (uint8_t*)stringID, LWM2M_STRING_ID_MAX_LEN);
        if (result == 0) goto error;
        stringID[result] = 0;
        coap_set_header_uri_path_segment(transacP->message, stringID);

        if (LWM2M_URI_IS_SET_INSTANCE(uriP))
        {
            result = utils_intToText(uriP->instanceId, (uint8_t*)stringID, LWM2M_STRING_ID_MAX_LEN);
            if (result == 0) goto error;
            stringID[result] = 0;
            coap_set_header_uri_path_segment(transacP->message, stringID);
        }
        else
        {
            if (LWM2M_URI_IS_SET_RESOURCE(uriP))
            {
                coap_set_header_uri_path_segment(transacP->message, NULL);
            }
        }
        if (LWM2M_URI_IS_SET_RESOURCE(uriP))
        {
            result = utils_intToText(uriP->resourceId, (uint8_t*)stringID, LWM2M_STRING_ID_MAX_LEN);
            if (result == 0) goto error;
            stringID[result] = 0;
            coap_set_header_uri_path_segment(transacP->message, stringID);
        }
    }
    if (0 < token_len)
    {
        if (NULL != token)
        {
            coap_set_header_token(transacP->message, token, token_len);
        }
        else {
            // generate a token
            uint8_t temp_token[COAP_TOKEN_LEN];
            time_t tv_sec = lwm2m_gettime();

            // initialize first 6 bytes, leave the last 2 random
            temp_token[0] = mID;
            temp_token[1] = mID >> 8;
            temp_token[2] = tv_sec;
            temp_token[3] = tv_sec >> 8;
            temp_token[4] = tv_sec >> 16;
            temp_token[5] = tv_sec >> 24;
            // use just the provided amount of bytes
            coap_set_header_token(transacP->message, temp_token, token_len);
        }
    }

    LOG("Exiting on success");
    return transacP;

error:
    LOG("Exiting on failure");
    lwm2m_free(transacP);
    return NULL;
}
Esempio n. 7
0
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);
}
Esempio n. 8
0
int discover_serialize(lwm2m_context_t * contextP,
                      lwm2m_uri_t * uriP,
                      int size,
                      lwm2m_data_t * dataP,
                      uint8_t ** bufferP)
{
    uint8_t bufferLink[PRV_LINK_BUFFER_SIZE];
    uint8_t baseUriStr[URI_MAX_STRING_LEN];
    int baseUriLen;
    int index;
    size_t head;
    int res;
    lwm2m_uri_t tempUri;

    baseUriLen = uri_toString(uriP, baseUriStr, URI_MAX_STRING_LEN, NULL);
    if (baseUriLen < 0) return -1;
    baseUriLen -= 1;

    head = 0;
    memset(&tempUri, 0, sizeof(lwm2m_uri_t));

    // get object level attributes
    PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_ITEM_START, LINK_ITEM_START_SIZE);
    PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_URI_SEPARATOR, LINK_URI_SEPARATOR_SIZE);
    res = utils_intToText(uriP->objectId, bufferLink + head, PRV_LINK_BUFFER_SIZE - head);
    if (res <= 0) return -1;
    head += res;
    PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_ITEM_END, LINK_ITEM_END_SIZE);
    tempUri.objectId = uriP->objectId;
    res = prv_serializeAttributes(contextP, &tempUri, bufferLink, head - 1, PRV_LINK_BUFFER_SIZE);
    if (res < 0) return -1;    // careful, 0 is valid
    if (res == 0) head = 0;    // rewind
    else head += res - 1;
    if (LWM2M_URI_IS_SET_INSTANCE(uriP))
    {
        size_t subHead;

        // get object instance level attributes
        subHead = 0;
        PRV_CONCAT_STR(bufferLink + head, PRV_LINK_BUFFER_SIZE - head, subHead, LINK_ITEM_START, LINK_ITEM_START_SIZE);
        PRV_CONCAT_STR(bufferLink + head, PRV_LINK_BUFFER_SIZE - head, subHead, LINK_URI_SEPARATOR, LINK_URI_SEPARATOR_SIZE);
        res = utils_intToText(uriP->objectId, bufferLink + head + subHead, PRV_LINK_BUFFER_SIZE - head - subHead);
        if (res <= 0) return -1;
        subHead += res;
        PRV_CONCAT_STR(bufferLink + head, PRV_LINK_BUFFER_SIZE - head, subHead, LINK_URI_SEPARATOR, LINK_URI_SEPARATOR_SIZE);
        res = utils_intToText(uriP->instanceId, bufferLink + head + subHead, PRV_LINK_BUFFER_SIZE - head - subHead);
        if (res <= 0) return -1;
        subHead += res;
        PRV_CONCAT_STR(bufferLink + head, PRV_LINK_BUFFER_SIZE - head, subHead, LINK_ITEM_END, LINK_ITEM_END_SIZE);
        tempUri.instanceId = uriP->instanceId;
        tempUri.flag = LWM2M_URI_FLAG_INSTANCE_ID;
        res = prv_serializeAttributes(contextP, &tempUri, bufferLink + head, head + subHead - 1, PRV_LINK_BUFFER_SIZE);
        if (res < 0) return -1;    // careful, 0 is valid
        if (res == 0) subHead = 0;    // rewind
        else subHead += res - 1;

        head += subHead;
    }

    for (index = 0; index < size && head < PRV_LINK_BUFFER_SIZE; index++)
    {
        res = prv_serializeLinkData(contextP, dataP + index, uriP, baseUriStr, baseUriLen, bufferLink + head, PRV_LINK_BUFFER_SIZE - head);
        if (res < 0) return -1;
        head += res;
    }

    if (head > 0)
    {
        head -= 1;

        *bufferP = (uint8_t *)lwm2m_malloc(head);
        if (*bufferP == NULL) return 0;
        memcpy(*bufferP, bufferLink, head);
    }

    return (int)head;
}
Esempio n. 9
0
static int prv_serializeAttributes(lwm2m_context_t * contextP,
                                   lwm2m_uri_t * uriP,
                                   uint8_t * buffer,
                                   size_t uriLen,
                                   size_t bufferLen)
{
    lwm2m_observed_t * observedP;
    lwm2m_watcher_t * watcherP;
    int head;
    int res;

    if (contextP == NULL) return 0;

    observedP = observe_findByUri(contextP, uriP);
    if (observedP == NULL || observedP->watcherList == NULL) return 0;

    head = 0;
    for (watcherP = observedP->watcherList; watcherP != NULL; watcherP = watcherP->next)
    {
        lwm2m_attributes_t * paramP;

        paramP = watcherP->parameters;
        if (paramP == NULL || paramP->toSet == 0) continue;

        if (observedP->watcherList->next != NULL)
        {
            // multiple servers
            memcpy(buffer + head, buffer, uriLen);

            PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
            PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_SERVER_ID_STR, ATTR_SERVER_ID_LEN);

            res = utils_intToText(watcherP->server->shortID, buffer + head, bufferLen - head);
            if (res <= 0) return -1;
            head += res;
        }
        else
        {
            head = uriLen;
        }

        if (paramP->toSet & LWM2M_ATTR_FLAG_MIN_PERIOD)
        {
            PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
            PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN);

            res = utils_intToText(paramP->minPeriod, buffer + head, bufferLen - head);
            if (res <= 0) return -1;
            head += res;
        }
        if (paramP->toSet & LWM2M_ATTR_FLAG_MAX_PERIOD)
        {
            PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
            PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN);

            res = utils_intToText(paramP->maxPeriod, buffer + head, bufferLen - head);
            if (res <= 0) return -1;
            head += res;
        }
        if (paramP->toSet & LWM2M_ATTR_FLAG_GREATER_THAN)
        {
            PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
            PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_GREATER_THAN_STR, ATTR_GREATER_THAN_LEN);

            res = utils_floatToText(paramP->greaterThan, buffer + head, bufferLen - head);
            if (res <= 0) return -1;
            head += res;
        }
        if (paramP->toSet & LWM2M_ATTR_FLAG_LESS_THAN)
        {
            PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
            PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_LESS_THAN_STR, ATTR_LESS_THAN_LEN);

            res = utils_floatToText(paramP->lessThan, buffer + head, bufferLen - head);
            if (res <= 0) return -1;
            head += res;
        }
        if (paramP->toSet & LWM2M_ATTR_FLAG_STEP)
        {
            PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
            PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_STEP_STR, ATTR_STEP_LEN);

            res = utils_floatToText(paramP->step, buffer + head, bufferLen - head);
            if (res <= 0) return -1;
            head += res;
        }
        PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ITEM_ATTR_END, LINK_ITEM_ATTR_END_SIZE);
    }

    if (head > 0) head -= uriLen;

    return head;
}
Esempio n. 10
0
// dataP array length is assumed to be 1.
static int prv_textSerialize(lwm2m_data_t * dataP,
                             uint8_t ** bufferP)
{
    size_t res;

    switch (dataP->type)
    {
    case LWM2M_TYPE_STRING:
        *bufferP = (uint8_t *)lwm2m_malloc(dataP->value.asBuffer.length);
        if (*bufferP == NULL) return 0;
        memcpy(*bufferP, dataP->value.asBuffer.buffer, dataP->value.asBuffer.length);
        return (int)dataP->value.asBuffer.length;

    case LWM2M_TYPE_INTEGER:
    {
        uint8_t intString[_PRV_STR_LENGTH];

        res = utils_intToText(dataP->value.asInteger, intString, _PRV_STR_LENGTH);
        if (res == 0) return -1;

        *bufferP = (uint8_t *)lwm2m_malloc(res);
        if (NULL == *bufferP) return -1;

        memcpy(*bufferP, intString, res);

        return (int)res;
    }

    case LWM2M_TYPE_FLOAT:
    {
        uint8_t floatString[_PRV_STR_LENGTH * 2];

        res = utils_floatToText(dataP->value.asFloat, floatString, _PRV_STR_LENGTH * 2);
        if (res == 0) return -1;

        *bufferP = (uint8_t *)lwm2m_malloc(res);
        if (NULL == *bufferP) return -1;

        memcpy(*bufferP, floatString, res);

        return (int)res;
    }

    case LWM2M_TYPE_BOOLEAN:
        *bufferP = (uint8_t *)lwm2m_malloc(1);
        if (NULL == *bufferP) return -1;

        *bufferP[0] = dataP->value.asBoolean ? '1' : '0';

        return 1;

    case LWM2M_TYPE_OBJECT_LINK:
    {
        char stringBuffer[11];
        size_t length;
        
        length = utils_intToText(dataP->value.asObjLink.objectId, (uint8_t*)stringBuffer, 5);
        if (length == 0) return -1;

        stringBuffer[5] = ':';
        res = length + 1;

        length = utils_intToText(dataP->value.asObjLink.objectInstanceId, (uint8_t*)stringBuffer + res, 5);
        if (length == 0) return -1;

        res += length;

        *bufferP = (uint8_t *)lwm2m_malloc(res);
        if (*bufferP == NULL) return -1;

        memcpy(*bufferP, stringBuffer, res);

        return res;
    }

    case LWM2M_TYPE_OPAQUE:
    {
        size_t length;

        length = utils_base64GetSize(dataP->value.asBuffer.length);
        *bufferP = (uint8_t *)lwm2m_malloc(length);
        if (*bufferP == NULL) return 0;
        length = utils_base64Encode(dataP->value.asBuffer.buffer, dataP->value.asBuffer.length, *bufferP, length);
        if (length == 0)
        {
            lwm2m_free(*bufferP);
            *bufferP = NULL;
            return 0;
        }
        return (int)length;
    }

    case LWM2M_TYPE_UNDEFINED:
    default:
        return -1;
    }
}
Esempio n. 11
0
static int prv_serializeLinkData(lwm2m_context_t * contextP,
                                 lwm2m_data_t * tlvP,
                                 lwm2m_uri_t * parentUriP,
                                 uint8_t * parentUriStr,
                                 size_t parentUriLen,
                                 uint8_t * buffer,
                                 size_t bufferLen)
{
    int head;
    int res;
    lwm2m_uri_t uri;

    head = 0;

    switch (tlvP->type)
    {
    case LWM2M_TYPE_UNDEFINED:
    case LWM2M_TYPE_STRING:
    case LWM2M_TYPE_OPAQUE:
    case LWM2M_TYPE_INTEGER:
    case LWM2M_TYPE_FLOAT:
    case LWM2M_TYPE_BOOLEAN:
    case LWM2M_TYPE_OBJECT_LINK:
    case LWM2M_TYPE_MULTIPLE_RESOURCE:
        if (bufferLen < LINK_ITEM_START_SIZE) return -1;
        memcpy(buffer + head, LINK_ITEM_START, LINK_ITEM_START_SIZE);
        head = LINK_ITEM_START_SIZE;

        if (parentUriLen > 0)
        {
            if (bufferLen - head < parentUriLen) return -1;
            memcpy(buffer + head, parentUriStr, parentUriLen);
            head += parentUriLen;
        }

        if (bufferLen - head < LINK_URI_SEPARATOR_SIZE) return -1;
        memcpy(buffer + head, LINK_URI_SEPARATOR, LINK_URI_SEPARATOR_SIZE);
        head += LINK_URI_SEPARATOR_SIZE;

        res = utils_intToText(tlvP->id, buffer + head, bufferLen - head);
        if (res <= 0) return -1;
        head += res;

        if (tlvP->type == LWM2M_TYPE_MULTIPLE_RESOURCE)
        {
            if (bufferLen - head < LINK_ITEM_DIM_START_SIZE) return -1;
            memcpy(buffer + head, LINK_ITEM_DIM_START, LINK_ITEM_DIM_START_SIZE);
            head += LINK_ITEM_DIM_START_SIZE;

            res = utils_intToText(tlvP->value.asChildren.count, buffer + head, bufferLen - head);
            if (res <= 0) return -1;
            head += res;

            if (bufferLen - head < LINK_ITEM_ATTR_END_SIZE) return -1;
            memcpy(buffer + head, LINK_ITEM_ATTR_END, LINK_ITEM_ATTR_END_SIZE);
            head += LINK_ITEM_ATTR_END_SIZE;
        }
        else
        {
            if (bufferLen - head < LINK_ITEM_END_SIZE) return -1;
            memcpy(buffer + head, LINK_ITEM_END, LINK_ITEM_END_SIZE);
            head += LINK_ITEM_END_SIZE;
        }

        memcpy(&uri, parentUriP, sizeof(lwm2m_uri_t));
        uri.resourceId = tlvP->id;
        uri.flag |= LWM2M_URI_FLAG_RESOURCE_ID;
        res = prv_serializeAttributes(contextP, &uri, buffer, head - 1, bufferLen);
        if (res < 0) return -1;    // careful, 0 is valid
        if (res > 0) head += res - 1;

        break;

    case LWM2M_TYPE_OBJECT_INSTANCE:
    {
        uint8_t uriStr[URI_MAX_STRING_LEN];
        size_t uriLen;
        size_t index;

        if (parentUriLen > 0)
        {
            if (URI_MAX_STRING_LEN < parentUriLen) return -1;
            memcpy(uriStr, parentUriStr, parentUriLen);
            uriLen = parentUriLen;
        }
        else
        {
            uriLen = 0;
        }

        if (URI_MAX_STRING_LEN - uriLen < LINK_URI_SEPARATOR_SIZE) return -1;
        memcpy(uriStr + uriLen, LINK_URI_SEPARATOR, LINK_URI_SEPARATOR_SIZE);
        uriLen += LINK_URI_SEPARATOR_SIZE;

        res = utils_intToText(tlvP->id, uriStr + uriLen, URI_MAX_STRING_LEN - uriLen);
        if (res <= 0) return -1;
        uriLen += res;

        memcpy(&uri, parentUriP, sizeof(lwm2m_uri_t));
        uri.instanceId = tlvP->id;
        uri.flag |= LWM2M_URI_FLAG_INSTANCE_ID;

        head = 0;
        PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ITEM_START, LINK_ITEM_START_SIZE);
        PRV_CONCAT_STR(buffer, bufferLen, head, uriStr, uriLen);
        PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ITEM_END, LINK_ITEM_END_SIZE);
        res = prv_serializeAttributes(contextP, &uri, buffer, head - 1, bufferLen);
        if (res < 0) return -1;    // careful, 0 is valid
        if (res == 0) head = 0;    // rewind
        else head += res - 1;

        for (index = 0; index < tlvP->value.asChildren.count; index++)
        {
            res = prv_serializeLinkData(contextP, tlvP->value.asChildren.array + index, &uri, uriStr, uriLen, buffer + head, bufferLen - head);
            if (res < 0) return -1;
            head += res;
        }
    }
    break;

    case LWM2M_TYPE_OBJECT:
    default:
        return -1;
    }

    return head;
}
Esempio n. 12
0
int json_serialize(lwm2m_uri_t * uriP,
                   int size,
                   lwm2m_data_t * tlvP,
                   uint8_t ** bufferP)
{
    int index;
    size_t head;
    uint8_t bufferJSON[PRV_JSON_BUFFER_SIZE];
    uint8_t baseUriStr[URI_MAX_STRING_LEN];
    int baseUriLen;
    uri_depth_t rootLevel;
    int num;
    lwm2m_data_t * targetP;

    LOG_ARG("size: %d", size);
    LOG_URI(uriP);
    if (size != 0 && tlvP == NULL) return -1;

    baseUriLen = uri_toString(uriP, baseUriStr, URI_MAX_STRING_LEN, &rootLevel);
    if (baseUriLen < 0) return -1;

    num = prv_findAndCheckData(uriP, rootLevel, size, tlvP, &targetP);
    if (num < 0) return -1;

    while (num == 1
        && (targetP->type == LWM2M_TYPE_OBJECT
         || targetP->type == LWM2M_TYPE_OBJECT_INSTANCE
         || targetP->type == LWM2M_TYPE_MULTIPLE_RESOURCE))
    {
        int res;

        res = utils_intToText(targetP->id, baseUriStr + baseUriLen, URI_MAX_STRING_LEN - baseUriLen);
        if (res <= 0) return 0;
        baseUriLen += res;
        if (baseUriLen >= URI_MAX_STRING_LEN -1) return 0;
        num = targetP->value.asChildren.count;
        targetP = targetP->value.asChildren.array;
        baseUriStr[baseUriLen] = '/';
        baseUriLen++;
    }

    if (baseUriLen > 0)
    {
        memcpy(bufferJSON, JSON_BN_HEADER_1, JSON_BN_HEADER_1_SIZE);
        head = JSON_BN_HEADER_1_SIZE;
        memcpy(bufferJSON + head, baseUriStr, baseUriLen);
        head += baseUriLen;
        memcpy(bufferJSON + head, JSON_BN_HEADER_2, JSON_BN_HEADER_2_SIZE);
        head += JSON_BN_HEADER_2_SIZE;
    }
    else
    {
        memcpy(bufferJSON, JSON_HEADER, JSON_HEADER_SIZE);
        head = JSON_HEADER_SIZE;
    }

    for (index = 0 ; index < num && head < PRV_JSON_BUFFER_SIZE ; index++)
    {
        int res;

        res = prv_serializeData(targetP + index, NULL, 0, bufferJSON + head, PRV_JSON_BUFFER_SIZE - head);
        if (res < 0) return res;
        head += res;
    }

    if (head + JSON_FOOTER_SIZE - 1 > PRV_JSON_BUFFER_SIZE) return 0;

    if (num > 0) head = head - 1;

    memcpy(bufferJSON + head, JSON_FOOTER, JSON_FOOTER_SIZE);
    head = head + JSON_FOOTER_SIZE;

    *bufferP = (uint8_t *)lwm2m_malloc(head);
    if (*bufferP == NULL) return -1;
    memcpy(*bufferP, bufferJSON, head);

    return head;
}
Esempio n. 13
0
int prv_serializeData(lwm2m_data_t * tlvP,
                      uint8_t * parentUriStr,
                      size_t parentUriLen,
                      uint8_t * buffer,
                      size_t bufferLen)
{
    int head;
    int res;

    head = 0;

    switch (tlvP->type)
    {
    case LWM2M_TYPE_OBJECT:
    case LWM2M_TYPE_OBJECT_INSTANCE:
    case LWM2M_TYPE_MULTIPLE_RESOURCE:
    {
        uint8_t uriStr[URI_MAX_STRING_LEN];
        size_t uriLen;
        size_t index;

        if (parentUriLen > 0)
        {
            if (URI_MAX_STRING_LEN < parentUriLen) return -1;
            memcpy(uriStr, parentUriStr, parentUriLen);
            uriLen = parentUriLen;
        }
        else
        {
            uriLen = 0;
        }
        res = utils_intToText(tlvP->id, uriStr + uriLen, URI_MAX_STRING_LEN - uriLen);
        if (res <= 0) return -1;
        uriLen += res;
        uriStr[uriLen] = '/';
        uriLen++;

        head = 0;
        for (index = 0 ; index < tlvP->value.asChildren.count; index++)
        {
            res = prv_serializeData(tlvP->value.asChildren.array + index, uriStr, uriLen, buffer + head, bufferLen - head);
            if (res < 0) return -1;
            head += res;
        }
    }
    break;

    default:
        if (bufferLen < JSON_RES_ITEM_URI_SIZE) return -1;
        memcpy(buffer, JSON_RES_ITEM_URI, JSON_RES_ITEM_URI_SIZE);
        head = JSON_RES_ITEM_URI_SIZE;

        if (parentUriLen > 0)
        {
            if (bufferLen - head < parentUriLen) return -1;
            memcpy(buffer + head, parentUriStr, parentUriLen);
            head += parentUriLen;
        }

        res = utils_intToText(tlvP->id, buffer + head, bufferLen - head);
        if (res <= 0) return -1;
        head += res;

        res = prv_serializeValue(tlvP, buffer + head, bufferLen - head);
        if (res < 0) return -1;
        head += res;
        break;
    }

    return head;
}
Esempio n. 14
0
static int prv_serializeValue(lwm2m_data_t * tlvP,
                              uint8_t * buffer,
                              size_t bufferLen)
{
    int res;
    int head;

    switch (tlvP->type)
    {
    case LWM2M_TYPE_STRING:
        if (bufferLen < JSON_ITEM_STRING_BEGIN_SIZE) return -1;
        memcpy(buffer, JSON_ITEM_STRING_BEGIN, JSON_ITEM_STRING_BEGIN_SIZE);
        head = JSON_ITEM_STRING_BEGIN_SIZE;

        if (bufferLen - head < tlvP->value.asBuffer.length) return -1;
        memcpy(buffer + head, tlvP->value.asBuffer.buffer, tlvP->value.asBuffer.length);
        head += tlvP->value.asBuffer.length;

        if (bufferLen - head < JSON_ITEM_STRING_END_SIZE) return -1;
        memcpy(buffer + head, JSON_ITEM_STRING_END, JSON_ITEM_STRING_END_SIZE);
        head += JSON_ITEM_STRING_END_SIZE;

        break;

    case LWM2M_TYPE_INTEGER:
    {
        int64_t value;

        if (0 == lwm2m_data_decode_int(tlvP, &value)) return -1;

        if (bufferLen < JSON_ITEM_NUM_SIZE) return -1;
        memcpy(buffer, JSON_ITEM_NUM, JSON_ITEM_NUM_SIZE);
        head = JSON_ITEM_NUM_SIZE;

        res = utils_intToText(value, buffer + head, bufferLen - head);
        if (res <= 0) return -1;
        head += res;

        if (bufferLen - head < JSON_ITEM_NUM_END_SIZE) return -1;
        memcpy(buffer + head, JSON_ITEM_NUM_END, JSON_ITEM_NUM_END_SIZE);
        head += JSON_ITEM_NUM_END_SIZE;
    }
    break;

    case LWM2M_TYPE_FLOAT:
    {
        double value;

        if (0 == lwm2m_data_decode_float(tlvP, &value)) return -1;

        if (bufferLen < JSON_ITEM_NUM_SIZE) return -1;
        memcpy(buffer, JSON_ITEM_NUM, JSON_ITEM_NUM_SIZE);
        head = JSON_ITEM_NUM_SIZE;

        res = utils_floatToText(value, buffer + head, bufferLen - head);
        if (res <= 0) return -1;
        head += res;

        if (bufferLen - head < JSON_ITEM_NUM_END_SIZE) return -1;
        memcpy(buffer + head, JSON_ITEM_NUM_END, JSON_ITEM_NUM_END_SIZE);
        head += JSON_ITEM_NUM_END_SIZE;
    }
    break;

    case LWM2M_TYPE_BOOLEAN:
    {
        bool value;

        if (0 == lwm2m_data_decode_bool(tlvP, &value)) return -1;

        if (value == true)
        {
            if (bufferLen < JSON_ITEM_BOOL_TRUE_SIZE) return -1;
            memcpy(buffer, JSON_ITEM_BOOL_TRUE, JSON_ITEM_BOOL_TRUE_SIZE);
            head = JSON_ITEM_BOOL_TRUE_SIZE;
        }
        else
        {
            if (bufferLen < JSON_ITEM_BOOL_FALSE_SIZE) return -1;
            memcpy(buffer, JSON_ITEM_BOOL_FALSE, JSON_ITEM_BOOL_FALSE_SIZE);
            head = JSON_ITEM_BOOL_FALSE_SIZE;
        }
    }
    break;

    case LWM2M_TYPE_OPAQUE:
        if (bufferLen < JSON_ITEM_STRING_BEGIN_SIZE) return -1;
        memcpy(buffer, JSON_ITEM_STRING_BEGIN, JSON_ITEM_STRING_BEGIN_SIZE);
        head = JSON_ITEM_STRING_BEGIN_SIZE;

        res = utils_base64Encode(tlvP->value.asBuffer.buffer, tlvP->value.asBuffer.length, buffer+head, bufferLen - head);
        if (tlvP->value.asBuffer.length != 0 && res == 0) return -1;
        head += res;

        if (bufferLen - head < JSON_ITEM_STRING_END_SIZE) return -1;
        memcpy(buffer + head, JSON_ITEM_STRING_END, JSON_ITEM_STRING_END_SIZE);
        head += JSON_ITEM_STRING_END_SIZE;
        break;

    case LWM2M_TYPE_OBJECT_LINK:
        // TODO: implement
        return -1;

    default:
        return -1;
    }

    return head;
}
Esempio n. 15
0
static int prv_serializeData(const lwm2m_data_t * tlvP,
                             const uint8_t * baseUriStr,
                             size_t baseUriLen,
                             uri_depth_t baseLevel,
                             const uint8_t * parentUriStr,
                             size_t parentUriLen,
                             uri_depth_t level,
                             bool *baseNameOutput,
                             uint8_t * buffer,
                             size_t bufferLen)
{
    size_t head;
    int res;

    head = 0;

    /* Check to override passed in level */
    switch (tlvP->type)
    {
    case LWM2M_TYPE_MULTIPLE_RESOURCE:
        level = URI_DEPTH_RESOURCE;
        break;
    case LWM2M_TYPE_OBJECT:
        level = URI_DEPTH_OBJECT;
        break;
    case LWM2M_TYPE_OBJECT_INSTANCE:
        level = URI_DEPTH_OBJECT_INSTANCE;
        break;
    default:
        break;
    }

    switch (tlvP->type)
    {
    case LWM2M_TYPE_MULTIPLE_RESOURCE:
    case LWM2M_TYPE_OBJECT:
    case LWM2M_TYPE_OBJECT_INSTANCE:
    {
        uint8_t uriStr[URI_MAX_STRING_LEN];
        size_t uriLen;
        size_t index;

        if (parentUriLen > 0)
        {
            if (URI_MAX_STRING_LEN < parentUriLen) return -1;
            memcpy(uriStr, parentUriStr, parentUriLen);
            uriLen = parentUriLen;
        }
        else
        {
            uriLen = 0;
        }
        res = utils_intToText(tlvP->id,
                              uriStr + uriLen,
                              URI_MAX_STRING_LEN - uriLen);
        if (res <= 0) return -1;
        uriLen += res;
        uriStr[uriLen] = '/';
        uriLen++;

        head = 0;
        for (index = 0 ; index < tlvP->value.asChildren.count; index++)
        {
            if (index != 0)
            {
                if (head + 1 > bufferLen) return 0;
                buffer[head++] = JSON_SEPARATOR;
            }

            res = prv_serializeData(tlvP->value.asChildren.array + index,
                                    baseUriStr,
                                    baseUriLen,
                                    baseLevel,
                                    uriStr,
                                    uriLen,
                                    level,
                                    baseNameOutput,
                                    buffer + head,
                                    bufferLen - head);
            if (res < 0) return -1;
            head += res;
        }
    }
    break;

    default:
        head = 0;
        if (bufferLen < 1) return -1;
        buffer[head++] = JSON_ITEM_BEGIN;

        if (!*baseNameOutput && baseUriLen > 0)
        {
            if (bufferLen - head < baseUriLen + JSON_BN_HEADER_SIZE + 2) return -1;
            memcpy(buffer + head, JSON_BN_HEADER, JSON_BN_HEADER_SIZE);
            head += JSON_BN_HEADER_SIZE;
            memcpy(buffer + head, baseUriStr, baseUriLen);
            head += baseUriLen;
            buffer[head++] = JSON_ITEM_STRING_END;
            buffer[head++] = JSON_SEPARATOR;
            *baseNameOutput = true;
        }

        /* TODO: support base time */

        if (!baseUriLen || level > baseLevel)
        {
            if (bufferLen - head < JSON_ITEM_URI_SIZE) return -1;
            memcpy(buffer + head, JSON_ITEM_URI, JSON_ITEM_URI_SIZE);
            head += JSON_ITEM_URI_SIZE;

            if (parentUriLen > 0)
            {
                if (bufferLen - head < parentUriLen) return -1;
                memcpy(buffer + head, parentUriStr, parentUriLen);
                head += parentUriLen;
            }

            res = utils_intToText(tlvP->id, buffer + head, bufferLen - head);
            if (res <= 0) return -1;
            head += res;

            if (bufferLen - head < 2) return -1;
            buffer[head++] = JSON_ITEM_URI_END;
            if (tlvP->type != LWM2M_TYPE_UNDEFINED)
            {
                buffer[head++] = JSON_SEPARATOR;
            }
        }

        if (tlvP->type != LWM2M_TYPE_UNDEFINED)
        {
            res = prv_serializeValue(tlvP, buffer + head, bufferLen - head);
            if (res < 0) return -1;
            head += res;
        }

        /* TODO: support time */

        if (bufferLen - head < 1) return -1;
        buffer[head++] = JSON_ITEM_END;

        break;
    }

    return (int)head;
}
Esempio n. 16
0
static int prv_serializeValue(const lwm2m_data_t * tlvP,
                              uint8_t * buffer,
                              size_t bufferLen)
{
    size_t res;
    size_t head;

    switch (tlvP->type)
    {
    case LWM2M_TYPE_STRING:
    case LWM2M_TYPE_CORE_LINK:
        if (bufferLen < JSON_ITEM_STRING_BEGIN_SIZE) return -1;
        memcpy(buffer, JSON_ITEM_STRING_BEGIN, JSON_ITEM_STRING_BEGIN_SIZE);
        head = JSON_ITEM_STRING_BEGIN_SIZE;

        res = json_escapeString(buffer + head,
                                bufferLen - head,
                                tlvP->value.asBuffer.buffer,
                                tlvP->value.asBuffer.length);
        if (!res) return -1;
        head += res;

        if (bufferLen - head < 1) return -1;
        buffer[head++] = JSON_ITEM_STRING_END;

        break;

    case LWM2M_TYPE_INTEGER:
    {
        int64_t value;

        if (0 == lwm2m_data_decode_int(tlvP, &value)) return -1;

        if (bufferLen < JSON_ITEM_NUM_SIZE) return -1;
        memcpy(buffer, JSON_ITEM_NUM, JSON_ITEM_NUM_SIZE);
        head = JSON_ITEM_NUM_SIZE;

        res = utils_intToText(value, buffer + head, bufferLen - head);
        if (!res) return -1;
        head += res;
    }
    break;

    case LWM2M_TYPE_UNSIGNED_INTEGER:
    {
        uint64_t value;

        if (0 == lwm2m_data_decode_uint(tlvP, &value)) return -1;

        if (bufferLen < JSON_ITEM_NUM_SIZE) return -1;
        memcpy(buffer, JSON_ITEM_NUM, JSON_ITEM_NUM_SIZE);
        head = JSON_ITEM_NUM_SIZE;

        res = utils_uintToText(value, buffer + head, bufferLen - head);
        if (!res) return -1;
        head += res;
    }
    break;

    case LWM2M_TYPE_FLOAT:
    {
        double value;

        if (0 == lwm2m_data_decode_float(tlvP, &value)) return -1;

        if (bufferLen < JSON_ITEM_NUM_SIZE) return -1;
        memcpy(buffer, JSON_ITEM_NUM, JSON_ITEM_NUM_SIZE);
        head = JSON_ITEM_NUM_SIZE;

        res = utils_floatToText(value, buffer + head, bufferLen - head);
        if (!res) return -1;
        head += res;
    }
    break;

    case LWM2M_TYPE_BOOLEAN:
    {
        bool value;

        if (0 == lwm2m_data_decode_bool(tlvP, &value)) return -1;

        if (value)
        {
            if (bufferLen < JSON_ITEM_BOOL_SIZE + JSON_TRUE_STRING_SIZE) return -1;
            memcpy(buffer,
                   JSON_ITEM_BOOL JSON_TRUE_STRING,
                   JSON_ITEM_BOOL_SIZE + JSON_TRUE_STRING_SIZE);
            head = JSON_ITEM_BOOL_SIZE + JSON_TRUE_STRING_SIZE;
        }
        else
        {
            if (bufferLen < JSON_ITEM_BOOL_SIZE + JSON_FALSE_STRING_SIZE) return -1;
            memcpy(buffer,
                   JSON_ITEM_BOOL JSON_FALSE_STRING,
                   JSON_ITEM_BOOL_SIZE + JSON_FALSE_STRING_SIZE);
            head = JSON_ITEM_BOOL_SIZE + JSON_FALSE_STRING_SIZE;
        }
    }
    break;

    case LWM2M_TYPE_OPAQUE:
        if (bufferLen < JSON_ITEM_OPAQUE_BEGIN_SIZE) return -1;
        memcpy(buffer, JSON_ITEM_OPAQUE_BEGIN, JSON_ITEM_OPAQUE_BEGIN_SIZE);
        head = JSON_ITEM_OPAQUE_BEGIN_SIZE;

        if (tlvP->value.asBuffer.length > 0)
        {
            res = utils_base64Encode(tlvP->value.asBuffer.buffer,
                                     tlvP->value.asBuffer.length,
                                     buffer+head,
                                     bufferLen - head);
            if (!res) return -1;
            head += res;
        }

        if (bufferLen - head < 1) return -1;
        buffer[head++] = JSON_ITEM_OPAQUE_END;
        break;

    case LWM2M_TYPE_OBJECT_LINK:
        if (bufferLen < JSON_ITEM_OBJECT_LINK_BEGIN_SIZE) return -1;
        memcpy(buffer,
               JSON_ITEM_OBJECT_LINK_BEGIN,
               JSON_ITEM_OBJECT_LINK_BEGIN_SIZE);
        head = JSON_ITEM_OBJECT_LINK_BEGIN_SIZE;

        res = utils_objLinkToText(tlvP->value.asObjLink.objectId,
                                  tlvP->value.asObjLink.objectInstanceId,
                                  buffer + head,
                                  bufferLen - head);
        if (!res) return -1;
        head += res;

        if (bufferLen - head < 1) return -1;
        buffer[head++] = JSON_ITEM_OBJECT_LINK_END;
        break;

    default:
        return -1;
    }

    return (int)head;
}