1
0
mirror of https://github.com/Tha14/toxic.git synced 2024-11-23 02:23:02 +01:00

merge with master (new api)

This commit is contained in:
Jfreegman 2015-03-30 21:46:25 -04:00
parent 23429d8da4
commit ee074f334e
No known key found for this signature in database
GPG Key ID: 3627F3144076AE63
38 changed files with 1710 additions and 1726 deletions

View File

@ -11,7 +11,7 @@ CFLAGS += '-DPACKAGE_DATADIR="$(abspath $(DATADIR))"'
CFLAGS += $(USER_CFLAGS) CFLAGS += $(USER_CFLAGS)
LDFLAGS = $(USER_LDFLAGS) LDFLAGS = $(USER_LDFLAGS)
OBJ = chat.o chat_commands.o configdir.o dns.o execute.o file_senders.o notify.o OBJ = chat.o chat_commands.o configdir.o dns.o execute.o file_transfers.o notify.o
OBJ += friendlist.o global_commands.o groupchat.o line_info.o input.o help.o autocomplete.o OBJ += friendlist.o global_commands.o groupchat.o line_info.o input.o help.o autocomplete.o
OBJ += log.o misc_tools.o prompt.o settings.o toxic.o toxic_strings.o windows.o message_queue.o OBJ += log.o misc_tools.o prompt.o settings.o toxic.o toxic_strings.o windows.o message_queue.o
OBJ += group_commands.o term_mplex.o OBJ += group_commands.o term_mplex.o

View File

