Issue #9, 'rhizomeprotocol' HttpImport test now passes

Any HTTP client can import a bundle into Rhizome using a PUSH request.
This commit is contained in:
Andrew Bettison 2012-10-02 17:15:14 +09:30
parent cc9cb8d827
commit 5fed0460e1
5 changed files with 57 additions and 68 deletions

View File

@ -41,60 +41,63 @@ int rhizome_enabled()
return rhizome_enabled_flag; return rhizome_enabled_flag;
} }
/* Import a bundle from the inbox folder. The bundle is contained a pair of files, one containing /* Import a bundle from a pair of files, one containing the manifest and the optional other
the manifest and the optional other containing the payload. containing the payload. The logic is all in rhizome_bundle_import(). This function just wraps
that function and manages file and object buffers and lifetimes.
The logic is all in rhizome_add_manifest(). This function just wraps that function and manages
file and object buffers and lifetimes.
*/ */
int rhizome_bundle_import(rhizome_manifest *m_in, rhizome_manifest **m_out, int rhizome_bundle_import_files(const char *manifest_path, const char *payload_path, int ttl)
const char *manifest_path, int ttl)
{ {
if (debug & DEBUG_RHIZOME) if (debug & DEBUG_RHIZOME)
DEBUGF("rhizome_bundle_import(m_in=%p, m_out=%p, manifest_path=%s, ttl=%d)", DEBUGF("(manifest_path=%s, payload_path=%s, ttl=%d)",
m_in, m_out,
manifest_path ? alloca_str_toprint(manifest_path) : "NULL", manifest_path ? alloca_str_toprint(manifest_path) : "NULL",
payload_path ? alloca_str_toprint(payload_path) : "NULL",
ttl ttl
); );
if (m_out)
*m_out = NULL;
/* Read manifest file if no manifest was given */ /* Read manifest file if no manifest was given */
rhizome_manifest *m = m_in; if (!manifest_path)
if (!m_in) { return WHY("No manifest supplied");
if (!manifest_path) int ret = 0;
return WHY("No manifest supplied"); rhizome_manifest *m = rhizome_new_manifest();
m = rhizome_new_manifest(); if (!m)
if (!m) ret = WHY("Out of manifests");
return WHY("Out of manifests"); else if (rhizome_read_manifest_file(m, manifest_path, 0 /* file not buffer */) == -1)
if (rhizome_read_manifest_file(m, manifest_path, 0 /* file not buffer */) == -1) { ret = WHY("Could not read manifest file");
rhizome_manifest_free(m); else if (rhizome_manifest_verify(m))
return WHY("Could not read manifest file"); ret = WHY("Verification of manifest file failed");
} else if (rhizome_manifest_verify(m)) { else {
rhizome_manifest_free(m); m->dataFileName = strdup(payload_path);
return WHY("Could not verify manifest file"); if (rhizome_manifest_check_file(m))
} ret = WHY("Payload does not belong to manifest");
else
ret = rhizome_bundle_import(m, ttl);
} }
if (m)
rhizome_manifest_free(m);
return ret;
}
/* Import a bundle from a finalised manifest struct. The dataFileName element must give the path
of a readable file containing the payload unless the payload is null (zero length). The logic is
all in rhizome_add_manifest(). This function just wraps that function and manages object buffers
and lifetimes.
*/
int rhizome_bundle_import(rhizome_manifest *m, int ttl)
{
if (debug & DEBUG_RHIZOME)
DEBUGF("(m=%p, ttl=%d)", m, ttl);
/* Add the manifest and its payload to the Rhizome database. */ /* Add the manifest and its payload to the Rhizome database. */
if (m->fileLength > 0 && !(m->dataFileName && m->dataFileName[0])) if (m->fileLength > 0 && !(m->dataFileName && m->dataFileName[0]))
return WHY("Missing data file name"); return WHY("Missing data file name");
if (rhizome_manifest_check_file(m)) if (rhizome_manifest_check_file(m))
return WHY("File does not belong to manifest"); return WHY("File does not belong to manifest");
int ret = rhizome_manifest_check_duplicate(m, NULL); int ret = rhizome_manifest_check_duplicate(m, NULL);
if (ret == 0) if (ret == 0) {
ret = rhizome_add_manifest(m, ttl); ret = rhizome_add_manifest(m, ttl);
if (ret == -1) { if (ret == -1)
WHY("rhizome_add_manifest() failed"); WHY("rhizome_add_manifest() failed");
} else {
if (manifest_path && rhizome_write_manifest_file(m, manifest_path))
ret = WHYF("Could not write %s", manifest_path);
} }
/* If the manifest structure was allocated in this function, and it is not being returned to the
caller, then this function is responsible for freeing it */
if (m_out)
*m_out = m;
else if (!m_in)
rhizome_manifest_free(m);
return ret; return ret;
} }

View File

@ -209,7 +209,8 @@ int rhizome_store_bundle(rhizome_manifest *m);
int rhizome_manifest_add_group(rhizome_manifest *m,char *groupid); int rhizome_manifest_add_group(rhizome_manifest *m,char *groupid);
int rhizome_clean_payload(const char *fileidhex); int rhizome_clean_payload(const char *fileidhex);
int rhizome_store_file(rhizome_manifest *m,const unsigned char *key); int rhizome_store_file(rhizome_manifest *m,const unsigned char *key);
int rhizome_bundle_import(rhizome_manifest *m_in, rhizome_manifest **m_out, const char *manifest_path, int ttl); int rhizome_bundle_import_files(const char *manifest_path, const char *payload_path, int ttl);
int rhizome_bundle_import(rhizome_manifest *m, int ttl);
int rhizome_manifest_verify(rhizome_manifest *m); int rhizome_manifest_verify(rhizome_manifest *m);
int rhizome_manifest_check_sanity(rhizome_manifest *m_in); int rhizome_manifest_check_sanity(rhizome_manifest *m_in);

