Compare commits

...

7 Commits

Author SHA1 Message Date
e8d9782ebc Продолжаем 2023-10-28 04:54:14 +03:00
09aff0e709 Разработка продолжена
На самом деле, она и не заканчивалась, просто я вот вчера пошёл в магазин ну типа в пятёрочку тут есть у меня недалеко на углу улицы и короче вот я пошёл иду такой а мне навстречу сам илон макс правда я не шучу реально илон маз к идёт такой и я ему такой привет а он такой тоже здравствуйте я спрашиваю типа как там с теслой и спайс икс а он перебивает меня и говорит смотри сейчас будет фокус ну я такой ладно и он типа раз и взрывается нахуй пиздец я тогда умер кстати
2023-10-20 05:48:20 +03:00
c84c62400b Specs change - so implementation change 2023-09-06 06:11:26 +03:00
ef784580b4 Something idk 2023-08-29 05:16:44 +03:00
c12682dd2a Some tweaks in makefile 2023-08-25 07:26:23 +03:00
c1c1970d04 KLDR almost done, now rly 2023-08-25 06:29:29 +03:00
786460d41b KLDR done (i think) 2023-08-19 21:42:21 +03:00
11 changed files with 719 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
src/.old
src/test.cpp
libstadium.so
libstadiumtest_release
libstadiumtest_sanitizer
libstadiumtest_fortified
pseudo_code.md

40
Makefile Normal file
View File

@ -0,0 +1,40 @@
# libstadium makefile
CC = g++
CFLAGS_DEFAULT = -march=native -std=c++23 -fno-rtti
CFLAGS_DEBUG = -ggdb -Wall -Werror -Wno-reorder -Wno-uninitialized -fanalyzer -Wno-analyzer-use-of-uninitialized-value
#CFLAGS_DEBUG_S = -O0 -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow
CFLAGS_DEBUG_F = -O1 -D_FORTIFY_SOURCE=3
CFLAGS_RELEASE = -static-libgcc -static-libstdc++ -static -Ofast -fdevirtualize-speculatively -fdata-sections -ffunction-sections -Wl,-gc-sections -Wl,-strip-all -Wl,-strip-discarded -flto -s -D_FORTIFY_SOURCE=3
SOURCES = src/Stadium.hpp src/Stadium.cpp \
src/Event.hpp src/Event.cpp \
src/Worker.hpp src/Worker.cpp \
src/KLDR.hpp \
src/Utils.hpp
SOURCES_TEST = src/test.cpp
#LINKED_LIBS = -l
OUTPUT_LIB = libstadium.so
OUTPUT_TEST_BIN = libstadiumtest_release
#OUTPUT_TEST_BIN_S = libstadiumtest_sanitizer
OUTPUT_TEST_BIN_F = libstadiumtest_fortified
default: clean release_test
debug_test: $(SOURCES) $(SOURCES_TEST)
$(CC) $(CFLAGS_DEFAULT) $(CFLAGS_DEBUG) $(CFLAGS_DEBUG_F) $(SOURCES) $(SOURCES_TEST) -o $(OUTPUT_TEST_BIN_F)
debug: $(SOURCES)
echo "NYI"
release_test: $(SOURCES)
$(CC) $(CFLAGS_DEFAULT) $(CFLAGS_RELEASE) $(SOURCES) $(SOURCES_TEST) -o $(OUTPUT_TEST_BIN)
release: $(SOURCES)
echo "NYI"
clean:
rm -f $(OUTPUT_LIB) $(OUTPUT_TEST_BIN_F) $(OUTPUT_TEST_BIN)

61
src/Event.cpp Normal file
View File

