From cb420c61e385e543b5895992037df729181f5fe0 Mon Sep 17 00:00:00 2001 From: Andrew Bettison Date: Wed, 22 Jan 2014 16:41:22 +1030 Subject: [PATCH] meshms.h Rename exposed MeshMS types and functions by adding "meshms_" prefix Check binary tree integrity during meshms_free_conversations() --- headerfiles.mk | 1 + meshms.c | 126 ++++++++++++++++++------------------------------- meshms.h | 74 +++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 81 deletions(-) create mode 100644 meshms.h diff --git a/headerfiles.mk b/headerfiles.mk index b390ac7b..49f29085 100644 --- a/headerfiles.mk +++ b/headerfiles.mk @@ -6,6 +6,7 @@ HDRS= fifo.h \ overlay_interface.h \ rhizome.h \ rhizome_http.h \ + meshms.h \ serval.h \ keyring.h \ socket.h \ diff --git a/meshms.c b/meshms.c index 05fed432..a1b640ee 100644 --- a/meshms.c +++ b/meshms.c @@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include "serval.h" #include "rhizome.h" +#include "meshms.h" #include "log.h" #include "conf.h" #include "crypto.h" @@ -31,45 +32,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define MESHMS_BLOCK_TYPE_MESSAGE 0x02 #define MESHMS_BLOCK_TYPE_BID_REFERENCE 0x03 -// the manifest details for one half of a conversation -struct ply { - rhizome_bid_t bundle_id; - uint64_t version; - uint64_t tail; - uint64_t size; -}; - -struct conversations { - // binary tree - struct conversations *_left; - struct conversations *_right; - // keeping a pointer to parent node here means the traversal iterator does not need a stack, so - // there is no fixed limit on the tree depth - struct conversations *_parent; - - // who are we talking to? - sid_t them; - - char found_my_ply; - struct ply my_ply; - - char found_their_ply; - struct ply their_ply; - - // what is the offset of their last message - uint64_t their_last_message; - // what is the last message we marked as read - uint64_t read_offset; - // our cached value for the last known size of their ply - uint64_t their_size; -}; - -struct conversation_iterator { - struct conversations *current; -}; - // cursor state for reading one half of a conversation -struct ply_read{ +struct ply_read { // rhizome payload struct rhizome_read read; // block buffer @@ -84,15 +48,15 @@ struct ply_read{ unsigned char *buffer; }; -static int meshms_conversations_list(const sid_t *my_sid, const sid_t *their_sid, struct conversations **conv); - -static void free_conversations(struct conversations *conv) +void meshms_free_conversations(struct meshms_conversations *conv) { - if (!conv) - return; - free_conversations(conv->_left); - free_conversations(conv->_right); - free(conv); + if (conv) { + if (conv->_parent && conv != conv->_parent->_left && conv != conv->_parent->_right) + WHYF("deformed MeshMS conversation tree"); + meshms_free_conversations(conv->_left); + meshms_free_conversations(conv->_right); + free(conv); + } } static int get_my_conversation_bundle(const sid_t *my_sidp, rhizome_manifest *m) @@ -101,7 +65,7 @@ static int get_my_conversation_bundle(const sid_t *my_sidp, rhizome_manifest *m) unsigned cn=0, in=0, kp=0; if (!keyring_find_sid(keyring,&cn,&in,&kp,my_sidp)) return WHYF("SID was not found in keyring: %s", alloca_tohex_sid_t(*my_sidp)); - + char seed[1024]; snprintf(seed, sizeof(seed), "incorrection%sconcentrativeness", @@ -135,10 +99,10 @@ static int get_my_conversation_bundle(const sid_t *my_sidp, rhizome_manifest *m) return 0; } -static struct conversations *add_conv(struct conversations **conv, const sid_t *them) +static struct meshms_conversations *add_conv(struct meshms_conversations **conv, const sid_t *them) { - struct conversations **ptr = conv; - struct conversations *parent = NULL; + struct meshms_conversations **ptr = conv; + struct meshms_conversations *parent = NULL; while (*ptr) { int cmp = cmp_sid_t(&(*ptr)->them, them); if (cmp == 0) @@ -150,7 +114,7 @@ static struct conversations *add_conv(struct conversations **conv, const sid_t * ptr = &(*ptr)->_right; } if (!*ptr){ - *ptr = emalloc_zero(sizeof(struct conversations)); + *ptr = emalloc_zero(sizeof(struct meshms_conversations)); (*ptr)->_parent = parent; if (*ptr) (*ptr)->them = *them; @@ -160,7 +124,7 @@ static struct conversations *add_conv(struct conversations **conv, const sid_t * // find matching conversations // if their_sid == my_sid, return all conversations with any recipient -static int get_database_conversations(const sid_t *my_sid, const sid_t *their_sid, struct conversations **conv) +static int get_database_conversations(const sid_t *my_sid, const sid_t *their_sid, struct meshms_conversations **conv) { sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT; sqlite3_stmt *statement = sqlite_prepare_bind(&retry, @@ -208,10 +172,10 @@ static int get_database_conversations(const sid_t *my_sid, const sid_t *their_si continue; } } - struct conversations *ptr = add_conv(conv, &their_sid); + struct meshms_conversations *ptr = add_conv(conv, &their_sid); if (!ptr) break; - struct ply *p; + struct meshms_ply *p; if (them==sender){ ptr->found_their_ply=1; p=&ptr->their_ply; @@ -228,17 +192,17 @@ static int get_database_conversations(const sid_t *my_sid, const sid_t *their_si return 0; } -static struct conversations * find_or_create_conv(const sid_t *my_sid, const sid_t *their_sid) +static struct meshms_conversations * find_or_create_conv(const sid_t *my_sid, const sid_t *their_sid) { - struct conversations *conv=NULL; + struct meshms_conversations *conv=NULL; if (meshms_conversations_list(my_sid, their_sid, &conv)) return NULL; - if (!conv && (conv = emalloc_zero(sizeof(struct conversations)))) + if (!conv && (conv = emalloc_zero(sizeof(struct meshms_conversations)))) conv->them = *their_sid; return conv; } -static int create_ply(const sid_t *my_sid, struct conversations *conv, rhizome_manifest *m) +static int create_ply(const sid_t *my_sid, struct meshms_conversations *conv, rhizome_manifest *m) { if (config.debug.meshms) DEBUGF("Creating ply for my_sid=%s them=%s", @@ -355,7 +319,7 @@ static int ply_find_next(struct ply_read *ply, char type){ } } -static int append_meshms_buffer(const sid_t *my_sid, struct conversations *conv, unsigned char *buffer, int len) +static int append_meshms_buffer(const sid_t *my_sid, struct meshms_conversations *conv, unsigned char *buffer, int len) { int ret=-1; rhizome_manifest *mout = NULL; @@ -416,7 +380,7 @@ end: // update if any conversations are unread or need to be acked. // return -1 for failure, 1 if the conversation index needs to be saved. -static int update_conversation(const sid_t *my_sid, struct conversations *conv) +static int update_conversation(const sid_t *my_sid, struct meshms_conversations *conv) { if (config.debug.meshms) DEBUG("Checking if conversation needs to be acked"); @@ -521,7 +485,7 @@ end: } // update conversations, and return 1 if the conversation index should be saved -static int update_conversations(const sid_t *my_sid, struct conversations *conv) +static int update_conversations(const sid_t *my_sid, struct meshms_conversations *conv) { if (!conv) return 0; @@ -542,7 +506,7 @@ static int update_conversations(const sid_t *my_sid, struct conversations *conv) // read our cached conversation list from our rhizome payload // if we can't load the existing data correctly, just ignore it. -static int read_known_conversations(rhizome_manifest *m, const sid_t *their_sid, struct conversations **conv) +static int read_known_conversations(rhizome_manifest *m, const sid_t *their_sid, struct meshms_conversations **conv) { if (m->haveSecret==NEW_BUNDLE_ID) return 0; @@ -575,7 +539,7 @@ static int read_known_conversations(rhizome_manifest *m, const sid_t *their_sid, DEBUGF("Reading existing conversation for %s", alloca_tohex_sid_t(sid)); if (their_sid && cmp_sid_t(&sid, their_sid) != 0) continue; - struct conversations *ptr = add_conv(conv, &sid); + struct meshms_conversations *ptr = add_conv(conv, &sid); if (!ptr) goto end; unsigned char details[8*3]; @@ -604,7 +568,7 @@ end: return ret; } -static ssize_t write_conversation(struct rhizome_write *write, struct conversations *conv) +static ssize_t write_conversation(struct rhizome_write *write, struct meshms_conversations *conv) { size_t len=0; if (!conv) @@ -646,7 +610,7 @@ static ssize_t write_conversation(struct rhizome_write *write, struct conversati return len; } -static int write_known_conversations(rhizome_manifest *m, struct conversations *conv) +static int write_known_conversations(rhizome_manifest *m, struct meshms_conversations *conv) { rhizome_manifest *mout=NULL; @@ -713,7 +677,7 @@ end: } // read information about existing conversations from a rhizome payload -static int meshms_conversations_list(const sid_t *my_sid, const sid_t *their_sid, struct conversations **conv) +int meshms_conversations_list(const sid_t *my_sid, const sid_t *their_sid, struct meshms_conversations **conv) { int ret=-1; rhizome_manifest *m = rhizome_new_manifest(); @@ -744,7 +708,7 @@ end: * * @author Andrew Bettison */ -static void conversation_iterator_start(struct conversation_iterator *it, struct conversations *conv) +void meshms_conversation_iterator_start(struct meshms_conversation_iterator *it, struct meshms_conversations *conv) { assert(conv->_parent == NULL); // can only iterate over whole tree it->current = conv; @@ -757,7 +721,7 @@ static void conversation_iterator_start(struct conversation_iterator *it, struct * * @author Andrew Bettison */ -static void conversation_iterator_advance(struct conversation_iterator *it) +void meshms_conversation_iterator_advance(struct meshms_conversation_iterator *it) { assert(it->current != NULL); // do not call on a finished iterator if (it->current->_right) { @@ -767,7 +731,7 @@ static void conversation_iterator_advance(struct conversation_iterator *it) } else { while (1) { - struct conversations *conv = it->current; + struct meshms_conversations *conv = it->current; it->current = it->current->_parent; if (it->current == NULL || conv == it->current->_left) break; @@ -800,7 +764,7 @@ int app_meshms_conversations(const struct cli_parsed *parsed, struct cli_context return -1; } - struct conversations *conv=NULL; + struct meshms_conversations *conv=NULL; if (meshms_conversations_list(&sid, NULL, &conv)){ keyring_free(keyring); return -1; @@ -812,10 +776,10 @@ int app_meshms_conversations(const struct cli_parsed *parsed, struct cli_context cli_columns(context, 5, names); int rows = 0; if (conv) { - struct conversation_iterator it; - for (conversation_iterator_start(&it, conv); + struct meshms_conversation_iterator it; + for (meshms_conversation_iterator_start(&it, conv); it.current && (count < 0 || rows < offset + count); - conversation_iterator_advance(&it), ++rows + meshms_conversation_iterator_advance(&it), ++rows ) { if (rows >= offset) { cli_put_long(context, rows, ":"); @@ -828,7 +792,7 @@ int app_meshms_conversations(const struct cli_parsed *parsed, struct cli_context } cli_row_count(context, rows); - free_conversations(conv); + meshms_free_conversations(conv); keyring_free(keyring); return 0; } @@ -855,7 +819,7 @@ int app_meshms_send_message(const struct cli_parsed *parsed, struct cli_context return WHY("invalid sender SID"); if (str_to_sid_t(&their_sid, their_sidhex) == -1) return WHY("invalid recipient SID"); - struct conversations *conv = find_or_create_conv(&my_sid, &their_sid); + struct meshms_conversations *conv = find_or_create_conv(&my_sid, &their_sid); if (!conv) { keyring_free(keyring); return -1; @@ -869,7 +833,7 @@ int app_meshms_send_message(const struct cli_parsed *parsed, struct cli_context message_len+=append_footer(buffer+message_len, MESHMS_BLOCK_TYPE_MESSAGE, message_len); int ret = append_meshms_buffer(&my_sid, conv, buffer, message_len); - free_conversations(conv); + meshms_free_conversations(conv); keyring_free(keyring); return ret; } @@ -898,7 +862,7 @@ int app_meshms_list_messages(const struct cli_parsed *parsed, struct cli_context keyring_free(keyring); return WHY("invalid recipient SID"); } - struct conversations *conv=find_or_create_conv(&my_sid, &their_sid); + struct meshms_conversations *conv=find_or_create_conv(&my_sid, &their_sid); if (!conv){ keyring_free(keyring); return -1; @@ -1031,12 +995,12 @@ end: rhizome_manifest_free(m_theirs); ply_read_close(&read_theirs); } - free_conversations(conv); + meshms_free_conversations(conv); keyring_free(keyring); return ret; } -static int mark_read(struct conversations *conv, const sid_t *their_sid, const char *offset_str) +static int mark_read(struct meshms_conversations *conv, const sid_t *their_sid, const char *offset_str) { int ret=0; if (conv){ @@ -1091,7 +1055,7 @@ int app_meshms_mark_read(const struct cli_parsed *parsed, struct cli_context *UN fromhex(their_sid.binary, their_sidhex, sizeof(their_sid.binary)); int ret=-1; - struct conversations *conv=NULL; + struct meshms_conversations *conv=NULL; rhizome_manifest *m = rhizome_new_manifest(); if (!m) goto end; @@ -1121,7 +1085,7 @@ int app_meshms_mark_read(const struct cli_parsed *parsed, struct cli_context *UN end: if (m) rhizome_manifest_free(m); - free_conversations(conv); + meshms_free_conversations(conv); keyring_free(keyring); return ret; } diff --git a/meshms.h b/meshms.h new file mode 100644 index 00000000..30637a75 --- /dev/null +++ b/meshms.h @@ -0,0 +1,74 @@ +/* +Serval DNA MeshMS +Copyright (C) 2014 Serval Project Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __SERVAL_DNA__MESHMS_H +#define __SERVAL_DNA__MESHMS_H + +#include "serval.h" +#include "rhizome.h" + +// the manifest details for one half of a conversation +struct meshms_ply { + rhizome_bid_t bundle_id; + uint64_t version; + uint64_t tail; + uint64_t size; +}; + +struct meshms_conversations { + // binary tree + struct meshms_conversations *_left; + struct meshms_conversations *_right; + // keeping a pointer to parent node here means the traversal iterator does not need a stack, so + // there is no fixed limit on the tree depth + struct meshms_conversations *_parent; + + // who are we talking to? + sid_t them; + + char found_my_ply; + struct meshms_ply my_ply; + + char found_their_ply; + struct meshms_ply their_ply; + + // what is the offset of their last message + uint64_t their_last_message; + // what is the last message we marked as read + uint64_t read_offset; + // our cached value for the last known size of their ply + uint64_t their_size; +}; + +/* Fetch the list of all MeshMS conversations into a binary tree whose nodes + * are all allocated by malloc(3). + */ +int meshms_conversations_list(const sid_t *my_sid, const sid_t *their_sid, struct meshms_conversations **conv); +void meshms_free_conversations(struct meshms_conversations *conv); + +/* For iterating over a binary tree of all MeshMS conversations, as created by + * meshms_conversations_list(). + */ +struct meshms_conversation_iterator { + struct meshms_conversations *current; +}; +void meshms_conversation_iterator_start(struct meshms_conversation_iterator *, struct meshms_conversations *); +void meshms_conversation_iterator_advance(struct meshms_conversation_iterator *); + +#endif // __SERVAL_DNA__MESHMS_H