void NetworkAddress_Free(NetworkAddress ** address)
{
    // TODO - review when addresses are freed (e.g. after client bootstrap, or connection lost ?)
    if (address && *address)
    {
        (*address)->useCount--;
        if ((*address)->useCount == 0)
        {
            int index;
            for (index = 0; index < MAX_NETWORK_ADDRESS_CACHE; index++)
            {
                if (networkAddressCache[index].address == *address)
                {
                    if (networkAddressCache[index].uri)
                    {
                        Lwm2m_Debug("Address free: %s\n", networkAddressCache[index].uri);
                        free(networkAddressCache[index].uri);
                        networkAddressCache[index].uri = NULL;
                    }
                    else
                    {
                        Lwm2m_Debug("Address free\n");
                    }
                    networkAddressCache[index].address = NULL;
                    break;
                }
            }
            free(*address);
        }
        *address = NULL;
    }
}
void coap_SendNotify(AddressType * addr, const char * path, const char * token, int tokenSize, ContentType contentType, const char * payload, int payloadLen, int sequence)
{
    coap_packet_t notify;
    coap_transaction_t *transaction;

    Lwm2m_Debug("Coap notify: %s\n", path);
    Lwm2m_Debug("Coap IPv6 request address: " PRINT6ADDR(&addr->Addr));
    Lwm2m_Debug("Coap request port: %d\n", addr->Port);

    coap_init_message(&notify, COAP_TYPE_NON, CONTENT_2_05, coap_get_mid());

    if (contentType != ContentType_None)
    {
        coap_set_header_content_format(&notify, contentType);
        coap_set_payload(&notify, payload, payloadLen);
    }

    coap_set_token(&notify, token, tokenSize);
    coap_set_header_observe(&notify, sequence);

    if ((transaction = coap_new_transaction(notify.mid, &addr->Addr, uip_htons(addr->Port))))
    {
        transaction->packet_len = coap_serialize_message(&notify, transaction->packet);

        coap_send_transaction(transaction); // for NON confirmable messages this will call coap_clear_transaction();
    }
}
static void addCachedAddress(NetworkAddress * address, const char * uri, int uriLength)
{
    if (address)
    {
        int index;
        for (index = 0; index < MAX_NETWORK_ADDRESS_CACHE; index++)
        {
            if (networkAddressCache[index].address == NULL)
            {
                if (uri && uriLength > 0)
                {
                    networkAddressCache[index].uri = (char *)malloc(uriLength + 1);
                    if (networkAddressCache[index].uri)
                    {
                        memcpy(networkAddressCache[index].uri, uri, uriLength);
                        networkAddressCache[index].uri[uriLength] = 0;
                        networkAddressCache[index].address = address;
                        Lwm2m_Debug("Address add: %s\n", networkAddressCache[index].uri);
                    }
                }
                else
                {
                    networkAddressCache[index].address = address;
                    networkAddressCache[index].uri = NULL;
                    Lwm2m_Debug("Address add (received)\n");    // TODO - print remote address
                }
                break;
            }
        }
    }
}
static NetworkAddress * getCachedAddress(NetworkAddress * matchAddress, const char * uri, int uriLength)
{
    NetworkAddress * result = NULL;
    int index;
    for (index = 0; index < MAX_NETWORK_ADDRESS_CACHE; index++)
    {
        NetworkAddress * address = networkAddressCache[index].address;
        if (address)
        {
            if (NetworkAddress_Compare(matchAddress, address) == 0)
            {
                if (uri && uriLength > 0 && networkAddressCache[index].uri == NULL)
                {
                    // Add info to cached address
                    address->Secure = matchAddress->Secure;
                    networkAddressCache[index].uri = (char *)malloc(uriLength + 1);
                    if (networkAddressCache[index].uri)
                    {
                        memcpy(networkAddressCache[index].uri, uri, uriLength);
                        networkAddressCache[index].uri[uriLength] = 0;
                        Lwm2m_Debug("Address add uri: %s\n", networkAddressCache[index].uri);
                    }
                }
                result = address;
                break;
            }
        }
    }
    return result;
}
void coap_SendNotify(AddressType * addr, const char * path, const char * token, int tokenSize, ContentType contentType,
        const char * payload, int payloadLen, int sequence)
{
    // TODO - FIXME: if path is not full uri then map addr to Network address + append path(?)
    coap_packet_t notify;
    coap_transaction_t *transaction;
    NetworkAddress * remoteAddress = NetworkAddress_New(path, strlen(path));

    Lwm2m_Debug("Coap notify: %s\n", path);
    //Lwm2m_Debug("Coap IPv6 request address: " PRINT6ADDR(&addr->Addr));
    //Lwm2m_Debug("Coap request port: %d\n", addr->Port);

    coap_init_message(&notify, COAP_TYPE_NON, CONTENT_2_05, coap_get_mid());

    if (contentType != ContentType_None)
    {
        coap_set_header_content_format(&notify, contentType);
        coap_set_payload(&notify, payload, payloadLen);
    }

    coap_set_token(&notify, token, tokenSize);
    coap_set_header_observe(&notify, sequence);

    if ((transaction = coap_new_transaction(networkSocket, notify.mid, remoteAddress)))
    {
        transaction->packet_len = coap_serialize_message(&notify, transaction->packet);

        coap_send_transaction(transaction); // for NON confirmable messages this will call coap_clear_transaction();
    }
}
Esempio n. 6
0
// Handler called when the server posts a "finished" message to /bs
static int BootStrapPost(void * ctxt, AddressType * addr, const char * path, const char * query, ContentType contentType,
                         const char * requestContent, size_t requestContentLen, char * responseContent, size_t * responseContentLen, int * responseCode)
{
    Lwm2mContextType * context = (Lwm2mContextType *)ctxt;
    Lwm2mBootStrapState state = Lwm2mCore_GetBootstrapState(context);

    *responseContentLen = 0;  // no content

    Lwm2m_Debug("POST to /bs\n");

    if (state == Lwm2mBootStrapState_BootStrapFinishPending)
    {
        Lwm2m_Info("Bootstrap finished\n");
        Lwm2mCore_SetBootstrapState(context, Lwm2mBootStrapState_BootStrapped);
        Lwm2mCore_UpdateAllServers(context, Lwm2mRegistrationState_Register);
        *responseCode = AwaResult_SuccessChanged;
    }
    else if ((state == Lwm2mBootStrapState_BootStrapPending) ||
             (state == Lwm2mBootStrapState_ClientHoldOff))
    {
        Lwm2m_Info("Server initiated bootstrap\n");
        Lwm2mCore_SetBootstrapState(context, Lwm2mBootStrapState_BootStrapped);
        Lwm2mCore_UpdateAllServers(context, Lwm2mRegistrationState_Register);
        *responseCode = AwaResult_SuccessChanged;
    }
    else
    {
        *responseCode = AwaResult_BadRequest;
    }
    return 0;
}
Esempio n. 7
0
static bool BootStrapFromSmartCard(Lwm2mContextType * context)
{
    // not implemented

    Lwm2m_Debug("Lwm2m_BootstrapFromSmartCard\n");
    return false;
}
static int connectivityStatisticsStartOrReset(void * context, ObjectIDType objectID, ObjectInstanceIDType objectInstanceID, ResourceIDType resourceID, uint8_t * inValueBuffer, size_t inValueBufferLen)
{
    Lwm2m_Debug("Reset/Start Connectivity Statistics");

    // Not implemented

    return 0;
}
Esempio n. 9
0
static int executeUpdate(void * context, ObjectIDType objectID, ObjectInstanceIDType objectInstanceID, ResourceIDType resourceID, uint8_t * inValueBuffer, size_t inValueBufferLen)
{
    Lwm2m_Debug("Firmware Update resource executed\n");
#ifndef CONTIKI
    // Fire IPC notifications to any subscribers.
    xmlif_ExecuteResourceHandler(context, objectID, objectInstanceID, resourceID, inValueBuffer, inValueBufferLen);
#endif
    return 0;
}
uip_ipaddr_t * getHostByName(const char *hostName)
{
    uip_ipaddr_t * result = NULL;
    static uip_ipaddr_t ipaddr;
    if (uiplib_ipaddrconv(hostName, &ipaddr) == 0)
    {
        uip_ipaddr_t *resolved_addr = NULL;
        resolv_status_t status = resolv_lookup(hostName, &resolved_addr);
        if (status == RESOLV_STATUS_UNCACHED || status == RESOLV_STATUS_EXPIRED)
        {
            Lwm2m_Debug("Attempting to look up %s\n", hostName);
            resolv_query(hostName);
            status = RESOLV_STATUS_RESOLVING;
        }
        else if (status == RESOLV_STATUS_CACHED && resolved_addr != NULL )
        {
            Lwm2m_Debug("Lookup of \"%s\" succeeded!\n", hostName);
        }
        else if (status == RESOLV_STATUS_RESOLVING)
        {
            resolved_addr = NULL;
            Lwm2m_Debug("Still looking up \"%s\"...\n", hostName);
        }
        else
        {
            resolved_addr = NULL;
            Lwm2m_Debug("Lookup of \"%s\" failed. status = %d\n", hostName, status);
        }
        if (resolved_addr)
        {
            uip_ipaddr_copy(&ipaddr, resolved_addr);
            result = &ipaddr;
        }
    }
    else
    {
        result = &ipaddr;
        Lwm2m_Debug("Cache hit on look up %s\n", hostName);
    }

    return result;
}
Esempio n. 11
0
static void RegisterObjects(Lwm2mContextType * context, Options * options)
{
    Lwm2m_Debug("Register built-in objects\n");

    Lwm2m_RegisterSecurityObject(context);
    if (options->BootStrap != NULL)
    {
        Lwm2m_PopulateSecurityObject(context, options->BootStrap);
    }
    Lwm2m_RegisterServerObject(context);
    Lwm2m_RegisterACLObject(context);

}
void coap_createCoapRequest(void * context, coap_method_t method, const char * uri, ContentType contentType, const char * payload, int payloadLen, TransactionCallback callback)
{
    coap_packet_t request;
    uip_ipaddr_t * remote_ipaddr = coap_getIpFromURI(uri);
    int remote_port = coap_getPortFromURI(uri);
    coap_transaction_t *transaction;
    char path[128] = {0};
    char query[128] = {0};

    coap_getPathQueryFromURI(uri, path, query);

    Lwm2m_Debug("Coap request: %s\n", uri);
    Lwm2m_Debug("Coap IPv6 request address: " PRINT6ADDR(remote_ipaddr));
    Lwm2m_Debug("Coap request port: %d\n", remote_port);
    Lwm2m_Debug("Coap request path: %s\n", path);
    Lwm2m_Debug("Coap request query: %s\n", query);

    coap_init_message(&request, COAP_TYPE_CON, method, coap_get_mid());

    coap_set_header_uri_path(&request, path);
    coap_set_header_uri_query(&request, query);

    if (contentType != ContentType_None)
    {
        coap_set_header_content_format(&request, contentType);
        coap_set_payload(&request, payload, payloadLen);
    }

    if (CurrentTransaction[CurrentTransactionIndex].TransactionUsed && CurrentTransaction[CurrentTransactionIndex].TransactionPtr)
    {
        Lwm2m_Warning("Canceled previous transaction [%d]: %p\n", CurrentTransactionIndex, CurrentTransaction[CurrentTransactionIndex].TransactionPtr);
        coap_clear_transaction(CurrentTransaction[CurrentTransactionIndex].TransactionPtr);
    }

    if ((transaction = coap_new_transaction(request.mid, remote_ipaddr, uip_htons(remote_port))))
    {
        transaction->callback = coap_CoapRequestCallback;
        CurrentTransaction[CurrentTransactionIndex].Callback = callback;
        CurrentTransaction[CurrentTransactionIndex].Context = context;
        CurrentTransaction[CurrentTransactionIndex].TransactionUsed = true;
        CurrentTransaction[CurrentTransactionIndex].TransactionPtr = transaction;
        memcpy(&CurrentTransaction[CurrentTransactionIndex].Address.Addr, remote_ipaddr, sizeof(uip_ipaddr_t));
        CurrentTransaction[CurrentTransactionIndex].Address.Port = uip_htons(remote_port);

        transaction->callback_data = &CurrentTransaction[CurrentTransactionIndex];

        transaction->packet_len = coap_serialize_message(&request, transaction->packet);

        Lwm2m_Debug("Sending transaction [%d]: %p\n", CurrentTransactionIndex, CurrentTransaction[CurrentTransactionIndex].TransactionPtr);
        coap_send_transaction(transaction);

        CurrentTransactionIndex++;

        if(CurrentTransactionIndex >= MAX_COAP_TRANSACTIONS)
        {
            CurrentTransactionIndex = 0;
        }
    }
}
int coap_RegisterUri(const char * uri)
{
    resource_t * temp = malloc(sizeof(resource_t));
    char * uriCopy = strdup(&uri[1]);

    Lwm2m_Debug("register %s\n", uriCopy);

    memcpy(temp, &rest_resource_template, sizeof(resource_t));

    rest_activate_resource(temp, uriCopy);

    return 0;
}
int coap_ResolveAddressByURI(unsigned char * address, AddressType * addr)
{
    int result = -1;

    Lwm2m_Debug("resolve address from Uri: %s\n", address);
    NetworkAddress * networkAddress = NetworkAddress_New(address, strlen(address));
    if (networkAddress)
    {
        NetworkAddress_SetAddressType(networkAddress, addr);
        NetworkAddress_Free(&networkAddress);
        result = 0;
    }
    return result;
}
Esempio n. 15
0
Lwm2mContextType * Lwm2mCore_Init(CoapInfo * coap, ContentType contentType)
{
    Lwm2m_Debug("Create object store\n");

    Lwm2mContextType * context = &Lwm2mContext;
    context->Coap = coap;
    context->Store = ObjectStore_Create();
    context->Definitions = DefinitionRegistry_Create();
    context->ContentType = contentType;

    Lwm2mEndPoint_InitEndPointList(&context->EndPointList);

    coap_SetContext(context);
    coap_SetRequestHandler(Lwm2mCore_HandleRequest);

    // Initialise registration data, i.e tables for storing client information
    Lwm2m_RegistrationInit(context);
    return context;
}
bool readUDP(NetworkSocket * networkSocket, uint8_t * buffer, int bufferLength, NetworkAddress ** sourceAddress, int *readLength)
{
    bool result = true;
    *readLength = 0;
    //if (uip_newdata() && (UIP_IP_BUF->destport == networkSocket->Port) )
    if (uip_newdata())
    {
        Lwm2m_Debug("Packet from: %d %d\n", UIP_IP_BUF->destport, networkSocket->Port);
        if (uip_datalen() > bufferLength)
            *readLength = bufferLength;
        else
            *readLength = uip_datalen();
    }
    if (*readLength > 0)
    {
        memcpy(buffer, uip_appdata, *readLength);
        NetworkAddress * networkAddress = NULL;
        NetworkAddress matchAddress;
        size_t size = sizeof(struct _NetworkAddress);
        memset(&matchAddress, 0, size);
        memcpy(&matchAddress.Address, &UIP_IP_BUF->srcipaddr, sizeof(uip_ipaddr_t));
        matchAddress.Port =  UIP_IP_BUF->srcport; //uip_ntohs(UIP_UDP_BUF->srcport);
        matchAddress.Secure = (networkSocket->SocketType & NetworkSocketType_Secure) == NetworkSocketType_Secure;
        networkAddress = getCachedAddress(&matchAddress, NULL, 0);

        if (networkAddress == NULL)
        {
            networkAddress = addCachedAddress(NULL, 0);
            if (networkAddress)
            {
                // Add new address to cache (note: uri and secure is unknown)
                memcpy(networkAddress, &matchAddress, size);
                networkAddress->useCount++;         // TODO - ensure addresses are freed? (after t/o or transaction or DTLS session closed)
            }
        }
        if (networkAddress)
        {
            *sourceAddress = networkAddress;
        }
    }
    return result;
}
static NetworkAddress * addCachedAddress(const char * uri, int uriLength)
{
    NetworkAddress * result = NULL;
    int index;
    for (index = 0; index < MAX_NETWORK_ADDRESS_CACHE; index++)
    {
        if (!networkAddressCache[index].InUse)
        {
            if (uri && uriLength > 0)
            {
                memcpy(networkAddressCache[index].Uri, uri, uriLength);
                networkAddressCache[index].Uri[uriLength] = 0;
                Lwm2m_Debug("Address add: %s\n", networkAddressCache[index].Uri);
            }
            networkAddressCache[index].InUse = true;
            result = &networkAddressCache[index].Address;
            break;
        }
    }
    return result;
}
void NetworkAddress_Free(NetworkAddress ** address)
{
    // TODO - review when addresses are freed (e.g. after client bootstrap, or connection lost ?)
    if (address && *address)
    {
        (*address)->useCount--;
        if ((*address)->useCount == 0)
        {
            int index;
            for (index = 0; index < MAX_NETWORK_ADDRESS_CACHE; index++)
            {
                if (NetworkAddress_Compare(&networkAddressCache[index].Address, *address) == 0)
                {
                    Lwm2m_Debug("Address free\n");
                    networkAddressCache[index].InUse = false;
                    memset(&networkAddressCache[index].Address, 0, sizeof(struct _NetworkAddress));
                    break;
                }
            }
        }
        *address = NULL;
    }
}
bool readUDP(NetworkSocket * networkSocket, uint8_t * buffer, int bufferLength, NetworkAddress ** sourceAddress, int *readLength)
{
    bool result = true;
    *readLength = 0;
    //if (uip_newdata() && (UIP_IP_BUF->destport == networkSocket->Port) )
    if (uip_newdata())
    {
        Lwm2m_Debug("Packet from: %d %d\n", uip_htons(UIP_IP_BUF->destport), networkSocket->Port);
        if (uip_datalen() > bufferLength)
            *readLength = bufferLength;
        else
            *readLength = uip_datalen();
    }
    if (*readLength > 0)
    {
        uip_ipaddr_t * address = &UIP_IP_BUF->srcipaddr;
        uint16_t port = uip_htons(UIP_IP_BUF->srcport);
        bool secure = (networkSocket->SocketType & NetworkSocketType_Secure) == NetworkSocketType_Secure;

        memcpy(buffer, uip_appdata, *readLength);
        NetworkAddress * networkAddress = getCachedAddress(address, port);

        if (networkAddress == NULL)
        {
            networkAddress = addCachedAddress(address, port, secure);
            if (networkAddress)
            {
                networkAddress->useCount++;         // TODO - ensure addresses are freed? (after t/o or transaction or DTLS session closed)
            }
        }
        if (networkAddress)
        {
            *sourceAddress = networkAddress;
        }
    }
    return result;
}
Esempio n. 20
0
int Lwm2mCore_GetIPAddressFromInterface(const char * interface, int addressFamily, char * destAddress, size_t destAddressLength)
{
    int returnCode = 0;

    if (addressFamily != AF_INET && addressFamily != AF_INET6)
    {
        Lwm2m_Error("Unsupported address family: %d. Only AF_INET and AF_INET6 are supported.\n", addressFamily);
        returnCode = 1;
        goto error;
    }
    struct ifaddrs *interfaceAddresses, *interfaceAddress;

    char host[NI_MAXHOST];

    if (getifaddrs(&interfaceAddresses) == -1)
    {
        perror("getifaddrs");
        returnCode = 1;
        goto error;
    }

    char linkLocalIpv6Address[NI_MAXHOST] = { 0 };
    char globalIpv6Address[NI_MAXHOST] = { 0 };
    bool found = false;
    int index = 0;
    for (interfaceAddress = interfaceAddresses; interfaceAddress != NULL; interfaceAddress = interfaceAddress->ifa_next)
    {
        if (interfaceAddress->ifa_addr == NULL)
        {
            continue;
        }

        if ((strcmp(interfaceAddress->ifa_name, interface)==0)&&(interfaceAddress->ifa_addr->sa_family==addressFamily))
        {
            int socketAddressLength = 0;
            switch(addressFamily)
            {
                case AF_INET:
                    socketAddressLength = sizeof(struct sockaddr_in);
                    break;
                default:
                    socketAddressLength = sizeof(struct sockaddr_in6);
                    break;
            }

            returnCode = getnameinfo(interfaceAddress->ifa_addr, socketAddressLength, host, sizeof(host), NULL, 0, NI_NUMERICHOST);

            if (returnCode != 0)
            {
                Lwm2m_Error("getnameinfo() failed: %s\n", gai_strerror(returnCode));
                goto error_free;
            }

            size_t addressLength = strlen(host);
            if (destAddressLength < addressLength)
            {
                Lwm2m_Error("Error: Address is longer than %zu characters\n", destAddressLength);
                goto error_free;
            }

            switch(addressFamily)
            {
                case AF_INET:
                    strcpy(destAddress, host);
                    found = true;
                    break;
                default:
                    if (strncmp(host, "fe80", 4) == 0)
                    {
                        Lwm2m_Debug("Address %d: %s (local)\n", index, host);
                        strcpy(linkLocalIpv6Address, host);
                    }
                    else
                    {
                        Lwm2m_Debug("Address %d: %s (global)\n", index, host);
                        strcpy(globalIpv6Address, host);
                    }
                    break;
            }
            index++;
        }
    }

    if (addressFamily == AF_INET6)
    {
        if (strlen(globalIpv6Address) > 0)
        {
            Lwm2m_Debug("Global IPv6 address found for interface %s: %s\n", interface, globalIpv6Address);
            strcpy(destAddress, globalIpv6Address);
            found = true;
        }
        else if (strlen(linkLocalIpv6Address) > 0)
        {
            Lwm2m_Warning("No global IPv6 address found for interface %s: using local: %s\n", interface, linkLocalIpv6Address);
            strcpy(destAddress, linkLocalIpv6Address);
            found = true;
        }
    }

    if (!found)
    {
        Lwm2m_Error("Could not find an %s IP address for interface %s\n", addressFamily == AF_INET? "IPv4" : "IPv6", interface);
        returnCode = 1;
    }

error_free:
    freeifaddrs(interfaceAddresses);
error:
    return returnCode;
}
static int coap_HandleRequest(void *packet, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
    int result = 1;
    const char *url = NULL;
    int urlLen = 0;
    const uint8_t * payload = NULL;
    int payloadLen = 0;
    int content = -1;

    coap_packet_t * const request = (coap_packet_t *) packet;

    CoapResponse coapResponse =
    { .responseContent = buffer, .responseContentLen = preferred_size, .responseCode = 400, };

    payloadLen = coap_get_payload(request, &payload);

    if ((urlLen = coap_get_header_uri_path(request, &url)))
    {
        char uriBuf[MAX_COAP_PATH] = { 0 };
        rest_resource_flags_t method = (rest_resource_flags_t) (1 << (((coap_packet_t *) packet)->code - 1)); //coap_get_rest_method(request);

        uriBuf[0] = '/';
        memcpy(&uriBuf[1], url, urlLen);

        char queryBuf[128] = "?";
        const char * query = NULL;

        int queryLength = coap_get_header_uri_query(request, &query);
        if (queryLength > 0)
            memcpy(&queryBuf[1], query, queryLength);

        queryBuf[queryLength+1] = '\0';

        CoapRequest coapRequest =
        { .ctxt = context, .addr =
        { 0 }, .path = uriBuf, .query = queryBuf, .token = request->token, .tokenLength = request->token_len, .requestContent = payload,
                .requestContentLen = payloadLen, };

        NetworkAddress_SetAddressType(sourceAddress, &coapRequest.addr);

        switch (method)
        {
        case METHOD_GET:

            coap_get_header_accept(request, &content);
            coapRequest.contentType = content;

            int32_t observe;

            if (!coap_get_header_observe(request, &observe))
                observe = -1;

            switch (observe)
            {
            case -1:
                Lwm2m_Debug("Coap GET for %s\n", uriBuf);
                coapRequest.type = COAP_GET_REQUEST;
                requestHandler(&coapRequest, &coapResponse);
                break;
            case 0:
                Lwm2m_Debug("Coap OBSERVE for %s\n", uriBuf);

                coapRequest.type = COAP_OBSERVE_REQUEST;
                requestHandler(&coapRequest, &coapResponse);
                coap_set_header_observe(response, 1);
                break;
            case 1:
                Lwm2m_Debug("Coap CANCEL OBSERVE for %s\n", uriBuf);

                coapRequest.type = COAP_CANCEL_OBSERVE_REQUEST;
                requestHandler(&coapRequest, &coapResponse);
                break;
            default:
                break;
            }
            coap_set_header_content_format(response, coapResponse.responseContentType); /* text/plain is the default, hence this option could be omitted. */
            break;

        case METHOD_POST:
            coap_get_header_content_format(request, &content);
            coapRequest.contentType = content;
            coapRequest.type = COAP_POST_REQUEST;
            Lwm2m_Debug("Coap POST for %s\n", uriBuf);
            requestHandler(&coapRequest, &coapResponse);
            if (coapResponse.responseContentLen > 0 && coapResponse.responseCode == 201)
            {
                coap_set_header_location_path(response, coapResponse.responseContent);
            }
            break;

        case METHOD_PUT:
            coap_get_header_content_format(request, &content);
            coapRequest.contentType = content;
            coapRequest.type = COAP_PUT_REQUEST;

            Lwm2m_Debug("Coap PUT for %s\n", uriBuf);
            requestHandler(&coapRequest, &coapResponse);
            break;

        case METHOD_DELETE:
            coapRequest.contentType = ContentType_None;
            coapRequest.type = COAP_DELETE_REQUEST;

            Lwm2m_Debug("Coap DELETE for %s\n", uriBuf);
            requestHandler(&coapRequest, &coapResponse);
            break;

        default:
            break;
        }

        if (coapResponse.responseContentLen > 0 && coapResponse.responseCode == 205)
        {
            coap_set_payload(response, coapResponse.responseContent, coapResponse.responseContentLen);
        }
    }

    coap_set_status_code(response, COAP_RESPONSE_CODE(coapResponse.responseCode));
    return result;
}
void coap_createCoapRequest(coap_method_t method, const char * uri, ContentType contentType, ObserveState observeState,
        const char * payload, int payloadLen, TransactionCallback callback, void * context)
{
    coap_packet_t request;
    char path[MAX_COAP_PATH] =
    { 0 };
    char query[128] =
    { 0 };
    coap_transaction_t *transaction;
    NetworkAddress * remoteAddress = NetworkAddress_New(uri, strlen(uri));

    coap_getPathQueryFromURI(uri, path, query);

    Lwm2m_Info("Coap request: %s\n", uri);
    //Lwm2m_Debug("Coap request path: %s\n", path);
    //Lwm2m_Debug("Coap request query: %s\n", query);

    coap_init_message(&request, COAP_TYPE_CON, method, coap_get_mid());

    coap_set_header_uri_path(&request, path);
    if (strlen(query) > 0)
        coap_set_header_uri_query(&request, query);
    // TODO - REVIEW: Erbium must copy path/query from request - else mem out of scope

    if (contentType != ContentType_None)
    {
        if ((method == COAP_POST) || (method == COAP_PUT))
        {
            coap_set_header_content_format(&request, contentType);
            coap_set_payload(&request, payload, payloadLen);
        }
        else
        {
            coap_set_header_accept(&request, contentType);
        }
    }


    if (method == COAP_GET)
    {
        if (observeState == ObserveState_Establish)
        {
            coap_set_header_observe(&request, 0);
            int token = addObserve(remoteAddress, path, callback, context);
            if (token != 0)
                coap_set_token(&request, (const uint8_t *) &token, sizeof(token));

        }
        else if (observeState == ObserveState_Cancel)
        {
            coap_set_header_observe(&request, 1);
            int token = removeObserve(remoteAddress, path);
            if (token != 0)
                coap_set_token(&request, (const uint8_t *) &token, sizeof(token));
        }
    }

    if (CurrentTransaction[CurrentTransactionIndex].TransactionUsed && CurrentTransaction[CurrentTransactionIndex].TransactionPtr)
    {
        Lwm2m_Warning("Canceled previous transaction [%d]: %p\n", CurrentTransactionIndex,
                CurrentTransaction[CurrentTransactionIndex].TransactionPtr);
        coap_clear_transaction(&CurrentTransaction[CurrentTransactionIndex].TransactionPtr);
    }

    //if ((transaction = coap_new_transaction(request.mid, remote_ipaddr, uip_htons(remote_port))))
    if ((transaction = coap_new_transaction(networkSocket, request.mid, remoteAddress)))
    {
        transaction->callback = coap_CoapRequestCallback;
        memcpy(CurrentTransaction[CurrentTransactionIndex].Path, path, MAX_COAP_PATH);
        CurrentTransaction[CurrentTransactionIndex].Callback = callback;
        CurrentTransaction[CurrentTransactionIndex].Context = context;
        CurrentTransaction[CurrentTransactionIndex].TransactionUsed = true;
        CurrentTransaction[CurrentTransactionIndex].TransactionPtr = transaction;
        NetworkAddress_SetAddressType(remoteAddress, &CurrentTransaction[CurrentTransactionIndex].Address);

        transaction->callback_data = &CurrentTransaction[CurrentTransactionIndex];

        transaction->packet_len = coap_serialize_message(&request, transaction->packet);

        Lwm2m_Debug("Sending transaction [%d]: %p\n", CurrentTransactionIndex, CurrentTransaction[CurrentTransactionIndex].TransactionPtr);
        coap_send_transaction(transaction);

        CurrentTransactionIndex++;

        if (CurrentTransactionIndex >= MAX_COAP_TRANSACTIONS)
        {
            CurrentTransactionIndex = 0;
        }
    }
}
Esempio n. 23
0
static bool BootStrapFromFactory(Lwm2mContextType * context)
{
    Lwm2m_Debug("Lwm2m_BootstrapFromFactory: %s\n", Lwm2mCore_GetUseFactoryBootstrap(context) ? "True" : "False");

    return Lwm2mCore_GetUseFactoryBootstrap(context);
}
static void coap_HandleResource(/*CoapRequestHandlerCallbacks * RequestCB,*/ void *packet, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
    const char *url = NULL;
    int urlLen = 0;
    const uint8_t * payload = NULL;
    int payloadLen = 0;
    int content = -1;

    coap_packet_t *const request = (coap_packet_t *)packet;

    CoapResponse coapResponse = {
       .responseContent = buffer,
       .responseContentLen = preferred_size,
       .responseCode = 400,
    };

    payloadLen = REST.get_request_payload(request, &payload);

    if ((urlLen = REST.get_url(request, &url)))
    {
        char uriBuf[64] = {0};
        rest_resource_flags_t method = REST.get_method_type(request);

        uriBuf[0] = '/';
        memcpy(&uriBuf[1], url, urlLen);

        const char * query = NULL;

        REST.get_query(request, &query);

        CoapRequest coapRequest = {
            .ctxt = context,
            .addr = { 0 },
            .path = uriBuf,
            .query = query,
            .token = request->token,
            .tokenLength = request->token_len,
            .requestContent = payload,
            .requestContentLen = payloadLen,
        };

        memcpy(&coapRequest.addr.Addr, &UIP_IP_BUF->srcipaddr, sizeof(uip_ipaddr_t));
        coapRequest.addr.Port = uip_ntohs(UIP_UDP_BUF->srcport);

        switch(method)
        {
        case METHOD_GET:
        
            REST.get_header_accept(request, &content);
            coapRequest.contentType = content;

            int32_t observe;

            if (!coap_get_header_observe(request, &observe))
              observe = -1;

            switch(observe)
            {
                case -1:
                    Lwm2m_Debug("Coap GET for %s\n", uriBuf);
                    coapRequest.type = COAP_GET_REQUEST;
                    requestHandler(&coapRequest, &coapResponse);
                    break;
                case 0:
                    Lwm2m_Debug("Coap OBSERVE for %s\n", uriBuf);

                    coapRequest.type = COAP_OBSERVE_REQUEST;
                    requestHandler(&coapRequest, &coapResponse);
                    coap_set_header_observe(response, 1);
                    break;
                case 1:
                    Lwm2m_Debug("Coap CANCEL OBSERVE for %s\n", uriBuf);

                    coapRequest.type = COAP_CANCEL_OBSERVE_REQUEST;
                    requestHandler(&coapRequest, &coapResponse);
                    break;
                default:
                    break;
            }
            REST.set_header_content_type(response, coapResponse.responseContentType); /* text/plain is the default, hence this option could be omitted. */
            break;

        case METHOD_POST:
            REST.get_header_content_type(request, &content);
            coapRequest.contentType = content;
            coapRequest.type = COAP_POST_REQUEST;
            Lwm2m_Debug("Coap POST for %s\n", uriBuf);
            requestHandler(&coapRequest, &coapResponse);
            break;

        case METHOD_PUT:
            REST.get_header_content_type(request, &content);
            coapRequest.contentType = content;
            coapRequest.type = COAP_PUT_REQUEST;

            Lwm2m_Debug("Coap PUT for %s\n", uriBuf);
            requestHandler(&coapRequest, &coapResponse);
            break;

        case METHOD_DELETE:
            coapRequest.contentType = ContentType_None;
            coapRequest.type = COAP_DELETE_REQUEST;

            Lwm2m_Debug("Coap DELETE for %s\n", uriBuf);
            requestHandler(&coapRequest, &coapResponse);
            break;

        default:
            break;
        }

        if (coapResponse.responseContentLen > 0 && coapResponse.responseCode == 205 )
        {
            REST.set_response_payload(response, coapResponse.responseContent, coapResponse.responseContentLen);
        }
    }

    REST.set_response_status(response, COAP_RESPONSE_CODE(coapResponse.responseCode));
}
Esempio n. 25
0
static int Bootstrap_Start(Options * options)
{
    int result = 0;

    if (options->Daemonise)
    {
        Daemonise(options->Verbose);
    }
    else
    {
        signal(SIGINT, CtrlCSignalHandler);
    }

    signal(SIGTERM, CtrlCSignalHandler);

    // open log files here
    if (options->LogFile)
    {
        errno = 0;
        logFile = fopen(options->LogFile, "at");
        if (logFile != NULL)
        {
            Lwm2m_SetOutput(logFile);

            // redirect stdout
            dup2(fileno(logFile), STDOUT_FILENO);
        }
        else
        {
            Lwm2m_Error("Failed to open log file %s: %s\n", options->LogFile, strerror(errno));
        }
    }

    if (options->Version)
    {
        Lwm2m_Printf(0, "%s\n", version);
        goto error_close_log;
    }

    Lwm2m_SetLogLevel((options->Verbose) ? DebugLevel_Debug : DebugLevel_Info);
    Lwm2m_PrintBanner();
    if (options->Verbose)
    {
        PrintOptions(options);
    }
    Lwm2m_Info("Awa LWM2M Bootstrap Server, version %s\n", version);
    Lwm2m_Info("  Process ID     : %d\n", getpid());
    Lwm2m_Info("  CoAP port      : %d\n", options->Port);

    if (options->InterfaceName != NULL)
    {
        Lwm2m_Info("  Interface      : %s [IPv%d]\n", options->InterfaceName, options->AddressFamily == AF_INET? 4 : 6);
    }
    else if (strcmp(DEFAULT_IP_ADDRESS, options->IPAddress) != 0)
    {
        Lwm2m_Info("  IP Address     : %s\n", options->IPAddress);
    }

    char ipAddress[NI_MAXHOST];
    if (options->InterfaceName != NULL)
    {
        if (Lwm2mCore_GetIPAddressFromInterface(options->InterfaceName, options->AddressFamily, ipAddress, sizeof(ipAddress)) != 0)
        {
            result = 1;
            goto error_close_log;
        }
        Lwm2m_Info("  Interface Addr : %s\n", ipAddress);
    }
    else
    {
        strncpy(ipAddress, options->IPAddress, NI_MAXHOST);
        ipAddress[NI_MAXHOST - 1] = '\0';  // Defensive
    }

    CoapInfo * coap = coap_Init(ipAddress, options->Port, (options->Verbose) ? DebugLevel_Debug : DebugLevel_Info);
    if (coap == NULL)
    {
        printf("Unable to map address to network interface\n");
        result = 1;
        goto error_close_log;
    }
    Lwm2mContextType * context = Lwm2mCore_Init(coap);

    // must happen after coap_Init()
    Lwm2m_RegisterObjectTypes(context);

    if (!Lwm2mBootstrap_BootStrapInit(context, options->Config, options->ConfigCount))
    {
        printf("Failed to initialise boostrap\n");
        result = 1;
        goto error_destroy;
    }

    // wait for messages on both the "IPC" and coap interfaces
    while (!quit)
    {
        int loop_result;
        struct pollfd fds[1];
        int nfds = 1;
        int timeout;

        fds[0].fd = coap->fd;
        fds[0].events = POLLIN;

        timeout = Lwm2mCore_Process(context);

        loop_result = poll(fds, nfds, timeout);

        if (loop_result < 0)
        {
            if (errno == EINTR)
            {
                continue;
            }

            perror("poll:");
            break;
        }
        else if (loop_result > 0)
        {
            if (fds[0].revents == POLLIN)
            {
                coap_HandleMessage();
            }
        }
        coap_Process();
    }
    Lwm2m_Debug("Exit triggered\n");

error_destroy:
    Lwm2mBootstrap_Destroy();
    Lwm2mCore_Destroy(context);
    coap_Destroy();

error_close_log:
    Lwm2m_Info("Bootstrap Server exiting\n");
    if (logFile != NULL)
    {
        fclose(logFile);
    }

    return result;
}
Esempio n. 26
0
static int Lwm2mServer_Start(Options * options)
{
    int xmlFd;
    int result = 0;

    if (options->Daemonise)
    {
        Daemonise(options->Verbose);
    }
    else
    {
        signal(SIGINT, Lwm2m_CtrlCSignalHandler);
    }

    signal(SIGTERM, Lwm2m_CtrlCSignalHandler);

    // open log files here
    if (options->LogFile != NULL)
    {
        errno = 0;
        logFile = fopen(options->LogFile, "at");
        if (logFile != NULL)
        {
            Lwm2m_SetOutput(logFile);

            // redirect stdout
            dup2(fileno(logFile), STDOUT_FILENO);
        }
        else
        {
            Lwm2m_Error("Failed to open log file %s: %s\n", options->LogFile, strerror(errno));
        }
    }

    if (options->Version)
    {
        Lwm2m_Printf(0, "%s\n", version);
        goto error_close_log;
    }

    Lwm2m_SetLogLevel((options->Verbose) ? DebugLevel_Debug : DebugLevel_Info);
    Lwm2m_PrintBanner();
    if (options->Verbose)
    {
        PrintOptions(options);
    }
    Lwm2m_Info("Awa LWM2M Server, version %s\n", version);
    Lwm2m_Info("  Process ID     : %d\n", getpid());
    Lwm2m_Info("  DTLS library   : %s\n", DTLS_LibraryName);
    Lwm2m_Info("  CoAP library   : %s\n", coap_LibraryName);
    Lwm2m_Info("  CoAP port      : %d\n", options->CoapPort);
    Lwm2m_Info("  Secure         : %s\n", options->Secure ? "true": "false");
    Lwm2m_Info("  IPC port       : %d\n", options->IpcPort);
    Lwm2m_Info("  Address family : IPv%d\n", options->AddressFamily == AF_INET ? 4 : 6);



    if (options->InterfaceName != NULL)
    {
        Lwm2m_Info("LWM2M server - Using interface %s [IPv%d]\n", options->InterfaceName, options->AddressFamily == AF_INET? 4 : 6);
    }
    else if (strcmp(DEFAULT_IP_ADDRESS, options->IPAddress) != 0)
    {
        Lwm2m_Info("LWM2M server - IP Address %s\n", options->IPAddress);
    }

    char ipAddress[NI_MAXHOST];
    if (options->InterfaceName != NULL)
    {
        if (Lwm2mCore_GetIPAddressFromInterface(options->InterfaceName, options->AddressFamily, ipAddress, sizeof(ipAddress)) != 0)
        {
            result = 1;
            goto error_close_log;
        }
        Lwm2m_Info("LWM2M server - Interface Address %s\n", ipAddress);
    }
    else
    {
        strncpy(ipAddress, options->IPAddress, NI_MAXHOST);
        ipAddress[NI_MAXHOST - 1] = '\0'; // Defensive
    }

    CoapInfo * coap = coap_Init(ipAddress, options->CoapPort, options->Secure, (options->Verbose) ? DebugLevel_Debug : DebugLevel_Info);
    if (coap == NULL)
    {
        printf("Unable to map address to network interface\n");
        result = 1;
        goto error_close_log;
    }

    if (options->Secure)
    {
    	coap_SetCertificate(serverCert, sizeof(serverCert), CertificateFormat_PEM);
        coap_SetPSK(pskIdentity, pskKey, sizeof(pskKey));
    }

    Lwm2mContextType * context = Lwm2mCore_Init(NULL, options->ContentType);  // NULL, don't map coap with objectStore

    // must happen after coap_Init()
    Lwm2m_RegisterObjectTypes(context);

    // listen for UDP packets on port 12345 for now.
    xmlFd = xmlif_init(context, options->IpcPort);
    if (xmlFd < 0)
    {
        result = 1;
        goto error_destroy;
    }
    xmlif_RegisterHandlers();

    // wait for messages on both the "IPC" and coap interfaces
    while (!quit)
    {
        int loop_result;
        struct pollfd fds[2];
        int nfds = 2;
        int timeout;

        fds[0].fd = coap->fd;
        fds[0].events = POLLIN;

        fds[1].fd = xmlFd;
        fds[1].events = POLLIN;

        timeout = Lwm2mCore_Process(context);

        loop_result = poll(fds, nfds, timeout);

        if (loop_result < 0)
        {
            if (errno == EINTR)
            {
                continue;
            }
            perror("poll:");
            break;
        }
        else if (loop_result > 0)
        {
            if (fds[0].revents == POLLIN)
            {
                coap_HandleMessage();
            }
            if (fds[1].revents == POLLIN)
            {
                xmlif_process(fds[1].fd);
            }
        }
        coap_Process();
    }
    Lwm2m_Debug("Exit triggered\n");

error_destroy:
    xmlif_destroy(xmlFd);
    Lwm2mCore_Destroy(context);
    coap_Destroy();

error_close_log:
    Lwm2m_Info("Server exiting\n");
    if (logFile != NULL)
    {
        fclose(logFile);
    }

    return result;
}
bool NetworkSocket_StartListening(NetworkSocket * networkSocket)
{
    bool result = false;
    if (networkSocket)
    {
        int protocol = IPPROTO_UDP;
        int socketMode = SOCK_DGRAM;
        if ((networkSocket->SocketType & NetworkSocketType_TCP) == NetworkSocketType_TCP)
        {
            protocol = IPPROTO_TCP;
            socketMode = SOCK_STREAM;
        }
        struct sockaddr_in ip4AnyAddress;
        struct sockaddr_in6 ip6AnyAddress;

        struct sockaddr_in * ip4Address = NULL;
        struct sockaddr_in6 * ip6Address = NULL;
        if (networkSocket->BindAddress)
        {
            if (networkSocket->BindAddress->Address.Sa.sa_family == AF_INET6)
            {
                ip6Address = &networkSocket->BindAddress->Address.Sin6;
            }
            else if (networkSocket->BindAddress->Address.Sa.sa_family == AF_INET)
            {
                ip4Address = &networkSocket->BindAddress->Address.Sin;
            }
        }
        else
        {

            memset(&ip4AnyAddress, 0, sizeof(struct sockaddr_in));
            ip4AnyAddress.sin_family = AF_INET;
            ip4AnyAddress.sin_addr.s_addr = INADDR_ANY;
            ip4AnyAddress.sin_port = htons(networkSocket->Port);
            ip4Address = &ip4AnyAddress;

            memset(&ip6AnyAddress, 0, sizeof(struct sockaddr_in6));
            ip6AnyAddress.sin6_family = AF_INET6;
            ip6AnyAddress.sin6_port = htons(networkSocket->Port);
            ip6Address = &ip6AnyAddress;

        }
        if (ip4Address)
            networkSocket->Socket = socket(AF_INET, socketMode, protocol);
        else
            networkSocket->Socket = SOCKET_ERROR;
        if (networkSocket->Socket != SOCKET_ERROR)
        {
            struct sockaddr *address = NULL;
            socklen_t addressLength = 0;
            addressLength = sizeof(struct sockaddr_in);
            address = (struct sockaddr *)ip4Address;
            int flag = fcntl(networkSocket->Socket, F_GETFL);
            flag = flag | O_NONBLOCK;
            if (fcntl(networkSocket->Socket, F_SETFL, flag) < 0)
            {
                // ignore error
            }
            if (bind(networkSocket->Socket, address, addressLength) == SOCKET_ERROR)
            {
                Lwm2m_Debug("Failed to bind to ip4 socket\n");
            }
            else
            {
                result = true;

            }
        }
        if (ip6Address)
            networkSocket->SocketIPv6 = socket(AF_INET6, socketMode, protocol);
        else
            networkSocket->SocketIPv6 = SOCKET_ERROR;
        if (networkSocket->SocketIPv6 != SOCKET_ERROR)
        {

            int yes = 1;
            if (setsockopt(networkSocket->SocketIPv6, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes) != SOCKET_ERROR))
            {
                struct sockaddr *address = NULL;
                socklen_t addressLength = 0;
                addressLength = sizeof(struct sockaddr_in6);
                address = (struct sockaddr *)ip6Address;
                int flag = fcntl(networkSocket->SocketIPv6, F_GETFL);
                flag = flag | O_NONBLOCK;
                if (fcntl(networkSocket->SocketIPv6, F_SETFL, flag) < 0)
                {
                    // ignore error
                }
                if (bind(networkSocket->SocketIPv6, address, addressLength) == SOCKET_ERROR)
                {
                    Lwm2m_Debug("Failed to bind to ip6 socket\n");
                }
                else
                {
                    result = true;
                }
            }
        }
    }
    return result;
}
Esempio n. 28
0
static int Lwm2mClient_Start(Options * options)
{
    FILE * logFile = NULL;
    uint8_t * loadedClientCert = NULL;
    int result = 0;
    uint8_t * key = NULL;

    if (options->Daemonise)
    {
        Daemonise(options->Verbose);
    }
    else
    {
        signal(SIGINT, Lwm2m_CtrlCSignalHandler);
    }

    signal(SIGTERM, Lwm2m_CtrlCSignalHandler);

    if (options->LogFile)
    {
        errno = 0;
        logFile = fopen(options->LogFile, "at");
        if (logFile != NULL)
        {
            Lwm2m_SetOutput(logFile);

            // redirect stdout
            dup2(fileno(logFile), STDOUT_FILENO);
        }
        else
        {
            Lwm2m_Error("Failed to open log file %s: %s\n", options->LogFile, strerror(errno));
        }
    }

    if (options->Version)
    {
        Lwm2m_Printf(0, "%s\n", version);
        goto error_close_log;
    }

    srandom((int)time(NULL)*getpid());
    if (options->CoapPort == 0)
    {
        options->CoapPort = 6000 + (rand() % 32768);
    }

    Lwm2m_SetLogLevel((options->Verbose) ? DebugLevel_Debug : DebugLevel_Info);
    Lwm2m_PrintBanner();
    if (options->Verbose)
    {
        PrintOptions(options);
    }
    Lwm2m_Info("Awa LWM2M Client, version %s\n", version);
    Lwm2m_Info("  Process ID     : %d\n", getpid());
    Lwm2m_Info("  Endpoint name  : \'%s\'\n", options->EndPointName);
    Lwm2m_Info("  DTLS library   : %s\n", DTLS_LibraryName);
    Lwm2m_Info("  CoAP library   : %s\n", coap_LibraryName);
    Lwm2m_Info("  CoAP port      : %d\n", options->CoapPort);
    Lwm2m_Info("  IPC port       : %d\n", options->IpcPort);
    Lwm2m_Info("  Address family : IPv%d\n", options->AddressFamily == AF_INET ? 4 : 6);

    Lwm2mCore_SetDefaultContentType(options->DefaultContentType);

    CoapInfo * coap = coap_Init((options->AddressFamily == AF_INET) ? "0.0.0.0" : "::", options->CoapPort, false /* not a server */, (options->Verbose) ? DebugLevel_Debug : DebugLevel_Info);
    if (coap == NULL)
    {
        Lwm2m_Error("Failed to initialise CoAP on port %d\n", options->CoapPort);
        result = 1;
        goto error_close_log;
    }

    // always set key
    if (options->CertificateFile)
    {
        loadedClientCert = LoadCertificateFile(options->CertificateFile);
    }
    else
        coap_SetCertificate(clientCert, sizeof(clientCert), AwaCertificateFormat_PEM);

    if (options->PskIdentity && options->PskKey)
    {
        int hexKeyLength = strlen(options->PskKey);
        int keyLength = hexKeyLength / 2;
        key = (uint8_t *)malloc(keyLength);
        if (key)
        {
           char * value = options->PskKey;
           int index;
           for (index = 0; index < keyLength; index++)
           {
               key[index] = HexToByte(value);
               value += 2;
           }
           coap_SetPSK(options->PskIdentity, key, keyLength);
        }
        else
            coap_SetPSK(pskIdentity, pskKey, sizeof(pskKey));
    }
    else
        coap_SetPSK(pskIdentity, pskKey, sizeof(pskKey));

    // if required read the bootstrap information from a file
    const BootstrapInfo * factoryBootstrapInfo;
    if (options->FactoryBootstrapFile != NULL)
    {
        factoryBootstrapInfo = BootstrapInformation_ReadConfigFile(options->FactoryBootstrapFile);
        if (factoryBootstrapInfo == NULL)
        {
            Lwm2m_Error("Factory Bootstrap configuration file load failed\n");
            result = 1;
            goto error_coap;
        }
        else
        {
            Lwm2m_Info("Factory Bootstrap:\n");
            Lwm2m_Info("Server Configuration\n");
            Lwm2m_Info("====================\n");
            BootstrapInformation_Dump(factoryBootstrapInfo);
        }
    }
    else
    {
        factoryBootstrapInfo = NULL;
    }

    Lwm2mContextType * context = Lwm2mCore_Init(coap, options->EndPointName);

    // Must happen after coap_Init().
    RegisterObjects(context, options);

    if (factoryBootstrapInfo != NULL)
    {
        Lwm2mCore_SetFactoryBootstrap(context, factoryBootstrapInfo);
    }

    // bootstrap information has been loaded, no need to hang onto this anymore
    BootstrapInformation_DeleteBootstrapInfo(factoryBootstrapInfo);

    // load any specified objDef files
    if (LoadObjectDefinitionsFromFiles(context, options->ObjDefsFiles, options->NumObjDefsFiles) != 0)
    {
        goto error_core;
    }

    // Listen for UDP packets on IPC port
    int xmlFd = xmlif_init(context, options->IpcPort);
    if (xmlFd < 0)
    {
        Lwm2m_Error("Failed to initialise XML interface on port %d\n", options->IpcPort);
        result = 1;
        goto error_core;
    }
    xmlif_RegisterHandlers();

    // Wait for messages on both the IPC and CoAP interfaces
    while (!quit)
    {
        int loop_result;
        struct pollfd fds[2];
        int nfds = 2;
        int timeout;

        fds[0].fd = coap->fd;
        fds[0].events = POLLIN;

        fds[1].fd = xmlFd;
        fds[1].events = POLLIN;

        timeout = Lwm2mCore_Process(context);

        loop_result = poll(fds, nfds, timeout);
        if (loop_result < 0)
        {
            if (errno == EINTR)
            {
                continue;
            }
            perror("poll:");
            break;
        }
        else if (loop_result > 0)
        {
            if (fds[0].revents == POLLIN)
            {
                coap_HandleMessage();
            }
            if (fds[1].revents == POLLIN)
            {
                xmlif_process(fds[1].fd);
            }
        }
        coap_Process();
    }
    Lwm2m_Debug("Exit triggered\n");

    xmlif_DestroyExecuteHandlers();
    xmlif_destroy(xmlFd);
error_core:
    Lwm2mCore_Destroy(context);
error_coap:
    coap_Destroy();

error_close_log:
    free(loadedClientCert);
    free(key);
    Lwm2m_Info("Client exiting\n");
    if (logFile)
    {
        fclose(logFile);
    }

    return result;
}