2023-08-19 22:37:55 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
// solanaceae port of tox_ngc_ft1
|
|
|
|
|
|
|
|
#include <solanaceae/toxcore/tox_event_interface.hpp>
|
2023-11-12 19:58:57 +01:00
|
|
|
#include <solanaceae/toxcore/tox_interface.hpp>
|
2023-08-19 22:37:55 +02:00
|
|
|
|
2023-08-19 22:50:52 +02:00
|
|
|
#include <solanaceae/ngc_ext/ngcext.hpp>
|
2024-07-15 16:38:33 +02:00
|
|
|
|
2023-12-13 19:38:55 +01:00
|
|
|
#include "./cca.hpp"
|
2023-08-19 22:37:55 +02:00
|
|
|
|
|
|
|
#include "./rcv_buf.hpp"
|
|
|
|
#include "./snd_buf.hpp"
|
|
|
|
|
|
|
|
#include "./ngcft1_file_kind.hpp"
|
|
|
|
|
2023-11-12 19:58:57 +01:00
|
|
|
#include <cstdint>
|
2023-08-19 22:37:55 +02:00
|
|
|
#include <map>
|
|
|
|
#include <set>
|
|
|
|
#include <memory>
|
2023-12-15 15:31:32 +01:00
|
|
|
#include <random>
|
2023-08-19 22:37:55 +02:00
|
|
|
|
|
|
|
namespace Events {
|
|
|
|
|
|
|
|
struct NGCFT1_recv_request {
|
|
|
|
uint32_t group_number;
|
|
|
|
uint32_t peer_number;
|
|
|
|
|
|
|
|
NGCFT1_file_kind file_kind;
|
|
|
|
|
|
|
|
const uint8_t* file_id;
|
2024-10-20 16:35:55 +02:00
|
|
|
uint32_t file_id_size;
|
2023-08-19 22:37:55 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct NGCFT1_recv_init {
|
|
|
|
uint32_t group_number;
|
|
|
|
uint32_t peer_number;
|
|
|
|
|
|
|
|
NGCFT1_file_kind file_kind;
|
|
|
|
|
|
|
|
const uint8_t* file_id;
|
2024-10-20 16:35:55 +02:00
|
|
|
uint32_t file_id_size;
|
2023-08-19 22:37:55 +02:00
|
|
|
|
|
|
|
const uint8_t transfer_id;
|
2024-10-20 16:35:55 +02:00
|
|
|
const uint64_t file_size;
|
2023-08-19 22:37:55 +02:00
|
|
|
|
|
|
|
// return true to accept, false to deny
|
|
|
|
bool& accept;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct NGCFT1_recv_data {
|
|
|
|
uint32_t group_number;
|
|
|
|
uint32_t peer_number;
|
|
|
|
|
|
|
|
uint8_t transfer_id;
|
|
|
|
|
2024-10-20 16:35:55 +02:00
|
|
|
uint64_t data_offset;
|
2023-08-19 22:37:55 +02:00
|
|
|
const uint8_t* data;
|
2024-10-20 16:35:55 +02:00
|
|
|
uint32_t data_size;
|
2023-08-19 22:37:55 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// request to fill data_size bytes into data
|
|
|
|
struct NGCFT1_send_data {
|
|
|
|
uint32_t group_number;
|
|
|
|
uint32_t peer_number;
|
|
|
|
|
|
|
|
uint8_t transfer_id;
|
|
|
|
|
2024-10-20 16:35:55 +02:00
|
|
|
uint64_t data_offset;
|
2023-08-19 22:37:55 +02:00
|
|
|
uint8_t* data;
|
2024-10-20 16:35:55 +02:00
|
|
|
uint32_t data_size;
|
2023-08-19 22:37:55 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct NGCFT1_recv_done {
|
|
|
|
uint32_t group_number;
|
|
|
|
uint32_t peer_number;
|
|
|
|
|
|
|
|
uint8_t transfer_id;
|
|
|
|
// TODO: reason
|
|
|
|
};
|
|
|
|
|
|
|
|
struct NGCFT1_send_done {
|
|
|
|
uint32_t group_number;
|
|
|
|
uint32_t peer_number;
|
|
|
|
|
|
|
|
uint8_t transfer_id;
|
|
|
|
// TODO: reason
|
|
|
|
};
|
|
|
|
|
|
|
|
struct NGCFT1_recv_message {
|
|
|
|
uint32_t group_number;
|
|
|
|
uint32_t peer_number;
|
|
|
|
|
|
|
|
uint32_t message_id;
|
|
|
|
|
|
|
|
NGCFT1_file_kind file_kind;
|
|
|
|
|
|
|
|
const uint8_t* file_id;
|
2024-10-20 16:35:55 +02:00
|
|
|
uint32_t file_id_size;
|
2023-08-19 22:37:55 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
} // Events
|
|
|
|
|
|
|
|
enum class NGCFT1_Event : uint8_t {
|
|
|
|
recv_request,
|
|
|
|
recv_init,
|
|
|
|
|
|
|
|
recv_data,
|
|
|
|
send_data,
|
|
|
|
|
|
|
|
recv_done,
|
|
|
|
send_done,
|
|
|
|
|
|
|
|
recv_message,
|
|
|
|
|
|
|
|
MAX
|
|
|
|
};
|
|
|
|
|
|
|
|
struct NGCFT1EventI {
|
|
|
|
using enumType = NGCFT1_Event;
|
|
|
|
virtual bool onEvent(const Events::NGCFT1_recv_request&) { return false; }
|
|
|
|
virtual bool onEvent(const Events::NGCFT1_recv_init&) { return false; }
|
|
|
|
virtual bool onEvent(const Events::NGCFT1_recv_data&) { return false; }
|
|
|
|
virtual bool onEvent(const Events::NGCFT1_send_data&) { return false; } // const?
|
|
|
|
virtual bool onEvent(const Events::NGCFT1_recv_done&) { return false; }
|
|
|
|
virtual bool onEvent(const Events::NGCFT1_send_done&) { return false; }
|
|
|
|
virtual bool onEvent(const Events::NGCFT1_recv_message&) { return false; }
|
|
|
|
};
|
|
|
|
|
|
|
|
using NGCFT1EventProviderI = EventProviderI<NGCFT1EventI>;
|
|
|
|
|
|
|
|
class NGCFT1 : public ToxEventI, public NGCEXTEventI, public NGCFT1EventProviderI {
|
|
|
|
ToxI& _t;
|
|
|
|
ToxEventProviderI& _tep;
|
2024-10-24 14:00:16 +02:00
|
|
|
ToxEventProviderI::SubscriptionReference _tep_sr;
|
2024-06-23 10:14:03 +02:00
|
|
|
NGCEXTEventProvider& _neep; // not the interface?
|
2024-10-24 14:00:16 +02:00
|
|
|
NGCEXTEventProvider::SubscriptionReference _neep_sr;
|
2023-08-19 22:37:55 +02:00
|
|
|
|
2023-12-15 15:31:32 +01:00
|
|
|
std::default_random_engine _rng{std::random_device{}()};
|
|
|
|
|
2024-07-07 15:27:30 +02:00
|
|
|
float _time_since_activity {10.f};
|
|
|
|
|
2023-08-19 22:37:55 +02:00
|
|
|
// TODO: config
|
|
|
|
size_t acks_per_packet {3u}; // 3
|
2024-03-05 16:48:58 +01:00
|
|
|
float init_retry_timeout_after {4.f};
|
2024-10-31 11:39:16 +01:00
|
|
|
float sending_give_up_after {10.f}; // sec (per active transfer)
|
2023-08-19 22:37:55 +02:00
|
|
|
|
|
|
|
struct Group {
|
|
|
|
struct Peer {
|
2023-10-11 03:00:03 +02:00
|
|
|
uint32_t max_packet_data_size {500-4};
|
|
|
|
//std::unique_ptr<CCAI> cca = std::make_unique<CUBIC>(max_packet_data_size); // TODO: replace with tox_group_max_custom_lossy_packet_length()-4
|
|
|
|
std::unique_ptr<CCAI> cca;
|
2023-08-19 22:37:55 +02:00
|
|
|
|
|
|
|
struct RecvTransfer {
|
|
|
|
uint32_t file_kind;
|
|
|
|
std::vector<uint8_t> file_id;
|
|
|
|
|
|
|
|
enum class State {
|
|
|
|
INITED, //init acked, but no data received yet (might be dropped)
|
|
|
|
RECV, // receiving data
|
2024-07-15 14:56:52 +02:00
|
|
|
FINISHING, // got all the data, but we wait for 2*delay, since its likely there is data still arriving
|
2023-08-19 22:37:55 +02:00
|
|
|
} state;
|
|
|
|
|
2024-10-20 16:35:55 +02:00
|
|
|
uint64_t file_size {0};
|
|
|
|
uint64_t file_size_current {0};
|
2023-08-19 22:37:55 +02:00
|
|
|
|
2024-07-15 14:56:52 +02:00
|
|
|
// if state FINISHING and it reaches 0, delete
|
|
|
|
float finishing_timer {0.f};
|
|
|
|
|
2023-08-19 22:37:55 +02:00
|
|
|
// sequence id based reassembly
|
|
|
|
RecvSequenceBuffer rsb;
|
|
|
|
};
|
|
|
|
std::array<std::optional<RecvTransfer>, 256> recv_transfers;
|
|
|
|
size_t next_recv_transfer_idx {0}; // next id will be 0
|
|
|
|
|
|
|
|
struct SendTransfer {
|
|
|
|
uint32_t file_kind;
|
|
|
|
std::vector<uint8_t> file_id;
|
|
|
|
|
|
|
|
enum class State {
|
|
|
|
INIT_SENT, // keep this state until ack or deny or giveup
|
|
|
|
|
|
|
|
SENDING, // we got the ack and are now sending data
|
|
|
|
|
|
|
|
FINISHING, // we sent all data but acks still outstanding????
|
|
|
|
|
|
|
|
// delete
|
|
|
|
} state;
|
|
|
|
|
|
|
|
size_t inits_sent {1}; // is sent when creating
|
|
|
|
|
|
|
|
float time_since_activity {0.f};
|
2024-10-20 16:35:55 +02:00
|
|
|
uint64_t file_size {0};
|
|
|
|
uint64_t file_size_current {0};
|
2023-08-19 22:37:55 +02:00
|
|
|
|
|
|
|
// sequence array
|
|
|
|
// list of sent but not acked seq_ids
|
|
|
|
SendSequenceBuffer ssb;
|
|
|
|
};
|
|
|
|
std::array<std::optional<SendTransfer>, 256> send_transfers;
|
|
|
|
size_t next_send_transfer_idx {0}; // next id will be 0
|
2023-09-01 23:20:03 +02:00
|
|
|
size_t next_send_transfer_send_idx {0};
|
2024-03-05 16:48:58 +01:00
|
|
|
|
|
|
|
size_t active_send_transfers {0};
|
2023-08-19 22:37:55 +02:00
|
|
|
};
|
|
|
|
std::map<uint32_t, Peer> peers;
|
|
|
|
};
|
|
|
|
std::map<uint32_t, Group> groups;
|
|
|
|
|
|
|
|
protected:
|
2023-09-01 17:34:05 +02:00
|
|
|
void updateSendTransfer(float time_delta, uint32_t group_number, uint32_t peer_number, Group::Peer& peer, size_t idx, std::set<CCAI::SeqIDType>& timeouts_set, int64_t& can_packet_size);
|
2023-08-19 22:37:55 +02:00
|
|
|
void iteratePeer(float time_delta, uint32_t group_number, uint32_t peer_number, Group::Peer& peer);
|
|
|
|
|
2024-07-12 13:14:24 +02:00
|
|
|
const CCAI* getPeerCCA(uint32_t group_number, uint32_t peer_number) const;
|
|
|
|
|
2023-08-19 22:37:55 +02:00
|
|
|
public:
|
|
|
|
NGCFT1(
|
|
|
|
ToxI& t,
|
|
|
|
ToxEventProviderI& tep,
|
2024-06-23 10:14:03 +02:00
|
|
|
NGCEXTEventProvider& neep
|
2023-08-19 22:37:55 +02:00
|
|
|
);
|
|
|
|
|
2024-01-07 17:23:06 +01:00
|
|
|
float iterate(float delta);
|
2023-08-19 22:37:55 +02:00
|
|
|
|
|
|
|
public: // ft1 api
|
2024-12-08 16:08:30 +01:00
|
|
|
bool NGC_FT1_send_request_private(
|
2023-08-19 22:37:55 +02:00
|
|
|
uint32_t group_number, uint32_t peer_number,
|
|
|
|
uint32_t file_kind,
|
2024-10-20 16:35:55 +02:00
|
|
|
const uint8_t* file_id, uint32_t file_id_size
|
2023-08-19 22:37:55 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
// public does not make sense here
|
|
|
|
bool NGC_FT1_send_init_private(
|
|
|
|
uint32_t group_number, uint32_t peer_number,
|
|
|
|
uint32_t file_kind,
|
2024-10-20 16:35:55 +02:00
|
|
|
const uint8_t* file_id, uint32_t file_id_size,
|
|
|
|
uint64_t file_size,
|
2024-10-30 11:25:33 +01:00
|
|
|
uint8_t* transfer_id,
|
|
|
|
bool can_compress = false // set this if you know the data is compressable (eg text)
|
2023-08-19 22:37:55 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
// sends the message and fills in message_id
|
|
|
|
bool NGC_FT1_send_message_public(
|
|
|
|
uint32_t group_number,
|
|
|
|
uint32_t& message_id,
|
|
|
|
uint32_t file_kind,
|
2024-10-20 16:35:55 +02:00
|
|
|
const uint8_t* file_id, uint32_t file_id_size
|
2023-08-19 22:37:55 +02:00
|
|
|
);
|
|
|
|
|
2024-07-12 13:14:24 +02:00
|
|
|
public: // cca stuff
|
|
|
|
// rtt/delay
|
|
|
|
// negative on error or no cca
|
|
|
|
float getPeerDelay(uint32_t group_number, uint32_t peer_number) const;
|
|
|
|
|
|
|
|
// belived possible current window
|
|
|
|
// negative on error or no cca
|
|
|
|
float getPeerWindow(uint32_t group_number, uint32_t peer_number) const;
|
|
|
|
|
|
|
|
// packets in flight
|
|
|
|
// returns -1 if error or no cca
|
|
|
|
int64_t getPeerInFlightPackets(uint32_t group_number, uint32_t peer_number) const;
|
|
|
|
|
|
|
|
// actual bytes in flight (aka window)
|
|
|
|
// returns -1 if error or no cca
|
|
|
|
int64_t getPeerInFlightBytes(uint32_t group_number, uint32_t peer_number) const;
|
|
|
|
|
2023-08-19 22:37:55 +02:00
|
|
|
protected:
|
|
|
|
bool onEvent(const Events::NGCEXT_ft1_request&) override;
|
|
|
|
bool onEvent(const Events::NGCEXT_ft1_init&) override;
|
|
|
|
bool onEvent(const Events::NGCEXT_ft1_init_ack&) override;
|
|
|
|
bool onEvent(const Events::NGCEXT_ft1_data&) override;
|
|
|
|
bool onEvent(const Events::NGCEXT_ft1_data_ack&) override;
|
|
|
|
bool onEvent(const Events::NGCEXT_ft1_message&) override;
|
2024-10-30 11:25:33 +01:00
|
|
|
bool onEvent(const Events::NGCEXT_ft1_init2&) override;
|
2023-08-19 22:37:55 +02:00
|
|
|
|
|
|
|
protected:
|
|
|
|
bool onToxEvent(const Tox_Event_Group_Peer_Exit* e) override;
|
|
|
|
//bool onToxEvent(const Tox_Event_Group_Custom_Packet* e) override;
|
|
|
|
//bool onToxEvent(const Tox_Event_Group_Custom_Private_Packet* e) override;
|
|
|
|
};
|
|
|
|
|