@ -11,7 +11,7 @@ Toxic is a [Tox](https://tox.im)-based instant messenging client which formerly
If you don't like installation methods listed above, you can still download precompiled binaries from [jenkins](https://jenkins.libtoxcore.so): If you don't like installation methods listed above, you can still download precompiled binaries from [jenkins](https://jenkins.libtoxcore.so):
* [Linux 32 bit](https://jenkins.libtoxcore.so/job/toxic_linux_i386/lastSuccessfulBuild/artifact/toxic_linux_i386.tar.xz) [![Build Status](https://jenkins.libtoxcore.so/job/toxic_linux_i386/badge/icon)](https://jenkins.libtoxcore.so/job/toxic_linux_i386/lastSuccessfulBuild/artifact/toxic_linux_i386.tar.xz) * [Linux 32 bit](https://jenkins.libtoxcore.so/job/toxic_linux_i386/lastSuccessfulBuild/artifact/toxic_linux_i386.tar.xz) [![Build Status](https://jenkins.libtoxcore.so/job/toxic_linux_i386/badge/icon)](https://jenkins.libtoxcore.so/job/toxic_linux_i386/lastSuccessfulBuild/artifact/toxic_linux_i386.tar.xz)
* [Linux 64 bit](https://jenkins.libtoxcore.so/job/toxic_linux_amd64/lastSuccessfulBuild/artifact/toxic_linux_amd64.tar.xz) [![Build Status](https://jenkins.libtoxcore.so/job/toxic_linux_amd64/badge/icon)](https://jenkins.libtoxcore.so/job/toxic_linux_amd64/lastSuccessfulBuild/artifact/toxic_linux_amd64.tar.xz) * [Linux 64 bit](https://jenkins.libtoxcore.so/job/toxic_linux_amd64/lastSuccessfulBuild/artifact/toxic_linux_amd64.tar.xz) [![Build Status](https://jenkins.libtoxcore.so/job/toxic_linux_amd64/badge/icon)](https://jenkins.libtoxcore.so/job/toxic_linux_amd64/lastSuccessfulBuild/artifact/toxic_linux_amd64.tar.xz)
* [~~Linux ARMv6~~](https://jenkins.libtoxcore.so/job/toxic_linux_armv6/lastSuccessfulBuild/artifact/toxic_linux_armv6.tar.xz) **CURRENTLY DISABLED** [![Build Status](https://jenkins.libtoxcore.so/job/toxic_linux_amd64/badge/icon)](https://jenkins.libtoxcore.so/job/toxic_linux_armv6/lastSuccessfulBuild/artifact/toxic_linux_armv6.tar.xz) * [~~Linux ARMv6~~](https://jenkins.libtoxcore.so/job/toxic_linux_armv6/lastSuccessfulBuild/artifact/toxic_linux_armv6.tar.xz) **CURRENTLY DISABLED** [![Build Status](https://jenkins.libtoxcore.so/job/toxic_linux_armv6/badge/icon)](https://jenkins.libtoxcore.so/job/toxic_linux_armv6/lastSuccessfulBuild/artifact/toxic_linux_armv6.tar.xz)
#### DEBs packages #### DEBs packages
* [toxic-i386.deb](https://jenkins.libtoxcore.so/job/toxic-linux-pkg/lastSuccessfulBuild/artifact/toxic-i386.deb) * [toxic-i386.deb](https://jenkins.libtoxcore.so/job/toxic-linux-pkg/lastSuccessfulBuild/artifact/toxic-i386.deb)

View File

@ -1,5 +1,5 @@
# Version # Version
TOXIC_VERSION = 0.5.2 TOXIC_VERSION = 0.6.0
REV = $(shell git rev-list HEAD --count 2>/dev/null || echo -n "error") REV = $(shell git rev-list HEAD --count 2>/dev/null || echo -n "error")
ifneq (, $(findstring error, $(REV))) ifneq (, $(findstring error, $(REV)))
VERSION = $(TOXIC_VERSION) VERSION = $(TOXIC_VERSION)

View File

@ -2,12 +2,12 @@
.\" Title: toxic .\" Title: toxic
.\" Author: [see the "AUTHORS" section] .\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/> .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
.\" Date: 2014-09-19 .\" Date: 2014-12-27
.\" Manual: Toxic Manual .\" Manual: Toxic Manual
.\" Source: toxic __VERSION__ .\" Source: toxic __VERSION__
.\" Language: English .\" Language: English
.\" .\"
.TH "TOXIC" "1" "2014\-09\-19" "toxic __VERSION__" "Toxic Manual" .TH "TOXIC" "1" "2014\-12\-27" "toxic __VERSION__" "Toxic Manual"
.\" ----------------------------------------------------------------- .\" -----------------------------------------------------------------
.\" * Define some portability stuff .\" * Define some portability stuff
.\" ----------------------------------------------------------------- .\" -----------------------------------------------------------------
@ -115,11 +115,6 @@ Force TCP connection (use this with proxies)
.RS 4 .RS 4
Unencrypt a data file\&. A warning will appear if this option is used with a data file that is already unencrypted\&. Unencrypt a data file\&. A warning will appear if this option is used with a data file that is already unencrypted\&.
.RE .RE
.PP
\-x, \-\-nodata
.RS 4
Ignore data file
.RE
.SH "FILES" .SH "FILES"
.PP .PP
__DATADIR__/DHTnodes __DATADIR__/DHTnodes

View File

@ -31,7 +31,7 @@ OPTIONS
Use default locale Use default locale
-e, --encrypt-data:: -e, --encrypt-data::
Encrypt an unencrypted data file. An error will occur if this option Encrypt an unencrypted data file. An error will occur if this option
is used with an encrypted data file. is used with an encrypted data file.
-f, --file data-file:: -f, --file data-file::
@ -60,12 +60,9 @@ OPTIONS
Force TCP connection (use this with proxies) Force TCP connection (use this with proxies)
-u, --unencrypt-data:: -u, --unencrypt-data::
Unencrypt a data file. A warning will appear if this option is used Unencrypt a data file. A warning will appear if this option is used
with a data file that is already unencrypted. with a data file that is already unencrypted.
-x, --nodata::
Ignore data file
FILES FILES
----- -----
{datadir}/DHTnodes:: {datadir}/DHTnodes::

View File

@ -202,7 +202,7 @@ Configuration related to notification sounds\&. Special value "silent" can be us
Each value is a string which corresponds to the absolute path of a wav sound file\&. Each value is a string which corresponds to the absolute path of a wav sound file\&.
.PP .PP
\fBerror\fR \fBnotif_error\fR
.RS 4 .RS 4
Sound to play when an error occurs\&. Sound to play when an error occurs\&.
.RE .RE

View File

@ -132,7 +132,7 @@ OPTIONS
Each value is a string which corresponds to the absolute path of a wav Each value is a string which corresponds to the absolute path of a wav
sound file. sound file.
*error*;; *notif_error*;;
Sound to play when an error occurs. Sound to play when an error occurs.
*self_log_in*;; *self_log_in*;;

View File

@ -59,7 +59,7 @@ static int set_call(Call* call, bool start)
{ {
call->in_idx = -1; call->in_idx = -1;
call->out_idx = -1; call->out_idx = -1;
if ( start ) { if ( start ) {
call->ttas = true; call->ttas = true;
@ -79,9 +79,9 @@ struct ASettings {
AudioError errors; AudioError errors;
ToxAv *av; ToxAv *av;
ToxAvCSettings cs; ToxAvCSettings cs;
Call calls[MAX_CALLS]; Call calls[MAX_CALLS];
} ASettins; } ASettins;
@ -105,15 +105,15 @@ static void print_err (ToxWindow *self, const char *error_str)
} }
ToxAv *init_audio(ToxWindow *self, Tox *tox) ToxAv *init_audio(ToxWindow *self, Tox *tox)
{ {
ASettins.cs = av_DefaultSettings; ASettins.cs = av_DefaultSettings;
ASettins.cs.max_video_height = ASettins.cs.max_video_width = 0; ASettins.cs.max_video_height = ASettins.cs.max_video_width = 0;
ASettins.errors = ae_None; ASettins.errors = ae_None;
memset(ASettins.calls, 0, sizeof(ASettins.calls)); memset(ASettins.calls, 0, sizeof(ASettins.calls));
/* Streaming stuff from core */ /* Streaming stuff from core */
ASettins.av = toxav_new(tox, MAX_CALLS); ASettins.av = toxav_new(tox, MAX_CALLS);
@ -122,7 +122,7 @@ ToxAv *init_audio(ToxWindow *self, Tox *tox)
ASettins.errors |= ae_StartingCoreAudio; ASettins.errors |= ae_StartingCoreAudio;
return NULL; return NULL;
} }
if ( init_devices(ASettins.av) == de_InternalError ) { if ( init_devices(ASettins.av) == de_InternalError ) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to init devices"); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to init devices");
toxav_kill(ASettins.av); toxav_kill(ASettins.av);
@ -142,7 +142,7 @@ ToxAv *init_audio(ToxWindow *self, Tox *tox)
toxav_register_callstate_callback(ASettins.av, callback_requ_timeout, av_OnRequestTimeout, self); toxav_register_callstate_callback(ASettins.av, callback_requ_timeout, av_OnRequestTimeout, self);
toxav_register_callstate_callback(ASettins.av, callback_peer_timeout, av_OnPeerTimeout, self); toxav_register_callstate_callback(ASettins.av, callback_peer_timeout, av_OnPeerTimeout, self);
//toxav_register_callstate_callback(ASettins.av, callback_media_change, av_OnMediaChange, self); //toxav_register_callstate_callback(ASettins.av, callback_media_change, av_OnMediaChange, self);
toxav_register_audio_callback(ASettins.av, write_device_callback, NULL); toxav_register_audio_callback(ASettins.av, write_device_callback, NULL);
return ASettins.av; return ASettins.av;
@ -156,14 +156,14 @@ void terminate_audio()
if ( ASettins.av ) if ( ASettins.av )
toxav_kill(ASettins.av); toxav_kill(ASettins.av);
terminate_devices(); terminate_devices();
} }
void read_device_callback (const int16_t* captured, uint32_t size, void* data) void read_device_callback (const int16_t* captured, uint32_t size, void* data)
{ {
int32_t call_index = *((int32_t*)data); /* TODO: Or pass an array of call_idx's */ int32_t call_index = *((int32_t*)data); /* TODO: Or pass an array of call_idx's */
uint8_t encoded_payload[RTP_PAYLOAD_SIZE]; uint8_t encoded_payload[RTP_PAYLOAD_SIZE];
int32_t payload_size = toxav_prepare_audio_frame(ASettins.av, call_index, encoded_payload, RTP_PAYLOAD_SIZE, captured, size); int32_t payload_size = toxav_prepare_audio_frame(ASettins.av, call_index, encoded_payload, RTP_PAYLOAD_SIZE, captured, size);
if ( payload_size <= 0 || toxav_send_audio(ASettins.av, call_index, encoded_payload, payload_size) < 0 ) { if ( payload_size <= 0 || toxav_send_audio(ASettins.av, call_index, encoded_payload, payload_size) < 0 ) {
@ -207,15 +207,15 @@ int start_transmission(ToxWindow *self, Call *call)
toxav_get_peer_csettings(ASettins.av, self->call_idx, 0, &csettings); toxav_get_peer_csettings(ASettins.av, self->call_idx, 0, &csettings);
if ( open_primary_device(input, &call->in_idx, if ( open_primary_device(input, &call->in_idx,
csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels) != de_None ) csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels) != de_None )
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to open input device!"); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to open input device!");
if ( register_device_callback(self->call_idx, call->in_idx, if ( register_device_callback(self->call_idx, call->in_idx,
read_device_callback, &self->call_idx, true) != de_None) read_device_callback, &self->call_idx, true) != de_None)
/* Set VAD as true for all; TODO: Make it more dynamic */ /* Set VAD as true for all; TODO: Make it more dynamic */
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to register input handler!"); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to register input handler!");
if ( open_primary_device(output, &call->out_idx, if ( open_primary_device(output, &call->out_idx,
csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels) != de_None ) { csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels) != de_None ) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to open output device!"); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to open output device!");
call->has_output = 0; call->has_output = 0;
@ -225,23 +225,23 @@ int start_transmission(ToxWindow *self, Call *call)
} }
int stop_transmission(Call *call, int32_t call_index) int stop_transmission(Call *call, int32_t call_index)
{ {
if ( call->ttas ) { if ( call->ttas ) {
toxav_kill_transmission(ASettins.av, call_index); toxav_kill_transmission(ASettins.av, call_index);
call->ttas = false; call->ttas = false;
if ( call->in_idx != -1 ) if ( call->in_idx != -1 )
close_device(input, call->in_idx); close_device(input, call->in_idx);
if ( call->out_idx != -1 ) if ( call->out_idx != -1 )
close_device(output, call->out_idx); close_device(output, call->out_idx);
if (set_call(call, false) == -1) if (set_call(call, false) == -1)
return -1; return -1;
return 0; return 0;
} }
return -1; return -1;
} }
/* /*
@ -269,10 +269,10 @@ void callback_recv_ringing ( void* av, int32_t call_index, void* arg )
} }
void callback_recv_starting ( void* av, int32_t call_index, void* arg ) void callback_recv_starting ( void* av, int32_t call_index, void* arg )
{ {
ToxWindow* windows = arg; ToxWindow* windows = arg;
int i; int i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) for (i = 0; i < MAX_WINDOWS_NUM; ++i)
if (windows[i].onStarting != NULL && windows[i].call_idx == call_index) { if (windows[i].onStarting != NULL && windows[i].call_idx == call_index) {
windows[i].onStarting(&windows[i], ASettins.av, call_index); windows[i].onStarting(&windows[i], ASettins.av, call_index);
if ( 0 != start_transmission(&windows[i], &ASettins.calls[call_index])) {/* YEAH! */ if ( 0 != start_transmission(&windows[i], &ASettins.calls[call_index])) {/* YEAH! */
line_info_add(&windows[i], NULL, NULL, NULL, SYS_MSG, 0, 0 , "Error starting transmission!"); line_info_add(&windows[i], NULL, NULL, NULL, SYS_MSG, 0, 0 , "Error starting transmission!");
@ -287,10 +287,10 @@ void callback_recv_ending ( void* av, int32_t call_index, void* arg )
} }
void callback_call_started ( void* av, int32_t call_index, void* arg ) void callback_call_started ( void* av, int32_t call_index, void* arg )
{ {
ToxWindow* windows = arg; ToxWindow* windows = arg;
int i; int i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) for (i = 0; i < MAX_WINDOWS_NUM; ++i)
if (windows[i].onStart != NULL && windows[i].call_idx == call_index) { if (windows[i].onStart != NULL && windows[i].call_idx == call_index) {
windows[i].onStart(&windows[i], ASettins.av, call_index); windows[i].onStart(&windows[i], ASettins.av, call_index);
if ( 0 != start_transmission(&windows[i], &ASettins.calls[call_index]) ) {/* YEAH! */ if ( 0 != start_transmission(&windows[i], &ASettins.calls[call_index]) ) {/* YEAH! */
@ -357,7 +357,7 @@ void cmd_call(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
goto on_error; goto on_error;
} }
if (!self->stb->is_online) { if (!self->stb->connection) {
error_str = "Friend is offline."; error_str = "Friend is offline.";
goto on_error; goto on_error;
} }
@ -545,12 +545,12 @@ void cmd_change_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (
error_str = "Invalid input"; error_str = "Invalid input";
goto on_error; goto on_error;
} }
if ( set_primary_device(type, selection) == de_InvalidSelection ) { if ( set_primary_device(type, selection) == de_InvalidSelection ) {
error_str="Invalid selection!"; error_str="Invalid selection!";
goto on_error; goto on_error;
} }
return; return;
on_error: on_error:
print_err (self, error_str); print_err (self, error_str);
@ -559,71 +559,71 @@ on_error:
void cmd_ccur_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_ccur_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{ {
const char *error_str; const char *error_str;
if ( argc != 2 ) { if ( argc != 2 ) {
if ( argc < 1 ) error_str = "Type must be specified!"; if ( argc < 1 ) error_str = "Type must be specified!";
else if ( argc < 2 ) error_str = "Must have id!"; else if ( argc < 2 ) error_str = "Must have id!";
else error_str = "Only two arguments allowed!"; else error_str = "Only two arguments allowed!";
goto on_error; goto on_error;
} }
DeviceType type; DeviceType type;
if ( strcmp(argv[1], "in") == 0 ) /* Input devices */ if ( strcmp(argv[1], "in") == 0 ) /* Input devices */
type = input; type = input;
else if ( strcmp(argv[1], "out") == 0 ) /* Output devices */ else if ( strcmp(argv[1], "out") == 0 ) /* Output devices */
type = output; type = output;
else { else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]);
return; return;
} }
char *end; char *end;
long int selection = strtol(argv[2], &end, 10); long int selection = strtol(argv[2], &end, 10);
if ( *end ) { if ( *end ) {
error_str = "Invalid input"; error_str = "Invalid input";
goto on_error; goto on_error;
} }
if ( selection_valid(type, selection) == de_InvalidSelection ) { if ( selection_valid(type, selection) == de_InvalidSelection ) {
error_str="Invalid selection!"; error_str="Invalid selection!";
goto on_error; goto on_error;
} }
/* If call is active, change device */ /* If call is active, change device */
if ( self->call_idx > -1) { if ( self->call_idx > -1) {
Call* this_call = &ASettins.calls[self->call_idx]; Call* this_call = &ASettins.calls[self->call_idx];
if (this_call->ttas) { if (this_call->ttas) {
ToxAvCSettings csettings; ToxAvCSettings csettings;
toxav_get_peer_csettings(ASettins.av, self->call_idx, 0, &csettings); toxav_get_peer_csettings(ASettins.av, self->call_idx, 0, &csettings);
if (type == output) { if (type == output) {
pthread_mutex_lock(&this_call->mutex); pthread_mutex_lock(&this_call->mutex);
close_device(output, this_call->out_idx); close_device(output, this_call->out_idx);
this_call->has_output = open_device(output, selection, &this_call->out_idx, this_call->has_output = open_device(output, selection, &this_call->out_idx,
csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels) csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels)
== de_None ? 1 : 0; == de_None ? 1 : 0;
pthread_mutex_unlock(&this_call->mutex); pthread_mutex_unlock(&this_call->mutex);
} }
else { else {
/* TODO: check for failure */ /* TODO: check for failure */
close_device(input, this_call->in_idx); close_device(input, this_call->in_idx);
open_device(input, selection, &this_call->in_idx, csettings.audio_sample_rate, open_device(input, selection, &this_call->in_idx, csettings.audio_sample_rate,
csettings.audio_frame_duration, csettings.audio_channels); csettings.audio_frame_duration, csettings.audio_channels);
/* Set VAD as true for all; TODO: Make it more dynamic */ /* Set VAD as true for all; TODO: Make it more dynamic */
register_device_callback(self->call_idx, this_call->in_idx, read_device_callback, &self->call_idx, true); register_device_callback(self->call_idx, this_call->in_idx, read_device_callback, &self->call_idx, true);
} }
} }
} }
self->device_selection[type] = selection; self->device_selection[type] = selection;
return; return;
on_error: on_error:
print_err (self, error_str); print_err (self, error_str);
@ -632,33 +632,33 @@ void cmd_ccur_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a
void cmd_mute(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_mute(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{ {
const char *error_str; const char *error_str;
if ( argc != 1 ) { if ( argc != 1 ) {
if ( argc < 1 ) error_str = "Type must be specified!"; if ( argc < 1 ) error_str = "Type must be specified!";
else error_str = "Only two arguments allowed!"; else error_str = "Only two arguments allowed!";
goto on_error; goto on_error;
} }
DeviceType type; DeviceType type;
if ( strcasecmp(argv[1], "in") == 0 ) /* Input devices */ if ( strcasecmp(argv[1], "in") == 0 ) /* Input devices */
type = input; type = input;
else if ( strcasecmp(argv[1], "out") == 0 ) /* Output devices */ else if ( strcasecmp(argv[1], "out") == 0 ) /* Output devices */
type = output; type = output;
else { else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]);
return; return;
} }
/* If call is active, use this_call values */ /* If call is active, use this_call values */
if ( self->call_idx > -1) { if ( self->call_idx > -1) {
Call* this_call = &ASettins.calls[self->call_idx]; Call* this_call = &ASettins.calls[self->call_idx];
pthread_mutex_lock(&this_call->mutex); pthread_mutex_lock(&this_call->mutex);
if (type == input) { if (type == input) {
device_mute(type, this_call->in_idx); device_mute(type, this_call->in_idx);
self->chatwin->infobox.in_is_muted ^= 1; self->chatwin->infobox.in_is_muted ^= 1;
@ -668,9 +668,9 @@ void cmd_mute(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
} }
pthread_mutex_unlock(&this_call->mutex); pthread_mutex_unlock(&this_call->mutex);
} }
return; return;
on_error: on_error:
print_err (self, error_str); print_err (self, error_str);
} }
@ -678,39 +678,39 @@ void cmd_mute(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
void cmd_sense(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_sense(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{ {
const char *error_str; const char *error_str;
if ( argc != 1 ) { if ( argc != 1 ) {
if ( argc < 1 ) error_str = "Must have value!"; if ( argc < 1 ) error_str = "Must have value!";
else error_str = "Only two arguments allowed!"; else error_str = "Only two arguments allowed!";
goto on_error; goto on_error;
} }
char *end; char *end;
float value = strtof(argv[1], &end); float value = strtof(argv[1], &end);
if ( *end ) { if ( *end ) {
error_str = "Invalid input"; error_str = "Invalid input";
goto on_error; goto on_error;
} }
/* Call must be active */ /* Call must be active */
if ( self->call_idx > -1) { if ( self->call_idx > -1) {
device_set_VAD_treshold(ASettins.calls[self->call_idx].in_idx, value); device_set_VAD_treshold(ASettins.calls[self->call_idx].in_idx, value);
self->chatwin->infobox.vad_lvl = value; self->chatwin->infobox.vad_lvl = value;
} }
return; return;
on_error: on_error:
print_err (self, error_str); print_err (self, error_str);
} }
void stop_current_call(ToxWindow* self) void stop_current_call(ToxWindow* self)
{ {
ToxAvCallState callstate; ToxAvCallState callstate;
if ( ASettins.av != NULL && self->call_idx != -1 && if ( ASettins.av != NULL && self->call_idx != -1 &&
( callstate = toxav_get_call_state(ASettins.av, self->call_idx) ) != av_CallNonExistent) { ( callstate = toxav_get_call_state(ASettins.av, self->call_idx) ) != av_CallNonExistent) {
switch (callstate) switch (callstate)
{ {

View File

@ -29,11 +29,13 @@
#include <time.h> #include <time.h>
#include <wchar.h> #include <wchar.h>
#include <assert.h> #include <assert.h>
#include <limits.h>
#include "toxic.h" #include "toxic.h"
#include "windows.h" #include "windows.h"
#include "execute.h" #include "execute.h"
#include "misc_tools.h" #include "misc_tools.h"
#include "file_transfers.h"
#include "friendlist.h" #include "friendlist.h"
#include "toxic_strings.h" #include "toxic_strings.h"
#include "log.h" #include "log.h"
@ -49,10 +51,7 @@
#include "audio_call.h" #include "audio_call.h"
#endif /* AUDIO */ #endif /* AUDIO */
extern char *DATA_FILE; extern char *DATA_FILE;
extern FileSender file_senders[MAX_FILES];
extern FriendsList Friends; extern FriendsList Friends;
extern struct Winthread Winthread; extern struct Winthread Winthread;
@ -105,25 +104,23 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
#endif /* AUDIO */ #endif /* AUDIO */
}; };
static void set_self_typingstatus(ToxWindow *self, Tox *m, uint8_t is_typing) static void set_self_typingstatus(ToxWindow *self, Tox *m, bool is_typing)
{ {
if (user_settings->show_typing_self == SHOW_TYPING_OFF) if (user_settings->show_typing_self == SHOW_TYPING_OFF)
return; return;
ChatContext *ctx = self->chatwin; ChatContext *ctx = self->chatwin;
tox_set_user_is_typing(m, self->num, is_typing); tox_self_set_typing(m, self->num, is_typing, NULL);
ctx->self_is_typing = is_typing; ctx->self_is_typing = is_typing;
} }
static void close_all_file_receivers(Tox *m, int friendnum);
void kill_chat_window(ToxWindow *self, Tox *m) void kill_chat_window(ToxWindow *self, Tox *m)
{ {
ChatContext *ctx = self->chatwin; ChatContext *ctx = self->chatwin;
StatusBar *statusbar = self->stb; StatusBar *statusbar = self->stb;
close_all_file_receivers(m, self->num); kill_all_file_transfers_friend(m, self->num);
log_disable(ctx->log); log_disable(ctx->log);
line_info_cleanup(ctx->hst); line_info_cleanup(ctx->hst);
cqueue_cleanup(ctx->cqueue); cqueue_cleanup(ctx->cqueue);
@ -145,19 +142,11 @@ void kill_chat_window(ToxWindow *self, Tox *m)
del_window(self); del_window(self);
} }
static void chat_onMessage(ToxWindow *self, Tox *m, int32_t num, const char *msg, uint16_t len) static void recv_message_helper(ToxWindow *self, Tox *m, uint32_t num, const char *msg, size_t len,
const char *nick, const char *timefrmt)
{ {
if (self->num != num)
return;
ChatContext *ctx = self->chatwin; ChatContext *ctx = self->chatwin;
char nick[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, nick, num);
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(self, timefrmt, nick, NULL, IN_MSG, 0, 0, "%s", msg); line_info_add(self, timefrmt, nick, NULL, IN_MSG, 0, 0, "%s", msg);
write_to_log(msg, nick, ctx->log, false); write_to_log(msg, nick, ctx->log, false);
@ -165,13 +154,44 @@ static void chat_onMessage(ToxWindow *self, Tox *m, int32_t num, const char *msg
box_notify2(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, self->active_box, "%s", msg); box_notify2(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, self->active_box, "%s", msg);
else else
box_notify(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, &self->active_box, nick, "%s", msg); box_notify(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, &self->active_box, nick, "%s", msg);
} }
static void chat_resume_file_transfers(Tox *m, int fnum); static void recv_action_helper(ToxWindow *self, Tox *m, uint32_t num, const char *action, size_t len,
static void chat_stop_file_senders(int fnum); const char *nick, const char *timefrmt)
{
ChatContext *ctx = self->chatwin;
static void chat_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_t status) line_info_add(self, timefrmt, nick, NULL, IN_ACTION, 0, 0, "%s", action);
write_to_log(action, nick, ctx->log, true);
if (self->active_box != -1)
box_notify2(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, self->active_box, "* %s %s", nick, action );
else
box_notify(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, &self->active_box, self->name, "* %s %s", nick, action );
}
static void chat_onMessage(ToxWindow *self, Tox *m, uint32_t num, TOX_MESSAGE_TYPE type, const char *msg, size_t len)
{
if (self->num != num)
return;
char nick[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, nick, num);
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
if (type == TOX_MESSAGE_TYPE_NORMAL)
return recv_message_helper(self, m, num, msg, len, nick, timefrmt);
if (type == TOX_MESSAGE_TYPE_ACTION)
return recv_action_helper(self, m, num, msg, len, nick, timefrmt);
}
static void chat_resume_file_transfers(Tox *m, uint32_t fnum);
static void chat_stop_file_senders(Tox *m, uint32_t friendnum);
static void chat_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, TOX_CONNECTION connection_status)
{ {
if (self->num != num) if (self->num != num)
return; return;
@ -186,23 +206,23 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_
char nick[TOX_MAX_NAME_LENGTH]; char nick[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, nick, num); get_nick_truncate(m, nick, num);
if (status == 1) { /* Friend goes online */ statusbar->connection = connection_status;
statusbar->is_online = true;
if (connection_status != TOX_CONNECTION_NONE) {
Friends.list[num].is_typing = user_settings->show_typing_other == SHOW_TYPING_ON Friends.list[num].is_typing = user_settings->show_typing_other == SHOW_TYPING_ON
? tox_get_is_typing(m, num) : 0; ? tox_friend_get_typing(m, num, NULL) : false;
chat_resume_file_transfers(m, num); chat_resume_file_transfers(m, num);
msg = "has come online"; msg = "has come online";
line_info_add(self, timefrmt, nick, NULL, CONNECTION, 0, GREEN, msg); line_info_add(self, timefrmt, nick, NULL, CONNECTION, 0, GREEN, msg);
write_to_log(msg, nick, ctx->log, true); write_to_log(msg, nick, ctx->log, true);
} else { /* Friend goes offline */ } else {
statusbar->is_online = false; Friends.list[num].is_typing = false;
Friends.list[num].is_typing = 0;
if (self->chatwin->self_is_typing) if (self->chatwin->self_is_typing)
set_self_typingstatus(self, m, 0); set_self_typingstatus(self, m, 0);
chat_stop_file_senders(num); chat_stop_file_senders(m, num);
msg = "has gone offline"; msg = "has gone offline";
line_info_add(self, timefrmt, nick, NULL, DISCONNECTION, 0, RED, msg); line_info_add(self, timefrmt, nick, NULL, DISCONNECTION, 0, RED, msg);
@ -210,7 +230,7 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_
} }
} }
static void chat_onTypingChange(ToxWindow *self, Tox *m, int32_t num, uint8_t is_typing) static void chat_onTypingChange(ToxWindow *self, Tox *m, uint32_t num, bool is_typing)
{ {
if (self->num != num) if (self->num != num)
return; return;
@ -218,29 +238,7 @@ static void chat_onTypingChange(ToxWindow *self, Tox *m, int32_t num, uint8_t is
Friends.list[num].is_typing = is_typing; Friends.list[num].is_typing = is_typing;
} }
static void chat_onAction(ToxWindow *self, Tox *m, int32_t num, const char *action, uint16_t len) static void chat_onNickChange(ToxWindow *self, Tox *m, uint32_t num, const char *nick, size_t length)
{
if (self->num != num)
return;
ChatContext *ctx = self->chatwin;
char nick[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, nick, num);
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(self, timefrmt, nick, NULL, IN_ACTION, 0, 0, "%s", action);
write_to_log(action, nick, ctx->log, true);
if (self->active_box != -1)
box_notify2(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, self->active_box, "* %s %s", nick, action );
else
box_notify(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, &self->active_box, self->name, "* %s %s", nick, action );
}
static void chat_onNickChange(ToxWindow *self, Tox *m, int32_t num, const char *nick, uint16_t len)
{ {
if (self->num != num) if (self->num != num)
return; return;
@ -248,13 +246,13 @@ static void chat_onNickChange(ToxWindow *self, Tox *m, int32_t num, const char *
StatusBar *statusbar = self->stb; StatusBar *statusbar = self->stb;
snprintf(statusbar->nick, sizeof(statusbar->nick), "%s", nick); snprintf(statusbar->nick, sizeof(statusbar->nick), "%s", nick);
len = strlen(statusbar->nick); length = strlen(statusbar->nick);
statusbar->nick_len = len; statusbar->nick_len = length;
set_window_title(self, statusbar->nick, len); set_window_title(self, statusbar->nick, length);
} }
static void chat_onStatusChange(ToxWindow *self, Tox *m, int32_t num, uint8_t status) static void chat_onStatusChange(ToxWindow *self, Tox *m, uint32_t num, TOX_USER_STATUS status)
{ {
if (self->num != num) if (self->num != num)
return; return;
@ -263,7 +261,7 @@ static void chat_onStatusChange(ToxWindow *self, Tox *m, int32_t num, uint8_t st
statusbar->status = status; statusbar->status = status;
} }
static void chat_onStatusMessageChange(ToxWindow *self, int32_t num, const char *status, uint16_t len) static void chat_onStatusMessageChange(ToxWindow *self, uint32_t num, const char *status, size_t length)
{ {
if (self->num != num) if (self->num != num)
return; return;
@ -274,83 +272,237 @@ static void chat_onStatusMessageChange(ToxWindow *self, int32_t num, const char
statusbar->statusmsg_len = strlen(statusbar->statusmsg); statusbar->statusmsg_len = strlen(statusbar->statusmsg);
} }
static void chat_onReadReceipt(ToxWindow *self, Tox *m, int32_t num, uint32_t receipt) static void chat_onReadReceipt(ToxWindow *self, Tox *m, uint32_t num, uint32_t receipt)
{ {
cqueue_remove(self, m, receipt); cqueue_remove(self, m, receipt);
} }
static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum, /* Stops active file senders for this friend. Call when a friend goes offline */
uint64_t filesize, const char *pathname, uint16_t path_len) static void chat_stop_file_senders(Tox *m, uint32_t friendnum)
{ {
if (self->num != num) // TODO: core purges file transfers when a friend goes offline. Ideally we want to repair/resume
kill_all_file_transfers_friend(m, friendnum);
}
/* Tries to resume broken file transfers. Call when a friend comes online */
static void chat_resume_file_transfers(Tox *m, uint32_t fnum)
{
// TODO
}
static void chat_onFileChunkRequest(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum, uint64_t position,
size_t length)
{
if (friendnum != self->num)
return; return;
/* holds the filename appended to the user specified path */ struct FileTransfer *ft = get_file_transfer_struct(friendnum, filenum);
char filename_path[MAX_STR_SIZE] = {0};
if (ft == NULL)
return;
if (ft->state != FILE_TRANSFER_STARTED)
return;
char msg[MAX_STR_SIZE];
if (length == 0) {
snprintf(msg, sizeof(msg), "File '%s' successfully sent.", ft->file_name);
print_progress_bar(self, ft->bps, 100.0, ft->line_id);
close_file_transfer(self, m, ft, -1, msg, transfer_completed);
return;
}
if (ft->file == NULL) {
snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Null file pointer.", ft->file_name);
close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error);
return;
}
if (ft->position != position) {
if (fseek(ft->file, position, SEEK_SET) == -1) {
snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Seek fail.", ft->file_name);
close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error);
return;
}
ft->position = position;
}
uint8_t send_data[length];
size_t send_length = fread(send_data, 1, sizeof(send_data), ft->file);
if (send_length != length) {
snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Read fail.", ft->file_name);
close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error);
return;
}
TOX_ERR_FILE_SEND_CHUNK err;
tox_file_send_chunk(m, friendnum, filenum, position, send_data, send_length, &err);
if (err != TOX_ERR_FILE_SEND_CHUNK_OK)
fprintf(stderr, "tox_file_send_chunk failed (error %d)\n", err);
ft->position += send_length;
ft->bps += send_length;
}
static void chat_onFileRecvChunk(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum, uint64_t position,
const char *data, size_t length)
{
if (friendnum != self->num)
return;
struct FileTransfer *ft = get_file_transfer_struct(friendnum, filenum);
if (ft == NULL)
return;
if (ft->state != FILE_TRANSFER_STARTED)
return;
char msg[MAX_STR_SIZE];
if (length == 0) {
snprintf(msg, sizeof(msg), "File '%s' successfully received.", ft->file_name);
print_progress_bar(self, ft->bps, 100.0, ft->line_id);
close_file_transfer(self, m, ft, -1, msg, transfer_completed);
return;
}
if (ft->file == NULL) {
snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Invalid file pointer.", ft->file_name);
close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error);
return;
}
if (fwrite(data, length, 1, ft->file) != 1) {
snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Write fail.", ft->file_name);
close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error);
return;
}
ft->bps += length;
ft->position += length;
}
static void chat_onFileControl(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum, TOX_FILE_CONTROL control)
{
if (self->num != friendnum)
return;
struct FileTransfer *ft = get_file_transfer_struct(friendnum, filenum);
if (ft == NULL)
return;
char msg[MAX_STR_SIZE];
switch (control) {
case TOX_FILE_CONTROL_RESUME:
/* transfer is accepted */
if (ft->state == FILE_TRANSFER_PENDING) {
ft->state = FILE_TRANSFER_STARTED;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer [%d] for '%s' accepted.",
ft->index, ft->file_name);
char progline[MAX_STR_SIZE];
prep_prog_line(progline);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", progline);
sound_notify(self, silent, NT_NOFOCUS | NT_BEEP | NT_WNDALERT_2, NULL);
ft->line_id = self->chatwin->hst->line_end->id + 2;
break;
}
/* transfer is resumed */
if (ft->state == FILE_TRANSFER_PAUSED) {
ft->state = FILE_TRANSFER_STARTED;
}
break;
case TOX_FILE_CONTROL_PAUSE:
break;
case TOX_FILE_CONTROL_CANCEL:
snprintf(msg, sizeof(msg), "File transfer for '%s' was aborted.", ft->file_name);
close_file_transfer(self, m, ft, -1, msg, notif_error);
break;
}
}
static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum, uint64_t file_size,
const char *filename, size_t name_length)
{
if (self->num != friendnum)
return;
struct FileTransfer *ft = get_new_file_receiver(friendnum);
if (!ft) {
tox_file_control(m, friendnum, filenum, TOX_FILE_CONTROL_CANCEL, NULL);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Too many concurrent file transfers.");
return;
}
/* holds the lone filename */
char filename_nopath[MAX_STR_SIZE];
get_file_name(filename_nopath, sizeof(filename_nopath), pathname);
char sizestr[32]; char sizestr[32];
bytes_convert_str(sizestr, sizeof(sizestr), filesize); bytes_convert_str(sizestr, sizeof(sizestr), file_size);
int len = strlen(filename_nopath); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer request for '%s' (%s)", filename, sizestr);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer request for '%s' (%s)",
filename_nopath, sizestr);
if (filenum >= MAX_FILES) { char file_path[MAX_STR_SIZE];
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Too many pending file requests; discarding."); size_t path_len = name_length;
/* use specified download path in config if possible */
if (!string_is_empty(user_settings->download_path)) {
snprintf(file_path, sizeof(file_path), "%s%s", user_settings->download_path, filename);
path_len += strlen(user_settings->download_path);
} else {
snprintf(file_path, sizeof(file_path), "%s", filename);
}
if (path_len >= sizeof(ft->file_path) || name_length >= sizeof(ft->file_name)) {
tox_file_control(m, friendnum, filenum, TOX_FILE_CONTROL_CANCEL, NULL);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer faield: File path too long.");
return; return;
} }
/* use specified path in config if possible */
if (user_settings->download_path[0]) {
snprintf(filename_path, sizeof(filename_path), "%s%s", user_settings->download_path, filename_nopath);
len += strlen(user_settings->download_path);
}
if (len >= sizeof(Friends.list[num].file_receiver[filenum].filename)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File name too long; discarding.");
return;
}
char filename[MAX_STR_SIZE];
if (filename_path[0])
strcpy(filename, filename_path);
else
strcpy(filename, filename_nopath);
/* Append a number to duplicate file names */ /* Append a number to duplicate file names */
FILE *filecheck = NULL; FILE *filecheck = NULL;
int count = 1; int count = 1;
while ((filecheck = fopen(filename, "r"))) { while ((filecheck = fopen(file_path, "r"))) {
fclose(filecheck); fclose(filecheck);
filename[len] = '\0'; file_path[path_len] = '\0';
char d[9]; char d[9];
sprintf(d, "(%d)", count++); sprintf(d, "(%d)", count);
int d_len = strlen(d); ++count;
size_t d_len = strlen(d);
if (len + d_len >= sizeof(filename)) { if (path_len + d_len >= sizeof(file_path)) {
len -= d_len; path_len -= d_len;
filename[len] = '\0'; file_path[path_len] = '\0';
} }
strcat(filename, d); strcat(file_path, d);
filename[len + d_len] = '\0'; file_path[path_len + d_len] = '\0';
if (count > 999) { if (count > 999) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error saving file to disk."); tox_file_control(m, friendnum, filenum, TOX_FILE_CONTROL_CANCEL, NULL);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: invalid file path.");
return; return;
} }
} }
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type '/savefile %d' to accept the file transfer.", filenum); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type '/savefile %d' to accept the file transfer.", ft->index);
Friends.list[num].file_receiver[filenum].pending = true; ft->state = FILE_TRANSFER_PENDING;
Friends.list[num].file_receiver[filenum].size = filesize; ft->direction = FILE_TRANSFER_RECV;
Friends.list[num].file_receiver[filenum].filenum = filenum; ft->file_size = file_size;
strcpy(Friends.list[num].file_receiver[filenum].filename, filename); ft->friendnum = friendnum;
ft->filenum = filenum;
snprintf(ft->file_path, sizeof(ft->file_path), "%s", file_path);
snprintf(ft->file_name, sizeof(ft->file_name), "%s", filename);
if (self->active_box != -1) if (self->active_box != -1)
box_notify2(self, transfer_pending, NT_WNDALERT_0 | NT_NOFOCUS, self->active_box, box_notify2(self, transfer_pending, NT_WNDALERT_0 | NT_NOFOCUS, self->active_box,
@ -360,208 +512,6 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
"Incoming file: %s", filename ); "Incoming file: %s", filename );
} }
/* Stops active file senders for this friend. Call when a friend goes offline */
static void chat_stop_file_senders(int fnum)
{
int i;
for (i = 0; i < MAX_FILES; ++i) {
if (file_senders[i].active && file_senders[i].friendnum == fnum)
file_senders[i].noconnection = true;
}
}
/* Tries to resume broken file transfers. Call when a friend comes online */
static void chat_resume_file_transfers(Tox *m, int fnum)
{
if (Friends.list[fnum].active_file_receivers == 0)
return;
int i;
for (i = 0; i < MAX_FILES; ++i) {
if (Friends.list[fnum].file_receiver[i].active) {
uint8_t bytes_recv[sizeof(uint64_t)];
memcpy(bytes_recv, &Friends.list[fnum].file_receiver[i].bytes_recv, sizeof(uint64_t));
net_to_host(bytes_recv, sizeof(uint64_t));
int filenum = Friends.list[fnum].file_receiver[i].filenum;
tox_file_send_control(m, fnum, 1, filenum, TOX_FILECONTROL_RESUME_BROKEN, bytes_recv, sizeof(uint64_t));
}
}
}
/* set CTRL to -1 if we don't want to send a control signal.
set msg to NULL if we don't want to display a message */
void chat_close_file_receiver(Tox *m, int filenum, int friendnum, int CTRL)
{
if (CTRL > 0)
tox_file_send_control(m, friendnum, 1, filenum, CTRL, 0, 0);
FILE *file = Friends.list[friendnum].file_receiver[filenum].file;
if (file != NULL)
fclose(file);
memset(&Friends.list[friendnum].file_receiver[filenum], 0, sizeof(struct FileReceiver));
--Friends.list[friendnum].active_file_receivers;
}
static void close_all_file_receivers(Tox *m, int friendnum)
{
int i;
for (i = 0; i < MAX_FILES; ++i) {
if (Friends.list[friendnum].file_receiver[i].active)
chat_close_file_receiver(m, i, friendnum, TOX_FILECONTROL_KILL);
}
}
static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t receive_send,
uint8_t filenum, uint8_t control_type, const char *data, uint16_t length)
{
if (self->num != num)
return;
const char *filename;
char msg[MAX_STR_SIZE] = {0};
int send_idx = 0; /* file sender index */
if (receive_send == 0) {
if (!Friends.list[num].file_receiver[filenum].active)
return;
filename = Friends.list[num].file_receiver[filenum].filename;
} else {
int i;
for (i = 0; i < MAX_FILES; ++i) {
send_idx = i;
if (file_senders[i].active && file_senders[i].filenum == filenum)
break;
}
if (!file_senders[send_idx].active)
return;
filename = file_senders[send_idx].filename;
}
switch (control_type) {
case TOX_FILECONTROL_ACCEPT:
if (receive_send != 1)
break;
/* transfer is accepted */
if (!file_senders[send_idx].started) {
file_senders[send_idx].started = true;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer [%d] for '%s' accepted.",
filenum, filename);
char progline[MAX_STR_SIZE];
prep_prog_line(progline);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", progline);
file_senders[send_idx].line_id = self->chatwin->hst->line_end->id + 2;
sound_notify(self, silent, NT_NOFOCUS | NT_BEEP | NT_WNDALERT_2, NULL);
} else { /* active transfer is unpaused by receiver */
file_senders[send_idx].paused = false;
file_senders[send_idx].timestamp = get_unix_time();
}
break;
case TOX_FILECONTROL_PAUSE:
if (receive_send == 1)
file_senders[send_idx].paused = true;
break;
case TOX_FILECONTROL_KILL:
snprintf(msg, sizeof(msg), "File transfer for '%s' failed.", filename);
if (self->active_box != -1)
box_notify2(self, error, NT_NOFOCUS | NT_WNDALERT_2,
self->active_box, "File transfer for '%s' failed!", filename );
else
box_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box,
self->name, "File transfer for '%s' failed!", filename );
if (receive_send == 0)
chat_close_file_receiver(m, filenum, num, -1);
else
close_file_sender(self, m, send_idx, NULL, -1, filenum, num);
break;
case TOX_FILECONTROL_FINISHED:
if (receive_send == 0) {
print_progress_bar(self, filenum, num, 100.0);
char filename_nopath[MAX_STR_SIZE];
get_file_name(filename_nopath, sizeof(filename_nopath), filename);
snprintf(msg, sizeof(msg), "File transfer for '%s' complete.", filename_nopath);
chat_close_file_receiver(m, filenum, num, TOX_FILECONTROL_FINISHED);
} else {
snprintf(msg, sizeof(msg), "File '%s' successfuly sent.", filename);
close_file_sender(self, m, send_idx, NULL, TOX_FILECONTROL_FINISHED, filenum, num);
}
if (self->active_box != -1)
box_notify2(self, transfer_completed, NT_NOFOCUS | NT_WNDALERT_2, self->active_box, "%s", msg);
else
box_notify(self, transfer_completed, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box,
self->name, "%s", msg);
break;
case TOX_FILECONTROL_RESUME_BROKEN:
if (receive_send == 0)
break;
FILE *fp = file_senders[send_idx].file;
if (fp == NULL)
break;
uint8_t tmp[sizeof(uint64_t)];
memcpy(tmp, &data, sizeof(uint64_t));
net_to_host(tmp, sizeof(uint64_t));
uint64_t datapos;
memcpy(&datapos, tmp, sizeof(uint64_t));
if (fseek(fp, datapos, SEEK_SET) == -1) {
snprintf(msg, sizeof(msg), "File transfer for '%s' failed to resume", filename);
close_file_sender(self, m, send_idx, NULL, TOX_FILECONTROL_FINISHED, filenum, num);
break;
}
tox_file_send_control(m, num, 0, filenum, TOX_FILECONTROL_ACCEPT, 0, 0);
file_senders[send_idx].noconnection = false;
break;
}
if (msg[0])
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", msg);
}
static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum, const char *data,
uint16_t length)
{
if (self->num != num)
return;
FILE *fp = Friends.list[num].file_receiver[filenum].file;
if (fp) {
if (fwrite(data, length, 1, fp) != 1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Error writing to file.");
chat_close_file_receiver(m, filenum, num, TOX_FILECONTROL_KILL);
}
}
Friends.list[num].file_receiver[filenum].bps += length;
Friends.list[num].file_receiver[filenum].bytes_recv += length;
}
static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, const char *invite_data, static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, const char *invite_data,
uint16_t length) uint16_t length)
{ {
@ -838,7 +788,9 @@ static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
return; return;
char selfname[TOX_MAX_NAME_LENGTH]; char selfname[TOX_MAX_NAME_LENGTH];
uint16_t len = tox_get_self_name(m, (uint8_t *) selfname); tox_self_get_name(m, (uint8_t *) selfname);
size_t len = tox_self_get_name_size(m);
selfname[len] = '\0'; selfname[len] = '\0';
char timefrmt[TIME_STR_SIZE]; char timefrmt[TIME_STR_SIZE];
@ -869,7 +821,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
if (ltr) { /* char is printable */ if (ltr) { /* char is printable */
input_new_char(self, key, x, y, x2, y2); input_new_char(self, key, x, y, x2, y2);
if (ctx->line[0] != '/' && !ctx->self_is_typing && statusbar->is_online) if (ctx->line[0] != '/' && !ctx->self_is_typing && statusbar->connection != TOX_CONNECTION_NONE)
set_self_typingstatus(self, m, 1); set_self_typingstatus(self, m, 1);
return; return;
@ -905,7 +857,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
ctx->start = wlen < x2 ? 0 : wlen - x2 + 1; ctx->start = wlen < x2 ? 0 : wlen - x2 + 1;
} }
} else { } else {
sound_notify(self, error, 0, NULL); sound_notify(self, notif_error, 0, NULL);
} }
} else if (key == '\n') { } else if (key == '\n') {
@ -930,7 +882,9 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
} }
} else if (!string_is_empty(line)) { } else if (!string_is_empty(line)) {
char selfname[TOX_MAX_NAME_LENGTH]; char selfname[TOX_MAX_NAME_LENGTH];
uint16_t len = tox_get_self_name(m, (uint8_t *) selfname); tox_self_get_name(m, (uint8_t *) selfname);
size_t len = tox_self_get_name_size(m);
selfname[len] = '\0'; selfname[len] = '\0';
char timefrmt[TIME_STR_SIZE]; char timefrmt[TIME_STR_SIZE];
@ -970,26 +924,20 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
wmove(statusbar->topline, 0, 0); wmove(statusbar->topline, 0, 0);
/* Draw name, status and note in statusbar */ /* Draw name, status and note in statusbar */
if (statusbar->is_online) { if (statusbar->connection != TOX_CONNECTION_NONE) {
int colour = WHITE; int colour = MAGENTA;
uint8_t status = statusbar->status; TOX_USER_STATUS status = statusbar->status;
switch (status) { switch (status) {
case TOX_USERSTATUS_NONE: case TOX_USER_STATUS_NONE:
colour = GREEN; colour = GREEN;
break; break;
case TOX_USER_STATUS_AWAY:
case TOX_USERSTATUS_AWAY:
colour = YELLOW; colour = YELLOW;
break; break;
case TOX_USER_STATUS_BUSY:
case TOX_USERSTATUS_BUSY:
colour = RED; colour = RED;
break; break;
case TOX_USERSTATUS_INVALID:
colour = MAGENTA;
break;
} }
wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD); wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
@ -1014,10 +962,11 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
/* Reset statusbar->statusmsg on window resize */ /* Reset statusbar->statusmsg on window resize */
if (x2 != self->x) { if (x2 != self->x) {
char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {'\0'}; char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH] = {'\0'};
pthread_mutex_lock(&Winthread.lock); pthread_mutex_lock(&Winthread.lock);
int s_len = tox_get_status_message(m, self->num, (uint8_t *) statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH); tox_friend_get_status_message(m, self->num, (uint8_t *) statusmsg, NULL);
size_t s_len = tox_friend_get_status_message_size(m, self->num, NULL);
pthread_mutex_unlock(&Winthread.lock); pthread_mutex_unlock(&Winthread.lock);
filter_str(statusmsg, s_len); filter_str(statusmsg, s_len);
@ -1028,7 +977,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
self->x = x2; self->x = x2;
/* Truncate note if it doesn't fit in statusbar */ /* Truncate note if it doesn't fit in statusbar */
uint16_t maxlen = x2 - getcurx(statusbar->topline) - (KEY_IDENT_DIGITS * 2) - 6; size_t maxlen = x2 - getcurx(statusbar->topline) - (KEY_IDENT_DIGITS * 2) - 6;
if (statusbar->statusmsg_len > maxlen) { if (statusbar->statusmsg_len > maxlen) {
statusbar->statusmsg[maxlen - 3] = '\0'; statusbar->statusmsg[maxlen - 3] = '\0';
@ -1043,7 +992,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
wmove(statusbar->topline, 0, x2 - (KEY_IDENT_DIGITS * 2) - 3); wmove(statusbar->topline, 0, x2 - (KEY_IDENT_DIGITS * 2) - 3);
wprintw(statusbar->topline, "{"); wprintw(statusbar->topline, "{");
int i; size_t i;
for (i = 0; i < KEY_IDENT_DIGITS; ++i) for (i = 0; i < KEY_IDENT_DIGITS; ++i)
wprintw(statusbar->topline, "%02X", Friends.list[self->num].pub_key[i] & 0xff); wprintw(statusbar->topline, "%02X", Friends.list[self->num].pub_key[i] & 0xff);
@ -1069,6 +1018,10 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
if (self->help->active) if (self->help->active)
help_onDraw(self); help_onDraw(self);
pthread_mutex_lock(&Winthread.lock);
refresh_file_transfer_progress(self, m, self->num);
pthread_mutex_unlock(&Winthread.lock);
} }
static void chat_onInit(ToxWindow *self, Tox *m) static void chat_onInit(ToxWindow *self, Tox *m)
@ -1081,11 +1034,13 @@ static void chat_onInit(ToxWindow *self, Tox *m)
/* Init statusbar info */ /* Init statusbar info */
StatusBar *statusbar = self->stb; StatusBar *statusbar = self->stb;
statusbar->status = tox_get_user_status(m, self->num); statusbar->status = tox_friend_get_status(m, self->num, NULL);
statusbar->is_online = tox_get_friend_connection_status(m, self->num) == 1; statusbar->connection = tox_friend_get_connection_status(m, self->num, NULL);
char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {'\0'}; char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH];
uint16_t s_len = tox_get_status_message(m, self->num, (uint8_t *) statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH); tox_friend_get_status_message(m, self->num, (uint8_t *) statusmsg, NULL);
size_t s_len = tox_friend_get_status_message_size(m, self->num, NULL);
statusmsg[s_len] = '\0'; statusmsg[s_len] = '\0';
filter_str(statusmsg, s_len); filter_str(statusmsg, s_len);
@ -1093,7 +1048,7 @@ static void chat_onInit(ToxWindow *self, Tox *m)
statusbar->statusmsg_len = strlen(statusbar->statusmsg); statusbar->statusmsg_len = strlen(statusbar->statusmsg);
char nick[TOX_MAX_NAME_LENGTH + 1]; char nick[TOX_MAX_NAME_LENGTH + 1];
int n_len = get_nick_truncate(m, nick, self->num); size_t n_len = get_nick_truncate(m, nick, self->num);
snprintf(statusbar->nick, sizeof(statusbar->nick), "%s", nick); snprintf(statusbar->nick, sizeof(statusbar->nick), "%s", nick);
statusbar->nick_len = n_len; statusbar->nick_len = n_len;
@ -1113,8 +1068,8 @@ static void chat_onInit(ToxWindow *self, Tox *m)
line_info_init(ctx->hst); line_info_init(ctx->hst);
char myid[TOX_FRIEND_ADDRESS_SIZE]; char myid[TOX_ADDRESS_SIZE];
tox_get_address(m, (uint8_t *) myid); tox_self_get_address(m, (uint8_t *) myid);
log_enable(nick, myid, Friends.list[self->num].pub_key, ctx->log, LOG_CHAT); log_enable(nick, myid, Friends.list[self->num].pub_key, ctx->log, LOG_CHAT);
load_chat_history(self, ctx->log); load_chat_history(self, ctx->log);
@ -1128,7 +1083,7 @@ static void chat_onInit(ToxWindow *self, Tox *m)
wmove(self->window, y2 - CURS_Y_OFFSET, 0); wmove(self->window, y2 - CURS_Y_OFFSET, 0);
} }
ToxWindow new_chat(Tox *m, int32_t friendnum) ToxWindow new_chat(Tox *m, uint32_t friendnum)
{ {
ToxWindow ret; ToxWindow ret;
memset(&ret, 0, sizeof(ret)); memset(&ret, 0, sizeof(ret));
@ -1145,10 +1100,10 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
ret.onNickChange = &chat_onNickChange; ret.onNickChange = &chat_onNickChange;
ret.onStatusChange = &chat_onStatusChange; ret.onStatusChange = &chat_onStatusChange;
ret.onStatusMessageChange = &chat_onStatusMessageChange; ret.onStatusMessageChange = &chat_onStatusMessageChange;
ret.onAction = &chat_onAction; ret.onFileChunkRequest = &chat_onFileChunkRequest;
ret.onFileSendRequest = &chat_onFileSendRequest; ret.onFileRecvChunk = &chat_onFileRecvChunk;
ret.onFileControl = &chat_onFileControl; ret.onFileControl = &chat_onFileControl;
ret.onFileData = &chat_onFileData; ret.onFileRecv = &chat_onFileRecv;
ret.onReadReceipt = &chat_onReadReceipt; ret.onReadReceipt = &chat_onReadReceipt;
ret.onGroupInvite = &chat_onGroupInvite; ret.onGroupInvite = &chat_onGroupInvite;
@ -1173,7 +1128,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
ret.active_box = -1; ret.active_box = -1;
char nick[TOX_MAX_NAME_LENGTH]; char nick[TOX_MAX_NAME_LENGTH];
int n_len = get_nick_truncate(m, nick, friendnum); size_t n_len = get_nick_truncate(m, nick, friendnum);
set_window_title(&ret, nick, n_len); set_window_title(&ret, nick, n_len);
ChatContext *chatwin = calloc(1, sizeof(ChatContext)); ChatContext *chatwin = calloc(1, sizeof(ChatContext));

View File

@ -31,15 +31,11 @@
#include "line_info.h" #include "line_info.h"
#include "groupchat.h" #include "groupchat.h"
#include "chat.h" #include "chat.h"
#include "file_senders.h" #include "file_transfers.h"
extern ToxWindow *prompt; extern ToxWindow *prompt;
extern FriendsList Friends; extern FriendsList Friends;
extern FileSender file_senders[MAX_FILES];
extern uint8_t max_file_senders_index;
extern uint8_t num_active_file_senders;
void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{ {
if (argc < 2) { if (argc < 2) {
@ -47,52 +43,39 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
return; return;
} }
char msg[MAX_STR_SIZE];
const char *inoutstr = argv[1]; const char *inoutstr = argv[1];
int filenum = atoi(argv[2]); int idx = atoi(argv[2]);
if (filenum >= MAX_FILES || filenum < 0) { if (idx >= MAX_FILES || idx < 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID."); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID.");
return; return;
} }
if (strcasecmp(inoutstr, "in") == 0) { /* cancel an incoming file transfer */ struct FileTransfer *ft = NULL;
if (!Friends.list[self->num].file_receiver[filenum].active) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID.");
return;
}
const char *filepath = Friends.list[self->num].file_receiver[filenum].filename; /* cancel an incoming file transfer */
char name[MAX_STR_SIZE]; if (strcasecmp(inoutstr, "in") == 0) {
get_file_name(name, sizeof(name), filepath); ft = get_file_transfer_struct_index(self->num, idx, FILE_TRANSFER_RECV);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer for '%s' canceled.", name); } else if (strcasecmp(inoutstr, "out") == 0) {
chat_close_file_receiver(m, filenum, self->num, TOX_FILECONTROL_KILL); ft = get_file_transfer_struct_index(self->num, idx, FILE_TRANSFER_SEND);
return;
} else if (strcasecmp(inoutstr, "out") == 0) { /* cancel an outgoing file transfer */
int i;
bool match = false;
for (i = 0; i < MAX_FILES; ++i) {
if (file_senders[i].active && file_senders[i].filenum == filenum) {
match = true;
break;
}
}
if (!match) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID.");
return;
}
const char *filename = file_senders[i].filename;
char msg[MAX_STR_SIZE];
snprintf(msg, sizeof(msg), "File transfer for '%s' canceled.", filename);
close_file_sender(self, m, i, msg, TOX_FILECONTROL_KILL, filenum, self->num);
return;
} else { } else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type must be 'in' or 'out'."); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type must be 'in' or 'out'.");
return; return;
} }
if (!ft) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID.");
return;
}
if (ft->state == FILE_TRANSFER_INACTIVE) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID.");
return;
}
snprintf(msg, sizeof(msg), "File transfer for '%s' aborted.", ft->file_name);
close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, silent);
} }
void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
@ -124,50 +107,76 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
return; return;
} }
uint8_t filenum = atoi(argv[1]); int idx = atoi(argv[1]);
if ((filenum == 0 && strcmp(argv[1], "0")) || filenum >= MAX_FILES) { if ((idx == 0 && strcmp(argv[1], "0")) || idx >= MAX_FILES) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending file transfers with that ID."); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending file transfers with that ID.");
return; return;
} }
if (!Friends.list[self->num].file_receiver[filenum].pending) { struct FileTransfer *ft = get_file_transfer_struct_index(self->num, idx, FILE_TRANSFER_RECV);
if (!ft) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending file transfers with that ID."); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending file transfers with that ID.");
return; return;
} }
const char *filename = Friends.list[self->num].file_receiver[filenum].filename; if (ft->state != FILE_TRANSFER_PENDING) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending file transfers with that ID.");
if (tox_file_send_control(m, self->num, 1, filenum, TOX_FILECONTROL_ACCEPT, 0, 0) == 0) { return;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Saving file [%d] as: '%s'", filenum, filename);
/* prep progress bar line */
char progline[MAX_STR_SIZE];
prep_prog_line(progline);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", progline);
Friends.list[self->num].file_receiver[filenum].line_id = self->chatwin->hst->line_end->id + 2;
if ((Friends.list[self->num].file_receiver[filenum].file = fopen(filename, "a")) == NULL) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "* Error writing to file.");
tox_file_send_control(m, self->num, 1, filenum, TOX_FILECONTROL_KILL, 0, 0);
} else {
Friends.list[self->num].file_receiver[filenum].active = true;
++Friends.list[self->num].active_file_receivers;
}
} else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed.");
} }
Friends.list[self->num].file_receiver[filenum].pending = false; if ((ft->file = fopen(ft->file_path, "a")) == NULL) {
const char *msg = "File transfer failed: Invalid file path.";
close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error);
return;
}
TOX_ERR_FILE_CONTROL err;
tox_file_control(m, self->num, ft->filenum, TOX_FILE_CONTROL_RESUME, &err);
if (err != TOX_ERR_FILE_CONTROL_OK)
goto on_recv_error;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Saving file [%d] as: '%s'", idx, ft->file_path);
/* prep progress bar line */
char progline[MAX_STR_SIZE];
prep_prog_line(progline);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", progline);
ft->line_id = self->chatwin->hst->line_end->id + 2;
ft->state = FILE_TRANSFER_STARTED;
return;
on_recv_error:
switch (err) {
case TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Friend not found.");
return;
case TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Friend is not online.");
return;
case TOX_ERR_FILE_CONTROL_NOT_FOUND:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Invalid filenumber.");
return;
case TOX_ERR_FILE_CONTROL_SENDQ:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Connection error.");
return;
default:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed (error %d)\n", err);
return;
}
} }
void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{ {
if (max_file_senders_index >= (MAX_FILES - 1)) { const char *errmsg = NULL;
const char *errmsg = "Please wait for some of your outgoing file transfers to complete.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
return;
}
if (argc < 1) { if (argc < 1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File path required."); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File path required.");
@ -199,51 +208,67 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
off_t filesize = file_size(path); off_t filesize = file_size(path);
if (filesize == -1) { if (filesize == 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File corrupt."); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file.");
fclose(file_to_send); fclose(file_to_send);
return; return;
} }
char filename[MAX_STR_SIZE] = {0}; char file_name[TOX_MAX_FILENAME_LENGTH];
get_file_name(filename, sizeof(filename), path); size_t namelen = get_file_name(file_name, sizeof(file_name), path);
int namelen = strlen(filename);
int filenum = tox_new_file_sender(m, self->num, filesize, (const uint8_t *) filename, namelen);
if (filenum == -1) { TOX_ERR_FILE_SEND err;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error sending file."); uint32_t filenum = tox_file_send(m, self->num, TOX_FILE_KIND_DATA, (uint64_t) filesize, NULL,
fclose(file_to_send); (uint8_t *) file_name, namelen, &err);
return;
if (err != TOX_ERR_FILE_SEND_OK)
goto on_send_error;
struct FileTransfer *ft = get_new_file_sender(self->num);
if (!ft) {
err = TOX_ERR_FILE_SEND_TOO_MANY;
goto on_send_error;
} }
int i; memcpy(ft->file_name, file_name, namelen + 1);
ft->state = FILE_TRANSFER_PENDING;
ft->file = file_to_send;
ft->file_size = filesize;
ft->filenum = filenum;
ft->friendnum = self->num;
ft->direction = FILE_TRANSFER_SEND;
for (i = 0; i < MAX_FILES; ++i) { char sizestr[32];
if (!file_senders[i].active) { bytes_convert_str(sizestr, sizeof(sizestr), filesize);
memcpy(file_senders[i].filename, filename, namelen + 1); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Sending file [%d]: '%s' (%s)", filenum, file_name, sizestr);
file_senders[i].active = true;
file_senders[i].started = false;
file_senders[i].toxwin = self;
file_senders[i].file = file_to_send;
file_senders[i].filenum = filenum;
file_senders[i].friendnum = self->num;
file_senders[i].timestamp = get_unix_time();
file_senders[i].size = filesize;
file_senders[i].piecelen = fread(file_senders[i].nextpiece, 1,
tox_file_data_size(m, self->num), file_to_send);
char sizestr[32]; return;
bytes_convert_str(sizestr, sizeof(sizestr), filesize);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,
"Sending file [%d]: '%s' (%s)", filenum, filename, sizestr);
++num_active_file_senders; on_send_error:
switch (err) {
case TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND:
errmsg = "File transfer failed: Invalid friend.";
break;
if (i == max_file_senders_index) case TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED:
++max_file_senders_index; errmsg = "File transfer failed: Friend is offline.";
break;
reset_file_sender_queue(); case TOX_ERR_FILE_SEND_NAME_TOO_LONG:
return; errmsg = "File transfer failed: Filename is too long.";
} break;
case TOX_ERR_FILE_SEND_TOO_MANY:
errmsg = "File transfer failed: Too many concurrent file transfers.";
break;
default:
errmsg = "File transfer failed.";
break;
} }
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", errmsg);
tox_file_control(m, self->num, filenum, TOX_FILE_CONTROL_CANCEL, NULL);
fclose(file_to_send);
} }

