NetworkAddress * NetworkAddress_New(const char * uri, int uriLength)
{
    NetworkAddress * result = NULL;
    if (uri && uriLength > 0)
    {
        int uriHostLength = getUriHostLength(uri, uriLength);
        if (uriHostLength > 0)
            result = getCachedAddressByUri(uri, uriHostLength);
        if (!result)
        {
            bool ip6Address = false;
            bool secure = false;
            int index = 0;
            int startIndex = 0;
            int port = 5683;
            char hostname[MAX_URI_LENGTH];
            int hostnameLength = 0;
            UriParseState state = UriParseState_Scheme;
            while (index < uriLength)
            {
                if (state == UriParseState_Scheme)
                {
                    if ((uri[index] == ':') && ((index + 2) <  uriLength) && (uri[index+1] == '/') &&  (uri[index+2] == '/'))
                    {
                        int length = index - startIndex;
                        if ((length == 4) && (strncmp(&uri[startIndex],"coap", length) == 0))
                        {

                        }
                        else if ((length == 5) && (strncmp(&uri[startIndex],"coaps", length) == 0))
                        {
                            port = 5684;
                            secure = true;
                        }
                        else
                        {
                            break;
                        }
                        state = UriParseState_Hostname;
                        index += 2;
                        startIndex = index + 1;
                    }
                    index++;
                }
                else if (state == UriParseState_Hostname)
                {
                    if ((uri[index] == '[') )
                    {
                        index++;
                        startIndex = index;
                        while (index < uriLength)
                        {
                            if (uri[index] == ']')
                            {
                                ip6Address = true;
                                break;
                            }
                            hostname[hostnameLength] = uri[index];
                            hostnameLength++;
                            index++;
                        }
                    }
                    else if ((uri[index] == ':') || (uri[index] == '/') )
                    {
                        hostname[hostnameLength] = 0;
                        if  (uri[index] == '/')
                            break;
                        state = UriParseState_Port;
                        port = 0;
                        startIndex = index + 1;
                    }
                    else
                    {
                        hostname[hostnameLength] = uri[index];
                        hostnameLength++;
                    }
                    index++;
                }
                else if (state == UriParseState_Port)
                {
                    if (uri[index] == '/')
                    {
                        break;
                    }
                    else if (isdigit(uri[index]))
                    {
                        port = (port * 10) + (uri[index] - '0');
                    }
                    index++;
                }
            }
            if (state == UriParseState_Hostname)
            {
                hostname[hostnameLength] = 0;
            }
            if (hostnameLength > 0 && port > 0)
            {
                NetworkAddress * networkAddress = NULL;
                if (ip6Address)
                {
                    networkAddress = NetworkAddress_FromIPAddress(hostname, port);
                }
                else
                {
                    struct hostent *resolvedAddress = gethostbyname(hostname);
                    if (resolvedAddress)
                    {
                        size_t size = sizeof(struct _NetworkAddress);
                        networkAddress = (NetworkAddress *) malloc(size);
                        if (networkAddress)
                        {
                            memset(networkAddress, 0, size);
                            if (resolvedAddress->h_addrtype == AF_INET)
                            {
                                networkAddress->Address.Sin.sin_family = AF_INET;
                                memcpy(&networkAddress->Address.Sin.sin_addr, *(resolvedAddress->h_addr_list), sizeof(struct in_addr));
                                networkAddress->Address.Sin.sin_port = htons(port);
                            }
                            else if (resolvedAddress->h_addrtype == AF_INET6)
                            {
                                networkAddress->Address.Sin6.sin6_family = AF_INET6;
                                memcpy(&networkAddress->Address.Sin6.sin6_addr, *(resolvedAddress->h_addr_list), sizeof(struct in6_addr));
                                networkAddress->Address.Sin6.sin6_port = htons(port);
                            }
                            else
                            {
                                free(networkAddress);
                                networkAddress = NULL;
                            }
                        }
                    }
                }
                if (networkAddress)
                {
                    networkAddress->Secure = secure;
                    result = getCachedAddress(networkAddress, uri, uriHostLength);
                    if (result)
                    {
                        // Matched existing address
                        free(networkAddress);
                    }
                    else
                    {
                        result = networkAddress;
                    }
                }

            }
        }

        if (result)
        {
            if (result->useCount == 0)
            {
                addCachedAddress(result, uri, uriHostLength);
            }
            result->useCount++;
        }
    }
    return result;
}
NetworkAddress * NetworkAddress_New(const char * uri, int uriLength)
{
    NetworkAddress * result = NULL;
    if (uri && uriLength > 0)
    {
        int uriHostLength = getUriHostLength(uri, uriLength);
        if (uriHostLength > 0)
            result = getCachedAddressByUri(uri, uriHostLength);
        if (!result)
        {
            bool secure = false;
            int index = 0;
            int startIndex = 0;
            int port = 5683;
            char hostname[MAX_URI_LENGTH];
            int hostnameLength = 0;
            UriParseState state = UriParseState_Scheme;
            while (index < uriLength)
            {
                if (state == UriParseState_Scheme)
                {
                    if ((uri[index] == ':') && ((index + 2) <  uriLength) && (uri[index+1] == '/') &&  (uri[index+2] == '/'))
                    {
                        int length = index - startIndex;
                        if ((length == 4) && (strncmp(&uri[startIndex],"coap", length) == 0))
                        {

                        }
                        else if ((length == 5) && (strncmp(&uri[startIndex],"coaps", length) == 0))
                        {
                            port = 5684;
                            secure = true;
                        }
                        else
                        {
                            break;
                        }
                        state = UriParseState_Hostname;
                        index += 2;
                        startIndex = index + 1;
                    }
                    index++;
                }
                else if (state == UriParseState_Hostname)
                {
                    if ((uri[index] == '[') )
                    {
                        index++;
                        while (index < uriLength)
                        {
                            if (uri[index] == ']')
                            {
                                break;
                            }
                            index++;
                        }
                    }
                    else if ((uri[index] == ':') || (uri[index] == '/') )
                    {
                        hostnameLength = index - startIndex;
                        memcpy(&hostname, &uri[startIndex], hostnameLength);
                        hostname[hostnameLength] = 0;
                        if  (uri[index] == '/')
                            break;
                        state = UriParseState_Port;
                        port = 0;
                        startIndex = index + 1;
                    }
                    index++;
                }
                else if (state == UriParseState_Port)
                {
                    if (uri[index] == '/')
                    {
                        break;
                    }
                    else if (isdigit(uri[index]))
                    {
                        port = (port * 10) + (uri[index] - '0');
                    }
                    index++;
                }
            }
            if (state == UriParseState_Hostname)
            {
                hostnameLength = uriLength - startIndex;
                memcpy(hostname, &uri[startIndex], hostnameLength);
                hostname[hostnameLength] = 0;
            }
            if (hostnameLength > 0 && port > 0)
            {
                uip_ipaddr_t * resolvedAddress = getHostByName(hostname);
                if (resolvedAddress)
                {
                    NetworkAddress * networkAddress = addCachedAddress(uri, uriHostLength);
                    if (networkAddress)
                    {
                        memcpy(&networkAddress->Address, resolvedAddress, sizeof(uip_ipaddr_t));
                        networkAddress->Secure = secure;
                        networkAddress->useCount = 1;
                        networkAddress->Port = UIP_HTONS(port);
                        result = networkAddress;
                    }
                }
            }
        }
    }
    return result;
}