diff --git a/meshms.c b/meshms.c index dfca326f..50bdf172 100644 --- a/meshms.c +++ b/meshms.c @@ -29,7 +29,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "strbuf.h" #include "keyring.h" #include "dataformats.h" -#include "commandline.h" #include "overlay_buffer.h" static unsigned mark_read(struct meshms_conversations *conv, const sid_t *their_sid, const uint64_t offset); @@ -828,193 +827,6 @@ end: return status; } -// output the list of existing conversations for a given local identity -DEFINE_CMD(app_meshms_conversations, 0, - "List MeshMS threads that include ", - "meshms","list","conversations" KEYRING_PIN_OPTIONS, "","[]","[]"); -static int app_meshms_conversations(const struct cli_parsed *parsed, struct cli_context *context) -{ - const char *sidhex, *offset_str, *count_str; - if (cli_arg(parsed, "sid", &sidhex, str_is_subscriber_id, "") == -1 - || cli_arg(parsed, "offset", &offset_str, NULL, "0")==-1 - || cli_arg(parsed, "count", &count_str, NULL, "-1")==-1) - return -1; - - sid_t sid; - struct meshms_conversations *conv = NULL; - enum meshms_status status = MESHMS_STATUS_ERROR; - - fromhex(sid.binary, sidhex, sizeof(sid.binary)); - int offset=atoi(offset_str); - int count=atoi(count_str); - - if (create_serval_instance_dir() == -1) - goto end; - if (!(keyring = keyring_open_instance_cli(parsed))) - goto end; - - if (rhizome_opendb() == -1) - goto end; - - if (meshms_failed(status = meshms_conversations_list(NULL, &sid, NULL, &conv))) - goto end; - - const char *names[]={ - "_id","recipient","read", "last_message", "read_offset" - }; - - cli_columns(context, 5, names); - int rows = 0; - if (conv) { - struct meshms_conversation_iterator it; - for (meshms_conversation_iterator_start(&it, conv); - it.current && (count < 0 || rows < offset + count); - meshms_conversation_iterator_advance(&it), ++rows - ) { - if (rows >= offset) { - cli_put_long(context, rows, ":"); - cli_put_hexvalue(context, it.current->them.binary, sizeof(it.current->them), ":"); - cli_put_string(context, it.current->read_offset < it.current->their_last_message ? "unread":"", ":"); - cli_put_long(context, it.current->their_last_message, ":"); - cli_put_long(context, it.current->read_offset, "\n"); - } - } - } - cli_row_count(context, rows); - status=MESHMS_STATUS_OK; - -end: - if (conv) - meshms_free_conversations(conv); - if (keyring) - keyring_free(keyring); - keyring = NULL; - return status; -} - -DEFINE_CMD(app_meshms_send_message, 0, - "Send a MeshMS message from to ", - "meshms","send","message" KEYRING_PIN_OPTIONS, "", "", ""); -static int app_meshms_send_message(const struct cli_parsed *parsed, struct cli_context *UNUSED(context)) -{ - const char *my_sidhex, *their_sidhex, *message; - if (cli_arg(parsed, "sender_sid", &my_sidhex, str_is_subscriber_id, "") == -1 - || cli_arg(parsed, "recipient_sid", &their_sidhex, str_is_subscriber_id, "") == -1 - || cli_arg(parsed, "payload", &message, NULL, "") == -1) - return -1; - - if (create_serval_instance_dir() == -1) - return -1; - if (!(keyring = keyring_open_instance_cli(parsed))) - return -1; - if (rhizome_opendb() == -1){ - keyring_free(keyring); - keyring = NULL; - return -1; - } - - sid_t my_sid, their_sid; - if (str_to_sid_t(&my_sid, my_sidhex) == -1) - return WHY("invalid sender SID"); - if (str_to_sid_t(&their_sid, their_sidhex) == -1) - return WHY("invalid recipient SID"); - // include terminating NUL - enum meshms_status status = meshms_send_message(&my_sid, &their_sid, message, strlen(message) + 1); - keyring_free(keyring); - keyring = NULL; - return meshms_failed(status) ? status : 0; -} - -DEFINE_CMD(app_meshms_list_messages, 0, - "List MeshMS messages between and ", - "meshms","list","messages" KEYRING_PIN_OPTIONS, "",""); -static int app_meshms_list_messages(const struct cli_parsed *parsed, struct cli_context *context) -{ - const char *my_sidhex, *their_sidhex; - if (cli_arg(parsed, "sender_sid", &my_sidhex, str_is_subscriber_id, "") == -1 - || cli_arg(parsed, "recipient_sid", &their_sidhex, str_is_subscriber_id, "") == -1) - return -1; - if (create_serval_instance_dir() == -1) - return -1; - if (!(keyring = keyring_open_instance_cli(parsed))) - return -1; - if (rhizome_opendb() == -1){ - keyring_free(keyring); - keyring = NULL; - return -1; - } - sid_t my_sid, their_sid; - if (str_to_sid_t(&my_sid, my_sidhex) == -1){ - keyring_free(keyring); - keyring = NULL; - return WHY("invalid sender SID"); - } - if (str_to_sid_t(&their_sid, their_sidhex) == -1){ - keyring_free(keyring); - keyring = NULL; - return WHY("invalid recipient SID"); - } - struct meshms_message_iterator iter; - enum meshms_status status; - if (meshms_failed(status = meshms_message_iterator_open(&iter, &my_sid, &their_sid))) { - keyring_free(keyring); - keyring = NULL; - return status; - } - const char *names[]={ - "_id","offset","age","type","message" - }; - cli_columns(context, 5, names); - bool_t marked_delivered = 0; - bool_t marked_read = 0; - time_s_t now = gettime(); - int id = 0; - while ((status = meshms_message_iterator_prev(&iter)) == MESHMS_STATUS_UPDATED) { - switch (iter.type) { - case MESSAGE_SENT: - if (iter.delivered && !marked_delivered){ - cli_put_long(context, id++, ":"); - cli_put_long(context, iter.latest_ack_offset, ":"); - cli_put_long(context, iter.timestamp?(int)(now - iter.timestamp):-1, ":"); - cli_put_string(context, "ACK", ":"); - cli_put_string(context, "delivered", "\n"); - marked_delivered = 1; - } - // TODO new message format here - cli_put_long(context, id++, ":"); - cli_put_long(context, iter.offset, ":"); - cli_put_long(context, iter.timestamp?(int)(now - iter.timestamp):-1, ":"); - cli_put_string(context, ">", ":"); - cli_put_string(context, iter.text, "\n"); - break; - case ACK_RECEIVED: - break; - case MESSAGE_RECEIVED: - if (iter.read && !marked_read) { - cli_put_long(context, id++, ":"); - cli_put_long(context, iter.read_offset, ":"); - cli_put_long(context, iter.timestamp?(int)(now - iter.timestamp):-1, ":"); - cli_put_string(context, "MARK", ":"); - cli_put_string(context, "read", "\n"); - marked_read = 1; - } - // TODO new message format here - cli_put_long(context, id++, ":"); - cli_put_long(context, iter.offset, ":"); - cli_put_long(context, iter.timestamp?(int)(now - iter.timestamp):-1, ":"); - cli_put_string(context, "<", ":"); - cli_put_string(context, iter.text, "\n"); - break; - } - } - if (!meshms_failed(status)) - cli_row_count(context, id); - meshms_message_iterator_close(&iter); - keyring_free(keyring); - keyring = NULL; - return status; -} - // Returns the number of read markers moved. static unsigned mark_read(struct meshms_conversations *conv, const sid_t *their_sid, const uint64_t offset) { @@ -1042,51 +854,6 @@ static unsigned mark_read(struct meshms_conversations *conv, const sid_t *their_ return ret; } -DEFINE_CMD(app_meshms_mark_read, 0, - "Mark incoming messages from this recipient as read.", - "meshms","read","messages" KEYRING_PIN_OPTIONS, "", "[]", "[]"); -static int app_meshms_mark_read(const struct cli_parsed *parsed, struct cli_context *UNUSED(context)) -{ - const char *my_sidhex, *their_sidhex, *offset_str; - if (cli_arg(parsed, "sender_sid", &my_sidhex, str_is_subscriber_id, "") == -1 - || cli_arg(parsed, "recipient_sid", &their_sidhex, str_is_subscriber_id, NULL) == -1 - || cli_arg(parsed, "offset", &offset_str, str_is_uint64_decimal, NULL)==-1) - return -1; - - if (create_serval_instance_dir() == -1) - return -1; - if (!(keyring = keyring_open_instance_cli(parsed))) - return -1; - int ret = -1; - if (rhizome_opendb() == -1) - goto done; - sid_t my_sid, their_sid; - if (str_to_sid_t(&my_sid, my_sidhex) == -1) { - ret = WHYF("my_sidhex=%s", my_sidhex); - goto done; - } - if (their_sidhex && str_to_sid_t(&their_sid, their_sidhex) == -1) { - ret = WHYF("their_sidhex=%s", their_sidhex); - goto done; - } - uint64_t offset = UINT64_MAX; - if (offset_str) { - if (!their_sidhex) { - ret = WHY("missing recipient_sid"); - goto done; - } - if (!str_to_uint64(offset_str, 10, &offset, NULL)) { - ret = WHYF("offset_str=%s", offset_str); - goto done; - } - } - enum meshms_status status = meshms_mark_read(&my_sid, their_sidhex ? &their_sid : NULL, offset); - ret = (status == MESHMS_STATUS_UPDATED) ? MESHMS_STATUS_OK : status; -done: - keyring_free(keyring); - keyring = NULL; - return ret; -} const char *meshms_status_message(enum meshms_status status) { diff --git a/meshms_cli.c b/meshms_cli.c new file mode 100644 index 00000000..e06844b1 --- /dev/null +++ b/meshms_cli.c @@ -0,0 +1,244 @@ +#include +#include "serval_types.h" +#include "dataformats.h" +#include "cli.h" +#include "meshms.h" +#include "log.h" +#include "debug.h" +#include "instance.h" +#include "conf.h" +#include "commandline.h" + + +// output the list of existing conversations for a given local identity +DEFINE_CMD(app_meshms_conversations, 0, + "List MeshMS threads that include ", + "meshms","list","conversations" KEYRING_PIN_OPTIONS, "","[]","[]"); +static int app_meshms_conversations(const struct cli_parsed *parsed, struct cli_context *context) +{ + const char *sidhex, *offset_str, *count_str; + if (cli_arg(parsed, "sid", &sidhex, str_is_subscriber_id, "") == -1 + || cli_arg(parsed, "offset", &offset_str, NULL, "0")==-1 + || cli_arg(parsed, "count", &count_str, NULL, "-1")==-1) + return -1; + + sid_t sid; + struct meshms_conversations *conv = NULL; + enum meshms_status status = MESHMS_STATUS_ERROR; + + fromhex(sid.binary, sidhex, sizeof(sid.binary)); + int offset=atoi(offset_str); + int count=atoi(count_str); + + if (create_serval_instance_dir() == -1) + goto end; + if (!(keyring = keyring_open_instance_cli(parsed))) + goto end; + + if (rhizome_opendb() == -1) + goto end; + + if (meshms_failed(status = meshms_conversations_list(NULL, &sid, NULL, &conv))) + goto end; + + const char *names[]={ + "_id","recipient","read", "last_message", "read_offset" + }; + + cli_columns(context, 5, names); + int rows = 0; + if (conv) { + struct meshms_conversation_iterator it; + for (meshms_conversation_iterator_start(&it, conv); + it.current && (count < 0 || rows < offset + count); + meshms_conversation_iterator_advance(&it), ++rows + ) { + if (rows >= offset) { + cli_put_long(context, rows, ":"); + cli_put_hexvalue(context, it.current->them.binary, sizeof(it.current->them), ":"); + cli_put_string(context, it.current->read_offset < it.current->their_last_message ? "unread":"", ":"); + cli_put_long(context, it.current->their_last_message, ":"); + cli_put_long(context, it.current->read_offset, "\n"); + } + } + } + cli_row_count(context, rows); + status=MESHMS_STATUS_OK; + +end: + if (conv) + meshms_free_conversations(conv); + if (keyring) + keyring_free(keyring); + keyring = NULL; + return status; +} + +DEFINE_CMD(app_meshms_send_message, 0, + "Send a MeshMS message from to ", + "meshms","send","message" KEYRING_PIN_OPTIONS, "", "", ""); +static int app_meshms_send_message(const struct cli_parsed *parsed, struct cli_context *UNUSED(context)) +{ + const char *my_sidhex, *their_sidhex, *message; + if (cli_arg(parsed, "sender_sid", &my_sidhex, str_is_subscriber_id, "") == -1 + || cli_arg(parsed, "recipient_sid", &their_sidhex, str_is_subscriber_id, "") == -1 + || cli_arg(parsed, "payload", &message, NULL, "") == -1) + return -1; + + if (create_serval_instance_dir() == -1) + return -1; + if (!(keyring = keyring_open_instance_cli(parsed))) + return -1; + if (rhizome_opendb() == -1){ + keyring_free(keyring); + keyring = NULL; + return -1; + } + + sid_t my_sid, their_sid; + if (str_to_sid_t(&my_sid, my_sidhex) == -1) + return WHY("invalid sender SID"); + if (str_to_sid_t(&their_sid, their_sidhex) == -1) + return WHY("invalid recipient SID"); + // include terminating NUL + enum meshms_status status = meshms_send_message(&my_sid, &their_sid, message, strlen(message) + 1); + keyring_free(keyring); + keyring = NULL; + return meshms_failed(status) ? status : 0; +} + +DEFINE_CMD(app_meshms_list_messages, 0, + "List MeshMS messages between and ", + "meshms","list","messages" KEYRING_PIN_OPTIONS, "",""); +static int app_meshms_list_messages(const struct cli_parsed *parsed, struct cli_context *context) +{ + const char *my_sidhex, *their_sidhex; + if (cli_arg(parsed, "sender_sid", &my_sidhex, str_is_subscriber_id, "") == -1 + || cli_arg(parsed, "recipient_sid", &their_sidhex, str_is_subscriber_id, "") == -1) + return -1; + if (create_serval_instance_dir() == -1) + return -1; + if (!(keyring = keyring_open_instance_cli(parsed))) + return -1; + if (rhizome_opendb() == -1){ + keyring_free(keyring); + keyring = NULL; + return -1; + } + sid_t my_sid, their_sid; + if (str_to_sid_t(&my_sid, my_sidhex) == -1){ + keyring_free(keyring); + keyring = NULL; + return WHY("invalid sender SID"); + } + if (str_to_sid_t(&their_sid, their_sidhex) == -1){ + keyring_free(keyring); + keyring = NULL; + return WHY("invalid recipient SID"); + } + struct meshms_message_iterator iter; + enum meshms_status status; + if (meshms_failed(status = meshms_message_iterator_open(&iter, &my_sid, &their_sid))) { + keyring_free(keyring); + keyring = NULL; + return status; + } + const char *names[]={ + "_id","offset","age","type","message" + }; + cli_columns(context, 5, names); + bool_t marked_delivered = 0; + bool_t marked_read = 0; + time_s_t now = gettime(); + int id = 0; + while ((status = meshms_message_iterator_prev(&iter)) == MESHMS_STATUS_UPDATED) { + switch (iter.type) { + case MESSAGE_SENT: + if (iter.delivered && !marked_delivered){ + cli_put_long(context, id++, ":"); + cli_put_long(context, iter.latest_ack_offset, ":"); + cli_put_long(context, iter.timestamp?(int)(now - iter.timestamp):-1, ":"); + cli_put_string(context, "ACK", ":"); + cli_put_string(context, "delivered", "\n"); + marked_delivered = 1; + } + // TODO new message format here + cli_put_long(context, id++, ":"); + cli_put_long(context, iter.offset, ":"); + cli_put_long(context, iter.timestamp?(int)(now - iter.timestamp):-1, ":"); + cli_put_string(context, ">", ":"); + cli_put_string(context, iter.text, "\n"); + break; + case ACK_RECEIVED: + break; + case MESSAGE_RECEIVED: + if (iter.read && !marked_read) { + cli_put_long(context, id++, ":"); + cli_put_long(context, iter.read_offset, ":"); + cli_put_long(context, iter.timestamp?(int)(now - iter.timestamp):-1, ":"); + cli_put_string(context, "MARK", ":"); + cli_put_string(context, "read", "\n"); + marked_read = 1; + } + // TODO new message format here + cli_put_long(context, id++, ":"); + cli_put_long(context, iter.offset, ":"); + cli_put_long(context, iter.timestamp?(int)(now - iter.timestamp):-1, ":"); + cli_put_string(context, "<", ":"); + cli_put_string(context, iter.text, "\n"); + break; + } + } + if (!meshms_failed(status)) + cli_row_count(context, id); + meshms_message_iterator_close(&iter); + keyring_free(keyring); + keyring = NULL; + return status; +} + +DEFINE_CMD(app_meshms_mark_read, 0, + "Mark incoming messages from this recipient as read.", + "meshms","read","messages" KEYRING_PIN_OPTIONS, "", "[]", "[]"); +static int app_meshms_mark_read(const struct cli_parsed *parsed, struct cli_context *UNUSED(context)) +{ + const char *my_sidhex, *their_sidhex, *offset_str; + if (cli_arg(parsed, "sender_sid", &my_sidhex, str_is_subscriber_id, "") == -1 + || cli_arg(parsed, "recipient_sid", &their_sidhex, str_is_subscriber_id, NULL) == -1 + || cli_arg(parsed, "offset", &offset_str, str_is_uint64_decimal, NULL)==-1) + return -1; + + if (create_serval_instance_dir() == -1) + return -1; + if (!(keyring = keyring_open_instance_cli(parsed))) + return -1; + int ret = -1; + if (rhizome_opendb() == -1) + goto done; + sid_t my_sid, their_sid; + if (str_to_sid_t(&my_sid, my_sidhex) == -1) { + ret = WHYF("my_sidhex=%s", my_sidhex); + goto done; + } + if (their_sidhex && str_to_sid_t(&their_sid, their_sidhex) == -1) { + ret = WHYF("their_sidhex=%s", their_sidhex); + goto done; + } + uint64_t offset = UINT64_MAX; + if (offset_str) { + if (!their_sidhex) { + ret = WHY("missing recipient_sid"); + goto done; + } + if (!str_to_uint64(offset_str, 10, &offset, NULL)) { + ret = WHYF("offset_str=%s", offset_str); + goto done; + } + } + enum meshms_status status = meshms_mark_read(&my_sid, their_sidhex ? &their_sid : NULL, offset); + ret = (status == MESHMS_STATUS_UPDATED) ? MESHMS_STATUS_OK : status; +done: + keyring_free(keyring); + keyring = NULL; + return ret; +} diff --git a/sourcefiles.mk b/sourcefiles.mk index a17b4631..ed7c3886 100644 --- a/sourcefiles.mk +++ b/sourcefiles.mk @@ -61,6 +61,7 @@ SERVAL_DAEMON_SOURCES = \ main.c \ radio_link.c \ meshms.c \ + meshms_cli.c \ message_ply.c \ keyring_restful.c \ meshms_restful.c \