Skip to content

Commit

Permalink
snp quic
Browse files Browse the repository at this point in the history
Signed-off-by: turuslan <[email protected]>
  • Loading branch information
turuslan committed Feb 11, 2025
1 parent 7c57b37 commit 1b02d30
Show file tree
Hide file tree
Showing 65 changed files with 3,340 additions and 0 deletions.
4 changes: 4 additions & 0 deletions BUILD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

```bash
brew install nasm # vcpkg liblsquic
```
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,13 @@ pkg_check_modules(libb2 REQUIRED IMPORTED_TARGET GLOBAL libb2)
find_package(Boost CONFIG REQUIRED)
find_package(fmt CONFIG REQUIRED)
find_package(jam_crust CONFIG REQUIRED)
find_package(lsquic CONFIG REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(scale CONFIG REQUIRED)
find_package(schnorrkel_crust CONFIG REQUIRED)
find_package(ZLIB REQUIRED)

include(vcpkg-overlay/cppcodec.cmake)

add_library(headers INTERFACE)
target_include_directories(headers INTERFACE
Expand Down
33 changes: 33 additions & 0 deletions src/TODO_qtils/asio_buffer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Copyright Quadrivium LLC
* All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <boost/asio/buffer.hpp>
#include <qtils/bytes.hpp>

namespace qtils {
inline boost::asio::const_buffer asioBuffer(BytesIn s) {
return {s.data(), s.size()};
}

boost::asio::mutable_buffer asioBuffer(auto &&t)
requires(requires { BytesOut{t}; })
{
BytesOut s{t};
return {s.data(), s.size()};
}

inline BytesIn asioBuffer(const boost::asio::const_buffer &s) {
// NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
return {reinterpret_cast<const uint8_t *>(s.data()), s.size()};
}

inline BytesOut asioBuffer(const boost::asio::mutable_buffer &s) {
// NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
return {reinterpret_cast<uint8_t *>(s.data()), s.size()};
}
} // namespace qtils
30 changes: 30 additions & 0 deletions src/TODO_qtils/from_span.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Copyright Quadrivium LLC
* All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <optional>
#include <qtils/bytes.hpp>
#include <stdexcept>

namespace qtils {
inline bool fromSpan(BytesOut out, BytesIn span) {
if (span.size() != out.size()) {
return false;
}
memcpy(out.data(), span.data(), out.size());
return true;
}

template <typename T>
std::optional<T> fromSpan(BytesIn span) {
T out;
if (not fromSpan(out, span)) {
return std::nullopt;
}
return out;
}
} // namespace qtils
11 changes: 11 additions & 0 deletions src/TODO_qtils/macro/forward.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Copyright Quadrivium LLC
* All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <utility>

#define FORWARD(x) std::forward<decltype(x)>(x)
16 changes: 16 additions & 0 deletions src/TODO_qtils/macro/make_shared.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Copyright Quadrivium LLC
* All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <memory>

#define MAKE_SHARED_(x_, ...) \
x_ { \
std::make_shared<decltype(x_)::element_type>(__VA_ARGS__) \
}

#define MAKE_SHARED_T(T, ...) std::make_shared<T::element_type>(__VA_ARGS__)
19 changes: 19 additions & 0 deletions src/TODO_qtils/macro/move.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Copyright Quadrivium LLC
* All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <utility>

#define MOVE(x) \
x { \
std::move(x) \
}

#define MOVE_(x) \
x##_ { \
std::move(x) \
}
18 changes: 18 additions & 0 deletions src/TODO_qtils/macro/weak.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Copyright Quadrivium LLC
* All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <memory>

#define WEAK_SELF \
weak_self { \
weak_from_this() \
}

#define WEAK_LOCK(name) \
auto name = weak_##name.lock(); \
if (not name) return
84 changes: 84 additions & 0 deletions src/TODO_qtils/map_entry.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* Copyright Quadrivium LLC
* All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <map>
#include <stdexcept>
#include <unordered_map>
#include <variant>

namespace qtils {
template <typename M>
struct MapEntry {
using I = typename M::iterator;
using K = typename M::key_type;

MapEntry(M &map, const K &key) : map{map} {
if (auto it = map.find(key); it != map.end()) {
it_or_key = it;
} else {
it_or_key = key;
}
}

bool has() const {
return std::holds_alternative<I>(it_or_key);
}
operator bool() const {
return has();
}
auto &operator*() {
if (not has()) {
throw std::logic_error{"MapEntry::operator*"};
}
return std::get<I>(it_or_key)->second;
}
auto *operator->() {
if (not has()) {
throw std::logic_error{"MapEntry::operator->"};
}
return &std::get<I>(it_or_key)->second;
}
void insert(M::mapped_type value) {
if (has()) {
throw std::logic_error{"MapEntry::insert"};
}
it_or_key =
map.emplace(std::move(std::get<K>(it_or_key)), std::move(value))
.first;
}
void insert_or_assign(M::mapped_type value) {
if (not has()) {
insert(std::move(value));
} else {
**this = std::move(value);
}
}
M::mapped_type remove() {
if (not has()) {
throw std::logic_error{"MapEntry::remove"};
}
auto node = map.extract(std::get<I>(it_or_key));
it_or_key = std::move(node.key());
return std::move(node.mapped());
}

// NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
M &map;
std::variant<I, K> it_or_key{};
};

template <typename K, typename V, typename L, typename A>
auto entry(std::map<K, V, L, A> &map, const K &key) {
return MapEntry<std::remove_cvref_t<decltype(map)>>{map, key};
}

template <typename K, typename V, typename H, typename E, typename A>
auto entry(std::unordered_map<K, V, H, E, A> &map, const K &key) {
return MapEntry<std::remove_cvref_t<decltype(map)>>{map, key};
}
} // namespace qtils
16 changes: 16 additions & 0 deletions src/TODO_qtils/std_hash_of.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Copyright Quadrivium LLC
* All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <utility>

namespace qtils {
template <typename T>
size_t stdHashOf(const T &v) {
return std::hash<T>()(v);
}
} // namespace qtils
2 changes: 2 additions & 0 deletions src/jam/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
# All Rights Reserved
# SPDX-License-Identifier: Apache-2.0
#

add_subdirectory(snp)
49 changes: 49 additions & 0 deletions src/jam/coro/coro.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Copyright Quadrivium LLC
* All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <boost/asio/awaitable.hpp>
#include <qtils/outcome.hpp>

namespace jam {
/**
* Return type for coroutine.
*
* Does not resume when:
* - called directly outside executor, returns coroutine.
* - `coroSpawn` called when not running inside executor,
* resumes on next executor tick.
* int main() {
* boost::asio::io_context io;
* coroSpawn(io, []() -> Coro<void> { co_return; }); // suspended
* io.run_one(); // resumes
* // may complete before next statement
* }
* Resumes when:
* - `coroSpawn` when running inside specified executor.
* post(executor, [] {
* coroSpawn(executor, []() -> Coro<void> { co_return; }) // resumes
* // may complete before next statement
* })
* co_await coroSpawn([]() -> Coro<void> { co_return; }) // resumes
* // may complete before next statement
* - `co_await`
* co_await foo() // resumes
* // may complete before next statement
* After resuming may complete before specified statement ends.
*
* Use `CORO_YIELD` explicitly to suspend coroutine until next executor tick.
*/
template <typename T>
using Coro = boost::asio::awaitable<T>;

/**
* Return type for coroutine returning outcome.
*/
template <typename T>
using CoroOutcome = Coro<outcome::result<T>>;
} // namespace jam
66 changes: 66 additions & 0 deletions src/jam/coro/future.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* Copyright Quadrivium LLC
* All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <TODO_qtils/macro/move.hpp>
#include <deque>
#include <jam/coro/handler.hpp>
#include <jam/coro/set_thread.hpp>
#include <stdexcept>
#include <variant>

namespace jam {
template <typename T>
class SharedFuture {
public:
using Self = std::shared_ptr<SharedFuture<T>>;

SharedFuture(IoContextPtr io_context_ptr) : MOVE_(io_context_ptr) {}

static Coro<bool> ready(Self self) {
SET_CORO_THREAD(self->io_context_ptr_);
co_return std::holds_alternative<T>(self->state_);
}

/**
* Resumes coroutine immediately or inside `set`.
*/
static Coro<T> get(Self self) {
SET_CORO_THREAD(self->io_context_ptr_);
if (auto *value = std::get_if<T>(&self->state_)) {
co_return *value;
}
auto &handlers = std::get<Handlers>(self->state_);
co_return co_await coroHandler<T>([&](CoroHandler<T> &&handler) {
handlers.emplace_back(std::move(handler));
});
}

/**
* Set value and wake waiting coroutines.
* Coroutines may complete before `set` returns.
*/
static Coro<void> set(Self self, T value) {
SET_CORO_THREAD(self->io_context_ptr_);
if (std::holds_alternative<T>(self->state_)) {
throw std::logic_error{"SharedFuture::set must be called once"};
}
auto handlers = std::move(std::get<Handlers>(self->state_));
self->state_ = std::move(value);
auto &state_value = std::get<T>(self->state_);
for (auto &handler : handlers) {
handler(state_value);
}
}

private:
using Handlers = std::deque<CoroHandler<T>>;

IoContextPtr io_context_ptr_;
std::variant<Handlers, T> state_;
};
} // namespace jam
Loading

0 comments on commit 1b02d30

Please sign in to comment.