From b7f989266df854fcd7772bec58e408c7359087ff Mon Sep 17 00:00:00 2001 From: Sebastian Stal Date: Mon, 5 Aug 2013 12:30:07 -0700 Subject: [PATCH] Add functions for dealing with userstatus kinds. --- core/Messenger.c | 88 ++++++++++++++++++++++++++++++++++++++---------- core/Messenger.h | 38 +++++++++++++++++---- 2 files changed, 102 insertions(+), 24 deletions(-) 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