View File

@ -75,7 +75,7 @@ static struct dns3_server_backup {
static struct thread_data { static struct thread_data {
ToxWindow *self; ToxWindow *self;
char id_bin[TOX_FRIEND_ADDRESS_SIZE]; char id_bin[TOX_ADDRESS_SIZE];
char addr[MAX_STR_SIZE]; char addr[MAX_STR_SIZE];
char msg[MAX_STR_SIZE]; char msg[MAX_STR_SIZE];
uint8_t busy; uint8_t busy;
@ -168,39 +168,39 @@ static int parse_dns_response(ToxWindow *self, u_char *answer, int ans_len, char
uint8_t *ans_pt = answer + sizeof(HEADER); uint8_t *ans_pt = answer + sizeof(HEADER);
uint8_t *ans_end = answer + ans_len; uint8_t *ans_end = answer + ans_len;
char exp_ans[PACKETSZ]; char exp_ans[PACKETSZ];
int len = dn_expand(answer, ans_end, ans_pt, exp_ans, sizeof(exp_ans)); int len = dn_expand(answer, ans_end, ans_pt, exp_ans, sizeof(exp_ans));
if (len == -1) if (len == -1)
return dns_error(self, "dn_expand failed."); return dns_error(self, "dn_expand failed.");
ans_pt += len; ans_pt += len;
if (ans_pt > ans_end - 4) if (ans_pt > ans_end - 4)
return dns_error(self, "DNS reply was too short."); return dns_error(self, "DNS reply was too short.");
int type; int type;
GETSHORT(type, ans_pt); GETSHORT(type, ans_pt);
if (type != T_TXT) if (type != T_TXT)
return dns_error(self, "Broken DNS reply."); return dns_error(self, "Broken DNS reply.");
ans_pt += INT16SZ; /* class */ ans_pt += INT16SZ; /* class */
uint32_t size = 0; uint32_t size = 0;
/* recurse through CNAME rr's */ /* recurse through CNAME rr's */
do { do {
ans_pt += size; ans_pt += size;
len = dn_expand(answer, ans_end, ans_pt, exp_ans, sizeof(exp_ans)); len = dn_expand(answer, ans_end, ans_pt, exp_ans, sizeof(exp_ans));
if (len == -1) if (len == -1)
return dns_error(self, "Second dn_expand failed."); return dns_error(self, "Second dn_expand failed.");
ans_pt += len; ans_pt += len;
if (ans_pt > ans_end - 10) if (ans_pt > ans_end - 10)
return dns_error(self, "DNS reply was too short."); return dns_error(self, "DNS reply was too short.");
GETSHORT(type, ans_pt); GETSHORT(type, ans_pt);
ans_pt += INT16SZ; ans_pt += INT16SZ;
@ -208,12 +208,12 @@ static int parse_dns_response(ToxWindow *self, u_char *answer, int ans_len, char
GETSHORT(size, ans_pt); GETSHORT(size, ans_pt);
if (ans_pt + size < answer || ans_pt + size > ans_end) if (ans_pt + size < answer || ans_pt + size > ans_end)
return dns_error(self, "RR overflow."); return dns_error(self, "RR overflow.");
} while (type == T_CNAME); } while (type == T_CNAME);
if (type != T_TXT) if (type != T_TXT)
return dns_error(self, "DNS response failed."); return dns_error(self, "DNS response failed.");
uint32_t txt_len = *ans_pt; uint32_t txt_len = *ans_pt;
@ -230,7 +230,7 @@ static int parse_dns_response(ToxWindow *self, u_char *answer, int ans_len, char
return txt_len; return txt_len;
} }
/* Takes address addr in the form "username@domain", puts the username in namebuf, /* Takes address addr in the form "username@domain", puts the username in namebuf,
and the domain in dombuf. and the domain in dombuf.
return length of username on success, -1 on failure */ return length of username on success, -1 on failure */
@ -322,7 +322,7 @@ void *dns3_lookup_thread(void *data)
char string[MAX_DNS_REQST_SIZE + 1]; char string[MAX_DNS_REQST_SIZE + 1];
uint32_t request_id; uint32_t request_id;
int str_len = tox_generate_dns3_string(dns_obj, (uint8_t *) string, sizeof(string), &request_id, int str_len = tox_generate_dns3_string(dns_obj, (uint8_t *) string, sizeof(string), &request_id,
(uint8_t *) name, namelen); (uint8_t *) name, namelen);
if (str_len == -1) { if (str_len == -1) {
@ -361,7 +361,7 @@ void *dns3_lookup_thread(void *data)
memcpy(encrypted_id, ans_id + prfx_len, ans_len - prfx_len); memcpy(encrypted_id, ans_id + prfx_len, ans_len - prfx_len);
if (tox_decrypt_dns3_TXT(dns_obj, (uint8_t *) t_data.id_bin, (uint8_t *) encrypted_id, if (tox_decrypt_dns3_TXT(dns_obj, (uint8_t *) t_data.id_bin, (uint8_t *) encrypted_id,
strlen(encrypted_id), request_id) == -1) { strlen(encrypted_id), request_id) == -1) {
dns_error(self, "Core failed to decrypt DNS response."); dns_error(self, "Core failed to decrypt DNS response.");
killdns_thread(dns_obj); killdns_thread(dns_obj);
@ -378,7 +378,7 @@ void *dns3_lookup_thread(void *data)
/* creates new thread for dns3 lookup. Only allows one lookup at a time. */ /* creates new thread for dns3 lookup. Only allows one lookup at a time. */
void dns3_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *msg) void dns3_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *msg)
{ {
if (arg_opts.proxy_type != TOX_PROXY_NONE && arg_opts.force_tcp) { if (arg_opts.proxy_type != TOX_PROXY_TYPE_NONE && arg_opts.force_tcp) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "DNS lookups are disabled."); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "DNS lookups are disabled.");
return; return;
} }

View File

@ -1,293 +0,0 @@
/* file_senders.c
*
*
* Copyright (C) 2014 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 <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include "toxic.h"
#include "windows.h"
#include "friendlist.h"
#include "file_senders.h"
#include "line_info.h"
#include "misc_tools.h"
#include "notify.h"
FileSender file_senders[MAX_FILES];
uint8_t max_file_senders_index;
uint8_t num_active_file_senders;
extern FriendsList Friends;
#define NUM_PROG_MARKS 50 /* number of "#"'s in file transfer progress bar. Keep well below MAX_STR_SIZE */
/* creates initial progress line that will be updated during file transfer.
Assumes progline is of size MAX_STR_SIZE */
void prep_prog_line(char *progline)
{
strcpy(progline, "0.0 B/s [");
int i;
for (i = 0; i < NUM_PROG_MARKS; ++i)
strcat(progline, "-");
strcat(progline, "] 0%");
}
/* prints a progress bar for file transfers.
if friendnum is -1 we're sending the file, otherwise we're receiving. */
void print_progress_bar(ToxWindow *self, int idx, int friendnum, double pct_done)
{
double bps;
uint32_t line_id;
if (friendnum < 0) {
bps = file_senders[idx].bps;
line_id = file_senders[idx].line_id;
} else {
bps = Friends.list[friendnum].file_receiver[idx].bps;
line_id = Friends.list[friendnum].file_receiver[idx].line_id;
}
char msg[MAX_STR_SIZE];
bytes_convert_str(msg, sizeof(msg), bps);
strcat(msg, "/s [");
int n = pct_done / (100 / NUM_PROG_MARKS);
int i, j;
for (i = 0; i < n; ++i)
strcat(msg, "#");
for (j = i; j < NUM_PROG_MARKS; ++j)
strcat(msg, "-");
strcat(msg, "] ");
char pctstr[16];
const char *frmt = pct_done == 100 ? "%.f%%" : "%.1f%%";
snprintf(pctstr, sizeof(pctstr), frmt, pct_done);
strcat(msg, pctstr);
line_info_set(self, line_id, msg);
}
/* refreshes active file receiver status bars */
static void refresh_recv_prog(Tox *m)
{
int i;
uint64_t curtime = get_unix_time();
for (i = 2; i < MAX_WINDOWS_NUM; ++i) {
ToxWindow *toxwin = get_window_ptr(i);
if (toxwin == NULL || !toxwin->is_chat)
continue;
int fnum = toxwin->num;
int j;
for (j = 0; j < MAX_FILES; ++j) {
if (!Friends.list[fnum].file_receiver[j].active)
continue;
int filenum = Friends.list[fnum].file_receiver[j].filenum;
double remain = (double) tox_file_data_remaining(m, fnum, filenum, 1);
/* must be called once per second */
if (timed_out(Friends.list[fnum].file_receiver[filenum].last_progress, curtime, 1)) {
Friends.list[fnum].file_receiver[filenum].last_progress = curtime;
uint64_t size = Friends.list[fnum].file_receiver[filenum].size;
double pct_done = remain > 0 ? (1 - (remain / size)) * 100 : 100;
print_progress_bar(toxwin, filenum, fnum, pct_done);
Friends.list[fnum].file_receiver[filenum].bps = 0;
}
}
}
}
/* refreshes active file sender status bars */
static void refresh_sender_prog(Tox *m)
{
int i;
uint64_t curtime = get_unix_time();
for (i = 0; i < max_file_senders_index; ++i) {
if (!file_senders[i].active || file_senders[i].finished)
continue;
int filenum = file_senders[i].filenum;
int32_t friendnum = file_senders[i].friendnum;
double remain = (double) tox_file_data_remaining(m, friendnum, filenum, 0);
/* must be called once per second */
if (timed_out(file_senders[i].last_progress, curtime, 1)) {
file_senders[i].last_progress = curtime;
double pct_done = remain > 0 ? (1 - (remain / file_senders[i].size)) * 100 : 100;
print_progress_bar(file_senders[i].toxwin, i, -1, pct_done);
file_senders[i].bps = 0;
}
}
}
static void set_max_file_senders_index(void)
{
int j;
for (j = max_file_senders_index; j > 0; --j) {
if (file_senders[j - 1].active)
break;
}
max_file_senders_index = j;
}
/* called whenever a file sender is opened or closed */
void reset_file_sender_queue(void)
{
int i;
int pos = 0;
for (i = 0; i < max_file_senders_index; ++i) {
if (file_senders[i].active)
file_senders[i].queue_pos = pos++;
}
}
/* set CTRL to -1 if we don't want to send a control signal.
set msg to NULL if we don't want to display a message */
void close_file_sender(ToxWindow *self, Tox *m, int i, const char *msg, int CTRL, int filenum, int32_t friendnum)
{
if (msg != NULL)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", msg);
if (CTRL > 0)
tox_file_send_control(m, friendnum, 0, filenum, CTRL, 0, 0);
fclose(file_senders[i].file);
memset(&file_senders[i], 0, sizeof(FileSender));
set_max_file_senders_index();
reset_file_sender_queue();
--num_active_file_senders;
}
void close_all_file_senders(Tox *m)
{
int i;
for (i = 0; i < max_file_senders_index; ++i) {
if (file_senders[i].active) {
fclose(file_senders[i].file);
tox_file_send_control(m, file_senders[i].friendnum, 0, file_senders[i].filenum,
TOX_FILECONTROL_KILL, 0, 0);
memset(&file_senders[i], 0, sizeof(FileSender));
}
set_max_file_senders_index();
}
}
static void send_file_data(ToxWindow *self, Tox *m, int i, int32_t friendnum, int filenum, const char *filename)
{
FILE *fp = file_senders[i].file;
while (true) {
if (tox_file_send_data(m, friendnum, filenum, (uint8_t *) file_senders[i].nextpiece,
file_senders[i].piecelen) == -1)
return;
file_senders[i].timestamp = get_unix_time();
file_senders[i].bps += file_senders[i].piecelen;
file_senders[i].piecelen = fread(file_senders[i].nextpiece, 1,
tox_file_data_size(m, friendnum), fp);
/* note: file sender is closed in chat_onFileControl callback after receiving reply */
if (file_senders[i].piecelen == 0) {
if (feof(fp) != 0) { /* make sure we're really at eof */
print_progress_bar(self, i, -1, 100.0);
tox_file_send_control(m, friendnum, 0, filenum, TOX_FILECONTROL_FINISHED, 0, 0);
file_senders[i].finished = true;
} else {
char msg[MAX_STR_SIZE];
snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Read error.", file_senders[i].filename);
close_file_sender(self, m, i, msg, TOX_FILECONTROL_KILL, filenum, friendnum);
sound_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, NULL);
if (self->active_box != -1)
box_notify2(self, error, NT_NOFOCUS | NT_WNDALERT_2, self->active_box, "%s", msg);
else
box_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, self->name, "%s", msg);
}
return;
}
}
}
void do_file_senders(Tox *m)
{
int i;
for (i = 0; i < max_file_senders_index; ++i) {
if (!file_senders[i].active)
continue;
if (file_senders[i].queue_pos > 0) {
--file_senders[i].queue_pos;
continue;
}
ToxWindow *self = file_senders[i].toxwin;
char *filename = file_senders[i].filename;
int filenum = file_senders[i].filenum;
int32_t friendnum = file_senders[i].friendnum;
/* kill file transfer if chatwindow is closed */
if (self->chatwin == NULL) {
close_file_sender(self, m, i, NULL, TOX_FILECONTROL_KILL, filenum, friendnum);
continue;
}
/* If file transfer has timed out kill transfer and send kill control */
if (timed_out(file_senders[i].timestamp, get_unix_time(), TIMEOUT_FILESENDER)
&& (!file_senders[i].paused || (file_senders[i].paused && file_senders[i].noconnection))) {
char msg[MAX_STR_SIZE];
snprintf(msg, sizeof(msg), "File transfer for '%s' timed out.", filename);
close_file_sender(self, m, i, msg, TOX_FILECONTROL_KILL, filenum, friendnum);
if (self->active_box != -1)
box_notify2(self, error, NT_NOFOCUS | NT_WNDALERT_2, self->active_box, "%s", msg);
else
box_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, self->name, "%s", msg);
continue;
}
if ( !(file_senders[i].paused | file_senders[i].noconnection | file_senders[i].finished) )
send_file_data(self, m, i, friendnum, filenum, filename);
file_senders[i].queue_pos = num_active_file_senders - 1;
}
refresh_sender_prog(m);
refresh_recv_prog(m);
}

View File

@ -1,76 +0,0 @@
/* file_senders.h
*
*
* Copyright (C) 2014 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 FILESENDERS_H
#define FILESENDERS_H
#include "toxic.h"
#include "windows.h"
#define KiB 1024
#define MiB 1048576 /* 1024 ^ 2 */
#define GiB 1073741824 /* 1024 ^ 3 */
#define FILE_PIECE_SIZE 2048 /* must be >= (MAX_CRYPTO_DATA_SIZE - 2) in toxcore/net_crypto.h */
#define MAX_FILES 32
#define TIMEOUT_FILESENDER 120
typedef struct {
FILE *file;
ToxWindow *toxwin;
int32_t friendnum;
bool active;
bool noconnection; /* set when the connection has been interrupted */
bool paused; /* set when transfer has been explicitly paused */
bool finished; /* set after entire file has been sent but no TOX_FILECONTROL_FINISHED receieved */
bool started; /* set after TOX_FILECONTROL_ACCEPT received */
int filenum;
char nextpiece[FILE_PIECE_SIZE];
uint16_t piecelen;
char filename[MAX_STR_SIZE];
uint64_t timestamp; /* marks the last time data was successfully transfered */
uint64_t last_progress; /* marks the last time the progress bar was refreshed */
double bps;
uint64_t size;
uint32_t line_id;
uint8_t queue_pos;
} FileSender;
/* creates initial progress line that will be updated during file transfer.
Assumes progline is of size MAX_STR_SIZE */
void prep_prog_line(char *progline);
/* prints a progress bar for file transfers.
if friendnum is -1 we're sending the file, otherwise we're receiving. */
void print_progress_bar(ToxWindow *self, int idx, int friendnum, double pct_remain);
/* set CTRL to -1 if we don't want to send a control signal.
set msg to NULL if we don't want to display a message */
void close_file_sender(ToxWindow *self, Tox *m, int i, const char *msg, int CTRL, int filenum, int32_t friendnum);
/* called whenever a file sender is opened or closed */
void reset_file_sender_queue(void);
void close_all_file_senders(Tox *m);
void do_file_senders(Tox *m);
#endif /* #define FILESENDERS_H */

236
src/file_transfers.c Normal file
View File

@ -0,0 +1,236 @@
/* file_transfers.c
*
*
* Copyright (C) 2014 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 <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include "toxic.h"
#include "windows.h"
#include "friendlist.h"
#include "file_transfers.h"
#include "line_info.h"
#include "misc_tools.h"
#include "notify.h"
extern FriendsList Friends;
#define NUM_PROG_MARKS 50 /* number of "#"'s in file transfer progress bar. Keep well below MAX_STR_SIZE */
/* creates initial progress line that will be updated during file transfer.
Assumes progline is of size MAX_STR_SIZE */
void prep_prog_line(char *progline)
{
strcpy(progline, "0.0 B/s [");
int i;
for (i = 0; i < NUM_PROG_MARKS; ++i)
strcat(progline, "-");
strcat(progline, "] 0%");
}
/* prints a progress bar for file transfers.
if friendnum is -1 we're sending the file, otherwise we're receiving. */
void print_progress_bar(ToxWindow *self, double bps, double pct_done, uint32_t line_id)
{
if (bps < 0 || pct_done < 0 || pct_done > 100)
return;
char msg[MAX_STR_SIZE];
bytes_convert_str(msg, sizeof(msg), bps);
strcat(msg, "/s [");
int n = pct_done / (100 / NUM_PROG_MARKS);
int i, j;
for (i = 0; i < n; ++i)
strcat(msg, "#");
for (j = i; j < NUM_PROG_MARKS; ++j)
strcat(msg, "-");
strcat(msg, "] ");
char pctstr[16];
const char *frmt = pct_done == 100 ? "%.f%%" : "%.1f%%";
snprintf(pctstr, sizeof(pctstr), frmt, pct_done);
strcat(msg, pctstr);
line_info_set(self, line_id, msg);
}
static void refresh_progress_helper(ToxWindow *self, struct FileTransfer *ft, uint64_t curtime)
{
if (ft->state == FILE_TRANSFER_INACTIVE)
return;
/* Timeout must be set to 1 second to show correct bytes per second */
if (!timed_out(ft->last_progress, curtime, 1))
return;
double remain = ft->file_size - ft->position;
double pct_done = remain > 0 ? (1 - (remain / ft->file_size)) * 100 : 100;
print_progress_bar(self, ft->bps, pct_done, ft->line_id);
ft->bps = 0;
ft->last_progress = curtime;
}
/* refreshes active file receiver status bars for friendnum */
void refresh_file_transfer_progress(ToxWindow *self, Tox *m, uint32_t friendnum)
{
uint64_t curtime = get_unix_time();
size_t i;
for (i = 0; i < MAX_FILES; ++i) {
refresh_progress_helper(self, &Friends.list[friendnum].file_receiver[i], curtime);
refresh_progress_helper(self, &Friends.list[friendnum].file_sender[i], curtime);
}
}
/* Returns a pointer to friendnum's FileTransfer struct associated with filenum.
* Returns NULL if filenum is invalid.
*/
struct FileTransfer *get_file_transfer_struct(uint32_t friendnum, uint32_t filenum)
{
size_t i;
for (i = 0; i < MAX_FILES; ++i) {
struct FileTransfer *ft_send = &Friends.list[friendnum].file_sender[i];
if (ft_send->state != FILE_TRANSFER_INACTIVE && ft_send->filenum == filenum)
return ft_send;
struct FileTransfer *ft_recv = &Friends.list[friendnum].file_receiver[i];
if (ft_recv->state != FILE_TRANSFER_INACTIVE && ft_recv->filenum == filenum)
return ft_recv;
}
return NULL;
}
/* Returns a pointer to the FileTransfer struct associated with index with the direction specified.
* Returns NULL on failure.
*/
struct FileTransfer *get_file_transfer_struct_index(uint32_t friendnum, uint32_t index,
FILE_TRANSFER_DIRECTION direction)
{
if (direction != FILE_TRANSFER_RECV && direction != FILE_TRANSFER_SEND)
return NULL;
size_t i;
for (i = 0; i < MAX_FILES; ++i) {
struct FileTransfer *ft = direction == FILE_TRANSFER_SEND ?
&Friends.list[friendnum].file_sender[i] :
&Friends.list[friendnum].file_receiver[i];
if (ft->state != FILE_TRANSFER_INACTIVE && ft->index == index)
return ft;
}
return NULL;
}
/* Returns a pointer to an unused file sender.
* Returns NULL if all file senders are in use.
*/
struct FileTransfer *get_new_file_sender(uint32_t friendnum)
{
size_t i;
for (i = 0; i < MAX_FILES; ++i) {
struct FileTransfer *ft = &Friends.list[friendnum].file_sender[i];
if (ft->state == FILE_TRANSFER_INACTIVE) {
ft->index = i;
return ft;
}
}
return NULL;
}
/* Returns a pointer to an unused file receiver.
* Returns NULL if all file receivers are in use.
*/
struct FileTransfer *get_new_file_receiver(uint32_t friendnum)
{
size_t i;
for (i = 0; i < MAX_FILES; ++i) {
struct FileTransfer *ft = &Friends.list[friendnum].file_receiver[i];
if (ft->state == FILE_TRANSFER_INACTIVE) {
ft->index = i;
return ft;
}
}
return NULL;
}
/* Closes file transfer ft.
*
* Set CTRL to -1 if we don't want to send a control signal.
* Set message or self to NULL if we don't want to display a message.
*/
void close_file_transfer(ToxWindow *self, Tox *m, struct FileTransfer *ft, int CTRL, const char *message,
Notification sound_type)
{
if (!ft)
return;
if (ft->state == FILE_TRANSFER_INACTIVE)
return;
if (ft->file)
fclose(ft->file);
memset(ft, 0, sizeof(struct FileTransfer));
if (CTRL >= 0)
tox_file_control(m, ft->friendnum, ft->filenum, (TOX_FILE_CONTROL) CTRL, NULL);
if (message && self) {
if (self->active_box != -1)
box_notify2(self, sound_type, NT_NOFOCUS | NT_WNDALERT_2, self->active_box, "%s", message);
else
box_notify(self, sound_type, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, self->name, "%s", message);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", message);
}
}
/* Kills all active file transfers for friendnum */
void kill_all_file_transfers_friend(Tox *m, uint32_t friendnum)
{
size_t i;
for (i = 0; i < MAX_FILES; ++i) {
close_file_transfer(NULL, m, &Friends.list[friendnum].file_sender[i], -1, NULL, silent);
close_file_transfer(NULL, m, &Friends.list[friendnum].file_receiver[i], -1, NULL, silent);
}
}

110
src/file_transfers.h Normal file
View File

@ -0,0 +1,110 @@
/* file_transfers.h
*
*
* Copyright (C) 2014 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 FILE_TRANSFERS_H
#define FILE_TRANSFERS_H
#include <limits.h>
#include "toxic.h"
#include "windows.h"
#include "notify.h"
#define KiB 1024
#define MiB 1048576 /* 1024 ^ 2 */
#define GiB 1073741824 /* 1024 ^ 3 */
#define MAX_FILES 32
#define TIMEOUT_FILESENDER 120
typedef enum FILE_TRANSFER_STATE {
FILE_TRANSFER_INACTIVE,
FILE_TRANSFER_PENDING,
FILE_TRANSFER_STARTED,
FILE_TRANSFER_PAUSED
} FILE_TRANSFER_STATE;
typedef enum FILE_TRANSFER_DIRECTION {
FILE_TRANSFER_SEND,
FILE_TRANSFER_RECV
} FILE_TRANSFER_DIRECTION;
struct FileTransfer {
FILE *file;
FILE_TRANSFER_STATE state;
FILE_TRANSFER_DIRECTION direction;
char file_name[TOX_MAX_FILENAME_LENGTH + 1];
char file_path[PATH_MAX + 1]; /* Not used by senders */
double bps;
uint32_t filenum;
uint32_t friendnum;
size_t index;
uint64_t file_size;
uint64_t last_progress;
uint64_t position;
uint32_t line_id;
};
/* creates initial progress line that will be updated during file transfer.
progline must be at lesat MAX_STR_SIZE bytes */
void prep_prog_line(char *progline);
/* prints a progress bar for file transfers */
void print_progress_bar(ToxWindow *self, double pct_done, double bps, uint32_t line_id);
/* refreshes active file transfer status bars for friendnum */
void refresh_file_transfer_progress(ToxWindow *self, Tox *m, uint32_t friendnum);
/* Returns a pointer to friendnum's FileTransfer struct associated with filenum.
* Returns NULL if filenum is invalid.
*/
struct FileTransfer *get_file_transfer_struct(uint32_t friendnum, uint32_t filenum);
/* Returns a pointer to the FileTransfer struct associated with index with the direction specified.
* Returns NULL on failure.
*/
struct FileTransfer *get_file_transfer_struct_index(uint32_t friendnum, uint32_t index,
FILE_TRANSFER_DIRECTION direction);
/* Returns a pointer to an unused file sender.
* Returns NULL if all file senders are in use.
*/
struct FileTransfer *get_new_file_sender(uint32_t friendnum);
/* Returns a pointer to an unused file receiver.
* Returns NULL if all file receivers are in use.
*/
struct FileTransfer *get_new_file_receiver(uint32_t friendnum);
/* Closes file transfer ft.
*
* Set CTRL to -1 if we don't want to send a control signal.
* Set message or self to NULL if we don't want to display a message.
*/
void close_file_transfer(ToxWindow *self, Tox *m, struct FileTransfer *ft, int CTRL, const char *message,
Notification sound_type);
/* Kills all active file transfers for friendnum */
void kill_all_file_transfers_friend(Tox *m, uint32_t friendnum);
#endif /* #define FILE_TRANSFERS_H */

View File

@ -59,16 +59,15 @@ static struct Blocked {
int num_selected; int num_selected;
int max_idx; int max_idx;
int num_blocked; int num_blocked;
uint32_t *index;
int *index;
BlockedFriend *list; BlockedFriend *list;
} Blocked; } Blocked;
static struct pendingDel { static struct PendingDel {
int num; uint32_t num;
bool active; bool active;
WINDOW *popup; WINDOW *popup;
} pendingdelete; } PendingDelete;
static void realloc_friends(int n) static void realloc_friends(int n)
{ {
@ -81,7 +80,7 @@ static void realloc_friends(int n)
} }
ToxicFriend *f = realloc(Friends.list, n * sizeof(ToxicFriend)); ToxicFriend *f = realloc(Friends.list, n * sizeof(ToxicFriend));
int *f_idx = realloc(Friends.index, n * sizeof(int)); uint32_t *f_idx = realloc(Friends.index, n * sizeof(uint32_t));
if (f == NULL || f_idx == NULL) if (f == NULL || f_idx == NULL)
exit_toxic_err("failed in realloc_friends", FATALERR_MEMORY); exit_toxic_err("failed in realloc_friends", FATALERR_MEMORY);
@ -101,7 +100,7 @@ static void realloc_blocklist(int n)
} }
BlockedFriend *b = realloc(Blocked.list, n * sizeof(BlockedFriend)); BlockedFriend *b = realloc(Blocked.list, n * sizeof(BlockedFriend));
int *b_idx = realloc(Blocked.index, n * sizeof(int)); uint32_t *b_idx = realloc(Blocked.index, n * sizeof(uint32_t));
if (b == NULL || b_idx == NULL) if (b == NULL || b_idx == NULL)
exit_toxic_err("failed in realloc_blocklist", FATALERR_MEMORY); exit_toxic_err("failed in realloc_blocklist", FATALERR_MEMORY);
@ -125,9 +124,6 @@ void kill_friendlist(void)
static int save_blocklist(char *path) static int save_blocklist(char *path)
{ {
if (arg_opts.ignore_data_file)
return 0;
if (path == NULL) if (path == NULL)
return -1; return -1;
@ -193,7 +189,7 @@ int load_blocklist(char *path)
off_t len = file_size(path); off_t len = file_size(path);
if (len == -1) { if (len == 0) {
fclose(fp); fclose(fp);
return -1; return -1;
} }
@ -255,8 +251,8 @@ static int index_name_cmp(const void *n1, const void *n2)
int res = qsort_strcasecmp_hlpr(Friends.list[*(int *) n1].name, Friends.list[*(int *) n2].name); int res = qsort_strcasecmp_hlpr(Friends.list[*(int *) n1].name, Friends.list[*(int *) n2].name);
/* Use weight to make qsort always put online friends before offline */ /* Use weight to make qsort always put online friends before offline */
res = Friends.list[*(int *) n1].online ? (res - S_WEIGHT) : (res + S_WEIGHT); res = Friends.list[*(int *) n1].connection_status ? (res - S_WEIGHT) : (res + S_WEIGHT);
res = Friends.list[*(int *) n2].online ? (res + S_WEIGHT) : (res - S_WEIGHT); res = Friends.list[*(int *) n2].connection_status ? (res + S_WEIGHT) : (res - S_WEIGHT);
return res; return res;
} }
@ -264,15 +260,15 @@ static int index_name_cmp(const void *n1, const void *n2)
/* sorts Friends.index first by connection status then alphabetically */ /* sorts Friends.index first by connection status then alphabetically */
void sort_friendlist_index(void) void sort_friendlist_index(void)
{ {
int i; size_t i;
int n = 0; uint32_t n = 0;
for (i = 0; i < Friends.max_idx; ++i) { for (i = 0; i < Friends.max_idx; ++i) {
if (Friends.list[i].active) if (Friends.list[i].active)
Friends.index[n++] = Friends.list[i].num; Friends.index[n++] = Friends.list[i].num;
} }
qsort(Friends.index, Friends.num_friends, sizeof(int), index_name_cmp); qsort(Friends.index, Friends.num_friends, sizeof(uint32_t), index_name_cmp);
} }
static int index_name_cmp_block(const void *n1, const void *n2) static int index_name_cmp_block(const void *n1, const void *n2)
@ -282,18 +278,18 @@ static int index_name_cmp_block(const void *n1, const void *n2)
static void sort_blocklist_index(void) static void sort_blocklist_index(void)
{ {
int i; size_t i;
int n = 0; uint32_t n = 0;
for (i = 0; i < Blocked.max_idx; ++i) { for (i = 0; i < Blocked.max_idx; ++i) {
if (Blocked.list[i].active) if (Blocked.list[i].active)
Blocked.index[n++] = Blocked.list[i].num; Blocked.index[n++] = Blocked.list[i].num;
} }
qsort(Blocked.index, Blocked.num_blocked, sizeof(int), index_name_cmp_block); qsort(Blocked.index, Blocked.num_blocked, sizeof(uint32_t), index_name_cmp_block);
} }
static void update_friend_last_online(int32_t num, uint64_t timestamp) static void update_friend_last_online(uint32_t num, uint64_t timestamp)
{ {
Friends.list[num].last_online.last_on = timestamp; Friends.list[num].last_online.last_on = timestamp;
Friends.list[num].last_online.tm = *localtime((const time_t*)&timestamp); Friends.list[num].last_online.tm = *localtime((const time_t*)&timestamp);
@ -304,42 +300,48 @@ static void update_friend_last_online(int32_t num, uint64_t timestamp)
&Friends.list[num].last_online.tm); &Friends.list[num].last_online.tm);
} }
static void friendlist_onMessage(ToxWindow *self, Tox *m, int32_t num, const char *str, uint16_t len) static void friendlist_onMessage(ToxWindow *self, Tox *m, uint32_t num, TOX_MESSAGE_TYPE type, const char *str,
size_t length)
{ {
if (num >= Friends.max_idx) if (num >= Friends.max_idx)
return; return;
if (Friends.list[num].chatwin == -1) { if (Friends.list[num].chatwin != -1)
if (get_num_active_windows() < MAX_WINDOWS_NUM) { return;
Friends.list[num].chatwin = add_window(m, new_chat(m, Friends.list[num].num));
} else {
char nick[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, nick, num);
char timefrmt[TIME_STR_SIZE]; if (get_num_active_windows() < MAX_WINDOWS_NUM) {
get_time_str(timefrmt, sizeof(timefrmt)); Friends.list[num].chatwin = add_window(m, new_chat(m, Friends.list[num].num));
return;
line_info_add(prompt, timefrmt, nick, NULL, IN_MSG, 0, 0, "%s", str);
const char *msg = "* Warning: Too many windows are open.";
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, msg);
sound_notify(prompt, error, NT_WNDALERT_1, NULL);
}
} }
char nick[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, nick, num);
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(prompt, timefrmt, nick, NULL, IN_MSG, 0, 0, "%s", str);
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, "* Warning: Too many windows are open.");
sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
} }
static void friendlist_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_t status) static void friendlist_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, TOX_CONNECTION connection_status)
{ {
if (num >= Friends.max_idx) if (num >= Friends.max_idx)
return; return;
Friends.list[num].online = status; if (connection_status == TOX_CONNECTION_NONE)
--Friends.num_online;
else
++Friends.num_online;
Friends.list[num].connection_status = connection_status;
update_friend_last_online(num, get_unix_time()); update_friend_last_online(num, get_unix_time());
store_data(m, DATA_FILE); store_data(m, DATA_FILE);
sort_friendlist_index(); sort_friendlist_index();
} }
static void friendlist_onNickChange(ToxWindow *self, Tox *m, int32_t num, const char *nick, uint16_t len) static void friendlist_onNickChange(ToxWindow *self, Tox *m, uint32_t num, const char *nick, size_t length)
{ {
if (num >= Friends.max_idx) if (num >= Friends.max_idx)
return; return;
@ -354,9 +356,9 @@ static void friendlist_onNickChange(ToxWindow *self, Tox *m, int32_t num, const
/* get data for chatlog renaming */ /* get data for chatlog renaming */
char newnamecpy[TOXIC_MAX_NAME_LENGTH + 1]; char newnamecpy[TOXIC_MAX_NAME_LENGTH + 1];
char myid[TOX_FRIEND_ADDRESS_SIZE]; char myid[TOX_ADDRESS_SIZE];
strcpy(newnamecpy, Friends.list[num].name); strcpy(newnamecpy, Friends.list[num].name);
tox_get_address(m, (uint8_t *) myid); tox_self_get_address(m, (uint8_t *) myid);
if (strcmp(oldname, newnamecpy) != 0) if (strcmp(oldname, newnamecpy) != 0)
rename_logfile(oldname, newnamecpy, myid, Friends.list[num].pub_key, Friends.list[num].chatwin); rename_logfile(oldname, newnamecpy, myid, Friends.list[num].pub_key, Friends.list[num].chatwin);
@ -364,7 +366,7 @@ static void friendlist_onNickChange(ToxWindow *self, Tox *m, int32_t num, const
sort_friendlist_index(); sort_friendlist_index();
} }
static void friendlist_onStatusChange(ToxWindow *self, Tox *m, int32_t num, uint8_t status) static void friendlist_onStatusChange(ToxWindow *self, Tox *m, uint32_t num, TOX_USER_STATUS status)
{ {
if (num >= Friends.max_idx) if (num >= Friends.max_idx)
return; return;
@ -372,50 +374,47 @@ static void friendlist_onStatusChange(ToxWindow *self, Tox *m, int32_t num, uint
Friends.list[num].status = status; Friends.list[num].status = status;
} }
static void friendlist_onStatusMessageChange(ToxWindow *self, int32_t num, const char *status, uint16_t len) static void friendlist_onStatusMessageChange(ToxWindow *self, uint32_t num, const char *note, size_t length)
{ {
if (len > TOX_MAX_STATUSMESSAGE_LENGTH || num >= Friends.max_idx) if (length > TOX_MAX_STATUS_MESSAGE_LENGTH || num >= Friends.max_idx)
return; return;
snprintf(Friends.list[num].statusmsg, sizeof(Friends.list[num].statusmsg), "%s", status); snprintf(Friends.list[num].statusmsg, sizeof(Friends.list[num].statusmsg), "%s", note);
Friends.list[num].statusmsg_len = strlen(Friends.list[num].statusmsg); Friends.list[num].statusmsg_len = strlen(Friends.list[num].statusmsg);
} }
void friendlist_onFriendAdded(ToxWindow *self, Tox *m, int32_t num, bool sort) void friendlist_onFriendAdded(ToxWindow *self, Tox *m, uint32_t num, bool sort)
{ {
if (Friends.max_idx < 0)
return;
Friends.num_friends = tox_count_friendlist(m);
realloc_friends(Friends.max_idx + 1); realloc_friends(Friends.max_idx + 1);
memset(&Friends.list[Friends.max_idx], 0, sizeof(ToxicFriend)); memset(&Friends.list[Friends.max_idx], 0, sizeof(ToxicFriend));
int i; uint32_t i;
for (i = 0; i <= Friends.max_idx; ++i) { for (i = 0; i <= Friends.max_idx; ++i) {
if (Friends.list[i].active) if (Friends.list[i].active)
continue; continue;
++Friends.num_friends;
Friends.list[i].num = num; Friends.list[i].num = num;
Friends.list[i].active = true; Friends.list[i].active = true;
Friends.list[i].chatwin = -1; Friends.list[i].chatwin = -1;
Friends.list[i].online = false; Friends.list[i].connection_status = TOX_CONNECTION_NONE;
Friends.list[i].status = TOX_USERSTATUS_NONE; Friends.list[i].status = TOX_USER_STATUS_NONE;
Friends.list[i].logging_on = (bool) user_settings->autolog == AUTOLOG_ON; Friends.list[i].logging_on = (bool) user_settings->autolog == AUTOLOG_ON;
tox_get_client_id(m, num, (uint8_t *) Friends.list[i].pub_key);
update_friend_last_online(i, tox_get_last_online(m, i)); TOX_ERR_FRIEND_GET_PUBLIC_KEY err;
tox_friend_get_public_key(m, num, (uint8_t *) Friends.list[i].pub_key, &err);
if (err != TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK)
fprintf(stderr, "tox_friend_get_public_key failed (error %d)\n", err);
// update_friend_last_online(i, 0);
char tempname[TOX_MAX_NAME_LENGTH] = {0}; char tempname[TOX_MAX_NAME_LENGTH] = {0};
int len = get_nick_truncate(m, tempname, num); get_nick_truncate(m, tempname, num);
snprintf(Friends.list[i].name, sizeof(Friends.list[i].name), "%s", tempname);
if (len == -1 || tempname[0] == '\0') { Friends.list[i].namelength = strlen(Friends.list[i].name);
strcpy(Friends.list[i].name, UNKNOWN_NAME);
Friends.list[i].namelength = strlen(UNKNOWN_NAME);
} else { /* Enforce toxic's maximum name length */
snprintf(Friends.list[i].name, sizeof(Friends.list[i].name), "%s", tempname);
Friends.list[i].namelength = strlen(Friends.list[i].name);
}
if (i == Friends.max_idx) if (i == Friends.max_idx)
++Friends.max_idx; ++Friends.max_idx;
@ -428,9 +427,8 @@ void friendlist_onFriendAdded(ToxWindow *self, Tox *m, int32_t num, bool sort)
} }
/* puts blocked friend back in friendlist. fnum is new friend number, bnum is blocked number */ /* puts blocked friend back in friendlist. fnum is new friend number, bnum is blocked number */
static void friendlist_add_blocked(Tox *m, int32_t fnum, int32_t bnum) static void friendlist_add_blocked(Tox *m, uint32_t fnum, uint32_t bnum)
{ {
Friends.num_friends = tox_count_friendlist(m);
realloc_friends(Friends.max_idx + 1); realloc_friends(Friends.max_idx + 1);
memset(&Friends.list[Friends.max_idx], 0, sizeof(ToxicFriend)); memset(&Friends.list[Friends.max_idx], 0, sizeof(ToxicFriend));
@ -440,10 +438,12 @@ static void friendlist_add_blocked(Tox *m, int32_t fnum, int32_t bnum)
if (Friends.list[i].active) if (Friends.list[i].active)
continue; continue;
++Friends.num_friends;
Friends.list[i].num = fnum; Friends.list[i].num = fnum;
Friends.list[i].active = true; Friends.list[i].active = true;
Friends.list[i].chatwin = -1; Friends.list[i].chatwin = -1;
Friends.list[i].status = TOX_USERSTATUS_NONE; Friends.list[i].status = TOX_USER_STATUS_NONE;
Friends.list[i].logging_on = (bool) user_settings->autolog == AUTOLOG_ON; Friends.list[i].logging_on = (bool) user_settings->autolog == AUTOLOG_ON;
Friends.list[i].namelength = Blocked.list[bnum].namelength; Friends.list[i].namelength = Blocked.list[bnum].namelength;
update_friend_last_online(i, Blocked.list[bnum].last_on); update_friend_last_online(i, Blocked.list[bnum].last_on);
@ -460,27 +460,29 @@ static void friendlist_add_blocked(Tox *m, int32_t fnum, int32_t bnum)
} }
} }
static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum, static void friendlist_onFileRecv(ToxWindow *self, Tox *m, uint32_t num, uint32_t filenum,
uint64_t filesize, const char *filename, uint16_t filename_len) uint64_t file_size, const char *filename, size_t name_length)
{ {
if (num >= Friends.max_idx) if (num >= Friends.max_idx)
return; return;
if (Friends.list[num].chatwin == -1) { if (Friends.list[num].chatwin != -1)
if (get_num_active_windows() < MAX_WINDOWS_NUM) { return;
Friends.list[num].chatwin = add_window(m, new_chat(m, Friends.list[num].num));
} else {
tox_file_send_control(m, num, 1, filenum, TOX_FILECONTROL_KILL, 0, 0);
char nick[TOX_MAX_NAME_LENGTH]; if (get_num_active_windows() < MAX_WINDOWS_NUM) {
get_nick_truncate(m, nick, num); Friends.list[num].chatwin = add_window(m, new_chat(m, Friends.list[num].num));
return;
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED,
"* File transfer from %s failed: too many windows are open.", nick);
sound_notify(prompt, error, NT_WNDALERT_1, NULL);
}
} }
tox_file_control(m, num, filenum, TOX_FILE_CONTROL_CANCEL, NULL);
char nick[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, nick, num);
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED,
"* File transfer from %s failed: too many windows are open.", nick);
sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
} }
static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const char *data, static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const char *data,
@ -489,17 +491,21 @@ static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const
if (num >= Friends.max_idx) if (num >= Friends.max_idx)
return; return;
if (Friends.list[num].chatwin == -1) { if (Friends.list[num].chatwin != -1)
if (get_num_active_windows() < MAX_WINDOWS_NUM) { return;
Friends.list[num].chatwin = add_window(m, new_chat(m, Friends.list[num].num));
} else { if (get_num_active_windows() < MAX_WINDOWS_NUM) {
char nick[TOX_MAX_NAME_LENGTH]; Friends.list[num].chatwin = add_window(m, new_chat(m, Friends.list[num].num));
get_nick_truncate(m, nick, num); return;
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED,
"* Group chat invite from %s failed: too many windows are open.", nick);
sound_notify(prompt, error, NT_WNDALERT_1, NULL);
}
} }
char nick[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, nick, num);
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED,
"* Group chat invite from %s failed: too many windows are open.", nick);
sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
} }
/* move friendlist/blocklist cursor up and down */ /* move friendlist/blocklist cursor up and down */
@ -516,8 +522,20 @@ static void select_friend(ToxWindow *self, wint_t key, int *selected, int num)
} }
} }
static void delete_friend(Tox *m, int32_t f_num) static void delete_friend(Tox *m, uint32_t f_num)
{ {
TOX_ERR_FRIEND_DELETE err;
if (tox_friend_delete(m, f_num, &err) != true) {
fprintf(stderr, "tox_friend_delete failed with error %d\n", err);
return;
}
--Friends.num_friends;
if (Friends.list[f_num].connection_status != TOX_CONNECTION_NONE)
--Friends.num_online;
/* close friend's chatwindow if it's currently open */
if (Friends.list[f_num].chatwin >= 0) { if (Friends.list[f_num].chatwin >= 0) {
ToxWindow *toxwin = get_window_ptr(Friends.list[f_num].chatwin); ToxWindow *toxwin = get_window_ptr(Friends.list[f_num].chatwin);
@ -527,7 +545,6 @@ static void delete_friend(Tox *m, int32_t f_num)
} }
} }
tox_del_friend(m, f_num);
memset(&Friends.list[f_num], 0, sizeof(ToxicFriend)); memset(&Friends.list[f_num], 0, sizeof(ToxicFriend));
int i; int i;
@ -538,7 +555,6 @@ static void delete_friend(Tox *m, int32_t f_num)
} }
Friends.max_idx = i; Friends.max_idx = i;
Friends.num_friends = tox_count_friendlist(m);
realloc_friends(i); realloc_friends(i);
/* make sure num_selected stays within Friends.num_friends range */ /* make sure num_selected stays within Friends.num_friends range */
@ -549,60 +565,60 @@ static void delete_friend(Tox *m, int32_t f_num)
} }
/* activates delete friend popup */ /* activates delete friend popup */
static void del_friend_activate(ToxWindow *self, Tox *m, int32_t f_num) static void del_friend_activate(ToxWindow *self, Tox *m, uint32_t f_num)
{ {
pendingdelete.popup = newwin(3, 22 + TOXIC_MAX_NAME_LENGTH, 8, 8); PendingDelete.popup = newwin(3, 22 + TOXIC_MAX_NAME_LENGTH, 8, 8);
pendingdelete.active = true; PendingDelete.active = true;
pendingdelete.num = f_num; PendingDelete.num = f_num;
} }
static void delete_blocked_friend(int32_t bnum); static void delete_blocked_friend(uint32_t bnum);
/* deactivates delete friend popup and deletes friend if instructed */ /* deactivates delete friend popup and deletes friend if instructed */
static void del_friend_deactivate(ToxWindow *self, Tox *m, wint_t key) static void del_friend_deactivate(ToxWindow *self, Tox *m, wint_t key)
{ {
if (key == 'y') { if (key == 'y') {
if (blocklist_view == 0) { if (blocklist_view == 0) {
delete_friend(m, pendingdelete.num); delete_friend(m, PendingDelete.num);
sort_friendlist_index(); sort_friendlist_index();
} else { } else {
delete_blocked_friend(pendingdelete.num); delete_blocked_friend(PendingDelete.num);
sort_blocklist_index(); sort_blocklist_index();
} }
} }
delwin(pendingdelete.popup); delwin(PendingDelete.popup);
memset(&pendingdelete, 0, sizeof(pendingdelete)); memset(&PendingDelete, 0, sizeof(PendingDelete));
clear(); clear();
refresh(); refresh();
} }
static void draw_del_popup(void) static void draw_del_popup(void)
{ {
if (!pendingdelete.active) if (!PendingDelete.active)
return; return;
wattron(pendingdelete.popup, A_BOLD); wattron(PendingDelete.popup, A_BOLD);
box(pendingdelete.popup, ACS_VLINE, ACS_HLINE); box(PendingDelete.popup, ACS_VLINE, ACS_HLINE);
wattroff(pendingdelete.popup, A_BOLD); wattroff(PendingDelete.popup, A_BOLD);
wmove(pendingdelete.popup, 1, 1); wmove(PendingDelete.popup, 1, 1);
wprintw(pendingdelete.popup, "Delete contact "); wprintw(PendingDelete.popup, "Delete contact ");
wattron(pendingdelete.popup, A_BOLD); wattron(PendingDelete.popup, A_BOLD);
if (blocklist_view == 0) if (blocklist_view == 0)
wprintw(pendingdelete.popup, "%s", Friends.list[pendingdelete.num].name); wprintw(PendingDelete.popup, "%s", Friends.list[PendingDelete.num].name);
else else
wprintw(pendingdelete.popup, "%s", Blocked.list[pendingdelete.num].name); wprintw(PendingDelete.popup, "%s", Blocked.list[PendingDelete.num].name);
wattroff(pendingdelete.popup, A_BOLD); wattroff(PendingDelete.popup, A_BOLD);
wprintw(pendingdelete.popup, "? y/n"); wprintw(PendingDelete.popup, "? y/n");
wrefresh(pendingdelete.popup); wrefresh(PendingDelete.popup);
} }
/* deletes contact from blocked list */ /* deletes contact from blocked list */
static void delete_blocked_friend(int32_t bnum) static void delete_blocked_friend(uint32_t bnum)
{ {
memset(&Blocked.list[bnum], 0, sizeof(BlockedFriend)); memset(&Blocked.list[bnum], 0, sizeof(BlockedFriend));
@ -623,7 +639,7 @@ static void delete_blocked_friend(int32_t bnum)
} }
/* deletes contact from friendlist and puts in blocklist */ /* deletes contact from friendlist and puts in blocklist */
void block_friend(Tox *m, int32_t fnum) void block_friend(Tox *m, uint32_t fnum)
{ {
if (Friends.num_friends <= 0) if (Friends.num_friends <= 0)
return; return;
@ -642,7 +658,7 @@ void block_friend(Tox *m, int32_t fnum)
Blocked.list[i].namelength = Friends.list[fnum].namelength; Blocked.list[i].namelength = Friends.list[fnum].namelength;
Blocked.list[i].last_on = Friends.list[fnum].last_online.last_on; Blocked.list[i].last_on = Friends.list[fnum].last_online.last_on;
memcpy(Blocked.list[i].pub_key, Friends.list[fnum].pub_key, TOX_PUBLIC_KEY_SIZE); memcpy(Blocked.list[i].pub_key, Friends.list[fnum].pub_key, TOX_PUBLIC_KEY_SIZE);
memcpy(Blocked.list[i].name, Friends.list[fnum].name, Friends.list[fnum].namelength + 1); memcpy(Blocked.list[i].name, Friends.list[fnum].name, Friends.list[fnum].namelength + 1);
++Blocked.num_blocked; ++Blocked.num_blocked;
@ -659,15 +675,16 @@ void block_friend(Tox *m, int32_t fnum)
} }
/* removes friend from blocklist, puts back in friendlist */ /* removes friend from blocklist, puts back in friendlist */
static void unblock_friend(Tox *m, int32_t bnum) static void unblock_friend(Tox *m, uint32_t bnum)
{ {
if (Blocked.num_blocked <= 0) if (Blocked.num_blocked <= 0)
return; return;
int32_t friendnum = tox_add_friend_norequest(m, (uint8_t *) Blocked.list[bnum].pub_key); TOX_ERR_FRIEND_ADD err;
uint32_t friendnum = tox_friend_add_norequest(m, (uint8_t *) Blocked.list[bnum].pub_key, &err);
if (friendnum == -1) { if (err != TOX_ERR_FRIEND_ADD_OK) {
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to unblock friend"); line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to unblock friend (error %d)\n", err);
return; return;
} }
@ -704,7 +721,7 @@ static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
f = Friends.index[Friends.num_selected]; f = Friends.index[Friends.num_selected];
/* lock screen and force decision on deletion popup */ /* lock screen and force decision on deletion popup */
if (pendingdelete.active) { if (PendingDelete.active) {
if (key == 'y' || key == 'n') if (key == 'y' || key == 'n')
del_friend_deactivate(self, m, key); del_friend_deactivate(self, m, key);
@ -728,7 +745,7 @@ static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
} else { } else {
const char *msg = "* Warning: Too many windows are open."; const char *msg = "* Warning: Too many windows are open.";
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, msg); line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, msg);
sound_notify(prompt, error, NT_WNDALERT_1, NULL); sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
} }
break; break;
@ -770,7 +787,7 @@ static void blocklist_onDraw(ToxWindow *self, Tox *m, int y2, int x2)
if ((y2 - FLIST_OFST) <= 0) if ((y2 - FLIST_OFST) <= 0)
return; return;
int selected_num = 0; uint32_t selected_num = 0;
/* Determine which portion of friendlist to draw based on current position */ /* Determine which portion of friendlist to draw based on current position */
int page = Blocked.num_selected / (y2 - FLIST_OFST); int page = Blocked.num_selected / (y2 - FLIST_OFST);
@ -780,7 +797,7 @@ static void blocklist_onDraw(ToxWindow *self, Tox *m, int y2, int x2)
int i; int i;
for (i = start; i < Blocked.num_blocked && i < end; ++i) { for (i = start; i < Blocked.num_blocked && i < end; ++i) {
int f = Blocked.index[i]; uint32_t f = Blocked.index[i];
bool f_selected = false; bool f_selected = false;
if (i == Blocked.num_selected) { if (i == Blocked.num_selected) {
@ -853,22 +870,18 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
return; return;
} }
uint64_t cur_time = get_unix_time(); // uint64_t cur_time = get_unix_time();
struct tm cur_loc_tm = *localtime((const time_t *) &cur_time); // struct tm cur_loc_tm = *localtime((const time_t *) &cur_time);
pthread_mutex_lock(&Winthread.lock);
int nf = tox_get_num_online_friends(m);
pthread_mutex_unlock(&Winthread.lock);
wattron(self->window, A_BOLD); wattron(self->window, A_BOLD);
wprintw(self->window, " Online: "); wprintw(self->window, " Online: ");
wattroff(self->window, A_BOLD); wattroff(self->window, A_BOLD);
wprintw(self->window, "%d/%d \n\n", nf, Friends.num_friends); wprintw(self->window, "%d/%d \n\n", Friends.num_online, Friends.num_friends);
if ((y2 - FLIST_OFST) <= 0) if ((y2 - FLIST_OFST) <= 0)
return; return;
int selected_num = 0; uint32_t selected_num = 0;
/* Determine which portion of friendlist to draw based on current position */ /* Determine which portion of friendlist to draw based on current position */
int page = Friends.num_selected / (y2 - FLIST_OFST); int page = Friends.num_selected / (y2 - FLIST_OFST);
@ -878,7 +891,7 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
int i; int i;
for (i = start; i < Friends.num_friends && i < end; ++i) { for (i = start; i < Friends.num_friends && i < end; ++i) {
int f = Friends.index[i]; uint32_t f = Friends.index[i];
bool f_selected = false; bool f_selected = false;
if (Friends.list[f].active) { if (Friends.list[f].active) {
@ -892,26 +905,20 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
wprintw(self->window, " "); wprintw(self->window, " ");
} }
if (Friends.list[f].online) { if (Friends.list[f].connection_status != TOX_CONNECTION_NONE) {
uint8_t status = Friends.list[f].status; TOX_USER_STATUS status = Friends.list[f].status;
int colour = WHITE; int colour = MAGENTA;
switch (status) { switch (status) {
case TOX_USERSTATUS_NONE: case TOX_USER_STATUS_NONE:
colour = GREEN; colour = GREEN;
break; break;
case TOX_USER_STATUS_AWAY:
case TOX_USERSTATUS_AWAY:
colour = YELLOW; colour = YELLOW;
break; break;
case TOX_USER_STATUS_BUSY:
case TOX_USERSTATUS_BUSY:
colour = RED; colour = RED;
break; break;
case TOX_USERSTATUS_INVALID:
colour = MAGENTA;
break;
} }
wattron(self->window, COLOR_PAIR(colour) | A_BOLD); wattron(self->window, COLOR_PAIR(colour) | A_BOLD);
@ -930,11 +937,11 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
/* Reset Friends.list[f].statusmsg on window resize */ /* Reset Friends.list[f].statusmsg on window resize */
if (fix_statuses) { if (fix_statuses) {
char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH]; char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH];
pthread_mutex_lock(&Winthread.lock); pthread_mutex_lock(&Winthread.lock);
int s_len = tox_get_status_message(m, Friends.list[f].num, (uint8_t *) statusmsg, tox_friend_get_status_message(m, Friends.list[f].num, (uint8_t *) statusmsg, NULL);
TOX_MAX_STATUSMESSAGE_LENGTH); size_t s_len = tox_friend_get_status_message_size(m, Friends.list[f].num, NULL);
pthread_mutex_unlock(&Winthread.lock); pthread_mutex_unlock(&Winthread.lock);
filter_str(statusmsg, s_len); filter_str(statusmsg, s_len);
@ -943,7 +950,7 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
} }
/* Truncate note if it doesn't fit on one line */ /* Truncate note if it doesn't fit on one line */
uint16_t maxlen = x2 - getcurx(self->window) - 2; size_t maxlen = x2 - getcurx(self->window) - 2;
if (Friends.list[f].statusmsg_len > maxlen) { if (Friends.list[f].statusmsg_len > maxlen) {
Friends.list[f].statusmsg[maxlen - 3] = '\0'; Friends.list[f].statusmsg[maxlen - 3] = '\0';
@ -969,31 +976,34 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
if (f_selected) if (f_selected)
wattroff(self->window, COLOR_PAIR(BLUE)); wattroff(self->window, COLOR_PAIR(BLUE));
uint64_t last_seen = Friends.list[f].last_online.last_on; wprintw(self->window, "\n");
/* Last online is currently broken in core */
if (last_seen != 0) { // uint64_t last_seen = Friends.list[f].last_online.last_on;
int day_dist = ( //
cur_loc_tm.tm_yday - Friends.list[f].last_online.tm.tm_yday // if (last_seen != 0) {
+ ((cur_loc_tm.tm_year - Friends.list[f].last_online.tm.tm_year) * 365) // int day_dist = (
); // cur_loc_tm.tm_yday - Friends.list[f].last_online.tm.tm_yday
const char *hourmin = Friends.list[f].last_online.hour_min_str; // + ((cur_loc_tm.tm_year - Friends.list[f].last_online.tm.tm_year) * 365)
// );
// const char *hourmin = Friends.list[f].last_online.hour_min_str;
switch (day_dist) { // switch (day_dist) {
case 0: // case 0:
wprintw(self->window, " Last seen: Today %s\n", hourmin); // wprintw(self->window, " Last seen: Today %s\n", hourmin);
break; // break;
case 1: // case 1:
wprintw(self->window, " Last seen: Yesterday %s\n", hourmin); // wprintw(self->window, " Last seen: Yesterday %s\n", hourmin);
break; // break;
default: // default:
wprintw(self->window, " Last seen: %d days ago\n", day_dist); // wprintw(self->window, " Last seen: %d days ago\n", day_dist);
break; // break;
} // }
} else { // } else {
wprintw(self->window, " Last seen: Never\n"); // wprintw(self->window, " Last seen: Never\n");
} // }
} }
} }
} }
@ -1020,7 +1030,7 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
help_onDraw(self); help_onDraw(self);
} }
void disable_chatwin(int32_t f_num) void disable_chatwin(uint32_t f_num)
{ {
Friends.list[f_num].chatwin = -1; Friends.list[f_num].chatwin = -1;
} }
@ -1048,7 +1058,7 @@ static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index)
const char *errmsg = "* Warning: Too many windows are open."; const char *errmsg = "* Warning: Too many windows are open.";
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg); line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg);
sound_notify(prompt, error, NT_WNDALERT_1, NULL); sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
} }
} }
} }
@ -1067,11 +1077,10 @@ ToxWindow new_friendlist(void)
ret.onFriendAdded = &friendlist_onFriendAdded; ret.onFriendAdded = &friendlist_onFriendAdded;
ret.onMessage = &friendlist_onMessage; ret.onMessage = &friendlist_onMessage;
ret.onConnectionChange = &friendlist_onConnectionChange; ret.onConnectionChange = &friendlist_onConnectionChange;
ret.onAction = &friendlist_onMessage; /* Action has identical behaviour to message */
ret.onNickChange = &friendlist_onNickChange; ret.onNickChange = &friendlist_onNickChange;
ret.onStatusChange = &friendlist_onStatusChange; ret.onStatusChange = &friendlist_onStatusChange;
ret.onStatusMessageChange = &friendlist_onStatusMessageChange; ret.onStatusMessageChange = &friendlist_onStatusMessageChange;
ret.onFileSendRequest = &friendlist_onFileSendRequest; ret.onFileRecv = &friendlist_onFileRecv;
ret.onGroupInvite = &friendlist_onGroupInvite; ret.onGroupInvite = &friendlist_onGroupInvite;
#ifdef AUDIO #ifdef AUDIO

