/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 *
 */

#include "qpid/sys/SocketAddress.h"

#include "qpid/Exception.h"
#include "qpid/Msg.h"
#include "qpid/log/Logger.h"

#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <arpa/inet.h>
#include <iosfwd>

namespace qpid {
namespace sys {

SocketAddress::SocketAddress(const std::string& host0, const std::string& port0) :
    host(host0),
    port(port0),
    addrInfo(0),
    currentAddrInfo(0)
{
}

SocketAddress::SocketAddress(const SocketAddress& sa) :
    host(sa.host),
    port(sa.port),
    addrInfo(0),
    currentAddrInfo(0)
{
}

SocketAddress& SocketAddress::operator=(const SocketAddress& sa)
{
    SocketAddress temp(sa);

    std::swap(temp.host, host);
    std::swap(temp.port, port);
    std::swap(temp.addrInfo, addrInfo);
    std::swap(temp.currentAddrInfo, currentAddrInfo);

    return *this;
}

SocketAddress::~SocketAddress()
{
    if (addrInfo) {
        ::freeaddrinfo(addrInfo);
    }
}

std::string SocketAddress::asString(::sockaddr const * const addr, size_t addrlen, bool dispNameOnly, bool hideDecoration)
{
    char servName[NI_MAXSERV];
    char dispName[NI_MAXHOST];
    if (int rc=::getnameinfo(addr, addrlen,
                             dispName, sizeof(dispName),
                             servName, sizeof(servName),
                             NI_NUMERICHOST | NI_NUMERICSERV) != 0)
        throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
    std::string s;
    switch (addr->sa_family) {
        case AF_INET: s += dispName; break;
        case AF_INET6:
            if (!hideDecoration) {
                s += "["; s += dispName; s+= "]";
            } else {
                s += dispName;
            }
            break;
        case AF_UNIX: s += "UNIX:"; break;
        default: throw Exception(QPID_MSG("Unexpected socket type"));
    }
    if (!dispNameOnly) {
        s += ":";
        s += servName;
    }
    return s;
}

uint16_t SocketAddress::getPort(::sockaddr const * const addr)
{
    switch (addr->sa_family) {
        case AF_INET: return ntohs(((const ::sockaddr_in*)(const void*)addr)->sin_port);
        case AF_INET6: return ntohs(((const ::sockaddr_in6*)(const void*)addr)->sin6_port);
        default:throw Exception(QPID_MSG("Unexpected socket type"));
    }
}

std::string SocketAddress::asString(bool numeric, bool dispNameOnly, bool hideDecoration) const
{
    if (!numeric)
        return host + ":" + port;
    // Canonicalise into numeric id
    const ::addrinfo& ai = getAddrInfo(*this);

    return asString(ai.ai_addr, ai.ai_addrlen, dispNameOnly, hideDecoration);
}

std::string SocketAddress::getHost() const
{
    return host;
}

/**
 * Return true if this SocketAddress is IPv4 or IPv6
 */
bool SocketAddress::isIp() const
{
    const ::addrinfo& ai = getAddrInfo(*this);
    return ai.ai_family == AF_INET || ai.ai_family == AF_INET6;
}

/**
 * this represents the low address of an ACL address range.
 * Given rangeHi that represents the high address,
 * return a string showing the numeric comparisons that the
 * inRange checks will do for address pair.
 */
std::string SocketAddress::comparisonDetails(const SocketAddress& rangeHi) const
{
    std::ostringstream os;
    SocketAddress thisSa(*this);
    SocketAddress rangeHiSa(rangeHi);
    (void) getAddrInfo(thisSa);
    (void) getAddrInfo(rangeHiSa);
    os << "(" << thisSa.asString(true, true, false) <<
          "," << rangeHiSa.asString(true, true, false) << ")";
    while (thisSa.nextAddress()) {
        if (!rangeHiSa.nextAddress()) {
            throw(Exception(QPID_MSG("Comparison iteration fails: " + (*this).asString() +
                                      rangeHi.asString())));
        }
        os << ",(" << thisSa.asString(true, true, false) <<
            "," << rangeHiSa.asString(true, true, false) << ")";
    }
    if (rangeHiSa.nextAddress()) {
        throw(Exception(QPID_MSG("Comparison iteration fails: " + (*this).asString() +
                                    rangeHi.asString())));
    }
    std::string result = os.str();
    return result;
}

/**
 * For ACL address matching make sure that the two addresses, *this
 * which is the low address and hiPeer which is the high address, are
 * both numeric ip addresses of the same family and that hi > *this.
 *
 * Note that if the addresses resolve to more than one struct addrinfo
 * then this and the hiPeer must be equal. This avoids having to do
 * difficult range checks where the this and hiPeer both resolve to
 * multiple IPv4 or IPv6 addresses.
 *
 * This check is run at acl file load time and not at run tme.
 */
bool SocketAddress::isComparable(const SocketAddress& hiPeer) const {
    try {
        // May only compare if this socket is IPv4 or IPv6
        SocketAddress lo(*this);
        const ::addrinfo& peerLoInfo = getAddrInfo(lo);
        if (!(peerLoInfo.ai_family == AF_INET || peerLoInfo.ai_family == AF_INET6)) {
            return false;
        }
        try {
            // May only compare if peer socket is same family
            SocketAddress hi(hiPeer);
            const ::addrinfo& peerHiInfo = getAddrInfo(hi);
            if (peerLoInfo.ai_family != peerHiInfo.ai_family) {
                return false;
            }
            // Host names that resolve to lists are allowed if they are equal.
            // For example: localhost, or fjord.lab.example.com
            if ((*this).asString() == hiPeer.asString()) {
                return true;
            }
            // May only compare if this and peer resolve to single address.
            if (lo.nextAddress() || hi.nextAddress()) {
                return false;
            }
            // Make sure that the lo/hi relationship is ok
            int res;
            if (!compareAddresses(peerLoInfo, peerHiInfo, res) || res < 0) {
                return false;
            }
            return true;
        } catch (const Exception&) {
            // failed to resolve hi
            return false;
        }
    } catch (const Exception&) {
        // failed to resolve lo
        return false;
    }
}

/**
 * *this SocketAddress was created from the numeric IP address of a
 *  connecting host.
 * The lo and hi addresses are the limit checks from the ACL file.
 * Return true if this address is in range of any of the address pairs
 * in the limit check range.
 *
 * This check is executed on every incoming connection.
 */
bool SocketAddress::inRange(const SocketAddress& lo,
                            const SocketAddress& hi) const
{
    (*this).firstAddress();
    lo.firstAddress();
    hi.firstAddress();
    const ::addrinfo& thisInfo = getAddrInfo(*this);
    const ::addrinfo& loInfo   = getAddrInfo(lo);
    const ::addrinfo& hiInfo   = getAddrInfo(hi);
    if (inRange(thisInfo, loInfo, hiInfo)) {
        return true;
    }
    while (lo.nextAddress()) {
        if (!hi.nextAddress()) {
            assert (false);
            throw(Exception(QPID_MSG("Comparison iteration fails: " +
                                     lo.asString() + hi.asString())));
        }
        const ::addrinfo& loInfo = getAddrInfo(lo);
        const ::addrinfo& hiInfo = getAddrInfo(hi);
        if (inRange(thisInfo, loInfo, hiInfo)) {
            return true;
        }
    }
    return false;
}

/**
 * *this SocketAddress was created from the numeric IP address of a
 *  connecting host.
 * The lo and hi addresses are one binary address pair from a range
 * given in an ACL file.
 * Return true if this binary address is '>= lo' and '<= hi'.
 */
bool SocketAddress::inRange(const ::addrinfo& thisInfo,
                            const ::addrinfo& lo,
                            const ::addrinfo& hi) const
{
    int resLo;
    int resHi;
    if (!compareAddresses(lo, thisInfo, resLo)) {
        return false;
    }
    if (!compareAddresses(hi, thisInfo, resHi)) {
        return false;
    }
    if (resLo < 0) {
        return false;
    }
    if (resHi > 0) {
        return false;
    }
    return true;
}

/**
 * Compare this address against two binary low/high addresses.
 * return true with result holding the comparison.
 */
bool SocketAddress::compareAddresses(const struct addrinfo& lo,
                                     const struct addrinfo& hi,
                                     int& result) const
{
    if (lo.ai_family != hi.ai_family) {
        return false;
    }
    if (lo.ai_family == AF_INET) {
        void* taddr;

        taddr = (void*)lo.ai_addr;
        struct sockaddr_in* sin4lo = (struct sockaddr_in*)taddr;
        taddr = (void*)hi.ai_addr;
        struct sockaddr_in* sin4hi = (struct sockaddr_in*)taddr;
        result = memcmp(&sin4hi->sin_addr, &sin4lo->sin_addr, sizeof(in_addr));
    } else if (lo.ai_family == AF_INET6) {
        void* taddr;

        taddr = (void*)lo.ai_addr;
        struct sockaddr_in6* sin6lo = (struct sockaddr_in6*)taddr;
        taddr = (void*)hi.ai_addr;
        struct sockaddr_in6* sin6hi = (struct sockaddr_in6*)taddr;
        result = memcmp(&sin6hi->sin6_addr, &sin6lo->sin6_addr, sizeof(in6_addr));
    } else {
        assert (false);
        return false;
    }
    return true;
}

void SocketAddress::firstAddress() const {
    if (addrInfo) {
        currentAddrInfo = addrInfo;
    } else {
        (void) getAddrInfo(*this);
    }
}

bool SocketAddress::nextAddress() const {
    bool r = (currentAddrInfo) && (currentAddrInfo->ai_next != 0);
    if (r)
        currentAddrInfo = currentAddrInfo->ai_next;
    return r;
}

const ::addrinfo& getAddrInfo(const SocketAddress& sa)
{
    if (!sa.addrInfo) {
        ::addrinfo hints;
        ::memset(&hints, 0, sizeof(hints));
        hints.ai_family = AF_UNSPEC; // Allow both IPv4 and IPv6
        hints.ai_socktype = SOCK_STREAM;

        const char* node = 0;
        if (sa.host.empty()) {
            hints.ai_flags = AI_PASSIVE;
        } else {
            hints.ai_flags = AI_ADDRCONFIG; // Only use protocols that we have configured interfaces for
            node = sa.host.c_str();
        }
        const char* service = sa.port.empty() ? "0" : sa.port.c_str();

        int n = ::getaddrinfo(node, service, &hints, &sa.addrInfo);
        if (n != 0)
            throw Exception(QPID_MSG("Cannot resolve " << sa.asString(false) << ": " << ::gai_strerror(n)));
        sa.currentAddrInfo = sa.addrInfo;
    }

    return *sa.currentAddrInfo;
}

}}
