From 71b48516e87bf826b8eb253d5750a6493a8282e2 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 14 Feb 2014 21:16:31 -0500 Subject: Added custom userpackets. A way to send and handle lossy UDP packets coming from friends. Will be used for A/V. --- toxcore/Messenger.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++-- toxcore/Messenger.h | 25 +++++++++++ toxcore/network.h | 6 +++ 3 files changed, 153 insertions(+), 3 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index fef2e9e5..cf3a60bf 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -43,6 +43,71 @@ static uint8_t friend_not_valid(Messenger *m, int friendnumber) return (unsigned int)friendnumber >= m->numfriends; } +static int add_online_friend(Messenger *m, int friendnumber) +{ + if (friend_not_valid(m, friendnumber)) + return -1; + + IP_Port temp_ip_port = get_friend_ipport(m, friendnumber); + + if (temp_ip_port.port == 0) + return -1; + + uint32_t i; + + for (i = 0; i < m->numonline_friends; ++i) { + if (m->online_friendlist[i].friend_num == (uint32_t)friendnumber) + return 0; + } + + Online_Friend *temp; + temp = realloc(m->online_friendlist, sizeof(Online_Friend) * (m->numonline_friends + 1)); + + if (temp == NULL) + return -1; + + m->online_friendlist = temp; + m->online_friendlist[m->numonline_friends].friend_num = friendnumber; + m->online_friendlist[m->numonline_friends].ip_port = temp_ip_port; + ++m->numonline_friends; + return 0; +} + + +static int remove_online_friend(Messenger *m, int friendnumber) +{ + uint32_t i; + Online_Friend *temp; + + for (i = 0; i < m->numonline_friends; ++i) { + /* Equal */ + if (m->online_friendlist[i].friend_num == (uint32_t)friendnumber) { + --m->numonline_friends; + + if (m->numonline_friends != i) { + memcpy( &m->online_friendlist[i], + &m->online_friendlist[m->numonline_friends], + sizeof(Online_Friend) ); + } + + if (m->numonline_friends == 0) { + free(m->online_friendlist); + m->online_friendlist = NULL; + return 0; + } + + temp = realloc(m->online_friendlist, sizeof(Online_Friend) * (m->numonline_friends)); + + if (temp == NULL) + return -1; + + m->online_friendlist = temp; + return 0; + } + } + + return -1; +} /* Set the size of the friend list to numfriends. * * return -1 if realloc fails. @@ -274,7 +339,7 @@ int m_delfriend(Messenger *m, int friendnumber) return -1; if (m->friendlist[friendnumber].status == FRIEND_ONLINE) - --m->numonline_friends; + remove_online_friend(m, friendnumber); onion_delfriend(m->onion_c, m->friendlist[friendnumber].onion_friendnum); crypto_kill(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id); @@ -670,9 +735,9 @@ static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_ if (is_online != was_online) { if (was_online) { break_files(m, friendnumber); - --m->numonline_friends; + remove_online_friend(m, friendnumber); } else { - ++m->numonline_friends; + add_online_friend(m, friendnumber); } m->friend_connectionstatuschange(m, friendnumber, is_online, m->friend_connectionstatuschange_userdata); @@ -1500,6 +1565,60 @@ int m_msi_packet(Messenger *m, int friendnumber, uint8_t *data, uint16_t length) return write_cryptpacket_id(m, friendnumber, PACKET_ID_MSI, data, length); } +static int friendnum_from_ip_port(Messenger *m, IP_Port ip_port) +{ + uint32_t i; + + for (i = 0; i < m->numonline_friends; ++i) { + if (ipport_equal(&m->online_friendlist[i].ip_port, &ip_port)) + return m->online_friendlist[i].friend_num; + } + + return -1; +} + +static int handle_custom_user_packet(void *object, IP_Port source, uint8_t *packet, uint32_t length) +{ + Messenger *m = object; + int friend_num = friendnum_from_ip_port(m, source); + + if (friend_num == -1) + return 1; + + if (m->friendlist[friend_num].packethandlers[packet[0] % TOTAL_USERPACKETS].function) + return m->friendlist[friend_num].packethandlers[packet[0] % TOTAL_USERPACKETS].function( + m->friendlist[friend_num].packethandlers[packet[0] % TOTAL_USERPACKETS].object, source, packet, length); + + return 1; +} + + +int custom_user_packet_registerhandler(Messenger *m, int friendnumber, uint8_t byte, packet_handler_callback cb, + void *object) +{ + if (friend_not_valid(m, friendnumber)) + return -1; + + if (byte < NET_PACKET_CUSTOM_RANGE_START || byte >= NET_PACKET_CUSTOM_RANGE_END) + return -1; + + m->friendlist[friendnumber].packethandlers[byte % TOTAL_USERPACKETS].function = cb; + m->friendlist[friendnumber].packethandlers[byte % TOTAL_USERPACKETS].object = object; + networking_registerhandler(m->net, byte, handle_custom_user_packet, m); + return 0; +} + +int send_custom_user_packet(Messenger *m, int friendnumber, uint8_t *data, uint32_t length) +{ + IP_Port ip_port = get_friend_ipport(m, friendnumber); + + if (ip_port.port == 0) + return -1; + + return sendpacket(m->net, ip_port, data, length); +} + + /* Function to filter out some friend requests*/ static int friend_already_added(uint8_t *client_id, void *data) { diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 40e857d1..375e2025 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -155,8 +155,15 @@ typedef struct { struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES]; int invited_groups[MAX_INVITED_GROUPS]; uint16_t invited_groups_num; + + Packet_Handles packethandlers[TOTAL_USERPACKETS]; } Friend; +typedef struct { + uint32_t friend_num; + IP_Port ip_port; +} Online_Friend; + typedef struct Messenger { Networking_Core *net; @@ -178,6 +185,8 @@ typedef struct Messenger { Friend *friendlist; uint32_t numfriends; + + Online_Friend *online_friendlist; uint32_t numonline_friends; Group_Chat **chats; @@ -628,6 +637,22 @@ int m_msi_packet(Messenger *m, int friendnumber, uint8_t *data, uint16_t length) /**********************************************/ +/* Set handlers for custom user packets (RTP packets for example.) + * + * return -1 on failure. + * return 0 on success. + */ +int custom_user_packet_registerhandler(Messenger *m, int friendnumber, uint8_t byte, packet_handler_callback cb, + void *object); + +/* High level function to send custom user packets. + * + * return -1 on failure. + * return number of bytes sent on success. + */ +int send_custom_user_packet(Messenger *m, int friendnumber, uint8_t *data, uint32_t length); + +/**********************************************/ /* Run this at startup. * return allocated instance of Messenger on success. * return 0 if there are problems. diff --git a/toxcore/network.h b/toxcore/network.h index 19c9ca63..aaf89f19 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -129,6 +129,12 @@ typedef int sock_t; #define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */ #define NET_PACKET_GROUP_CHATS 48 /* Group chats packet ID. */ +/* Range of ids that custom user packets can use. */ +#define NET_PACKET_CUSTOM_RANGE_START 64 +#define NET_PACKET_CUSTOM_RANGE_END 96 + +#define TOTAL_USERPACKETS (NET_PACKET_CUSTOM_RANGE_END - NET_PACKET_CUSTOM_RANGE_START) + /* See: docs/Prevent_Tracking.txt and onion.{c, h} */ #define NET_PACKET_ONION_SEND_INITIAL 128 #define NET_PACKET_ONION_SEND_1 129 -- cgit v1.2.3