View File

@ -27,20 +27,7 @@
#include "toxic.h" #include "toxic.h"
#include "windows.h" #include "windows.h"
#include "file_senders.h" #include "file_transfers.h"
struct FileReceiver {
char filename[MAX_STR_SIZE];
int filenum;
FILE *file;
bool pending;
bool active;
uint64_t size;
uint64_t bytes_recv;
double bps;
uint64_t last_progress; /* unix-time when we last updated progress */
uint32_t line_id;
};
struct LastOnline { struct LastOnline {
uint64_t last_on; uint64_t last_on;
@ -56,45 +43,47 @@ struct GroupInvite {
typedef struct { typedef struct {
char name[TOXIC_MAX_NAME_LENGTH + 1]; char name[TOXIC_MAX_NAME_LENGTH + 1];
int namelength; int namelength;
char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH + 1]; char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH + 1];
uint16_t statusmsg_len; size_t statusmsg_len;
char pub_key[TOX_PUBLIC_KEY_SIZE]; char pub_key[TOX_PUBLIC_KEY_SIZE];
int32_t num; uint32_t num;
int chatwin; int chatwin;
bool active; bool active;
bool online; TOX_CONNECTION connection_status;
uint8_t is_typing; bool is_typing;
bool logging_on; /* saves preference for friend irrespective of global settings */ bool logging_on; /* saves preference for friend irrespective of global settings */
uint8_t status; uint8_t status;
struct GroupInvite group_invite;
struct LastOnline last_online; struct LastOnline last_online;
struct FileReceiver file_receiver[MAX_FILES]; struct GroupInvite group_invite;
uint8_t active_file_receivers; struct FileTransfer file_receiver[MAX_FILES];
struct FileTransfer file_sender[MAX_FILES];
} ToxicFriend; } ToxicFriend;
typedef struct { typedef struct {
char name[TOXIC_MAX_NAME_LENGTH + 1]; char name[TOXIC_MAX_NAME_LENGTH + 1];
int namelength; int namelength;
char pub_key[TOX_PUBLIC_KEY_SIZE]; char pub_key[TOX_PUBLIC_KEY_SIZE];
int32_t num; uint32_t num;
bool active; bool active;
uint64_t last_on; uint64_t last_on;
} BlockedFriend; } BlockedFriend;
typedef struct { typedef struct {
int num_selected; int num_selected;
int max_idx; /* 1 + the index of the last friend in list */ size_t num_friends;
int num_friends; size_t num_online;
int *index; size_t max_idx; /* 1 + the index of the last friend in list */
uint32_t *index;
ToxicFriend *list; ToxicFriend *list;
} FriendsList; } FriendsList;
ToxWindow new_friendlist(void); ToxWindow new_friendlist(void);
void disable_chatwin(int32_t f_num); void disable_chatwin(uint32_t f_num);
int get_friendnum(uint8_t *name); int get_friendnum(uint8_t *name);
int load_blocklist(char *data); int load_blocklist(char *data);
void kill_friendlist(void); void kill_friendlist(void);
void friendlist_onFriendAdded(ToxWindow *self, Tox *m, int32_t num, bool sort); void friendlist_onFriendAdded(ToxWindow *self, Tox *m, uint32_t num, bool sort);
/* sorts friendlist_index first by connection status then alphabetically */ /* sorts friendlist_index first by connection status then alphabetically */
void sort_friendlist_index(void); void sort_friendlist_index(void);

View File

@ -61,13 +61,14 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
return; return;
} }
const char *msg; TOX_ERR_FRIEND_ADD err;
int32_t friendnum = tox_add_friend_norequest(m, FrndRequests.request[req].key); uint32_t friendnum = tox_friend_add_norequest(m, FrndRequests.request[req].key, &err);
if (friendnum == -1) if (err != TOX_ERR_FRIEND_ADD_OK) {
msg = "Failed to add friend."; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to add friend (error %d\n)", err);
else { return;
msg = "Friend request accepted."; } else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Friend request accepted.");
on_friendadded(m, friendnum, true); on_friendadded(m, friendnum, true);
} }
@ -82,47 +83,55 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
FrndRequests.max_idx = i; FrndRequests.max_idx = i;
--FrndRequests.num_requests; --FrndRequests.num_requests;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", msg);
} }
void cmd_add_helper(ToxWindow *self, Tox *m, char *id_bin, char *msg) void cmd_add_helper(ToxWindow *self, Tox *m, const char *id_bin, const char *msg)
{ {
const char *errmsg; const char *errmsg;
int32_t f_num = tox_add_friend(m, (uint8_t *) id_bin, (uint8_t *) msg, (uint16_t) strlen(msg));
switch (f_num) { TOX_ERR_FRIEND_ADD err;
case TOX_FAERR_TOOLONG: uint32_t f_num = tox_friend_add(m, (uint8_t *) id_bin, (uint8_t *) msg, strlen(msg), &err);
switch (err) {
case TOX_ERR_FRIEND_ADD_TOO_LONG:
errmsg = "Message is too long."; errmsg = "Message is too long.";
break; break;
case TOX_FAERR_NOMESSAGE: case TOX_ERR_FRIEND_ADD_NO_MESSAGE:
errmsg = "Please add a message to your request."; errmsg = "Please add a message to your request.";
break; break;
case TOX_FAERR_OWNKEY: case TOX_ERR_FRIEND_ADD_OWN_KEY:
errmsg = "That appears to be your own ID."; errmsg = "That appears to be your own ID.";
break; break;
case TOX_FAERR_ALREADYSENT: case TOX_ERR_FRIEND_ADD_ALREADY_SENT:
errmsg = "Friend request has already been sent."; errmsg = "Friend request has already been sent.";
break; break;
case TOX_FAERR_UNKNOWN: case TOX_ERR_FRIEND_ADD_BAD_CHECKSUM:
errmsg = "Undefined error when adding friend.";
break;
case TOX_FAERR_BADCHECKSUM:
errmsg = "Bad checksum in address."; errmsg = "Bad checksum in address.";
break; break;
case TOX_FAERR_SETNEWNOSPAM: case TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM:
errmsg = "Nospam was different."; errmsg = "Nospam was different.";
break; break;
default: case TOX_ERR_FRIEND_ADD_MALLOC:
errmsg = "Core memory allocation failed.";
break;
case TOX_ERR_FRIEND_ADD_OK:
errmsg = "Friend request sent."; errmsg = "Friend request sent.";
on_friendadded(m, f_num, true); on_friendadded(m, f_num, true);
break; break;
case TOX_ERR_FRIEND_ADD_NULL:
/* fallthrough */
default:
errmsg = "Faile to add friend: Unknown error.";
break;
} }
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
@ -152,21 +161,23 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
snprintf(msg, sizeof(msg), "%s", tmp); snprintf(msg, sizeof(msg), "%s", tmp);
} else { } else {
char selfname[TOX_MAX_NAME_LENGTH]; char selfname[TOX_MAX_NAME_LENGTH];
uint16_t n_len = tox_get_self_name(m, (uint8_t *) selfname); tox_self_get_name(m, (uint8_t *) selfname);
size_t n_len = tox_self_get_name_size(m);
selfname[n_len] = '\0'; selfname[n_len] = '\0';
snprintf(msg, sizeof(msg), "Hello, my name is %s. Care to Tox?", selfname); snprintf(msg, sizeof(msg), "Hello, my name is %s. Care to Tox?", selfname);
} }
char id_bin[TOX_FRIEND_ADDRESS_SIZE] = {0}; char id_bin[TOX_ADDRESS_SIZE] = {0};
uint16_t id_len = (uint16_t) strlen(id); uint16_t id_len = (uint16_t) strlen(id);
/* try to add tox ID */ /* try to add tox ID */
if (id_len == 2 * TOX_FRIEND_ADDRESS_SIZE) { if (id_len == 2 * TOX_ADDRESS_SIZE) {
size_t i; size_t i;
char xx[3]; char xx[3];
uint32_t x; uint32_t x;
for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; ++i) { for (i = 0; i < TOX_ADDRESS_SIZE; ++i) {
xx[0] = id[2 * i]; xx[0] = id[2 * i];
xx[1] = id[2 * i + 1]; xx[1] = id[2 * i + 1];
xx[2] = '\0'; xx[2] = '\0';
@ -187,77 +198,72 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
void cmd_avatar(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_avatar(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{ {
if (argc < 2) { // if (argc < 2) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: No file path supplied."); // line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: No file path supplied.");
return; // return;
} // }
/* turns the avatar off */ // /* turns the avatar off */
if (strlen(argv[1]) < 3) { // if (strlen(argv[1]) < 3) {
tox_unset_avatar(m); // tox_unset_avatar(m);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No avatar set."); // line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No avatar set.");
return; // return;
} // }
if (argv[1][0] != '\"') { // if (argv[1][0] != '\"') {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Path must be enclosed in quotes."); // line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Path must be enclosed in quotes.");
return; // return;
} // }
/* remove opening and closing quotes */ // /* remove opening and closing quotes */
char path[MAX_STR_SIZE]; // char path[MAX_STR_SIZE];
snprintf(path, sizeof(path), "%s", &argv[1][1]); // snprintf(path, sizeof(path), "%s", &argv[1][1]);
int len = strlen(path) - 1; // int len = strlen(path) - 1;
path[len] = '\0'; // path[len] = '\0';
off_t sz = file_size(path); // off_t sz = file_size(path);
if (sz <= 8) { // if (sz <= 8) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Invalid file."); // line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Invalid file.");
return; // return;
} // }
if (sz > TOX_AVATAR_MAX_DATA_LENGTH) { // FILE *fp = fopen(path, "rb");
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: File is too large.");
return;
}
FILE *fp = fopen(path, "rb"); // if (fp == NULL) {
// line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Could not open file.");
// return;
// }
if (fp == NULL) { // char PNG_signature[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Could not open file.");
return;
}
char PNG_signature[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}; // if (check_file_signature(PNG_signature, sizeof(PNG_signature), fp) != 0) {
// fclose(fp);
// line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: File type not supported.");
// return;
// }
if (check_file_signature(PNG_signature, sizeof(PNG_signature), fp) != 0) { // char *avatar = malloc(sz);
fclose(fp);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: File type not supported.");
return;
}
char *avatar = malloc(sz); // if (avatar == NULL)
// exit_toxic_err("Failed in cmd_avatar", FATALERR_MEMORY);
if (avatar == NULL) // if (fread(avatar, sz, 1, fp) != 1) {
exit_toxic_err("Failed in set_avatar", FATALERR_MEMORY); // fclose(fp);
// free(avatar);
// line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Read fail.");
// return;
// }
if (fread(avatar, sz, 1, fp) != 1) { // if (tox_set_avatar(m, TOX_AVATAR_FORMAT_PNG, (const uint8_t *) avatar, (uint32_t) sz) == -1)
fclose(fp); // line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar");
free(avatar);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Read fail.");
return;
}
if (tox_set_avatar(m, TOX_AVATAR_FORMAT_PNG, (const uint8_t *) avatar, (uint32_t) sz) == -1) // char filename[MAX_STR_SIZE];
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Core error."); // get_file_name(filename, sizeof(filename), path);
// line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Avatar set to '%s'", filename);
char filename[MAX_STR_SIZE]; // fclose(fp);
get_file_name(filename, sizeof(filename), path); // free(avatar);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Avatar set to '%s'", filename);
fclose(fp);
free(avatar);
} }
void cmd_clear(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_clear(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
@ -283,8 +289,26 @@ void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
} }
char *binary_string = hex_string_to_bin(key); char *binary_string = hex_string_to_bin(key);
tox_bootstrap_from_address(m, ip, atoi(port), (uint8_t *) binary_string);
TOX_ERR_BOOTSTRAP err;
tox_bootstrap(m, ip, atoi(port), (uint8_t *) binary_string, &err);
free(binary_string); free(binary_string);
switch (err) {
case TOX_ERR_BOOTSTRAP_BAD_HOST:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Bootstrap failed: Invalid IP.");
break;
case TOX_ERR_BOOTSTRAP_BAD_PORT:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Bootstrap failed: Invalid port.");
break;
case TOX_ERR_BOOTSTRAP_NULL:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Bootstrap failed.");
break;
default:
break;
}
} }
void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
@ -456,8 +480,8 @@ void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
const char *swch = argv[1]; const char *swch = argv[1];
if (!strcmp(swch, "1") || !strcmp(swch, "on")) { if (!strcmp(swch, "1") || !strcmp(swch, "on")) {
char myid[TOX_FRIEND_ADDRESS_SIZE]; char myid[TOX_ADDRESS_SIZE];
tox_get_address(m, (uint8_t *) myid); tox_self_get_address(m, (uint8_t *) myid);
if (self->is_chat) { if (self->is_chat) {
Friends.list[self->num].logging_on = true; Friends.list[self->num].logging_on = true;
@ -488,13 +512,13 @@ void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
void cmd_myid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_myid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{ {
char id[TOX_FRIEND_ADDRESS_SIZE * 2 + 1] = {0}; char id[TOX_ADDRESS_SIZE * 2 + 1] = {0};
char address[TOX_FRIEND_ADDRESS_SIZE]; char address[TOX_ADDRESS_SIZE];
tox_get_address(m, (uint8_t *) address); tox_self_get_address(m, (uint8_t *) address);
size_t i; size_t i;
for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; ++i) { for (i = 0; i < TOX_ADDRESS_SIZE; ++i) {
char xx[3]; char xx[3];
snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff);
strcat(id, xx); strcat(id, xx);
@ -511,7 +535,7 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
} }
char nick[MAX_STR_SIZE]; char nick[MAX_STR_SIZE];
int len = 0; size_t len = 0;
if (argv[1][0] == '\"') { /* remove opening and closing quotes */ if (argv[1][0] == '\"') { /* remove opening and closing quotes */
snprintf(nick, sizeof(nick), "%s", &argv[1][1]); snprintf(nick, sizeof(nick), "%s", &argv[1][1]);
@ -530,11 +554,7 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1); len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
nick[len] = '\0'; nick[len] = '\0';
if (tox_set_name(m, (uint8_t *) nick, (uint16_t) len) == -1) { tox_self_set_name(m, (uint8_t *) nick, len, NULL);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Core error setting nick.");
return;
}
prompt_update_nick(prompt, nick); prompt_update_nick(prompt, nick);
set_nick_all_groups(m, nick, len); set_nick_all_groups(m, nick, len);
@ -606,31 +626,24 @@ void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
goto finish; goto finish;
} }
char status[MAX_STR_SIZE]; const char *status_str = argv[1];
snprintf(status, sizeof(status), "%s", argv[1]); TOX_USER_STATUS status;
str_to_lower(status);
TOX_USERSTATUS status_kind; if (!strcasecmp(status_str, "online"))
status = TOX_USER_STATUS_NONE;
if (!strcmp(status, "online")) else if (!strcasecmp(status_str, "away"))
status_kind = TOX_USERSTATUS_NONE; status = TOX_USER_STATUS_AWAY;
else if (!strcmp(status, "away")) else if (!strcasecmp(status_str, "busy"))
status_kind = TOX_USERSTATUS_AWAY; status = TOX_USER_STATUS_BUSY;
else if (!strcmp(status, "busy"))
status_kind = TOX_USERSTATUS_BUSY;
else { else {
errmsg = "Invalid status. Valid statuses are: online, busy and away."; errmsg = "Invalid status. Valid statuses are: online, busy and away.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
goto finish; goto finish;
} }
if (tox_set_user_status(m, status_kind) == -1) { tox_self_set_status(m, status);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Core failed to set status\n"); prompt_update_status(prompt, status);
return; set_status_all_groups(m, status);
}
set_status_all_groups(m, status_kind);
prompt_update_status(prompt, status_kind);
if (have_note) { if (have_note) {
if (argv[2][0] != '\"') { if (argv[2][0] != '\"') {

View File

@ -43,7 +43,7 @@ void cmd_quit(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]
void cmd_requests(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_requests(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_status(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_status(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_add_helper(ToxWindow *self, Tox *m, char *id_bin, char *msg); void cmd_add_helper(ToxWindow *self, Tox *m, const char *id_bin, const char *msg);
#ifdef AUDIO #ifdef AUDIO
void cmd_list_devices(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_list_devices(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);

View File

@ -284,7 +284,9 @@ static void groupchat_onGroupMessage(ToxWindow *self, Tox *m, int groupnum, int
get_group_nick_truncate(m, nick, peernum, groupnum); get_group_nick_truncate(m, nick, peernum, groupnum);
char selfnick[TOX_MAX_NAME_LENGTH]; char selfnick[TOX_MAX_NAME_LENGTH];
uint16_t sn_len = tox_group_get_self_name(m, groupnum, (uint8_t *) selfnick); tox_self_get_name(m, (uint8_t *) selfnick);
size_t sn_len = tox_self_get_name_size(m);
selfnick[sn_len] = '\0'; selfnick[sn_len] = '\0';
int nick_clr = CYAN; int nick_clr = CYAN;
@ -323,7 +325,9 @@ static void groupchat_onGroupAction(ToxWindow *self, Tox *m, int groupnum, int p
get_group_nick_truncate(m, nick, peernum, groupnum); get_group_nick_truncate(m, nick, peernum, groupnum);
char selfnick[TOX_MAX_NAME_LENGTH]; char selfnick[TOX_MAX_NAME_LENGTH];
uint16_t n_len = tox_group_get_self_name(m, groupnum, (uint8_t *) selfnick); tox_self_get_name(m, (uint8_t *) selfnick);
size_t n_len = tox_self_get_name_size(m);
selfnick[n_len] = '\0'; selfnick[n_len] = '\0';
if (strcasestr(action, selfnick)) { if (strcasestr(action, selfnick)) {
@ -782,10 +786,10 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
ctx->start = wlen < x2 ? 0 : wlen - x2 + 1; ctx->start = wlen < x2 ? 0 : wlen - x2 + 1;
} }
} else { } else {
sound_notify(self, error, 0, NULL); sound_notify(self, notif_error, 0, NULL);
} }
} else { } else {
sound_notify(self, error, 0, NULL); sound_notify(self, notif_error, 0, NULL);
} }
} else if (key == user_settings->key_peer_list_down) { /* Scroll peerlist up and down one position */ } else if (key == user_settings->key_peer_list_down) { /* Scroll peerlist up and down one position */
int L = y2 - CHATBOX_HEIGHT - SDBAR_OFST; int L = y2 - CHATBOX_HEIGHT - SDBAR_OFST;
@ -931,8 +935,8 @@ static void groupchat_onInit(ToxWindow *self, Tox *m)
line_info_init(ctx->hst); line_info_init(ctx->hst);
if (user_settings->autolog == AUTOLOG_ON) { if (user_settings->autolog == AUTOLOG_ON) {
char myid[TOX_FRIEND_ADDRESS_SIZE]; char myid[TOX_ADDRESS_SIZE];
tox_get_address(m, (uint8_t *) myid); tox_self_get_address(m, (uint8_t *) myid);
log_enable(self->name, myid, NULL, ctx->log, LOG_GROUP); log_enable(self->name, myid, NULL, ctx->log, LOG_GROUP);
} }

View File

@ -46,12 +46,12 @@ void input_new_char(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_
/* this is the only place we need to do this check */ /* this is the only place we need to do this check */
if (cur_len == -1) { if (cur_len == -1) {
sound_notify(self, error, 0, NULL); sound_notify(self, notif_error, 0, NULL);
return; return;
} }
if (add_char_to_buf(ctx, key) == -1) { if (add_char_to_buf(ctx, key) == -1) {
sound_notify(self, error, 0, NULL); sound_notify(self, notif_error, 0, NULL);
return; return;
} }
@ -67,7 +67,7 @@ static void input_backspace(ToxWindow *self, int x, int mx_x)
ChatContext *ctx = self->chatwin; ChatContext *ctx = self->chatwin;
if (del_char_buf_bck(ctx) == -1) { if (del_char_buf_bck(ctx) == -1) {
sound_notify(self, error, 0, NULL); sound_notify(self, notif_error, 0, NULL);
return; return;
} }
@ -84,7 +84,7 @@ static void input_backspace(ToxWindow *self, int x, int mx_x)
static void input_delete(ToxWindow *self) static void input_delete(ToxWindow *self)
{ {
if (del_char_buf_frnt(self->chatwin) == -1) if (del_char_buf_frnt(self->chatwin) == -1)
sound_notify(self, error, 0, NULL); sound_notify(self, notif_error, 0, NULL);
} }
/* delete last typed word */ /* delete last typed word */
@ -93,7 +93,7 @@ static void input_del_word(ToxWindow *self, int x, int mx_x)
ChatContext *ctx = self->chatwin; ChatContext *ctx = self->chatwin;
if (del_word_buf(ctx) == -1) { if (del_word_buf(ctx) == -1) {
sound_notify(self, error, 0, NULL); sound_notify(self, notif_error, 0, NULL);
return; return;
} }
} }
@ -102,14 +102,14 @@ static void input_del_word(ToxWindow *self, int x, int mx_x)
static void input_discard(ToxWindow *self) static void input_discard(ToxWindow *self)
{ {
if (discard_buf(self->chatwin) == -1) if (discard_buf(self->chatwin) == -1)
sound_notify(self, error, 0, NULL); sound_notify(self, notif_error, 0, NULL);
} }
/* deletes entire line after cursor from input field and buffer */ /* deletes entire line after cursor from input field and buffer */
static void input_kill(ChatContext *ctx) static void input_kill(ChatContext *ctx)
{ {
if (kill_buf(ctx) == -1) if (kill_buf(ctx) == -1)
sound_notify(NULL, error, NT_ALWAYS, NULL); sound_notify(NULL, notif_error, NT_ALWAYS, NULL);
} }
static void input_yank(ToxWindow *self, int x, int mx_x) static void input_yank(ToxWindow *self, int x, int mx_x)
@ -117,7 +117,7 @@ static void input_yank(ToxWindow *self, int x, int mx_x)
ChatContext *ctx = self->chatwin; ChatContext *ctx = self->chatwin;
if (yank_buf(ctx) == -1) { if (yank_buf(ctx) == -1) {
sound_notify(self, error, 0, NULL); sound_notify(self, notif_error, 0, NULL);
return; return;
} }
@ -264,7 +264,7 @@ bool input_handle(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y)
break; break;
} }
/* TODO: this special case is ugly. /* TODO: this special case is ugly.
maybe convert entire function to if/else and make them all customizable keys? */ maybe convert entire function to if/else and make them all customizable keys? */
if (!match && key == user_settings->key_toggle_peerlist) { if (!match && key == user_settings->key_toggle_peerlist) {
if (self->is_groupchat) { if (self->is_groupchat) {

View File

@ -155,11 +155,13 @@ void line_info_add(ToxWindow *self, const char *timestr, const char *name1, cons
/* for type-specific formatting in print function */ /* for type-specific formatting in print function */
switch (type) { switch (type) {
case IN_ACTION: case IN_ACTION:
/* fallthrough */
case OUT_ACTION: case OUT_ACTION:
len += strlen(user_settings->line_normal) + 2; len += strlen(user_settings->line_normal) + 2;
break; break;
case IN_MSG: case IN_MSG:
/* fallthrough */
case OUT_MSG: case OUT_MSG:
len += strlen(user_settings->line_normal) + 3; len += strlen(user_settings->line_normal) + 3;
break; break;
@ -304,7 +306,9 @@ void line_info_print(ToxWindow *self)
switch (type) { switch (type) {
case OUT_MSG: case OUT_MSG:
/* fallthrough */
case OUT_MSG_READ: case OUT_MSG_READ:
/* fallthrough */
case IN_MSG: case IN_MSG:
case IN_PRVT_MSG: case IN_PRVT_MSG:
case OUT_PRVT_MSG: case OUT_PRVT_MSG:
@ -349,7 +353,9 @@ void line_info_print(ToxWindow *self)
break; break;
case OUT_ACTION_READ: case OUT_ACTION_READ:
/* fallthrough */
case OUT_ACTION: case OUT_ACTION:
/* fallthrough */
case IN_ACTION: case IN_ACTION:
wattron(win, COLOR_PAIR(BLUE)); wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "%s ", line->timestr); wprintw(win, "%s ", line->timestr);
@ -494,14 +500,14 @@ static void line_info_scroll_up(struct history *hst)
{ {
if (hst->line_start->prev) if (hst->line_start->prev)
hst->line_start = hst->line_start->prev; hst->line_start = hst->line_start->prev;
else sound_notify(NULL, error, NT_ALWAYS, NULL); else sound_notify(NULL, notif_error, NT_ALWAYS, NULL);
} }
static void line_info_scroll_down(struct history *hst) static void line_info_scroll_down(struct history *hst)
{ {
if (hst->line_start->next) if (hst->line_start->next)
hst->line_start = hst->line_start->next; hst->line_start = hst->line_start->next;
else sound_notify(NULL, error, NT_ALWAYS, NULL); else sound_notify(NULL, notif_error, NT_ALWAYS, NULL);
} }
static void line_info_page_up(ToxWindow *self, struct history *hst) static void line_info_page_up(ToxWindow *self, struct history *hst)

View File

@ -42,7 +42,7 @@ void cqueue_cleanup(struct chat_queue *q)
free(q); free(q);
} }
void cqueue_add(struct chat_queue *q, const char *msg, int len, uint8_t type, uint32_t line_id) void cqueue_add(struct chat_queue *q, const char *msg, size_t len, uint8_t type, uint32_t line_id)
{ {
struct cqueue_msg *new_m = malloc(sizeof(struct cqueue_msg)); struct cqueue_msg *new_m = malloc(sizeof(struct cqueue_msg));
@ -103,7 +103,9 @@ void cqueue_remove(ToxWindow *self, Tox *m, uint32_t receipt)
} }
char selfname[TOX_MAX_NAME_LENGTH]; char selfname[TOX_MAX_NAME_LENGTH];
uint16_t len = tox_get_self_name(m, (uint8_t *) selfname); tox_self_get_name(m, (uint8_t *) selfname);
size_t len = tox_self_get_name_size(m);
selfname[len] = '\0'; selfname[len] = '\0';
write_to_log(msg->message, selfname, self->chatwin->log, msg->type == OUT_ACTION); write_to_log(msg->message, selfname, self->chatwin->log, msg->type == OUT_ACTION);
@ -145,10 +147,8 @@ void cqueue_try_send(ToxWindow *self, Tox *m)
uint32_t receipt = 0; uint32_t receipt = 0;
if (msg->type == OUT_MSG) TOX_MESSAGE_TYPE type = msg->type == OUT_MSG ? TOX_MESSAGE_TYPE_NORMAL : TOX_MESSAGE_TYPE_ACTION;
receipt = tox_send_message(m, self->num, (uint8_t *) msg->message, msg->len); receipt = tox_friend_send_message(m, self->num, type, (uint8_t *) msg->message, msg->len, NULL);
else
receipt = tox_send_action(m, self->num, (uint8_t *) msg->message, msg->len);
msg->last_send_try = curtime; msg->last_send_try = curtime;
msg->receipt = receipt; msg->receipt = receipt;

View File

@ -25,7 +25,7 @@
struct cqueue_msg { struct cqueue_msg {
char message[MAX_STR_SIZE]; char message[MAX_STR_SIZE];
int len; size_t len;
int line_id; int line_id;
uint8_t type; uint8_t type;
uint32_t receipt; uint32_t receipt;
@ -40,7 +40,7 @@ struct chat_queue {
}; };
void cqueue_cleanup(struct chat_queue *q); void cqueue_cleanup(struct chat_queue *q);
void cqueue_add(struct chat_queue *q, const char *msg, int len, uint8_t type, uint32_t line_id); void cqueue_add(struct chat_queue *q, const char *msg, size_t len, uint8_t type, uint32_t line_id);
/* Tries to send the oldest unsent message in queue. */ /* Tries to send the oldest unsent message in queue. */
void cqueue_try_send(ToxWindow *self, Tox *m); void cqueue_try_send(ToxWindow *self, Tox *m);
@ -48,4 +48,4 @@ void cqueue_try_send(ToxWindow *self, Tox *m);
/* removes message with matching receipt from queue, writes to log and updates line to show the message was received. */ /* removes message with matching receipt from queue, writes to log and updates line to show the message was received. */
void cqueue_remove(ToxWindow *self, Tox *m, uint32_t receipt); void cqueue_remove(ToxWindow *self, Tox *m, uint32_t receipt);
#endif /* #define MESSAGE_QUEUE_H */ #endif /* #define MESSAGE_QUEUE_H */

View File

@ -32,7 +32,7 @@
#include "windows.h" #include "windows.h"
#include "misc_tools.h" #include "misc_tools.h"
#include "settings.h" #include "settings.h"
#include "file_senders.h" #include "file_transfers.h"
extern ToxWindow *prompt; extern ToxWindow *prompt;
extern struct user_settings *user_settings; extern struct user_settings *user_settings;
@ -212,9 +212,9 @@ int valid_nick(const char *nick)
} }
/* Converts all newline/tab chars to spaces (use for strings that should be contained to a single line) */ /* Converts all newline/tab chars to spaces (use for strings that should be contained to a single line) */
void filter_str(char *str, int len) void filter_str(char *str, size_t len)
{ {
int i; size_t i;
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
if (str[i] == '\n' || str[i] == '\r' || str[i] == '\t' || str[i] == '\v') if (str[i] == '\n' || str[i] == '\r' || str[i] == '\t' || str[i] == '\v')
@ -222,17 +222,19 @@ void filter_str(char *str, int len)
} }
} }
/* gets base file name from path or original file name if no path is supplied */ /* gets base file name from path or original file name if no path is supplied.
void get_file_name(char *namebuf, int bufsize, const char *pathname) * Returns the file name length
*/
size_t get_file_name(char *namebuf, size_t bufsize, const char *pathname)
{ {
int idx = strlen(pathname) - 1; int len = strlen(pathname) - 1;
char *path = strdup(pathname); char *path = strdup(pathname);
if (path == NULL) if (path == NULL)
exit_toxic_err("failed in get_file_name", FATALERR_MEMORY); exit_toxic_err("failed in get_file_name", FATALERR_MEMORY);
while (idx >= 0 && pathname[idx] == '/') while (len >= 0 && pathname[len] == '/')
path[idx--] = '\0'; path[len--] = '\0';
char *finalname = strdup(path); char *finalname = strdup(path);
@ -249,6 +251,8 @@ void get_file_name(char *namebuf, int bufsize, const char *pathname)
snprintf(namebuf, bufsize, "%s", finalname); snprintf(namebuf, bufsize, "%s", finalname);
free(finalname); free(finalname);
free(path); free(path);
return strlen(namebuf);
} }
/* converts str to all lowercase */ /* converts str to all lowercase */
@ -263,13 +267,15 @@ void str_to_lower(char *str)
/* puts friendnum's nick in buf, truncating at TOXIC_MAX_NAME_LENGTH if necessary. /* puts friendnum's nick in buf, truncating at TOXIC_MAX_NAME_LENGTH if necessary.
if toxcore API call fails, put UNKNOWN_NAME in buf if toxcore API call fails, put UNKNOWN_NAME in buf
Returns nick len */ Returns nick len */
int get_nick_truncate(Tox *m, char *buf, int friendnum) size_t get_nick_truncate(Tox *m, char *buf, uint32_t friendnum)
{ {
int len = tox_get_name(m, friendnum, (uint8_t *) buf); size_t len = tox_friend_get_name_size(m, friendnum, NULL);
if (len == -1) { if (len == 0) {
strcpy(buf, UNKNOWN_NAME); strcpy(buf, UNKNOWN_NAME);
len = strlen(UNKNOWN_NAME); len = strlen(UNKNOWN_NAME);
} else {
tox_friend_get_name(m, friendnum, (uint8_t *) buf, NULL);
} }
len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1); len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
@ -297,7 +303,7 @@ int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum)
/* copies data to msg buffer. /* copies data to msg buffer.
returns length of msg. returns length of msg.
returns 0 and nulls msg if length is too big for buffer size */ returns 0 and nulls msg if length is too big for buffer size */
uint16_t copy_tox_str(char *msg, size_t size, const char *data, uint16_t length) size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length)
{ {
if (length > size - 1) { if (length > size - 1) {
msg[0] = '\0'; msg[0] = '\0';
@ -366,13 +372,13 @@ bool file_exists(const char *path)
return stat(path, &s) == 0; return stat(path, &s) == 0;
} }
/* returns file size or -1 on error */ /* returns file size. If file doesn't exist returns 0. */
off_t file_size(const char *path) off_t file_size(const char *path)
{ {
struct stat st; struct stat st;
if (stat(path, &st) == -1) if (stat(path, &st) == -1)
return -1; return 0;
return st.st_size; return st.st_size;
} }

View File

@ -92,17 +92,17 @@ int qsort_strcasecmp_hlpr(const void *str1, const void *str2);
int valid_nick(const char *nick); int valid_nick(const char *nick);
/* Converts all newline/tab chars to spaces (use for strings that should be contained to a single line) */ /* Converts all newline/tab chars to spaces (use for strings that should be contained to a single line) */
void filter_str(char *str, int len); void filter_str(char *str, size_t len);
/* gets base file name from path or original file name if no path is supplied */ /* gets base file name from path or original file name if no path is supplied */
void get_file_name(char *namebuf, int bufsize, const char *pathname); size_t get_file_name(char *namebuf, size_t bufsize, const char *pathname);
/* converts str to all lowercase */ /* converts str to all lowercase */
void str_to_lower(char *str); void str_to_lower(char *str);
/* puts friendnum's nick in buf, truncating at TOXIC_MAX_NAME_LENGTH if necessary. /* puts friendnum's nick in buf, truncating at TOXIC_MAX_NAME_LENGTH if necessary.
Returns nick len on success, -1 on failure */ Returns nick len on success, -1 on failure */
int get_nick_truncate(Tox *m, char *buf, int friendnum); size_t get_nick_truncate(Tox *m, char *buf, uint32_t friendnum);
/* same as get_nick_truncate but for groupchats */ /* same as get_nick_truncate but for groupchats */
int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum); int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum);
@ -110,7 +110,7 @@ int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum);
/* copies data to msg buffer. /* copies data to msg buffer.
returns length of msg. returns length of msg.
returns 0 and nulls msg if length is too big for buffer size */ returns 0 and nulls msg if length is too big for buffer size */
uint16_t copy_tox_str(char *msg, size_t size, const char *data, uint16_t length); size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length);
/* returns index of the first instance of ch in s starting at idx. /* returns index of the first instance of ch in s starting at idx.
returns length of s if char not found */ returns length of s if char not found */
@ -126,7 +126,7 @@ void bytes_convert_str(char *buf, int size, uint64_t bytes);
/* checks if a file exists. Returns true or false */ /* checks if a file exists. Returns true or false */
bool file_exists(const char *path); bool file_exists(const char *path);
/* returns file size or -1 on error */ /* returns file size. If file doesn't exist returns 0. */
off_t file_size(const char *path); off_t file_size(const char *path);
/* compares the first size bytes of fp and signature. /* compares the first size bytes of fp and signature.

View File

@ -1,5 +1,5 @@
/* notify.c /* notify.c
* *
* *
* Copyright (C) 2014 Toxic All Rights Reserved. * Copyright (C) 2014 Toxic All Rights Reserved.
* *
@ -67,12 +67,12 @@ extern struct user_settings *user_settings;
struct Control { struct Control {
time_t cooldown; time_t cooldown;
time_t notif_timeout; time_t notif_timeout;
#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY) #if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY)
pthread_mutex_t poll_mutex[1]; pthread_mutex_t poll_mutex[1];
bool poll_active; bool poll_active;
#endif #endif
#ifdef SOUND_NOTIFY #ifdef SOUND_NOTIFY
uint32_t device_idx; /* index of output device */ uint32_t device_idx; /* index of output device */
char* sounds[SOUNDS_SIZE]; char* sounds[SOUNDS_SIZE];
@ -107,11 +107,11 @@ static void tab_notify(ToxWindow *self, uint64_t flags)
if (self == NULL) if (self == NULL)
return; return;
if (flags & NT_WNDALERT_0) if (flags & NT_WNDALERT_0)
self->alert = WINDOW_ALERT_0; self->alert = WINDOW_ALERT_0;
else if ( (flags & NT_WNDALERT_1) && (!self->alert || self->alert > WINDOW_ALERT_0) ) else if ( (flags & NT_WNDALERT_1) && (!self->alert || self->alert > WINDOW_ALERT_0) )
self->alert = WINDOW_ALERT_1; self->alert = WINDOW_ALERT_1;
else if ( (flags & NT_WNDALERT_2) && (!self->alert || self->alert > WINDOW_ALERT_1) ) else if ( (flags & NT_WNDALERT_2) && (!self->alert || self->alert > WINDOW_ALERT_1) )
self->alert = WINDOW_ALERT_2; self->alert = WINDOW_ALERT_2;
} }
@ -154,14 +154,14 @@ static bool device_opened = false;
time_t last_opened_update = 0; time_t last_opened_update = 0;
bool m_open_device() bool m_open_device()
{ {
last_opened_update = get_unix_time(); last_opened_update = get_unix_time();
if (device_opened) return true; if (device_opened) return true;
/* Blah error check */ /* Blah error check */
open_primary_device(output, &Control.device_idx, 48000, 20, 1); open_primary_device(output, &Control.device_idx, 48000, 20, 1);
return (device_opened = true); return (device_opened = true);
} }
@ -194,9 +194,9 @@ void graceful_clear()
*actives[i].id_indicator = -1; /* reset indicator value */ *actives[i].id_indicator = -1; /* reset indicator value */
if ( actives[i].looping ) { if ( actives[i].looping ) {
stop_sound(i); stop_sound(i);
} else { } else {
if (!is_playing(actives[i].source)) if (!is_playing(actives[i].source))
memset(&actives[i], 0, sizeof(struct _ActiveNotifications)); memset(&actives[i], 0, sizeof(struct _ActiveNotifications));
else break; else break;
} }
@ -217,17 +217,17 @@ void* do_playing(void* _p)
{ {
(void)_p; (void)_p;
int i; int i;
bool has_looping = false; bool has_looping = false;
while(Control.poll_active) { while(Control.poll_active) {
control_lock(); control_lock();
for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) { for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) {
if (actives[i].looping) has_looping = true; if (actives[i].looping) has_looping = true;
if (actives[i].active && !actives[i].looping if (actives[i].active && !actives[i].looping
#ifdef BOX_NOTIFY #ifdef BOX_NOTIFY
&& !actives[i].box && !actives[i].box
@ -237,7 +237,7 @@ void* do_playing(void* _p)
*actives[i].id_indicator = -1; /* reset indicator value */ *actives[i].id_indicator = -1; /* reset indicator value */
if (!is_playing(actives[i].source)) { if (!is_playing(actives[i].source)) {
/* Close */ /* Close */
alSourceStop(actives[i].source); alSourceStop(actives[i].source);
alDeleteSources(1, &actives[i].source); alDeleteSources(1, &actives[i].source);
alDeleteBuffers(1, &actives[i].buffer); alDeleteBuffers(1, &actives[i].buffer);
@ -263,14 +263,14 @@ void* do_playing(void* _p)
} }
#endif #endif
} }
/* device is opened and no activity in under DEVICE_COOLDOWN time, close device*/ /* device is opened and no activity in under DEVICE_COOLDOWN time, close device*/
if (device_opened && !has_looping && if (device_opened && !has_looping &&
(get_unix_time() - last_opened_update) > DEVICE_COOLDOWN) { (get_unix_time() - last_opened_update) > DEVICE_COOLDOWN) {
m_close_device(); m_close_device();
} }
has_looping = false; has_looping = false;
control_unlock(); control_unlock();
usleep(10000); usleep(10000);
} }
@ -278,20 +278,20 @@ void* do_playing(void* _p)
} }
int play_source(uint32_t source, uint32_t buffer, bool looping) int play_source(uint32_t source, uint32_t buffer, bool looping)
{ {
int i = 0; int i = 0;
for (; i < ACTIVE_NOTIFS_MAX && actives[i].active; i ++); for (; i < ACTIVE_NOTIFS_MAX && actives[i].active; i ++);
if ( i == ACTIVE_NOTIFS_MAX ) { if ( i == ACTIVE_NOTIFS_MAX ) {
return -1; /* Full */ return -1; /* Full */
} }
alSourcePlay(source); alSourcePlay(source);
actives[i].active = 1; actives[i].active = 1;
actives[i].source = source; actives[i].source = source;
actives[i].buffer = buffer; actives[i].buffer = buffer;
actives[i].looping = looping; actives[i].looping = looping;
return i; return i;
} }
@ -324,20 +324,20 @@ void graceful_clear()
{ {
int i; int i;
control_lock(); control_lock();
for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) { for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) {
if (actives[i].box) { if (actives[i].box) {
GError* ignore; GError* ignore;
notify_notification_close(actives[i].box, &ignore); notify_notification_close(actives[i].box, &ignore);
actives[i].box = NULL; actives[i].box = NULL;
} }
if (actives[i].id_indicator) if (actives[i].id_indicator)
*actives[i].id_indicator = -1; /* reset indicator value */ *actives[i].id_indicator = -1; /* reset indicator value */
memset(&actives[i], 0, sizeof(struct _ActiveNotifications)); memset(&actives[i], 0, sizeof(struct _ActiveNotifications));
} }
control_unlock(); control_unlock();
} }
#endif #endif
@ -356,7 +356,7 @@ int init_notify(int login_cooldown, int notification_timeout)
#ifdef SOUND_NOTIFY #ifdef SOUND_NOTIFY
alutInitWithoutContext(NULL, NULL); alutInitWithoutContext(NULL, NULL);
#endif /* SOUND_NOTIFY */ #endif /* SOUND_NOTIFY */
#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY) #if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY)
if (pthread_mutex_init(Control.poll_mutex, NULL) != 0) if (pthread_mutex_init(Control.poll_mutex, NULL) != 0)
return -1; return -1;
@ -371,8 +371,8 @@ int init_notify(int login_cooldown, int notification_timeout)
Control.poll_active = 1; Control.poll_active = 1;
#endif #endif
Control.cooldown = get_unix_time() + login_cooldown; Control.cooldown = get_unix_time() + login_cooldown;
#ifdef BOX_NOTIFY #ifdef BOX_NOTIFY
notify_init("Toxic"); notify_init("Toxic");
#endif #endif
@ -381,11 +381,11 @@ int init_notify(int login_cooldown, int notification_timeout)
} }
void terminate_notify() void terminate_notify()
{ {
#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY) #if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY)
if ( !Control.poll_active ) return; if ( !Control.poll_active ) return;
Control.poll_active = 0; Control.poll_active = 0;
graceful_clear(); graceful_clear();
#endif #endif
@ -394,7 +394,7 @@ void terminate_notify()
for (; i < SOUNDS_SIZE; i ++) free(Control.sounds[i]); for (; i < SOUNDS_SIZE; i ++) free(Control.sounds[i]);
alutExit(); alutExit();
#endif /* SOUND_NOTIFY */ #endif /* SOUND_NOTIFY */
#ifdef BOX_NOTIFY #ifdef BOX_NOTIFY
notify_uninit(); notify_uninit();
#endif #endif
@ -404,7 +404,7 @@ void terminate_notify()
int set_sound(Notification sound, const char* value) int set_sound(Notification sound, const char* value)
{ {
if (sound == silent) return 0; if (sound == silent) return 0;
free(Control.sounds[sound]); free(Control.sounds[sound]);
size_t len = strlen(value) + 1; size_t len = strlen(value) + 1;
@ -416,18 +416,18 @@ int set_sound(Notification sound, const char* value)
} }
int play_sound_internal(Notification what, bool loop) int play_sound_internal(Notification what, bool loop)
{ {
uint32_t source; uint32_t source;
uint32_t buffer; uint32_t buffer;
m_open_device(); m_open_device();
alGenSources(1, &source); alGenSources(1, &source);
alGenBuffers(1, &buffer); alGenBuffers(1, &buffer);
buffer = alutCreateBufferFromFile(Control.sounds[what]); buffer = alutCreateBufferFromFile(Control.sounds[what]);
alSourcei(source, AL_BUFFER, buffer); alSourcei(source, AL_BUFFER, buffer);
alSourcei(source, AL_LOOPING, loop); alSourcei(source, AL_LOOPING, loop);
int rc = play_source(source, buffer, loop); int rc = play_source(source, buffer, loop);
if (rc < 0) { if (rc < 0) {
alSourceStop(source); alSourceStop(source);
@ -435,7 +435,7 @@ int play_sound_internal(Notification what, bool loop)
alDeleteBuffers(1,&buffer); alDeleteBuffers(1,&buffer);
return -1; return -1;
} }
return rc; return rc;
} }
@ -464,7 +464,7 @@ void stop_sound(int id)
notify_notification_close(actives[id].box, &ignore); notify_notification_close(actives[id].box, &ignore);
} }
#endif #endif
if (actives[id].id_indicator) if (actives[id].id_indicator)
*actives[id].id_indicator = -1; *actives[id].id_indicator = -1;
// alSourcei(actives[id].source, AL_LOOPING, false); // alSourcei(actives[id].source, AL_LOOPING, false);
alSourceStop(actives[id].source); alSourceStop(actives[id].source);
@ -484,11 +484,11 @@ static int m_play_sound(Notification notif, uint64_t flags)
beep(); beep();
return -1; return -1;
#endif /* SOUND_NOTIFY */ #endif /* SOUND_NOTIFY */
} }
#ifdef BOX_NOTIFY #ifdef BOX_NOTIFY
void m_notify_action(NotifyNotification *box, char *action, void* data) void m_notify_action(NotifyNotification *box, char *action, void* data)
{ {
} }
#endif #endif
@ -503,7 +503,7 @@ int sound_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_in
int id = -1; int id = -1;
control_lock(); control_lock();
if (self && (!self->stb || self->stb->status != TOX_USERSTATUS_BUSY) && user_settings->alerts == ALERTS_ENABLED) if (self && (!self->stb || self->stb->status != TOX_USER_STATUS_BUSY) && user_settings->alerts == ALERTS_ENABLED)
id = m_play_sound(notif, flags); id = m_play_sound(notif, flags);
else if (flags & NT_ALWAYS) else if (flags & NT_ALWAYS)
id = m_play_sound(notif, flags); id = m_play_sound(notif, flags);
@ -520,7 +520,7 @@ int sound_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_in
#endif #endif
if ( id_indicator && id != -1 ) { if ( id_indicator && id != -1 ) {
actives[id].id_indicator = id_indicator; actives[id].id_indicator = id_indicator;
*id_indicator = id; *id_indicator = id;
} }
@ -533,46 +533,46 @@ int sound_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_in
int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id) int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id)
{ {
tab_notify(self, flags); tab_notify(self, flags);
if (notifications_are_disabled(flags)) if (notifications_are_disabled(flags))
return -1; return -1;
if (id < 0 || id >= ACTIVE_NOTIFS_MAX) return -1; if (id < 0 || id >= ACTIVE_NOTIFS_MAX) return -1;
#ifdef SOUND_NOTIFY #ifdef SOUND_NOTIFY
control_lock(); control_lock();
if (!actives[id].active || !Control.sounds[notif]) { if (!actives[id].active || !Control.sounds[notif]) {
control_unlock(); control_unlock();
return -1; return -1;
} }
m_open_device(); m_open_device();
alSourceStop(actives[id].source); alSourceStop(actives[id].source);
alDeleteSources(1, &actives[id].source); alDeleteSources(1, &actives[id].source);
alDeleteBuffers(1,&actives[id].buffer); alDeleteBuffers(1,&actives[id].buffer);
alGenSources(1, &actives[id].source); alGenSources(1, &actives[id].source);
alGenBuffers(1, &actives[id].buffer); alGenBuffers(1, &actives[id].buffer);
actives[id].buffer = alutCreateBufferFromFile(Control.sounds[notif]); actives[id].buffer = alutCreateBufferFromFile(Control.sounds[notif]);
alSourcei(actives[id].source, AL_BUFFER, actives[id].buffer); alSourcei(actives[id].source, AL_BUFFER, actives[id].buffer);
alSourcei(actives[id].source, AL_LOOPING, flags & NT_LOOP); alSourcei(actives[id].source, AL_LOOPING, flags & NT_LOOP);
alSourcePlay(actives[id].source); alSourcePlay(actives[id].source);
control_unlock(); control_unlock();
return id; return id;
#else #else
if (notif != silent) if (notif != silent)
beep(); beep();
return 0; return 0;
#endif /* SOUND_NOTIFY */ #endif /* SOUND_NOTIFY */
} }
int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator, char* title, const char* format, ...) int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator, const char* title, const char* format, ...)
{ {
if (notifications_are_disabled(flags)) { if (notifications_are_disabled(flags)) {
tab_notify(self, flags); tab_notify(self, flags);
@ -594,7 +594,7 @@ int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indi
return -1; /* Full */ return -1; /* Full */
} }
actives[id].active = 1; actives[id].active = 1;
actives[id].id_indicator = id_indicator; actives[id].id_indicator = id_indicator;
if (id_indicator) *id_indicator = id; if (id_indicator) *id_indicator = id;
} }
@ -607,13 +607,13 @@ int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indi
vsnprintf (actives[id].messages[0], MAX_BOX_MSG_LEN, format, __ARGS__); vsnprintf (actives[id].messages[0], MAX_BOX_MSG_LEN, format, __ARGS__);
va_end (__ARGS__); va_end (__ARGS__);
if (strlen(actives[id].messages[0]) > MAX_BOX_MSG_LEN - 3) if (strlen(actives[id].messages[0]) > MAX_BOX_MSG_LEN - 3)
strcpy(actives[id].messages[0] + MAX_BOX_MSG_LEN - 3, "..."); strcpy(actives[id].messages[0] + MAX_BOX_MSG_LEN - 3, "...");
actives[id].box = notify_notification_new(actives[id].title, actives[id].messages[0], NULL); actives[id].box = notify_notification_new(actives[id].title, actives[id].messages[0], NULL);
actives[id].size++; actives[id].size++;
actives[id].n_timeout = get_unix_time() + Control.notif_timeout / 1000; actives[id].n_timeout = get_unix_time() + Control.notif_timeout / 1000;
notify_notification_set_timeout(actives[id].box, Control.notif_timeout); notify_notification_set_timeout(actives[id].box, Control.notif_timeout);
notify_notification_set_app_name(actives[id].box, "toxic"); notify_notification_set_app_name(actives[id].box, "toxic");
/*notify_notification_add_action(actives[id].box, "lel", "default", m_notify_action, self, NULL);*/ /*notify_notification_add_action(actives[id].box, "lel", "default", m_notify_action, self, NULL);*/
@ -687,7 +687,7 @@ int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const
control_lock(); control_lock();
int id; int id;
for (id = 0; id < ACTIVE_NOTIFS_MAX && actives[id].active; id ++); for (id = 0; id < ACTIVE_NOTIFS_MAX && actives[id].active; id ++);
if ( id == ACTIVE_NOTIFS_MAX ) { if ( id == ACTIVE_NOTIFS_MAX ) {
control_unlock(); control_unlock();
@ -706,7 +706,7 @@ int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const
vsnprintf (actives[id].messages[0], MAX_BOX_MSG_LEN, format, __ARGS__); vsnprintf (actives[id].messages[0], MAX_BOX_MSG_LEN, format, __ARGS__);
va_end (__ARGS__); va_end (__ARGS__);
if (strlen(actives[id].messages[0]) > MAX_BOX_MSG_LEN - 3) if (strlen(actives[id].messages[0]) > MAX_BOX_MSG_LEN - 3)
strcpy(actives[id].messages[0] + MAX_BOX_MSG_LEN - 3, "..."); strcpy(actives[id].messages[0] + MAX_BOX_MSG_LEN - 3, "...");
actives[id].active = 1; actives[id].active = 1;

View File

@ -1,5 +1,5 @@
/* notify.h /* notify.h
* *
* *
* Copyright (C) 2014 Toxic All Rights Reserved. * Copyright (C) 2014 Toxic All Rights Reserved.
* *
@ -29,7 +29,7 @@
typedef enum _Notification typedef enum _Notification
{ {
silent = -1, silent = -1,
error, notif_error,
self_log_in, self_log_in,
self_log_out, self_log_out,
user_log_in, user_log_in,
@ -49,14 +49,14 @@ typedef enum _Flags {
NT_LOOP = 1 << 2, /* Loop sound. If this setting active, notify() will return id of the sound NT_LOOP = 1 << 2, /* Loop sound. If this setting active, notify() will return id of the sound
* so it could be stopped. It will return 0 if error or NT_NATIVE flag is set and play \a instead * so it could be stopped. It will return 0 if error or NT_NATIVE flag is set and play \a instead
*/ */
NT_RESTOL = 1 << 3, /* Respect tolerance. Usually used to stop flood at toxic startup NT_RESTOL = 1 << 3, /* Respect tolerance. Usually used to stop flood at toxic startup
* Only works if login_cooldown is true when calling init_notify() * Only works if login_cooldown is true when calling init_notify()
*/ */
NT_NOTIFWND = 1 << 4, /* Pop notify window. NOTE: only works(/WILL WORK) if libnotify is present */ NT_NOTIFWND = 1 << 4, /* Pop notify window. NOTE: only works(/WILL WORK) if libnotify is present */
NT_WNDALERT_0 = 1 << 5, /* Alert toxic */ NT_WNDALERT_0 = 1 << 5, /* Alert toxic */
NT_WNDALERT_1 = 1 << 6, /* Alert toxic */ NT_WNDALERT_1 = 1 << 6, /* Alert toxic */
NT_WNDALERT_2 = 1 << 7, /* Alert toxic */ NT_WNDALERT_2 = 1 << 7, /* Alert toxic */
NT_ALWAYS = 1 << 8, /* Force sound to play */ NT_ALWAYS = 1 << 8, /* Force sound to play */
} Flags; } Flags;
@ -68,7 +68,7 @@ int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id);
void stop_sound(int id); void stop_sound(int id);
int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator, char* title, const char* format, ...); int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator, const char* title, const char* format, ...);
int box_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id, const char* format, ...); int box_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id, const char* format, ...);
int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const char* title, const char* format, ...); int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const char* title, const char* format, ...);
int box_silent_notify2(ToxWindow* self, uint64_t flags, int id, const char* format, ...); int box_silent_notify2(ToxWindow* self, uint64_t flags, int id, const char* format, ...);