@ -0,0 +1,61 @@
/*
* Event.cpp
* Copyright (c) 2023 Cyclone Team. Licensed under GNU GPLv3-only terms.
*
*/
#include "Event.hpp"
namespace Stadium::v1 {
// Default ctor
Event::Event () {
this->Type.Category = this->Type.Subcategory = this->AsyncID = 0;
}
// Ctor with positional arguments
Event::Event (EventType type, KLDRArray<> data, uint16_t id = 0) : Type(std::move(type)), Payload(std::move(data)), AsyncID(id) {
// TODO: calculate hash
}
// Ctor with positional arguments number two
Event::Event (uint8_t cat, uint8_t subcat, KLDRArray<> data, uint16_t id = 0) : Payload(std::move(data)), AsyncID(id) {
this->Type.Category = cat;
this->Type.Subcategory = subcat;
// TODO: calculate hash
}
// Parse raw data and fill fields from it
void
Event::MakeFrom (const char *data, size_t data_sz) { // TODO: supply hash type/size (???)
if (data_sz < MIN_RAW_EVENT_SIZE)
throw std::invalid_argument("raw event size cant be less than 21 bytes");
this->Type.Category = data[0];
this->Type.Subcategory = data[1];
this->AsyncID = *reinterpret_cast<const uint16_t*>(&data[2]);
// TODO: parse hash
// TODO: parse payload to KLDRArray
}
// Write to stdout info about event
void
Event::Print () const {
printf(
"[Event] Object at: %lu; Category: 0x%.2hhx; Subcategory: 0x%.2hhx; AsyncID: %hu; Payload size: cells: %lu, bytes:%lu\n", // TODO: add hash
reinterpret_cast<size_t>(this),
this->Type.Category,
this->Type.Subcategory,
this->AsyncID,
this->Payload.CellsAmount(),
this->Payload.FlatSize()
);
}
}

67
src/Event.hpp Normal file
View File

@ -0,0 +1,67 @@
/*
* Event.hpp
* Copyright (c) 2023 Cyclone Team. Licensed under GNU GPLv3-only terms.
*
*/
#ifndef LIBSTADIUM_EVENT_HPP
#define LIBSTADIUM_EVENT_HPP
#include <cstdio>
#include <vector>
#include <string>
#include <stdexcept>
#include "KLDR.hpp"
#define MIN_RAW_EVENT_SIZE 21
namespace Stadium::v1 {
// Asynchronous ID of event
typedef uint16_t EventAsyncID;
// Type of event
struct EventType {
uint8_t Category;
uint8_t Subcategory;
};
// Get stringized name of event
std::string ResolveEventType (EventType);
// Event class
class Event final {
uint32_t Lifetime = 0; // Lifetime of event in seconds
// CryptoAlgo HashAlgo; // TODO
// std::vector<char> Hash;
KLDRArray<> Payload;
EventType Type;
EventAsyncID AsyncID;
public:
Event ();//CryptoAlgo);
Event (EventType, KLDRArray<>, uint16_t);
Event (uint8_t, uint8_t, KLDRArray<>, uint16_t);
void MakeFrom (const char *, size_t);
void Print () const;
};
} // namespace Stadium::v1
#endif

309
src/KLDR.hpp Normal file
View File

@ -0,0 +1,309 @@
/*
* KLDR.hpp
* Copyright (c) 2023 Cyclone Team. Licensed under GNU GPLv3-only terms.
*
*/
#ifndef LIBSTADIUM_KLDR_HPP
#define LIBSTADIUM_KLDR_HPP
#include <cstdio>
#include <iomanip>
#include <vector>
#include <string>
#include <random>
#include <exception>
namespace Stadium::v1 {
enum KLDRDefaultKeys : uint8_t { // TODO: think about better way (maybe std::map<string,uint8_t> or smt like that)
Data = 0x01, // Main data of event
ObjectID = 0x02, // ID of object in local context
SrcEventAuthor = 0x03, // Source author of event
PrevEvent = 0x04, // ID of previous event, logically connected to this
NextEvent = 0x05, // ID of next event
BatchNumber = 0x06, // Number of event in chain of events
Path = 0x07, // Path to requested/uploaded resource
Power = 0x08, // Access right to object
//ServerSession = 0x09, // ID of server-side session
// Crypto-related
CryptoAlgos = 0x11, // Array of used cryptography algos
CryptoKeyID = 0x12, // ID of crypto key used for data encryption in this event
SignedDataHash = 0x13 // Signed by sender hash of data
};
// Get stringized name of KLDR key
std::string ResolveKLDRKey (KLDRDefaultKeys); // TODO: this is can be better
/*
* KLDR stands for "Key-Length-Data-Repeat".
* Schematically, binary array with KLDR-formatted data looks like this.
* Single cell:
* [key: 1 or 2 bytes][length of data: 1/2/4 bytes][data: <length of data> bytes]
* Whole array:
* [cell 1][cell 2]...[cell n]
*
* Suffix "F" in function name stands for "Fast", i.e. it is unsafe, but fast version.
*
* This can be more optimized for performance with cost of more memory usage.
*/
template <typename KeyT = uint8_t, typename LengthT = uint16_t>
class KLDRArray final {
private:
std::vector<KeyT> Keys;
std::vector<LengthT> Lengths;
std::vector<char*> Values;
public:
// Constructor
KLDRArray () {}; // TODO: check used types and/or parse given char array/vector
// Destructor
~KLDRArray () {
// Freeing all pointers if vector is not empty
for (size_t i = 0; i < this->CellsAmount(); i++) {
delete[] this->Values[i];
}
}
// Move operator WARNING: есть шанс, что я тут сделал ложно, ибо мб мув просто продлевает время жизни вместо перемещения. Ассигнмента тоже касается
KLDRArray (KLDRArray&& src) : Keys(std::move(src.Keys)), Lengths(std::move(src.Lengths)), Values(std::move(src.Values)) {}
// Move assignment operator
KLDRArray& operator= (KLDRArray&& src) {
if (this == &src)
return *this;
this->Keys = std::move(src.Keys);
this->Lengths = std::move(src.Lengths);
this->Values = std::move(src.Values);
return *this;
}
// Copy operator (creating deep copy)
KLDRArray (KLDRArray& src) : Keys(src.Keys), Lengths(src.Lengths)
{
size_t valSize = 0;
for (size_t i = 0; i < src.Values.size(); i++) {
valSize = src.Lengths[i];
this->Values.push_back(new char[valSize]);
std::copy(src.Values[i], src.Values[i] + valSize, this->Values[i]);
}
}
// Copy assignment operator (creating deep copy)
KLDRArray& operator= (const KLDRArray& src) {
if (this == &src)
return *this;
this->Keys = src.Keys;
this->Lengths = src.Lengths;
size_t valSize = 0;
for (size_t i = 0; i < src.Values.size(); i++) {
valSize = src.Lengths[i];
this->Values.push_back(new char[valSize]);
std::copy(src.Values[i], src.Values[i] + valSize, this->Values[i]);
}
return *this;
}
// Write data to PREALLOCATED char array
// WARNING: unsafe and probably UB (may be i test this later but who knows)
void AsArrayF (char* arr) {
char* ptr = arr;
for (size_t i = 0; i < this->CellsAmount(); i++) {
std::copy((char*)&this->Keys[i], (char*)(&this->Keys[i] + sizeof(KeyT)), ptr);
ptr += sizeof(KeyT);
std::copy((char*)&this->Lengths[i], (char*)(&this->Lengths[i] + sizeof(LengthT)), ptr);
ptr += sizeof(LengthT);
std::copy(this->Values[i], this->Values[i] + this->Lengths[i], ptr);
ptr += this->Lengths[i];
}
}
// Return contents as char vector
std::vector<char> AsArray () const {
std::vector<char> result;
for (size_t i = 0; i < this->CellsAmount(); i++) {
for (uint j = 0; j < sizeof(KeyT); j++)
result.push_back(((char*)(&this->Keys[i]))[j]);
for (uint j = 0; j < sizeof(LengthT); j++)
result.push_back(((char*)(&this->Lengths[i]))[j]);
for (uint j = 0; j < this->Lengths[i]; j++)
result.push_back(((char*)this->Values[i])[j]);
}
return result;
}
// Print all contents of array to stdout
void Print () const {
printf(
"[KLDRArray] Object at: %lu; "
"KeyT size: %lu; "
"LengthT size: %lu; "
"Elements amount: %lu\n",
(size_t)this,
sizeof(KeyT),
sizeof(LengthT),
this->CellsAmount()
);
for (size_t i = 0; i < this->CellsAmount(); i++) {
printf("\tKey: ");
switch (this->Keys[i]) {
case v1::KLDRDefaultKeys::Data:
printf("Data");
break;
case v1::KLDRDefaultKeys::ObjectID:
printf("ObjectID");
break;
case v1::KLDRDefaultKeys::SrcEventAuthor:
printf("SrcEventAuthor");
break;
case v1::KLDRDefaultKeys::PrevEvent:
printf("PrevEvent");
break;
case v1::KLDRDefaultKeys::NextEvent:
printf("NextEvent");
break;
case v1::KLDRDefaultKeys::BatchNumber:
printf("BatchNumber");
break;
case v1::KLDRDefaultKeys::Path:
printf("Path");
break;
case v1::KLDRDefaultKeys::Power:
printf("Power");
break;
// case v1::KLDRDefaultKeys::ServerSession:
// printf("ServerSession");
// break;
case v1::KLDRDefaultKeys::CryptoAlgos:
printf("CryptoAlgos");
break;
case v1::KLDRDefaultKeys::CryptoKeyID:
printf("CryptoKeyID");
break;
case v1::KLDRDefaultKeys::SignedDataHash:
printf("SignedDataHash");
break;
default:
printf("0x%.2X", (KeyT)this->Keys[i]);
}
printf("; Length: %u; ", (uint)this->Lengths[i]);
printf("ValuePtr: %lu; Value: ", (uint64_t)this->Values[i]);
for (LengthT j = 0; j < this->Lengths[i]; j++)
printf("%.2X ", ((uint8_t*)this->Values[i])[j]);
printf("\n");
}
}
// Get amount of cells in array
inline size_t CellsAmount () const {
return this->Keys.size();
}
// Get size of all data in array as if they in packed condition
size_t FlatSize () const {
size_t result = this->Keys.size() * sizeof(KeyT) + this->Lengths.size() * sizeof(LengthT);
for (size_t i = 0; i < this->CellsAmount(); i++)
result += this->Lengths[i];
return result;
}
// If there are specified key
bool KeyExists (KeyT key) const {
for (size_t i = 0; i < this->CellsAmount(); i++) {
if (this->Keys[i] == key) {
return true;
}
}
return false;
}
// Add new cell to array, fast version without key checks, data will be copied
void AddF (KeyT key, LengthT length, char* data) {
this->Keys.push_back(key);
this->Lengths.push_back(length);
char* newData = new char[length];
std::copy(data, data + length, newData);
this->Values.push_back(newData);
}
// Add new cell to array, but only if key is unique
void Add (KeyT key, LengthT length, char* data) {
if (this->KeyExists(key))
throw std::invalid_argument("supplied key already exist");
this->AddF(key, length, data);
}
// Get just pointer to value from array by key
char* Get (KeyT key) const {
for (size_t i = 0; i < this->CellsAmount(); i++) {
if (this->Keys[i] == key) {
return this->Values[i];
}
}
throw std::invalid_argument("invalid KLDRArray key");
}
// Get pointer to value and length from array by key
char* Get (KeyT key, LengthT* length) const {
for (size_t i = 0; i < this->CellsAmount(); i++) {
if (this->Keys[i] == key) {
*length = this->Lengths[i];
return this->Values[i];
}
}
throw std::invalid_argument("invalid KLDRArray key");
}
// TODO: get copy of value
// Delete cell from array by key
void Del (KeyT key) {
for (size_t i = 0; i < this->CellsAmount(); i++) {
if (this->Keys[i] == key) {
this->Keys.erase(this->Keys.begin() + i);
this->Lengths.erase(this->Lengths.begin() + i);
this->Values.erase(this->Values.begin() + i);
return;
}
}
throw std::invalid_argument("invalid KLDRArray key");
}
// Shuffle array
void Shuffle () {
size_t elements = this->CellsAmount();
std::random_device seed;
std::mt19937 gen{seed()};
std::uniform_int_distribution<size_t> dist{0, elements-1};
size_t pickedIndex = 0;
for (size_t i = 0; i < elements; i++) {
do
pickedIndex = dist(gen);
while (pickedIndex == i);
std::swap(this->Keys[i], this->Keys[pickedIndex]);
std::swap(this->Lengths[i], this->Lengths[pickedIndex]);
std::swap(this->Values[i], this->Values[pickedIndex]);
}
}
};
}
#endif

28
src/Stadium.cpp Normal file
View File

@ -0,0 +1,28 @@
/*
* Stadium.cpp
* Copyright (c) 2023 Cyclone Team. Licensed under GNU GPLv3-only terms.
*
* API logic:
*
* -> [ Incoming Events Queue ] ---> [ Base Event Handlers ]
* / \-> [ Custom Event Handlers ]
* [ Transport ] <-> [ StadiumCrypto (optional) ] <-> -> [ Expected Event Handlers ]
* \
* <- [ Outcoming Events Queue ] <--- [ Base Methods ]
* \
* <- [ Custom Methods ]
*
* Arch logic:
*
* [ Base Event Handlers ] [ Custom Event Handlers ] [ Base Methods ] [ Custom Methods ]
* [ Base Event Management ] [ E2EE ] [ Far-Visibility Integrity Checks ] [ DoS Protection ]
* [ Session Management ] [ Direct-Visibility Integrity Checks ] [ DoS Protection ]
* [ Several Workers ] [ Event Parser ] [ DoS Protection ]
* [ Various Transport Adapters ]
*
*/
#include "Stadium.hpp"

28
src/Stadium.hpp Normal file
View File

@ -0,0 +1,28 @@
/*
* Stadium.hpp
* Copyright (c) 2023 Cyclone Team. Licensed under GNU GPLv3-only terms.
*
*/
#ifndef LIBSTADIUM_HPP
#define LIBSTADIUM_HPP
#include "Utils.hpp"
#include "KLDR.hpp"
#include "Event.hpp"
#include "Worker.hpp"
namespace Stadium::v1 {
// TODO
// __DATE__ __TIME__
}
#endif

