mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-24 07:16:43 +00:00
Add API's for marking a feed as blocked
This commit is contained in:
parent
f83b15d251
commit
508e95436a
@ -85,6 +85,10 @@ public abstract class AbstractId {
|
|||||||
this.binary = binary;
|
this.binary = binary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean isEquivalent(Object other){
|
||||||
|
return other.getClass() == this.getClass();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
// must be the exact same type with the same binary contents to be considered equal
|
// must be the exact same type with the same binary contents to be considered equal
|
||||||
@ -92,7 +96,7 @@ public abstract class AbstractId {
|
|||||||
return false;
|
return false;
|
||||||
if (other==this)
|
if (other==this)
|
||||||
return true;
|
return true;
|
||||||
if (other.getClass() == this.getClass()) {
|
if (isEquivalent(other)) {
|
||||||
AbstractId oBinary = (AbstractId) other;
|
AbstractId oBinary = (AbstractId) other;
|
||||||
for (int i = 0; i < this.binary.length; i++)
|
for (int i = 0; i < this.binary.length; i++)
|
||||||
if (this.binary[i] != oBinary.binary[i])
|
if (this.binary[i] != oBinary.binary[i])
|
||||||
|
@ -220,12 +220,8 @@ public class ServalDClient implements ServalDHttpConnectionFactory {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int meshmbFollow(Subscriber id, SigningKey peer) throws ServalDInterfaceException, IOException {
|
public int meshmbAlterSubscription(Subscriber id, MeshMBCommon.SubscriptionAction action, SigningKey peer) throws ServalDInterfaceException, IOException {
|
||||||
return MeshMBCommon.follow(this, id, peer);
|
return MeshMBCommon.alterSubscription(this, id, action, peer);
|
||||||
}
|
|
||||||
|
|
||||||
public int meshmbIgnore(Subscriber id, SigningKey peer) throws ServalDInterfaceException, IOException {
|
|
||||||
return MeshMBCommon.ignore(this, id, peer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MeshMBSubscriptionList meshmbSubscriptions(Subscriber identity) throws IOException, ServalDInterfaceException {
|
public MeshMBSubscriptionList meshmbSubscriptions(Subscriber identity) throws IOException, ServalDInterfaceException {
|
||||||
|
@ -29,4 +29,9 @@ public class SigningKey extends AbstractId {
|
|||||||
public String getMimeType() {
|
public String getMimeType() {
|
||||||
return "serval-mesh/id";
|
return "serval-mesh/id";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isEquivalent(Object other){
|
||||||
|
return SigningKey.class.isInstance(other);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,12 @@ public class MeshMBCommon {
|
|||||||
|
|
||||||
public static final String SERVICE = "MeshMB1";
|
public static final String SERVICE = "MeshMB1";
|
||||||
|
|
||||||
|
public enum SubscriptionAction{
|
||||||
|
Follow,
|
||||||
|
Ignore,
|
||||||
|
Block
|
||||||
|
}
|
||||||
|
|
||||||
public static int sendMessage(ServalDHttpConnectionFactory connector, SigningKey id, String text) throws IOException, ServalDInterfaceException {
|
public static int sendMessage(ServalDHttpConnectionFactory connector, SigningKey id, String text) throws IOException, ServalDInterfaceException {
|
||||||
HttpURLConnection conn = connector.newServalDHttpConnection("/restful/meshmb/" + id.toHex() + "/sendmessage");
|
HttpURLConnection conn = connector.newServalDHttpConnection("/restful/meshmb/" + id.toHex() + "/sendmessage");
|
||||||
PostHelper helper = new PostHelper(conn);
|
PostHelper helper = new PostHelper(conn);
|
||||||
@ -28,15 +34,8 @@ public class MeshMBCommon {
|
|||||||
return conn.getResponseCode();
|
return conn.getResponseCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int ignore(ServalDHttpConnectionFactory connector, Subscriber id, SigningKey peer) throws ServalDInterfaceException, IOException {
|
public static int alterSubscription(ServalDHttpConnectionFactory connector, Subscriber id, SubscriptionAction action, SigningKey peer) throws ServalDInterfaceException, IOException {
|
||||||
HttpURLConnection conn = connector.newServalDHttpConnection("/restful/meshmb/" + id.signingKey.toHex() + "/ignore/" + peer.toHex());
|
HttpURLConnection conn = connector.newServalDHttpConnection("/restful/meshmb/" + id.signingKey.toHex() + "/"+action.toString().toLowerCase()+"/" + peer.toHex());
|
||||||
conn.setRequestMethod("POST");
|
|
||||||
conn.connect();
|
|
||||||
return conn.getResponseCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int follow(ServalDHttpConnectionFactory connector, Subscriber id, SigningKey peer) throws ServalDInterfaceException, IOException {
|
|
||||||
HttpURLConnection conn = connector.newServalDHttpConnection("/restful/meshmb/" + id.signingKey.toHex() + "/follow/" + peer.toHex());
|
|
||||||
conn.setRequestMethod("POST");
|
conn.setRequestMethod("POST");
|
||||||
conn.connect();
|
conn.connect();
|
||||||
return conn.getResponseCode();
|
return conn.getResponseCode();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.servalproject.servaldna.meshmb;
|
package org.servalproject.servaldna.meshmb;
|
||||||
|
|
||||||
import org.servalproject.json.JSONTableScanner;
|
import org.servalproject.json.JSONTableScanner;
|
||||||
|
import org.servalproject.json.JSONTokeniser;
|
||||||
import org.servalproject.servaldna.AbstractJsonList;
|
import org.servalproject.servaldna.AbstractJsonList;
|
||||||
import org.servalproject.servaldna.ServalDHttpConnectionFactory;
|
import org.servalproject.servaldna.ServalDHttpConnectionFactory;
|
||||||
import org.servalproject.servaldna.ServalDInterfaceException;
|
import org.servalproject.servaldna.ServalDInterfaceException;
|
||||||
@ -23,9 +24,10 @@ public class MeshMBSubscriptionList extends AbstractJsonList<MeshMBSubscription,
|
|||||||
super(httpConnector, new JSONTableScanner()
|
super(httpConnector, new JSONTableScanner()
|
||||||
.addColumn("id", SigningKey.class)
|
.addColumn("id", SigningKey.class)
|
||||||
.addColumn("author", SubscriberId.class)
|
.addColumn("author", SubscriberId.class)
|
||||||
.addColumn("name", String.class)
|
.addColumn("blocked", Boolean.class)
|
||||||
|
.addColumn("name", String.class, JSONTokeniser.Narrow.ALLOW_NULL)
|
||||||
.addColumn("timestamp", Long.class)
|
.addColumn("timestamp", Long.class)
|
||||||
.addColumn("last_message", String.class)
|
.addColumn("last_message", String.class, JSONTokeniser.Narrow.ALLOW_NULL)
|
||||||
);
|
);
|
||||||
this.identity = identity;
|
this.identity = identity;
|
||||||
}
|
}
|
||||||
@ -40,7 +42,7 @@ public class MeshMBSubscriptionList extends AbstractJsonList<MeshMBSubscription,
|
|||||||
new Subscriber((SubscriberId)row.get("author"),
|
new Subscriber((SubscriberId)row.get("author"),
|
||||||
(SigningKey) row.get("id"),
|
(SigningKey) row.get("id"),
|
||||||
true),
|
true),
|
||||||
false,
|
(Boolean) row.get("blocked"),
|
||||||
(String) row.get("name"),
|
(String) row.get("name"),
|
||||||
(Long) row.get("timestamp"),
|
(Long) row.get("timestamp"),
|
||||||
(String) row.get("last_message")
|
(String) row.get("last_message")
|
||||||
|
141
meshmb.c
141
meshmb.c
@ -22,6 +22,8 @@ struct feed_metadata{
|
|||||||
uint64_t size;
|
uint64_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define FLAG_BLOCKED (1<<0)
|
||||||
|
|
||||||
struct meshmb_feeds{
|
struct meshmb_feeds{
|
||||||
struct tree_root root;
|
struct tree_root root;
|
||||||
keyring_identity *id;
|
keyring_identity *id;
|
||||||
@ -29,8 +31,8 @@ struct meshmb_feeds{
|
|||||||
sign_keypair_t ack_bundle_keypair;
|
sign_keypair_t ack_bundle_keypair;
|
||||||
rhizome_manifest *ack_manifest;
|
rhizome_manifest *ack_manifest;
|
||||||
struct rhizome_write ack_writer;
|
struct rhizome_write ack_writer;
|
||||||
bool_t dirty;
|
|
||||||
uint8_t generation;
|
uint8_t generation;
|
||||||
|
bool_t dirty:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct meshmb_activity_iterator *meshmb_activity_open(struct meshmb_feeds *feeds){
|
struct meshmb_activity_iterator *meshmb_activity_open(struct meshmb_feeds *feeds){
|
||||||
@ -74,6 +76,8 @@ static int activity_next_ack(struct meshmb_activity_iterator *i){
|
|||||||
}else{
|
}else{
|
||||||
struct feed_metadata *metadata;
|
struct feed_metadata *metadata;
|
||||||
if (tree_find(&i->feeds->root, (void**)&metadata, ack.binary, ack.binary_length, NULL, NULL)==TREE_FOUND){
|
if (tree_find(&i->feeds->root, (void**)&metadata, ack.binary, ack.binary_length, NULL, NULL)==TREE_FOUND){
|
||||||
|
if (metadata->details.blocked)
|
||||||
|
continue;
|
||||||
bundle_id = &metadata->bundle_id;
|
bundle_id = &metadata->bundle_id;
|
||||||
i->metadata = metadata;
|
i->metadata = metadata;
|
||||||
}else{
|
}else{
|
||||||
@ -240,6 +244,8 @@ static int activity_ack(struct meshmb_feeds *feeds, struct message_ply_ack *ack)
|
|||||||
|
|
||||||
static int update_stats(struct meshmb_feeds *feeds, struct feed_metadata *metadata, struct message_ply_read *reader)
|
static int update_stats(struct meshmb_feeds *feeds, struct feed_metadata *metadata, struct message_ply_read *reader)
|
||||||
{
|
{
|
||||||
|
if (metadata->details.blocked)
|
||||||
|
return 0;
|
||||||
if (!metadata->details.ply.found){
|
if (!metadata->details.ply.found){
|
||||||
// get the current size from the db
|
// get the current size from the db
|
||||||
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
||||||
@ -329,7 +335,7 @@ static int update_stats(struct meshmb_feeds *feeds, struct feed_metadata *metada
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO, might be quicker to fetch all meshmb bundles and test if they are in the feed list
|
// TODO, might sometimes be quicker to fetch all meshmb bundles and test if they are in the feed list
|
||||||
static int update_stats_tree(void **record, void *context)
|
static int update_stats_tree(void **record, void *context)
|
||||||
{
|
{
|
||||||
struct feed_metadata *metadata = (struct feed_metadata *)*record;
|
struct feed_metadata *metadata = (struct feed_metadata *)*record;
|
||||||
@ -346,7 +352,8 @@ int meshmb_bundle_update(struct meshmb_feeds *feeds, rhizome_manifest *m, struct
|
|||||||
{
|
{
|
||||||
struct feed_metadata *metadata;
|
struct feed_metadata *metadata;
|
||||||
if (strcmp(m->service, RHIZOME_SERVICE_MESHMB) == 0
|
if (strcmp(m->service, RHIZOME_SERVICE_MESHMB) == 0
|
||||||
&& tree_find(&feeds->root, (void**)&metadata, m->keypair.public_key.binary, sizeof m->keypair.public_key.binary, NULL, NULL)==TREE_FOUND){
|
&& tree_find(&feeds->root, (void**)&metadata, m->keypair.public_key.binary, sizeof m->keypair.public_key.binary, NULL, NULL)==TREE_FOUND
|
||||||
|
&& !metadata->details.blocked){
|
||||||
|
|
||||||
metadata->details.ply.found = 1;
|
metadata->details.ply.found = 1;
|
||||||
if (metadata->details.ply.size != m->filesize){
|
if (metadata->details.ply.size != m->filesize){
|
||||||
@ -384,21 +391,24 @@ static int write_metadata(void **record, void *context)
|
|||||||
len += sizeof (rhizome_bid_t);
|
len += sizeof (rhizome_bid_t);
|
||||||
bcopy(metadata->details.ply.author.binary, &buffer[len], sizeof (sid_t));
|
bcopy(metadata->details.ply.author.binary, &buffer[len], sizeof (sid_t));
|
||||||
len += sizeof (sid_t);
|
len += sizeof (sid_t);
|
||||||
buffer[len++]=0;// flags?
|
uint8_t flags = (metadata->details.blocked ? FLAG_BLOCKED : 0);
|
||||||
len+=pack_uint(&buffer[len], metadata->size);
|
buffer[len++]=flags;
|
||||||
len+=pack_uint(&buffer[len], metadata->size - metadata->last_message_offset);
|
if (!metadata->details.blocked){
|
||||||
len+=pack_uint(&buffer[len], metadata->size - metadata->last_seen);
|
len+=pack_uint(&buffer[len], metadata->size);
|
||||||
len+=pack_uint(&buffer[len], metadata->details.timestamp);
|
len+=pack_uint(&buffer[len], metadata->size - metadata->last_message_offset);
|
||||||
if (name_len > 1)
|
len+=pack_uint(&buffer[len], metadata->size - metadata->last_seen);
|
||||||
strncpy_nul((char *)&buffer[len], metadata->details.name, name_len);
|
len+=pack_uint(&buffer[len], metadata->details.timestamp);
|
||||||
else
|
if (name_len > 1)
|
||||||
buffer[len]=0;
|
strncpy_nul((char *)&buffer[len], metadata->details.name, name_len);
|
||||||
len+=name_len;
|
else
|
||||||
if (msg_len > 1)
|
buffer[len]=0;
|
||||||
strncpy_nul((char *)&buffer[len], metadata->details.last_message, msg_len);
|
len+=name_len;
|
||||||
else
|
if (msg_len > 1)
|
||||||
buffer[len]=0;
|
strncpy_nul((char *)&buffer[len], metadata->details.last_message, msg_len);
|
||||||
len+=msg_len;
|
else
|
||||||
|
buffer[len]=0;
|
||||||
|
len+=msg_len;
|
||||||
|
}
|
||||||
assert(len < sizeof buffer);
|
assert(len < sizeof buffer);
|
||||||
DEBUGF(meshmb, "Write %zu bytes of metadata for %s/%s",
|
DEBUGF(meshmb, "Write %zu bytes of metadata for %s/%s",
|
||||||
len,
|
len,
|
||||||
@ -525,10 +535,12 @@ static int read_metadata(struct meshmb_feeds *feeds, struct rhizome_read *read)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
uint64_t delta=0;
|
uint64_t delta=0;
|
||||||
uint64_t size;
|
uint64_t size=0;
|
||||||
uint64_t last_message_offset;
|
uint64_t last_message_offset=0;
|
||||||
uint64_t last_seen;
|
uint64_t last_seen=0;
|
||||||
uint64_t timestamp;
|
uint64_t timestamp=0;
|
||||||
|
const char *name=NULL;
|
||||||
|
const char *msg=NULL;
|
||||||
|
|
||||||
int unpacked;
|
int unpacked;
|
||||||
const rhizome_bid_t *bid = (const rhizome_bid_t *)&buffer[0];
|
const rhizome_bid_t *bid = (const rhizome_bid_t *)&buffer[0];
|
||||||
@ -541,39 +553,41 @@ static int read_metadata(struct meshmb_feeds *feeds, struct rhizome_read *read)
|
|||||||
if (offset >= (unsigned)bytes)
|
if (offset >= (unsigned)bytes)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
//uint8_t flags = buffer[offset++];
|
uint8_t flags = buffer[offset++];
|
||||||
offset++;
|
|
||||||
if (offset >= (unsigned)bytes)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if ((unpacked = unpack_uint(buffer+offset, bytes-offset, &size)) == -1)
|
if (!(flags & FLAG_BLOCKED)){
|
||||||
goto error;
|
|
||||||
offset += unpacked;
|
|
||||||
|
|
||||||
if ((unpacked = unpack_uint(buffer+offset, bytes-offset, &delta)) == -1)
|
|
||||||
goto error;
|
|
||||||
offset += unpacked;
|
|
||||||
last_message_offset = size - delta;
|
|
||||||
|
|
||||||
if ((unpacked = unpack_uint(buffer+offset, bytes-offset, &delta)) == -1)
|
|
||||||
goto error;
|
|
||||||
offset += unpacked;
|
|
||||||
last_seen = size - delta;
|
|
||||||
|
|
||||||
if ((unpacked = unpack_uint(buffer+offset, bytes-offset, ×tamp)) == -1)
|
|
||||||
goto error;
|
|
||||||
offset += unpacked;
|
|
||||||
|
|
||||||
const char *name = (const char *)&buffer[offset];
|
|
||||||
while(buffer[offset++]){
|
|
||||||
if (offset >= (unsigned)bytes)
|
if (offset >= (unsigned)bytes)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
|
|
||||||
const char *msg = (const char *)&buffer[offset];
|
if ((unpacked = unpack_uint(buffer+offset, bytes-offset, &size)) == -1)
|
||||||
while(buffer[offset++]){
|
|
||||||
if (offset >= (unsigned)bytes)
|
|
||||||
goto error;
|
goto error;
|
||||||
|
offset += unpacked;
|
||||||
|
|
||||||
|
if ((unpacked = unpack_uint(buffer+offset, bytes-offset, &delta)) == -1)
|
||||||
|
goto error;
|
||||||
|
offset += unpacked;
|
||||||
|
last_message_offset = size - delta;
|
||||||
|
|
||||||
|
if ((unpacked = unpack_uint(buffer+offset, bytes-offset, &delta)) == -1)
|
||||||
|
goto error;
|
||||||
|
offset += unpacked;
|
||||||
|
last_seen = size - delta;
|
||||||
|
|
||||||
|
if ((unpacked = unpack_uint(buffer+offset, bytes-offset, ×tamp)) == -1)
|
||||||
|
goto error;
|
||||||
|
offset += unpacked;
|
||||||
|
|
||||||
|
name = (const char *)&buffer[offset];
|
||||||
|
while(buffer[offset++]){
|
||||||
|
if (offset >= (unsigned)bytes)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = (const char *)&buffer[offset];
|
||||||
|
while(buffer[offset++]){
|
||||||
|
if (offset >= (unsigned)bytes)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUGF(meshmb, "Seeking backwards %"PRIu64", %u, %zu", read->offset, offset, bytes);
|
DEBUGF(meshmb, "Seeking backwards %"PRIu64", %u, %zu", read->offset, offset, bytes);
|
||||||
@ -583,6 +597,7 @@ static int read_metadata(struct meshmb_feeds *feeds, struct rhizome_read *read)
|
|||||||
if (tree_find(&feeds->root, (void**)&result, bid->binary, sizeof *bid, alloc_feed, feeds)<0)
|
if (tree_find(&feeds->root, (void**)&result, bid->binary, sizeof *bid, alloc_feed, feeds)<0)
|
||||||
return WHY("Failed to allocate metadata");
|
return WHY("Failed to allocate metadata");
|
||||||
|
|
||||||
|
result->details.blocked = (flags & FLAG_BLOCKED) ? 1 : 0;
|
||||||
result->last_message_offset = last_message_offset;
|
result->last_message_offset = last_message_offset;
|
||||||
result->last_seen = last_seen;
|
result->last_seen = last_seen;
|
||||||
result->size = size;
|
result->size = size;
|
||||||
@ -675,8 +690,6 @@ int meshmb_follow(struct meshmb_feeds *feeds, rhizome_bid_t *bid)
|
|||||||
struct feed_metadata *metadata;
|
struct feed_metadata *metadata;
|
||||||
DEBUGF(meshmb, "Attempting to follow %s", alloca_tohex_rhizome_bid_t(*bid));
|
DEBUGF(meshmb, "Attempting to follow %s", alloca_tohex_rhizome_bid_t(*bid));
|
||||||
|
|
||||||
// TODO load the manifest and check the service!
|
|
||||||
|
|
||||||
if (tree_find(&feeds->root, (void**)&metadata, bid->binary, sizeof *bid, alloc_feed, feeds)!=TREE_FOUND)
|
if (tree_find(&feeds->root, (void**)&metadata, bid->binary, sizeof *bid, alloc_feed, feeds)!=TREE_FOUND)
|
||||||
return WHYF("Failed to follow feed");
|
return WHYF("Failed to follow feed");
|
||||||
|
|
||||||
@ -687,6 +700,30 @@ int meshmb_follow(struct meshmb_feeds *feeds, rhizome_bid_t *bid)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int meshmb_block(struct meshmb_feeds *feeds, rhizome_bid_t *bid)
|
||||||
|
{
|
||||||
|
struct feed_metadata *metadata;
|
||||||
|
DEBUGF(meshmb, "Attempting to block %s", alloca_tohex_rhizome_bid_t(*bid));
|
||||||
|
|
||||||
|
if (tree_find(&feeds->root, (void**)&metadata, bid->binary, sizeof *bid, alloc_feed, feeds)!=TREE_FOUND)
|
||||||
|
return WHYF("Failed to block feed");
|
||||||
|
if (metadata->details.name){
|
||||||
|
free((void*)metadata->details.name);
|
||||||
|
metadata->details.name = NULL;
|
||||||
|
}
|
||||||
|
if (metadata->details.last_message){
|
||||||
|
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 (!metadata->details.blocked)
|
||||||
|
feeds->dirty = 1;
|
||||||
|
metadata->details.blocked = 1;
|
||||||
|
metadata->details.timestamp = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int meshmb_ignore(struct meshmb_feeds *feeds, rhizome_bid_t *bid)
|
int meshmb_ignore(struct meshmb_feeds *feeds, rhizome_bid_t *bid)
|
||||||
{
|
{
|
||||||
DEBUGF(meshmb, "Attempting to ignore %s", alloca_tohex_rhizome_bid_t(*bid));
|
DEBUGF(meshmb, "Attempting to ignore %s", alloca_tohex_rhizome_bid_t(*bid));
|
||||||
|
2
meshmb.h
2
meshmb.h
@ -14,6 +14,7 @@ struct meshmb_feed_details{
|
|||||||
const char *name;
|
const char *name;
|
||||||
const char *last_message;
|
const char *last_message;
|
||||||
time_s_t timestamp;
|
time_s_t timestamp;
|
||||||
|
bool_t blocked:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// threaded feed iterator state
|
// threaded feed iterator state
|
||||||
@ -41,6 +42,7 @@ int meshmb_flush(struct meshmb_feeds *feeds);
|
|||||||
// set / clear follow flag for this feed
|
// set / clear follow flag for this feed
|
||||||
int meshmb_follow(struct meshmb_feeds *feeds, rhizome_bid_t *bid);
|
int meshmb_follow(struct meshmb_feeds *feeds, rhizome_bid_t *bid);
|
||||||
int meshmb_ignore(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);
|
||||||
|
|
||||||
// enumerate feeds, starting from restart_from
|
// enumerate feeds, starting from restart_from
|
||||||
typedef int (*meshmb_callback) (struct meshmb_feed_details *details, void *context);
|
typedef int (*meshmb_callback) (struct meshmb_feed_details *details, void *context);
|
||||||
|
13
meshmb_cli.c
13
meshmb_cli.c
@ -212,8 +212,8 @@ static int app_meshmb_find(const struct cli_parsed *parsed, struct cli_context *
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_CMD(app_meshmb_follow, 0,
|
DEFINE_CMD(app_meshmb_follow, 0,
|
||||||
"Start or stop following a broadcast feed",
|
"Follow, block or ignore a broadcast feed",
|
||||||
"meshmb", "follow|ignore" KEYRING_PIN_OPTIONS, "<id>", "<peer>");
|
"meshmb", "follow|ignore|block" KEYRING_PIN_OPTIONS, "<id>", "<peer>");
|
||||||
static int app_meshmb_follow(const struct cli_parsed *parsed, struct cli_context *UNUSED(context))
|
static int app_meshmb_follow(const struct cli_parsed *parsed, struct cli_context *UNUSED(context))
|
||||||
{
|
{
|
||||||
const char *peerhex;
|
const char *peerhex;
|
||||||
@ -221,6 +221,7 @@ static int app_meshmb_follow(const struct cli_parsed *parsed, struct cli_context
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int follow = cli_arg(parsed, "follow", NULL, NULL, NULL) == 0;
|
int follow = cli_arg(parsed, "follow", NULL, NULL, NULL) == 0;
|
||||||
|
int block = cli_arg(parsed, "block", NULL, NULL, NULL) == 0;
|
||||||
|
|
||||||
identity_t peer;
|
identity_t peer;
|
||||||
if (str_to_identity_t(&peer, peerhex) == -1)
|
if (str_to_identity_t(&peer, peerhex) == -1)
|
||||||
@ -230,7 +231,9 @@ static int app_meshmb_follow(const struct cli_parsed *parsed, struct cli_context
|
|||||||
|
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
if (feeds){
|
if (feeds){
|
||||||
if (follow){
|
if (block){
|
||||||
|
ret = meshmb_block(feeds, &peer);
|
||||||
|
}else if (follow){
|
||||||
ret = meshmb_follow(feeds, &peer);
|
ret = meshmb_follow(feeds, &peer);
|
||||||
}else{
|
}else{
|
||||||
ret = meshmb_ignore(feeds, &peer);
|
ret = meshmb_ignore(feeds, &peer);
|
||||||
@ -263,6 +266,7 @@ static int list_callback(struct meshmb_feed_details *details, void *context)
|
|||||||
cli_put_long(enum_context->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->ply.bundle_id), ":");
|
cli_put_string(enum_context->context, alloca_tohex_rhizome_bid_t(details->ply.bundle_id), ":");
|
||||||
cli_put_string(enum_context->context, alloca_tohex_sid_t(details->ply.author), ":");
|
cli_put_string(enum_context->context, alloca_tohex_sid_t(details->ply.author), ":");
|
||||||
|
cli_put_string(enum_context->context, details->blocked ? "true" : "false", ":");
|
||||||
cli_put_string(enum_context->context, details->name, ":");
|
cli_put_string(enum_context->context, details->name, ":");
|
||||||
cli_put_long(enum_context->context, details->timestamp ? (long)(gettime() - details->timestamp) : (long)-1, ":");
|
cli_put_long(enum_context->context, details->timestamp ? (long)(gettime() - details->timestamp) : (long)-1, ":");
|
||||||
cli_put_string(enum_context->context, details->last_message, "\n");
|
cli_put_string(enum_context->context, details->last_message, "\n");
|
||||||
@ -270,7 +274,7 @@ static int list_callback(struct meshmb_feed_details *details, void *context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_CMD(app_meshmb_list, 0,
|
DEFINE_CMD(app_meshmb_list, 0,
|
||||||
"List the feeds that you are currently following",
|
"List the feeds that you are currently following or blocking",
|
||||||
"meshmb", "list", "following" KEYRING_PIN_OPTIONS, "<id>");
|
"meshmb", "list", "following" KEYRING_PIN_OPTIONS, "<id>");
|
||||||
static int app_meshmb_list(const struct cli_parsed *parsed, struct cli_context *context)
|
static int app_meshmb_list(const struct cli_parsed *parsed, struct cli_context *context)
|
||||||
{
|
{
|
||||||
@ -282,6 +286,7 @@ static int app_meshmb_list(const struct cli_parsed *parsed, struct cli_context *
|
|||||||
"_id",
|
"_id",
|
||||||
"id",
|
"id",
|
||||||
"author",
|
"author",
|
||||||
|
"blocked",
|
||||||
"name",
|
"name",
|
||||||
"age",
|
"age",
|
||||||
"last_message"
|
"last_message"
|
||||||
|
@ -20,6 +20,10 @@ struct meshmb_session{
|
|||||||
struct meshmb_feeds *feeds;
|
struct meshmb_feeds *feeds;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define FLAG_FOLLOW (1)
|
||||||
|
#define FLAG_IGNORE (2)
|
||||||
|
#define FLAG_BLOCK (3)
|
||||||
|
|
||||||
static struct meshmb_session *sessions = NULL;
|
static struct meshmb_session *sessions = NULL;
|
||||||
|
|
||||||
static struct meshmb_session *open_session(const identity_t *identity){
|
static struct meshmb_session *open_session(const identity_t *identity){
|
||||||
@ -484,40 +488,25 @@ static int restful_meshmb_newsince_find(httpd_request *r, const char *remainder)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
static int restful_meshmb_follow(httpd_request *r, const char *remainder)
|
static int restful_meshmb_follow_ignore(httpd_request *r, const char *remainder)
|
||||||
{
|
{
|
||||||
if (*remainder)
|
if (*remainder)
|
||||||
return 404;
|
return 404;
|
||||||
assert(r->finalise_union == NULL);
|
assert(r->finalise_union == NULL);
|
||||||
|
|
||||||
struct meshmb_session *session = open_session(&r->bid);
|
struct meshmb_session *session = open_session(&r->bid);
|
||||||
int ret;
|
int ret=-1;
|
||||||
|
|
||||||
if (session
|
if (session){
|
||||||
&& meshmb_follow(session->feeds, &r->u.meshmb_feeds.bundle_id)!=-1
|
switch(r->ui64){
|
||||||
&& meshmb_flush(session->feeds)!=-1){
|
case FLAG_FOLLOW: ret = meshmb_follow(session->feeds, &r->u.meshmb_feeds.bundle_id); break;
|
||||||
http_request_simple_response(&r->http, 201, "TODO, detailed response");
|
case FLAG_IGNORE: ret = meshmb_ignore(session->feeds, &r->u.meshmb_feeds.bundle_id); break;
|
||||||
ret = 201;
|
case FLAG_BLOCK: ret = meshmb_block (session->feeds, &r->u.meshmb_feeds.bundle_id); break;
|
||||||
}else{
|
default:
|
||||||
http_request_simple_response(&r->http, 500, "TODO, detailed response");
|
FATAL("Unexpected value");
|
||||||
ret = 500;
|
}
|
||||||
}
|
}
|
||||||
if (session)
|
if (ret!=-1
|
||||||
close_session(session);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int restful_meshmb_ignore(httpd_request *r, const char *remainder)
|
|
||||||
{
|
|
||||||
if (*remainder)
|
|
||||||
return 404;
|
|
||||||
assert(r->finalise_union == NULL);
|
|
||||||
|
|
||||||
struct meshmb_session *session = open_session(&r->bid);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (session
|
|
||||||
&& meshmb_ignore(session->feeds, &r->u.meshmb_feeds.bundle_id)!=-1
|
|
||||||
&& meshmb_flush(session->feeds)!=-1){
|
&& meshmb_flush(session->feeds)!=-1){
|
||||||
http_request_simple_response(&r->http, 201, "TODO, detailed response");
|
http_request_simple_response(&r->http, 201, "TODO, detailed response");
|
||||||
ret = 201;
|
ret = 201;
|
||||||
@ -545,7 +534,7 @@ static int restful_feedlist_enum(struct meshmb_feed_details *details, void *cont
|
|||||||
strbuf_json_hex(state->buffer, details->ply.bundle_id.binary, sizeof details->ply.bundle_id.binary);
|
strbuf_json_hex(state->buffer, details->ply.bundle_id.binary, sizeof details->ply.bundle_id.binary);
|
||||||
strbuf_puts(state->buffer, ",");
|
strbuf_puts(state->buffer, ",");
|
||||||
strbuf_json_hex(state->buffer, details->ply.author.binary, sizeof details->ply.author.binary);
|
strbuf_json_hex(state->buffer, details->ply.author.binary, sizeof details->ply.author.binary);
|
||||||
strbuf_puts(state->buffer, ",");
|
strbuf_puts(state->buffer, details->blocked ? ",true," : ",false,");
|
||||||
strbuf_json_string(state->buffer, details->name);
|
strbuf_json_string(state->buffer, details->name);
|
||||||
strbuf_puts(state->buffer, ",");
|
strbuf_puts(state->buffer, ",");
|
||||||
strbuf_sprintf(state->buffer, "%d", details->timestamp);
|
strbuf_sprintf(state->buffer, "%d", details->timestamp);
|
||||||
@ -569,6 +558,7 @@ static int restful_meshmb_feedlist_json_content_chunk(struct http_request *hr, s
|
|||||||
const char *headers[] = {
|
const char *headers[] = {
|
||||||
"id",
|
"id",
|
||||||
"author",
|
"author",
|
||||||
|
"blocked",
|
||||||
"name",
|
"name",
|
||||||
"timestamp",
|
"timestamp",
|
||||||
"last_message"
|
"last_message"
|
||||||
@ -918,13 +908,21 @@ static int restful_meshmb_(httpd_request *r, const char *remainder)
|
|||||||
remainder = "";
|
remainder = "";
|
||||||
} else if(str_startswith(remainder, "/follow/", &end)
|
} else if(str_startswith(remainder, "/follow/", &end)
|
||||||
&& strn_to_identity_t(&r->u.meshmb_feeds.bundle_id, end, &end) != -1) {
|
&& strn_to_identity_t(&r->u.meshmb_feeds.bundle_id, end, &end) != -1) {
|
||||||
handler = restful_meshmb_follow;
|
handler = restful_meshmb_follow_ignore;
|
||||||
verb = HTTP_VERB_POST;
|
verb = HTTP_VERB_POST;
|
||||||
|
r->ui64 = FLAG_FOLLOW;
|
||||||
remainder = "";
|
remainder = "";
|
||||||
} else if(str_startswith(remainder, "/ignore/", &end)
|
} else if(str_startswith(remainder, "/ignore/", &end)
|
||||||
&& strn_to_identity_t(&r->u.meshmb_feeds.bundle_id, end, &end) != -1) {
|
&& strn_to_identity_t(&r->u.meshmb_feeds.bundle_id, end, &end) != -1) {
|
||||||
handler = restful_meshmb_ignore;
|
handler = restful_meshmb_follow_ignore;
|
||||||
verb = HTTP_VERB_POST;
|
verb = HTTP_VERB_POST;
|
||||||
|
r->ui64 = FLAG_IGNORE;
|
||||||
|
remainder = "";
|
||||||
|
} else if(str_startswith(remainder, "/block/", &end)
|
||||||
|
&& strn_to_identity_t(&r->u.meshmb_feeds.bundle_id, end, &end) != -1) {
|
||||||
|
handler = restful_meshmb_follow_ignore;
|
||||||
|
verb = HTTP_VERB_POST;
|
||||||
|
r->ui64 = FLAG_BLOCK;
|
||||||
remainder = "";
|
remainder = "";
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
40
tests/meshmb
40
tests/meshmb
@ -85,16 +85,16 @@ setup_meshmbFollow() {
|
|||||||
test_meshmbFollow() {
|
test_meshmbFollow() {
|
||||||
executeOk_servald meshmb follow $IDA1 $IDA2
|
executeOk_servald meshmb follow $IDA1 $IDA2
|
||||||
executeOk_servald meshmb list following $IDA1
|
executeOk_servald meshmb list following $IDA1
|
||||||
assertStdoutGrep --matches=1 ":$IDA2:$SIDA2:Feed B:[0-9]\+:Message 2\$"
|
assertStdoutGrep --matches=1 ":$IDA2:$SIDA2:false:Feed B:[0-9]\+:Message 2\$"
|
||||||
assertStdoutGrep --matches=0 ":$IDA3:$SIDA3:Feed C:[0-9]\+:Message 3\$"
|
assertStdoutGrep --matches=0 ":$IDA3:$SIDA3:false:Feed C:[0-9]\+:Message 3\$"
|
||||||
executeOk_servald meshmb follow $IDA1 $IDA3
|
executeOk_servald meshmb follow $IDA1 $IDA3
|
||||||
executeOk_servald meshmb list following $IDA1
|
executeOk_servald meshmb list following $IDA1
|
||||||
assertStdoutGrep --matches=1 ":$IDA2:$SIDA2:Feed B:[0-9]\+:Message 2\$"
|
assertStdoutGrep --matches=1 ":$IDA2:$SIDA2:false:Feed B:[0-9]\+:Message 2\$"
|
||||||
assertStdoutGrep --matches=1 ":$IDA3:$SIDA3:Feed C:[0-9]\+:Message 3\$"
|
assertStdoutGrep --matches=1 ":$IDA3:$SIDA3:false:Feed C:[0-9]\+:Message 3\$"
|
||||||
executeOk_servald meshmb ignore $IDA1 $IDA2
|
executeOk_servald meshmb ignore $IDA1 $IDA2
|
||||||
executeOk_servald meshmb list following $IDA1
|
executeOk_servald meshmb list following $IDA1
|
||||||
assertStdoutGrep --matches=0 ":$IDA2:$SIDA2:Feed B:[0-9]\+:Message 2\$"
|
assertStdoutGrep --matches=0 ":$IDA2:$SIDA2:false:Feed B:[0-9]\+:Message 2\$"
|
||||||
assertStdoutGrep --matches=1 ":$IDA3:$SIDA3:Feed C:[0-9]\+:Message 3\$"
|
assertStdoutGrep --matches=1 ":$IDA3:$SIDA3:false:Feed C:[0-9]\+:Message 3\$"
|
||||||
}
|
}
|
||||||
|
|
||||||
doc_meshmbThreading="Thread incoming message feeds"
|
doc_meshmbThreading="Thread incoming message feeds"
|
||||||
@ -143,4 +143,32 @@ test_meshmbThreading() {
|
|||||||
assertStdoutGrep --matches=1 "5:$IDA5:$SIDA5:Feed E:[0-9]\+:[0-9]\+:Message 6\$"
|
assertStdoutGrep --matches=1 "5:$IDA5:$SIDA5:Feed E:[0-9]\+:[0-9]\+:Message 6\$"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doc_meshmbBlock="Record blocked feeds"
|
||||||
|
setup_meshmbBlock() {
|
||||||
|
setup_identities 4
|
||||||
|
executeOk_servald keyring set did $SIDA1 "" "Feed A"
|
||||||
|
executeOk_servald keyring set did $SIDA2 "" "Feed B"
|
||||||
|
executeOk_servald keyring set did $SIDA3 "" "Feed C"
|
||||||
|
executeOk_servald keyring set did $SIDA4 "" "Feed D"
|
||||||
|
executeOk_servald meshmb send $IDA2 "Message 1"
|
||||||
|
executeOk_servald meshmb send $IDA3 "Message 2"
|
||||||
|
executeOk_servald meshmb send $IDA4 "Message 3"
|
||||||
|
executeOk_servald meshmb follow $IDA1 $IDA2
|
||||||
|
executeOk_servald meshmb follow $IDA1 $IDA3
|
||||||
|
}
|
||||||
|
test_meshmbBlock() {
|
||||||
|
executeOk_servald meshmb block $IDA1 $IDA3
|
||||||
|
executeOk_servald meshmb block $IDA1 $IDA4
|
||||||
|
executeOk_servald meshmb activity $IDA1
|
||||||
|
tfw_cat --stdout
|
||||||
|
assertStdoutGrep --matches=1 "0:$IDA2:$SIDA2:Feed B:[0-9]\+:[0-9]\+:Message 1\$"
|
||||||
|
# what was followed, disappears
|
||||||
|
assertStdoutGrep --matches=0 ":$IDA3:$SIDA3:"
|
||||||
|
executeOk_servald meshmb list following $IDA1
|
||||||
|
tfw_cat --stdout
|
||||||
|
assertStdoutGrep --matches=1 ":$IDA2:$SIDA2:false:Feed B:[0-9]\+:Message 1\$"
|
||||||
|
assertStdoutGrep --matches=1 ":$IDA3:$SIDA3:true::-1:\$"
|
||||||
|
assertStdoutGrep --matches=1 ":$IDA4:$SIDA4:true::-1:\$"
|
||||||
|
}
|
||||||
|
|
||||||
runTests "$@"
|
runTests "$@"
|
||||||
|
@ -110,8 +110,8 @@ test_MeshMBRestFollow() {
|
|||||||
--request POST \
|
--request POST \
|
||||||
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/follow/$IDA2"
|
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/follow/$IDA2"
|
||||||
executeOk_servald meshmb list following $IDA1
|
executeOk_servald meshmb list following $IDA1
|
||||||
assertStdoutGrep --matches=1 ":$IDA2:$SIDA2::[0-9]\+:Message 2\$"
|
assertStdoutGrep --matches=1 ":$IDA2:$SIDA2:false::[0-9]\+:Message 2\$"
|
||||||
assertStdoutGrep --matches=0 ":$IDA3:$SIDA3::[0-9]\+:Message 3\$"
|
assertStdoutGrep --matches=0 ":$IDA3:$SIDA3:false::[0-9]\+:Message 3\$"
|
||||||
executeOk curl \
|
executeOk curl \
|
||||||
--silent --fail --show-error \
|
--silent --fail --show-error \
|
||||||
--output follow.json \
|
--output follow.json \
|
||||||
@ -119,8 +119,8 @@ test_MeshMBRestFollow() {
|
|||||||
--request POST \
|
--request POST \
|
||||||
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/follow/$IDA3"
|
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/follow/$IDA3"
|
||||||
executeOk_servald meshmb list following $IDA1
|
executeOk_servald meshmb list following $IDA1
|
||||||
assertStdoutGrep --matches=1 ":$IDA2:$SIDA2::[0-9]\+:Message 2\$"
|
assertStdoutGrep --matches=1 ":$IDA2:$SIDA2:false::[0-9]\+:Message 2\$"
|
||||||
assertStdoutGrep --matches=1 ":$IDA3:$SIDA3::[0-9]\+:Message 3\$"
|
assertStdoutGrep --matches=1 ":$IDA3:$SIDA3:false::[0-9]\+:Message 3\$"
|
||||||
executeOk curl \
|
executeOk curl \
|
||||||
--silent --fail --show-error \
|
--silent --fail --show-error \
|
||||||
--output follow.json \
|
--output follow.json \
|
||||||
@ -128,8 +128,8 @@ test_MeshMBRestFollow() {
|
|||||||
--request POST \
|
--request POST \
|
||||||
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/ignore/$IDA2"
|
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/ignore/$IDA2"
|
||||||
executeOk_servald meshmb list following $IDA1
|
executeOk_servald meshmb list following $IDA1
|
||||||
assertStdoutGrep --matches=0 ":$IDA2:$SIDA2::[0-9]\+:Message 2\$"
|
assertStdoutGrep --matches=0 ":$IDA2:$SIDA2:false::[0-9]\+:Message 2\$"
|
||||||
assertStdoutGrep --matches=1 ":$IDA3:$SIDA3::[0-9]\+:Message 3\$"
|
assertStdoutGrep --matches=1 ":$IDA3:$SIDA3:false::[0-9]\+:Message 3\$"
|
||||||
}
|
}
|
||||||
|
|
||||||
doc_MeshMBRestFeeds="Restful list subscribed feeds"
|
doc_MeshMBRestFeeds="Restful list subscribed feeds"
|
||||||
|
Loading…
Reference in New Issue
Block a user