basic commandline parsing + basic tox setup

This commit is contained in:
Green Sky 2023-01-13 21:11:42 +01:00
parent 04310100b5
commit b7915c55a4
No known key found for this signature in database
8 changed files with 352 additions and 1 deletions

View File

@ -6,6 +6,15 @@ project(tox_ngc_ft1_tool C CXX)
add_executable(tox_ngc_ft1_tool add_executable(tox_ngc_ft1_tool
./main.cpp ./main.cpp
./command_line.hpp
./command_line.cpp
./tox_utils.hpp
./tox_utils.cpp
./tox_client.hpp
./tox_client.cpp
) )
target_compile_features(tox_ngc_ft1_tool PUBLIC cxx_std_17) target_compile_features(tox_ngc_ft1_tool PUBLIC cxx_std_17)

94
src/command_line.cpp Normal file
View File

@ -0,0 +1,94 @@
#include "./command_line.hpp"
#include <iostream>
#include <cassert>
CommandLine::CommandLine(int argc, char** argv) {
assert(argc > 0);
exe = argv[0];
for (int i = 1; i < argc; i++) {
std::string_view arg_sv{argv[i]};
if (arg_sv == "-v") {
version = true;
_should_exit = true;
} else if (arg_sv == "-V") {
verbose = true;
} else if (arg_sv == "-h") {
help = true;
printHelp();
_should_exit = true;
} else if (arg_sv == "-G") {
if (i+1 >= argc) {
std::cerr << "-G missing <chat_id> parameter!\n\n";
printHelp();
_should_exit = true;
return;
}
chat_id = argv[++i];
} else if (arg_sv == "-F") {
if (i+1 >= argc) {
std::cerr << "-F missing <path> parameter!\n\n";
printHelp();
_should_exit = true;
return;
}
profile_path = argv[++i];
} else if (arg_sv == "-a") {
} else if (arg_sv == "-f") {
if (i+1 >= argc) {
std::cerr << "-f missing <path> parameter!\n\n";
printHelp();
_should_exit = true;
return;
}
send_path = argv[++i];
} else if (arg_sv == "-d") {
if (i+1 >= argc) {
std::cerr << "-d missing <path> parameter!\n\n";
printHelp();
_should_exit = true;
return;
}
receive_dump_dir = argv[++i];
} else if (arg_sv == "-D") {
if (i+1 >= argc) {
std::cerr << "-D missing <id/hash> parameter!\n\n";
printHelp();
_should_exit = true;
return;
}
receive_id = argv[++i];
}
}
}
void CommandLine::printHelp(void) {
std::cout
<< "meta:\n"
<< " -v version info\n"
<< " -V verbose\n"
<< " -h help\n"
<< "\n"
<< " connectivity:\n"
<< " -G <chat_id>\n"
<< " -F profile.tox\n"
<< " will print friend id at startup\n"
<< " will autoaccept any invite\n"
<< " if no -F give, will not save profile.\n"
<< " if profile exists load, otherwise create new\n"
<< "\n"
<< " transfer variant:\n"
<< " -a id1/sha128_single/sha128_info/sha256_single/sha256_info\n"
<< "\n"
<< " send:\n"
<< " -f send_this_file.zip\n"
<< "\n"
<< " receive:\n"
<< " -d dump/everything/in/this/dir\n"
<< " -D <id/hash> (what to dl)\n"
;
}

65
src/command_line.hpp Normal file
View File

@ -0,0 +1,65 @@
#pragma once
#include <string>
// meta:
// -v version info
// -V verbose
// -h help
//
// connectivity:
// -G <chat_id>
// -F profile.tox
// will print friend id at startup
// will autoaccept any invite
// if no -F give, will not save profile.
// if profile exists load, otherwise create new
//
// transfer variant:
// -a id1/sha128_single/sha128_info/sha256_single/sha256_info
//
// send:
// -f send_this_file.zip
//
// receive:
// -d dump/everything/in/this/dir
// -D <id/hash> (what to dl)
struct CommandLine {
std::string exe;
// meta:
// -v
bool version {false};
// -V
bool verbose {false};
// -h
bool help {false};
// connectivity:
// -G <chat_id>
std::string chat_id;
// -F profile.tox
std::string profile_path;
// transfer variant:
// -a id1/sha128_single/sha128_info/sha256_single/sha256_info
// some enum?
// send:
// -f send_this_file.zip
std::string send_path;
// receive:
// -d dump/everything/in/this/dir
std::string receive_dump_dir;
// -D <id/hash> (what to dl)
std::string receive_id;
CommandLine(int argc, char** argv);
void printHelp(void);
bool _should_exit {false};
};

View File

