1
0
mirror of https://github.com/Tha14/toxic.git synced 2025-06-28 00:06:45 +02:00

Compare commits

...

19 Commits

Author SHA1 Message Date
fd263e3e0a Add config option to show real-time network info in UI 2022-03-20 11:16:46 -04:00
15ab58aa13 Add run time, avg. kb/s and packets/s to netprof log dump 2022-03-20 11:16:46 -04:00
b91f5a8758 Add tox network profiling
Profiling can be enabled with the -s run option
2022-03-20 11:16:11 -04:00
cec96e1ea3 Use calloc instead of malloc for new message queue items
This prevents us from accidentally using uninitialized memory
2022-03-18 12:17:50 -04:00
eb7e6151a2 cleanup: Ensure python_api.c is never completely empty.
C doesn't allow this, there must be at least some declarations in it,
even if no code.
2022-03-17 17:52:37 +00:00
22ca3704d2 Use a small hack to get around an ncurses buffer overread
Patch by iphydf
2022-03-16 16:31:41 -04:00
fdfaaf953f cleanup: Remove all uses of deprecated enum names.
All-caps enum names have been deprecated for a while now and will go
away in 0.3.0.
2022-03-07 19:20:35 +00:00
310cf464d0 Fix bug causing messages containing newline byte to disappear
The wcswidth() function was silently failing when trying to convert
messages containing a newline to a widechar buffer which resulted
in the message showing up as an empty line. we now fall back
to using strlen to get the width of the string, which might still
cause minor display bugs when the message contains unicode, but is
still better than losing messages entirely.
2022-03-02 15:58:21 -05:00
0c11b3121a Update static musl build script
Bump toxcore to v0.2.16 and add new msgpack dependency
2022-02-20 13:12:23 -05:00
1bdf0041bc Bump toxic and curl versions in static build script 2022-02-12 21:17:19 -05:00
6a203fd7bf Make sure we compare wchars to wchars instead of bytes 2022-02-03 13:01:08 -05:00
93b3bbd5f6 chore: Use latest instead of versioned toktok-stack image. 2022-01-30 19:32:00 +00:00
e122c5dbca Use widechars to display strings in the UI
This fixes a bug where printing a bunch of UTF8 chars with glyphs
that have a size > 1 would make the entire chat window disappear.
It also fixes an issue where said UTF8 chars would be truncated
and generally not display correctly.
2022-01-27 15:45:56 -05:00
f6f41a510b Add some simple impersonation detection on friend requests
This will alert the user when the first six bytes of a new
contact's public key is the same as any other contact in
their list. These 6 bytes are used elsewhere in toxic for
unique identification.

Also did a small refactor regarding the KEY_IDENT_BYTES
define
2022-01-23 11:32:57 -05:00
05dbc626e2 Make sure we check for duplicate paths in pending file transfers list
This fixes a bug where if you receive multiple file transfer
requests simultaneously and they have the same path the files
will overwrite each other
2022-01-17 10:53:34 -05:00
ceb175e3f1 chore: Add check that the static build script works.
Otherwise it'll break again in the future and we won't know.
2022-01-13 01:37:24 +00:00
4bd1d9bfee Update libbrotli pc file sed
libbrotli has updated its .pc files since the last sed was written, so
it didn't work anymore, resulting in Toxic build failing. However, the
way they have updated it, it's still broken, so a different sed is
needed.
2022-01-05 15:55:30 -05:00
55944aa5a9 Remove broken Docker check
The Docker detection method doesn't work on cgroup v2 systems, so the
script just keeps erroring out.

There doesn't seem to be a simple way to detect that we are running
inside a Docker container, so it makes sense to drop that check
altogether.
2022-01-05 15:52:57 -05:00
b71c6a3792 Improve static build script documentation 2022-01-05 15:51:52 -05:00
27 changed files with 707 additions and 113 deletions

View File

@ -1,7 +1,7 @@
---
cirrus-ci_task:
bazel-opt_task:
container:
image: toxchat/toktok-stack:0.0.31-third_party
image: toxchat/toktok-stack:latest-release
cpu: 2
memory: 2G
configure_script:
@ -9,5 +9,4 @@ cirrus-ci_task:
test_all_script:
- cd /src/workspace && bazel test -k
--remote_http_cache=http://$CIRRUS_HTTP_CACHE_HOST
--config=release
//toxic/...

View File

@ -12,7 +12,8 @@ branches:
required_status_checks:
contexts:
- build
- cirrus-ci
- build-static
- bazel-opt
- Codacy Static Code Analysis
- code-review/reviewable
- infer

View File

@ -18,6 +18,7 @@ jobs:
libalut-dev
libconfig-dev
libcurl4-gnutls-dev
libmsgpack-dev
libnotify-dev
libopenal-dev
libopus-dev
@ -37,6 +38,22 @@ jobs:
- name: Build toxic
run: make -j4
build-static:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Build minimal static toxic binary
run: docker run --rm
-v /tmp/artifact:/artifact
-v $PWD:/toxic
amd64/alpine:latest
sh -c 'yes | /toxic/script/build-minimal-static-toxic.sh'
- name: Display binary checksum
run: |
tar Jxf /tmp/artifact/toxic-minimal-static-musl_linux_x86-64.tar.xz
sha256sum toxic-minimal-static-musl_linux_x86-64/toxic
infer:
runs-on: ubuntu-latest
container: toxchat/infer
@ -56,6 +73,7 @@ jobs:
libalut-dev
libconfig-dev
libcurl4-gnutls-dev
libmsgpack-dev
libncurses-dev
libnotify-dev
libopenal-dev
@ -87,6 +105,7 @@ jobs:
libnotify
libpng
libqrencode
msgpack
ncurses
openal
python3

View File

