Add restful API's for follow and ignore

This commit is contained in:
Jeremy Lakeman 2016-12-13 12:25:38 +10:30
parent a8c29bbb15
commit e7ca268dbc
8 changed files with 193 additions and 45 deletions

View File

@ -216,6 +216,12 @@ typedef struct httpd_request
time_s_t timestamp;
bool_t eof;
} plylist;
struct {
rhizome_bid_t bundle_id;
enum list_phase phase;
size_t rowcount;
} meshmb_feeds;
struct {
int fd;

View File

@ -204,6 +204,14 @@ public class ServalDClient implements ServalDHttpConnectionFactory {
return list;
}
public int meshmbFollow(SigningKey id, SigningKey peer) throws ServalDInterfaceException, IOException {
return MeshMBCommon.follow(this, id, peer);
}
public int meshmbIgnore(SigningKey id, SigningKey peer) throws ServalDInterfaceException, IOException {
return MeshMBCommon.ignore(this, id, peer);
}
// interface ServalDHttpConnectionFactory
public HttpURLConnection newServalDHttpConnection(String path) throws ServalDInterfaceException, IOException
{

View File

@ -1,6 +1,7 @@
package org.servalproject.servaldna.meshmb;
import org.servalproject.servaldna.PostHelper;
import org.servalproject.servaldna.ServalDClient;
import org.servalproject.servaldna.ServalDHttpConnectionFactory;
import org.servalproject.servaldna.ServalDInterfaceException;
import org.servalproject.servaldna.SigningKey;
@ -26,5 +27,17 @@ public class MeshMBCommon {
return conn.getResponseCode();
}
public static int ignore(ServalDHttpConnectionFactory connector, SigningKey id, SigningKey peer) throws ServalDInterfaceException, IOException {
HttpURLConnection conn = connector.newServalDHttpConnection("/restful/meshmb/" + id.toHex() + "/follow/" + peer.toHex());
conn.setRequestMethod("POST");
conn.connect();
return conn.getResponseCode();
}
public static int follow(ServalDHttpConnectionFactory connector, SigningKey id, SigningKey peer) throws ServalDInterfaceException, IOException {
HttpURLConnection conn = connector.newServalDHttpConnection("/restful/meshmb/" + id.toHex() + "/ignore/" + peer.toHex());
conn.setRequestMethod("POST");
conn.connect();
return conn.getResponseCode();
}
}

27
mem.c
View File

@ -60,30 +60,3 @@ char *_str_edup(struct __sourceloc __whence, const char *str)
{
return _strn_edup(__whence, str, strlen(str));
}
#undef malloc
#undef calloc
#undef free
#undef realloc
#define SDM_GUARD_AFTER 16384
void *_serval_debug_malloc(unsigned int bytes, struct __sourceloc __whence)
{
void *r=malloc(bytes+SDM_GUARD_AFTER);
_DEBUGF("malloc(%d) -> %p", bytes, r);
return r;
}
void *_serval_debug_calloc(unsigned int bytes, unsigned int count, struct __sourceloc __whence)
{
void *r=calloc((bytes*count)+SDM_GUARD_AFTER,1);
_DEBUGF("calloc(%d,%d) -> %p", bytes, count, r);
return r;
}
void _serval_debug_free(void *p, struct __sourceloc __whence)
{
_DEBUGF("free(%p)", p);
free(p);
}

11
mem.h
View File

@ -24,17 +24,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "lang.h"
#include "log.h"
// #define MALLOC_PARANOIA
#ifdef MALLOC_PARANOIA
#define malloc(X) _serval_debug_malloc(X,__WHENCE__)
#define calloc(X,Y) _serval_debug_calloc(X,Y,__WHENCE__)
#define free(X) _serval_debug_free(X,__WHENCE__)
void *_serval_debug_malloc(unsigned int bytes, struct __sourceloc whence) __attribute__ ((__ATTRIBUTE_malloc, __ATTRIBUTE_alloc_size(1)));
void *_serval_debug_calloc(unsigned int bytes, unsigned int count, struct __sourceloc whence) __attribute__ ((__ATTRIBUTE_malloc, __ATTRIBUTE_alloc_size(1)));
void _serval_debug_free(void *p, struct __sourceloc whence);
#endif
/* Equivalent to malloc(3), but logs an error before returning NULL.
*
* @author Andrew Bettison <andrew@servalproject.com>

View File

@ -386,6 +386,114 @@ static int restful_meshmb_newsince_find(httpd_request *r, const char *remainder)
}
*/
// allow multiple requests to re-use the same struct meshmb_feeds *, keeping it up to date as bundles arrive
struct meshmb_session{
struct meshmb_session *next;
struct meshmb_session *prev;
unsigned ref_count;
keyring_identity *id;
struct meshmb_feeds *feeds;
};
static struct meshmb_session *sessions = NULL;
static struct meshmb_session *open_session(const identity_t *identity){
keyring_identity *id = keyring_find_identity(keyring, identity);
if (!id)
return NULL;
struct meshmb_session *session = sessions;
while(session){
if (session->id == id){
session->ref_count++;
return session;
}
session = session->next;
}
struct meshmb_feeds *feeds = NULL;
if (meshmb_open(id, &feeds)==-1)
return NULL;
session = emalloc(sizeof (struct meshmb_session));
if (!session){
meshmb_close(feeds);
return NULL;
}
session->next = sessions;
session->prev = NULL;
if (sessions)
sessions->prev = session;
sessions = session;
session->ref_count = 1;
session->id = id;
session->feeds = feeds;
return session;
}
static void close_session(struct meshmb_session *session){
if (--session->ref_count == 0){
if (session->next)
session->next->prev = session->prev;
if (session->prev)
session->prev->next = session->next;
else
sessions = session->next;
meshmb_close(session->feeds);
free(session);
}
}
static int restful_meshmb_follow(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_follow(session->feeds, &r->u.meshmb_feeds.bundle_id)!=-1
&& meshmb_flush(session->feeds)!=-1){
http_request_simple_response(&r->http, 201, "TODO, detailed response");
ret = 201;
}else{
http_request_simple_response(&r->http, 500, "TODO, detailed response");
ret = 500;
}
if (session)
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){
http_request_simple_response(&r->http, 201, "TODO, detailed response");
ret = 201;
}else{
http_request_simple_response(&r->http, 500, "TODO, detailed response");
ret = 500;
}
if (session)
close_session(session);
return ret;
}
DECLARE_HANDLER("/restful/meshmb/", restful_meshmb_);
static int restful_meshmb_(httpd_request *r, const char *remainder)
{
@ -415,6 +523,16 @@ static int restful_meshmb_(httpd_request *r, const char *remainder)
&& strcmp(end, "messagelist.json") == 0) {
handler = restful_meshmb_newsince_list;
remainder = "";
} else if(str_startswith(remainder, "/follow/", &end)
&& strn_to_identity_t(&r->u.meshmb_feeds.bundle_id, end, &end) != -1) {
handler = restful_meshmb_follow;
verb = HTTP_VERB_POST;
remainder = "";
} else if(str_startswith(remainder, "/ignore/", &end)
&& strn_to_identity_t(&r->u.meshmb_feeds.bundle_id, end, &end) != -1) {
handler = restful_meshmb_ignore;
verb = HTTP_VERB_POST;
remainder = "";
}
/*
} else if(strcmp(remainder, "/find.json") == 0) {

View File

@ -84,18 +84,17 @@ setup_meshmbFollow() {
}
test_meshmbFollow() {
executeOk_servald meshmb follow $IDA1 $IDA2
tfw_cat --stderr
executeOk_servald meshmb list following $IDA1
tfw_cat --stdout --stderr
assertStdoutGrep --matches=1 ":$IDA2:Feed B:[0-9]\+:Message 2\$"
assertStdoutGrep --matches=0 ":$IDA3:Feed C:[0-9]\+:Message 3\$"
executeOk_servald meshmb follow $IDA1 $IDA3
tfw_cat --stderr
executeOk_servald meshmb list following $IDA1
tfw_cat --stdout --stderr
assertStdoutGrep --matches=1 ":$IDA2:Feed B:[0-9]\+:Message 2\$"
assertStdoutGrep --matches=1 ":$IDA3:Feed C:[0-9]\+:Message 3\$"
executeOk_servald meshmb ignore $IDA1 $IDA2
tfw_cat --stderr
executeOk_servald meshmb list following $IDA1
tfw_cat --stdout --stderr
#TODO list....
assertStdoutGrep --matches=0 ":$IDA2:Feed B:[0-9]\+:Message 2\$"
assertStdoutGrep --matches=1 ":$IDA3:Feed C:[0-9]\+:Message 3\$"
}
runTests "$@"

View File

@ -95,5 +95,47 @@ test_MeshMBRestList() {
}
])"
}
doc_MeshMBRestFollow="Restful follow another feed"
setup_MeshMBRestFollow() {
IDENTITY_COUNT=3
setup
executeOk_servald meshmb send $IDA1 "Message 1"
executeOk_servald meshmb send $IDA2 "Message 2"
executeOk_servald meshmb send $IDA3 "Message 3"
}
test_MeshMBRestFollow() {
executeOk curl \
-H "Expect:" \
--silent --fail --show-error \
--output follow.json \
--basic --user harry:potter \
--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\$"
executeOk curl \
-H "Expect:" \
--silent --fail --show-error \
--output follow.json \
--basic --user harry:potter \
--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\$"
executeOk curl \
-H "Expect:" \
--silent --fail --show-error \
--output follow.json \
--basic --user harry:potter \
--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\$"
}
runTests "$@"