Commit 59f718f0 authored by Luker's avatar Luker

Added lattice

parent 0c912b10
......@@ -216,6 +216,8 @@ SET(SOURCES src/Fenrir/v1/wrapper/include_all.cpp)
SET(HEADERS src/Fenrir/v1/API/Report.hpp
src/Fenrir/v1/auth/Auth.hpp
src/Fenrir/v1/auth/Lattice.hpp
src/Fenrir/v1/auth/Lattice.ipp
src/Fenrir/v1/auth/Token.hpp
src/Fenrir/v1/crypto/Crypto.hpp
src/Fenrir/v1/crypto/Crypto_NULL.hpp
......@@ -273,6 +275,7 @@ SET(HEADERS src/Fenrir/v1/API/Report.hpp
src/Fenrir/v1/resolve/DNSSEC.ipp
src/Fenrir/v1/resolve/Resolver.hpp
src/Fenrir/v1/service/Service.hpp
src/Fenrir/v1/service/Service_Info.hpp
src/Fenrir/v1/service/Service_ID.hpp
src/Fenrir/v1/util/hash.hpp
src/Fenrir/v1/util/endian.hpp
......
......@@ -24,6 +24,7 @@
#include "Fenrir/v1/util/Shared_Lock.ipp"
#include "Fenrir/v1/plugin/Loader.ipp"
#include "Fenrir/v1/auth/Lattice.ipp"
#include "Fenrir/v1/data/control/Control.ipp"
#include "Fenrir/v1/data/Conn0.ipp"
#include "Fenrir/v1/data/packet/Stream.ipp"
......
......@@ -20,47 +20,17 @@
#pragma once
#include "Fenrir/v1/libFenrir.hpp"
#include "Fenrir/v1/data/Username.hpp"
#include "Fenrir/v1/utils/hash.hpp"
#include <memory>
#include <mutex>
#include <unordered_map>
#include <vector>
#include "../libFenrir.hpp"
#include "Username.hpp"
#include "../Utils/hash.hpp"
namespace Fenrir {
namespace Auth {
class FENRIR_LOCAL Lattice_Node
{
public:
std::vector<uint8_t> name;
std::vector<std::weak_ptr<Lattice_Node>> parents;
std::vector<std::shared_ptr<Lattice_Node>> children;
uint8_t id;
Lattice_Node (uint8_t _id, const std::vector<uint8_t> &_name)
:name(_name), id(_id) {}
std::vector<uint8_t> serialize();
};
class FENRIR_LOCAL Lattice
{
public:
Lattice (const std::vector<uint8_t> &raw);
operator bool() const; // check validity of parsed lattice
bool exists (uint8_t id);
bool includes (uint8_t parent, uint8_t child);
std::vector<uint8_t> serialize();
private:
std::shared_ptr<Lattice_Node> top;
std::shared_ptr<Lattice_Node> find (std::shared_ptr<Lattice_Node> from,
uint8_t id, std::vector<uint8_t> &out);
};
class FENRIR_LOCAL Manager
{
// Manage lattices, authentication tokens, usernames.
......
/*
* Copyright (c) 2017, Luca Fulchir<luca@fulchir.it>, All rights reserved.
*
* This file is part of libFenrir.
*
* libFenrir is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* libFenrir is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* and a copy of the GNU Lesser General Public License
* along with libFenrir. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "Fenrir/v1/common.hpp"
#include <gsl/span>
#include <memory>
#include <vector>
namespace Fenrir__v1 {
namespace Impl {
class FENRIR_LOCAL Lattice_Node
{
public:
std::vector<uint8_t> _name;
std::vector<std::weak_ptr<Lattice_Node>> _parents;
std::vector<std::shared_ptr<Lattice_Node>> _children;
uint8_t _id;
Lattice_Node() = delete;
Lattice_Node (const uint8_t id, const gsl::span<const uint8_t> name)
:_id (id)
{
_name.reserve (static_cast<size_t> (name.size()));
std::copy (name.begin(), name.end(), std::back_inserter (_name));
}
Lattice_Node (const Lattice_Node&) = default;
Lattice_Node& operator= (const Lattice_Node&) = default;
Lattice_Node (Lattice_Node &&) = default;
Lattice_Node& operator= (Lattice_Node &&) = default;
~Lattice_Node() = default;
};
class FENRIR_LOCAL Lattice
{
public:
// id 0 is reserved (top), id 255 is reserved (bottom)
Lattice ();
Lattice (const gsl::span<const uint8_t> raw);
Lattice (const Lattice&) = default;
Lattice& operator= (const Lattice&) = default;
Lattice (Lattice &&) = default;
Lattice& operator= (Lattice &&) = default;
~Lattice() = default;
operator bool() const;
bool exists (const uint8_t id) const;
bool includes (const uint8_t parent, const uint8_t child) const;
bool add_node (const uint8_t id, const gsl::span<const uint8_t> name,
const std::vector<uint8_t> parents);
size_t raw_size() const;
// output format:
// 1b Node ID
// 1b Name length (max 30) + Xbytes: raw name
// 1b number of parents + list of parents (1b each)
bool write (gsl::span<uint8_t> out) const;
private:
static constexpr uint8_t TOP = 0x00, BOTTOM = 0xFF;
static constexpr uint8_t MAX_NAME = 30;
std::shared_ptr<Lattice_Node> _top;
std::shared_ptr<Lattice_Node> find(const std::shared_ptr<Lattice_Node> from,
const uint8_t id) const;
};
} // namespace Impl
} // namespace Fenrir__v1
/*
* Copyright (c) 2017, Luca Fulchir<luca@fulchir.it>, All rights reserved.
*
* This file is part of libFenrir.
*
* libFenrir is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* libFenrir is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* and a copy of the GNU Lesser General Public License
* along with libFenrir. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "Fenrir/v1/common.hpp"
#include "Fenrir/v1/auth/Lattice.hpp"
#include <array>
#include <deque>
namespace Fenrir__v1 {
namespace Impl {
namespace {
constexpr std::array<const uint8_t, 3> lattice_a_TOP {{ 't', 'o', 'p'}};
constexpr std::array<const uint8_t, 6> lattice_a_BOTTOM {{
'b','o','t','t','o','m' }};
}
FENRIR_INLINE Lattice::Lattice()
{
auto bottom = std::make_shared<Lattice_Node> (BOTTOM,
gsl::span<const uint8_t> {lattice_a_BOTTOM});
_top = std::make_shared<Lattice_Node> (TOP,
gsl::span<const uint8_t> {lattice_a_TOP});
_top->_children.emplace_back (bottom);
bottom->_parents.emplace_back (_top);
}
FENRIR_INLINE Lattice::Lattice (const gsl::span<const uint8_t> raw)
{
auto bottom = std::make_shared<Lattice_Node> (BOTTOM,
gsl::span<const uint8_t> {lattice_a_BOTTOM});
_top = std::make_shared<Lattice_Node> (TOP,
gsl::span<const uint8_t> {lattice_a_TOP});
_top->_children.emplace_back (bottom);
bottom->_parents.emplace_back (_top);
ssize_t idx = 0;
while (idx < raw.size()) {
if (raw.size() - idx < 4) {
_top = nullptr;
return;
}
const uint8_t node_id = raw[idx++];
if (node_id == TOP || node_id == BOTTOM) {
_top = nullptr;
return;
}
const uint8_t name_len = raw[idx++];
if (name_len > MAX_NAME || (idx + MAX_NAME) > raw.size()) {
_top = nullptr;
return;
}
const gsl::span<const uint8_t> name (raw.data() + idx, name_len);
idx += name_len;
const uint8_t parents_len = raw[idx++];
if (idx + parents_len > raw.size()) {
_top = nullptr;
return;
}
std::vector<uint8_t> parents (parents_len);
while (parents_len > 0) {
const uint8_t parent_id = raw[idx];
if (parent_id == BOTTOM) {
_top = nullptr;
return;
}
parents.push_back (parent_id);
++idx;
}
if (!add_node (node_id, name, parents)) {
_top = nullptr;
return;
}
}
}
FENRIR_INLINE Lattice::operator bool() const
{ return _top != nullptr; }
FENRIR_INLINE bool Lattice::exists (const uint8_t id) const
{
if (find (_top, id) == nullptr)
return false;
return true;
}
FENRIR_INLINE bool Lattice::includes (const uint8_t parent,
const uint8_t child) const
{
auto node = find (_top, parent);
if (find (node, child) == nullptr)
return false;
return true;
}
FENRIR_INLINE bool Lattice::add_node (const uint8_t id,
const gsl::span<const uint8_t> name,
const std::vector<uint8_t> parents)
{
// limit name to 30 chars.
if (name.size() > MAX_NAME)
return false;
if (find (_top, id) != nullptr)
return false; // already present
std::vector<std::shared_ptr<Lattice_Node>> sh_parents;
sh_parents.reserve (parents.size());
for (const auto p : parents) {
if (p == BOTTOM)
return false;
auto tmp = find (_top, p);
if (tmp == nullptr)
return false; // parent missing
sh_parents.push_back (tmp);
}
// find bottom quickly (find() is actually BFS)
auto bot = _top;
while (bot->_id != BOTTOM)
bot = bot->_children.front();
auto node = std::make_shared<Lattice_Node> (id, name);
node->_children.push_back(find (_top, BOTTOM));
for (auto p : sh_parents) {
if (p->_children[0]->_id == BOTTOM)
p->_children.clear();
p->_children.push_back (node);
node->_parents.push_back (p);
}
return true;
}
FENRIR_INLINE size_t Lattice::raw_size() const
{
// BFS
size_t ret_size = 0;
std::deque<std::shared_ptr<Lattice_Node>> queue;
// skip top and bottom, they do not need to be saved
for (auto x : _top->_children) {
if (x->_id == BOTTOM)
break;
queue.push_back (x);
}
while (queue.size() > 0) {
auto x = queue.front();
queue.pop_front();
ret_size += 1 + // Node ID
1 + x->_name.size() + // length + name
1 + x->_parents.size(); // length + ids
for (auto child : x->_children)
queue.push_back (child);
}
return ret_size;
}
FENRIR_INLINE bool Lattice::write (gsl::span<uint8_t> out) const
{
if (static_cast<size_t> (out.size()) != raw_size())
return false;
// BFS
std::deque<std::shared_ptr<Lattice_Node>> queue;
queue.push_back (_top);
auto it = out.begin();
while (queue.size() > 0) {
auto x = queue.front();
queue.pop_front();
for (auto child : x->_children)
queue.push_back (child);
*it = x->_id;
*it = static_cast<uint8_t> (x->_name.size());
for (const uint8_t el : x->_name)
*(it++) = el;
*it = static_cast<uint8_t> (x->_parents.size());
for (auto weak_p : x->_parents) {
auto sh_p = weak_p.lock();
assert (sh_p != nullptr && "Lattice_Write:: parent nullptr");
*(it++) = sh_p->_id;
}
}
return true;
}
FENRIR_INLINE std::shared_ptr<Lattice_Node> Lattice::find (
const std::shared_ptr<Lattice_Node> from,
const uint8_t id) const
{
// BFS
std::deque<std::shared_ptr<Lattice_Node>> queue;
queue.push_back (from);
while (queue.size() > 0) {
auto x = queue.front();
queue.pop_front();
if (x->_id == id)
return x;
for (auto child : x->_children)
queue.push_back (child);
}
return nullptr;
}
} // namespace Impl
} // namespace Fenrir__v1
/*
* Copyright (c) 2017, Luca Fulchir<luca@fulchir.it>, All rights reserved.
*
* This file is part of libFenrir.
*
* libFenrir is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* libFenrir is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* and a copy of the GNU Lesser General Public License
* along with libFenrir. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "Fenrir/v1/common.hpp"
#include "Fenrir/v1/auth/Lattice.hpp"
#include "Fenrir/v1/data/Storage_t.hpp"
#include "Fenrir/v1/data/packet/Stream.hpp"
#include "Fenrir/v1/service/Service_ID.hpp"
#include <algorithm>
#include <atomic>
#include <memory>
#include <type_safe/strong_typedef.hpp>
#include <vector>
#include <tuple>
namespace Fenrir__v1 {
namespace Impl {
// lockless, thread safe.
class FENRIR_LOCAL Service_Info
{
public:
using stream_info = std::vector<Storage_t, Stream_PRIO>;
Service_Info()
: _info (nullptr)
{}
Service_Info (const Service_Info&) = delete;
Service_Info& operator= (const Service_Info&) = delete;
Service_Info (Service_Info &&) = default;
Service_Info& operator= (Service_Info &&) = default;
~Service_Info() = default;
stream_info get_streams (const Service_ID &service) const
{
auto p = _info.load();
if (p == nullptr)
return stream_info{};
auto res = std::lower_bound (p->begin(), p->end(), service,
[] (const auto it, const Service_ID &id)
{
return std::get<Service_ID> (it) < id;
}
if (std::get<Service_ID> (*res) == service))
return std::get<stream_info> (*res);
return stream_info{};
}
Lattice get_lattice (const Service_ID &service) const
{
auto p = _info.load();
if (p == nullptr)
return Lattice{};
auto res = std::lower_bound (p->begin(), p->end(), service,
[] (const auto it, const Service_ID &id)
{
return std::get<Service_ID> (it) < id;
}
if (std::get<Service_ID> (*res) == service))
return std::get<Lattice> (*res);
return Lattice{};
}
bool add_service (const Service_ID id, stream_info &streams,
Lattice &lattice)
{
std::shared_ptr<std::vector<std::tuple<Service_ID, stream_info>>>
current, copy;
do {
current = _info.load();
size_t cur_size = 0;
if (current != nullptr)
cur_size = current->size();
copy = std::make_shared<std::vector<
std::tuple<Service_ID, stream_info>>> (
cur_size + 1);
for (size_t idx = 0; idx < cur_size; ++idx) {
copy->push_back ((*current)[idx]);
}
copy->emplace_back (id, streams, lattice);
} while (!_info.compare_exchange_strong (current, copy));
return true;
}
private:
// TODO: test thread safety
std::atomic<std::shared_ptr<std::vector<
std::tuple<Service_ID, stream_info, Lattice>>>> _info;
};
} // namespace Impl
} // namespace Fenrir__v1
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment