after 2 weeks of porting over the ngc_ft1 code to solanaceae and rewriting the highlevel logic
(29 commits predate this)
This commit is contained in:
281
solanaceae/ngc_ext/ngcext.cpp
Normal file
281
solanaceae/ngc_ext/ngcext.cpp
Normal file
@ -0,0 +1,281 @@
|
||||
#include "./ngcext.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
NGCEXTEventProvider::NGCEXTEventProvider(ToxEventProviderI& tep) : _tep(tep) {
|
||||
_tep.subscribe(this, Tox_Event::TOX_EVENT_GROUP_CUSTOM_PACKET);
|
||||
_tep.subscribe(this, Tox_Event::TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET);
|
||||
}
|
||||
|
||||
#define _DATA_HAVE(x, error) if ((data_size - curser) < (x)) { error; }
|
||||
|
||||
bool NGCEXTEventProvider::parse_hs1_request_last_ids(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool _private
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NGCEXTEventProvider::parse_hs1_response_last_ids(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool _private
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NGCEXTEventProvider::parse_ft1_request(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool // dont care private
|
||||
) {
|
||||
Events::NGCEXT_ft1_request e;
|
||||
e.group_number = group_number;
|
||||
e.peer_number = peer_number;
|
||||
size_t curser = 0;
|
||||
|
||||
// - 4 byte (file_kind)
|
||||
e.file_kind = 0u;
|
||||
_DATA_HAVE(sizeof(e.file_kind), std::cerr << "NGCEXT: packet too small, missing file_kind\n"; return false)
|
||||
for (size_t i = 0; i < sizeof(e.file_kind); i++, curser++) {
|
||||
e.file_kind |= uint32_t(data[curser]) << (i*8);
|
||||
}
|
||||
|
||||
// - X bytes (file_kind dependent id, differnt sizes)
|
||||
e.file_id = {data+curser, data+curser+(data_size-curser)};
|
||||
|
||||
return dispatch(
|
||||
NGCEXT_Event::FT1_REQUEST,
|
||||
e
|
||||
);
|
||||
}
|
||||
|
||||
bool NGCEXTEventProvider::parse_ft1_init(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool _private
|
||||
) {
|
||||
if (!_private) {
|
||||
std::cerr << "NGCEXT: ft1_init cant be public\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
Events::NGCEXT_ft1_init e;
|
||||
e.group_number = group_number;
|
||||
e.peer_number = peer_number;
|
||||
size_t curser = 0;
|
||||
|
||||
// - 4 byte (file_kind)
|
||||
e.file_kind = 0u;
|
||||
_DATA_HAVE(sizeof(e.file_kind), std::cerr << "NGCEXT: packet too small, missing file_kind\n"; return false)
|
||||
for (size_t i = 0; i < sizeof(e.file_kind); i++, curser++) {
|
||||
e.file_kind |= uint32_t(data[curser]) << (i*8);
|
||||
}
|
||||
|
||||
// - 8 bytes (data size)
|
||||
e.file_size = 0u;
|
||||
_DATA_HAVE(sizeof(e.file_size), std::cerr << "NGCEXT: packet too small, missing file_size\n"; return false)
|
||||
for (size_t i = 0; i < sizeof(e.file_size); i++, curser++) {
|
||||
e.file_size |= size_t(data[curser]) << (i*8);
|
||||
}
|
||||
|
||||
// - 1 byte (temporary_file_tf_id)
|
||||
_DATA_HAVE(sizeof(e.transfer_id), std::cerr << "NGCEXT: packet too small, missing transfer_id\n"; return false)
|
||||
e.transfer_id = data[curser++];
|
||||
|
||||
// - X bytes (file_kind dependent id, differnt sizes)
|
||||
e.file_id = {data+curser, data+curser+(data_size-curser)};
|
||||
|
||||
return dispatch(
|
||||
NGCEXT_Event::FT1_INIT,
|
||||
e
|
||||
);
|
||||
}
|
||||
|
||||
bool NGCEXTEventProvider::parse_ft1_init_ack(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool _private
|
||||
) {
|
||||
if (!_private) {
|
||||
std::cerr << "NGCEXT: ft1_init_ack cant be public\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
Events::NGCEXT_ft1_init_ack e;
|
||||
e.group_number = group_number;
|
||||
e.peer_number = peer_number;
|
||||
size_t curser = 0;
|
||||
|
||||
// - 1 byte (temporary_file_tf_id)
|
||||
_DATA_HAVE(sizeof(e.transfer_id), std::cerr << "NGCEXT: packet too small, missing transfer_id\n"; return false)
|
||||
e.transfer_id = data[curser++];
|
||||
|
||||
return dispatch(
|
||||
NGCEXT_Event::FT1_INIT_ACK,
|
||||
e
|
||||
);
|
||||
}
|
||||
|
||||
bool NGCEXTEventProvider::parse_ft1_data(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool _private
|
||||
) {
|
||||
if (!_private) {
|
||||
std::cerr << "NGCEXT: ft1_data cant be public\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
Events::NGCEXT_ft1_data e;
|
||||
e.group_number = group_number;
|
||||
e.peer_number = peer_number;
|
||||
size_t curser = 0;
|
||||
|
||||
// - 1 byte (temporary_file_tf_id)
|
||||
_DATA_HAVE(sizeof(e.transfer_id), std::cerr << "NGCEXT: packet too small, missing transfer_id\n"; return false)
|
||||
e.transfer_id = data[curser++];
|
||||
|
||||
// - 2 bytes (sequence_id)
|
||||
e.sequence_id = 0u;
|
||||
_DATA_HAVE(sizeof(e.sequence_id), std::cerr << "NGCEXT: packet too small, missing sequence_id\n"; return false)
|
||||
for (size_t i = 0; i < sizeof(e.sequence_id); i++, curser++) {
|
||||
e.sequence_id |= uint32_t(data[curser]) << (i*8);
|
||||
}
|
||||
|
||||
// - X bytes (the data fragment)
|
||||
// (size is implicit)
|
||||
e.data = {data+curser, data+curser+(data_size-curser)};
|
||||
|
||||
return dispatch(
|
||||
NGCEXT_Event::FT1_DATA,
|
||||
e
|
||||
);
|
||||
}
|
||||
|
||||
bool NGCEXTEventProvider::parse_ft1_data_ack(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool _private
|
||||
) {
|
||||
if (!_private) {
|
||||
std::cerr << "NGCEXT: ft1_data_ack cant be public\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
Events::NGCEXT_ft1_data_ack e;
|
||||
e.group_number = group_number;
|
||||
e.peer_number = peer_number;
|
||||
size_t curser = 0;
|
||||
|
||||
// - 1 byte (temporary_file_tf_id)
|
||||
_DATA_HAVE(sizeof(e.transfer_id), std::cerr << "NGCEXT: packet too small, missing transfer_id\n"; return false)
|
||||
e.transfer_id = data[curser++];
|
||||
|
||||
while (curser < data_size) {
|
||||
_DATA_HAVE(sizeof(uint16_t), std::cerr << "NGCEXT: packet too small, missing seq_id\n"; return false)
|
||||
uint16_t seq_id = data[curser++];
|
||||
seq_id |= data[curser++] << (1*8);
|
||||
e.sequence_ids.push_back(seq_id);
|
||||
}
|
||||
|
||||
return dispatch(
|
||||
NGCEXT_Event::FT1_DATA_ACK,
|
||||
e
|
||||
);
|
||||
}
|
||||
|
||||
bool NGCEXTEventProvider::parse_ft1_message(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool _private
|
||||
) {
|
||||
if (_private) {
|
||||
std::cerr << "NGCEXT: ft1_message cant be private (yet)\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
Events::NGCEXT_ft1_message e;
|
||||
e.group_number = group_number;
|
||||
e.peer_number = peer_number;
|
||||
size_t curser = 0;
|
||||
|
||||
// - 4 byte (message_id)
|
||||
e.message_id = 0u;
|
||||
_DATA_HAVE(sizeof(e.message_id), std::cerr << "NGCEXT: packet too small, missing message_id\n"; return false)
|
||||
for (size_t i = 0; i < sizeof(e.message_id); i++, curser++) {
|
||||
e.message_id |= uint32_t(data[curser]) << (i*8);
|
||||
}
|
||||
|
||||
// - 4 byte (file_kind)
|
||||
e.file_kind = 0u;
|
||||
_DATA_HAVE(sizeof(e.file_kind), std::cerr << "NGCEXT: packet too small, missing file_kind\n"; return false)
|
||||
for (size_t i = 0; i < sizeof(e.file_kind); i++, curser++) {
|
||||
e.file_kind |= uint32_t(data[curser]) << (i*8);
|
||||
}
|
||||
|
||||
// - X bytes (file_kind dependent id, differnt sizes)
|
||||
e.file_id = {data+curser, data+curser+(data_size-curser)};
|
||||
|
||||
return dispatch(
|
||||
NGCEXT_Event::FT1_MESSAGE,
|
||||
e
|
||||
);
|
||||
}
|
||||
|
||||
bool NGCEXTEventProvider::handlePacket(
|
||||
const uint32_t group_number,
|
||||
const uint32_t peer_number,
|
||||
const uint8_t* data,
|
||||
const size_t data_size,
|
||||
const bool _private
|
||||
) {
|
||||
if (data_size < 1) {
|
||||
return false; // waht
|
||||
}
|
||||
|
||||
NGCEXT_Event pkg_type = static_cast<NGCEXT_Event>(data[0]);
|
||||
|
||||
switch (pkg_type) {
|
||||
case NGCEXT_Event::HS1_REQUEST_LAST_IDS:
|
||||
return false;
|
||||
case NGCEXT_Event::HS1_RESPONSE_LAST_IDS:
|
||||
return false;
|
||||
case NGCEXT_Event::FT1_REQUEST:
|
||||
return parse_ft1_request(group_number, peer_number, data+1, data_size-1, _private);
|
||||
case NGCEXT_Event::FT1_INIT:
|
||||
return parse_ft1_init(group_number, peer_number, data+1, data_size-1, _private);
|
||||
case NGCEXT_Event::FT1_INIT_ACK:
|
||||
return parse_ft1_init_ack(group_number, peer_number, data+1, data_size-1, _private);
|
||||
case NGCEXT_Event::FT1_DATA:
|
||||
return parse_ft1_data(group_number, peer_number, data+1, data_size-1, _private);
|
||||
case NGCEXT_Event::FT1_DATA_ACK:
|
||||
return parse_ft1_data_ack(group_number, peer_number, data+1, data_size-1, _private);
|
||||
case NGCEXT_Event::FT1_MESSAGE:
|
||||
return parse_ft1_message(group_number, peer_number, data+1, data_size-1, _private);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NGCEXTEventProvider::onToxEvent(const Tox_Event_Group_Custom_Packet* e) {
|
||||
const auto group_number = tox_event_group_custom_packet_get_group_number(e);
|
||||
const auto peer_number = tox_event_group_custom_packet_get_peer_id(e);
|
||||
const uint8_t* data = tox_event_group_custom_packet_get_data(e);
|
||||
const auto data_length = tox_event_group_custom_packet_get_data_length(e);
|
||||
|
||||
return handlePacket(group_number, peer_number, data, data_length, false);
|
||||
}
|
||||
|
||||
bool NGCEXTEventProvider::onToxEvent(const Tox_Event_Group_Custom_Private_Packet* e) {
|
||||
const auto group_number = tox_event_group_custom_private_packet_get_group_number(e);
|
||||
const auto peer_number = tox_event_group_custom_private_packet_get_peer_id(e);
|
||||
const uint8_t* data = tox_event_group_custom_private_packet_get_data(e);
|
||||
const auto data_length = tox_event_group_custom_private_packet_get_data_length(e);
|
||||
|
||||
return handlePacket(group_number, peer_number, data, data_length, true);
|
||||
}
|
||||
|
278
solanaceae/ngc_ext/ngcext.hpp
Normal file
278
solanaceae/ngc_ext/ngcext.hpp
Normal file
@ -0,0 +1,278 @@
|
||||
#pragma once
|
||||
|
||||
// solanaceae port of tox_ngc_ext
|
||||
|
||||
#include <solanaceae/toxcore/tox_event_interface.hpp>
|
||||
#include <solanaceae/util/event_provider.hpp>
|
||||
|
||||
#include <solanaceae/toxcore/tox_key.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
namespace Events {
|
||||
|
||||
// TODO: implement events as non-owning
|
||||
|
||||
struct NGCEXT_hs1_request_last_ids {
|
||||
uint32_t group_number;
|
||||
uint32_t peer_number;
|
||||
|
||||
// - peer_key bytes (peer key we want to know ids for)
|
||||
ToxKey peer_key;
|
||||
|
||||
// - 1 byte (uint8_t count ids, atleast 1)
|
||||
uint8_t count_ids;
|
||||
};
|
||||
|
||||
struct NGCEXT_hs1_response_last_ids {
|
||||
uint32_t group_number;
|
||||
uint32_t peer_number;
|
||||
|
||||
// respond to a request with 0 or more message ids, sorted by newest first
|
||||
// - peer_key bytes (the msg_ids are from)
|
||||
ToxKey peer_key;
|
||||
|
||||
// - 1 byte (uint8_t count ids, can be 0)
|
||||
uint8_t count_ids;
|
||||
|
||||
// - array [
|
||||
// - msg_id bytes (the message id)
|
||||
// - ]
|
||||
std::vector<uint32_t> msg_ids;
|
||||
};
|
||||
|
||||
struct NGCEXT_ft1_request {
|
||||
uint32_t group_number;
|
||||
uint32_t peer_number;
|
||||
|
||||
// request the other side to initiate a FT
|
||||
// - 4 byte (file_kind)
|
||||
uint32_t file_kind;
|
||||
|
||||
// - X bytes (file_kind dependent id, differnt sizes)
|
||||
std::vector<uint8_t> file_id;
|
||||
};
|
||||
|
||||
struct NGCEXT_ft1_init {
|
||||
uint32_t group_number;
|
||||
uint32_t peer_number;
|
||||
|
||||
// tell the other side you want to start a FT
|
||||
// - 4 byte (file_kind)
|
||||
uint32_t file_kind;
|
||||
|
||||
// - 8 bytes (data size)
|
||||
uint64_t file_size;
|
||||
|
||||
// - 1 byte (temporary_file_tf_id, for this peer only, technically just a prefix to distinguish between simultainious fts)
|
||||
uint8_t transfer_id;
|
||||
|
||||
// - X bytes (file_kind dependent id, differnt sizes)
|
||||
std::vector<uint8_t> file_id;
|
||||
|
||||
// TODO: max supported lossy packet size
|
||||
};
|
||||
|
||||
struct NGCEXT_ft1_init_ack {
|
||||
uint32_t group_number;
|
||||
uint32_t peer_number;
|
||||
|
||||
// - 1 byte (transfer_id)
|
||||
uint8_t transfer_id;
|
||||
|
||||
// TODO: max supported lossy packet size
|
||||
};
|
||||
|
||||
struct NGCEXT_ft1_data {
|
||||
uint32_t group_number;
|
||||
uint32_t peer_number;
|
||||
|
||||
// data fragment
|
||||
// - 1 byte (temporary_file_tf_id)
|
||||
uint8_t transfer_id;
|
||||
|
||||
// - 2 bytes (sequece id)
|
||||
uint16_t sequence_id;
|
||||
|
||||
// - X bytes (the data fragment)
|
||||
// (size is implicit)
|
||||
std::vector<uint8_t> data;
|
||||
};
|
||||
|
||||
struct NGCEXT_ft1_data_ack {
|
||||
uint32_t group_number;
|
||||
uint32_t peer_number;
|
||||
|
||||
// - 1 byte (temporary_file_tf_id)
|
||||
uint8_t transfer_id;
|
||||
|
||||
// - array [ (of sequece ids)
|
||||
// - 2 bytes (sequece id)
|
||||
// - ]
|
||||
std::vector<uint16_t> sequence_ids;
|
||||
};
|
||||
|
||||
struct NGCEXT_ft1_message {
|
||||
uint32_t group_number;
|
||||
uint32_t peer_number;
|
||||
|
||||
// - 4 byte (message_id)
|
||||
uint32_t message_id;
|
||||
|
||||
// request the other side to initiate a FT
|
||||
// - 4 byte (file_kind)
|
||||
uint32_t file_kind;
|
||||
|
||||
// - X bytes (file_kind dependent id, differnt sizes)
|
||||
std::vector<uint8_t> file_id;
|
||||
};
|
||||
|
||||
} // Events
|
||||
|
||||
enum class NGCEXT_Event : uint8_t {
|
||||
//TODO: make it possible to go further back
|
||||
// request last (few) message_ids for a peer
|
||||
// - peer_key bytes (peer key we want to know ids for)
|
||||
// - 1 byte (uint8_t count ids, atleast 1)
|
||||
HS1_REQUEST_LAST_IDS = 0x80 | 1u,
|
||||
|
||||
// respond to a request with 0 or more message ids, sorted by newest first
|
||||
// - peer_key bytes (the msg_ids are from)
|
||||
// - 1 byte (uint8_t count ids, can be 0)
|
||||
// - array [
|
||||
// - msg_id bytes (the message id)
|
||||
// - ]
|
||||
HS1_RESPONSE_LAST_IDS,
|
||||
|
||||
// request the other side to initiate a FT
|
||||
// - 4 byte (file_kind)
|
||||
// - X bytes (file_kind dependent id, differnt sizes)
|
||||
FT1_REQUEST = 0x80 | 8u,
|
||||
|
||||
// TODO: request result negative, speed up not found
|
||||
|
||||
// tell the other side you want to start a FT
|
||||
// TODO: might use id layer instead. with it, it would look similar to friends_ft
|
||||
// - 4 byte (file_kind)
|
||||
// - 8 bytes (data size, can be 0 if unknown, BUT files have to be atleast 1 byte)
|
||||
// - 1 byte (temporary_file_tf_id, for this peer only, technically just a prefix to distinguish between simultainious fts)
|
||||
// - X bytes (file_kind dependent id, differnt sizes)
|
||||
FT1_INIT,
|
||||
|
||||
// acknowlage init (like an accept)
|
||||
// like tox ft control continue
|
||||
// - 1 byte (transfer_id)
|
||||
FT1_INIT_ACK,
|
||||
|
||||
// TODO: init deny, speed up non acceptance
|
||||
|
||||
// data fragment
|
||||
// - 1 byte (temporary_file_tf_id)
|
||||
// - 2 bytes (sequece id)
|
||||
// - X bytes (the data fragment)
|
||||
// (size is implicit)
|
||||
FT1_DATA,
|
||||
|
||||
// acknowlage data fragments
|
||||
// TODO: last 3 should be sufficient, 5 should be generous
|
||||
// - 1 byte (temporary_file_tf_id)
|
||||
// // this is implicit (pkg size)- 1 byte (number of sequence ids to ack, this kind of depends on window size)
|
||||
// - array [ (of sequece ids)
|
||||
// - 2 bytes (sequece id)
|
||||
// - ]
|
||||
FT1_DATA_ACK,
|
||||
|
||||
// send file as message
|
||||
// basically the opposite of request
|
||||
// contains file_kind and file_id (and timestamp?)
|
||||
// - 4 byte (message_id)
|
||||
// - 4 byte (file_kind)
|
||||
// - X bytes (file_kind dependent id, differnt sizes)
|
||||
FT1_MESSAGE,
|
||||
|
||||
MAX
|
||||
};
|
||||
|
||||
struct NGCEXTEventI {
|
||||
using enumType = NGCEXT_Event;
|
||||
virtual bool onEvent(const Events::NGCEXT_hs1_request_last_ids&) { return false; }
|
||||
virtual bool onEvent(const Events::NGCEXT_hs1_response_last_ids&) { return false; }
|
||||
virtual bool onEvent(const Events::NGCEXT_ft1_request&) { return false; }
|
||||
virtual bool onEvent(const Events::NGCEXT_ft1_init&) { return false; }
|
||||
virtual bool onEvent(const Events::NGCEXT_ft1_init_ack&) { return false; }
|
||||
virtual bool onEvent(const Events::NGCEXT_ft1_data&) { return false; }
|
||||
virtual bool onEvent(const Events::NGCEXT_ft1_data_ack&) { return false; }
|
||||
virtual bool onEvent(const Events::NGCEXT_ft1_message&) { return false; }
|
||||
};
|
||||
|
||||
using NGCEXTEventProviderI = EventProviderI<NGCEXTEventI>;
|
||||
|
||||
class NGCEXTEventProvider : public ToxEventI, public NGCEXTEventProviderI {
|
||||
ToxEventProviderI& _tep;
|
||||
|
||||
public:
|
||||
NGCEXTEventProvider(ToxEventProviderI& tep/*, ToxI& t*/);
|
||||
|
||||
protected:
|
||||
bool parse_hs1_request_last_ids(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool _private
|
||||
);
|
||||
|
||||
bool parse_hs1_response_last_ids(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool _private
|
||||
);
|
||||
|
||||
bool parse_ft1_request(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool _private
|
||||
);
|
||||
|
||||
bool parse_ft1_init(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool _private
|
||||
);
|
||||
|
||||
bool parse_ft1_init_ack(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool _private
|
||||
);
|
||||
|
||||
bool parse_ft1_data(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool _private
|
||||
);
|
||||
|
||||
bool parse_ft1_data_ack(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool _private
|
||||
);
|
||||
|
||||
bool parse_ft1_message(
|
||||
uint32_t group_number, uint32_t peer_number,
|
||||
const uint8_t* data, size_t data_size,
|
||||
bool _private
|
||||
);
|
||||
|
||||
bool handlePacket(
|
||||
const uint32_t group_number,
|
||||
const uint32_t peer_number,
|
||||
const uint8_t* data,
|
||||
const size_t data_size,
|
||||
const bool _private
|
||||
);
|
||||
|
||||
protected:
|
||||
bool onToxEvent(const Tox_Event_Group_Custom_Packet* e) override;
|
||||
bool onToxEvent(const Tox_Event_Group_Custom_Private_Packet* e) override;
|
||||
};
|
||||
|
Reference in New Issue
Block a user