@ -1,6 +1,8 @@
load("@rules_cc//cc:defs.bzl", "cc_binary")
load("//tools/project:build_defs.bzl", "project")
package(features = ["layering_check"])
project()
cc_binary(

View File

@ -14,7 +14,7 @@ LDFLAGS += ${USER_LDFLAGS}
OBJ = autocomplete.o avatars.o bootstrap.o chat.o chat_commands.o configdir.o curl_util.o execute.o
OBJ += file_transfers.o friendlist.o global_commands.o conference_commands.o conference.o help.o input.o line_info.o
OBJ += log.o message_queue.o misc_tools.o name_lookup.o notify.o prompt.o qr_code.o settings.o
OBJ += log.o message_queue.o misc_tools.o name_lookup.o netprof.o notify.o prompt.o qr_code.o settings.o
OBJ += term_mplex.o toxic.o toxic_strings.o windows.o
# Check if debug build is enabled

View File

@ -138,6 +138,11 @@ Show welcome message on startup\&. true or false
Enable friend connection change notifications\&. true or false
.RE
.PP
\fBshow_network_info\fR
.RS 4
Show network information in the UI home window\&. true or false
.RE
.PP
\fBnodelist_update_freq\fR
.RS 4
How often in days to update the DHT nodes list\&. (integer; 0 to disable)

View File

@ -87,6 +87,9 @@ OPTIONS
*show_connection_msg*;;
Enable friend connection change notifications. true or false
*show_network_info*;;
Show network information in the UI home window. true or false
*nodelist_update_freq*;;
How often in days to update the DHT nodes list. (integer; 0 to disable)

View File

@ -56,6 +56,9 @@ ui = {
// true to show friend connection change messages on the home screen
show_connection_msg=true;
// true to show network information in the UI home window
show_network_info=true;
// How often in days to update the DHT nodes list. (0 to disable updates)
nodeslist_update_freq=7;

View File

@ -2,7 +2,7 @@
# MIT License
#
# Copyright (c) 2021 Maxim Biro <nurupo.contributions@gmail.com>
# Copyright (c) 2021-2022 Maxim Biro <nurupo.contributions@gmail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@ -36,8 +36,19 @@
#
# that would use Toxic code from /home/jfreegman/git/toxic and place the build
# artifact at /tmp/artifact.
# You can change between amd64/alpine:latest and i386/alpine:latest, for 64-bit
# and 32-bit builds.
#
# You can change between:
# amd64/alpine:latest,
# i386/alpine:latest,
# arm64v8/alpine:latest,
# arm32v7/alpine:latest,
# arm32v6/alpine:latest,
# ppc64le/alpine:latest,
# s390x/alpine:latest,
# etc.
# as long as your system can run foreign architecture binaries, e.g. via qemu
# static bins and binfmt (install qemu-user-static package on Debian/Ubuntu).
#
#
# To debug, run:
#
@ -53,13 +64,6 @@ set -eu
ARTIFACT_DIR="/artifact"
TOXIC_SRC_DIR="/toxic"
# Make sure we run in the expected environment
if ! grep -q 'docker' /proc/1/cgroup
then
echo "Error: This script should be run inside a disposable Docker container as it might modify system files in ways that would break a real system."
exit 1
fi
if [ ! -f /etc/os-release ] || ! grep -qi 'Alpine Linux' /etc/os-release
then
echo "Error: This script expects to be run on Alpine Linux."
@ -110,6 +114,7 @@ apk add \
libsodium-dev \
libsodium-static \
linux-headers \
msgpack-c-dev \
ncurses-dev \
ncurses-static \
ncurses-terminfo \
@ -132,10 +137,10 @@ mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
# The git hash of the c-toxcore version we're using
TOXCORE_VERSION="v0.2.13"
TOXCORE_VERSION="v0.2.16"
# The sha256sum of the c-toxcore tarball for TOXCORE_VERSION
TOXCORE_HASH="67114fa57504c58b695f5dce8ef85124d555f2c3c353d0d2615e6d4845114ab8"
TOXCORE_HASH="653aa42654b607f0940cecfac873e9ce55605119a90d1dc454d1090ff6ca29c0"
TOXCORE_FILENAME="c-toxcore-$TOXCORE_VERSION.tar.gz"
@ -164,8 +169,8 @@ cmake --build _build --target install
# location with SSL_CERT_FILE env variable.
cd "$BUILD_DIR"
CURL_VERSION="7.80.0"
CURL_HASH="dab997c9b08cb4a636a03f2f7f985eaba33279c1c52692430018fae4a4878dc7"
CURL_VERSION="7.81.0"
CURL_HASH="ac8e1087711084548d788ef18b9b732c8de887457b81f616fc681d1044b32f98"
CURL_FILENAME="curl-$CURL_VERSION.tar.gz"
wget --timeout=10 -O "$CURL_FILENAME" "https://curl.haxx.se/download/$CURL_FILENAME"
@ -186,7 +191,8 @@ cd curl*
--with-openssl
make
make install
sed -i 's|-lbrotlidec |-lbrotlidec-static -lbrotlicommon-static |g' $BUILD_DIR/prefix-curl/lib/pkgconfig/libcurl.pc
sed -i 's|-lbrotlidec |-lbrotlidec -lbrotlicommon |g' $BUILD_DIR/prefix-curl/lib/pkgconfig/libcurl.pc
# Build Toxic
cd "$BUILD_DIR"
@ -301,4 +307,3 @@ mv "$PREPARE_ARTIFACT_DIR" "$PREPARE_ARTIFACT_DIR/../$ARTIFACT_NAME"
tar -cJf "$ARTIFACT_NAME.tar.xz" "$ARTIFACT_NAME"
mv "$ARTIFACT_NAME.tar.xz" "$ARTIFACT_DIR"
chmod 777 -R "$ARTIFACT_DIR"

View File

@ -130,7 +130,7 @@ static void set_self_typingstatus(ToxWindow *self, Tox *m, bool is_typing)
ChatContext *ctx = self->chatwin;
TOX_ERR_SET_TYPING err;
Tox_Err_Set_Typing err;
tox_self_set_typing(m, self->num, is_typing, &err);
if (err != TOX_ERR_SET_TYPING_OK) {
@ -676,8 +676,10 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
FILE *filecheck = NULL;
int count = 1;
while ((filecheck = fopen(file_path, "r"))) {
while ((filecheck = fopen(file_path, "r")) || file_transfer_recv_path_exists(file_path)) {
if (filecheck) {
fclose(filecheck);
}
file_path[path_len] = '\0';
char d[5];
@ -1383,7 +1385,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
self->x = x2;
/* Truncate note if it doesn't fit in statusbar */
size_t maxlen = x2 - getcurx(statusbar->topline) - (KEY_IDENT_DIGITS * 2) - 6;
size_t maxlen = x2 - getcurx(statusbar->topline) - KEY_IDENT_BYTES - 6;
pthread_mutex_lock(&Winthread.lock);
size_t statusmsg_len = statusbar->statusmsg_len;
@ -1414,10 +1416,10 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
int s_x;
getyx(statusbar->topline, s_y, s_x);
mvwhline(statusbar->topline, s_y, s_x, ' ', x2 - s_x - (KEY_IDENT_DIGITS * 2) - 3);
mvwhline(statusbar->topline, s_y, s_x, ' ', x2 - s_x - KEY_IDENT_BYTES - 3);
wattroff(statusbar->topline, COLOR_PAIR(BAR_TEXT));
wmove(statusbar->topline, 0, x2 - (KEY_IDENT_DIGITS * 2) - 3);
wmove(statusbar->topline, 0, x2 - KEY_IDENT_BYTES - 3);
wattron(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wprintw(statusbar->topline, "{");
@ -1425,7 +1427,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
wattron(statusbar->topline, COLOR_PAIR(BAR_TEXT));
for (size_t i = 0; i < KEY_IDENT_DIGITS; ++i) {
for (size_t i = 0; i < KEY_IDENT_BYTES / 2; ++i) {
wprintw(statusbar->topline, "%02X", Friends.list[self->num].pub_key[i] & 0xff);
}

View File

@ -45,9 +45,8 @@ extern FriendsList Friends;
void init_progress_bar(char *progline)
{
strcpy(progline, "0% [");
int i;
for (i = 0; i < NUM_PROG_MARKS; ++i) {
for (size_t i = 0; i < NUM_PROG_MARKS; ++i) {
strcat(progline, "-");
}
@ -397,3 +396,26 @@ void kill_all_file_transfers(Tox *m)
kill_all_file_transfers_friend(m, Friends.list[i].num);
}
}
bool file_transfer_recv_path_exists(const char *path)
{
for (size_t friendnumber = 0; friendnumber < Friends.max_idx; ++friendnumber) {
if (!Friends.list[friendnumber].active) {
continue;
}
for (size_t i = 0; i < MAX_FILES; ++i) {
FileTransfer *ft = &Friends.list[friendnumber].file_receiver[i];
if (ft->state == FILE_TRANSFER_INACTIVE) {
continue;
}
if (strcmp(path, ft->file_path) == 0) {
return true;
}
}
}
return false;
}

View File

@ -145,4 +145,7 @@ void kill_all_file_transfers_friend(Tox *m, uint32_t friendnumber);
void kill_all_file_transfers(Tox *m);
/* Return true if any pending or active file receiver has the path `path`. */
bool file_transfer_recv_path_exists(const char *path);
#endif /* FILE_TRANSFERS_H */

View File

@ -1129,7 +1129,7 @@ int game_packet_send(const GameData *game, const uint8_t *data, size_t length, G
memcpy(packet + 1 + GAME_PACKET_HEADER_SIZE, data, length);
packet_length += length;
TOX_ERR_FRIEND_CUSTOM_PACKET err;
Tox_Err_Friend_Custom_Packet err;
if (!tox_friend_send_lossless_packet(game->tox, game->friend_number, packet, packet_length, &err)) {
fprintf(stderr, "failed to send game packet: error %d\n", err);

View File

@ -20,6 +20,10 @@
*
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* needed for wcswidth() */
#endif
#include <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>
@ -137,13 +141,16 @@ static struct line_info *line_info_ret_queue(struct history *hst)
* Return 0 if string does not contain a newline byte.
* Return -1 if printing was aborted.
*/
static int print_n_chars(WINDOW *win, const char *s, size_t n, int max_y)
static int print_n_chars(WINDOW *win, const wchar_t *s, size_t n, int max_y)
{
// we use an array to represent a single wchar in order to get around an ncurses
// bug with waddnwstr() that overreads the memory address by one byte when
// supplied with a single wchar.
wchar_t ch[2] = {0};
bool newline = false;
char ch;
for (size_t i = 0; i < n && (ch = s[i]); ++i) {
if (ch == '\n') {
for (size_t i = 0; i < n && (ch[0] = s[i]); ++i) {
if (ch[0] == L'\n') {
newline = true;
int x;
@ -159,7 +166,17 @@ static int print_n_chars(WINDOW *win, const char *s, size_t n, int max_y)
}
if (win) {
wprintw(win, "%c", ch);
#ifdef HAVE_WIDECHAR
waddnwstr(win, ch, 1);
#else
char b;
if (wcstombs(&b, ch, sizeof(char)) != 1) {
continue;
}
wprintw(win, "%c", b);
#endif // HAVE_WIDECHAR
}
}
@ -169,10 +186,10 @@ static int print_n_chars(WINDOW *win, const char *s, size_t n, int max_y)
/* Returns the index of the last space character in `s` found before `limit`.
* Returns -1 if no space is found.
*/
static int rspace_index(const char *s, int limit)
static int rspace_index(const wchar_t *s, int limit)
{
for (int i = limit; i >= 0; --i) {
if (s[i] == ' ') {
if (s[i] == L' ') {
return i;
}
}
@ -183,12 +200,12 @@ static int rspace_index(const char *s, int limit)
/* Returns the first index in `s` containing a newline byte found before `limit`.
* Returns -1 if no newline is found.
*/
static int newline_index(const char *s, int limit)
static int newline_index(const wchar_t *s, int limit)
{
char ch;
wchar_t ch;
for (int i = 0; i < limit && (ch = s[i]); ++i) {
if (ch == '\n') {
if (ch == L'\n') {
return i;
}
}
@ -197,13 +214,13 @@ static int newline_index(const char *s, int limit)
}
/* Returns the number of newline bytes in `s` */
static unsigned int newline_count(const char *s)
static unsigned int newline_count(const wchar_t *s)
{
char ch;
wchar_t ch;
unsigned int count = 0;
for (size_t i = 0; (ch = s[i]); ++i) {
if (ch == '\n') {
if (ch == L'\n') {
++count;
}
}
@ -226,10 +243,10 @@ static int print_wrap(WINDOW *win, struct line_info *line, int max_x, int max_y)
int y;
UNUSED_VAR(y);
const char *msg = line->msg;
uint16_t length = line->msg_len;
const wchar_t *msg = line->msg;
uint16_t length = line->msg_width;
uint16_t lines = 0;
const int x_start = line->len - line->msg_len - 1; // manually keep track of x position because ncurses sucks
const int x_start = line->len - line->msg_width - 1; // manually keep track of x position because ncurses sucks
int x_limit = max_x - x_start;
if (x_limit <= 1) {
@ -246,7 +263,7 @@ static int print_wrap(WINDOW *win, struct line_info *line, int max_x, int max_y)
}
if (length < x_limit) {
int p_ret = print_n_chars(win, msg, length, max_y);
const int p_ret = print_n_chars(win, msg, length, max_y);
if (p_ret == 1) {
lines += newline_count(msg);
@ -258,7 +275,7 @@ static int print_wrap(WINDOW *win, struct line_info *line, int max_x, int max_y)
break;
}
int newline_idx = newline_index(msg, x_limit - 1);
const int newline_idx = newline_index(msg, x_limit - 1);
if (newline_idx >= 0) {
if (print_n_chars(win, msg, newline_idx + 1, max_y) == -1) {
@ -272,7 +289,7 @@ static int print_wrap(WINDOW *win, struct line_info *line, int max_x, int max_y)
continue;
}
int space_idx = rspace_index(msg, x_limit - 1);
const int space_idx = rspace_index(msg, x_limit - 1);
if (space_idx >= 1) {
if (print_n_chars(win, msg, space_idx, max_y) == -1) {
@ -321,6 +338,37 @@ static int print_wrap(WINDOW *win, struct line_info *line, int max_x, int max_y)
return 0;
}
/* Converts `msg` into a widechar string and puts the result in `buf`.
*
* Returns the widechar width of the string.
*/
static uint16_t line_info_add_msg(wchar_t *buf, size_t buf_size, const char *msg)
{
if (msg == NULL || msg[0] == '\0') {
return 0;
}
const wint_t wc_msg_len = mbs_to_wcs_buf(buf, msg, buf_size);
if (wc_msg_len > 0 && wc_msg_len < buf_size) {
buf[wc_msg_len] = L'\0';
int width = wcswidth(buf, wc_msg_len);
if (width == -1) { // the best we can do on failure is to fall back to strlen
width = strlen(msg);
}
return (uint16_t)width;
} else {
fprintf(stderr, "Failed to convert string '%s' to widechar\n", msg);
const wchar_t *err = L"Failed to parse message";
uint16_t width = (uint16_t)wcslen(err);
wmemcpy(buf, err, width);
buf[width] = L'\0';
return width;
}
}
static void line_info_init_line(ToxWindow *self, struct line_info *line)
{
int y2;
@ -409,13 +457,8 @@ int line_info_add(ToxWindow *self, bool show_timestamp, const char *name1, const
break;
}
uint16_t msg_len = 0;
if (frmt_msg[0]) {
snprintf(new_line->msg, sizeof(new_line->msg), "%s", frmt_msg);
msg_len = strlen(new_line->msg);
len += msg_len;
}
const uint16_t msg_width = line_info_add_msg(new_line->msg, sizeof(new_line->msg), frmt_msg);
len += msg_width;
if (show_timestamp) {
get_time_str(new_line->timestr, sizeof(new_line->timestr));
@ -434,7 +477,7 @@ int line_info_add(ToxWindow *self, bool show_timestamp, const char *name1, const
new_line->id = (hst->line_end->id + 1 + hst->queue_size) % INT_MAX;
new_line->len = len;
new_line->msg_len = msg_len;
new_line->msg_width = msg_width;
new_line->type = type;
new_line->bold = bold;
new_line->colour = colour;
@ -518,9 +561,8 @@ void line_info_print(ToxWindow *self)
const int max_y = y2 - CHATBOX_HEIGHT - WINDOW_BAR_HEIGHT;
const int max_x = self->show_peerlist ? x2 - 1 - SIDEBAR_WIDTH : x2;
uint16_t numlines = line->format_lines;
int print_ret = 0;
while (line && numlines++ <= max_y && print_ret == 0) {
while (line && numlines++ <= max_y) {
int y;
int x;
getyx(win, y, x);
@ -557,22 +599,22 @@ void line_info_print(ToxWindow *self)
wprintw(win, "%s %s: ", user_settings->line_normal, line->name1);
wattroff(win, COLOR_PAIR(nameclr));
if (line->msg[0] == 0) {
if (line->msg[0] == L'\0') {
waddch(win, '\n');
break;
}
if (line->msg[0] == '>') {
if (line->msg[0] == L'>') {
wattron(win, COLOR_PAIR(GREEN));
} else if (line->msg[0] == '<') {
} else if (line->msg[0] == L'<') {
wattron(win, COLOR_PAIR(RED));
}
print_ret = print_wrap(win, line, max_x, max_y);
print_wrap(win, line, max_x, max_y);
if (line->msg[0] == '>') {
if (line->msg[0] == L'>') {
wattroff(win, COLOR_PAIR(GREEN));
} else if (line->msg[0] == '<') {
} else if (line->msg[0] == L'<') {
wattroff(win, COLOR_PAIR(RED));
}
@ -592,7 +634,7 @@ void line_info_print(ToxWindow *self)
wattron(win, COLOR_PAIR(YELLOW));
wprintw(win, "%s %s ", user_settings->line_normal, line->name1);
print_ret = print_wrap(win, line, max_x, max_y);
print_wrap(win, line, max_x, max_y);
wattroff(win, COLOR_PAIR(YELLOW));
waddch(win, '\n');
@ -613,7 +655,7 @@ void line_info_print(ToxWindow *self)
wattron(win, COLOR_PAIR(line->colour));
}
print_ret = print_wrap(win, line, max_x, max_y);
print_wrap(win, line, max_x, max_y);
waddch(win, '\n');
if (line->bold) {
@ -631,8 +673,8 @@ void line_info_print(ToxWindow *self)
wprintw(win, "$ ");
wattroff(win, COLOR_PAIR(GREEN));
if (line->msg[0]) {
print_ret = print_wrap(win, line, max_x, max_y);
if (line->msg[0] != L'\0') {
print_wrap(win, line, max_x, max_y);
}
waddch(win, '\n');
@ -650,7 +692,7 @@ void line_info_print(ToxWindow *self)
wprintw(win, "%s ", line->name1);
wattroff(win, A_BOLD);
print_ret = print_wrap(win, line, max_x, max_y);
print_wrap(win, line, max_x, max_y);
waddch(win, '\n');
wattroff(win, COLOR_PAIR(line->colour));
@ -669,7 +711,7 @@ void line_info_print(ToxWindow *self)
wprintw(win, "%s ", line->name1);
wattroff(win, A_BOLD);
print_ret = print_wrap(win, line, max_x, max_y);
print_wrap(win, line, max_x, max_y);
waddch(win, '\n');
wattroff(win, COLOR_PAIR(line->colour));
@ -687,7 +729,7 @@ void line_info_print(ToxWindow *self)
wprintw(win, "%s", line->name1);
wattroff(win, A_BOLD);
print_ret = print_wrap(win, line, max_x, max_y);
print_wrap(win, line, max_x, max_y);
wattron(win, A_BOLD);
wprintw(win, "%s\n", line->name2);
@ -749,10 +791,9 @@ void line_info_set(ToxWindow *self, uint32_t id, char *msg)
while (line) {
if (line->id == id) {
size_t new_len = strlen(msg);
line->len = line->len - line->msg_len + new_len;
line->msg_len = new_len;
snprintf(line->msg, sizeof(line->msg), "%s", msg);
const uint16_t new_width = line_info_add_msg(line->msg, sizeof(line->msg), msg);
line->len = line->len - line->msg_width + new_width;
line->msg_width = new_width;
return;
}

View File

@ -49,7 +49,7 @@ struct line_info {
char timestr[TIME_STR_SIZE];
char name1[TOXIC_MAX_NAME_LENGTH + 1];
char name2[TOXIC_MAX_NAME_LENGTH + 1];
char msg[MAX_LINE_INFO_MSG_SIZE];
wchar_t msg[MAX_LINE_INFO_MSG_SIZE];
time_t timestamp;
uint8_t type;
uint8_t bold;
@ -58,7 +58,7 @@ struct line_info {
bool read_flag; /* true if a message has been flagged as read */
uint32_t id;
uint16_t len; /* combined length of entire line */
uint16_t msg_len; /* length of the message */
uint16_t msg_width; /* width of the message */
uint16_t format_lines; /* number of lines the combined string takes up (dynamically set) */
struct line_info *prev;

View File

@ -62,21 +62,21 @@ static int get_log_path(char *dest, int destsize, const char *name, const char *
/* first 6 bytes of selfkey */
char self_id[32] = {0};
path_len += KEY_IDENT_DIGITS * 2;
path_len += KEY_IDENT_BYTES;
sprintf(&self_id[0], "%02X", selfkey[0] & 0xff);
sprintf(&self_id[2], "%02X", selfkey[1] & 0xff);
sprintf(&self_id[4], "%02X", selfkey[2] & 0xff);
self_id[KEY_IDENT_DIGITS * 2] = '\0';
self_id[KEY_IDENT_BYTES] = '\0';
char other_id[32] = {0};
if (otherkey) {
/* first 6 bytes of otherkey */
path_len += KEY_IDENT_DIGITS * 2;
path_len += KEY_IDENT_BYTES;
sprintf(&other_id[0], "%02X", otherkey[0] & 0xff);
sprintf(&other_id[2], "%02X", otherkey[1] & 0xff);
sprintf(&other_id[4], "%02X", otherkey[2] & 0xff);
other_id[KEY_IDENT_DIGITS * 2] = '\0';
other_id[KEY_IDENT_BYTES] = '\0';
}
if (path_len >= destsize) {

View File

@ -48,7 +48,7 @@ void cqueue_add(struct chat_queue *q, const char *msg, size_t len, uint8_t type,
return;
}
struct cqueue_msg *new_m = malloc(sizeof(struct cqueue_msg));
struct cqueue_msg *new_m = calloc(1, sizeof(struct cqueue_msg));
if (new_m == NULL) {
exit_toxic_err("failed in cqueue_message", FATALERR_MEMORY);
@ -62,6 +62,7 @@ void cqueue_add(struct chat_queue *q, const char *msg, size_t len, uint8_t type,
new_m->time_added = get_unix_time();
new_m->receipt = -1;
new_m->next = NULL;
new_m->noread_flag = false;
if (q->root == NULL) {
new_m->prev = NULL;
@ -203,7 +204,7 @@ void cqueue_try_send(ToxWindow *self, Tox *m)
return;
}
TOX_ERR_FRIEND_SEND_MESSAGE err;
Tox_Err_Friend_Send_Message err;
Tox_Message_Type type = msg->type == OUT_MSG ? TOX_MESSAGE_TYPE_NORMAL : TOX_MESSAGE_TYPE_ACTION;
uint32_t receipt = tox_friend_send_message(m, self->num, type, (uint8_t *) msg->message, msg->len, &err);

View File

@ -477,10 +477,9 @@ on_error:
returns length of msg, which will be no larger than size-1 */
size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length)
{
size_t i;
size_t j = 0;
for (i = 0; (i < length) && (j < size - 1); ++i) {
for (size_t i = 0; (i < length) && (j < size - 1); ++i) {
if (data[i] != '\r') {
msg[j++] = data[i];
}

299
src/netprof.c Normal file
View File

@ -0,0 +1,299 @@
/* netprof.c
*
*
* Copyright (C) 2022 Toxic All Rights Reserved.
*
* This file is part of Toxic.
*
* Toxic is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Toxic is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdint.h>
#include <stdio.h>
#include "netprof.h"
#include "../../toxcore/toxcore/tox_private.h" // set this to your local toxcore source directory
static void log_tcp_packet_id(FILE *fp, unsigned int id, uint64_t total, uint64_t TCP_id_sent, uint64_t TCP_id_recv)
{
switch (id) {
case TOX_NETPROF_PACKET_ID_ZERO:
case TOX_NETPROF_PACKET_ID_ONE:
case TOX_NETPROF_PACKET_ID_TWO:
case TOX_NETPROF_PACKET_ID_TCP_DISCONNECT:
case TOX_NETPROF_PACKET_ID_FOUR:
case TOX_NETPROF_PACKET_ID_TCP_PONG:
case TOX_NETPROF_PACKET_ID_TCP_OOB_SEND:
case TOX_NETPROF_PACKET_ID_TCP_OOB_RECV:
case TOX_NETPROF_PACKET_ID_TCP_ONION_REQUEST:
case TOX_NETPROF_PACKET_ID_TCP_ONION_RESPONSE:
case TOX_NETPROF_PACKET_ID_TCP_DATA: {
if (TCP_id_recv || TCP_id_sent) {
fprintf(fp, "0x%02x (total): %lu (%.2f%%)\n", id, TCP_id_sent + TCP_id_recv,
((float)TCP_id_recv + TCP_id_sent) / total * 100.0);
}
if (TCP_id_sent) {
fprintf(fp, "0x%02x (sent): %lu (%.2f%%)\n", id, TCP_id_sent, (float)TCP_id_sent / total * 100.0);
}
if (TCP_id_recv) {
fprintf(fp, "0x%02x (recv): %lu (%.2f%%)\n", id, TCP_id_recv, (float)TCP_id_recv / total * 100.0);
}
break;
}
default:
return;
}
}
static void log_udp_packet_id(FILE *fp, unsigned int id, uint64_t total, uint64_t UDP_id_sent, uint64_t UDP_id_recv)
{
switch (id) {
case TOX_NETPROF_PACKET_ID_ZERO:
case TOX_NETPROF_PACKET_ID_ONE:
case TOX_NETPROF_PACKET_ID_TWO:
case TOX_NETPROF_PACKET_ID_FOUR:
case TOX_NETPROF_PACKET_ID_COOKIE_REQUEST:
case TOX_NETPROF_PACKET_ID_COOKIE_RESPONSE:
case TOX_NETPROF_PACKET_ID_CRYPTO_HS:
case TOX_NETPROF_PACKET_ID_CRYPTO_DATA:
case TOX_NETPROF_PACKET_ID_CRYPTO:
case TOX_NETPROF_PACKET_ID_LAN_DISCOVERY:
case TOX_NETPROF_PACKET_ID_ONION_SEND_INITIAL:
case TOX_NETPROF_PACKET_ID_ONION_SEND_1:
case TOX_NETPROF_PACKET_ID_ONION_SEND_2:
case TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST:
case TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE:
case TOX_NETPROF_PACKET_ID_ONION_DATA_REQUEST:
case TOX_NETPROF_PACKET_ID_ONION_DATA_RESPONSE:
case TOX_NETPROF_PACKET_ID_ONION_RECV_3:
case TOX_NETPROF_PACKET_ID_ONION_RECV_2:
case TOX_NETPROF_PACKET_ID_ONION_RECV_1:
case TOX_NETPROF_PACKET_ID_BOOTSTRAP_INFO: {
if (UDP_id_recv || UDP_id_sent) {
fprintf(fp, "0x%02x (total): %lu (%.2f%%)\n", id, UDP_id_sent + UDP_id_recv,
((float)UDP_id_recv + UDP_id_sent) / total * 100.0);
}
if (UDP_id_sent) {
fprintf(fp, "0x%02x (sent): %lu (%.2f%%)\n", id, UDP_id_sent, (float)UDP_id_sent / total * 100.0);
}
if (UDP_id_recv) {
fprintf(fp, "0x%02x (recv): %lu (%.2f%%)\n", id, UDP_id_recv, (float)UDP_id_recv / total * 100.0);
}
break;
}
default:
return;
}
}
static void dump_packet_id_counts(const Tox *m, FILE *fp, uint64_t total_count, Tox_Netprof_Packet_Type packet_type)
{
if (packet_type == TOX_NETPROF_PACKET_TYPE_TCP) {
fprintf(fp, "--- TCP packet counts by packet ID --- \n");
} else {
fprintf(fp, "--- UDP packet counts by packet ID --- \n");
}
for (unsigned long i = TOX_NETPROF_PACKET_ID_ZERO; i <= TOX_NETPROF_PACKET_ID_BOOTSTRAP_INFO; ++i) {
const uint64_t id_count_sent = tox_netprof_get_packet_id_count(m, packet_type, i, TOX_NETPROF_DIRECTION_SENT);
const uint64_t id_count_recv = tox_netprof_get_packet_id_count(m, packet_type, i, TOX_NETPROF_DIRECTION_RECV);
if (packet_type == TOX_NETPROF_PACKET_TYPE_TCP) {
log_tcp_packet_id(fp, i, total_count, id_count_sent, id_count_recv);
} else {
log_udp_packet_id(fp, i, total_count, id_count_sent, id_count_recv);
}
}
fprintf(fp, "\n\n");
}
static void dump_packet_id_bytes(const Tox *m, FILE *fp, uint64_t total_bytes, Tox_Netprof_Packet_Type packet_type)
{
if (packet_type == TOX_NETPROF_PACKET_TYPE_TCP) {
fprintf(fp, "--- TCP byte counts by packet ID --- \n");
} else {
fprintf(fp, "--- UDP byte counts by packet ID --- \n");
}
for (unsigned long i = TOX_NETPROF_PACKET_ID_ZERO; i <= TOX_NETPROF_PACKET_ID_BOOTSTRAP_INFO; ++i) {
const uint64_t id_bytes_sent = tox_netprof_get_packet_id_bytes(m, packet_type, i, TOX_NETPROF_DIRECTION_SENT);
const uint64_t id_bytes_recv = tox_netprof_get_packet_id_bytes(m, packet_type, i, TOX_NETPROF_DIRECTION_RECV);
if (packet_type == TOX_NETPROF_PACKET_TYPE_TCP) {
log_tcp_packet_id(fp, i, total_bytes, id_bytes_sent, id_bytes_recv);
} else {
log_udp_packet_id(fp, i, total_bytes, id_bytes_sent, id_bytes_recv);
}
}
fprintf(fp, "\n\n");
}
static void dump_packet_count_totals(const Tox *m, FILE *fp, uint64_t total_packet_count,
uint64_t UDP_count_sent, uint64_t UDP_count_recv,
uint64_t TCP_count_sent, uint64_t TCP_count_recv)
{
const uint64_t total_UDP_count = UDP_count_sent + UDP_count_recv;
const uint64_t total_TCP_count = TCP_count_sent + TCP_count_recv;
const uint64_t total_packet_count_sent = UDP_count_sent + TCP_count_sent;
const uint64_t total_packet_count_recv = UDP_count_recv + TCP_count_recv;
fprintf(fp, "--- Total packet counts --- \n");
fprintf(fp, "Total packets: %lu\n", total_packet_count);
fprintf(fp, "Total packets sent: %lu (%.2f%%)\n", total_packet_count_sent,
(float)total_packet_count_sent / total_packet_count * 100.0);
fprintf(fp, "Total packets recv: %lu (%.2f%%)\n", total_packet_count_recv,
(float)total_packet_count_recv / total_packet_count * 100.0);
fprintf(fp, "total UDP packets: %lu (%.2f%%)\n", total_UDP_count,
(float)total_UDP_count / total_packet_count * 100.0);
fprintf(fp, "UDP packets sent: %lu (%.2f%%)\n", UDP_count_sent,
(float)UDP_count_sent / total_packet_count * 100.0);
fprintf(fp, "UDP packets recv: %lu (%.2f%%)\n", UDP_count_recv,
(float)UDP_count_recv / total_packet_count * 100.0);
fprintf(fp, "Total TCP packets: %lu (%.2f%%)\n", total_TCP_count,
(float)total_TCP_count / total_packet_count * 100.0);
fprintf(fp, "TCP packets sent: %lu (%.2f%%)\n", TCP_count_sent,
(float)TCP_count_sent / total_packet_count * 100.0);
fprintf(fp, "TCP packets recv: %lu (%.2f%%)\n", TCP_count_recv,
(float)TCP_count_recv / total_packet_count * 100.0);
fprintf(fp, "\n\n");
}
void dump_packet_bytes_totals(const Tox *m, FILE *fp, const uint64_t total_bytes,
const uint64_t UDP_bytes_sent, const uint64_t UDP_bytes_recv,
const uint64_t TCP_bytes_sent, const uint64_t TCP_bytes_recv)
{
const uint64_t total_UDP_bytes = UDP_bytes_sent + UDP_bytes_recv;
const uint64_t total_TCP_bytes = TCP_bytes_sent + TCP_bytes_recv;
const uint64_t total_bytes_sent = UDP_bytes_sent + TCP_bytes_sent;
const uint64_t total_bytes_recv = UDP_bytes_recv + TCP_bytes_recv;
fprintf(fp, "--- Total byte counts --- \n");
fprintf(fp, "Total bytes: %lu\n", total_bytes);
fprintf(fp, "Total bytes sent: %lu (%.2f%%)\n", total_bytes_sent,
(float)total_bytes_sent / total_bytes * 100.0);
fprintf(fp, "Total bytes recv: %lu (%.2f%%)\n", total_bytes_recv,
(float)total_bytes_recv / total_bytes * 100.0);
fprintf(fp, "Total UDP bytes: %lu (%.2f%%)\n", total_UDP_bytes,
(float)total_UDP_bytes / total_bytes * 100.0);
fprintf(fp, "UDP bytes sent: %lu (%.2f%%)\n", UDP_bytes_sent,
(float)UDP_bytes_sent / total_bytes * 100.0);
fprintf(fp, "UDP bytes recv: %lu (%.2f%%)\n", UDP_bytes_recv,
(float)UDP_bytes_recv / total_bytes * 100.0);
fprintf(fp, "Total TCP bytes: %lu (%.2f%%)\n", total_TCP_bytes,
(float)total_TCP_bytes / total_bytes * 100.0);
fprintf(fp, "TCP bytes sent: %lu (%.2f%%)\n", TCP_bytes_sent,
(float)TCP_bytes_sent / total_bytes * 100.0);
fprintf(fp, "TCP bytes recv: %lu (%.2f%%)\n", TCP_bytes_recv,
(float)TCP_bytes_recv / total_bytes * 100.0);
fprintf(fp, "\n\n");
}
void netprof_log_dump(const Tox *m, FILE *fp, time_t run_time)
{
if (fp == NULL) {
fprintf(stderr, "Failed to dump network statistics: null file pointer\n");
return;
}
const uint64_t UDP_count_sent = tox_netprof_get_packet_total_count(m, TOX_NETPROF_PACKET_TYPE_UDP,
TOX_NETPROF_DIRECTION_SENT);
const uint64_t UDP_count_recv = tox_netprof_get_packet_total_count(m, TOX_NETPROF_PACKET_TYPE_UDP,
TOX_NETPROF_DIRECTION_RECV);
const uint64_t TCP_count_sent = tox_netprof_get_packet_total_count(m, TOX_NETPROF_PACKET_TYPE_TCP,
TOX_NETPROF_DIRECTION_SENT);
const uint64_t TCP_count_recv = tox_netprof_get_packet_total_count(m, TOX_NETPROF_PACKET_TYPE_TCP,
TOX_NETPROF_DIRECTION_RECV);
const uint64_t UDP_bytes_sent = tox_netprof_get_packet_total_bytes(m, TOX_NETPROF_PACKET_TYPE_UDP,
TOX_NETPROF_DIRECTION_SENT);
const uint64_t UDP_bytes_recv = tox_netprof_get_packet_total_bytes(m, TOX_NETPROF_PACKET_TYPE_UDP,
TOX_NETPROF_DIRECTION_RECV);
const uint64_t TCP_bytes_sent = tox_netprof_get_packet_total_bytes(m, TOX_NETPROF_PACKET_TYPE_TCP,
TOX_NETPROF_DIRECTION_SENT);
const uint64_t TCP_bytes_recv = tox_netprof_get_packet_total_bytes(m, TOX_NETPROF_PACKET_TYPE_TCP,
TOX_NETPROF_DIRECTION_RECV);
const uint64_t total_count = UDP_count_sent + UDP_count_recv + TCP_count_sent + TCP_count_recv;
const uint64_t total_bytes = UDP_bytes_sent + UDP_bytes_recv + TCP_bytes_sent + TCP_bytes_recv;
fprintf(fp, "--- Tox network profile log dump ---\n");
fprintf(fp, "Run time: %lu seconds\n", run_time);
if (run_time && total_count && total_bytes) {
fprintf(fp, "Average kilobytes per second: %.2f\n", ((float)total_bytes / run_time) / 1000.0);
fprintf(fp, "Average packets per second: %lu\n", total_count / run_time);
fprintf(fp, "Average packet size: %lu bytes\n", total_bytes / total_count);
fprintf(fp, "\n");
}
dump_packet_count_totals(m, fp, total_count, UDP_count_sent, UDP_count_recv, TCP_count_sent, TCP_count_recv);
dump_packet_bytes_totals(m, fp, total_bytes, UDP_bytes_sent, UDP_bytes_recv, TCP_bytes_sent, TCP_bytes_recv);
dump_packet_id_counts(m, fp, total_count, TOX_NETPROF_PACKET_TYPE_TCP);
dump_packet_id_counts(m, fp, total_count, TOX_NETPROF_PACKET_TYPE_UDP);
dump_packet_id_bytes(m, fp, total_bytes, TOX_NETPROF_PACKET_TYPE_TCP);
dump_packet_id_bytes(m, fp, total_bytes, TOX_NETPROF_PACKET_TYPE_UDP);
fflush(fp);
}
uint64_t netprof_get_bytes_up(const Tox *m)
{
const uint64_t UDP_bytes_sent = tox_netprof_get_packet_total_bytes(m, TOX_NETPROF_PACKET_TYPE_UDP,
TOX_NETPROF_DIRECTION_SENT);
const uint64_t TCP_bytes_sent = tox_netprof_get_packet_total_bytes(m, TOX_NETPROF_PACKET_TYPE_TCP,
TOX_NETPROF_DIRECTION_SENT);
return UDP_bytes_sent + TCP_bytes_sent;
}
uint64_t netprof_get_bytes_down(const Tox *m)
{
const uint64_t UDP_bytes_recv = tox_netprof_get_packet_total_bytes(m, TOX_NETPROF_PACKET_TYPE_UDP,
TOX_NETPROF_DIRECTION_RECV);
const uint64_t TCP_bytes_recv = tox_netprof_get_packet_total_bytes(m, TOX_NETPROF_PACKET_TYPE_TCP,
TOX_NETPROF_DIRECTION_RECV);
return UDP_bytes_recv + TCP_bytes_recv;
}

35
src/netprof.h Normal file
View File

@ -0,0 +1,35 @@
/* netprof.h
*
*
* Copyright (C) 2022 Toxic All Rights Reserved.
*
* This file is part of Toxic.
*
* Toxic is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Toxic is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef TOXIC_NETPROF
#define TOXIC_NETPROF
#include <stdio.h>
#include <time.h>
#include <tox/tox.h>
void netprof_log_dump(const Tox *m, FILE *fp, time_t run_time);
uint64_t netprof_get_bytes_down(const Tox *m);
uint64_t netprof_get_bytes_up(const Tox *m);
#endif // TOXIC_NETPROF

View File

@ -36,6 +36,7 @@
#include "line_info.h"
#include "log.h"
#include "misc_tools.h"
#include "netprof.h"
#include "notify.h"
#include "prompt.h"
#include "settings.h"
@ -175,9 +176,7 @@ static int add_friend_request(const char *public_key, const char *data)
return -1;
}
int i;
for (i = 0; i <= FrndRequests.max_idx; ++i) {
for (int i = 0; i <= FrndRequests.max_idx; ++i) {
if (!FrndRequests.request[i].active) {
FrndRequests.request[i].active = true;
memcpy(FrndRequests.request[i].key, public_key, TOX_PUBLIC_KEY_SIZE);
@ -307,6 +306,77 @@ static bool prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
return input_ret;
}
#define NET_INFO_REFRESH_INTERVAL 1
static void draw_network_info(const Tox *m, StatusBar *stb)
{
WINDOW *win = stb->topline;
wattron(win, COLOR_PAIR(BAR_TEXT));
wprintw(win, "%s", stb->network_info);
wattroff(win, COLOR_PAIR(BAR_TEXT));
if (!timed_out(stb->time_last_refreshed, NET_INFO_REFRESH_INTERVAL)) {
return;
}
stb->time_last_refreshed = get_unix_time();
const uint64_t up_bytes = netprof_get_bytes_up(m);
const uint64_t down_bytes = netprof_get_bytes_down(m);
const uint64_t up_delta = (up_bytes - stb->up_bytes) / NET_INFO_REFRESH_INTERVAL;
const uint64_t down_delta = (down_bytes - stb->down_bytes) / NET_INFO_REFRESH_INTERVAL;
stb->up_bytes = up_bytes;
stb->down_bytes = down_bytes;
float up = up_bytes;
float down = down_bytes;
const char *up_unit = "bytes";
const char *down_unit = "bytes";
if (up_bytes > MiB) {
up /= (float)MiB;
up_unit = "MiB";
} else if (up_bytes > KiB) {
up /= (float)KiB;
up_unit = "KiB";
}
if (down_bytes > MiB) {
down /= (float)MiB;
down_unit = "MiB";
} else if (down_bytes > KiB) {
down /= (float)KiB;
down_unit = "KiB";
}
float up_bps = up_delta;
float down_bps = down_delta;
const char *up_bps_unit = "b/s";
const char *down_bps_unit = "b/s";
if (up_bps > MiB) {
up_bps /= (float)MiB;
up_bps_unit = "MiB/s";
} else if (up_bps > KiB) {
up_bps /= (float)KiB;
up_bps_unit = "KiB/s";
}
if (down_bps > MiB) {
down_bps /= (float)MiB;
down_bps_unit = "MiB/s";
} else if (down_bps > KiB) {
down_bps /= (float)KiB;
down_bps_unit = "KiB/s";
}
snprintf(stb->network_info, sizeof(stb->network_info),
" | [Up: %.1f%s (%.1f%s) | Down: %.1f%s (%.1f%s)]", up, up_unit, up_bps, up_bps_unit,
down, down_unit, down_bps, down_bps_unit);
}
static void prompt_onDraw(ToxWindow *self, Tox *m)
{
int x2;
@ -464,6 +534,10 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
wattroff(statusbar->topline, COLOR_PAIR(BAR_TEXT));
}
if (user_settings->show_network_info) {
draw_network_info(m, statusbar);
}
int y;
int x;
getyx(self->window, y, x);
@ -526,6 +600,26 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, uint32_t friendnu
}
}
/**
* Return true is the first 3 bytes of `key` are identical to any other contact in the contact list.
*/
static bool key_is_similar(const char *key)
{
for (size_t i = 0; i < Friends.max_idx; ++i) {
const ToxicFriend *friend = &Friends.list[i];
if (!friend->active) {
continue;
}
if (memcmp(friend->pub_key, key, KEY_IDENT_BYTES / 2) == 0) {
return true;
}
}
return false;
}
static void prompt_onFriendRequest(ToxWindow *self, Tox *m, const char *key, const char *data, size_t length)
{
UNUSED_VAR(m);
@ -536,6 +630,13 @@ static void prompt_onFriendRequest(ToxWindow *self, Tox *m, const char *key, con
line_info_add(self, true, NULL, NULL, SYS_MSG, 0, 0, "Friend request with the message '%s'", data);
write_to_log("Friend request with the message '%s'", "", ctx->log, true);
if (key_is_similar(key)) {
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED,
"WARNING: This contact's public key is suspiciously similar to that of another contact ");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED,
"in your list. This may be an impersonation attempt, or it may have occurred by chance.");
}
int n = add_friend_request(key, data);
if (n == -1) {

View File

@ -20,9 +20,10 @@
*
*/
#include "api.h"
#ifdef PYTHON
#include <Python.h>
#include "api.h"
#include "execute.h"

View File

@ -63,6 +63,7 @@ static struct ui_strings {
const char *show_typing_other;
const char *show_welcome_msg;
const char *show_connection_msg;
const char *show_network_info;
const char *nodeslist_update_freq;
const char *autosave_freq;
@ -97,6 +98,7 @@ static struct ui_strings {
"show_typing_other",
"show_welcome_msg",
"show_connection_msg",
"show_network_info",
"nodeslist_update_freq",
"autosave_freq",
"line_join",
@ -130,6 +132,7 @@ static void ui_defaults(struct user_settings *settings)
settings->show_typing_other = SHOW_TYPING_ON;
settings->show_welcome_msg = SHOW_WELCOME_MSG_ON;
settings->show_connection_msg = SHOW_CONNECTION_MSG_ON;
settings->show_network_info = SHOW_NETWORK_INFO_OFF;
settings->nodeslist_update_freq = 7;
settings->autosave_freq = 600;
@ -398,6 +401,7 @@ int settings_load(struct user_settings *s, const char *patharg)
config_setting_lookup_bool(setting, ui_strings.show_typing_other, &s->show_typing_other);
config_setting_lookup_bool(setting, ui_strings.show_welcome_msg, &s->show_welcome_msg);
config_setting_lookup_bool(setting, ui_strings.show_connection_msg, &s->show_connection_msg);
config_setting_lookup_bool(setting, ui_strings.show_network_info, &s->show_network_info);
config_setting_lookup_int(setting, ui_strings.history_size, &s->history_size);
config_setting_lookup_int(setting, ui_strings.notification_timeout, &s->notification_timeout);

View File

@ -54,6 +54,7 @@ struct user_settings {
int show_typing_other; /* boolean */
int show_welcome_msg; /* boolean */
int show_connection_msg; /* boolean */
int show_network_info; /* boolean */
int nodeslist_update_freq; /* int (<= 0 to disable updates) */
int autosave_freq; /* int (<= 0 to disable autosave) */
@ -120,6 +121,9 @@ enum settings_values {
SHOW_CONNECTION_MSG_OFF = 0,
SHOW_CONNECTION_MSG_ON = 1,
SHOW_NETWORK_INFO_OFF = 0,
SHOW_NETWORK_INFO_ON = 1,
DFLT_HST_SIZE = 700,
MPLEX_OFF = 0,

View File

@ -58,6 +58,7 @@
#include "message_queue.h"
#include "misc_tools.h"
#include "name_lookup.h"
#include "netprof.h"
#include "notify.h"
#include "prompt.h"
#include "settings.h"
@ -143,6 +144,22 @@ static void catch_SIGSEGV(int sig)
exit(EXIT_FAILURE);
}
void cb_toxcore_logger(Tox *m, TOX_LOG_LEVEL level, const char *file, uint32_t line, const char *func,
const char *message, void *user_data)
{
UNUSED_VAR(user_data);
UNUSED_VAR(file);
UNUSED_VAR(m);
if (user_data) {
FILE *fp = (FILE *)user_data;
fprintf(fp, "[%d] %u:%s() - %s\n", level, line, func, message);
fflush(fp);
} else {
fprintf(stderr, "[%d] %u:%s() - %s\n", level, line, func, message);
}
}
static void flag_window_resize(int sig)
{
UNUSED_VAR(sig);
@ -177,6 +194,10 @@ void free_global_data(void)
void exit_toxic_success(Tox *m)
{
if (arg_opts.netprof_log_dump) {
netprof_log_dump(m, arg_opts.netprof_fp, get_unix_time() - arg_opts.netprof_start_time);
}
store_data(m, DATA_FILE);
user_password = (struct user_password) {
@ -207,6 +228,11 @@ void exit_toxic_success(Tox *m)
arg_opts.log_fp = NULL;
}
if (arg_opts.netprof_fp != NULL) {
fclose(arg_opts.netprof_fp);
arg_opts.netprof_fp = NULL;
}
endwin();
curl_global_cleanup();
@ -229,22 +255,6 @@ void exit_toxic_err(const char *errmsg, int errcode)
exit(EXIT_FAILURE);
}
void cb_toxcore_logger(Tox *m, TOX_LOG_LEVEL level, const char *file, uint32_t line, const char *func,
const char *message, void *user_data)
{
UNUSED_VAR(user_data);
UNUSED_VAR(file);
UNUSED_VAR(m);
if (user_data) {
FILE *fp = (FILE *)user_data;
fprintf(fp, "[%d] %u:%s() - %s\n", level, line, func, message);
fflush(fp);
} else {
fprintf(stderr, "[%d] %u:%s() - %s\n", level, line, func, message);
}
}
/* Sets ncurses refresh rate. Lower values make it refresh more often. */
void set_window_refresh_rate(size_t refresh_rate)
{
@ -1199,6 +1209,7 @@ static void print_usage(void)
fprintf(stderr, " -p, --SOCKS5-proxy Use SOCKS5 proxy: Requires [IP] [port]\n");
fprintf(stderr, " -P, --HTTP-proxy Use HTTP proxy: Requires [IP] [port]\n");
fprintf(stderr, " -r, --namelist Use specified name lookup server list\n");
fprintf(stderr, " -s, --netstats Dump network statistic to log on exit: Requires [path]\n");
fprintf(stderr, " -t, --force-tcp Force toxic to use a TCP connection (use with proxies)\n");
fprintf(stderr, " -T, --tcp-server Act as a TCP relay server: Requires [port]\n");
fprintf(stderr, " -u, --unencrypt-data Unencrypt an encrypted data file\n");
@ -1238,6 +1249,7 @@ static void parse_args(int argc, char *argv[])
{"help", no_argument, 0, 'h'},
{"noconnect", no_argument, 0, 'o'},
{"namelist", required_argument, 0, 'r'},
{"netstats", required_argument, 0, 's'},
{"force-tcp", no_argument, 0, 't'},
{"tcp-server", required_argument, 0, 'T'},
{"SOCKS5-proxy", required_argument, 0, 'p'},
@ -1247,7 +1259,7 @@ static void parse_args(int argc, char *argv[])
{NULL, no_argument, NULL, 0},
};
const char *opts_str = "4bdehLotuxvc:f:l:n:r:p:P:T:";
const char *opts_str = "4bdehLotuxvc:f:l:n:r:s:p:P:T:";
int opt = 0;
int indexptr = 0;
@ -1443,6 +1455,25 @@ static void parse_args(int argc, char *argv[])
break;
}
case 's': {
if (optarg == NULL) {
queue_init_message("Invalid argument for option: %d", opt);
break;
}
arg_opts.netprof_fp = fopen(optarg, "w");
if (arg_opts.netprof_fp != NULL) {
queue_init_message("Network profile logging enabled. Logging to file: '%s'", optarg);
arg_opts.netprof_log_dump = true;
arg_opts.netprof_start_time = time(NULL);
} else {
queue_init_message("Failed to open file '%s' for network profile logging.", optarg);
}
break;
}
case 'u': {
arg_opts.unencrypt_data = 1;
break;

View File

@ -23,6 +23,10 @@
#ifndef TOXIC_H
#define TOXIC_H
#ifndef NCURSES_WIDECHAR
#define NCURSES_WIDECHAR 1
#endif
#ifndef TOXICVER
#define TOXICVER "NOVERS" /* Use the -D flag to set this */
#endif
@ -46,7 +50,7 @@
#define MAX_STR_SIZE TOX_MAX_MESSAGE_LENGTH /* must be >= TOX_MAX_MESSAGE_LENGTH */
#define MAX_CMDNAME_SIZE 64
#define TOXIC_MAX_NAME_LENGTH 32 /* Must be <= TOX_MAX_NAME_LENGTH */
#define KEY_IDENT_DIGITS 3 /* number of hex digits to display for the pub-key based identifier */
#define KEY_IDENT_BYTES 6 /* number of hex digits to display for the public key identifier */
#define TIME_STR_SIZE 32
#define COLOR_STR_SIZE 10 /* should fit every color option */

View File

@ -142,6 +142,10 @@ struct arg_opts {
bool logging;
FILE *log_fp;
bool netprof_log_dump;
time_t netprof_start_time;
FILE *netprof_fp;
char proxy_address[256];
uint8_t proxy_type;
uint16_t proxy_port;
@ -248,6 +252,12 @@ struct StatusBar {
size_t nick_len;
Tox_User_Status status;
Tox_Connection connection;
/* network info */
uint64_t up_bytes;
uint64_t down_bytes;
uint64_t time_last_refreshed;
char network_info[MAX_STR_SIZE];
};
#ifdef AUDIO