#include <iostream>
#include <fstream>
#include <chrono>
#include <thread>
#include <vector>
#include <atomic>
#include <cstring>
#include <ogg/ogg.h>
static const char* account_uuid = TOXMOD_ACCOUNT_ID;
static const char* api_key = TOXMOD_API_KEY;
static const char* single_tenant_prefix = "dev";
static const unsigned int num_players = 150;
static const unsigned int buffer_copy_sleep_ms = 250;
static const unsigned int server_begin_upload_ms = 3000;
const char* input_filename = "test_clip.opus";
static const unsigned int packet_length_ms = 20;
static const unsigned int maximum_packets_in_circular_buffer = 1000 / packet_length_ms;
static const unsigned int maximum_opus_packet_size = 80;
std::vector<tox_server_instance_t> tox_server_instances;
if(err)
}
std::string random_string(int len) {
std::string tmp_s;
static const char alphanum[] = "0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
tmp_s.reserve(len);
for(int i = 0; i < len; ++i)
tmp_s += alphanum[rand() % (sizeof(alphanum) - 1)];
return tmp_s;
}
void get_page(ogg_sync_state* sync_state, ogg_page* page, std::ifstream& clip_file) {
unsigned int chunk_size = 1024;
while((ogg_sync_pageout(sync_state, page) != 1) && !clip_file.eof()) {
char* buffer = ogg_sync_buffer(sync_state, chunk_size);
clip_file.read(buffer, chunk_size);
const long bytes_read = (long)clip_file.gcount();
ogg_sync_wrote(sync_state, bytes_read);
}
}
bool check_is_opus_header(const unsigned char* packet, unsigned int packet_size) {
if(packet_size < 8)
return false;
return (packet[0] == 0x4f) && (packet[1] == 0x70);
}
const char** found_player_uuid) {
const char* source_session_uuid;
const char* source_player_uuid;
const char* found_session_uuid;
error_handler(e);
error_handler(e);
int idx = rand() % tox_server_instances.size();
do {
idx = (idx + 1) % tox_server_instances.size();
found_player_inst = tox_server_instances[idx];
error_handler(e);
} while(strcmp(source_session_uuid, found_session_uuid) &&
!(strcmp(source_player_uuid, *found_player_uuid)));
error_handler(e);
}
std::atomic<bool> should_run_buffer_copies = {true};
void run_buffer_copies() {
while(should_run_buffer_copies.load()) {
for(auto&& it : tox_server_instances) {
error_handler(err);
}
std::this_thread::sleep_for(std::chrono::milliseconds(buffer_copy_sleep_ms));
}
}
std::atomic<bool> should_run_begin_uploads = {true};
void run_begin_uploads() {
while(should_run_begin_uploads.load()) {
for(auto&& it : tox_server_instances) {
error_handler(err);
}
std::this_thread::sleep_for(std::chrono::milliseconds(server_begin_upload_ms));
}
}
std::atomic<bool> should_run_run_uploads = {true};
void run_run_uploads() {
while(should_run_run_uploads.load()) {
error_handler(err);
}
}
void* tox_alt_malloc(size_t sz) { return malloc(sz); }
void tox_alt_free(void* ptr) { free(ptr); }
void* tox_alt_realloc(void* ptr, size_t sz) { return realloc(ptr, sz); }
void custom_logging_callback(const char* message) {
std::cout << "[libtox] " << message << std::endl;
}
void custom_error_callback(const char* message) {
std::cerr << "[libtox] " << message << std::endl;
}
int main() {
srand((unsigned int)time(NULL));
if(!strcmp(account_uuid, "your account uuid here")) {
std::cerr << ("Account UUID has not been set. Please set your account_uuid, api_key, "
"and (if applicable) single_tenant_prefix in this example program's "
"source code file before using it.")
<< std::endl;
return 1;
}
if(!strcmp(api_key, "your api key here")) {
std::cerr << ("API Key has not been set. Please set your account_uuid, api_key, "
"and (if applicable) single_tenant_prefix in this example program's "
"source code file before using it.")
<< std::endl;
return 1;
}
std::cout << "Running " << num_players << " simultaneous player chat streams from "
<< input_filename << " through tox_server" << std::endl;
tox_alt_free, tox_alt_realloc, nullptr, nullptr);
error_handler(err);
std::string session_name = random_string(20);
for(size_t i = 0; i < num_players; i++) {
const std::string player_name = random_string(20);
if(rand() % 10 < 1)
session_name = random_string(20);
tox_server_instances.push_back(tox_server_instance);
error_handler(err);
}
std::thread buffer_copy_thread(run_buffer_copies);
std::thread begin_uploads_thread(run_begin_uploads);
std::thread run_uploads_thread(run_run_uploads);
{
ogg_sync_state sync_state;
ogg_stream_state stream_state;
ogg_page page;
ogg_packet packet;
ogg_sync_init(&sync_state);
std::ifstream clip_file(input_filename, std::ios::binary);
if(!clip_file.good()) {
std::cerr << "Failed to open clip file " << input_filename << std::endl;
return 1;
}
size_t counter = 0;
size_t clip_time_ms = 0;
while(!clip_file.eof()) {
get_page(&sync_state, &page, clip_file);
if(ogg_page_bos(&page)) {
const int serial_number = ogg_page_serialno(&page);
ogg_stream_init(&stream_state, serial_number);
}
ogg_stream_pagein(&stream_state, &page);
while(ogg_stream_packetout(&stream_state, &packet) != 0) {
if(!check_is_opus_header(packet.packet, packet.bytes)) {
for(auto&& it : tox_server_instances) {
error_handler(err);
}
std::this_thread::sleep_for(std::chrono::milliseconds(packet_length_ms));
counter++;
if(clip_time_ms % 1000 < packet_length_ms)
std::cout << "." << std::endl;
if(clip_time_ms % 2000 < packet_length_ms) {
std::cout << "Making change to can hear list" << std::endl;
tox_server_instances[rand() % tox_server_instances.size()];
std::vector<const char*> audible_players;
int num_audible_players = rand() % 10;
for(int i = 0; i < num_audible_players; ++i) {
const char* player_uuid;
get_random_other_player_in_session(source_player_inst, &player_uuid);
audible_players.push_back(player_uuid);
}
&source_player_inst, audible_players.data(), num_audible_players);
error_handler(err);
}
if(clip_time_ms % 5000 < packet_length_ms) {
tox_server_instances[rand() % tox_server_instances.size()];
const char* player_uuid;
get_random_other_player_in_session(source_player_inst, &player_uuid);
std::cout << "Muting player: " << std::string(player_uuid) << std::endl;
error_handler(err);
}
clip_time_ms += packet_length_ms;
}
}
}
std::cout << "Total Opus Packets Count: " << counter << std::endl;
ogg_sync_clear(&sync_state);
ogg_stream_clear(&stream_state);
}
std::cout << "Finished Running through audio, stopping threads" << std::endl;
should_run_buffer_copies.store(false);
should_run_begin_uploads.store(false);
should_run_run_uploads.store(false);
buffer_copy_thread.join();
begin_uploads_thread.join();
run_uploads_thread.join();
for(auto&& it : tox_server_instances) {
error_handler(err);
}
int num_current_uploads;
do {
error_handler(err);
} while(num_current_uploads > 0);
error_handler(err);
return 0;
}
Definition tox_server.h:147
const char * session_name_unique
Definition tox_server.h:157
unsigned long circular_buffer_max_num_packets
Definition tox_server.h:163
int enable_proximity_chat
Definition tox_server.h:195
const char * player_name_unique
Definition tox_server.h:152
unsigned long max_packet_size
Definition tox_server.h:168
Definition tox_server.h:136
TOX_SERVER_ERROR tox_server_add_packet(tox_server_instance_t *tox_instance_ptr, const unsigned char *packet, unsigned int packet_size)
TOX_SERVER_ERROR tox_server_get_internal_session_uuid(tox_server_instance_t *tox_instance_ptr, const char **internal_session_uuid)
TOX_SERVER_ERROR tox_server_destroy_instance(tox_server_instance_t *tox_instance_ptr)
TOX_SERVER_ERROR tox_server_set_proximity_chat_player_can_hear(tox_server_instance_t *tox_instance_ptr, const char *const *players, unsigned int num_players)
TOX_SERVER_ERROR tox_server_set_log_error_callback(void(*log_error_callback)(const char *))
TOX_SERVER_ERROR tox_server_begin_upload(tox_server_instance_t *tox_instance_ptr)
TOX_SERVER_ERROR tox_server_global_init_mem(const char *account_uuid, const char *api_key, const char *single_tenant_prefix, tox_server_malloc_callback tox_malloc, tox_server_free_callback tox_free, tox_server_realloc_callback tox_realloc, tox_server_strdup_callback tox_strdup, tox_server_calloc_callback tox_calloc)
const char * tox_server_error_name(TOX_SERVER_ERROR error)
TOX_SERVER_ERROR tox_server_set_log_info_callback(void(*log_info_callback)(const char *))
TOX_SERVER_ERROR tox_server_create_instance(tox_server_instance_t *tox_instance_ptr, const tox_server_config_t *tox_server_config_ptr)
TOX_SERVER_ERROR
Definition tox_server.h:55
TOX_SERVER_ERROR tox_server_global_cleanup(void)
TOX_SERVER_ERROR tox_server_run_all_uploads_with_timeout(int *num_running_uploads, int wait_timeout_milliseconds)
TOX_SERVER_ERROR tox_server_run_buffer_copy(tox_server_instance_t *tox_instance_ptr)
TOX_SERVER_ERROR tox_server_get_internal_player_uuid(tox_server_instance_t *tox_instance_ptr, const char **internal_player_uuid)
TOX_SERVER_ERROR tox_server_set_player_muted(tox_server_instance_t *tox_instance_ptr, const char *player, int muted)