diff --git a/commandline.c b/commandline.c index 27b27009..52356620 100644 --- a/commandline.c +++ b/commandline.c @@ -2306,6 +2306,8 @@ struct cli_schema command_line_options[]={ "Get specified configuration variable."}, {app_vomp_console,{"console",NULL}, 0, "Test phone call life-cycle from the console"}, + {app_meshms_list_conversations,{"meshms","list","conversations" KEYRING_PIN_OPTIONS, "","[]","[]",NULL},0, + "List MeshMS threads that include "}, {app_meshms_list_messages,{"meshms","list","messages" KEYRING_PIN_OPTIONS, "","",NULL},0, "List MeshMS messages between and "}, {app_meshms_add_message,{"meshms","add","message" KEYRING_PIN_OPTIONS, "[]","[]","","","",NULL},0, diff --git a/meshms.c b/meshms.c index 9492d890..10231bd9 100644 --- a/meshms.c +++ b/meshms.c @@ -485,3 +485,34 @@ int app_meshms_ack_messages(const struct cli_parsed *parsed, void *context) return ret; } + +int app_meshms_list_conversations(const struct cli_parsed *parsed, void *context) +{ + if (create_serval_instance_dir() == -1) + return -1; + if (!(keyring = keyring_open_instance_cli(parsed))) + return -1; + if (rhizome_opendb() == -1) + return -1; + + if (config.debug.verbose) + DEBUG_cli_parsed(parsed); + const char *sid,*offset_str,*count_str; + + // Parse mandatory arguments + cli_arg(parsed, "sid", &sid, cli_optional_sid, ""); + cli_arg(parsed, "offset", &offset_str, NULL, "0"); + cli_arg(parsed, "count", &count_str, NULL, "9999"); + int offset=atoi(offset_str); + int count=atoi(count_str); + // Sanity check passed arguments + if ( strcmp(sid,"") == 0 ) + { + cli_puts("One or more missing arguments"); cli_delim("\n"); + } + sid_t aSid; + if (sid[0] && str_to_sid_t(&aSid, sid) == -1) + return WHYF("invalid sid: %s", sid); + + return rhizome_meshms_find_conversations(sid,offset,count); +} diff --git a/rhizome.h b/rhizome.h index 4849c0c8..2b501105 100644 --- a/rhizome.h +++ b/rhizome.h @@ -721,5 +721,6 @@ int meshms_block_type(unsigned char *buffer,int offset, int blength); int rhizome_meshms_find_conversation(const char *sender_sid, const char *recipient_sid, char *manifest_id, int offset); +int rhizome_meshms_find_conversations(const char *sid, int offset, int count); #endif //__SERVALDNA__RHIZOME_H diff --git a/rhizome_database.c b/rhizome_database.c index 8148671a..ef872aa9 100644 --- a/rhizome_database.c +++ b/rhizome_database.c @@ -1280,11 +1280,66 @@ cleanup: OUT(); } +int rhizome_meshms_find_conversations(const char *sid, int offset, int count) +{ + IN(); + strbuf b = strbuf_alloca(1024); + strbuf_sprintf(b, "SELECT DISTINCT sender,recipient FROM manifests WHERE 1=1"); + strbuf_sprintf(b, " AND ( sender = ?3 or recipient = ?3)"); + strbuf_sprintf(b, " ORDER BY MIN(sender,recipient), MAX(sender,recipient)"); + + const char *names[]={ + "partya","partyb" + }; + cli_columns(2,names); + if (offset) + strbuf_sprintf(b, " OFFSET %u", offset); + + if (strbuf_overrun(b)) + RETURN(WHYF("SQL command too long: ", strbuf_str(b))); + + //Statement is the SQL query and retry is the response from the database + sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT; + sqlite3_stmt *statement = sqlite_prepare(&retry, "%s", strbuf_str(b)); + if (!statement) + RETURN(-1); + + int ret = 0; + + if (ret==SQLITE_OK && sid && *sid) + ret = sqlite3_bind_text(statement, 3, sid, -1, SQLITE_STATIC); + + if (ret!=SQLITE_OK){ + ret = WHYF("Failed to bind parameters: %s", sqlite3_errmsg(rhizome_db)); + goto cleanup; + } + + ret=-1; + + int row=0; + while (sqlite_step_retry(&retry, statement) == SQLITE_ROW) { + if (!(sqlite3_column_count(statement) == 2 + && sqlite3_column_type(statement, 0) == SQLITE_TEXT + && sqlite3_column_type(statement, 1) == SQLITE_TEXT + )) { + WHY("Incorrect row structure"); + ret=-1; + goto cleanup; + } + row++; + if (row>count) break; + const char *sida = (const char *) sqlite3_column_text(statement, 0); + const char *sidb = (const char *) sqlite3_column_text(statement, 1); + cli_put_string(sida, ":"); + cli_put_string(sidb, "\n"); + } - - - +cleanup: + sqlite3_finalize(statement); + RETURN(ret); + OUT(); +} void rhizome_bytes_to_hex_upper(unsigned const char *in, char *out, int byteCount) { diff --git a/serval.h b/serval.h index 9e9bbc20..6e229cc9 100644 --- a/serval.h +++ b/serval.h @@ -686,6 +686,7 @@ int app_vomp_console(const struct cli_parsed *parsed, void *context); int app_meshms_add_message(const struct cli_parsed *parsed, void *context); int app_meshms_ack_messages(const struct cli_parsed *parsed, void *context); int app_meshms_list_messages(const struct cli_parsed *parsed, void *context); +int app_meshms_list_conversations(const struct cli_parsed *parsed, void *context); int monitor_get_fds(struct pollfd *fds,int *fdcount,int fdmax); diff --git a/tests/rhizomeops b/tests/rhizomeops index 6fb38ac0..421b9539 100755 --- a/tests/rhizomeops +++ b/tests/rhizomeops @@ -711,7 +711,7 @@ test_MeshMSAddGrow() { executeOk_servald rhizome extract file "$id" file1x assert --message="extracted payload is correct" diff file1 file1x for ofilehash in "${ofilehashes[@]}"; do - execute --exit-status=1 --stderr $servald rhizome export file "$ofilehash" + execute --exit-status=1 --stderr $servald rhizome export file "$ofilehash" done done }