diff --git a/httpd.h b/httpd.h index da4238f7..4b3f5952 100644 --- a/httpd.h +++ b/httpd.h @@ -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; diff --git a/java-api/src/org/servalproject/servaldna/ServalDClient.java b/java-api/src/org/servalproject/servaldna/ServalDClient.java index 2fe757f9..7609723e 100644 --- a/java-api/src/org/servalproject/servaldna/ServalDClient.java +++ b/java-api/src/org/servalproject/servaldna/ServalDClient.java @@ -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 { diff --git a/java-api/src/org/servalproject/servaldna/meshmb/MeshMBCommon.java b/java-api/src/org/servalproject/servaldna/meshmb/MeshMBCommon.java index 13e1d561..5d55300c 100644 --- a/java-api/src/org/servalproject/servaldna/meshmb/MeshMBCommon.java +++ b/java-api/src/org/servalproject/servaldna/meshmb/MeshMBCommon.java @@ -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(); + } } diff --git a/mem.c b/mem.c index 57a8004d..cc59dbf3 100644 --- a/mem.c +++ b/mem.c @@ -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); -} diff --git a/mem.h b/mem.h index f98f7b7b..1d178fda 100644 --- a/mem.h +++ b/mem.h @@ -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 diff --git a/meshmb_restful.c b/meshmb_restful.c index 2192207e..a46652c3 100644 --- a/meshmb_restful.c +++ b/meshmb_restful.c @@ -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) { diff --git a/tests/meshmb b/tests/meshmb index e1cd6d60..4b7b00e4 100755 --- a/tests/meshmb +++ b/tests/meshmb @@ -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 "$@" diff --git a/tests/meshmbrestful b/tests/meshmbrestful index fc1d7772..03dc7d0e 100755 --- a/tests/meshmbrestful +++ b/tests/meshmbrestful @@ -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 "$@"