From b5db32585a89749ce8e91348d176292cdc20abfd Mon Sep 17 00:00:00 2001 From: "Coren[m]" Date: Thu, 12 Sep 2013 19:09:25 +0200 Subject: [PATCH 1/3] Patch to allow DHT_bootstrap to also do LAN discovery. This patch inserts LAN discovery in DHT_bootstrap, allowing it to find clients even if it's run parameterless (and clients don't connect to it directly, e.g. because the port is already bound to a different client). - moves the #define of LAN_DISCOVERY_INTERVAL from Messenger.c to LAN_discovery.h - includes LAN_discovery.h into DHT_bootstrap.c - DHT_bootstrap.c sends and accepts LAN_discovery packets --- other/DHT_bootstrap.c | 8 ++++++++ toxcore/LAN_discovery.h | 2 ++ toxcore/Messenger.c | 2 -- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c index 654b759f..aed17020 100644 --- a/other/DHT_bootstrap.c +++ b/other/DHT_bootstrap.c @@ -31,6 +31,7 @@ #endif #include "../toxcore/DHT.h" +#include "../toxcore/LAN_discovery.h" #include "../toxcore/friend_requests.h" #include "../testing/misc_tools.c" @@ -123,6 +124,9 @@ int main(int argc, char *argv[]) int is_waiting_for_dht_connection = 1; + uint64_t last_LANdiscovery = 0; + LANdiscovery_init(dht); + while (1) { if (is_waiting_for_dht_connection && DHT_isconnected(dht)) { printf("Connected to other bootstrap server successfully.\n"); @@ -130,6 +134,10 @@ int main(int argc, char *argv[]) } do_DHT(dht); + if (last_LANdiscovery + (is_waiting_for_dht_connection ? 5 : LAN_DISCOVERY_INTERVAL) < unix_time()) { + send_LANdiscovery(htons(PORT), dht->c); + last_LANdiscovery = unix_time(); + } networking_poll(dht->c->lossless_udp->net); diff --git a/toxcore/LAN_discovery.h b/toxcore/LAN_discovery.h index 78990936..3e9d9de5 100644 --- a/toxcore/LAN_discovery.h +++ b/toxcore/LAN_discovery.h @@ -35,6 +35,8 @@ #include #endif +/* Interval in seconds between LAN discovery packet sending. */ +#define LAN_DISCOVERY_INTERVAL 60 /* Send a LAN discovery pcaket to the broadcast address with port port. */ int send_LANdiscovery(uint16_t port, Net_Crypto *c); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index b712d142..2ff5634a 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -637,8 +637,6 @@ int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_id, uint return write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, packet, length + 1); } -/* Interval in seconds between LAN discovery packet sending. */ -#define LAN_DISCOVERY_INTERVAL 60 #define PORT 33445 /* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */ From 91d7f4857f3c555f0cc3f13a07a68b40ea6d6a5b Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 12 Sep 2013 19:26:30 -0400 Subject: [PATCH 2/3] Very basic group chats, tested and working with nTox. Please wait until the tox.h API is updated before integrating it into your clients. nTox: /g creates a new group chat /i friendnum groupnum invite friendnum to groupnum /z groupnum message send message to groupnum NOTE: group chats currenly might not handle packet loss well if there are less than 6 participants. --- testing/nTox.c | 45 ++++++++++++++-- testing/nTox.h | 2 +- toxcore/Messenger.c | 121 ++++++++++++++++++++++++++++++++++++++++-- toxcore/Messenger.h | 56 ++++++++++++++++++- toxcore/group_chats.h | 1 + 5 files changed, 217 insertions(+), 8 deletions(-) diff --git a/testing/nTox.c b/testing/nTox.c index 438468bd..d6e25ac0 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -348,13 +348,34 @@ void line_eval(Tox *m, char *line) do_refresh(); } else if (inpt_command == 'h') { //help new_lines(help); - } else if (inpt_command == 'i') { //info + } else if (inpt_command == 'x') { //info char idstring[200]; get_id(m, idstring); new_lines(idstring); - } + } else if (inpt_command == 'g') { //create new group chat + char msg[256]; + sprintf(msg, "[g] Created new group chat with number: %u", add_groupchat(m)); + new_lines(msg); + } else if (inpt_command == 'i') { //invite friendnum to groupnum + char *posi[1]; + int friendnumber = strtoul(line + prompt_offset, posi, 0); + int groupnumber = strtoul(*posi + 1, NULL, 0); + char msg[256]; + sprintf(msg, "[g] Invited friend number %u to group number %u, returned: %u (0 means success)", friendnumber, + groupnumber, invite_friend(m, friendnumber, groupnumber)); + new_lines(msg); + } else if (inpt_command == 'z') { //send message to groupnum + char *posi[1]; + int groupnumber = strtoul(line + prompt_offset, posi, 0); - else if (inpt_command == 'q') { //exit + if (**posi != 0) { + char msg[256 + 1024]; + sprintf(msg, "[g] sent message: %s to group num: %u returned: %u (0 means success)", *posi + 1, groupnumber, + group_message_send(m, groupnumber, (uint8_t *)*posi + 1, strlen(*posi + 1) + 1)); + new_lines(msg); + } + + } else if (inpt_command == 'q') { //exit endwin(); exit(EXIT_SUCCESS); } else { @@ -535,6 +556,22 @@ void print_help(void) puts("\t-f\t-\tSpecify a keyfile to read (or write to) from."); } +void print_invite(Messenger *m, int friendnumber, uint8_t *group_public_key, void *userdata) +{ + char msg[256]; + sprintf(msg, "[i] recieved group chat invite from: %u, auto accepting and joining. group number: %u", friendnumber, + join_groupchat(m, friendnumber, group_public_key)); + new_lines(msg); +} + +void print_groupmessage(Messenger *m, int groupnumber, uint8_t *message, uint16_t length, void *userdata) +{ + char msg[256 + length]; + sprintf(msg, "[g] %u: %s", groupnumber, message); + new_lines(msg); +} + + int main(int argc, char *argv[]) { int on = 0; @@ -579,6 +616,8 @@ int main(int argc, char *argv[]) tox_callback_friendmessage(m, print_message, NULL); tox_callback_namechange(m, print_nickchange, NULL); tox_callback_statusmessage(m, print_statuschange, NULL); + m_callback_group_invite(m, print_invite, NULL); + m_callback_group_message(m, print_groupmessage, NULL); initscr(); noecho(); diff --git a/testing/nTox.h b/testing/nTox.h index a72ce0c2..8a41965b 100644 --- a/testing/nTox.h +++ b/testing/nTox.h @@ -31,7 +31,7 @@ #include #include "../toxcore/tox.h" - +#include "../toxcore/Messenger.h" //TODO: remove this #define STRING_LENGTH 256 #define HISTORY 50 #define PUB_KEY_BYTES 32 diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 177b8eb0..99279d5e 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -673,6 +673,40 @@ static int group_num(Messenger *m, uint8_t *group_public_key) return -1; } +/* Set the callback for group invites. + * + * Function(Messenger *m, int friendnumber, uint8_t *group_public_key, void *userdata) + */ +void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, void *), void *userdata) +{ + m->group_invite = function; + m->group_invite_userdata = userdata; +} + +/* Set the callback for group messages. + * + * Function(Messenger *m, int groupnumber, uint8_t * message, uint16_t length, void *userdata) + */ +void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void *), + void *userdata) +{ + m->group_message = function; + m->group_message_userdata = userdata; +} +static void group_message_function(Group_Chat *chat, int peer_number, uint8_t *message, uint16_t length, void *userdata) +{ + Messenger *m = userdata; + uint32_t i; + + for (i = 0; i < m->numchats; ++i) { //TODO: remove this + if (m->chats[i] == chat) + break; + } + + if (m->group_message) + (*m->group_message)(m, i, message, length, m->group_invite_userdata); +} + /* Creates a new groupchat and puts it in the chats array. * * return group number on success. @@ -689,6 +723,7 @@ int add_groupchat(Messenger *m) if (newchat == NULL) return -1; + callback_groupmessage(newchat, &group_message_function, m); m->chats[i] = newchat; return i; } @@ -705,6 +740,8 @@ int add_groupchat(Messenger *m) if (temp[m->numchats] == NULL) return -1; + m->chats = temp; + callback_groupmessage(temp[m->numchats], &group_message_function, m); ++m->numchats; return (m->numchats - 1); } @@ -714,7 +751,7 @@ int add_groupchat(Messenger *m) * return 0 on success. * return -1 if failure. */ -static int del_groupchat(Messenger *m, int groupnumber) +int del_groupchat(Messenger *m, int groupnumber) { if ((unsigned int)groupnumber >= m->numchats) return -1; @@ -748,9 +785,42 @@ static int del_groupchat(Messenger *m, int groupnumber) return 0; } +/* return 1 if that friend was invited to the group + * return 0 if the friend was not or error. + */ +static uint8_t group_invited(Messenger *m, int friendnumber, int groupnumber) +{ + //TODO: this function; + return 1; +} + +/* invite friendnumber to groupnumber + * return 0 on success + * return -1 on failure + */ +int invite_friend(Messenger *m, int friendnumber, int groupnumber) +{ + if (friend_not_valid(m, friendnumber) || (unsigned int)groupnumber >= m->numchats) + return -1; + + if (m->chats == NULL) + return -1; + + if (m->friendlist[friendnumber].status == NOFRIEND || m->chats[groupnumber] == NULL) + return -1; + + //TODO: store invited friends. + if (write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_GROUPCHAT, m->chats[groupnumber]->self_public_key, + crypto_box_PUBLICKEYBYTES) == 0) + return -1; + + return 0; +} + + /* Join a group (you need to have been invited first.) * - * returns 0 on success + * returns group number on success * returns -1 on failure. */ int join_groupchat(Messenger *m, int friendnumber, uint8_t *friend_group_public_key) @@ -770,12 +840,34 @@ int join_groupchat(Messenger *m, int friendnumber, uint8_t *friend_group_public_ if (write_cryptpacket_id(m, friendnumber, PACKET_ID_JOIN_GROUPCHAT, data, sizeof(data))) { chat_bootstrap_nonlazy(m->chats[groupnum], get_friend_ipport(m, friendnumber), friend_group_public_key); //TODO: check if ip returned is zero? - return 0; + return groupnum; } return -1; } +/* send a group message + * return 0 on success + * return -1 on failure + */ + +int group_message_send(Messenger *m, int groupnumber, uint8_t *message, uint32_t length) +{ + if ((unsigned int)groupnumber >= m->numchats) + return -1; + + if (m->chats == NULL) + return -1; + + if (m->chats[groupnumber] == NULL) + return -1; + + if (group_sendmessage(m->chats[groupnumber], message, length) > 0) + return 0; + + return -1; +} + static int handle_group(void *object, IP_Port source, uint8_t *packet, uint32_t length) { Messenger *m = object; @@ -1064,6 +1156,29 @@ void doFriends(Messenger *m) break; } + + case PACKET_ID_INVITE_GROUPCHAT: { + if (data_length != crypto_box_PUBLICKEYBYTES) + break; + + if (m->group_invite) + (*m->group_invite)(m, i, data, m->group_invite_userdata); + } + + case PACKET_ID_JOIN_GROUPCHAT: { + if (data_length != crypto_box_PUBLICKEYBYTES * 2) + break; + + int groupnum = group_num(m, data); + + if (groupnum == -1) + break; + + if (!group_invited(m, i, groupnum)) + break; + + group_newpeer(m->chats[groupnum], data + crypto_box_PUBLICKEYBYTES); + } } } else { if (is_cryptoconnected(m->net_crypto, diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 7649a779..0656c736 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -157,7 +157,10 @@ typedef struct Messenger { void *friend_statuschange_userdata; void (*friend_connectionstatuschange)(struct Messenger *m, int, uint8_t, void *); void *friend_connectionstatuschange_userdata; - + void (*group_invite)(struct Messenger *m, int, uint8_t *, void *); + void *group_invite_userdata; + void (*group_message)(struct Messenger *m, int, uint8_t *, uint16_t, void *); + void *group_message_userdata; } Messenger; @@ -369,6 +372,57 @@ void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int, u */ void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, int, uint8_t, void *), void *userdata); +/**********GROUP CHATS************/ + +/* Set the callback for group invites. + * + * Function(Messenger *m, int friendnumber, uint8_t *group_public_key, void *userdata) + */ +void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, void *), void *userdata); + +/* Set the callback for group messages. + * + * Function(Messenger *m, int groupnumber, uint8_t * message, uint16_t length, void *userdata) + */ +void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void *), + void *userdata); + +/* Creates a new groupchat and puts it in the chats array. + * + * return group number on success. + * return -1 on failure. + */ +int add_groupchat(Messenger *m); + +/* Delete a groupchat from the chats array. + * + * return 0 on success. + * return -1 if failure. + */ +int del_groupchat(Messenger *m, int groupnumber); + +/* invite friendnumber to groupnumber + * return 0 on success + * return -1 on failure + */ +int invite_friend(Messenger *m, int friendnumber, int groupnumber); + +/* Join a group (you need to have been invited first.) + * + * returns group number on success + * returns -1 on failure. + */ +int join_groupchat(Messenger *m, int friendnumber, uint8_t *friend_group_public_key); + +/* send a group message + * return 0 on success + * return -1 on failure + */ + +int group_message_send(Messenger *m, int groupnumber, uint8_t *message, uint32_t length); + +/*********************************/ + /* Run this at startup. * return allocated instance of Messenger on success. * return 0 if there are problems. diff --git a/toxcore/group_chats.h b/toxcore/group_chats.h index 535b46db..78a5488c 100644 --- a/toxcore/group_chats.h +++ b/toxcore/group_chats.h @@ -77,6 +77,7 @@ void callback_groupmessage(Group_Chat *chat, void (*function)(Group_Chat *chat, /* * Send a message to the group. * + * returns the number of peers it has sent it to. */ uint32_t group_sendmessage(Group_Chat *chat, uint8_t *message, uint32_t length); From f8b979a92a8c316c49bed28e158a468a2f74346c Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 12 Sep 2013 20:29:30 -0400 Subject: [PATCH 3/3] Put group chat functions in the public API. Group chats are not complete, they seem to work very well though. This means that the functions will change. --- testing/nTox.c | 16 +++++------ testing/nTox.h | 1 - toxcore/tox.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ toxcore/tox.h | 53 +++++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+), 9 deletions(-) diff --git a/testing/nTox.c b/testing/nTox.c index d6e25ac0..fa3b5b8c 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -354,7 +354,7 @@ void line_eval(Tox *m, char *line) new_lines(idstring); } else if (inpt_command == 'g') { //create new group chat char msg[256]; - sprintf(msg, "[g] Created new group chat with number: %u", add_groupchat(m)); + sprintf(msg, "[g] Created new group chat with number: %u", tox_add_groupchat(m)); new_lines(msg); } else if (inpt_command == 'i') { //invite friendnum to groupnum char *posi[1]; @@ -362,7 +362,7 @@ void line_eval(Tox *m, char *line) int groupnumber = strtoul(*posi + 1, NULL, 0); char msg[256]; sprintf(msg, "[g] Invited friend number %u to group number %u, returned: %u (0 means success)", friendnumber, - groupnumber, invite_friend(m, friendnumber, groupnumber)); + groupnumber, tox_invite_friend(m, friendnumber, groupnumber)); new_lines(msg); } else if (inpt_command == 'z') { //send message to groupnum char *posi[1]; @@ -371,7 +371,7 @@ void line_eval(Tox *m, char *line) if (**posi != 0) { char msg[256 + 1024]; sprintf(msg, "[g] sent message: %s to group num: %u returned: %u (0 means success)", *posi + 1, groupnumber, - group_message_send(m, groupnumber, (uint8_t *)*posi + 1, strlen(*posi + 1) + 1)); + tox_group_message_send(m, groupnumber, (uint8_t *)*posi + 1, strlen(*posi + 1) + 1)); new_lines(msg); } @@ -556,15 +556,15 @@ void print_help(void) puts("\t-f\t-\tSpecify a keyfile to read (or write to) from."); } -void print_invite(Messenger *m, int friendnumber, uint8_t *group_public_key, void *userdata) +void print_invite(Tox *m, int friendnumber, uint8_t *group_public_key, void *userdata) { char msg[256]; sprintf(msg, "[i] recieved group chat invite from: %u, auto accepting and joining. group number: %u", friendnumber, - join_groupchat(m, friendnumber, group_public_key)); + tox_join_groupchat(m, friendnumber, group_public_key)); new_lines(msg); } -void print_groupmessage(Messenger *m, int groupnumber, uint8_t *message, uint16_t length, void *userdata) +void print_groupmessage(Tox *m, int groupnumber, uint8_t *message, uint16_t length, void *userdata) { char msg[256 + length]; sprintf(msg, "[g] %u: %s", groupnumber, message); @@ -616,8 +616,8 @@ int main(int argc, char *argv[]) tox_callback_friendmessage(m, print_message, NULL); tox_callback_namechange(m, print_nickchange, NULL); tox_callback_statusmessage(m, print_statuschange, NULL); - m_callback_group_invite(m, print_invite, NULL); - m_callback_group_message(m, print_groupmessage, NULL); + tox_callback_group_invite(m, print_invite, NULL); + tox_callback_group_message(m, print_groupmessage, NULL); initscr(); noecho(); diff --git a/testing/nTox.h b/testing/nTox.h index 8a41965b..2cd5db09 100644 --- a/testing/nTox.h +++ b/testing/nTox.h @@ -31,7 +31,6 @@ #include #include "../toxcore/tox.h" -#include "../toxcore/Messenger.h" //TODO: remove this #define STRING_LENGTH 256 #define HISTORY 50 #define PUB_KEY_BYTES 32 diff --git a/toxcore/tox.c b/toxcore/tox.c index 54bbd9f0..417f1af3 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -366,6 +366,81 @@ void tox_callback_connectionstatus(void *tox, void (*function)(Messenger *tox, i m_callback_connectionstatus(m, function, userdata); } +/**********GROUP CHAT FUNCTIONS: WARNING WILL BREAK A LOT************/ + +/* Set the callback for group invites. + * + * Function(Tox *tox, int friendnumber, uint8_t *group_public_key, void *userdata) + */ +void tox_callback_group_invite(void *tox, void (*function)(Messenger *tox, int, uint8_t *, void *), void *userdata) +{ + Messenger *m = tox; + m_callback_group_invite(m, function, userdata); +} +/* Set the callback for group messages. + * + * Function(Tox *tox, int groupnumber, uint8_t * message, uint16_t length, void *userdata) + */ +void tox_callback_group_message(void *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *), + void *userdata) +{ + Messenger *m = tox; + m_callback_group_message(m, function, userdata); +} +/* Creates a new groupchat and puts it in the chats array. + * + * return group number on success. + * return -1 on failure. + */ +int tox_add_groupchat(void *tox) +{ + Messenger *m = tox; + return add_groupchat(m); +} +/* Delete a groupchat from the chats array. + * + * return 0 on success. + * return -1 if failure. + */ +int tox_del_groupchat(void *tox, int groupnumber) +{ + Messenger *m = tox; + return del_groupchat(m, groupnumber); +} +/* invite friendnumber to groupnumber + * return 0 on success + * return -1 on failure + */ +int tox_invite_friend(void *tox, int friendnumber, int groupnumber) +{ + Messenger *m = tox; + return invite_friend(m, friendnumber, groupnumber); +} +/* Join a group (you need to have been invited first.) + * + * returns group number on success + * returns -1 on failure. + */ +int tox_join_groupchat(void *tox, int friendnumber, uint8_t *friend_group_public_key) +{ + Messenger *m = tox; + return join_groupchat(m, friendnumber, friend_group_public_key); +} + +/* send a group message + * return 0 on success + * return -1 on failure + */ +int tox_group_message_send(void *tox, int groupnumber, uint8_t *message, uint32_t length) +{ + Messenger *m = tox; + return group_message_send(m, groupnumber, message, length); +} + + + +/******************END OF GROUP CHAT FUNCTIONS************************/ + /* Use this function to bootstrap the client. * Sends a get nodes request to the given node with ip port and public_key. */ diff --git a/toxcore/tox.h b/toxcore/tox.h index 811e798b..6d5db49f 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -289,6 +289,59 @@ void tox_callback_read_receipt(Tox *tox, void (*function)(Tox *tox, int, uint32_ */ void tox_callback_connectionstatus(Tox *tox, void (*function)(Tox *tox, int, uint8_t, void *), void *userdata); +/**********GROUP CHAT FUNCTIONS: WARNING WILL BREAK A LOT************/ + +/* Set the callback for group invites. + * + * Function(Tox *tox, int friendnumber, uint8_t *group_public_key, void *userdata) + */ +void tox_callback_group_invite(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, void *), void *userdata); + +/* Set the callback for group messages. + * + * Function(Tox *tox, int groupnumber, uint8_t * message, uint16_t length, void *userdata) + */ +void tox_callback_group_message(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *), + void *userdata); + +/* Creates a new groupchat and puts it in the chats array. + * + * return group number on success. + * return -1 on failure. + */ +int tox_add_groupchat(Tox *tox); + +/* Delete a groupchat from the chats array. + * + * return 0 on success. + * return -1 if failure. + */ +int tox_del_groupchat(Tox *tox, int groupnumber); + +/* invite friendnumber to groupnumber + * return 0 on success + * return -1 on failure + */ +int tox_invite_friend(Tox *tox, int friendnumber, int groupnumber); + +/* Join a group (you need to have been invited first.) + * + * returns group number on success + * returns -1 on failure. + */ +int tox_join_groupchat(Tox *tox, int friendnumber, uint8_t *friend_group_public_key); + + +/* send a group message + * return 0 on success + * return -1 on failure + */ +int tox_group_message_send(Tox *tox, int groupnumber, uint8_t *message, uint32_t length); + + + +/******************END OF GROUP CHAT FUNCTIONS************************/ + /* Use this function to bootstrap the client. * Sends a get nodes request to the given node with ip port and public_key. */