From b7f989266df854fcd7772bec58e408c7359087ff Mon Sep 17 00:00:00 2001 From: Sebastian Stal Date: Mon, 5 Aug 2013 12:30:07 -0700 Subject: Add functions for dealing with userstatus kinds. --- core/Messenger.c | 88 ++++++++++++++++++++++++++++++++++++++++++++------------ core/Messenger.h | 38 ++++++++++++++++++++---- 2 files changed, 102 insertions(+), 24 deletions(-) (limited to 'core') diff --git a/core/Messenger.c b/core/Messenger.c index 57d485bb..d8bf3413 100644 --- a/core/Messenger.c +++ b/core/Messenger.c @@ -35,6 +35,7 @@ typedef struct { uint8_t *userstatus; uint16_t userstatus_length; uint8_t userstatus_sent; + USERSTATUS_KIND userstatus_kind; uint16_t info_size; /* length of the info */ } Friend; @@ -45,6 +46,7 @@ static uint16_t self_name_length; static uint8_t *self_userstatus; static uint16_t self_userstatus_len; +static USERSTATUS_KIND self_userstatus_kind; #define MAX_NUM_FRIENDS 256 @@ -98,12 +100,12 @@ int getclient_id(int friend_id, uint8_t *client_id) * return FAERR_NOMESSAGE if no message (message length must be >= 1 byte) * return FAERR_OWNKEY if user's own key * return FAERR_ALREADYSENT if friend request already sent or already a friend - * return FAERR_UNKNOWN for unknown error + * return FAERR_UNKNOWN for unknown error */ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) { - if (length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + if (length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES + - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES)) return FAERR_TOOLONG; if (length < 1) @@ -123,6 +125,7 @@ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); friendlist[i].userstatus = calloc(1, 1); friendlist[i].userstatus_length = 1; + friendlist[i].userstatus_kind = USERSTATUS_KIND_OFFLINE; memcpy(friendlist[i].info, data, length); friendlist[i].info_size = length; @@ -205,7 +208,7 @@ int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length) return write_cryptpacket(friendlist[friendnumber].crypt_connection_id, temp, length + 1); } -/* send a name packet to friendnumber +/* send a name packet to friendnumber length is the length with the NULL terminator*/ static int m_sendname(int friendnumber, uint8_t * name, uint16_t length) { @@ -247,14 +250,14 @@ int setname(uint8_t * name, uint16_t length) } /* get our nickname - put it in name + put it in name name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes. return the length of the name */ uint16_t getself_name(uint8_t *name) { memcpy(name, self_name, self_name_length); return self_name_length; -} +} /* get name of friendnumber put it in name @@ -269,10 +272,13 @@ int getname(int friendnumber, uint8_t * name) return 0; } -int m_set_userstatus(uint8_t *status, uint16_t length) +int m_set_userstatus(USERSTATUS_KIND kind, uint8_t *status, uint16_t length) { if (length > MAX_USERSTATUS_LENGTH) return -1; + if (kind != USERSTATUS_KIND_RETAIN) { + self_userstatus_kind = kind; + } uint8_t *newstatus = calloc(length, 1); memcpy(newstatus, status, length); free(self_userstatus); @@ -285,6 +291,20 @@ int m_set_userstatus(uint8_t *status, uint16_t length) return 0; } +int m_set_userstatus_kind(USERSTATUS_KIND kind) { + if (kind >= USERSTATUS_KIND_INVALID) { + return -1; + } + if (kind == USERSTATUS_KIND_RETAIN) { + return 0; + } + self_userstatus_kind = kind; + uint32_t i; + for (i = 0; i < numfriends; ++i) + friendlist[i].userstatus_sent = 0; + return 0; +} + /* return the size of friendnumber's user status guaranteed to be at most MAX_USERSTATUS_LENGTH */ int m_get_userstatus_size(int friendnumber) @@ -305,11 +325,33 @@ int m_copy_userstatus(int friendnumber, uint8_t * buf, uint32_t maxlen) return 0; } +int m_copy_self_userstatus(uint8_t * buf, uint32_t maxlen) +{ + memset(buf, 0, maxlen); + memcpy(buf, self_userstatus, MIN(maxlen, MAX_USERSTATUS_LENGTH) - 1); + return 0; +} + +USERSTATUS_KIND m_get_userstatus_kind(int friendnumber) { + if (friendnumber >= numfriends || friendnumber < 0) + return USERSTATUS_KIND_INVALID; + USERSTATUS_KIND uk = friendlist[friendnumber].userstatus_kind; + if (uk >= USERSTATUS_KIND_INVALID) { + uk = USERSTATUS_KIND_ONLINE; + } + return uk; +} + +USERSTATUS_KIND m_get_self_userstatus_kind(void) { + return self_userstatus_kind; +} + static int send_userstatus(int friendnumber, uint8_t * status, uint16_t length) { - uint8_t *thepacket = malloc(length + 1); - memcpy(thepacket + 1, status, length); + uint8_t *thepacket = malloc(length + 2); + memcpy(thepacket + 2, status, length); thepacket[0] = PACKET_ID_USERSTATUS; + thepacket[1] = self_userstatus_kind; int written = write_cryptpacket(friendlist[friendnumber].crypt_connection_id, thepacket, length + 1); free(thepacket); return written; @@ -327,6 +369,11 @@ static int set_friend_userstatus(int friendnumber, uint8_t * status, uint16_t le return 0; } +static void set_friend_userstatus_kind(int friendnumber, USERSTATUS_KIND k) +{ + friendlist[friendnumber].userstatus_kind = k; +} + /* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); static uint8_t friend_request_isset = 0; */ /* set the function that will be executed when a friend request is received. */ @@ -353,9 +400,9 @@ void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t)) friend_namechange_isset = 1; } -static void (*friend_statuschange)(int, uint8_t *, uint16_t); +static void (*friend_statuschange)(int, USERSTATUS_KIND, uint8_t *, uint16_t); static uint8_t friend_statuschange_isset = 0; -void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t)) +void m_callback_userstatus(void (*function)(int, USERSTATUS_KIND, uint8_t *, uint16_t)) { friend_statuschange = function; friend_statuschange_isset = 1; @@ -366,7 +413,7 @@ void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t)) int initMessenger(void) { new_keys(); - m_set_userstatus((uint8_t*)"Online", sizeof("Online")); + m_set_userstatus(USERSTATUS_KIND_ONLINE, (uint8_t*)"Online", sizeof("Online")); initNetCrypto(); IP ip; ip.i = 0; @@ -438,12 +485,17 @@ static void doFriends(void) break; } case PACKET_ID_USERSTATUS: { - uint8_t *status = calloc(MIN(len - 1, MAX_USERSTATUS_LENGTH), 1); - memcpy(status, temp + 1, MIN(len - 1, MAX_USERSTATUS_LENGTH)); - if (friend_statuschange_isset) - friend_statuschange(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH)); - set_friend_userstatus(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH)); - free(status); + if (len > 2) { + uint8_t *status = calloc(MIN(len - 2, MAX_USERSTATUS_LENGTH), 1); + memcpy(status, temp + 2, MIN(len - 2, MAX_USERSTATUS_LENGTH)); + if (friend_statuschange_isset) + friend_statuschange(i, temp[1], status, MIN(len - 2, MAX_USERSTATUS_LENGTH)); + set_friend_userstatus(i, status, MIN(len - 2, MAX_USERSTATUS_LENGTH)); + free(status); + } else if (friend_statuschange_isset) { + friend_statuschange(i, temp[1], friendlist[i].userstatus, friendlist[i].userstatus_length); + } + set_friend_userstatus_kind(i, temp[1]); break; } case PACKET_ID_MESSAGE: { diff --git a/core/Messenger.h b/core/Messenger.h index 20b38caa..8940aadd 100644 --- a/core/Messenger.h +++ b/core/Messenger.h @@ -60,6 +60,22 @@ extern "C" { /* don't assume MAX_USERSTATUS_LENGTH will stay at 128, it may be increased to an absurdly large number later */ +/* USERSTATUS_KIND + * Represents the different kinds of userstatus + * someone can have. + * More on this later... */ + +typedef enum { + USERSTATUS_KIND_RETAIN = (uint8_t)0, /* This is a special value that must not be returned by + * m_get_userstatus_kind. You can pass it into m_set_userstatus + * to keep the current USERSTATUS_KIND. */ + USERSTATUS_KIND_ONLINE, /* Recommended representation: Green. */ + USERSTATUS_KIND_AWAY, /* Recommended representation: Orange, or yellow. */ + USERSTATUS_KIND_BUSY, /* Recommended representation: Red. */ + USERSTATUS_KIND_OFFLINE, /* Recommended representation: Grey, semi-transparent. */ + USERSTATUS_KIND_INVALID, +} USERSTATUS_KIND; + /* * add a friend * set the data that will be sent along with friend request @@ -70,7 +86,7 @@ extern "C" { * return -2 if no message (message length must be >= 1 byte) * return -3 if user's own key * return -4 if friend request already sent or already a friend - * return -5 for unknown error + * return -5 for unknown error */ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length); @@ -114,7 +130,7 @@ int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length); int setname(uint8_t *name, uint16_t length); /* get our nickname - put it in name + put it in name return the length of the name*/ uint16_t getself_name(uint8_t *name); @@ -128,7 +144,8 @@ int getname(int friendnumber, uint8_t *name); /* set our user status you are responsible for freeing status after returns 0 on success, -1 on failure */ -int m_set_userstatus(uint8_t *status, uint16_t length); +int m_set_userstatus(USERSTATUS_KIND kind, uint8_t *status, uint16_t length); +int m_set_userstatus_kind(USERSTATUS_KIND kind); /* return the length of friendnumber's user status, including null @@ -136,8 +153,17 @@ int m_set_userstatus(uint8_t *status, uint16_t length); int m_get_userstatus_size(int friendnumber); /* copy friendnumber's userstatus into buf, truncating if size is over maxlen - get the size you need to allocate from m_get_userstatus_size */ + get the size you need to allocate from m_get_userstatus_size + The self variant will copy our own userstatus. */ int m_copy_userstatus(int friendnumber, uint8_t *buf, uint32_t maxlen); +int m_copy_self_userstatus(uint8_t *buf, uint32_t maxlen); + +/* Return one of USERSTATUS_KIND values, except USERSTATUS_KIND_RETAIN. + * Values unknown to your application should be represented as USERSTATUS_KIND_ONLINE. + * As above, the self variant will return our own USERSTATUS_KIND. + * If friendnumber is invalid, this shall return USERSTATUS_KIND_INVALID. */ +USERSTATUS_KIND m_get_userstatus_kind(int friendnumber); +USERSTATUS_KIND m_get_self_userstatus_kind(void); /* set the function that will be executed when a friend request is received. function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ @@ -153,9 +179,9 @@ void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t)); void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t)); /* set the callback for user status changes - function(int friendnumber, uint8_t *newstatus, uint16_t length) + function(int friendnumber, USERSTATUS_KIND kind, uint8_t *newstatus, uint16_t length) you are not responsible for freeing newstatus */ -void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t)); +void m_callback_userstatus(void (*function)(int, USERSTATUS_KIND, uint8_t *, uint16_t)); /* run this at startup returns 0 if no connection problems -- cgit v1.2.3 From 071ac463082646189ade6e31bb3f6051516f81b2 Mon Sep 17 00:00:00 2001 From: plutooo Date: Mon, 5 Aug 2013 12:51:58 -0700 Subject: core: Rewrote ping-module, better performance and cleaner code. --- core/CMakeLists.txt | 4 ++- core/DHT.c | 61 +++------------------------------- core/ping.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++ core/ping.h | 13 ++++++++ core/util.c | 31 +++++++++++++++++ core/util.h | 10 ++++++ 6 files changed, 156 insertions(+), 58 deletions(-) create mode 100644 core/ping.c create mode 100644 core/ping.h create mode 100644 core/util.c create mode 100644 core/util.h (limited to 'core') diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index eacb772c..55a41912 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -8,7 +8,9 @@ set(core_sources net_crypto.c friend_requests.c LAN_discovery.c - Messenger.c) + Messenger.c + util.c + ping.c) if(SHARED_TOXCORE) add_library(toxcore SHARED ${core_sources}) diff --git a/core/DHT.c b/core/DHT.c index 6375b86b..01abfdd2 100644 --- a/core/DHT.c +++ b/core/DHT.c @@ -24,6 +24,7 @@ /*----------------------------------------------------------------------------------*/ #include "DHT.h" +#include "ping.h" /* maximum number of clients stored per friend. */ #define MAX_FRIEND_CLIENTS 8 @@ -109,7 +110,6 @@ uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; static Client_data close_clientlist[LCLIENT_LIST]; static Friend * friends_list; static uint16_t num_friends; -static Pinged pings[LPING_ARRAY]; static Pinged send_nodes[LSEND_NODES_ARRAY]; /*----------------------------------------------------------------------------------*/ @@ -426,35 +426,6 @@ static void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nod } } -/* check if we are currently pinging an ip_port and/or a ping_id variables with - * values of zero will not be checked. If we are already, return 1 else return 0 - * - * TODO: optimize this - */ -static int is_pinging(IP_Port ip_port, uint64_t ping_id) -{ - uint32_t i; - uint8_t pinging; - uint64_t temp_time = unix_time(); - - for (i = 0; i < LPING_ARRAY; ++i ) { - if (!is_timeout(temp_time, pings[i].timestamp, PING_TIMEOUT)) { - pinging = 0; - - if (ip_port.ip.i != 0 && ipport_equal(pings[i].ip_port, ip_port)) - ++pinging; - - if (ping_id != 0 && pings[i].ping_id == ping_id) - ++pinging; - - if (pinging == ((ping_id != 0) + (ip_port.ip.i != 0))) - return 1; - } - } - - return 0; -} - /* Same as last function but for get_node requests. */ static int is_gettingnodes(IP_Port ip_port, uint64_t ping_id) { @@ -480,32 +451,6 @@ static int is_gettingnodes(IP_Port ip_port, uint64_t ping_id) return 0; } -/* Add a new ping request to the list of ping requests - * returns the ping_id to put in the ping request - * returns 0 if problem. - * - * TODO: optimize this - */ -static uint64_t add_pinging(IP_Port ip_port) -{ - uint32_t i, j; - uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int(); - uint64_t temp_time = unix_time(); - - for(i = 0; i < PING_TIMEOUT; ++i ) { - for(j = 0; j < LPING_ARRAY; ++j ) { - if(is_timeout(temp_time, pings[j].timestamp, PING_TIMEOUT - i)) { - pings[j].timestamp = temp_time; - pings[j].ip_port = ip_port; - pings[j].ping_id = ping_id; - return ping_id; - } - } - } - - return 0; -} - /* Same but for get node requests */ static uint64_t add_gettingnodes(IP_Port ip_port) { @@ -536,7 +481,7 @@ static int pingreq(IP_Port ip_port, uint8_t * public_key) if(id_equal(public_key, self_public_key) || is_pinging(ip_port, 0)) return 1; - uint64_t ping_id = add_pinging(ip_port); + uint64_t ping_id = add_ping(ip_port); if(ping_id == 0) return 1; @@ -1301,6 +1246,8 @@ void DHT_save(uint8_t * data) */ int DHT_load(uint8_t * data, uint32_t size) { + init_ping(); + if(size < sizeof(close_clientlist)) return -1; diff --git a/core/ping.c b/core/ping.c new file mode 100644 index 00000000..8a7d534f --- /dev/null +++ b/core/ping.c @@ -0,0 +1,95 @@ +/* + * ping.c -- Buffered pinging using cyclic arrays. + * + * This file is donated to the Tox Project. + * Copyright 2013 plutooo + */ + +#include +#include + +#include "network.h" +#include "util.h" + +#define PING_NUM_MAX 256 +#define PING_TIMEOUT 5 // 5s + +typedef struct { + IP_Port ipp; + uint64_t id; + uint64_t timestamp; +} pinged_t; + +static pinged_t pings[PING_NUM_MAX]; +static size_t num_pings; +static size_t pos_pings; + + +void init_ping() { + num_pings = 0; + pos_pings = 0; +} + +static bool is_timeout(uint64_t time) { + return (time + PING_TIMEOUT) < now(); +} + +static void remove_timeouts() { // O(n) + size_t i, id; + size_t new_pos = pos_pings; + size_t new_num = num_pings; + + // Loop through buffer, oldest first + for(i=0; i + +void init_ping(); +uint64_t add_ping(IP_Port ipp); +bool is_pinging(IP_Port ipp, uint64_t ping_id); + diff --git a/core/util.c b/core/util.c new file mode 100644 index 00000000..6b40dad7 --- /dev/null +++ b/core/util.c @@ -0,0 +1,31 @@ +/* + * util.c -- Utilities. + * + * This file is donated to the Tox Project. + * Copyright 2013 plutooo + */ + +#include +#include +#include + +#include "network.h" + +uint64_t now() { + return time(NULL); +} + +uint64_t random_64b() { + uint64_t r; + + // This is probably not random enough? + r = random_int(); + r <<= 32; + r |= random_int(); + + return r; +} + +bool ipp_eq(IP_Port a, IP_Port b) { + return (a.ip.i == b.ip.i) && (a.port == b.port); +} diff --git a/core/util.h b/core/util.h new file mode 100644 index 00000000..aab2ead9 --- /dev/null +++ b/core/util.h @@ -0,0 +1,10 @@ +/* + * util.h -- Utilities. + * + * This file is donated to the Tox Project. + * Copyright 2013 plutooo + */ + +uint64_t now(); +uint64_t random_64b(); +bool ipp_eq(IP_Port a, IP_Port b); -- cgit v1.2.3 From 9364db9effb37a44e4de8166c00af00e5320c803 Mon Sep 17 00:00:00 2001 From: Nick ODell Date: Mon, 5 Aug 2013 14:46:45 -0600 Subject: Fix bug where handle_NATping wouldn't perform bounds checking --- core/DHT.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/DHT.c b/core/DHT.c index 6375b86b..f6c48a6d 100644 --- a/core/DHT.c +++ b/core/DHT.c @@ -1108,7 +1108,7 @@ static int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type) static int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source) { if (length < crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + ENCRYPTION_PADDING - && length > MAX_DATA_SIZE + ENCRYPTION_PADDING) + || length > MAX_DATA_SIZE + ENCRYPTION_PADDING) return 1; /* check if request is for us. */ -- cgit v1.2.3 From 84607c893799ebab736336267c58b12d4fd5b037 Mon Sep 17 00:00:00 2001 From: Nick ODell Date: Mon, 5 Aug 2013 14:54:53 -0600 Subject: Fix bug where friendreq_handlepacket did not do bounds checking --- core/friend_requests.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/friend_requests.c b/core/friend_requests.c index f1ffb8d0..5550b662 100644 --- a/core/friend_requests.c +++ b/core/friend_requests.c @@ -104,7 +104,7 @@ static int request_recieved(uint8_t * client_id) int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) { if (packet[0] == 32) { - if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && + if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING || length > MAX_DATA_SIZE + ENCRYPTION_PADDING) return 1; if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {// check if request is for us. -- cgit v1.2.3 From 524cf1895413026f528d9c59d16755a066c56f1c Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 5 Aug 2013 20:35:47 -0400 Subject: Fixed style and is_pinging(). --- core/ping.c | 110 ++++++++++++++++++++++++++++++++---------------------------- core/util.c | 25 ++++++++------ 2 files changed, 73 insertions(+), 62 deletions(-) (limited to 'core') diff --git a/core/ping.c b/core/ping.c index 8a7d534f..ffabe221 100644 --- a/core/ping.c +++ b/core/ping.c @@ -15,9 +15,9 @@ #define PING_TIMEOUT 5 // 5s typedef struct { - IP_Port ipp; - uint64_t id; - uint64_t timestamp; + IP_Port ipp; + uint64_t id; + uint64_t timestamp; } pinged_t; static pinged_t pings[PING_NUM_MAX]; @@ -25,71 +25,79 @@ static size_t num_pings; static size_t pos_pings; -void init_ping() { - num_pings = 0; - pos_pings = 0; +void init_ping() +{ + num_pings = 0; + pos_pings = 0; } -static bool is_timeout(uint64_t time) { - return (time + PING_TIMEOUT) < now(); +static bool is_timeout(uint64_t time) +{ + return (time + PING_TIMEOUT) < now(); } -static void remove_timeouts() { // O(n) - size_t i, id; - size_t new_pos = pos_pings; - size_t new_num = num_pings; - - // Loop through buffer, oldest first - for(i=0; i