From 9cb561229adb45aa43627c589562567bccd7c409 Mon Sep 17 00:00:00 2001 From: Jeremy Lakeman Date: Wed, 14 Jun 2017 14:51:06 +0930 Subject: [PATCH] Allow following a feed that isn't in rhizome yet, and override the displayed name --- .../servaldna/ServalDClient.java | 4 +- .../servaldna/meshmb/MeshMBCommon.java | 12 +++- meshmb.c | 67 ++++++++++++------- meshmb.h | 7 +- meshmb_cli.c | 20 ++++-- meshmb_restful.c | 26 ++++++- tests/meshmb | 4 +- 7 files changed, 99 insertions(+), 41 deletions(-) diff --git a/java-api/src/org/servalproject/servaldna/ServalDClient.java b/java-api/src/org/servalproject/servaldna/ServalDClient.java index c8b6e16f..b5090ce6 100644 --- a/java-api/src/org/servalproject/servaldna/ServalDClient.java +++ b/java-api/src/org/servalproject/servaldna/ServalDClient.java @@ -220,8 +220,8 @@ public class ServalDClient implements ServalDHttpConnectionFactory { return list; } - public int meshmbAlterSubscription(Subscriber id, MeshMBCommon.SubscriptionAction action, SigningKey peer) throws ServalDInterfaceException, IOException { - return MeshMBCommon.alterSubscription(this, id, action, peer); + public int meshmbAlterSubscription(Subscriber id, MeshMBCommon.SubscriptionAction action, Subscriber peer, String name) throws ServalDInterfaceException, IOException { + return MeshMBCommon.alterSubscription(this, id, action, peer, name); } public MeshMBSubscriptionList meshmbSubscriptions(Subscriber identity) throws IOException, ServalDInterfaceException { diff --git a/java-api/src/org/servalproject/servaldna/meshmb/MeshMBCommon.java b/java-api/src/org/servalproject/servaldna/meshmb/MeshMBCommon.java index da5e54a3..f401f78b 100644 --- a/java-api/src/org/servalproject/servaldna/meshmb/MeshMBCommon.java +++ b/java-api/src/org/servalproject/servaldna/meshmb/MeshMBCommon.java @@ -9,6 +9,7 @@ import org.servalproject.servaldna.Subscriber; import java.io.IOException; import java.net.HttpURLConnection; +import java.util.Vector; /** * Created by jeremy on 5/10/16. @@ -34,8 +35,15 @@ public class MeshMBCommon { return conn.getResponseCode(); } - public static int alterSubscription(ServalDHttpConnectionFactory connector, Subscriber id, SubscriptionAction action, SigningKey peer) throws ServalDInterfaceException, IOException { - HttpURLConnection conn = connector.newServalDHttpConnection("/restful/meshmb/" + id.signingKey.toHex() + "/"+action.toString().toLowerCase()+"/" + peer.toHex()); + public static int alterSubscription(ServalDHttpConnectionFactory connector, Subscriber id, SubscriptionAction action, Subscriber peer, String name) throws ServalDInterfaceException, IOException { + Vector parms = new Vector<>(); + parms.add(new ServalDHttpConnectionFactory.QueryParam("sender", peer.sid.toHex())); + if (name!=null && !"".equals(name)) + parms.add(new ServalDHttpConnectionFactory.QueryParam("name", name)); + HttpURLConnection conn = connector.newServalDHttpConnection( + "/restful/meshmb/"+id.signingKey.toHex()+"/"+peer.signingKey.toHex(), + parms + ); conn.setRequestMethod("POST"); conn.connect(); return conn.getResponseCode(); diff --git a/meshmb.c b/meshmb.c index 475f1689..740d55a5 100644 --- a/meshmb.c +++ b/meshmb.c @@ -23,6 +23,7 @@ struct feed_metadata{ }; #define FLAG_BLOCKED (1<<0) +#define FLAG_OVERRIDDEN_NAME (1<<1) struct meshmb_feeds{ struct tree_root root; @@ -242,6 +243,27 @@ static int activity_ack(struct meshmb_feeds *feeds, struct message_ply_ack *ack) return r; } +static int replace_string(char **ptr, const char *new_value, ssize_t len, size_t max_len){ + if (!*ptr && (!new_value || !*new_value)) + return 0; + + if (len == -1) + len = strlen(new_value); + if ((size_t)len >= max_len) + len = max_len -1; + + if (*ptr && *new_value && strn_str_cmp(new_value, len, *ptr) == 0) + return 0; + + if (*ptr){ + free((void*)*ptr); + *ptr = NULL; + } + if (new_value && *new_value) + *ptr = strn_edup(new_value, len); + return 1; +} + static int update_stats(struct meshmb_feeds *feeds, struct feed_metadata *metadata, struct message_ply_read *reader) { if (metadata->details.blocked) @@ -269,19 +291,9 @@ static int update_stats(struct meshmb_feeds *feeds, struct feed_metadata *metada && message_ply_read_open(reader, &metadata->bundle_id, NULL)!=0) return -1; - // TODO allow the user to specify an overridden name? - if (metadata->details.name){ - free((void*)metadata->details.name); - metadata->details.name = NULL; - } metadata->details.ply.author = reader->author; - - if (reader->name){ - size_t len = strlen(reader->name); - if (len >= MAX_NAME_LEN) - len = MAX_NAME_LEN -1; - metadata->details.name = strn_edup(reader->name, len); - } + if (!metadata->details.overridden_name) + replace_string((char **)&metadata->details.name, reader->name, -1, MAX_NAME_LEN); reader->read.offset = reader->read.length; time_s_t timestamp = 0; @@ -301,13 +313,7 @@ static int update_stats(struct meshmb_feeds *feeds, struct feed_metadata *metada break; last_offset = reader->record_end_offset; - - if (metadata->details.last_message) - free((void*)metadata->details.last_message); - size_t len = reader->record_length; - if (len >= MAX_MSG_LEN) - len = MAX_MSG_LEN -1; - metadata->details.last_message = strn_edup((const char *)reader->record, len); + replace_string((char **)&metadata->details.last_message, (const char *)reader->record, reader->record_length, MAX_MSG_LEN); metadata->details.timestamp = timestamp; break; } @@ -391,7 +397,11 @@ static int write_metadata(void **record, void *context) len += sizeof (rhizome_bid_t); bcopy(metadata->details.ply.author.binary, &buffer[len], sizeof (sid_t)); len += sizeof (sid_t); - uint8_t flags = (metadata->details.blocked ? FLAG_BLOCKED : 0); + uint8_t flags = 0; + if (metadata->details.blocked) + flags |= FLAG_BLOCKED; + if (metadata->details.overridden_name) + flags |= FLAG_OVERRIDDEN_NAME; buffer[len++]=flags; if (!metadata->details.blocked){ len+=pack_uint(&buffer[len], metadata->size); @@ -605,6 +615,7 @@ static int read_metadata(struct meshmb_feeds *feeds, struct rhizome_read *read) result->details.name = (name && *name) ? str_edup(name) : NULL; result->details.last_message = (msg && *msg) ? str_edup(msg) : NULL; result->details.timestamp = timestamp; + result->details.overridden_name = (flags & FLAG_OVERRIDDEN_NAME) ? 1 : 0; DEBUGF(meshmb, "Processed %u bytes of metadata for %s (%s)", offset, @@ -685,7 +696,7 @@ int meshmb_open(keyring_identity *id, struct meshmb_feeds **feeds) return ret; } -int meshmb_follow(struct meshmb_feeds *feeds, rhizome_bid_t *bid) +int meshmb_follow(struct meshmb_feeds *feeds, const rhizome_bid_t *bid, const sid_t *author, const char *name) { struct feed_metadata *metadata; DEBUGF(meshmb, "Attempting to follow %s", alloca_tohex_rhizome_bid_t(*bid)); @@ -697,10 +708,16 @@ int meshmb_follow(struct meshmb_feeds *feeds, rhizome_bid_t *bid) bzero(&reader, sizeof(reader)); update_stats(feeds, metadata, &reader); message_ply_read_close(&reader); + + if (author && is_sid_t_any(metadata->details.ply.author)) + metadata->details.ply.author = *author; + if (name && replace_string((char **)&metadata->details.name, name, -1, MAX_NAME_LEN)) + metadata->details.overridden_name = 1; + return 0; } -int meshmb_block(struct meshmb_feeds *feeds, rhizome_bid_t *bid) +int meshmb_block(struct meshmb_feeds *feeds, const rhizome_bid_t *bid, const sid_t *author) { struct feed_metadata *metadata; DEBUGF(meshmb, "Attempting to block %s", alloca_tohex_rhizome_bid_t(*bid)); @@ -715,8 +732,8 @@ int meshmb_block(struct meshmb_feeds *feeds, rhizome_bid_t *bid) free((void*)metadata->details.last_message); metadata->details.last_message = NULL; } - if (is_all_matching(metadata->details.ply.author.binary, sizeof metadata->details.ply.author, 0)) - crypto_sign_to_sid(bid, &metadata->details.ply.author); + if (author && is_sid_t_any(metadata->details.ply.author)) + metadata->details.ply.author = *author; if (!metadata->details.blocked) feeds->dirty = 1; metadata->details.blocked = 1; @@ -724,7 +741,7 @@ int meshmb_block(struct meshmb_feeds *feeds, rhizome_bid_t *bid) return 0; } -int meshmb_ignore(struct meshmb_feeds *feeds, rhizome_bid_t *bid) +int meshmb_ignore(struct meshmb_feeds *feeds, const rhizome_bid_t *bid) { DEBUGF(meshmb, "Attempting to ignore %s", alloca_tohex_rhizome_bid_t(*bid)); tree_walk_prefix(&feeds->root, bid->binary, sizeof *bid, free_feed, feeds); diff --git a/meshmb.h b/meshmb.h index cbcdf96f..daca137c 100644 --- a/meshmb.h +++ b/meshmb.h @@ -15,6 +15,7 @@ struct meshmb_feed_details{ const char *last_message; time_s_t timestamp; bool_t blocked:1; + bool_t overridden_name:1; }; // threaded feed iterator state @@ -40,9 +41,9 @@ void meshmb_close(struct meshmb_feeds *feeds); int meshmb_flush(struct meshmb_feeds *feeds); // set / clear follow flag for this feed -int meshmb_follow(struct meshmb_feeds *feeds, rhizome_bid_t *bid); -int meshmb_ignore(struct meshmb_feeds *feeds, rhizome_bid_t *bid); -int meshmb_block(struct meshmb_feeds *feeds, rhizome_bid_t *bid); +int meshmb_follow(struct meshmb_feeds *feeds, const rhizome_bid_t *bid, const sid_t *sender, const char *name); +int meshmb_ignore(struct meshmb_feeds *feeds, const rhizome_bid_t *bid); +int meshmb_block(struct meshmb_feeds *feeds, const rhizome_bid_t *bid, const sid_t *sender); // enumerate feeds, starting from restart_from typedef int (*meshmb_callback) (struct meshmb_feed_details *details, void *context); diff --git a/meshmb_cli.c b/meshmb_cli.c index 2cc720b6..777260d9 100644 --- a/meshmb_cli.c +++ b/meshmb_cli.c @@ -213,13 +213,18 @@ static int app_meshmb_find(const struct cli_parsed *parsed, struct cli_context * DEFINE_CMD(app_meshmb_follow, 0, "Follow, block or ignore a broadcast feed", - "meshmb", "follow|ignore|block" KEYRING_PIN_OPTIONS, "", ""); + "meshmb", "follow|ignore|block" KEYRING_PIN_OPTIONS, "", "", "[]", "[]"); static int app_meshmb_follow(const struct cli_parsed *parsed, struct cli_context *UNUSED(context)) { const char *peerhex; - if (cli_arg(parsed, "peer", &peerhex, str_is_identity, "") == -1) + const char *sidhex; + const char *name; + + if (cli_arg(parsed, "peer", &peerhex, str_is_identity, "") == -1 + || cli_arg(parsed, "sender", &sidhex, str_is_subscriber_id, NULL) == -1) return -1; + cli_arg(parsed, "name", &name, NULL, NULL); int follow = cli_arg(parsed, "follow", NULL, NULL, NULL) == 0; int block = cli_arg(parsed, "block", NULL, NULL, NULL) == 0; @@ -227,14 +232,21 @@ static int app_meshmb_follow(const struct cli_parsed *parsed, struct cli_context if (str_to_identity_t(&peer, peerhex) == -1) return WHY("Invalid identity"); + sid_t sender; + bzero(&sender, sizeof sender); + if (sidhex && *sidhex){ + if (str_to_sid_t(&sender, sidhex) == -1) + return WHY("Invalid sender"); + } + struct meshmb_feeds *feeds = cli_feeds_open(parsed); int ret = -1; if (feeds){ if (block){ - ret = meshmb_block(feeds, &peer); + ret = meshmb_block(feeds, &peer, (sidhex && *sidhex ? &sender : NULL)); }else if (follow){ - ret = meshmb_follow(feeds, &peer); + ret = meshmb_follow(feeds, &peer, (sidhex && *sidhex ? &sender : NULL), name); }else{ ret = meshmb_ignore(feeds, &peer); } diff --git a/meshmb_restful.c b/meshmb_restful.c index 36b30b4d..7ad5d295 100644 --- a/meshmb_restful.c +++ b/meshmb_restful.c @@ -498,14 +498,34 @@ static int restful_meshmb_follow_ignore(httpd_request *r, const char *remainder) int ret=-1; if (session){ + const char *name = http_request_get_query_param(&r->http, "name"); + const char *sender_hex = http_request_get_query_param(&r->http, "sender"); + sid_t sender; + bzero(&sender, sizeof sender); + if (sender_hex && *sender_hex){ + if (str_to_sid_t(&sender, sender_hex) == -1) + goto fail; + } + switch(r->ui64){ - case FLAG_FOLLOW: ret = meshmb_follow(session->feeds, &r->u.meshmb_feeds.bundle_id); break; - case FLAG_IGNORE: ret = meshmb_ignore(session->feeds, &r->u.meshmb_feeds.bundle_id); break; - case FLAG_BLOCK: ret = meshmb_block (session->feeds, &r->u.meshmb_feeds.bundle_id); break; + case FLAG_FOLLOW: + ret = meshmb_follow(session->feeds, &r->u.meshmb_feeds.bundle_id, + (sender_hex && *sender_hex) ? &sender : NULL, + name); + break; + case FLAG_IGNORE: + ret = meshmb_ignore(session->feeds, &r->u.meshmb_feeds.bundle_id); + break; + case FLAG_BLOCK: + ret = meshmb_block (session->feeds, &r->u.meshmb_feeds.bundle_id, + (sender_hex && *sender_hex) ? &sender : NULL); + break; default: FATAL("Unexpected value"); } } + +fail: if (ret!=-1 && meshmb_flush(session->feeds)!=-1){ http_request_simple_response(&r->http, 201, "TODO, detailed response"); diff --git a/tests/meshmb b/tests/meshmb index 7b91b72d..1a9ff1ab 100755 --- a/tests/meshmb +++ b/tests/meshmb @@ -157,8 +157,8 @@ setup_meshmbBlock() { executeOk_servald meshmb follow $IDA1 $IDA3 } test_meshmbBlock() { - executeOk_servald meshmb block $IDA1 $IDA3 - executeOk_servald meshmb block $IDA1 $IDA4 + executeOk_servald meshmb block $IDA1 $IDA3 $SIDA3 + executeOk_servald meshmb block $IDA1 $IDA4 $SIDA4 executeOk_servald meshmb activity $IDA1 tfw_cat --stdout assertStdoutGrep --matches=1 "0:$IDA2:$SIDA2:Feed B:[0-9]\+:[0-9]\+:Message 1\$"