Example #1
0
int lwm2m_step(lwm2m_context_t * contextP,
               struct timeval * timeoutP)
{
    lwm2m_transaction_t * transacP;
    struct timeval tv;

    if (0 != lwm2m_gettimeofday(&tv, NULL)) return COAP_500_INTERNAL_SERVER_ERROR;

    transacP = contextP->transactionList;
    while (transacP != NULL)
    {
        // transaction_send() may remove transaction from the linked list
        lwm2m_transaction_t * nextP = transacP->next;
        int removed = 0;

        if (transacP->retrans_time <= tv.tv_sec)
        {
            removed = transaction_send(contextP, transacP);
        }

        if (0 == removed)
        {
            time_t interval;

            if (transacP->retrans_time > tv.tv_sec)
            {
                interval = transacP->retrans_time - tv.tv_sec;
            }
            else
            {
                interval = 1;
            }

            if (timeoutP->tv_sec > interval)
            {
                timeoutP->tv_sec = interval;
            }
        }

        transacP = nextP;
    }

    return 0;
}
Example #2
0
static void prv_handleRegistrationReply(lwm2m_transaction_t * transacP,
                                        void * message)
{
    lwm2m_server_t * targetP;
    coap_packet_t * packet = (coap_packet_t *)message;

    targetP = (lwm2m_server_t *)(transacP->peerP);
    struct timeval tv;

    switch(targetP->status)
    {
    case STATE_REG_PENDING:
    {
        if (packet == NULL)
        {
            targetP->status = STATE_UNKNOWN;
            targetP->mid = 0;
        }
        else if (packet->mid == targetP->mid
              && packet->type == COAP_TYPE_ACK
              && packet->location_path != NULL)
        {
            if (packet->code == CREATED_2_01)
            {
                targetP->status = STATE_REGISTERED;
                targetP->location = coap_get_multi_option_as_string(packet->location_path);

                if (0 == lwm2m_gettimeofday(&tv, NULL)) 
                {
                    targetP->registration = tv.tv_sec;
                }
            }
            else if (packet->code == BAD_REQUEST_4_00)
            {
                targetP->status = STATE_UNKNOWN;
                targetP->mid = 0;
            }
        }
    }
    break;
    default:
        break;
    }
}
Example #3
0
static void prv_handleRegistrationUpdateReply(lwm2m_transaction_t * transacP,
                                        void * message)
{
    lwm2m_server_t * targetP;
    coap_packet_t * packet = (coap_packet_t *)message;
    struct timeval tv;

    targetP = (lwm2m_server_t *)(transacP->peerP);

    switch(targetP->status)
    {
    case STATE_REG_UPDATE_PENDING:
    {
        if (packet == NULL)
        {
            targetP->status = STATE_UNKNOWN;
            targetP->mid = 0;
        }
        else if (packet->mid == targetP->mid
              && packet->type == COAP_TYPE_ACK)
        {
            if (packet->code == CHANGED_2_04)
            {
                if (0 == lwm2m_gettimeofday(&tv, NULL)) 
                {
                    targetP->registration = tv.tv_sec;
                }
                targetP->status = STATE_REGISTERED;
            }
            else if (packet->code == BAD_REQUEST_4_00)
            {
                targetP->status = STATE_UNKNOWN;
                targetP->mid = 0;
                // trigger a new registration? infinite loop?
            }
        }
    }
    break;
    default:
        break;
    }
}
Example #4
0
coap_status_t handle_registration_request(lwm2m_context_t * contextP,
                                          lwm2m_uri_t * uriP,
                                          void * fromSessionH,
                                          coap_packet_t * message,
                                          coap_packet_t * response)
{
    coap_status_t result;
    struct timeval tv;

    if (lwm2m_gettimeofday(&tv, NULL) != 0)
    {
        return COAP_500_INTERNAL_SERVER_ERROR;
    }

    switch(message->code)
    {
    case COAP_POST:
    {
        char * name = NULL;
        uint32_t lifetime;
        char * msisdn;
        lwm2m_binding_t binding;
        lwm2m_client_object_t * objects;
        lwm2m_client_t * clientP;
        char location[MAX_LOCATION_LENGTH];

        if ((uriP->flag & LWM2M_URI_MASK_ID) != 0) return COAP_400_BAD_REQUEST;
        if (0 != prv_getParameters(message->uri_query, &name, &lifetime, &msisdn, &binding))
        {
            return COAP_400_BAD_REQUEST;
        }
        objects = prv_decodeRegisterPayload(message->payload, message->payload_len);
        if (objects == NULL)
        {
            lwm2m_free(name);
            if (msisdn != NULL) lwm2m_free(msisdn);
            return COAP_400_BAD_REQUEST;
        }
        // Endpoint client name is mandatory
        if (name == NULL)
        {
            if (msisdn != NULL) lwm2m_free(msisdn);
            return COAP_400_BAD_REQUEST;
        }
        if (lifetime == 0)
        {
            lifetime = LWM2M_DEFAULT_LIFETIME;
        }

        clientP = prv_getClientByName(contextP, name);
        if (clientP != NULL)
        {
            // we reset this registration
            lwm2m_free(clientP->name);
            if (clientP->msisdn != NULL) lwm2m_free(clientP->msisdn);
            prv_freeClientObjectList(clientP->objectList);
            clientP->objectList = NULL;
        }
        else
        {
            clientP = (lwm2m_client_t *)lwm2m_malloc(sizeof(lwm2m_client_t));
            if (clientP == NULL)
            {
                lwm2m_free(name);
                if (msisdn != NULL) lwm2m_free(msisdn);
                prv_freeClientObjectList(objects);
                return COAP_500_INTERNAL_SERVER_ERROR;
            }
            memset(clientP, 0, sizeof(lwm2m_client_t));
            clientP->internalID = lwm2m_list_newId((lwm2m_list_t *)contextP->clientList);
            contextP->clientList = (lwm2m_client_t *)LWM2M_LIST_ADD(contextP->clientList, clientP);
        }
        clientP->name = name;
        clientP->binding = binding;
        clientP->msisdn = msisdn;
        clientP->lifetime = lifetime;
        clientP->endOfLife = tv.tv_sec + lifetime;
        clientP->objectList = objects;
        clientP->sessionH = fromSessionH;

        if (prv_getLocationString(clientP->internalID, location) == 0)
        {
            prv_freeClient(clientP);
            return COAP_500_INTERNAL_SERVER_ERROR;
        }
        if (coap_set_header_location_path(response, location) == 0)
        {
            prv_freeClient(clientP);
            return COAP_500_INTERNAL_SERVER_ERROR;
        }

        if (contextP->monitorCallback != NULL)
        {
            contextP->monitorCallback(clientP->internalID, NULL, CREATED_2_01, NULL, 0, contextP->monitorUserData);
        }
        result = COAP_201_CREATED;
    }
    break;

    case COAP_PUT:
    {
        char * name = NULL;
        uint32_t lifetime;
        char * msisdn;
        lwm2m_binding_t binding;
        lwm2m_client_object_t * objects;
        lwm2m_client_t * clientP;

        if ((uriP->flag & LWM2M_URI_MASK_ID) != LWM2M_URI_FLAG_OBJECT_ID) return COAP_400_BAD_REQUEST;

        clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, uriP->objectId);
        if (clientP == NULL) return COAP_404_NOT_FOUND;

        if (0 != prv_getParameters(message->uri_query, &name, &lifetime, &msisdn, &binding))
        {
            return COAP_400_BAD_REQUEST;
        }
        objects = prv_decodeRegisterPayload(message->payload, message->payload_len);

        // Endpoint client name MUST NOT be present
        if (name != NULL)
        {
            lwm2m_free(name);
            if (msisdn != NULL) lwm2m_free(msisdn);
            return COAP_400_BAD_REQUEST;
        }

        if (binding != BINDING_UNKNOWN)
        {
            clientP->binding = binding;
        }
        if (msisdn != NULL)
        {
            if (clientP->msisdn != NULL) lwm2m_free(clientP->msisdn);
            clientP->msisdn = msisdn;
        }
        if (lifetime != 0)
        {
            clientP->lifetime = lifetime;
        }
        // client IP address, port or MSISDN may have changed
        clientP->sessionH = fromSessionH;

        if (objects != NULL)
        {
            lwm2m_observation_t * observationP;

            // remove observations on object/instance no longer existing
            observationP = clientP->observationList;
            while (observationP != NULL)
            {
                lwm2m_client_object_t * objP;
                lwm2m_observation_t * nextP;

                nextP = observationP->next;

                objP = (lwm2m_client_object_t *)lwm2m_list_find((lwm2m_list_t *)objects, observationP->uri.objectId);
                if (objP == NULL)
                {
                    observationP->callback(clientP->internalID,
                                           &observationP->uri,
                                           COAP_202_DELETED,
                                           NULL, 0,
                                           observationP->userData);
                    observation_remove(clientP, observationP);
                }
                else
                {
                    if ((observationP->uri.flag & LWM2M_URI_FLAG_INSTANCE_ID) != 0)
                    {
                        if (lwm2m_list_find((lwm2m_list_t *)objP->instanceList, observationP->uri.instanceId) == NULL)
                        {
                            observationP->callback(clientP->internalID,
                                                   &observationP->uri,
                                                   COAP_202_DELETED,
                                                   NULL, 0,
                                                   observationP->userData);
                            observation_remove(clientP, observationP);
                        }
                    }
                }

                observationP = nextP;
            }

            prv_freeClientObjectList(clientP->objectList);
            clientP->objectList = objects;
        }

        clientP->endOfLife = tv.tv_sec + clientP->lifetime;

        if (contextP->monitorCallback != NULL)
        {
            contextP->monitorCallback(clientP->internalID, NULL, COAP_204_CHANGED, NULL, 0, contextP->monitorUserData);
        }
        result = COAP_204_CHANGED;
    }
    break;

    case COAP_DELETE:
    {
        lwm2m_client_t * clientP;

        if ((uriP->flag & LWM2M_URI_MASK_ID) != LWM2M_URI_FLAG_OBJECT_ID) return COAP_400_BAD_REQUEST;

        contextP->clientList = (lwm2m_client_t *)LWM2M_LIST_RM(contextP->clientList, uriP->objectId, &clientP);
        if (clientP == NULL) return COAP_400_BAD_REQUEST;
        if (contextP->monitorCallback != NULL)
        {
            contextP->monitorCallback(clientP->internalID, NULL, DELETED_2_02, NULL, 0, contextP->monitorUserData);
        }
        prv_freeClient(clientP);
        result = COAP_202_DELETED;
    }
    break;

    default:
        return COAP_400_BAD_REQUEST;
    }

    return result;
}
Example #5
0
int transaction_send(lwm2m_context_t * contextP,
                     lwm2m_transaction_t * transacP)
{
    if (transacP->buffer == NULL)
    {
        uint8_t tempBuffer[LWM2M_MAX_PACKET_SIZE];
        int length;

        length = coap_serialize_message(transacP->message, tempBuffer);
        if (length <= 0) return COAP_500_INTERNAL_SERVER_ERROR;

        transacP->buffer = (uint8_t*)lwm2m_malloc(length);
        if (transacP->buffer == NULL) return COAP_500_INTERNAL_SERVER_ERROR;

        memcpy(transacP->buffer, tempBuffer, length);
        transacP->buffer_len = length;
    }

    switch(transacP->peerType)
    {
    case ENDPOINT_CLIENT:
        LOG("Sending %d bytes\r\n", transacP->buffer_len);
        contextP->bufferSendCallback(((lwm2m_client_t*)transacP->peerP)->sessionH,
                                     transacP->buffer, transacP->buffer_len, contextP->bufferSendUserData);

        break;

    case ENDPOINT_SERVER:
        LOG("Sending %d bytes\r\n", transacP->buffer_len);
        contextP->bufferSendCallback(((lwm2m_server_t*)transacP->peerP)->sessionH,
                                     transacP->buffer, transacP->buffer_len, contextP->bufferSendUserData);
        break;

    case ENDPOINT_BOOTSTRAP:
        // not implemented yet
        break;

    default:
        return 0;
    }

    if (transacP->retrans_counter == 0)
    {
        struct timeval tv;

        if (0 == lwm2m_gettimeofday(&tv, NULL))
        {
            transacP->retrans_time = tv.tv_sec;
            transacP->retrans_counter = 1;
        }
        else
        {
            // crude error handling
            transacP->retrans_counter = COAP_MAX_RETRANSMIT;
        }
    }

    if (transacP->retrans_counter < COAP_MAX_RETRANSMIT)
    {
        transacP->retrans_time += COAP_RESPONSE_TIMEOUT * transacP->retrans_counter;
        transacP->retrans_counter++;
    }
    else
    {
        if (transacP->callback)
        {
            transacP->callback(transacP, NULL);
        }
        transaction_remove(contextP, transacP);
        return -1;
    }

    return 0;
}