View File

@ -45,23 +45,13 @@ int rhizome_direct_form_received(rhizome_http_request *r)
if (!strcmp(r->path,"/rhizome/import")) { if (!strcmp(r->path,"/rhizome/import")) {
switch(r->fields_seen) { switch(r->fields_seen) {
case RD_MIME_STATE_MANIFESTHEADERS | RD_MIME_STATE_DATAHEADERS: { case RD_MIME_STATE_MANIFESTHEADERS | RD_MIME_STATE_DATAHEADERS: {
/* A bundle to import */ /* Got a bundle to import */
strbuf cmd = strbuf_alloca(1024); strbuf manifest_path = strbuf_alloca(50);
strbuf_sprintf(cmd, strbuf payload_path = strbuf_alloca(50);
"servald rhizome import bundle rhizomedirect.%d.data rhizomedirect.%d.manifest", strbuf_sprintf(manifest_path, "rhizomedirect.%d.manifest", r->alarm.poll.fd);
r->alarm.poll.fd, r->alarm.poll.fd strbuf_sprintf(payload_path, "rhizomedirect.%d.data", r->alarm.poll.fd);
); int ret = rhizome_bundle_import_files(strbuf_str(manifest_path), strbuf_str(payload_path), 1); // ttl = 1
DEBUGF("system(\"%s\")", strbuf_str(cmd));
int status = system(strbuf_str(cmd));
/* clean up after ourselves */
rhizome_direct_clear_temporary_files(r); rhizome_direct_clear_temporary_files(r);
if (status == -1) {
WHYF_perror("system(\"%s\")", strbuf_str(cmd));
return rhizome_server_simple_http_response(r, 500, "Server error: Rhizome import command not executed.");
}
strbuf st = strbuf_alloca(100);
strbuf_append_exit_status(st, status);
DEBUGF("Import command %s", strbuf_str(st));
/* report back to caller. /* report back to caller.
200 = ok, which is probably appropriate for when we already had the bundle. 200 = ok, which is probably appropriate for when we already had the bundle.
201 = content created, which is probably appropriate for when we successfully 201 = content created, which is probably appropriate for when we successfully
@ -70,18 +60,13 @@ int rhizome_direct_form_received(rhizome_http_request *r)
the import fails due to malformed data etc. the import fails due to malformed data etc.
(should probably also indicate if we have a newer version if possible) (should probably also indicate if we have a newer version if possible)
*/ */
if (WIFEXITED(status)) { switch (ret) {
switch (WEXITSTATUS(status)) { case 0:
case 0: return rhizome_server_simple_http_response(r, 201, "Bundle succesfully imported.");
return rhizome_server_simple_http_response(r, 201, "Bundle succesfully imported."); case 2:
case 1: return rhizome_server_simple_http_response(r, 200, "Bundle already imported.");
return rhizome_server_simple_http_response(r, 200, "Bundle already imported.");
default:
return rhizome_server_simple_http_response(r, 500, "Server error: Rhizome import command failed.");
}
} }
WHY("should not reach here"); return rhizome_server_simple_http_response(r, 500, "Server error: Rhizome import command failed.");
return rhizome_server_simple_http_response(r, 500, "Server error: Internal bug.");
} }
break; break;
default: default:

View File

@ -388,7 +388,7 @@ void rhizome_import_received_bundle(struct rhizome_manifest *m)
DEBUGF("manifest len=%d has %d signatories", m->manifest_bytes, m->sig_count); DEBUGF("manifest len=%d has %d signatories", m->manifest_bytes, m->sig_count);
dump("manifest", m->manifestdata, m->manifest_all_bytes); dump("manifest", m->manifestdata, m->manifest_all_bytes);
} }
rhizome_bundle_import(m, NULL, NULL, m->ttl - 1 /* TTL */); rhizome_bundle_import(m, m->ttl - 1 /* TTL */);
} }
/* Verifies manifests as late as possible to avoid wasting time. */ /* Verifies manifests as late as possible to avoid wasting time. */
@ -707,7 +707,7 @@ int rhizome_queue_manifest_import(rhizome_manifest *m, struct sockaddr_in *peeri
} else { } else {
if (debug & DEBUG_RHIZOME_RX) if (debug & DEBUG_RHIZOME_RX)
DEBUGF("We already have the file for this manifest; importing from manifest alone."); DEBUGF("We already have the file for this manifest; importing from manifest alone.");
rhizome_bundle_import(m, NULL, NULL, m->ttl-1); rhizome_bundle_import(m, m->ttl-1);
} }
} }

View File

@ -317,7 +317,7 @@ test_HttpImport() {
"$addr_localhost:$PORTA/rhizome/import" "$addr_localhost:$PORTA/rhizome/import"
tfw_cat http.headers http.output tfw_cat http.headers http.output
executeOk_servald rhizome list '' executeOk_servald rhizome list ''
assert_rhizome_list README.WHYNOTSIPS assert_rhizome_list README.WHYNOTSIPS!
} }
doc_HttpAddLocal="Add file locally using HTTP, returns manifest" doc_HttpAddLocal="Add file locally using HTTP, returns manifest"