Add bundle author to feed metadata

This commit is contained in:
Jeremy Lakeman 2017-02-06 12:53:12 +10:30
parent a0dbe115aa
commit 5ccff053c2
11 changed files with 90 additions and 36 deletions

View File

@ -2,18 +2,19 @@ package org.servalproject.servaldna.meshmb;
import org.servalproject.servaldna.BundleId;
import org.servalproject.servaldna.SigningKey;
import org.servalproject.servaldna.Subscriber;
/**
* Created by jeremy on 11/01/17.
*/
public class MeshMBSubscription {
public final SigningKey id;
public final Subscriber subscriber;
public final String name;
public final long timestamp;
public final String lastMessage;
public MeshMBSubscription(SigningKey id, String name, long timestamp, String lastMessage){
this.id = id;
public MeshMBSubscription(Subscriber subscriber, String name, long timestamp, String lastMessage){
this.subscriber = subscriber;
this.name = name;
this.lastMessage = lastMessage;
this.timestamp = timestamp;

View File

@ -6,6 +6,7 @@ import org.servalproject.servaldna.ServalDHttpConnectionFactory;
import org.servalproject.servaldna.ServalDInterfaceException;
import org.servalproject.servaldna.SigningKey;
import org.servalproject.servaldna.Subscriber;
import org.servalproject.servaldna.SubscriberId;
import java.io.IOException;
import java.util.Map;
@ -21,6 +22,7 @@ public class MeshMBSubscriptionList extends AbstractJsonList<MeshMBSubscription,
public MeshMBSubscriptionList(ServalDHttpConnectionFactory httpConnector, Subscriber identity){
super(httpConnector, new JSONTableScanner()
.addColumn("id", SigningKey.class)
.addColumn("author", SubscriberId.class)
.addColumn("name", String.class)
.addColumn("timestamp", Long.class)
.addColumn("last_message", String.class)
@ -35,7 +37,9 @@ public class MeshMBSubscriptionList extends AbstractJsonList<MeshMBSubscription,
@Override
protected MeshMBSubscription factory(Map<String, Object> row, long rowCount) throws ServalDInterfaceException {
return new MeshMBSubscription(
(SigningKey) row.get("id"),
new Subscriber((SubscriberId)row.get("author"),
(SigningKey) row.get("id"),
true),
(String) row.get("name"),
(Long) row.get("timestamp"),
(String) row.get("last_message")

View File

@ -60,6 +60,7 @@ static void update_stats(struct meshmb_feeds *feeds, struct feed_metadata *metad
free((void*)metadata->details.name);
metadata->details.name = NULL;
}
metadata->details.author = reader->author;
if (reader->name){
size_t len = strlen(reader->name);
@ -147,9 +148,12 @@ static int write_metadata(void **record, void *context)
unsigned msg_len = (metadata->details.last_message ? strlen(metadata->details.last_message) : 0) + 1;
assert(msg_len <= MAX_MSG_LEN);
uint8_t buffer[sizeof (rhizome_bid_t) + 1 + 12*4 + name_len + msg_len];
bcopy(metadata->ply.bundle_id.binary, buffer, sizeof (rhizome_bid_t));
size_t len = sizeof (rhizome_bid_t);
uint8_t buffer[sizeof (rhizome_bid_t) + sizeof (sid_t) + 1 + 12*4 + name_len + msg_len];
size_t len = 0;
bcopy(metadata->ply.bundle_id.binary, &buffer[len], sizeof (rhizome_bid_t));
len += sizeof (rhizome_bid_t);
bcopy(metadata->details.author.binary, &buffer[len], sizeof (sid_t));
len += sizeof (sid_t);
buffer[len++]=0;// flags?
len+=pack_uint(&buffer[len], metadata->size);
len+=pack_uint(&buffer[len], metadata->size - metadata->last_message_offset);
@ -166,7 +170,11 @@ static int write_metadata(void **record, void *context)
buffer[len]=0;
len+=msg_len;
assert(len < sizeof buffer);
DEBUGF(meshmb, "Write %u bytes of metadata for %s", len, alloca_tohex_rhizome_bid_t(metadata->ply.bundle_id));
DEBUGF(meshmb, "Write %u bytes of metadata for %s/%s",
len,
alloca_tohex_rhizome_bid_t(metadata->ply.bundle_id),
alloca_tohex_sid_t(metadata->details.author)
);
return rhizome_write_buffer(write, buffer, len);
}
@ -267,7 +275,7 @@ static int read_metadata(struct meshmb_feeds *feeds, struct rhizome_read *read)
{
struct rhizome_read_buffer buff;
bzero(&buff, sizeof(buff));
uint8_t buffer[sizeof (rhizome_bid_t) + 12*3 + MAX_NAME_LEN + MAX_MSG_LEN];
uint8_t buffer[sizeof (rhizome_bid_t) + sizeof (sid_t) + 12*3 + MAX_NAME_LEN + MAX_MSG_LEN];
uint8_t version=0xFF;
if (rhizome_read_buffered(read, &buff, &version, 1)==-1)
@ -291,40 +299,46 @@ static int read_metadata(struct meshmb_feeds *feeds, struct rhizome_read *read)
const rhizome_bid_t *bid = (const rhizome_bid_t *)&buffer[0];
unsigned offset = sizeof(rhizome_bid_t);
if (offset >= (unsigned)bytes)
return WHY("Buffer overflow while parsing metadata");
goto error;
const sid_t *author = (const sid_t *)&buffer[offset];
offset+= sizeof(sid_t);
if (offset >= (unsigned)bytes)
goto error;
//uint8_t flags = buffer[offset++];
offset++;
if (offset >= (unsigned)bytes)
return WHY("Buffer overflow while parsing metadata");
goto error;
if ((unpacked = unpack_uint(buffer+offset, bytes-offset, &size)) == -1)
return WHY("Buffer overflow while parsing metadata");
goto error;
offset += unpacked;
if ((unpacked = unpack_uint(buffer+offset, bytes-offset, &delta)) == -1)
return WHY("Buffer overflow while parsing metadata");
goto error;
offset += unpacked;
last_message_offset = size - delta;
if ((unpacked = unpack_uint(buffer+offset, bytes-offset, &delta)) == -1)
return WHY("Buffer overflow while parsing metadata");
goto error;
offset += unpacked;
last_seen = size - delta;
if ((unpacked = unpack_uint(buffer+offset, bytes-offset, &timestamp)) == -1)
return WHY("Buffer overflow while parsing metadata");
goto error;
offset += unpacked;
const char *name = (const char *)&buffer[offset];
while(buffer[offset++]){
if (offset >= (unsigned)bytes)
return WHY("Buffer overflow while parsing metadata");
goto error;
}
const char *msg = (const char *)&buffer[offset];
while(buffer[offset++]){
if (offset >= (unsigned)bytes)
return WHY("Buffer overflow while parsing metadata");
goto error;
}
read->offset += offset - bytes;
@ -336,14 +350,22 @@ static int read_metadata(struct meshmb_feeds *feeds, struct rhizome_read *read)
result->last_seen = last_seen;
result->size = size;
result->details.bundle_id = *bid;
result->details.author = *author;
result->details.name = (name && *name) ? str_edup(name) : NULL;
result->details.last_message = (msg && *msg) ? str_edup(msg) : NULL;
result->details.timestamp = timestamp;
DEBUGF(meshmb, "Processed %u bytes of metadata for %s", offset, alloca_tohex_rhizome_bid_t(result->ply.bundle_id));
DEBUGF(meshmb, "Processed %u bytes of metadata for %s",
offset,
alloca_tohex_rhizome_bid_t(result->ply.bundle_id),
alloca_tohex_sid_t(result->details.author)
);
}
feeds->dirty = 0;
return 0;
error:
return WHY("Buffer overflow while parsing metadata");
}
int meshmb_open(keyring_identity *id, struct meshmb_feeds **feeds)

View File

@ -11,6 +11,7 @@ enum meshmb_send_status{
// details of a feed that you are following
struct meshmb_feed_details{
rhizome_bid_t bundle_id;
sid_t author;
const char *name;
const char *last_message;
time_s_t timestamp;

View File

@ -140,6 +140,7 @@ static int app_meshmb_find(const struct cli_parsed *parsed, struct cli_context *
const char *names[]={
"_id",
"id",
"author",
"version",
"date",
"name"
@ -154,6 +155,20 @@ static int app_meshmb_find(const struct cli_parsed *parsed, struct cli_context *
rhizome_manifest *m = cursor.manifest;
cli_put_long(context, m->rowid, ":");
cli_put_hexvalue(context, m->keypair.public_key.binary, sizeof m->keypair.public_key.binary, ":");
switch (m->authorship) {
case AUTHOR_NOT_CHECKED:
case AUTHOR_AUTHENTIC:
case AUTHOR_LOCAL:
case AUTHOR_REMOTE:
cli_put_hexvalue(context, m->author.binary, sizeof m->author.binary, ":");
break;
default:
cli_put_string(context, NULL, ":");
break;
}
cli_put_long(context, m->version, ":");
cli_put_long(context, m->has_date ? m->date : 0, ":");
cli_put_string(context, m->name, "\n");
@ -232,6 +247,7 @@ static int list_callback(struct meshmb_feed_details *details, void *context)
enum_context->rowcount++;
cli_put_long(enum_context->context, enum_context->rowcount, ":");
cli_put_string(enum_context->context, alloca_tohex_rhizome_bid_t(details->bundle_id), ":");
cli_put_string(enum_context->context, alloca_tohex_sid_t(details->author), ":");
cli_put_string(enum_context->context, details->name, ":");
cli_put_long(enum_context->context, details->timestamp ? (long)(gettime() - details->timestamp) : (long)-1, ":");
cli_put_string(enum_context->context, details->last_message, "\n");
@ -271,6 +287,7 @@ static int app_meshmb_list(const struct cli_parsed *parsed, struct cli_context *
const char *names[]={
"_id",
"id",
"author",
"name",
"age",
"last_message"

View File

@ -508,6 +508,8 @@ static int restful_feedlist_enum(struct meshmb_feed_details *details, void *cont
strbuf_puts(state->buffer, "\n[");
strbuf_json_hex(state->buffer, details->bundle_id.binary, sizeof details->bundle_id.binary);
strbuf_puts(state->buffer, ",");
strbuf_json_hex(state->buffer, details->author.binary, sizeof details->author.binary);
strbuf_puts(state->buffer, ",");
strbuf_json_string(state->buffer, details->name);
strbuf_puts(state->buffer, ",");
strbuf_sprintf(state->buffer, "%d", details->timestamp);
@ -530,6 +532,7 @@ static int restful_meshmb_feedlist_json_content_chunk(struct http_request *hr, s
httpd_request *r = (httpd_request *) hr;
const char *headers[] = {
"id",
"author",
"name",
"timestamp",
"last_message"

View File

@ -17,6 +17,7 @@ static int message_ply_load_manifest(const keyring_identity *id, struct message_
if (!m->haveSecret || m->authorship != AUTHOR_AUTHENTIC)
return -1;
assert(m->author_identity == id);
ply->author=m->author;
return 0;
}
@ -58,6 +59,7 @@ static int message_ply_fill_manifest(const keyring_identity *id, const sid_t *re
assert(m->haveSecret);
assert(!recipient || m->payloadEncryption == PAYLOAD_ENCRYPTED);
ply->bundle_id = m->keypair.public_key;
ply->author = m->author;
ply->found = ply->known_bid = 1;
}
return ret;
@ -142,6 +144,7 @@ int message_ply_read_open(struct message_ply_read *ply, const rhizome_bid_t *bid
&& rhizome_open_decrypt_read(m, &ply->read) == RHIZOME_PAYLOAD_STATUS_STORED){
assert(m->filesize != RHIZOME_SIZE_UNSET);
ply->author = m->author;
ply->read.offset = ply->read.length = m->filesize;
if (m->name && *m->name)
ply->name = str_edup(m->name);

View File

@ -11,6 +11,7 @@
// the manifest details for one ply
struct message_ply {
rhizome_bid_t bundle_id;
sid_t author;
uint64_t version;
uint64_t tail;
uint64_t size;
@ -26,6 +27,8 @@ struct message_ply_read {
struct rhizome_read_buffer buff;
// copy of the manifest name field
const char *name;
// copy of the manifest author
sid_t author;
// details of the current record
uint64_t record_end_offset;
uint16_t record_length;

View File

@ -76,7 +76,7 @@ static void cli_put_manifest(struct cli_context *context, const rhizome_manifest
cli_field_name(context, ".secret", ":");
cli_put_string(context, secret, "\n");
}
if (m->authorship == AUTHOR_AUTHENTIC) {
if (m->authorship == AUTHOR_AUTHENTIC || m->authorship == AUTHOR_REMOTE) {
cli_field_name(context, ".author", ":");
cli_put_string(context, alloca_tohex_sid_t(m->author), "\n");
}

View File

@ -65,10 +65,10 @@ setup_meshmbListFeeds() {
test_meshmbListFeeds() {
executeOk_servald meshmb find
tfw_cat --stdout
assertStdoutGrep --matches=1 "^_id:id:version:date:name$"
assertStdoutGrep --matches=1 ":${IDA1}:"
assertStdoutGrep --matches=1 ":${IDA2}:"
assertStdoutGrep --matches=1 ":${IDA3}:"
assertStdoutGrep --matches=1 "^_id:id:author:version:date:name$"
assertStdoutGrep --matches=1 ":${IDA1}:${SIDA1}:"
assertStdoutGrep --matches=1 ":${IDA2}:${SIDA2}:"
assertStdoutGrep --matches=1 ":${IDA3}:${SIDA3}:"
assertStdoutLineCount '==' 5
}
@ -85,16 +85,16 @@ setup_meshmbFollow() {
test_meshmbFollow() {
executeOk_servald meshmb follow $IDA1 $IDA2
executeOk_servald meshmb list following $IDA1
assertStdoutGrep --matches=1 ":$IDA2:Feed B:[0-9]\+:Message 2\$"
assertStdoutGrep --matches=0 ":$IDA3:Feed C:[0-9]\+:Message 3\$"
assertStdoutGrep --matches=1 ":$IDA2:$SIDA2:Feed B:[0-9]\+:Message 2\$"
assertStdoutGrep --matches=0 ":$IDA3:$SIDA3:Feed C:[0-9]\+:Message 3\$"
executeOk_servald meshmb follow $IDA1 $IDA3
executeOk_servald meshmb list following $IDA1
assertStdoutGrep --matches=1 ":$IDA2:Feed B:[0-9]\+:Message 2\$"
assertStdoutGrep --matches=1 ":$IDA3:Feed C:[0-9]\+:Message 3\$"
assertStdoutGrep --matches=1 ":$IDA2:$SIDA2:Feed B:[0-9]\+:Message 2\$"
assertStdoutGrep --matches=1 ":$IDA3:$SIDA3:Feed C:[0-9]\+:Message 3\$"
executeOk_servald meshmb ignore $IDA1 $IDA2
executeOk_servald meshmb list following $IDA1
assertStdoutGrep --matches=0 ":$IDA2:Feed B:[0-9]\+:Message 2\$"
assertStdoutGrep --matches=1 ":$IDA3:Feed C:[0-9]\+:Message 3\$"
assertStdoutGrep --matches=0 ":$IDA2:$SIDA2:Feed B:[0-9]\+:Message 2\$"
assertStdoutGrep --matches=1 ":$IDA3:$SIDA3:Feed C:[0-9]\+:Message 3\$"
}
runTests "$@"

View File

@ -113,8 +113,8 @@ test_MeshMBRestFollow() {
--request POST \
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/follow/$IDA2"
executeOk_servald meshmb list following $IDA1
assertStdoutGrep --matches=1 ":$IDA2::[0-9]\+:Message 2\$"
assertStdoutGrep --matches=0 ":$IDA3::[0-9]\+:Message 3\$"
assertStdoutGrep --matches=1 ":$IDA2:$SIDA2::[0-9]\+:Message 2\$"
assertStdoutGrep --matches=0 ":$IDA3:$SIDA3::[0-9]\+:Message 3\$"
executeOk curl \
-H "Expect:" \
--silent --fail --show-error \
@ -123,8 +123,8 @@ test_MeshMBRestFollow() {
--request POST \
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/follow/$IDA3"
executeOk_servald meshmb list following $IDA1
assertStdoutGrep --matches=1 ":$IDA2::[0-9]\+:Message 2\$"
assertStdoutGrep --matches=1 ":$IDA3::[0-9]\+:Message 3\$"
assertStdoutGrep --matches=1 ":$IDA2:$SIDA2::[0-9]\+:Message 2\$"
assertStdoutGrep --matches=1 ":$IDA3:$SIDA3::[0-9]\+:Message 3\$"
executeOk curl \
-H "Expect:" \
--silent --fail --show-error \
@ -133,8 +133,8 @@ test_MeshMBRestFollow() {
--request POST \
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/ignore/$IDA2"
executeOk_servald meshmb list following $IDA1
assertStdoutGrep --matches=0 ":$IDA2::[0-9]\+:Message 2\$"
assertStdoutGrep --matches=1 ":$IDA3::[0-9]\+:Message 3\$"
assertStdoutGrep --matches=0 ":$IDA2:$SIDA2::[0-9]\+:Message 2\$"
assertStdoutGrep --matches=1 ":$IDA3:$SIDA3::[0-9]\+:Message 3\$"
}
doc_MeshMBRestFeeds="Restful list subscribed feeds"