View File

@ -102,6 +102,13 @@ void kill_prompt_window(ToxWindow *self)
del_window(self); del_window(self);
} }
/* callback: Updates own connection status in prompt statusbar */
void prompt_onSelfConnectionChange(Tox *m, TOX_CONNECTION connection_status, void *userdata)
{
StatusBar *statusbar = prompt->stb;
statusbar->connection = connection_status;
}
/* Updates own nick in prompt statusbar */ /* Updates own nick in prompt statusbar */
void prompt_update_nick(ToxWindow *prompt, const char *nick) void prompt_update_nick(ToxWindow *prompt, const char *nick)
{ {
@ -115,25 +122,23 @@ void prompt_update_statusmessage(ToxWindow *prompt, Tox *m, const char *statusms
{ {
StatusBar *statusbar = prompt->stb; StatusBar *statusbar = prompt->stb;
snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg); snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg);
int len = strlen(statusbar->statusmsg); size_t len = strlen(statusbar->statusmsg);
statusbar->statusmsg_len = len; statusbar->statusmsg_len = len;
tox_set_status_message(m, (uint8_t *) statusmsg, (uint64_t) len);
TOX_ERR_SET_INFO err;
tox_self_set_status_message(m, (uint8_t *) statusmsg, len, &err);
if (err != TOX_ERR_SET_INFO_OK)
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set note (error %d)\n", err);
} }
/* Updates own status in prompt statusbar */ /* Updates own status in prompt statusbar */
void prompt_update_status(ToxWindow *prompt, uint8_t status) void prompt_update_status(ToxWindow *prompt, TOX_USER_STATUS status)
{ {
StatusBar *statusbar = prompt->stb; StatusBar *statusbar = prompt->stb;
statusbar->status = status; statusbar->status = status;
} }
/* Updates own connection status in prompt statusbar */
void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected)
{
StatusBar *statusbar = prompt->stb;
statusbar->is_online = is_connected;
}
/* Adds friend request to pending friend requests. /* Adds friend request to pending friend requests.
Returns request number on success, -1 if queue is full. */ Returns request number on success, -1 if queue is full. */
static int add_friend_request(const char *public_key, const char *data) static int add_friend_request(const char *public_key, const char *data)
@ -210,10 +215,10 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
ctx->start = wlen < x2 ? 0 : wlen - x2 + 1; ctx->start = wlen < x2 ? 0 : wlen - x2 + 1;
} }
} else { } else {
sound_notify(self, error, 0, NULL); sound_notify(self, notif_error, 0, NULL);
} }
} else { } else {
sound_notify(self, error, 0, NULL); sound_notify(self, notif_error, 0, NULL);
} }
} else if (key == '\n') { } else if (key == '\n') {
rm_trailing_spaces_buf(ctx); rm_trailing_spaces_buf(ctx);
@ -254,30 +259,23 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
mvwhline(statusbar->topline, 1, 0, ACS_HLINE, x2); mvwhline(statusbar->topline, 1, 0, ACS_HLINE, x2);
wmove(statusbar->topline, 0, 0); wmove(statusbar->topline, 0, 0);
if (statusbar->is_online) { if (statusbar->connection != TOX_CONNECTION_NONE) {
int colour = WHITE; int colour = MAGENTA;
const char *status_text = "Unknown"; const char *status_text = "ERROR";
switch (statusbar->status) { switch (statusbar->status) {
case TOX_USERSTATUS_NONE: case TOX_USER_STATUS_NONE:
status_text = "Online"; status_text = "Online";
colour = GREEN; colour = GREEN;
break; break;
case TOX_USER_STATUS_AWAY:
case TOX_USERSTATUS_AWAY:
status_text = "Away"; status_text = "Away";
colour = YELLOW; colour = YELLOW;
break; break;
case TOX_USER_STATUS_BUSY:
case TOX_USERSTATUS_BUSY:
status_text = "Busy"; status_text = "Busy";
colour = RED; colour = RED;
break; break;
case TOX_USERSTATUS_INVALID:
status_text = "ERROR";
colour = MAGENTA;
break;
} }
wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD); wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
@ -296,10 +294,10 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
/* Reset statusbar->statusmsg on window resize */ /* Reset statusbar->statusmsg on window resize */
if (x2 != self->x) { if (x2 != self->x) {
char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {0}; char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH];
pthread_mutex_lock(&Winthread.lock); pthread_mutex_lock(&Winthread.lock);
tox_get_self_status_message(m, (uint8_t *) statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH); tox_self_get_status_message(m, (uint8_t *) statusmsg);
pthread_mutex_unlock(&Winthread.lock); pthread_mutex_unlock(&Winthread.lock);
snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg); snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg);
@ -335,11 +333,8 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
help_onDraw(self); help_onDraw(self);
} }
static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum , uint8_t status) static void prompt_onConnectionChange(ToxWindow *self, Tox *m, uint32_t friendnum , TOX_CONNECTION connection_status)
{ {
if (friendnum < 0)
return;
ChatContext *ctx = self->chatwin; ChatContext *ctx = self->chatwin;
char nick[TOX_MAX_NAME_LENGTH] = {0}; /* stop removing this initiation */ char nick[TOX_MAX_NAME_LENGTH] = {0}; /* stop removing this initiation */
@ -352,7 +347,7 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum
get_time_str(timefrmt, sizeof(timefrmt)); get_time_str(timefrmt, sizeof(timefrmt));
const char *msg; const char *msg;
if (status == 1) { if (connection_status != TOX_CONNECTION_NONE) {
msg = "has come online"; msg = "has come online";
line_info_add(self, timefrmt, nick, NULL, CONNECTION, 0, GREEN, msg); line_info_add(self, timefrmt, nick, NULL, CONNECTION, 0, GREEN, msg);
write_to_log(msg, nick, ctx->log, true); write_to_log(msg, nick, ctx->log, true);
@ -377,7 +372,7 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum
} }
} }
static void prompt_onFriendRequest(ToxWindow *self, Tox *m, const char *key, const char *data, uint16_t length) static void prompt_onFriendRequest(ToxWindow *self, Tox *m, const char *key, const char *data, size_t length)
{ {
ChatContext *ctx = self->chatwin; ChatContext *ctx = self->chatwin;
@ -407,15 +402,19 @@ void prompt_init_statusbar(ToxWindow *self, Tox *m)
/* Init statusbar info */ /* Init statusbar info */
StatusBar *statusbar = self->stb; StatusBar *statusbar = self->stb;
statusbar->status = TOX_USERSTATUS_NONE; statusbar->status = TOX_USER_STATUS_NONE;
statusbar->is_online = false; statusbar->connection = TOX_CONNECTION_NONE;
char nick[TOX_MAX_NAME_LENGTH]; char nick[TOX_MAX_NAME_LENGTH];
char statusmsg[MAX_STR_SIZE]; char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH];
uint16_t n_len = tox_get_self_name(m, (uint8_t *) nick); size_t n_len = tox_self_get_name_size(m);
uint16_t s_len = tox_get_self_status_message(m, (uint8_t *) statusmsg, MAX_STR_SIZE); tox_self_get_name(m, (uint8_t *) nick);
uint8_t status = tox_get_self_user_status(m);
size_t s_len = tox_self_get_status_message_size(m);
tox_self_get_status_message(m, (uint8_t *) statusmsg);
TOX_USER_STATUS status = tox_self_get_status(m);
nick[n_len] = '\0'; nick[n_len] = '\0';
statusmsg[s_len] = '\0'; statusmsg[s_len] = '\0';
@ -469,8 +468,8 @@ static void prompt_onInit(ToxWindow *self, Tox *m)
line_info_init(ctx->hst); line_info_init(ctx->hst);
if (user_settings->autolog == AUTOLOG_ON) { if (user_settings->autolog == AUTOLOG_ON) {
char myid[TOX_FRIEND_ADDRESS_SIZE]; char myid[TOX_ADDRESS_SIZE];
tox_get_address(m, (uint8_t *) myid); tox_self_get_address(m, (uint8_t *) myid);
log_enable(self->name, myid, NULL, ctx->log, LOG_PROMPT); log_enable(self->name, myid, NULL, ctx->log, LOG_PROMPT);
} }

View File

@ -45,8 +45,11 @@ void prep_prompt_win(void);
void prompt_init_statusbar(ToxWindow *self, Tox *m); void prompt_init_statusbar(ToxWindow *self, Tox *m);
void prompt_update_nick(ToxWindow *prompt, const char *nick); void prompt_update_nick(ToxWindow *prompt, const char *nick);
void prompt_update_statusmessage(ToxWindow *prompt, Tox *m, const char *statusmsg); void prompt_update_statusmessage(ToxWindow *prompt, Tox *m, const char *statusmsg);
void prompt_update_status(ToxWindow *prompt, uint8_t status); void prompt_update_status(ToxWindow *prompt, TOX_USER_STATUS status);
void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected); void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected);
void kill_prompt_window(ToxWindow *self); void kill_prompt_window(ToxWindow *self);
/* callback: Updates own connection status in prompt statusbar */
void prompt_onSelfConnectionChange(Tox *m, TOX_CONNECTION connection_status, void *userdata);
#endif /* end of include guard: PROMPT_H */ #endif /* end of include guard: PROMPT_H */

