/*
 *
 * 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"

// Ensure we get all of winsock2.h
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif

#include <winsock2.h>
#include <ws2tcpip.h>
#include <string.h>

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;
        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(((::sockaddr_in*)addr)->sin_port);
        case AF_INET6: return ntohs(((::sockaddr_in6*)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 (Exception) {
            // failed to resolve hi
            return false;
        }
    } catch (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) {
        struct sockaddr_in* sin4lo = (struct sockaddr_in*)lo.ai_addr;
        struct sockaddr_in* sin4hi = (struct sockaddr_in*)hi.ai_addr;
        result = memcmp(&sin4hi->sin_addr, &sin4lo->sin_addr, sizeof(in_addr));
    } else if (lo.ai_family == AF_INET6) {
        struct sockaddr_in6* sin6lo = (struct sockaddr_in6*)lo.ai_addr;
        struct sockaddr_in6* sin6hi = (struct sockaddr_in6*)hi.ai_addr;
        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->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_flags = AI_ADDRCONFIG; // Only use protocols that we have configured interfaces for
        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 {
            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;
}

}}
