diff --git a/meshmb.c b/meshmb.c new file mode 100644 index 00000000..80bd7fab --- /dev/null +++ b/meshmb.c @@ -0,0 +1,165 @@ +#include "serval_types.h" +#include "dataformats.h" +#include "cli.h" +#include "log.h" +#include "debug.h" +#include "instance.h" +#include "conf.h" +#include "commandline.h" +#include "overlay_buffer.h" + +/* +DEFINE_CMD(app_meshmb_news, 0, + "", + "meshmb", "news" KEYRING_PIN_OPTIONS, ""); +static int app_meshmb_news(const struct cli_parsed *parsed, struct cli_context *context) +{ + return 0; +} +*/ + +static int meshmb_send(keyring_identity *id, const char *message, size_t message_len){ + struct message_ply ply; + bzero(&ply, sizeof ply); + + bcopy(id->sign_pk, &ply.bundle_id, sizeof(ply.bundle_id)); + ply.known_bid = 1; + + struct overlay_buffer *b = ob_new(); + message_ply_append_message(b, message, message_len); + message_ply_append_timestamp(b); + assert(!ob_overrun(b)); + + int ret = message_ply_append(id, RHIZOME_SERVICE_MESHMB, NULL, &ply, b); + ob_free(b); + + return ret; +} + +DEFINE_CMD(app_meshmb_send, 0, + "", + "meshmb", "send" KEYRING_PIN_OPTIONS, "", ""); +static int app_meshmb_send(const struct cli_parsed *parsed, struct cli_context *UNUSED(context)) +{ + const char *idhex, *message; + if (cli_arg(parsed, "id", &idhex, str_is_identity, "") == -1 + || cli_arg(parsed, "message", &message, NULL, "") == -1) + return -1; + + identity_t identity; + if (str_to_identity_t(&identity, idhex) == -1) + return WHY("Invalid identity"); + + 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 end; + + keyring_identity *id = keyring_find_identity(keyring, &identity); + if (!id){ + WHY("Invalid identity"); + goto end; + } + + ret = meshmb_send(id, message, strlen(message)+1); +end: + keyring_free(keyring); + keyring = NULL; + return ret; +} + +/* +DEFINE_CMD(app_meshmb_list, 0, + "", + "meshmb", "list", "following|blocked" KEYRING_PIN_OPTIONS, "--last-message", ""); +static int app_meshmb_list(const struct cli_parsed *parsed, struct cli_context *context) +{ + return 0; +} + +DEFINE_CMD(app_meshmb_follow, 0, + "", + "meshmb", "follow|ignore|block" KEYRING_PIN_OPTIONS, "", ""); +static int app_meshmb_follow(const struct cli_parsed *parsed, struct cli_context *context) +{ + return 0; +} + +DEFINE_CMD(app_meshmb_find, 0, + "", + "meshmb", "find", "[]"); +static int app_meshmb_find(const struct cli_parsed *parsed, struct cli_context *context) +{ + return 0; +} +*/ + +DEFINE_CMD(app_meshmb_read, 0, + "", + "meshmb", "read", ""); +static int app_meshmb_read(const struct cli_parsed *parsed, struct cli_context *context) +{ + const char *hex_id; + if (cli_arg(parsed, "id", &hex_id, str_is_identity, "") == -1) + return -1; + + rhizome_bid_t bid; + if (str_to_rhizome_bid_t(&bid, hex_id) == -1) + return WHY("Invalid Identity"); + + /* Ensure the Rhizome database exists and is open */ + if (create_serval_instance_dir() == -1) + return -1; + if (rhizome_opendb() == -1) + return -1; + + struct message_ply_read read; + bzero(&read, sizeof read); + + if (message_ply_read_open(&read, &bid)==-1) + return -1; + + int ret=0; + int row_id=0; + const char *names[]={ + "_id","offset","age","message" + }; + cli_columns(context, 4, names); + time_s_t timestamp = 0; + time_s_t now = gettime(); + + while(message_ply_read_prev(&read)==0){ + switch(read.type){ + case MESSAGE_BLOCK_TYPE_TIME: + if (read.record_length<4){ + WARN("Malformed ply, expected 4 byte timestamp"); + continue; + } + timestamp = read_uint32(read.record); + break; + + case MESSAGE_BLOCK_TYPE_MESSAGE: + cli_put_long(context, row_id++, ":"); + cli_put_long(context, read.record_end_offset, ":"); + cli_put_long(context, timestamp ? (now - timestamp) : (long)-1, ":"); + cli_put_string(context, (const char *)read.record, "\n"); + + break; + + case MESSAGE_BLOCK_TYPE_ACK: + // TODO, link to some other ply? + break; + + default: + //ignore unknown types + break; + } + } + + message_ply_read_close(&read); + return ret; +} diff --git a/rhizome.h b/rhizome.h index d93e680c..0e8950aa 100644 --- a/rhizome.h +++ b/rhizome.h @@ -329,6 +329,7 @@ int rhizome_manifest_remove_field(rhizome_manifest *, const char *field_label, s #define RHIZOME_SERVICE_FILE "file" #define RHIZOME_SERVICE_MESHMS "MeshMS1" #define RHIZOME_SERVICE_MESHMS2 "MeshMS2" +#define RHIZOME_SERVICE_MESHMB "MeshMB1" extern int64_t rhizome_space; diff --git a/sourcefiles.mk b/sourcefiles.mk index ed7c3886..48089ed0 100644 --- a/sourcefiles.mk +++ b/sourcefiles.mk @@ -61,6 +61,7 @@ SERVAL_DAEMON_SOURCES = \ main.c \ radio_link.c \ meshms.c \ + meshmb.c \ meshms_cli.c \ message_ply.c \ keyring_restful.c \ diff --git a/tests/all b/tests/all index bf1925cb..e0ede96f 100755 --- a/tests/all +++ b/tests/all @@ -33,6 +33,7 @@ includeTests dnaprotocol includeTests rhizomeops includeTests rhizomeprotocol includeTests meshms +includeTests meshmb includeTests directory_service includeTests vomp includeTests keyringrestful diff --git a/tests/meshmb b/tests/meshmb new file mode 100755 index 00000000..2e74088b --- /dev/null +++ b/tests/meshmb @@ -0,0 +1,60 @@ +#!/bin/bash + +source "${0%/*}/../testframework.sh" +source "${0%/*}/../testdefs.sh" +source "${0%/*}/../testdefs_rhizome.sh" + +rexp_age='[0-9]*' + +setup_identities() { + setup_servald + executeOk_servald config \ + set debug.meshms on \ + set debug.rhizome on \ + set debug.rhizome_manifest on \ + set debug.rhizome_store on \ + set log.console.level debug \ + set log.console.show_time on + set_instance +A + create_identities $1 +} + +teardown() { + stop_all_servald_servers + kill_all_servald_processes + assert_no_servald_processes + report_all_servald_servers +} + +doc_meshmbSend="Send broadcast message" +setup_meshmbSend() { + setup_identities 1 +} +test_meshmbSend() { + executeOk_servald meshmb send $IDA1 "Message 1" + tfw_cat --stdout --stderr + executeOk_servald rhizome export bundle $IDA1 broadcast.manifest broadcast + tfw_cat -h broadcast.manifest + tfw_cat -h broadcast + executeOk_servald meshmb send $IDA1 "Message 2" + tfw_cat --stdout --stderr + executeOk_servald rhizome export bundle $IDA1 broadcast2.manifest broadcast2 + tfw_cat -h broadcast2.manifest + tfw_cat -h broadcast2 +} + + +doc_meshmbRead="Read messages" +setup_meshmbRead() { + setup_identities 1 + executeOk_servald meshmb send $IDA1 "Message 1" + executeOk_servald meshmb send $IDA1 "Message 2" +} +test_meshmbRead() { + executeOk_servald meshmb read $IDA1 + assertStdoutGrep --matches=1 "^_id:offset:age:message$" + assertStdoutGrep --matches=1 "^0:30:${rexp_age}:Message 2$" + assertStdoutGrep --matches=1 "^1:12:${rexp_age}:Message 1$" + assertStdoutLineCount '==' 4 +} +runTests "$@"