/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    Copyright (c) 2013-2017 Nest Labs, Inc.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 *    @file
 *      This file implements the human-readable string formatting and
 *      parsing methods from class <tt>Inet::IPAddress</tt>.
 *
 */

#include <algorithm>
#include <limits>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include <inet/IPAddress.h>
#include <inet/InetInterface.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/StringBuilder.h>

#if CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS
#include <arpa/inet.h>
#endif

namespace chip {
namespace Inet {

// Normalize a string to lowercase per RFC 5952 (canonical IPv6 text form).
// ip6addr_ntoa_r and otIp6AddressToString output uppercase, which is
// non-canonical.
static void NormalizeIp6ToLower(char * str)
{
    for (char * p = str; *p != '\0'; ++p)
    {
        if (*p >= 'A' && *p <= 'F')
        {
            *p = static_cast<char>(*p + ('a' - 'A'));
        }
    }
}

char * IPAddress::ToString(char * buf, uint32_t bufSize) const
{
#if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
#if INET_CONFIG_ENABLE_IPV4
    if (IsIPv4())
    {
        ip4_addr_t ip4_addr = ToIPv4();
        ip4addr_ntoa_r(&ip4_addr, buf, (int) bufSize);
    }
    else
#endif // INET_CONFIG_ENABLE_IPV4
    {
        ip6_addr_t ip6_addr = ToIPv6();
        ip6addr_ntoa_r(&ip6_addr, buf, (int) bufSize);
        // Normalize to lowercase per RFC 5952 (canonical IPv6 text form).
        NormalizeIp6ToLower(buf);
    }
#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK
    // socklen_t is sometimes signed, sometimes not, so the only safe way to do
    // this is to promote everything to an unsigned type that's known to be big
    // enough for everything, then cast back to uint32_t after taking the min.
    bufSize = static_cast<uint32_t>(
        std::min(static_cast<uintmax_t>(std::numeric_limits<socklen_t>::max()), static_cast<uintmax_t>(bufSize)));
#if INET_CONFIG_ENABLE_IPV4
    if (IsIPv4())
    {
        const void * addr = &Addr[3];
        const char * s    = inet_ntop(AF_INET, addr, buf, static_cast<socklen_t>(bufSize));
        // This cast is safe because |s| points into |buf| which is not const.
        buf = const_cast<char *>(s);
    }
    else
#endif // INET_CONFIG_ENABLE_IPV4
    {
        const void * addr = &Addr[0];
        const char * s    = inet_ntop(AF_INET6, addr, buf, static_cast<socklen_t>(bufSize));
        // This cast is safe because |s| points into |buf| which is not const.
        buf = const_cast<char *>(s);
    }
#elif CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
    otIp6Address addr = ToIPv6();
    otIp6AddressToString(&addr, buf, static_cast<uint16_t>(bufSize));
    // Normalize to lowercase per RFC 5952 (canonical IPv6 text form).
    NormalizeIp6ToLower(buf);
#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP

    return buf;
}

char * IPAddress::ToString(char * buf, uint32_t bufSize, const Inet::InterfaceId & interfaceId) const
{
    if (IsIPv6LinkLocal() && interfaceId.IsPresent())
    {
        char ipStr[IPAddress::kMaxStringLength];
        if (ToString(ipStr, sizeof(ipStr)) == nullptr)
        {
            return nullptr;
        }

        // Normalize to lowercase per RFC 5952 (canonical IPv6 text form).
        NormalizeIp6ToLower(ipStr);

        StringBuilderBase builder(buf, bufSize);
        builder.Add(ipStr);

        char ifName[Inet::InterfaceId::kMaxIfNameLength];
        if (interfaceId.GetInterfaceName(ifName, sizeof(ifName)) == CHIP_NO_ERROR)
        {
            builder.Add("%").Add(ifName);
        }

        return builder.Fit() ? buf : nullptr;
    }

    return ToString(buf, bufSize);
}

bool IPAddress::FromString(const char * str, IPAddress & output)
{
#if INET_CONFIG_ENABLE_IPV4
    if (strchr(str, ':') == nullptr)
    {
#if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
        ip4_addr_t ipv4Addr;
        if (!ip4addr_aton(str, &ipv4Addr))
            return false;
#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK
        struct in_addr ipv4Addr;
        if (inet_pton(AF_INET, str, &ipv4Addr) < 1)
            return false;
#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP
        output = IPAddress(ipv4Addr);
    }
    else
#endif // INET_CONFIG_ENABLE_IPV4
    {
#if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
        ip6_addr_t ipv6Addr;
        if (!ip6addr_aton(str, &ipv6Addr))
            return false;
#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK
        struct in6_addr ipv6Addr;
        if (inet_pton(AF_INET6, str, &ipv6Addr) < 1)
            return false;
#elif CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
        otIp6Address ipv6Addr;
        if (OT_ERROR_NONE != otIp6AddressFromString(str, &ipv6Addr))
            return false;
#endif
        output = IPAddress(ipv6Addr);
    }

    return true;
}

bool IPAddress::FromString(const char * str, size_t strLen, IPAddress & output)
{
    bool res = false;

    if (strLen < INET6_ADDRSTRLEN)
    {
        char hostNameBuf[INET6_ADDRSTRLEN];
        memcpy(hostNameBuf, str, strLen);
        hostNameBuf[strLen] = 0;
        res                 = IPAddress::FromString(hostNameBuf, output);
    }

    return res;
}

bool IPAddress::FromString(const char * str, IPAddress & addrOutput, class InterfaceId & ifaceOutput)
{
    char * addrStr       = const_cast<char *>(str);
    char * addrPart      = nullptr;
    char * scopePart     = nullptr;
    char * strtokContext = nullptr;

    addrPart = strtok_r(addrStr, "%", &strtokContext);
    if (addrPart != nullptr)
    {
        scopePart = strtok_r(nullptr, "%", &strtokContext);
    }

    if (addrPart == nullptr || scopePart == nullptr)
    {
        ifaceOutput = Inet::InterfaceId();
        return Inet::IPAddress::FromString(addrStr, addrOutput);
    }

    CHIP_ERROR err = Inet::InterfaceId::InterfaceNameToId(scopePart, ifaceOutput);
    if (err != CHIP_NO_ERROR)
    {
        return false;
    }
    return Inet::IPAddress::FromString(addrPart, addrOutput);
}

} // namespace Inet
} // namespace chip
