From abb2a393308bdfe62814bef19a185ee5423b8a6e Mon Sep 17 00:00:00 2001 From: Andrew Bettison Date: Mon, 29 Jun 2015 14:52:29 +0930 Subject: [PATCH] Fix MeshMS REST newsince race condition During GET /restful/meshms/SID1/SID2/newsince/messagelist.json, if a new message was received before the request reached the end of its message iterator and paused, then the new message did not make it into the output. --- httpd.h | 1 + meshms.c | 7 +++++++ meshms_restful.c | 12 ++++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/httpd.h b/httpd.h index 5a80aac1..a3c1b5d1 100644 --- a/httpd.h +++ b/httpd.h @@ -188,6 +188,7 @@ typedef struct httpd_request enum list_phase phase; size_t rowcount; struct meshms_message_iterator iter; + unsigned dirty; int finished; } msglist; diff --git a/meshms.c b/meshms.c index 6258d128..ec941644 100644 --- a/meshms.c +++ b/meshms.c @@ -785,6 +785,11 @@ void meshms_conversation_iterator_advance(struct meshms_conversation_iterator *i enum meshms_status meshms_message_iterator_open(struct meshms_message_iterator *iter, const sid_t *me, const sid_t *them) { + if (config.debug.meshms) + DEBUGF("iter=%p me=%s them=%s", iter, + me ? alloca_tohex_sid_t(*me) : "NULL", + them ? alloca_tohex_sid_t(*them) : "NULL" + ); enum meshms_status status; bzero(iter, sizeof *iter); if (meshms_failed(status = find_or_create_conv(me, them, &iter->_conv))) @@ -842,6 +847,8 @@ int meshms_message_iterator_is_open(const struct meshms_message_iterator *iter) void meshms_message_iterator_close(struct meshms_message_iterator *iter) { + if (config.debug.meshms) + DEBUGF("iter=%p", iter); if (iter->_my_manifest) { ply_read_close(&iter->_my_reader); rhizome_manifest_free(iter->_my_manifest); diff --git a/meshms_restful.c b/meshms_restful.c index a3298bb6..d559816d 100644 --- a/meshms_restful.c +++ b/meshms_restful.c @@ -290,6 +290,10 @@ static HTTP_CONTENT_GENERATOR restful_meshms_messagelist_json_content; static enum meshms_status reopen_meshms_message_iterator(httpd_request *r) { + if (r->u.msglist.dirty) { + meshms_message_iterator_close(&r->u.msglist.iter); + r->u.msglist.dirty = 0; + } if (!meshms_message_iterator_is_open(&r->u.msglist.iter)) { enum meshms_status status; if ( meshms_failed(status = meshms_message_iterator_open(&r->u.msglist.iter, &r->sid1, &r->sid2)) @@ -352,9 +356,13 @@ static int restful_meshms_newsince_messagelist_json(httpd_request *r, const char static void on_rhizome_bundle_added(httpd_request *r, rhizome_manifest *m) { - // TODO select on sender and/or recipient fields if (strcmp(m->service, RHIZOME_SERVICE_MESHMS2) == 0) { - http_request_resume_response(&r->http); + if ( (cmp_sid_t(&m->sender, &r->sid1) == 0 && cmp_sid_t(&m->recipient, &r->sid2) == 0) + || (cmp_sid_t(&m->sender, &r->sid2) == 0 && cmp_sid_t(&m->recipient, &r->sid1) == 0) + ) { + r->u.msglist.dirty = 1; + http_request_resume_response(&r->http); + } } }