/*
 *
 *    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 <lib/support/CodeUtils.h>

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

namespace chip {
namespace Inet {

char * IPAddress::ToString(char * buf, uint32_t bufSize) const
{
#if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_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);
    }
#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_OPEN_THREAD_ENDPOINT
    otIp6Address addr = ToIPv6();
    otIp6AddressToString(&addr, buf, static_cast<uint16_t>(bufSize));
#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP

    return buf;
}

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_OPEN_THREAD_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_OPEN_THREAD_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_OPEN_THREAD_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