View File

@ -199,7 +199,7 @@ static void audio_defaults(struct user_settings* settings)
#ifdef SOUND_NOTIFY #ifdef SOUND_NOTIFY
static const struct sound_strings { static const struct sound_strings {
const char* self; const char* self;
const char* error; const char* notif_error;
const char* self_log_in; const char* self_log_in;
const char* self_log_out; const char* self_log_out;
const char* user_log_in; const char* user_log_in;
@ -211,7 +211,7 @@ static const struct sound_strings {
const char* transfer_completed; const char* transfer_completed;
} sound_strings = { } sound_strings = {
"sounds", "sounds",
"error", "notif_error",
"self_log_in", "self_log_in",
"self_log_out", "self_log_out",
"user_log_in", "user_log_in",
@ -406,10 +406,10 @@ int settings_load(struct user_settings *s, const char *patharg)
#ifdef SOUND_NOTIFY #ifdef SOUND_NOTIFY
if ((setting = config_lookup(cfg, sound_strings.self)) != NULL) { if ((setting = config_lookup(cfg, sound_strings.self)) != NULL) {
if ( (config_setting_lookup_string(setting, sound_strings.error, &str) != CONFIG_TRUE) || if ( (config_setting_lookup_string(setting, sound_strings.notif_error, &str) != CONFIG_TRUE) ||
!set_sound(error, str) ) { !set_sound(notif_error, str) ) {
if (str && strcasecmp(str, NO_SOUND) != 0) if (str && strcasecmp(str, NO_SOUND) != 0)
set_sound(error, PACKAGE_DATADIR "/sounds/ToxicError.wav"); set_sound(notif_error, PACKAGE_DATADIR "/sounds/ToxicError.wav");
} }
if ( !config_setting_lookup_string(setting, sound_strings.user_log_in, &str) || if ( !config_setting_lookup_string(setting, sound_strings.user_log_in, &str) ||
@ -455,7 +455,7 @@ int settings_load(struct user_settings *s, const char *patharg)
} }
} }
else { else {
set_sound(error, PACKAGE_DATADIR "/sounds/ToxicError.wav"); set_sound(notif_error, PACKAGE_DATADIR "/sounds/ToxicError.wav");
set_sound(user_log_in, PACKAGE_DATADIR "/sounds/ToxicContactOnline.wav"); set_sound(user_log_in, PACKAGE_DATADIR "/sounds/ToxicContactOnline.wav");
set_sound(user_log_out, PACKAGE_DATADIR "/sounds/ToxicContactOffline.wav"); set_sound(user_log_out, PACKAGE_DATADIR "/sounds/ToxicContactOffline.wav");
set_sound(call_incoming, PACKAGE_DATADIR "/sounds/ToxicIncomingCall.wav"); set_sound(call_incoming, PACKAGE_DATADIR "/sounds/ToxicIncomingCall.wav");

View File

@ -67,7 +67,7 @@ struct user_settings {
int key_toggle_peerlist; int key_toggle_peerlist;
int mplex_away; /* boolean (1 for reaction to terminal attach/detach) */ int mplex_away; /* boolean (1 for reaction to terminal attach/detach) */
char mplex_away_note [TOX_MAX_STATUSMESSAGE_LENGTH]; char mplex_away_note [TOX_MAX_STATUS_MESSAGE_LENGTH];
#ifdef AUDIO #ifdef AUDIO
int audio_in_dev; int audio_in_dev;

View File

@ -70,8 +70,8 @@ static char buffer [BUFFER_SIZE];
static bool auto_away_active = false; static bool auto_away_active = false;
static mplex_status mplex = MPLEX_NONE; static mplex_status mplex = MPLEX_NONE;
static TOX_USERSTATUS prev_status = TOX_USERSTATUS_NONE; static TOX_USER_STATUS prev_status = TOX_USER_STATUS_NONE;
static char prev_note [TOX_MAX_STATUSMESSAGE_LENGTH] = ""; static char prev_note [TOX_MAX_STATUS_MESSAGE_LENGTH] = "";
/* mutex for access to status data, for sync between: /* mutex for access to status data, for sync between:
- user command /status from ncurses thread - user command /status from ncurses thread
@ -314,7 +314,7 @@ static int mplex_is_detached ()
static void mplex_timer_handler (Tox *m) static void mplex_timer_handler (Tox *m)
{ {
TOX_USERSTATUS current_status, new_status; TOX_USER_STATUS current_status, new_status;
const char *new_note; const char *new_note;
if (mplex == MPLEX_NONE) if (mplex == MPLEX_NONE)
@ -323,23 +323,23 @@ static void mplex_timer_handler (Tox *m)
int detached = mplex_is_detached (); int detached = mplex_is_detached ();
pthread_mutex_lock (&Winthread.lock); pthread_mutex_lock (&Winthread.lock);
current_status = tox_get_self_user_status (m); current_status = tox_self_get_status (m);
pthread_mutex_unlock (&Winthread.lock); pthread_mutex_unlock (&Winthread.lock);
if (auto_away_active && current_status == TOX_USERSTATUS_AWAY && !detached) if (auto_away_active && current_status == TOX_USER_STATUS_AWAY && !detached)
{ {
auto_away_active = false; auto_away_active = false;
new_status = prev_status; new_status = prev_status;
new_note = prev_note; new_note = prev_note;
} }
else else
if (current_status == TOX_USERSTATUS_NONE && detached) if (current_status == TOX_USER_STATUS_NONE && detached)
{ {
auto_away_active = true; auto_away_active = true;
prev_status = current_status; prev_status = current_status;
new_status = TOX_USERSTATUS_AWAY; new_status = TOX_USER_STATUS_AWAY;
pthread_mutex_lock (&Winthread.lock); pthread_mutex_lock (&Winthread.lock);
tox_get_self_status_message (m, (uint8_t*) prev_note, sizeof (prev_note)); tox_self_get_status_message (m, (uint8_t*) prev_note);
pthread_mutex_unlock (&Winthread.lock); pthread_mutex_unlock (&Winthread.lock);
new_note = user_settings->mplex_away_note; new_note = user_settings->mplex_away_note;
} }
@ -348,8 +348,8 @@ static void mplex_timer_handler (Tox *m)
char argv[3][MAX_STR_SIZE]; char argv[3][MAX_STR_SIZE];
strcpy (argv[0], "/status"); strcpy (argv[0], "/status");
strcpy (argv[1], (new_status == TOX_USERSTATUS_AWAY ? "away" : strcpy (argv[1], (new_status == TOX_USER_STATUS_AWAY ? "away" :
new_status == TOX_USERSTATUS_BUSY ? "busy" : "online")); new_status == TOX_USER_STATUS_BUSY ? "busy" : "online"));
argv[2][0] = '\"'; argv[2][0] = '\"';
strcpy (argv[2] + 1, new_note); strcpy (argv[2] + 1, new_note);
strcat (argv[2], "\""); strcat (argv[2], "\"");

View File

@ -50,7 +50,7 @@
#include "groupchat.h" #include "groupchat.h"
#include "prompt.h" #include "prompt.h"
#include "misc_tools.h" #include "misc_tools.h"
#include "file_senders.h" #include "file_transfers.h"
#include "line_info.h" #include "line_info.h"
#include "settings.h" #include "settings.h"
#include "log.h" #include "log.h"
@ -79,6 +79,8 @@ char *BLOCK_FILE = NULL;
ToxWindow *prompt = NULL; ToxWindow *prompt = NULL;
#define AUTOSAVE_FREQ 60 #define AUTOSAVE_FREQ 60
#define MIN_PASSWORD_LEN 6
#define MAX_PASSWORD_LEN 64
struct Winthread Winthread; struct Winthread Winthread;
struct cqueue_thread cqueue_thread; struct cqueue_thread cqueue_thread;
@ -86,8 +88,6 @@ struct audio_thread audio_thread;
struct arg_opts arg_opts; struct arg_opts arg_opts;
struct user_settings *user_settings = NULL; struct user_settings *user_settings = NULL;
#define MIN_PASSWORD_LEN 6
#define MAX_PASSWORD_LEN 64
static struct user_password { static struct user_password {
bool data_is_encrypted; bool data_is_encrypted;
@ -102,7 +102,7 @@ static void catch_SIGINT(int sig)
static void catch_SIGSEGV(int sig) static void catch_SIGSEGV(int sig)
{ {
freopen("/dev/tty", "w", stderr); freopen("/dev/tty", "w", stderr); // make sure stderr is enabled since we may have disabled it
endwin(); endwin();
fprintf(stderr, "Caught SIGSEGV: Aborting toxic session.\n"); fprintf(stderr, "Caught SIGSEGV: Aborting toxic session.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -124,7 +124,6 @@ void exit_toxic_success(Tox *m)
{ {
store_data(m, DATA_FILE); store_data(m, DATA_FILE);
memset(&user_password, 0, sizeof(struct user_password)); memset(&user_password, 0, sizeof(struct user_password));
close_all_file_senders(m);
kill_all_windows(m); kill_all_windows(m);
terminate_notify(); terminate_notify();
@ -151,9 +150,6 @@ void exit_toxic_success(Tox *m)
void exit_toxic_err(const char *errmsg, int errcode) void exit_toxic_err(const char *errmsg, int errcode)
{ {
if (errmsg == NULL)
errmsg = "No error message";
freopen("/dev/tty", "w", stderr); freopen("/dev/tty", "w", stderr);
endwin(); endwin();
fprintf(stderr, "Toxic session aborted with error code %d (%s)\n", errcode, errmsg); fprintf(stderr, "Toxic session aborted with error code %d (%s)\n", errcode, errmsg);
@ -167,7 +163,7 @@ static void init_term(void)
if (!arg_opts.default_locale) { if (!arg_opts.default_locale) {
if (setlocale(LC_ALL, "") == NULL) if (setlocale(LC_ALL, "") == NULL)
exit_toxic_err("Could not set your locale, please check your locale settings or " exit_toxic_err("Could not set your locale, please check your locale settings or "
"disable unicode support with the -d flag.", FATALERR_LOCALE_SET); "disable unicode support with the -d flag.", FATALERR_LOCALE_NOT_SET);
} }
#endif #endif
@ -255,82 +251,6 @@ static void print_init_messages(ToxWindow *toxwin)
line_info_add(toxwin, NULL, NULL, NULL, SYS_MSG, 0, 0, init_messages.msgs[i]); line_info_add(toxwin, NULL, NULL, NULL, SYS_MSG, 0, 0, init_messages.msgs[i]);
} }
static Tox *init_tox(void)
{
Tox_Options tox_opts;
tox_opts.ipv6enabled = !arg_opts.use_ipv4;
tox_opts.udp_disabled = arg_opts.force_tcp;
tox_opts.proxy_type = arg_opts.proxy_type;
if (tox_opts.proxy_type != TOX_PROXY_NONE) {
tox_opts.proxy_port = arg_opts.proxy_port;
snprintf(tox_opts.proxy_address, sizeof(tox_opts.proxy_address), "%s", arg_opts.proxy_address);
const char *ps = tox_opts.proxy_type == TOX_PROXY_SOCKS5 ? "SOCKS5" : "HTTP";
char tmp[48];
snprintf(tmp, sizeof(tmp), "Using %s proxy %s : %d", ps, arg_opts.proxy_address, arg_opts.proxy_port);
queue_init_message("%s", tmp);
}
if (tox_opts.udp_disabled) {
queue_init_message("UDP disabled");
} else if (tox_opts.proxy_type != TOX_PROXY_NONE) {
const char *msg = "WARNING: Using a proxy without disabling UDP may leak your real IP address.";
queue_init_message("%s", msg);
msg = "Use the -t option to disable UDP.";
queue_init_message("%s", msg);
}
/* Init core */
Tox *m = tox_new(&tox_opts);
if (tox_opts.ipv6enabled && m == NULL) {
queue_init_message("IPv6 failed to initialize");
tox_opts.ipv6enabled = 0;
m = tox_new(&tox_opts);
}
if (!tox_opts.ipv6enabled)
queue_init_message("Forcing IPv4 connection");
if (tox_opts.proxy_type != TOX_PROXY_NONE && m == NULL)
exit_toxic_err("Proxy error", FATALERR_PROXY);
if (m == NULL)
return NULL;
/* Callbacks */
tox_callback_connection_status(m, on_connectionchange, NULL);
tox_callback_typing_change(m, on_typing_change, NULL);
tox_callback_friend_request(m, on_request, NULL);
tox_callback_friend_message(m, on_message, NULL);
tox_callback_name_change(m, on_nickchange, NULL);
tox_callback_user_status(m, on_statuschange, NULL);
tox_callback_status_message(m, on_statusmessagechange, NULL);
tox_callback_friend_action(m, on_action, NULL);
tox_callback_file_send_request(m, on_file_sendrequest, NULL);
tox_callback_file_control(m, on_file_control, NULL);
tox_callback_file_data(m, on_file_data, NULL);
tox_callback_read_receipt(m, on_read_receipt, NULL);
tox_callback_group_invite(m, on_group_invite, NULL);
tox_callback_group_message(m, on_group_message, NULL);
tox_callback_group_action(m, on_group_action, NULL);
tox_callback_group_private_message(m, on_group_private_message, NULL);
tox_callback_group_op_certificate(m, on_group_op_certificate, NULL);
tox_callback_group_peerlist_update(m, on_group_namelistchange, NULL);
tox_callback_group_peer_join(m, on_group_peer_join, NULL);
tox_callback_group_peer_exit(m, on_group_peer_exit, NULL);
tox_callback_group_nick_change(m, on_group_nick_change, NULL);
tox_callback_group_topic_change(m, on_group_topic_change, NULL);
tox_callback_group_self_join(m, on_group_self_join, NULL);
tox_callback_group_self_timeout(m, on_group_self_timeout, NULL);
tox_callback_group_rejected(m, on_group_rejected, NULL);
tox_set_name(m, (uint8_t *) "Toxic User", strlen("Toxic User"));
return m;
}
#define MIN_NODE_LINE 50 /* IP: 7 + port: 5 + key: 38 + spaces: 2 = 70. ! (& e.g. tox.im = 6) */ #define MIN_NODE_LINE 50 /* IP: 7 + port: 5 + key: 38 + spaces: 2 = 70. ! (& e.g. tox.im = 6) */
#define MAX_NODE_LINE 256 /* Approx max number of chars in a sever line (name + port + key) */ #define MAX_NODE_LINE 256 /* Approx max number of chars in a sever line (name + port + key) */
#define MAXNODES 50 #define MAXNODES 50
@ -387,7 +307,7 @@ static int load_nodelist(const char *filename)
int init_connection_helper(Tox *m, int line) int init_connection_helper(Tox *m, int line)
{ {
return tox_bootstrap_from_address(m, toxNodes.nodes[line], toxNodes.ports[line], (uint8_t *) toxNodes.keys[line]); return tox_bootstrap(m, toxNodes.nodes[line], toxNodes.ports[line], (uint8_t *) toxNodes.keys[line], NULL);
} }
/* Connects to a random DHT node listed in the DHTnodes file /* Connects to a random DHT node listed in the DHTnodes file
@ -439,43 +359,10 @@ int init_connection(Tox *m)
return 4; return 4;
} }
#define TRY_CONNECT 10 /* Seconds between connection attempts when DHT is not connected */
static void do_connection(Tox *m, ToxWindow *prompt)
{
if (arg_opts.no_connect == 1)
return;
static int conn_err = 0;
static bool was_connected = false;
static uint64_t last_conn_try = 0;
uint64_t curtime = get_unix_time();
bool is_connected = tox_isconnected(m);
if (was_connected && is_connected)
return;
if (!was_connected && is_connected) {
was_connected = true;
prompt_update_connectionstatus(prompt, was_connected);
} else if (was_connected && !is_connected) {
was_connected = false;
prompt_update_connectionstatus(prompt, was_connected);
} else if (!was_connected && !is_connected && timed_out(last_conn_try, curtime, TRY_CONNECT)) {
/* if autoconnect has already failed there's no point in trying again */
if (conn_err == 0) {
last_conn_try = curtime;
if ((conn_err = init_connection(m)) != 0)
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Auto-connect failed with error code %d", conn_err);
}
}
}
static void load_friendlist(Tox *m) static void load_friendlist(Tox *m)
{ {
uint32_t i; size_t i;
uint32_t numfriends = tox_count_friendlist(m); size_t numfriends = tox_self_get_friend_list_size(m);
for (i = 0; i < numfriends; ++i) for (i = 0; i < numfriends; ++i)
friendlist_onFriendAdded(NULL, m, i, false); friendlist_onFriendAdded(NULL, m, i, false);
@ -554,6 +441,7 @@ static void first_time_encrypt(const char *msg)
int len = 0; int len = 0;
bool valid_password = false; bool valid_password = false;
char passconfirm[MAX_PASSWORD_LEN + 1] = {0}; char passconfirm[MAX_PASSWORD_LEN + 1] = {0};
printf("Enter a new password (must be at least %d characters) ", MIN_PASSWORD_LEN); printf("Enter a new password (must be at least %d characters) ", MIN_PASSWORD_LEN);
while (valid_password == false) { while (valid_password == false) {
@ -584,7 +472,7 @@ static void first_time_encrypt(const char *msg)
valid_password = true; valid_password = true;
} }
queue_init_message("Data file '%s' has been encrypted", DATA_FILE); queue_init_message("Data file '%s' will be encrypted", DATA_FILE);
memset(passconfirm, 0, sizeof(passconfirm)); memset(passconfirm, 0, sizeof(passconfirm));
user_password.data_is_encrypted = true; user_password.data_is_encrypted = true;
} }
@ -598,13 +486,10 @@ static void first_time_encrypt(const char *msg)
*/ */
int store_data(Tox *m, const char *path) int store_data(Tox *m, const char *path)
{ {
if (arg_opts.ignore_data_file)
return 0;
if (path == NULL) if (path == NULL)
return -1; return -1;
int len = user_password.data_is_encrypted ? tox_encrypted_size(m) : tox_size(m); size_t len = user_password.data_is_encrypted ? tox_encrypted_size(m) : tox_get_savedata_size(m);
char *buf = malloc(len); char *buf = malloc(len);
if (buf == NULL) if (buf == NULL)
@ -616,72 +501,136 @@ int store_data(Tox *m, const char *path)
return -1; return -1;
} }
} else { } else {
tox_save(m, (uint8_t *) buf); tox_get_savedata(m, (uint8_t *) buf);
} }
FILE *fd = fopen(path, "wb"); FILE *fp = fopen(path, "wb");
if (fd == NULL) { if (fp == NULL) {
free(buf); free(buf);
return -1; return -1;
} }
if (fwrite(buf, len, 1, fd) != 1) { if (fwrite(buf, len, 1, fp) != 1) {
free(buf); free(buf);
fclose(fd); fclose(fp);
return -1; return -1;
} }
free(buf); free(buf);
fclose(fd); fclose(fp);
return 0; return 0;
} }
static void load_data(Tox *m, char *path) static void init_tox_callbacks(Tox *m)
{ {
if (arg_opts.ignore_data_file) tox_callback_self_connection_status(m, prompt_onSelfConnectionChange, NULL);
return;
FILE *fd = fopen(path, "rb"); tox_callback_friend_connection_status(m, on_connectionchange, NULL);
tox_callback_friend_typing(m, on_typing_change, NULL);
tox_callback_friend_request(m, on_request, NULL);
tox_callback_friend_message(m, on_message, NULL);
tox_callback_friend_name(m, on_nickchange, NULL);
tox_callback_friend_status(m, on_statuschange, NULL);
tox_callback_friend_status_message(m, on_statusmessagechange, NULL);
tox_callback_friend_read_receipt(m, on_read_receipt, NULL);
if (fd != NULL) { tox_callback_file_recv(m, on_file_recv, NULL);
off_t len = file_size(path); tox_callback_file_chunk_request(m, on_file_chunk_request, NULL);
tox_callback_file_recv_control(m, on_file_control, NULL);
tox_callback_file_recv_chunk(m, on_file_recv_chunk, NULL);
if (len == -1) { tox_callback_group_invite(m, on_group_invite, NULL);
fclose(fd); tox_callback_group_message(m, on_group_message, NULL);
exit_toxic_err("failed in load_data", FATALERR_FILEOP); tox_callback_group_action(m, on_group_action, NULL);
tox_callback_group_private_message(m, on_group_private_message, NULL);
tox_callback_group_op_certificate(m, on_group_op_certificate, NULL);
tox_callback_group_peerlist_update(m, on_group_namelistchange, NULL);
tox_callback_group_peer_join(m, on_group_peer_join, NULL);
tox_callback_group_peer_exit(m, on_group_peer_exit, NULL);
tox_callback_group_nick_change(m, on_group_nick_change, NULL);
tox_callback_group_topic_change(m, on_group_topic_change, NULL);
tox_callback_group_self_join(m, on_group_self_join, NULL);
tox_callback_group_self_timeout(m, on_group_self_timeout, NULL);
tox_callback_group_rejected(m, on_group_rejected, NULL);
}
static void init_tox_options(struct Tox_Options *tox_opts)
{
tox_opts->ipv6_enabled = !arg_opts.use_ipv4;
tox_opts->udp_enabled = !arg_opts.force_tcp;
tox_opts->proxy_type = arg_opts.proxy_type;
if (!tox_opts->ipv6_enabled)
queue_init_message("Forcing IPv4 connection");
if (tox_opts->proxy_type != TOX_PROXY_TYPE_NONE) {
tox_opts->proxy_port = arg_opts.proxy_port;
tox_opts->proxy_host = arg_opts.proxy_address;
const char *ps = tox_opts->proxy_type == TOX_PROXY_TYPE_SOCKS5 ? "SOCKS5" : "HTTP";
char tmp[48];
snprintf(tmp, sizeof(tmp), "Using %s proxy %s : %d", ps, arg_opts.proxy_address, arg_opts.proxy_port);
queue_init_message("%s", tmp);
}
if (!tox_opts->udp_enabled) {
queue_init_message("UDP disabled");
} else if (tox_opts->proxy_type != TOX_PROXY_TYPE_NONE) {
const char *msg = "WARNING: Using a proxy without disabling UDP may leak your real IP address.";
queue_init_message("%s", msg);
msg = "Use the -t option to disable UDP.";
queue_init_message("%s", msg);
}
}
/* Returns a new Tox object on success.
* If object fails to initialize the toxic process will terminate.
*/
static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts)
{
Tox *m = NULL;
FILE *fp = fopen(data_path, "rb");
if (fp != NULL) {
off_t len = file_size(data_path);
if (len == 0) {
fclose(fp);
exit_toxic_err("failed in load_toxic", FATALERR_FILEOP);
} }
char *buf = malloc(len); char *buf = malloc(len);
if (buf == NULL) { if (buf == NULL) {
fclose(fd); fclose(fp);
exit_toxic_err("failed in load_data", FATALERR_MEMORY); exit_toxic_err("failed in load_toxic", FATALERR_MEMORY);
} }
if (fread(buf, len, 1, fd) != 1) { if (fread(buf, len, 1, fp) != 1) {
free(buf); free(buf);
fclose(fd); fclose(fp);
exit_toxic_err("failed in load_data", FATALERR_FILEOP); exit_toxic_err("failed in load_toxic", FATALERR_FILEOP);
} }
bool is_encrypted = tox_is_save_encrypted((uint8_t *) buf); bool is_encrypted = tox_is_data_encrypted((uint8_t *) buf);
/* attempt to encrypt an already encrypted data file */ /* attempt to encrypt an already encrypted data file */
if (arg_opts.encrypt_data && is_encrypted) if (arg_opts.encrypt_data && is_encrypted)
exit_toxic_err("failed in load_data", FATALERR_ENCRYPT); exit_toxic_err("failed in load_toxic", FATALERR_ENCRYPT);
if (arg_opts.unencrypt_data && is_encrypted) if (arg_opts.unencrypt_data && is_encrypted)
queue_init_message("Data file '%s' has been unencrypted", path); queue_init_message("Data file '%s' has been unencrypted", data_path);
else if (arg_opts.unencrypt_data) else if (arg_opts.unencrypt_data)
queue_init_message("Warning: passed --unencrypt-data option with unencrypted data file '%s'", path); queue_init_message("Warning: passed --unencrypt-data option with unencrypted data file '%s'", data_path);
if (is_encrypted) { if (is_encrypted) {
if (!arg_opts.unencrypt_data) if (!arg_opts.unencrypt_data)
user_password.data_is_encrypted = true; user_password.data_is_encrypted = true;
int pwlen = 0; size_t pwlen = 0;
system("clear"); system("clear"); // TODO: is this portable?
printf("Enter password (q to quit) "); printf("Enter password (q to quit) ");
while (true) { while (true) {
@ -698,44 +647,99 @@ static void load_data(Tox *m, char *path)
continue; continue;
} }
if (tox_encrypted_load(m, (uint8_t *) buf, len, (uint8_t *) user_password.pass, pwlen) == 0) { TOX_ERR_ENCRYPTED_NEW enc_err;
m = tox_encrypted_new(tox_opts, (uint8_t *) buf, len, (uint8_t *) user_password.pass, pwlen, &enc_err);
if (enc_err == TOX_ERR_ENCRYPTED_NEW_OK) {
break; break;
} else { } else if (enc_err == TOX_ERR_ENCRYPTED_NEW_LOAD_DECRYPTION_FAILED) {
system("clear"); system("clear");
sleep(1); sleep(1);
printf("Invalid password. Try again. "); printf("Invalid password. Try again. ");
} else {
exit_toxic_err("tox_encrypted_new() failed", enc_err);
} }
} }
} else { } else {
/* tox_load errors are to be ignored until toxcore is fixed */ TOX_ERR_NEW err;
tox_load(m, (uint8_t *) buf, len); m = tox_new(tox_opts, (uint8_t *) buf, len, &err);
if (err != TOX_ERR_NEW_OK)
exit_toxic_err("tox_new() failed", err);
} }
load_friendlist(m);
load_blocklist(BLOCK_FILE);
free(buf); free(buf);
fclose(fd); fclose(fp);
} else { } else {
/* if file exists then open() failing is fatal */ /* if file exists then open() failing is fatal */
if (file_exists(path)) if (file_exists(data_path))
exit_toxic_err("failed in load_data", FATALERR_FILEOP); exit_toxic_err("failed in load_toxic", FATALERR_FILEOP);
if (store_data(m, path) != 0) TOX_ERR_NEW err;
exit_toxic_err("failed in load_data", FATALERR_STORE_DATA); m = tox_new(tox_opts, NULL, 0, &err);
if (err != TOX_ERR_NEW_OK)
exit_toxic_err("tox_new() failed", err);
if (store_data(m, data_path) == -1)
exit_toxic_err("failed in load_toxic", FATALERR_FILEOP);
} }
return m;
}
static Tox *load_toxic(char *data_path)
{
struct Tox_Options tox_opts;
init_tox_options(&tox_opts);
Tox *m = load_tox(data_path, &tox_opts);
if (m == NULL)
exit_toxic_err("load_tox() failed", FATALERR_TOX_INIT);
init_tox_callbacks(m);
load_friendlist(m);
load_blocklist(BLOCK_FILE);
if (tox_self_get_name_size(m) == 0)
tox_self_set_name(m, (uint8_t *) "Toxic User", strlen("Toxic User"), NULL);
return m;
}
#define TRY_BOOTSTRAP_INTERVAL 5
static uint64_t last_bootstrap_time = 0;
static void do_bootstrap(Tox *m)
{
static int conn_err = 0;
uint64_t curtime = get_unix_time();
if (!timed_out(last_bootstrap_time, curtime, TRY_BOOTSTRAP_INTERVAL))
return;
if (tox_self_get_connection_status(m) != TOX_CONNECTION_NONE)
return;
if (conn_err != 0)
return;
last_bootstrap_time = curtime;
conn_err = init_connection(m);
if (conn_err != 0)
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Auto-connect failed with error code %d", conn_err);
} }
static void do_toxic(Tox *m, ToxWindow *prompt) static void do_toxic(Tox *m, ToxWindow *prompt)
{ {
if (arg_opts.no_connect)
return;
pthread_mutex_lock(&Winthread.lock); pthread_mutex_lock(&Winthread.lock);
do_connection(m, prompt); tox_iterate(m);
do_file_senders(m); do_bootstrap(m);
if (arg_opts.no_connect == 0) {
tox_do(m); /* main tox-core loop */
}
pthread_mutex_unlock(&Winthread.lock); pthread_mutex_unlock(&Winthread.lock);
} }
@ -772,16 +776,19 @@ void *thread_cqueue(void *data)
while (true) { while (true) {
pthread_mutex_lock(&Winthread.lock); pthread_mutex_lock(&Winthread.lock);
int i;
size_t i;
for (i = 2; i < MAX_WINDOWS_NUM; ++i) { for (i = 2; i < MAX_WINDOWS_NUM; ++i) {
ToxWindow *toxwin = get_window_ptr(i); ToxWindow *toxwin = get_window_ptr(i);
if (toxwin != NULL && toxwin->is_chat && tox_get_friend_connection_status(m, toxwin->num) == 1) if (toxwin != NULL && toxwin->is_chat
&& tox_friend_get_connection_status(m, toxwin->num, NULL) != TOX_CONNECTION_NONE)
cqueue_try_send(toxwin, m); cqueue_try_send(toxwin, m);
} }
pthread_mutex_unlock(&Winthread.lock); pthread_mutex_unlock(&Winthread.lock);
usleep(4000); usleep(4000);
} }
} }
@ -795,6 +802,7 @@ void *thread_audio(void *data)
pthread_mutex_lock(&Winthread.lock); pthread_mutex_lock(&Winthread.lock);
toxav_do(av); toxav_do(av);
pthread_mutex_unlock(&Winthread.lock); pthread_mutex_unlock(&Winthread.lock);
usleep(toxav_do_interval(av) * 1000); usleep(toxav_do_interval(av) * 1000);
} }
} }
@ -817,7 +825,6 @@ static void print_usage(void)
fprintf(stderr, " -r, --dnslist Use specified DNSservers file\n"); fprintf(stderr, " -r, --dnslist Use specified DNSservers file\n");
fprintf(stderr, " -t, --force-tcp Force TCP connection (use this with proxies)\n"); fprintf(stderr, " -t, --force-tcp Force TCP connection (use this with proxies)\n");
fprintf(stderr, " -u, --unencrypt-data Unencrypt an encrypted data file\n"); fprintf(stderr, " -u, --unencrypt-data Unencrypt an encrypted data file\n");
fprintf(stderr, " -x, --nodata Ignore data file\n");
} }
static void set_default_opts(void) static void set_default_opts(void)
@ -825,7 +832,7 @@ static void set_default_opts(void)
memset(&arg_opts, 0, sizeof(struct arg_opts)); memset(&arg_opts, 0, sizeof(struct arg_opts));
/* set any non-zero defaults here*/ /* set any non-zero defaults here*/
arg_opts.proxy_type = TOX_PROXY_NONE; arg_opts.proxy_type = TOX_PROXY_TYPE_NONE;
} }
static void parse_args(int argc, char *argv[]) static void parse_args(int argc, char *argv[])
@ -834,7 +841,6 @@ static void parse_args(int argc, char *argv[])
static struct option long_opts[] = { static struct option long_opts[] = {
{"file", required_argument, 0, 'f'}, {"file", required_argument, 0, 'f'},
{"nodata", no_argument, 0, 'x'},
{"ipv4", no_argument, 0, '4'}, {"ipv4", no_argument, 0, '4'},
{"debug", no_argument, 0, 'b'}, {"debug", no_argument, 0, 'b'},
{"default-locale", no_argument, 0, 'd'}, {"default-locale", no_argument, 0, 'd'},
@ -911,7 +917,7 @@ static void parse_args(int argc, char *argv[])
break; break;
case 'p': case 'p':
arg_opts.proxy_type = TOX_PROXY_SOCKS5; arg_opts.proxy_type = TOX_PROXY_TYPE_SOCKS5;
snprintf(arg_opts.proxy_address, sizeof(arg_opts.proxy_address), "%s", optarg); snprintf(arg_opts.proxy_address, sizeof(arg_opts.proxy_address), "%s", optarg);
if (++optind > argc || argv[optind-1][0] == '-') if (++optind > argc || argv[optind-1][0] == '-')
@ -921,7 +927,7 @@ static void parse_args(int argc, char *argv[])
break; break;
case 'P': case 'P':
arg_opts.proxy_type = TOX_PROXY_HTTP; arg_opts.proxy_type = TOX_PROXY_TYPE_HTTP;
snprintf(arg_opts.proxy_address, sizeof(arg_opts.proxy_address), "%s", optarg); snprintf(arg_opts.proxy_address, sizeof(arg_opts.proxy_address), "%s", optarg);
if (++optind > argc || argv[optind-1][0] == '-') if (++optind > argc || argv[optind-1][0] == '-')
@ -946,11 +952,6 @@ static void parse_args(int argc, char *argv[])
arg_opts.unencrypt_data = 1; arg_opts.unencrypt_data = 1;
break; break;
case 'x':
arg_opts.ignore_data_file = 1;
queue_init_message("Ignoring data file");
break;
case 'h': case 'h':
default: default:
print_usage(); print_usage();
@ -1015,6 +1016,7 @@ static useconds_t optimal_msleepval(uint64_t *looptimer, uint64_t *loopcount, ui
} }
#ifdef X11 #ifdef X11
// FIXME
void DnD_callback(const char* asdv, DropType dt) void DnD_callback(const char* asdv, DropType dt)
{ {
if (dt != DT_plain) if (dt != DT_plain)
@ -1026,31 +1028,32 @@ void DnD_callback(const char* asdv, DropType dt)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
parse_args(argc, argv); parse_args(argc, argv);
/* Use the -b flag to enable stderr */
if (!arg_opts.debug)
freopen("/dev/null", "w", stderr);
if (arg_opts.encrypt_data && arg_opts.unencrypt_data) { if (arg_opts.encrypt_data && arg_opts.unencrypt_data) {
arg_opts.encrypt_data = 0; arg_opts.encrypt_data = 0;
arg_opts.unencrypt_data = 0; arg_opts.unencrypt_data = 0;
queue_init_message("Warning: Using --unencrypt-data and --encrypt-data simultaneously has no effect"); queue_init_message("Warning: Using --unencrypt-data and --encrypt-data simultaneously has no effect");
} }
/* Use the -b flag to enable stderr */
if (!arg_opts.debug)
freopen("/dev/null", "w", stderr);
/* Make sure all written files are read/writeable only by the current user. */ /* Make sure all written files are read/writeable only by the current user. */
umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
int config_err = init_default_data_files(); int config_err = init_default_data_files();
bool datafile_exists = file_exists(DATA_FILE); bool datafile_exists = file_exists(DATA_FILE);
if (!arg_opts.ignore_data_file) { if (datafile_exists)
if (!datafile_exists && !arg_opts.unencrypt_data) last_bootstrap_time = get_unix_time();
first_time_encrypt("Creating new data file. Would you like to encrypt it? Y/n (q to quit)");
else if (arg_opts.encrypt_data) if (!datafile_exists && !arg_opts.unencrypt_data)
first_time_encrypt("Encrypt existing data file? Y/n (q to quit)"); first_time_encrypt("Creating new data file. Would you like to encrypt it? Y/n (q to quit)");
} else if (arg_opts.encrypt_data)
first_time_encrypt("Encrypt existing data file? Y/n (q to quit)");
/* init user_settings struct and load settings from conf file */ /* init user_settings struct and load settings from conf file */
user_settings = calloc(1, sizeof(struct user_settings)); user_settings = calloc(1, sizeof(struct user_settings));
@ -1066,20 +1069,14 @@ int main(int argc, char *argv[])
queue_init_message("X failed to initialize"); queue_init_message("X failed to initialize");
#endif #endif
Tox *m = init_tox(); Tox *m = load_toxic(DATA_FILE);
if (m == NULL) if (arg_opts.encrypt_data && !datafile_exists)
exit_toxic_err("failed in main", FATALERR_NETWORKINIT); arg_opts.encrypt_data = 0;
if (!arg_opts.ignore_data_file) {
if (arg_opts.encrypt_data && !datafile_exists)
arg_opts.encrypt_data = 0;
load_data(m, DATA_FILE);
}
init_term(); init_term();
prompt = init_windows(m); prompt = init_windows(m);
prompt_init_statusbar(prompt, m); prompt_init_statusbar(prompt, m);
@ -1124,7 +1121,7 @@ int main(int argc, char *argv[])
queue_init_message("Failed to load user settings"); queue_init_message("Failed to load user settings");
/* screen/tmux auto-away timer */ /* screen/tmux auto-away timer */
if (init_mplex_away_timer (m) == -1) if (init_mplex_away_timer(m) == -1)
queue_init_message("Failed to init mplex auto-away."); queue_init_message("Failed to init mplex auto-away.");
load_groups(m); load_groups(m);

View File

@ -77,13 +77,13 @@ typedef enum _FATAL_ERRS {
FATALERR_THREAD_CREATE = -3, /* thread creation failed for critical thread */ FATALERR_THREAD_CREATE = -3, /* thread creation failed for critical thread */
FATALERR_MUTEX_INIT = -4, /* mutex init for critical thread failed */ FATALERR_MUTEX_INIT = -4, /* mutex init for critical thread failed */
FATALERR_THREAD_ATTR = -5, /* thread attr object init failed */ FATALERR_THREAD_ATTR = -5, /* thread attr object init failed */
FATALERR_LOCALE_SET = -6, /* system locale not set */ FATALERR_LOCALE_NOT_SET = -6, /* system locale not set */
FATALERR_STORE_DATA = -7, /* store_data failed in critical section */ FATALERR_STORE_DATA = -7, /* store_data failed in critical section */
FATALERR_NETWORKINIT = -8, /* Tox network failed to init */ FATALERR_INFLOOP = -8, /* infinite loop detected */
FATALERR_INFLOOP = -9, /* infinite loop detected */ FATALERR_WININIT = -9, /* window init failed */
FATALERR_WININIT = -10, /* window init failed */ FATALERR_PROXY = -10, /* Tox network failed to init using a proxy */
FATALERR_PROXY = -11, /* Tox network failed to init using a proxy */ FATALERR_ENCRYPT = -11, /* Data file encryption failure */
FATALERR_ENCRYPT = -12, /* Data file encryption failure */ FATALERR_TOX_INIT = -12, /* Tox instance failed to initialize */
} FATAL_ERRS; } FATAL_ERRS;
/* Fixes text color problem on some terminals. /* Fixes text color problem on some terminals.
@ -98,21 +98,23 @@ void exit_toxic_err(const char *errmsg, int errcode);
int store_data(Tox *m, const char *path); int store_data(Tox *m, const char *path);
void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata); /* callbacks */
void on_connectionchange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata); void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata);
void on_message(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata); void on_connectionchange(Tox *m, uint32_t friendnumber, TOX_CONNECTION status, void *userdata);
void on_action(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata); void on_message(Tox *m, uint32_t friendnumber, TOX_MESSAGE_TYPE type, const uint8_t *string, size_t length, void *userdata);
void on_nickchange(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata); void on_action(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata);
void on_statuschange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata); void on_nickchange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata);
void on_statusmessagechange(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata); void on_statuschange(Tox *m, uint32_t friendnumber, TOX_USER_STATUS status, void *userdata);
void on_friendadded(Tox *m, int32_t friendnumber, bool sort); void on_statusmessagechange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata);
void on_file_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, const uint8_t *pathname, void on_friendadded(Tox *m, uint32_t friendnumber, bool sort);
uint16_t pathname_length, void *userdata); void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata);
void on_file_control(Tox *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type, void on_file_recv_chunk(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
const uint8_t *data, uint16_t length, void *userdata); size_t length, void *userdata);
void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *userdata); void on_file_control (Tox *m, uint32_t friendnumber, uint32_t filenumber, TOX_FILE_CONTROL control, void *userdata);
void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata); void on_file_recv(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint32_t kind, uint64_t file_size,
void on_read_receipt(Tox *m, int32_t, uint32_t, void *userdata); const uint8_t *filename, size_t filename_length, void *userdata);
void on_typing_change(Tox *m, uint32_t friendnumber, bool is_typing, void *userdata);
void on_read_receipt(Tox *m, uint32_t friendnumber, uint32_t receipt, void *userdata);
void on_group_invite(Tox *m, int32_t friendnumber, const uint8_t *invite_data, uint16_t length, void *userdata); void on_group_invite(Tox *m, int32_t friendnumber, const uint8_t *invite_data, uint16_t length, void *userdata);
void on_group_message(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *message, uint16_t length, void *userdata); void on_group_message(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *message, uint16_t length, void *userdata);