@ -1,6 +1,29 @@
#include <tox/tox.h> #include "./tox_client.hpp"
#include "./command_line.hpp"
#include <memory>
#include <iostream>
#include <unordered_map>
int main(int argc, char** argv) { int main(int argc, char** argv) {
CommandLine cl(argc, argv);
if (cl.version) {
std::cout << "tox_ngc_ft1_tool v0.0.1\n";
}
if (cl._should_exit) {
return 0;
}
ToxClient client(cl);
std::cout << "tox id: " << client.getOwnAddress() << "\n";
while (true) {
client.iterate();
}
return 0; return 0;
} }

98
src/tox_client.cpp Normal file
View File

@ -0,0 +1,98 @@
#include "./tox_client.hpp"
#include "./tox_utils.hpp"
#include <vector>
#include <fstream>
#include <cassert>
#include <iostream>
#include <stdexcept>
ToxClient::ToxClient(const CommandLine& cl) :
_tox_profile_path(cl.profile_path)
{
TOX_ERR_OPTIONS_NEW err_opt_new;
Tox_Options* options = tox_options_new(&err_opt_new);
assert(err_opt_new == TOX_ERR_OPTIONS_NEW::TOX_ERR_OPTIONS_NEW_OK);
// use cl for options
//tox_options_set_log_callback(options, log_cb);
tox_options_set_local_discovery_enabled(options, false);
tox_options_set_udp_enabled(options, true);
tox_options_set_hole_punching_enabled(options, true);
std::vector<uint8_t> profile_data{};
if (!_tox_profile_path.empty()) {
std::ifstream ifile{_tox_profile_path, std::ios::binary};
if (ifile.is_open()) {
std::cout << "TOX loading save " << _tox_profile_path << "\n";
// fill savedata
while (ifile.good()) {
auto ch = ifile.get();
if (ch == EOF) {
break;
} else {
profile_data.push_back(ch);
}
}
if (profile_data.empty()) {
std::cerr << "empty tox save\n";
} else {
// set options
tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
tox_options_set_savedata_data(options, profile_data.data(), profile_data.size());
}
ifile.close(); // do i need this?
}
}
TOX_ERR_NEW err_new;
_tox = tox_new(options, &err_new);
tox_options_free(options);
if (err_new != TOX_ERR_NEW_OK) {
std::cerr << "tox_new failed with error code " << err_new << "\n";
throw std::runtime_error{"tox failed"};
}
_tox_profile_dirty = true;
}
void ToxClient::iterate(void) {
tox_iterate(_tox, this);
if (_tox_profile_dirty) {
saveToxProfile();
}
}
std::string ToxClient::getOwnAddress(void) const {
std::vector<uint8_t> self_addr{};
self_addr.resize(TOX_ADDRESS_SIZE);
tox_self_get_address(_tox, self_addr.data());
return bin2hex(self_addr);
}
void ToxClient::saveToxProfile(void) {
if (_tox_profile_path.empty()) {
return;
}
std::vector<uint8_t> data{};
data.resize(tox_get_savedata_size(_tox));
tox_get_savedata(_tox, data.data());
std::ofstream ofile{_tox_profile_path, std::ios::binary};
// TODO: improve
for (const auto& ch : data) {
ofile.put(ch);
}
ofile.close(); // TODO: do i need this
_tox_profile_dirty = false;
}

31
src/tox_client.hpp Normal file
View File

@ -0,0 +1,31 @@
#pragma once
#include "./command_line.hpp"
#include <tox/tox.h>
#include <ngc_ext.h>
#include <ngc_ft1.h>
#include <string>
struct ToxClient final {
ToxClient(const CommandLine& cl);
void iterate(void);
void setToxProfilePath(const std::string& new_path) { _tox_profile_path = new_path; }
std::string getOwnAddress(void) const;
private:
void saveToxProfile(void);
private:
Tox* _tox {nullptr};
NGC_EXT_CTX* _ext_ctx {nullptr};
NGC_FT1* _ft1_ctx {nullptr};
std::string _tox_profile_path;
bool _tox_profile_dirty {false}; // set in callbacks
};

23
src/tox_utils.cpp Normal file
View File

@ -0,0 +1,23 @@
#include "./tox_utils.hpp"
#include <sodium.h>
std::vector<uint8_t> hex2bin(const std::string& str) {
std::vector<uint8_t> bin{};
bin.resize(str.size()/2, 0);
sodium_hex2bin(bin.data(), bin.size(), str.c_str(), str.length(), nullptr, nullptr, nullptr);
return bin;
}
std::string bin2hex(const std::vector<uint8_t>& bin) {
std::string str{};
str.resize(bin.size()*2, '?');
// HECK, std is 1 larger than size returns ('\0')
sodium_bin2hex(str.data(), str.size()+1, bin.data(), bin.size());
return str;
}

8
src/tox_utils.hpp Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include <string>
#include <vector>
std::vector<uint8_t> hex2bin(const std::string& str);
std::string bin2hex(const std::vector<uint8_t>& bin);