Allow following a feed that isn't in rhizome yet, and override the displayed name

This commit is contained in:
Jeremy Lakeman 2017-06-14 14:51:06 +09:30
parent 508e95436a
commit 9cb561229a
7 changed files with 99 additions and 41 deletions

View File

@ -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 {

View File

@ -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<ServalDHttpConnectionFactory.QueryParam> 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();

View File

@ -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);

View File

@ -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);

View File

@ -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, "<id>", "<peer>");
"meshmb", "follow|ignore|block" KEYRING_PIN_OPTIONS, "<id>", "<peer>", "[<sender>]", "[<name>]");
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);
}

View File

@ -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");

View File

@ -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\$"