View File

@ -125,7 +125,7 @@ int yank_buf(ChatContext *ctx)
return 0; return 0;
} }
/* Deletes all characters from line starting at pos and going backwards /* Deletes all characters from line starting at pos and going backwards
until we find a space or run out of characters. until we find a space or run out of characters.
Return 0 on success, -1 if nothing to delete */ Return 0 on success, -1 if nothing to delete */
int del_word_buf(ChatContext *ctx) int del_word_buf(ChatContext *ctx)
@ -225,7 +225,7 @@ void fetch_hist_item(ChatContext *ctx, int key_dir)
if (key_dir == KEY_UP) { if (key_dir == KEY_UP) {
if (--ctx->hst_pos < 0) { if (--ctx->hst_pos < 0) {
ctx->hst_pos = 0; ctx->hst_pos = 0;
sound_notify(NULL, error, NT_ALWAYS, NULL); sound_notify(NULL, notif_error, NT_ALWAYS, NULL);
} }
} else { } else {
if (++ctx->hst_pos >= ctx->hst_tot) { if (++ctx->hst_pos >= ctx->hst_tot) {

View File

@ -46,12 +46,12 @@ extern struct user_settings *user_settings;
static int num_active_windows; static int num_active_windows;
/* CALLBACKS START */ /* CALLBACKS START */
void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata) void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
{ {
char msg[MAX_STR_SIZE + 1]; char msg[MAX_STR_SIZE + 1];
length = copy_tox_str(msg, sizeof(msg), (const char *) data, length); length = copy_tox_str(msg, sizeof(msg), (const char *) data, length);
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onFriendRequest != NULL) { if (windows[i].onFriendRequest != NULL) {
@ -60,22 +60,22 @@ void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t
} }
} }
void on_connectionchange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata) void on_connectionchange(Tox *m, uint32_t friendnumber, TOX_CONNECTION connection_status, void *userdata)
{ {
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onConnectionChange != NULL) if (windows[i].onConnectionChange != NULL)
windows[i].onConnectionChange(&windows[i], m, friendnumber, status); windows[i].onConnectionChange(&windows[i], m, friendnumber, connection_status);
} }
} }
void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata) void on_typing_change(Tox *m, uint32_t friendnumber, bool is_typing, void *userdata)
{ {
if (user_settings->show_typing_other == SHOW_TYPING_OFF) if (user_settings->show_typing_other == SHOW_TYPING_OFF)
return; return;
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onTypingChange != NULL) if (windows[i].onTypingChange != NULL)
@ -83,39 +83,27 @@ void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *use
} }
} }
void on_message(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata) void on_message(Tox *m, uint32_t friendnumber, TOX_MESSAGE_TYPE type, const uint8_t *string, size_t length,
void *userdata)
{ {
char msg[MAX_STR_SIZE + 1]; char msg[MAX_STR_SIZE + 1];
length = copy_tox_str(msg, sizeof(msg), (const char *) string, length); length = copy_tox_str(msg, sizeof(msg), (const char *) string, length);
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onMessage != NULL) if (windows[i].onMessage != NULL)
windows[i].onMessage(&windows[i], m, friendnumber, msg, length); windows[i].onMessage(&windows[i], m, friendnumber, type, msg, length);
} }
} }
void on_action(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata) void on_nickchange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata)
{
char msg[MAX_STR_SIZE + 1];
length = copy_tox_str(msg, sizeof(msg), (const char *) string, length);
int i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onAction != NULL)
windows[i].onAction(&windows[i], m, friendnumber, msg, length);
}
}
void on_nickchange(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata)
{ {
char nick[TOXIC_MAX_NAME_LENGTH + 1]; char nick[TOXIC_MAX_NAME_LENGTH + 1];
length = copy_tox_str(nick, sizeof(nick), (const char *) string, length); length = copy_tox_str(nick, sizeof(nick), (const char *) string, length);
filter_str(nick, length); filter_str(nick, length);
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onNickChange != NULL) if (windows[i].onNickChange != NULL)
@ -125,13 +113,13 @@ void on_nickchange(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t
store_data(m, DATA_FILE); store_data(m, DATA_FILE);
} }
void on_statusmessagechange(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata) void on_statusmessagechange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata)
{ {
char msg[TOX_MAX_STATUSMESSAGE_LENGTH + 1]; char msg[TOX_MAX_STATUS_MESSAGE_LENGTH + 1];
length = copy_tox_str(msg, sizeof(msg), (const char *) string, length); length = copy_tox_str(msg, sizeof(msg), (const char *) string, length);
filter_str(msg, length); filter_str(msg, length);
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onStatusMessageChange != NULL) if (windows[i].onStatusMessageChange != NULL)
@ -139,9 +127,9 @@ void on_statusmessagechange(Tox *m, int32_t friendnumber, const uint8_t *string,
} }
} }
void on_statuschange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata) void on_statuschange(Tox *m, uint32_t friendnumber, TOX_USER_STATUS status, void *userdata)
{ {
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onStatusChange != NULL) if (windows[i].onStatusChange != NULL)
@ -149,9 +137,9 @@ void on_statuschange(Tox *m, int32_t friendnumber, uint8_t status, void *userdat
} }
} }
void on_friendadded(Tox *m, int32_t friendnumber, bool sort) void on_friendadded(Tox *m, uint32_t friendnumber, bool sort)
{ {
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onFriendAdded != NULL) if (windows[i].onFriendAdded != NULL)
@ -177,7 +165,7 @@ void on_group_message(Tox *m, int groupnumber, uint32_t peernumber, const uint8_
char msg[MAX_STR_SIZE + 1]; char msg[MAX_STR_SIZE + 1];
length = copy_tox_str(msg, sizeof(msg), (const char *) message, length); length = copy_tox_str(msg, sizeof(msg), (const char *) message, length);
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupMessage != NULL) if (windows[i].onGroupMessage != NULL)
@ -191,7 +179,7 @@ void on_group_action(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t
char msg[MAX_STR_SIZE + 1]; char msg[MAX_STR_SIZE + 1];
length = copy_tox_str(msg, sizeof(msg), (const char *) action, length); length = copy_tox_str(msg, sizeof(msg), (const char *) action, length);
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupAction != NULL) if (windows[i].onGroupAction != NULL)
@ -205,7 +193,7 @@ void on_group_private_message(Tox *m, int groupnumber, uint32_t peernumber, cons
char msg[MAX_STR_SIZE + 1]; char msg[MAX_STR_SIZE + 1];
length = copy_tox_str(msg, sizeof(msg), (const char *) message, length); length = copy_tox_str(msg, sizeof(msg), (const char *) message, length);
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupPrivateMessage != NULL) if (windows[i].onGroupPrivateMessage != NULL)
@ -215,7 +203,7 @@ void on_group_private_message(Tox *m, int groupnumber, uint32_t peernumber, cons
void on_group_namelistchange(Tox *m, int groupnumber, void *userdata) void on_group_namelistchange(Tox *m, int groupnumber, void *userdata)
{ {
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupNamelistChange != NULL) if (windows[i].onGroupNamelistChange != NULL)
@ -259,7 +247,7 @@ void on_group_topic_change(Tox *m, int groupnumber, uint32_t peernumber, const u
char data[MAX_STR_SIZE + 1]; char data[MAX_STR_SIZE + 1];
length = copy_tox_str(data, sizeof(data), (const char *) topic, length); length = copy_tox_str(data, sizeof(data), (const char *) topic, length);
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupTopicChange != NULL) if (windows[i].onGroupTopicChange != NULL)
@ -323,44 +311,60 @@ void on_group_rejected(Tox *m, int groupnumber, uint8_t type, void *userdata)
} }
} }
void on_file_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position,
const uint8_t *filename, uint16_t filename_length, void *userdata) size_t length, void *userdata)
{ {
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onFileSendRequest != NULL) if (windows[i].onFileChunkRequest != NULL)
windows[i].onFileSendRequest(&windows[i], m, friendnumber, filenumber, filesize, windows[i].onFileChunkRequest(&windows[i], m, friendnumber, filenumber, position, length);
(const char *) filename, filename_length);
} }
} }
void on_file_control (Tox *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, void on_file_recv_chunk(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position,
uint8_t control_type, const uint8_t *data, uint16_t length, void *userdata) const uint8_t *data, size_t length, void *user_data)
{ {
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onFileRecvChunk != NULL)
windows[i].onFileRecvChunk(&windows[i], m, friendnumber, filenumber, position, (char *) data, length);
}
}
void on_file_control(Tox *m, uint32_t friendnumber, uint32_t filenumber, TOX_FILE_CONTROL control,
void *userdata)
{
size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onFileControl != NULL) if (windows[i].onFileControl != NULL)
windows[i].onFileControl(&windows[i], m, friendnumber, receive_send, filenumber, windows[i].onFileControl(&windows[i], m, friendnumber, filenumber, control);
control_type, (const char *) data, length);
} }
} }
void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void on_file_recv(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint32_t kind, uint64_t file_size,
void *userdata) const uint8_t *filename, size_t filename_length, void *userdata)
{ {
int i; /* We don't care about receiving avatars */
if (kind != TOX_FILE_KIND_DATA) {
tox_file_control(m, friendnumber, filenumber, TOX_FILE_CONTROL_CANCEL, NULL);
return;
}
size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onFileData != NULL) if (windows[i].onFileRecv != NULL)
windows[i].onFileData(&windows[i], m, friendnumber, filenumber, (const char *) data, length); windows[i].onFileRecv(&windows[i], m, friendnumber, filenumber, file_size, (char *) filename,
filename_length);
} }
} }
void on_read_receipt(Tox *m, int32_t friendnumber, uint32_t receipt, void *userdata) void on_read_receipt(Tox *m, uint32_t friendnumber, uint32_t receipt, void *userdata)
{ {
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onReadReceipt != NULL) if (windows[i].onReadReceipt != NULL)
@ -375,7 +379,7 @@ int add_window(Tox *m, ToxWindow w)
if (LINES < 2) if (LINES < 2)
return -1; return -1;
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; i++) { for (i = 0; i < MAX_WINDOWS_NUM; i++) {
if (windows[i].active) if (windows[i].active)
@ -469,7 +473,7 @@ void on_window_resize(void)
getmaxyx(stdscr, y2, x2); getmaxyx(stdscr, y2, x2);
y2 -= 2; y2 -= 2;
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (!windows[i].active) if (!windows[i].active)
@ -541,7 +545,7 @@ static void draw_bar(void)
printw(" TOXIC " TOXICVER " |"); printw(" TOXIC " TOXICVER " |");
attroff(COLOR_PAIR(BLUE) | A_BOLD); attroff(COLOR_PAIR(BLUE) | A_BOLD);
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (!windows[i].active) if (!windows[i].active)
@ -619,7 +623,7 @@ void draw_active_window(Tox *m)
call at least once per second */ call at least once per second */
void refresh_inactive_windows(void) void refresh_inactive_windows(void)
{ {
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
ToxWindow *a = &windows[i]; ToxWindow *a = &windows[i];
@ -655,7 +659,7 @@ int get_num_active_windows(void)
/* destroys all chat and groupchat windows (should only be called on shutdown) */ /* destroys all chat and groupchat windows (should only be called on shutdown) */
void kill_all_windows(Tox *m) void kill_all_windows(Tox *m)
{ {
int i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].is_chat) if (windows[i].is_chat)

View File

@ -81,21 +81,21 @@ struct audio_thread {
}; };
struct arg_opts { struct arg_opts {
int ignore_data_file; bool use_ipv4;
int use_ipv4; bool force_tcp;
int force_tcp; bool debug;
int debug; bool default_locale;
int default_locale; bool use_custom_data;
int use_custom_data; bool no_connect;
int no_connect; bool encrypt_data;
int encrypt_data; bool unencrypt_data;
int unencrypt_data;
char dns_path[MAX_STR_SIZE]; char dns_path[MAX_STR_SIZE];
char config_path[MAX_STR_SIZE]; char config_path[MAX_STR_SIZE];
char nodes_path[MAX_STR_SIZE]; char nodes_path[MAX_STR_SIZE];
uint8_t proxy_type;
char proxy_address[256]; char proxy_address[256];
uint8_t proxy_type;
uint16_t proxy_port; uint16_t proxy_port;
}; };
@ -106,22 +106,25 @@ typedef struct ChatContext ChatContext;
typedef struct Help Help; typedef struct Help Help;
struct ToxWindow { struct ToxWindow {
/* ncurses */
void(*onKey)(ToxWindow *, Tox *, wint_t, bool); void(*onKey)(ToxWindow *, Tox *, wint_t, bool);
void(*onDraw)(ToxWindow *, Tox *); void(*onDraw)(ToxWindow *, Tox *);
void(*onInit)(ToxWindow *, Tox *); void(*onInit)(ToxWindow *, Tox *);
void(*onFriendRequest)(ToxWindow *, Tox *, const char *, const char *, uint16_t);
void(*onFriendAdded)(ToxWindow *, Tox *, int32_t, bool); /* toxcore */
void(*onConnectionChange)(ToxWindow *, Tox *, int32_t, uint8_t); void(*onFriendRequest)(ToxWindow *, Tox *, const char *, const char *, size_t);
void(*onMessage)(ToxWindow *, Tox *, int32_t, const char *, uint16_t); void(*onFriendAdded)(ToxWindow *, Tox *, uint32_t, bool);
void(*onNickChange)(ToxWindow *, Tox *, int32_t, const char *, uint16_t); void(*onConnectionChange)(ToxWindow *, Tox *, uint32_t, TOX_CONNECTION);
void(*onStatusChange)(ToxWindow *, Tox *, int32_t, uint8_t); void(*onMessage)(ToxWindow *, Tox *, uint32_t, TOX_MESSAGE_TYPE, const char *, size_t);
void(*onStatusMessageChange)(ToxWindow *, int32_t, const char *, uint16_t); void(*onNickChange)(ToxWindow *, Tox *, uint32_t, const char *, size_t);
void(*onAction)(ToxWindow *, Tox *, int32_t, const char *, uint16_t); void(*onStatusChange)(ToxWindow *, Tox *, uint32_t, TOX_USER_STATUS);
void(*onFileSendRequest)(ToxWindow *, Tox *, int32_t, uint8_t, uint64_t, const char *, uint16_t); void(*onStatusMessageChange)(ToxWindow *, uint32_t, const char *, size_t);
void(*onFileControl)(ToxWindow *, Tox *, int32_t, uint8_t, uint8_t, uint8_t, const char *, uint16_t); void(*onFileChunkRequest)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, size_t);
void(*onFileData)(ToxWindow *, Tox *, int32_t, uint8_t, const char *, uint16_t); void(*onFileRecvChunk)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, const char *, size_t);
void(*onTypingChange)(ToxWindow *, Tox *, int32_t, uint8_t); void(*onFileControl)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_FILE_CONTROL);
void(*onReadReceipt)(ToxWindow *, Tox *, int32_t, uint32_t); void(*onFileRecv)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, const char *, size_t);
void(*onTypingChange)(ToxWindow *, Tox *, uint32_t, bool);
void(*onReadReceipt)(ToxWindow *, Tox *, uint32_t, uint32_t);
void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, const char *, uint16_t); void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, const char *, uint16_t);
void(*onGroupMessage)(ToxWindow *, Tox *, int, int, const char *, uint16_t); void(*onGroupMessage)(ToxWindow *, Tox *, int, int, const char *, uint16_t);
@ -161,7 +164,7 @@ struct ToxWindow {
int active_box; /* For box notify */ int active_box; /* For box notify */
char name[TOXIC_MAX_NAME_LENGTH + 1]; char name[TOXIC_MAX_NAME_LENGTH + 1];
int32_t num; /* corresponds to friendnumber in chat windows */ uint32_t num; /* corresponds to friendnumber in chat windows */
bool active; bool active;
int x; int x;
@ -183,19 +186,19 @@ struct ToxWindow {
/* statusbar info holder */ /* statusbar info holder */
struct StatusBar { struct StatusBar {
WINDOW *topline; WINDOW *topline;
char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH + 1]; char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH + 1];
uint16_t statusmsg_len; size_t statusmsg_len;
char nick[TOXIC_MAX_NAME_LENGTH + 1]; char nick[TOXIC_MAX_NAME_LENGTH + 1];
int nick_len; size_t nick_len;
uint8_t status; TOX_USER_STATUS status;
bool is_online; TOX_CONNECTION connection;
}; };
#ifdef AUDIO #ifdef AUDIO
#define INFOBOX_HEIGHT 7 #define INFOBOX_HEIGHT 7
#define INFOBOX_WIDTH 21 #define INFOBOX_WIDTH 21
/* holds display info for audio calls */ /* holds display info for audio calls */
struct infobox { struct infobox {
float vad_lvl; float vad_lvl;