/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * 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.
 */
#define LOG_TAG "Netd"

#include "Network.h"

#include "RouteController.h"
#include "SockDiag.h"
#include "log/log.h"

#include <android-base/strings.h>
#include <sstream>

namespace android {
namespace net {

Network::~Network() {
    if (!mInterfaces.empty()) {
        ALOGE("deleting network with netId %u without clearing its interfaces", mNetId);
    }
}

unsigned Network::getNetId() const {
    return mNetId;
}

bool Network::hasInterface(const std::string& interface) const {
    return mInterfaces.find(interface) != mInterfaces.end();
}

const std::set<std::string>& Network::getInterfaces() const {
    return mInterfaces;
}

int Network::clearInterfaces() {
    while (!mInterfaces.empty()) {
        // Make a copy of the string, so removeInterface() doesn't lose its parameter when it
        // removes the string from the set.
        std::string interface = *mInterfaces.begin();
        if (int ret = removeInterface(interface)) {
            return ret;
        }
    }
    return 0;
}

std::string Network::toString() const {
    const char kSeparator[] = " ";
    std::stringstream repr;

    repr << mNetId << kSeparator << getTypeString();

    if (mInterfaces.size() > 0) {
        repr << kSeparator << android::base::Join(mInterfaces, ",");
    }

    return repr.str();
}

std::string Network::uidRangesToString() const {
    if (mUidRangeMap.empty()) {
        return "";
    }

    std::ostringstream result;
    for (auto it = mUidRangeMap.begin(); it != mUidRangeMap.end(); ++it) {
        result << "prio " << it->first << " " << it->second.toString();
        if (std::next(it) != mUidRangeMap.end()) result << "; ";
    }
    return result.str();
}

// Check if the user has been added to this network. If yes, the highest priority of matching
// setting is returned by subPriority. Thus caller can make choice among several matching
// networks.
bool Network::appliesToUser(uid_t uid, uint32_t* subPriority) const {
    for (const auto& [priority, uidRanges] : mUidRangeMap) {
        if (uidRanges.hasUid(uid)) {
            *subPriority = priority;
            return true;
        }
    }
    return false;
}

void Network::addToUidRangeMap(const UidRanges& uidRanges, uint32_t subPriority) {
    auto iter = mUidRangeMap.find(subPriority);
    if (iter != mUidRangeMap.end()) {
        iter->second.add(uidRanges);
    } else {
        mUidRangeMap[subPriority] = uidRanges;
    }
}

void Network::removeFromUidRangeMap(const UidRanges& uidRanges, uint32_t subPriority) {
    auto iter = mUidRangeMap.find(subPriority);
    if (iter != mUidRangeMap.end()) {
        iter->second.remove(uidRanges);
        if (iter->second.empty()) {
            mUidRangeMap.erase(subPriority);
        }
    } else {
        ALOGW("uidRanges with priority %u not found", subPriority);
    }
}

bool Network::canAddUidRanges(const UidRanges& uidRanges, uint32_t subPriority) const {
    if (uidRanges.overlapsSelf()) {
        ALOGE("uid range %s overlaps self", uidRanges.toString().c_str());
        return false;
    }

    auto iter = mUidRangeMap.find(subPriority);
    if (iter != mUidRangeMap.end() && uidRanges.overlaps(iter->second)) {
        ALOGE("uid range %s overlaps priority %u %s", uidRanges.toString().c_str(), subPriority,
              iter->second.toString().c_str());
        return false;
    }
    return true;
}

bool Network::isSecure() const {
    return mSecure;
}

Network::Network(unsigned netId, bool secure) : mNetId(netId), mSecure(secure) {}

}  // namespace net
}  // namespace android
