Esempio n. 1
0
uint8_t bootstrap_handleRequest(lwm2m_context_t * contextP,
                                lwm2m_uri_t * uriP,
                                void * fromSessionH,
                                coap_packet_t * message,
                                coap_packet_t * response)
{
    uint8_t result;
    char * name;

    LOG_URI(uriP);
    if (contextP->bootstrapCallback == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
    if (message->code != COAP_POST) return COAP_400_BAD_REQUEST;
    if (message->uri_query == NULL) return COAP_400_BAD_REQUEST;
    if (message->payload != NULL) return COAP_400_BAD_REQUEST;

    if (lwm2m_strncmp((char *)message->uri_query->data, QUERY_NAME, QUERY_NAME_LEN) != 0)
    {
        return COAP_400_BAD_REQUEST;
    }

    if (message->uri_query->len == QUERY_NAME_LEN) return COAP_400_BAD_REQUEST;
    if (message->uri_query->next != NULL) return COAP_400_BAD_REQUEST;

    name = (char *)lwm2m_malloc(message->uri_query->len - QUERY_NAME_LEN + 1);
    if (name == NULL) return COAP_500_INTERNAL_SERVER_ERROR;

    memcpy(name, message->uri_query->data + QUERY_NAME_LEN, message->uri_query->len - QUERY_NAME_LEN);
    name[message->uri_query->len - QUERY_NAME_LEN] = 0;

    result = contextP->bootstrapCallback(fromSessionH, COAP_NO_ERROR, NULL, name, contextP->bootstrapUserData);

    lwm2m_free(name);

    return result;
}
Esempio n. 2
0
static lwm2m_client_object_t * prv_decodeRegisterPayload(uint8_t * payload,
                                                         uint16_t payloadLength,
                                                         char ** altPath)
{
    lwm2m_client_object_t * objList;
    uint16_t id;
    uint16_t instance;
    uint16_t start;
    uint16_t end;
    int result;
    uint16_t altPathStart;
    uint16_t altPathEnd;
    uint16_t altPathLen;

    objList = NULL;
    start = 0;
    altPathStart = 0;
    altPathEnd = 0;
    altPathLen = 0;
    *altPath = NULL;

    // Does the registration payload begin with an alternative path ?
    while (start < payloadLength && payload[start] == ' ') start++;
    if (start != payloadLength)
    {
        if (payload[start] == '<')
        {
            altPathStart = start + 1;
        }
        while (start < payloadLength - 1 && payload[start] != '>') start++;
        if (start != payloadLength - 1)
        {
            altPathEnd = start - 1;
            if ((payloadLength > altPathEnd + REG_LWM2M_RESOURCE_TYPE_LEN)
             && (0 == lwm2m_strncmp(REG_LWM2M_RESOURCE_TYPE, (char *) payload + altPathEnd + 1, REG_LWM2M_RESOURCE_TYPE_LEN)))
            {
                payload[altPathEnd + 1] = 0;
                *altPath = lwm2m_strdup((char *)payload + altPathStart);
                if (*altPath == NULL) return NULL;
                if (0 == prv_isAltPathValid(*altPath))
                {
                    return NULL;
                }
                altPathLen = altPathEnd - altPathStart + 1;
            }
        }
    }

    if (altPathLen != 0)
    {
        start = altPathEnd + 1 + REG_LWM2M_RESOURCE_TYPE_LEN;
        // If declared alternative path is "/", use NULL instead
        if (altPathLen == 1)
        {
            lwm2m_free(*altPath);
            *altPath = NULL;
        }
    }
    else
    {
        start = 0;
    }

    while (start < payloadLength)
    {
        while (start < payloadLength && payload[start] == ' ') start++;
        if (start == payloadLength) return objList;
        end = start;
        while (end < payloadLength && payload[end] != ',') end++;
        result = prv_getId(payload + start, end - start, *altPath, altPathLen, &id, &instance);
        if (result != 0)
        {
            lwm2m_client_object_t * objectP;

            objectP = (lwm2m_client_object_t *)lwm2m_list_find((lwm2m_list_t *)objList, id);
            if (objectP == NULL)
            {
                objectP = (lwm2m_client_object_t *)lwm2m_malloc(sizeof(lwm2m_client_object_t));
                memset(objectP, 0, sizeof(lwm2m_client_object_t));
                if (objectP == NULL) return objList;
                objectP->id = id;
                objList = (lwm2m_client_object_t *)LWM2M_LIST_ADD(objList, objectP);
            }
            if (result == 2)
            {
                lwm2m_list_t * instanceP;

                instanceP = lwm2m_list_find(objectP->instanceList, instance);
                if (instanceP == NULL)
                {
                    instanceP = (lwm2m_list_t *)lwm2m_malloc(sizeof(lwm2m_list_t));
                    memset(instanceP, 0, sizeof(lwm2m_list_t));
                    instanceP->id = instance;
                    objectP->instanceList = LWM2M_LIST_ADD(objectP->instanceList, instanceP);
                }
            }
        }
        start = end + 1;
    }

    return objList;
}
Esempio n. 3
0
static int prv_getId(uint8_t * data,
                     uint16_t length,
                     char * altPath,
                     uint16_t altPathLen,
                     uint16_t * objId,
                     uint16_t * instanceId)
{
    int value;
    uint16_t limit;
    uint16_t end;

    // Expecting application/link-format (RFC6690)
    // strip open and close tags
    if (length >= 1 && data[0] == '<' && data[length-1] == '>')
    {
        data++;
        length-=2;
    } 
    else
    {
        return 0;
    }

    if (altPath != NULL)
    {
        if (length <= altPathLen) return 0;
        if (0 != lwm2m_strncmp((char *)data, altPath, altPathLen)) return 0;
        data += altPathLen;
        length -= altPathLen;
    }

    // If there is a preceding /, remove it
    if (length >= 1 && data[0] == '/')
    {
        data++;
        length-=1;
    }

    limit = 0;
    while (limit < length && data[limit] != '/' && data[limit] != ' ') limit++;
    value = prv_get_number(data, limit);
    if (value < 0 || value >= LWM2M_MAX_ID) return 0;
    *objId = value;

    if (limit != length)
    {
        limit += 1;
        end = limit;
        while (end < length && data[end] != ' ') end++;
        if (end != limit)
        {
            value = prv_get_number(data + limit, end - limit);
            if (value >= 0 && value < LWM2M_MAX_ID)
            {
                *instanceId = value;
                return 2;
            }
        }
    }

    return 1;
}
Esempio n. 4
0
static int prv_getParameters(multi_option_t * query,
                             char ** nameP,
                             uint32_t * lifetimeP,
                             char ** msisdnP,
                             lwm2m_binding_t * bindingP)
{
    *nameP = NULL;
    *lifetimeP = 0;
    *msisdnP = NULL;
    *bindingP = BINDING_UNKNOWN;

    while (query != NULL)
    {
        if (lwm2m_strncmp((char *)query->data, QUERY_TEMPLATE, QUERY_LENGTH) == 0)
        {
            if (*nameP != NULL) goto error;
            if (query->len == QUERY_LENGTH) goto error;

            *nameP = (char *)lwm2m_malloc(query->len - QUERY_LENGTH + 1);
            if (*nameP != NULL)
            {
                memcpy(*nameP, query->data + QUERY_LENGTH, query->len - QUERY_LENGTH);
                (*nameP)[query->len - QUERY_LENGTH] = 0;
            }
        }
        else if (lwm2m_strncmp((char *)query->data, QUERY_SMS, QUERY_SMS_LEN) == 0)
        {
            if (*msisdnP != NULL) goto error;
            if (query->len == QUERY_SMS_LEN) goto error;

            *msisdnP = (char *)lwm2m_malloc(query->len - QUERY_SMS_LEN + 1);
            if (*msisdnP != NULL)
            {
                memcpy(*msisdnP, query->data + QUERY_SMS_LEN, query->len - QUERY_SMS_LEN);
                (*msisdnP)[query->len - QUERY_SMS_LEN] = 0;
            }
        }
        else if (lwm2m_strncmp((char *)query->data, QUERY_LIFETIME, QUERY_LIFETIME_LEN) == 0)
        {
            int i;

            if (*lifetimeP != 0) goto error;
            if (query->len == QUERY_LIFETIME_LEN) goto error;

            for (i = QUERY_LIFETIME_LEN ; i < query->len ; i++)
            {
                if (query->data[i] < '0' || query->data[i] > '9') goto error;
                *lifetimeP = (*lifetimeP * 10) + (query->data[i] - '0');
            }
        }
        else if (lwm2m_strncmp((char *)query->data, QUERY_VERSION, QUERY_VERSION_LEN) == 0)
        {
            if ((query->len != QUERY_VERSION_FULL_LEN)
             || (lwm2m_strncmp((char *)query->data, QUERY_VERSION_FULL, QUERY_VERSION_FULL_LEN) != 0))
            {
                goto error;
            }
        }
        else if (lwm2m_strncmp((char *)query->data, QUERY_BINDING, QUERY_BINDING_LEN) == 0)
        {
            if (*bindingP != BINDING_UNKNOWN) goto error;
            if (query->len == QUERY_BINDING_LEN) goto error;

            *bindingP = lwm2m_stringToBinding(query->data + QUERY_BINDING_LEN, query->len - QUERY_BINDING_LEN);
        }
        query = query->next;
    }

    return 0;

error:
    if (*nameP != NULL) lwm2m_free(*nameP);
    if (*msisdnP != NULL) lwm2m_free(*msisdnP);

    return -1;
}
Esempio n. 5
0
static int prv_parseItem(uint8_t * buffer,
                         size_t bufferLen,
                         _record_t * recordP)
{
    size_t index;

    recordP->resId = LWM2M_MAX_ID;
    recordP->resInstId = LWM2M_MAX_ID;
    recordP->type = _TYPE_UNSET;
    recordP->value = NULL;
    recordP->valueLen = 0;

    index = 0;
    do
    {
        int tokenStart;
        int tokenLen;
        int valueStart;
        int valueLen;
        int next;

        next = prv_split(buffer+index, bufferLen-index, &tokenStart, &tokenLen, &valueStart, &valueLen);
        if (next < 0) return -1;

        switch (tokenLen)
        {
        case 1:
        {
            switch (buffer[index+tokenStart])
            {
            case 'n':
            {
                int i;
                uint32_t readId;

                if (recordP->resId != LWM2M_MAX_ID) return -1;

                // Check for " around URI
                if (valueLen < 3
                 || buffer[index+valueStart] != '"'
                 || buffer[index+valueStart+valueLen-1] != '"')
                {
                    return -1;
                }
                i = 1;
                readId = 0;
                while (i < valueLen-1 && buffer[index+valueStart+i] != '/')
                {
                    if (buffer[index+valueStart+i] < '0'
                     || buffer[index+valueStart+i] > '9')
                    {
                        return -1;
                    }
                    readId *= 10;
                    readId += buffer[index+valueStart+i] - '0';
                    if (readId > LWM2M_MAX_ID) return -1;
                    i++;
                }
                recordP->resId = readId;
                if (buffer[index+valueStart+i] == '/')
                {
                    int j;

                    if (i == valueLen-1) return -1;

                    j = 1;
                    readId = 0;
                    while (i+j < valueLen-1)
                    {
                        if (buffer[index+valueStart+i+j] < '0'
                         || buffer[index+valueStart+i+j] > '9')
                        {
                            return -1;
                        }
                        readId *= 10;
                        readId += buffer[index+valueStart+i+j] - '0';
                        if (readId > LWM2M_MAX_ID) return -1;
                        i++;
                    }
                    recordP->resInstId = readId;
                }
                // TODO: support more URIs than just res and res/instance
            }
            break;

            case 'v':
                if (recordP->type != _TYPE_UNSET) return -1;
                recordP->type = _TYPE_FLOAT;
                recordP->value = buffer + index + valueStart;
                recordP->valueLen = valueLen;
                break;

            case 't':
                // TODO: support time
                break;

            default:
                return -1;
            }
        }
        break;

        case 2:
        {
            // "bv", "ov", or "sv"
            if (buffer[index+tokenStart+1] != 'v') return -1;
            switch (buffer[index+tokenStart])
            {
            case 'b':
                if (recordP->type != _TYPE_UNSET) return -1;
                if (0 == lwm2m_strncmp(JSON_TRUE_STRING, (char *)buffer + index + valueStart, valueLen))
                {
                    recordP->type = _TYPE_TRUE;
                }
                else if (0 == lwm2m_strncmp(JSON_FALSE_STRING, (char *)buffer + index + valueStart, valueLen))
                {
                    recordP->type = _TYPE_FALSE;
                }
                else
                {
                    return -1;
                }
                break;

            case 'o':
                if (recordP->type != _TYPE_UNSET) return -1;
                // TODO: support object link
                break;

            case 's':
                if (recordP->type != _TYPE_UNSET) return -1;
                // Check for " around value
                if (valueLen < 2
                 || buffer[index+valueStart] != '"'
                 || buffer[index+valueStart+valueLen-1] != '"')
                {
                    return -1;
                }
                recordP->type = _TYPE_STRING;
                recordP->value = buffer + index + valueStart + 1;
                recordP->valueLen = valueLen - 2;
                break;

            default:
                return -1;
            }
        }
        break;

        default:
            return -1;
        }

        index += next + 1;
    } while (index < bufferLen);

    return 0;
}
Esempio n. 6
0
static int prv_readAttributes(multi_option_t * query,
                              lwm2m_attributes_t * attrP)
{
    int64_t intValue;
    double floatValue;

    memset(attrP, 0, sizeof(lwm2m_attributes_t));

    while (query != NULL)
    {
        if (lwm2m_strncmp((char *)query->data, ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN) == 0)
        {
            if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_MIN_PERIOD)) return -1;
            if (query->len == ATTR_MIN_PERIOD_LEN) return -1;

            if (1 != utils_textToInt(query->data + ATTR_MIN_PERIOD_LEN, query->len - ATTR_MIN_PERIOD_LEN, &intValue)) return -1;
            if (intValue < 0) return -1;

            attrP->toSet |= LWM2M_ATTR_FLAG_MIN_PERIOD;
            attrP->minPeriod = intValue;
        }
        else if (lwm2m_strncmp((char *)query->data, ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN - 1) == 0)
        {
            if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_MIN_PERIOD)) return -1;
            if (query->len != ATTR_MIN_PERIOD_LEN - 1) return -1;

            attrP->toClear |= LWM2M_ATTR_FLAG_MIN_PERIOD;
        }
        else if (lwm2m_strncmp((char *)query->data, ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN) == 0)
        {
            if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_MAX_PERIOD)) return -1;
            if (query->len == ATTR_MAX_PERIOD_LEN) return -1;

            if (1 != utils_textToInt(query->data + ATTR_MAX_PERIOD_LEN, query->len - ATTR_MAX_PERIOD_LEN, &intValue)) return -1;
            if (intValue < 0) return -1;

            attrP->toSet |= LWM2M_ATTR_FLAG_MAX_PERIOD;
            attrP->maxPeriod = intValue;
        }
        else if (lwm2m_strncmp((char *)query->data, ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN - 1) == 0)
        {
            if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_MAX_PERIOD)) return -1;
            if (query->len != ATTR_MAX_PERIOD_LEN - 1) return -1;

            attrP->toClear |= LWM2M_ATTR_FLAG_MAX_PERIOD;
        }
        else if (lwm2m_strncmp((char *)query->data, ATTR_GREATER_THAN_STR, ATTR_GREATER_THAN_LEN) == 0)
        {
            if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_GREATER_THAN)) return -1;
            if (query->len == ATTR_GREATER_THAN_LEN) return -1;

            if (1 != utils_textToFloat(query->data + ATTR_GREATER_THAN_LEN, query->len - ATTR_GREATER_THAN_LEN, &floatValue)) return -1;

            attrP->toSet |= LWM2M_ATTR_FLAG_GREATER_THAN;
            attrP->greaterThan = floatValue;
        }
        else if (lwm2m_strncmp((char *)query->data, ATTR_GREATER_THAN_STR, ATTR_GREATER_THAN_LEN - 1) == 0)
        {
            if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_GREATER_THAN)) return -1;
            if (query->len != ATTR_GREATER_THAN_LEN - 1) return -1;

            attrP->toClear |= LWM2M_ATTR_FLAG_GREATER_THAN;
        }
        else if (lwm2m_strncmp((char *)query->data, ATTR_LESS_THAN_STR, ATTR_LESS_THAN_LEN) == 0)
        {
            if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_LESS_THAN)) return -1;
            if (query->len == ATTR_LESS_THAN_LEN) return -1;

            if (1 != utils_textToFloat(query->data + ATTR_LESS_THAN_LEN, query->len - ATTR_LESS_THAN_LEN, &floatValue)) return -1;

            attrP->toSet |= LWM2M_ATTR_FLAG_LESS_THAN;
            attrP->lessThan = floatValue;
        }
        else if (lwm2m_strncmp((char *)query->data, ATTR_LESS_THAN_STR, ATTR_LESS_THAN_LEN - 1) == 0)
        {
            if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_LESS_THAN)) return -1;
            if (query->len != ATTR_LESS_THAN_LEN - 1) return -1;

            attrP->toClear |= LWM2M_ATTR_FLAG_LESS_THAN;
        }
        else if (lwm2m_strncmp((char *)query->data, ATTR_STEP_STR, ATTR_STEP_LEN) == 0)
        {
            if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_STEP)) return -1;
            if (query->len == ATTR_STEP_LEN) return -1;

            if (1 != utils_textToFloat(query->data + ATTR_STEP_LEN, query->len - ATTR_STEP_LEN, &floatValue)) return -1;
            if (floatValue < 0) return -1;

            attrP->toSet |= LWM2M_ATTR_FLAG_STEP;
            attrP->step = floatValue;
        }
        else if (lwm2m_strncmp((char *)query->data, ATTR_STEP_STR, ATTR_STEP_LEN - 1) == 0)
        {
            if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_STEP)) return -1;
            if (query->len != ATTR_STEP_LEN - 1) return -1;

            attrP->toClear |= LWM2M_ATTR_FLAG_STEP;
        }
        else return -1;

        query = query->next;
    }

    return 0;
}
Esempio n. 7
0
static int prv_parseLinkAttributes(uint8_t * data,
                                   uint16_t length,
                                   bool * supportJSON,
                                   char ** altPath)
{
    uint16_t index;
    uint16_t pathStart;
    uint16_t pathLength;
    bool isValid;

    isValid = false;

    // Expecting application/link-format (RFC6690)
    // leading space were removed before. Remove trailing spaces.
    while (length > 0 && data[length-1] == ' ') length--;

    // strip open tag
    if (length >= 2 && data[0] == REG_URI_START)
    {
        data += 1;
        length -= 1;
    }
    else
    {
        return 0;
    }

    pathStart = 0;
    index = length - 1;
    while (index > 0 && data[index] != REG_URI_END) index--;
    // link attributes are required
    if (index == 0 || index == length - 1) return 0;

    // If there is a preceding /, remove it
    if (data[pathStart] == '/')
    {
        pathStart += 1;
    }
    pathLength = index - pathStart;

    index++;
    if (index >= length || data[index] != REG_ATTR_SEPARATOR) return 0;
    index++;

    while (index < length)
    {
        uint16_t result;
        uint16_t keyStart;
        uint16_t keyLength;
        uint16_t valueStart;
        uint16_t valueLength;

        result = prv_splitLinkAttribute(data + index, length - index, &keyStart, &keyLength, &valueStart, &valueLength);
        if (result == 0) return 0;

        if (keyLength == REG_ATTR_TYPE_KEY_LEN
         && 0 == lwm2m_strncmp(REG_ATTR_TYPE_KEY, data + index + keyStart, keyLength))
        {
            if (isValid == true) return 0; // declared twice
            if (valueLength != REG_ATTR_TYPE_VALUE_LEN
             || 0 != lwm2m_strncmp(REG_ATTR_TYPE_VALUE, data + index + valueStart, valueLength))
            {
                return 0;
            }
            isValid = true;
        }
        else if (keyLength == REG_ATTR_CONTENT_KEY_LEN
              && 0 == lwm2m_strncmp(REG_ATTR_CONTENT_KEY, data + index + keyStart, keyLength))
        {
            if (*supportJSON == true) return 0; // declared twice
            if (valueLength == REG_ATTR_CONTENT_JSON_LEN
             && 0 == lwm2m_strncmp(REG_ATTR_CONTENT_JSON, data + index + valueStart, valueLength))
            {
                *supportJSON = true;
            }
            else
            {
                return 0;
            }
        }
        // else ignore this one

        index += result;
    }

    if (isValid == false) return 0;

    if (pathLength != 0)
    {
        *altPath = (char *)lwm2m_malloc(pathLength + 1);
        if (*altPath == NULL) return 0;
        memcpy(*altPath, data + pathStart, pathLength);
        (*altPath)[pathLength] = 0;
    }

    return 1;
}
Esempio n. 8
0
static int prv_parseItem(uint8_t * buffer,
                         size_t bufferLen,
                         _record_t * recordP)
{
    size_t index;

    memset(recordP->ids, 0xFF, 4*sizeof(uint16_t));
    recordP->type = _TYPE_UNSET;
    recordP->value = NULL;
    recordP->valueLen = 0;

    index = 0;
    do
    {
        int tokenStart;
        int tokenLen;
        int valueStart;
        int valueLen;
        int next;

        next = prv_split(buffer+index, bufferLen-index, &tokenStart, &tokenLen, &valueStart, &valueLen);
        if (next < 0) return -1;

        switch (tokenLen)
        {
        case 1:
        {
            switch (buffer[index+tokenStart])
            {
            case 'n':
            {
                int i;
                int j;

                if (recordP->ids[0] != LWM2M_MAX_ID) return -1;

                // Check for " around URI
                if (valueLen < 2
                 || buffer[index+valueStart] != '"'
                 || buffer[index+valueStart+valueLen-1] != '"')
                {
                    return -1;
                }
                // Ignore starting /
                if (buffer[index + valueStart + 1] == '/')
                {
                    if (valueLen < 4)
                    {
                        return -1;
                    }
                    valueStart += 1;
                    valueLen -= 1;
                }
                i = 0;
                j = 0;
                if (valueLen > 1)
                {
                    do {
                        uint32_t readId;

                        readId = 0;
                        i++;
                        while (i < valueLen-1 && buffer[index+valueStart+i] != '/')
                        {
                            if (buffer[index+valueStart+i] < '0'
                             || buffer[index+valueStart+i] > '9')
                            {
                                return -1;
                            }
                            readId *= 10;
                            readId += buffer[index+valueStart+i] - '0';
                            if (readId > LWM2M_MAX_ID) return -1;
                            i++;
                        }
                        recordP->ids[j] = readId;
                        j++;
                    } while (i < valueLen-1 && j < 4 && buffer[index+valueStart+i] == '/');
                    if (i < valueLen-1 ) return -1;
                }
            }
            break;

            case 'v':
                if (recordP->type != _TYPE_UNSET) return -1;
                recordP->type = _TYPE_FLOAT;
                recordP->value = buffer + index + valueStart;
                recordP->valueLen = valueLen;
                break;

            case 't':
                // TODO: support time
                break;

            default:
                return -1;
            }
        }
        break;

        case 2:
        {
            // "bv", "ov", or "sv"
            if (buffer[index+tokenStart+1] != 'v') return -1;
            switch (buffer[index+tokenStart])
            {
            case 'b':
                if (recordP->type != _TYPE_UNSET) return -1;
                if (0 == lwm2m_strncmp(JSON_TRUE_STRING, (char *)buffer + index + valueStart, valueLen))
                {
                    recordP->type = _TYPE_TRUE;
                }
                else if (0 == lwm2m_strncmp(JSON_FALSE_STRING, (char *)buffer + index + valueStart, valueLen))
                {
                    recordP->type = _TYPE_FALSE;
                }
                else
                {
                    return -1;
                }
                break;

            case 'o':
                if (recordP->type != _TYPE_UNSET) return -1;
                // TODO: support object link
                break;

            case 's':
                if (recordP->type != _TYPE_UNSET) return -1;
                // Check for " around value
                if (valueLen < 2
                 || buffer[index+valueStart] != '"'
                 || buffer[index+valueStart+valueLen-1] != '"')
                {
                    return -1;
                }
                recordP->type = _TYPE_STRING;
                recordP->value = buffer + index + valueStart + 1;
                recordP->valueLen = valueLen - 2;
                break;

            default:
                return -1;
            }
        }
        break;

        default:
            return -1;
        }

        index += next + 1;
    } while (index < bufferLen);

    return 0;
}
Esempio n. 9
0
static int prv_parseItem(const uint8_t * buffer,
                         size_t bufferLen,
                         _record_t * recordP,
                         char * baseUri,
                         time_t * baseTime,
                         lwm2m_data_t *baseValue)
{
    size_t index;
    const uint8_t *name = NULL;
    size_t nameLength = 0;
    bool timeSeen = false;
    bool bnSeen = false;
    bool btSeen = false;
    bool bvSeen = false;
    bool bverSeen = false;

    memset(recordP->ids, 0xFF, 4*sizeof(uint16_t));
    memset(&recordP->value, 0, sizeof(recordP->value));
    recordP->time = 0;

    index = 0;
    do
    {
        size_t tokenStart;
        size_t tokenLen;
        size_t valueStart;
        size_t valueLen;
        int next;

        next = json_split(buffer+index,
                          bufferLen-index,
                          &tokenStart,
                          &tokenLen,
                          &valueStart,
                          &valueLen);
        if (next < 0) return -1;
        if (tokenLen == 0) return -1;

        switch (buffer[index+tokenStart])
        {
        case 'b':
            if (tokenLen == 2 && buffer[index+tokenStart+1] == 'n')
            {
                if (bnSeen) return -1;
                bnSeen = true;
                /* Check for " around URI */
                if (valueLen < 2
                 || buffer[index+valueStart] != '"'
                 || buffer[index+valueStart+valueLen-1] != '"')
                {
                    return -1;
                }
                if (valueLen >= 3)
                {
                    if (valueLen == 3 && buffer[index+valueStart+1] != '/') return -1;
                    if (valueLen > URI_MAX_STRING_LEN) return -1;
                    memcpy(baseUri, buffer+index+valueStart+1, valueLen-2);
                    baseUri[valueLen-2] = '\0';
                }
                else
                {
                    baseUri[0] = '\0';
                }
            }
            else if (tokenLen == 2 && buffer[index+tokenStart+1] == 't')
            {
                if (btSeen) return -1;
                btSeen = true;
                if (!json_convertTime(buffer+index+valueStart, valueLen, baseTime))
                    return -1;
            }
            else if (tokenLen == 2 && buffer[index+tokenStart+1] == 'v')
            {
                if (bvSeen) return -1;
                bvSeen = true;
                if (valueLen == 0)
                {
                    baseValue->type = LWM2M_TYPE_UNDEFINED;
                }
                else
                {
                    if (!json_convertNumeric(buffer+index+valueStart, valueLen, baseValue))
                        return -1;
                    /* Convert explicit 0 to implicit 0 */
                    switch (baseValue->type)
                    {
                    case LWM2M_TYPE_INTEGER:
                        if (baseValue->value.asInteger == 0)
                        {
                            baseValue->type = LWM2M_TYPE_UNDEFINED;
                        }
                        break;
                    case LWM2M_TYPE_UNSIGNED_INTEGER:
                        if (baseValue->value.asUnsigned == 0)
                        {
                            baseValue->type = LWM2M_TYPE_UNDEFINED;
                        }
                        break;
                    case LWM2M_TYPE_FLOAT:
                        if (baseValue->value.asFloat == 0.0)
                        {
                            baseValue->type = LWM2M_TYPE_UNDEFINED;
                        }
                        break;
                    default:
                        return -1;
                    }
                }
            }
            else if (tokenLen == 4
                  && buffer[index+tokenStart+1] == 'v'
                  && buffer[index+tokenStart+2] == 'e'
                  && buffer[index+tokenStart+3] == 'r')
            {
                int64_t value;
                int res;
                if (bverSeen) return -1;
                bverSeen = true;
                res = utils_textToInt(buffer+index+valueStart, valueLen, &value);
                /* Only the default version (10) is supported */
                if (!res || value != 10)
                {
                    return -1;
                }
            }
            else if (buffer[index+tokenStart+tokenLen-1] == '_')
            {
                /* Label ending in _ must be supported or generate error. */
                return -1;
            }
            break;
        case 'n':
        {
            if (tokenLen == 1)
            {
                if (name) return -1;

                /* Check for " around URI */
                if (valueLen < 2
                        || buffer[index+valueStart] != '"'
                                || buffer[index+valueStart+valueLen-1] != '"')
                {
                    return -1;
                }
                name = buffer + index + valueStart + 1;
                nameLength = valueLen - 2;
            }
            else if (buffer[index+tokenStart+tokenLen-1] == '_')
            {
                /* Label ending in _ must be supported or generate error. */
                return -1;
            }
            break;
        }
        case 't':
            if (tokenLen == 1)
            {
                if (timeSeen) return -1;
                timeSeen = true;
                if (!json_convertTime(buffer+index+valueStart, valueLen, &recordP->time))
                    return -1;
            }
            else if (buffer[index+tokenStart+tokenLen-1] == '_')
            {
                /* Label ending in _ must be supported or generate error. */
                return -1;
            }
            break;
        case 'v':
            if (tokenLen == 1)
            {
                if (recordP->value.type != LWM2M_TYPE_UNDEFINED) return -1;
                if (!json_convertNumeric(buffer+index+valueStart, valueLen, &recordP->value))
                    return -1;
            }
            else if (tokenLen == 2 && buffer[index+tokenStart+1] == 'b')
            {
                if (recordP->value.type != LWM2M_TYPE_UNDEFINED) return -1;
                if (0 == lwm2m_strncmp(JSON_TRUE_STRING,
                                       (char *)buffer + index + valueStart,
                                       valueLen))
                {
                    lwm2m_data_encode_bool(true, &recordP->value);
                }
                else if (0 == lwm2m_strncmp(JSON_FALSE_STRING,
                                            (char *)buffer + index + valueStart,
                                            valueLen))
                {
                    lwm2m_data_encode_bool(false, &recordP->value);
                }
                else
                {
                    return -1;
                }
            }
            else if (tokenLen == 2
                  && (buffer[index+tokenStart+1] == 'd'
                   || buffer[index+tokenStart+1] == 's'))
            {
                if (recordP->value.type != LWM2M_TYPE_UNDEFINED) return -1;
                /* Check for " around value */
                if (valueLen < 2
                 || buffer[index+valueStart] != '"'
                 || buffer[index+valueStart+valueLen-1] != '"')
                {
                    return -1;
                }
                if (buffer[index+tokenStart+1] == 'd')
                {
                    /* Don't use lwm2m_data_encode_opaque here. It would copy the buffer */
                    recordP->value.type = LWM2M_TYPE_OPAQUE;
                }
                else
                {
                    /* Don't use lwm2m_data_encode_nstring here. It would copy the buffer */
                    recordP->value.type = LWM2M_TYPE_STRING;
                }
                recordP->value.value.asBuffer.buffer = (uint8_t *)buffer + index + valueStart + 1;
                recordP->value.value.asBuffer.length = valueLen - 2;
            }
            else if (tokenLen == 3 && buffer[index+tokenStart+1] == 'l' && buffer[index+tokenStart+2] == 'o')
            {
                if (recordP->value.type != LWM2M_TYPE_UNDEFINED) return -1;
                /* Check for " around value */
                if (valueLen < 2
                 || buffer[index+valueStart] != '"'
                 || buffer[index+valueStart+valueLen-1] != '"')
                {
                    return -1;
                }
                if (!utils_textToObjLink(buffer + index + valueStart + 1,
                                         valueLen - 2,
                                         &recordP->value.value.asObjLink.objectId,
                                         &recordP->value.value.asObjLink.objectInstanceId))
                {
                    return -1;
                }
                recordP->value.type = LWM2M_TYPE_OBJECT_LINK;
            }
            else if (buffer[index+tokenStart+tokenLen-1] == '_')
            {
                /* Label ending in _ must be supported or generate error. */
                return -1;
            }
            break;
        default:
            if (buffer[index+tokenStart+tokenLen-1] == '_')
            {
                /* Label ending in _ must be supported or generate error. */
                return -1;
            }
            break;
        }

        index += next + 1;
    } while (index < bufferLen);

    /* Combine with base values */
    recordP->time += *baseTime;
    if (baseUri[0] || name)
    {
        lwm2m_uri_t uri;
        size_t length = strlen(baseUri);
        char uriStr[URI_MAX_STRING_LEN];
        if (length > sizeof(uriStr)) return -1;
        memcpy(uriStr, baseUri, length);
        if (nameLength)
        {
            if (nameLength + length > sizeof(uriStr)) return -1;
            memcpy(uriStr + length, name, nameLength);
            length += nameLength;
        }
        if (!lwm2m_stringToUri(uriStr, length, &uri)) return -1;
        if (LWM2M_URI_IS_SET_OBJECT(&uri))
        {
            recordP->ids[0] = uri.objectId;
        }
        if (LWM2M_URI_IS_SET_INSTANCE(&uri))
        {
            recordP->ids[1] = uri.instanceId;
        }
        if (LWM2M_URI_IS_SET_RESOURCE(&uri))
        {
            recordP->ids[2] = uri.resourceId;
        }
        if (LWM2M_URI_IS_SET_RESOURCE_INSTANCE(&uri))
        {
            recordP->ids[3] = uri.resourceInstanceId;
        }
    }
    if (baseValue->type != LWM2M_TYPE_UNDEFINED)
    {
        if (recordP->value.type == LWM2M_TYPE_UNDEFINED)
        {
            memcpy(&recordP->value, baseValue, sizeof(*baseValue));
        }
        else
        {
            switch (recordP->value.type)
            {
            case LWM2M_TYPE_INTEGER:
                switch(baseValue->type)
                {
                case LWM2M_TYPE_INTEGER:
                    recordP->value.value.asInteger += baseValue->value.asInteger;
                    break;
                case LWM2M_TYPE_UNSIGNED_INTEGER:
                    recordP->value.value.asInteger += baseValue->value.asUnsigned;
                    break;
                case LWM2M_TYPE_FLOAT:
                    recordP->value.value.asInteger += baseValue->value.asFloat;
                    break;
                default:
                    return -1;
                }
                break;
            case LWM2M_TYPE_UNSIGNED_INTEGER:
                switch(baseValue->type)
                {
                case LWM2M_TYPE_INTEGER:
                    recordP->value.value.asUnsigned += baseValue->value.asInteger;
                    break;
                case LWM2M_TYPE_UNSIGNED_INTEGER:
                    recordP->value.value.asUnsigned += baseValue->value.asUnsigned;
                    break;
                case LWM2M_TYPE_FLOAT:
                    recordP->value.value.asUnsigned += baseValue->value.asFloat;
                    break;
                default:
                    return -1;
                }
                break;
            case LWM2M_TYPE_FLOAT:
                switch(baseValue->type)
                {
                case LWM2M_TYPE_INTEGER:
                    recordP->value.value.asFloat += baseValue->value.asInteger;
                    break;
                case LWM2M_TYPE_UNSIGNED_INTEGER:
                    recordP->value.value.asFloat += baseValue->value.asUnsigned;
                    break;
                case LWM2M_TYPE_FLOAT:
                    recordP->value.value.asFloat += baseValue->value.asFloat;
                    break;
                default:
                    return -1;
                }
                break;
            default:
                return -1;
            }
        }
    }

    return 0;
}