1
0
mirror of https://github.com/Tha14/toxic.git synced 2024-07-01 19:57:47 +02:00

Merge pull request #50 from JFreegman/master

Implemented file transfers
This commit is contained in:
JFreegman 2013-10-10 21:39:59 -07:00
commit 95fe2356e5
9 changed files with 281 additions and 6 deletions

View File

@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.65])
AC_INIT([toxic], [0.2.1], [http://tox.im/])
AC_INIT([toxic], [0.2.2], [http://tox.im/])
AC_CONFIG_AUX_DIR(configure_aux)
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])

View File

@ -106,6 +106,75 @@ static void chat_onStatusMessageChange(ToxWindow *self, int num, uint8_t *status
memcpy(statusbar->statusmsg, status, len);
}
static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int num, uint8_t filenum, uint64_t filesize,
uint8_t *filename, uint16_t filename_len)
{
if (self-> num != num)
return;
ChatContext *ctx = (ChatContext *) self->chatwin;
wprintw(ctx->history, "File transfer request for '%s' of size %llu.\n", filename, (long long unsigned int)filesize);
if (filenum > MAX_FILENUMBER) {
wprintw(ctx->history, "Too many pending file requests; discarding.\n");
return;
}
wprintw(ctx->history, "Type '/file %d' to accept the file transfer.\n", filenum);
pending_file_transfers[filenum] = num;
self->blink = true;
beep();
}
static void chat_onFileControl(ToxWindow *self, Tox *m, int num, uint8_t receive_send, uint8_t filenum,
uint8_t control_type, uint8_t *data, uint16_t length)
{
if (self->num != num)
return;
ChatContext *ctx = (ChatContext *) self->chatwin;
switch(control_type) {
case 0:
wprintw(ctx->history, "File transfer accepted.\n");
break;
case 3:
wprintw(ctx->history, "File successfully recieved.\n");
break;
default:
wprintw(ctx->history, "Control %u receieved.\n", control_type);
break;
}
self->blink = true;
beep();
}
static void chat_onFileData(ToxWindow *self, Tox *m, int num, uint8_t filenum, uint8_t *data, uint16_t length)
{
if (self->num != num)
return;
ChatContext *ctx = (ChatContext *) self->chatwin;
char filename[MAX_STR_SIZE];
snprintf(filename, sizeof(filename), "%d.%u.bin", num, filenum);
FILE *file_to_save = fopen(filename, "a");
if (fwrite(data, length, 1, file_to_save) != 1) {
wattron(ctx->history, COLOR_PAIR(RED));
wprintw(ctx->history, "* Error writing to file.\n");
wattroff(ctx->history, COLOR_PAIR(RED));
}
fclose(file_to_save);
}
static void print_chat_help(ChatContext *ctx)
{
wattron(ctx->history, COLOR_PAIR(CYAN) | A_BOLD);
@ -120,6 +189,8 @@ static void print_chat_help(ChatContext *ctx)
wprintw(ctx->history, " /myid : Print your ID\n");
wprintw(ctx->history, " /clear : Clear the screen\n");
wprintw(ctx->history, " /close : Close the current chat window\n");
wprintw(ctx->history, " /sendfile <nickname> <file>: Send a file\n");
wprintw(ctx->history, " /file <n> : Accept a file\n");
wprintw(ctx->history, " /quit or /exit : Exit Toxic\n");
wprintw(ctx->history, " /help : Print this message again\n");
@ -368,6 +439,9 @@ ToxWindow new_chat(Tox *m, ToxWindow *prompt, int friendnum)
ret.onStatusChange = &chat_onStatusChange;
ret.onStatusMessageChange = &chat_onStatusMessageChange;
ret.onAction = &chat_onAction;
ret.onFileSendRequest = &chat_onFileSendRequest;
ret.onFileControl = &chat_onFileControl;
ret.onFileData = &chat_onFileData;
uint8_t name[TOX_MAX_NAME_LENGTH] = {'\0'};
tox_getname(m, friendnum, name);

View File

@ -180,6 +180,28 @@ void cmd_connect(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **arg
free(binary_string);
}
void cmd_file(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv)
{
if (argc < 1) {
wprintw(window, "Wrong number of arguments.\n");
return;
}
uint8_t filenum = atoi(argv[1]);
if (filenum < 0 || filenum > MAX_FILENUMBER) {
wprintw(window, "File transfer failed.\n");
return;
}
int friendnum = pending_file_transfers[filenum];
if (tox_file_sendcontrol(m, friendnum, 1, filenum, 0, 0, 0))
wprintw(window, "Accepted file transfer %u. Saving file as %d.%u.bin.\n", filenum, friendnum, filenum);
else
wprintw(window, "File transfer failed.\n");
}
void cmd_groupchat(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv)
{
int ngc = get_num_groupchats();
@ -392,6 +414,71 @@ void cmd_quit(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv)
exit_toxic(m);
}
void cmd_sendfile(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv)
{
if (argc < 1) {
wprintw(window, "Wrong number of arguments.\n");
return;
}
uint8_t *friendname = argv[1];
int friendnum = get_friendnum(friendname);
if (friendnum == -1) {
wprintw(window, "Friend '%s' not found.\n", friendname);
return;
}
if (friendname[0] == '\"')
friendname[strlen(++friendname)-1] = L'\0';
uint8_t *filename = argv[2];
int filename_len = strlen(filename);
if (filename[0] != '\"') {
wprintw(window, "File name must be enclosed in quotes.\n");
return;
}
filename[strlen(++filename)-1] = L'\0';
if (filename_len > MAX_STR_SIZE) {
wprintw(window, "File path exceeds character limit.\n");
return;
}
FILE *file_to_send = fopen(filename, "r");
if (file_to_send == NULL) {
wprintw(window, "File '%s' not found.\n", filename);
return;
}
fseek(file_to_send, 0, SEEK_END);
uint64_t filesize = ftell(file_to_send);
fseek(file_to_send, 0, SEEK_SET);
int filenum = tox_new_filesender(m, friendnum, filesize, filename, filename_len + 1);
if (filenum == -1) {
wprintw(window, "Error sending file\n");
return;
}
memcpy(file_senders[num_file_senders].filename, filename, filename_len + 1);
memcpy(file_senders[num_file_senders].friendname, friendname, strlen(friendname) + 1);
file_senders[num_file_senders].file = file_to_send;
file_senders[num_file_senders].filenum = filenum;
file_senders[num_file_senders].friendnum = friendnum;
file_senders[num_file_senders].piecelen = fread(file_senders[num_file_senders].nextpiece, 1,
tox_filedata_size(m, friendnum), file_to_send);
wprintw(window, "Sending file '%s' to %s...\n", filename, friendname);
++num_file_senders;
}
void cmd_status(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv)
{
uint8_t *msg = NULL;

View File

@ -7,6 +7,7 @@ void cmd_accept(WINDOW *, ToxWindow *, Tox *m, int, char **);
void cmd_add(WINDOW *, ToxWindow *, Tox *m, int, char **);
void cmd_clear(WINDOW *, ToxWindow *, Tox *m, int, char **);
void cmd_connect(WINDOW *, ToxWindow *, Tox *m, int, char **);
void cmd_file(WINDOW *, ToxWindow *, Tox *m, int, char **);
void cmd_groupchat(WINDOW *, ToxWindow *, Tox *m, int, char **);
void cmd_invite(WINDOW *, ToxWindow *, Tox *m, int, char **);
void cmd_join(WINDOW *, ToxWindow *, Tox *m, int, char **);
@ -15,11 +16,12 @@ void cmd_myid(WINDOW *, ToxWindow *, Tox *m, int, char **);
void cmd_nick(WINDOW *, ToxWindow *, Tox *m, int, char **);
void cmd_note(WINDOW *, ToxWindow *, Tox *m, int, char **);
void cmd_quit(WINDOW *, ToxWindow *, Tox *m, int, char **);
void cmd_sendfile(WINDOW *, ToxWindow *, Tox *m, int, char **);
void cmd_status(WINDOW *, ToxWindow *, Tox *m, int, char **);
void execute(WINDOW *window, ToxWindow *prompt, Tox *m, char *u_cmd, int buf_len);
#define NUM_COMMANDS 15
#define NUM_COMMANDS 17
static struct {
char *name;
@ -30,6 +32,7 @@ static struct {
{ "/clear", cmd_clear },
{ "/connect", cmd_connect },
{ "/exit", cmd_quit },
{ "/file", cmd_file },
{ "/groupchat", cmd_groupchat },
{ "/invite", cmd_invite },
{ "/join", cmd_join },
@ -39,5 +42,6 @@ static struct {
{ "/note", cmd_note },
{ "/q", cmd_quit },
{ "/quit", cmd_quit },
{ "/sendfile", cmd_sendfile },
{ "/status", cmd_status },
};

View File

@ -108,6 +108,16 @@ int friendlist_onFriendAdded(Tox *m, int num)
return -1;
}
void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int num, uint8_t filenum, uint64_t filesize,
uint8_t *filename, uint16_t filename_len)
{
if (num < 0 || num >= num_friends)
return;
if (friends[num].chatwin == -1)
friends[num].chatwin = add_window(m, new_chat(m, prompt, friends[num].num));
}
static void select_friend(Tox *m, wint_t key)
{
if (num_friends < 1)
@ -286,6 +296,7 @@ ToxWindow new_friendlist()
ret.onNickChange = &friendlist_onNickChange;
ret.onStatusChange = &friendlist_onStatusChange;
ret.onStatusMessageChange = &friendlist_onStatusMessageChange;
ret.onFileSendRequest = &friendlist_onFileSendRequest;
strcpy(ret.name, "friends");
return ret;

View File

@ -92,6 +92,7 @@ static Tox *init_tox()
{
/* Init core */
Tox *m = tox_new(TOX_ENABLE_IPV6_DEFAULT);
if (m == NULL)
return NULL;
@ -105,6 +106,10 @@ static Tox *init_tox()
tox_callback_action(m, on_action, NULL);
tox_callback_group_invite(m, on_groupinvite, NULL);
tox_callback_group_message(m, on_groupmessage, NULL);
tox_callback_file_sendrequest(m, on_file_sendrequest, NULL);
tox_callback_file_control(m, on_file_control, NULL);
tox_callback_file_data(m, on_file_data, NULL);
#ifdef __linux__
tox_setname(m, (uint8_t *) "Cool guy", sizeof("Cool guy"));
#elif defined(_WIN32)
@ -114,6 +119,7 @@ static Tox *init_tox()
#else
tox_setname(m, (uint8_t *) "Registered Minix user #4", sizeof("Registered Minix user #4"));
#endif
return m;
}
@ -341,6 +347,36 @@ static void load_data(Tox *m, char *path)
}
}
void do_file_senders(Tox *m)
{
int i;
for (i = 0; i < NUM_FILE_SENDERS; ++i) {
if (file_senders[i].file == NULL)
continue;
while (true) {
if (!tox_file_senddata(m, file_senders[i].friendnum, file_senders[i].filenum,
file_senders[i].nextpiece, file_senders[i].piecelen))
return;
file_senders[i].piecelen = fread(file_senders[i].nextpiece, 1, tox_filedata_size(m, file_senders[i].friendnum),
file_senders[i].file);
if (file_senders[i].piecelen == 0) {
fclose(file_senders[i].file);
file_senders[i].file = NULL;
tox_file_sendcontrol(m, file_senders[i].friendnum, 0, file_senders[i].filenum, 3, 0, 0);
/* TODO: move this alert to chat window */
wprintw(prompt->window, "File '%s' successfuly sent to %s.\n", file_senders[i].filename,
file_senders[i].friendname);
return;
}
}
}
}
void exit_toxic(Tox *m)
{
store_data(m, DATA_FILE);
@ -442,10 +478,8 @@ int main(int argc, char *argv[])
prompt_init_statusbar(prompt, m);
while (true) {
/* Update tox */
do_tox(m, prompt);
/* Draw */
do_file_senders(m);
draw_active_window(m);
}

View File

@ -320,7 +320,7 @@ void prompt_init_statusbar(ToxWindow *self, Tox *m)
snprintf(statusbar->nick, sizeof(statusbar->nick), "%s", nick);
/* temporary until statusmessage saving works */
uint8_t *statusmsg = "Toxing on Toxic v.0.2.1";
uint8_t *statusmsg = "Toxing on Toxic v.0.2.2";
m_set_statusmessage(m, statusmsg, strlen(statusmsg) + 1);
snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg);

View File

@ -56,6 +56,9 @@ struct ToxWindow_ {
void(*onAction)(ToxWindow *, Tox *, int, uint8_t *, uint16_t);
void(*onGroupMessage)(ToxWindow *, Tox *, int, int, uint8_t *, uint16_t);
void(*onGroupInvite)(ToxWindow *, Tox *, int, uint8_t *);
void(*onFileSendRequest)(ToxWindow *, Tox *, int, uint8_t, uint64_t, uint8_t *, uint16_t);
void(*onFileControl)(ToxWindow *, Tox *, int, uint8_t, uint8_t, uint8_t, uint8_t *, uint16_t);
void(*onFileData)(ToxWindow *, Tox *, int, uint8_t, uint8_t *, uint16_t);
char name[TOX_MAX_NAME_LENGTH];
int num;
@ -92,6 +95,29 @@ typedef struct {
bool active;
} GroupChat;
/* Start file transfer code */
#define NUM_FILE_SENDERS 256
#define MAX_FILENUMBER 100 /* fix */
#define FILE_PIECE_SIZE 1024
typedef struct {
FILE *file;
uint16_t friendnum;
uint8_t filenum;
uint8_t nextpiece[FILE_PIECE_SIZE];
uint16_t piecelen;
uint8_t friendname[TOXIC_MAX_NAME_LENGTH];
uint8_t filename[MAX_STR_SIZE];
} FileSender;
FileSender file_senders[NUM_FILE_SENDERS];
uint8_t num_file_senders;
uint8_t pending_file_transfers[MAX_FILENUMBER];
/* End file transfer code */
void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata);
void on_connectionchange(Tox *m, int friendnumber, uint8_t status, void *userdata);
void on_message(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata);
@ -102,6 +128,10 @@ void on_statusmessagechange(Tox *m, int friendnumber, uint8_t *string, uint16_t
void on_friendadded(Tox *m, int friendnumber);
void on_groupmessage(Tox *m, int groupnumber, int peernumber, uint8_t *message, uint16_t length, void *userdata);
void on_groupinvite(Tox *m, int friendnumber, uint8_t *group_pub_key, void *userdata);
void on_file_sendrequest(Tox *m, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata);
void on_file_control(Tox *m, int friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type, uint8_t *data, uint16_t length, void *userdata);
void on_file_data(Tox *m, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata);
ToxWindow *init_windows();
void draw_active_window(Tox *m);
int add_window(Tox *m, ToxWindow w);

View File

@ -137,6 +137,41 @@ void on_groupinvite(Tox *m, int friendnumber, uint8_t *group_pub_key, void *user
windows[i].onGroupInvite(&windows[i], m, friendnumber, group_pub_key);
}
}
void on_file_sendrequest(Tox *m, int friendnumber, uint8_t filenumber, uint64_t filesize,
uint8_t *filename, uint16_t filename_length, void *userdata)
{
int i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onFileSendRequest != NULL)
windows[i].onFileSendRequest(&windows[i], m, friendnumber, filenumber, filesize,
filename, filename_length);
}
}
void on_file_control (Tox *m, int friendnumber, uint8_t receive_send, uint8_t filenumber,
uint8_t control_type, uint8_t *data, uint16_t length, void *userdata)
{
int i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onFileControl != NULL)
windows[i].onFileControl(&windows[i], m, friendnumber, receive_send, filenumber,
control_type, data, length);
}
}
void on_file_data(Tox *m, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata)
{
int i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onFileData != NULL)
windows[i].onFileData(&windows[i], m, friendnumber, filenumber, data, length);
}
}
/* CALLBACKS END */
int add_window(Tox *m, ToxWindow w)