40
src/Utils.hpp Normal file
View File

@ -0,0 +1,40 @@
/*
* Utils.hpp
* Copyright (c) 2023 Cyclone Team. Licensed under GNU GPLv3-only terms.
*
*/
#ifndef LIBSTADIUM_UTILS_HPP
#define LIBSTADIUM_UTILS_HPP
#include <iostream>
#include <cstdint>
namespace Stadium::Utils {
// Print information about any std-compatible container to stdout
template<typename Container>
void
PrintArray (Container& arr) {
printf("Array at %lu; length: %lu\n",
reinterpret_cast<size_t>(&arr),
arr.size()
);
for (size_t i = 0; i < arr.size(); i++)
printf("%.2X ", (uint8_t)arr[i]);
printf("\n");
}
}
#endif

53
src/Worker.cpp Normal file
View File

@ -0,0 +1,53 @@
/*
* Worker.cpp
* Copyright (c) 2023 Cyclone Team. Licensed under GNU GPLv3-only terms.
*
*/
#include "Worker.hpp"
namespace Stadium::v1 {
// Parse ingoing packet data to event, check its properties and put it to queue if all okay
void
Worker::PutIngoing (const char* data) {
// TODO
}
// Send outgoing event
void
Worker::PutOutgoing (EventType type, KLDRArray<> data) {
// TODO
}
// Bind handler for ingoing events
void
Worker::BindHandler (EventType event_type, EventHandler handle) {
this->Handlers[event_type] = handle;
}
// Expect ingoing event by its ID
Event
Worker::ExpectEvent (EventAsyncID async_id) {
// TODO
}
// Start ingoing event processing loop
void
Worker::IngoingLoop () {
// TODO
}
// Get single outgoing event from queue and form it to binary
std::vector<char>
Worker::GetOutgoingDataVec () {
// TODO
}
}

59
src/Worker.hpp Normal file
View File

@ -0,0 +1,59 @@
/*
* Worker.hpp
* Copyright (c) 2023 Cyclone Team. Licensed under GNU GPLv3-only terms.
*
*/
#ifndef LIBSTADIUM_WORKER_HPP
#define LIBSTADIUM_WORKER_HPP
#include <atomic>
#include <queue>
#include <unordered_map>
#include <functional>
#include "KLDR.hpp"
#include "Event.hpp"
namespace Stadium::v1 {
// Event handler type
typedef std::function<void()> EventHandler;
// Working class
class Worker final {
private:
static bool Running; // If workers are running
static std::unordered_map<EventType, EventHandler> Handlers; // Map of handlers associated with packet types
static std::unordered_map<EventAsyncID, Event> ExpectedEvents; // Map of expected events and their async IDs
static std::atomic<EventAsyncID> LastAsyncID; // Increments every use of Expect()
static std::queue<Event> OutgoingEvents; // FIFO of outgoing events
static std::queue<Event> IngoingEvents; // FIFO of ingoing events
public:
void PutIngoing (const char*);
void PutOutgoing (EventType, KLDRArray<>);
void BindHandler (EventType, EventHandler);
Event ExpectEvent (EventAsyncID);
void IngoingLoop ();
void OutgoingLoop ();
std::vector<char> GetOutgoingDataVec ();
};
}
#endif

27
src/test.cpp Normal file
View File

@ -0,0 +1,27 @@
#include <cstdio>
#include "Stadium.hpp"
#include "Utils.hpp"
int main () {
Stadium::v1::KLDRArray<> arr;
char str1[] = "goodbye, var?\n";
char str2[] = "hello, world!\n";
char str3[] = "fisting\n";
char str4[] = "IS 300$!!!!!!!!!!!!!!!!!!\n";
char str5[] = "a)\n";
arr.Add(Stadium::v1::KLDRDefaultKeys::Data, sizeof(str1), (char*)&str1);
arr.Add(Stadium::v1::KLDRDefaultKeys::ObjectID, sizeof(str2), (char*)&str2);
arr.Add(0xF4, sizeof(str3), (char*)&str3);
arr.Add(0x6a, sizeof(str4), (char*)&str4);
arr.Add(Stadium::v1::KLDRDefaultKeys::SignedDataHash, sizeof(str5), (char*)&str5);
arr.Shuffle();
arr.Print();
Stadium::v1::Event e{0x01, 0xf4, std::move(arr), 54};
e.Print();
//
return 0;
}