diff --git a/rhizome.h b/rhizome.h index 94318c96..55ded6ac 100644 --- a/rhizome.h +++ b/rhizome.h @@ -378,6 +378,13 @@ typedef struct rhizome_http_request { } rhizome_http_request; +struct http_response { + unsigned int result_code; + const char * content_type; + unsigned long long content_length; + const char * body; +}; + int rhizome_server_free_http_request(rhizome_http_request *r); int rhizome_server_http_send_bytes(rhizome_http_request *r); int rhizome_server_parse_http_request(rhizome_http_request *r); @@ -474,6 +481,8 @@ rhizome_direct_sync_request void *transport_specific_state); int rhizome_direct_continue_sync_request(rhizome_direct_sync_request *r); int rhizome_direct_conclude_sync_request(rhizome_direct_sync_request *r); +rhizome_direct_bundle_cursor *rhizome_direct_get_fill_response +(unsigned char *buffer,int size); typedef struct rhizome_direct_transport_state_http { int port; diff --git a/rhizome_direct.c b/rhizome_direct.c index bdc3796a..a053784f 100644 --- a/rhizome_direct.c +++ b/rhizome_direct.c @@ -255,6 +255,27 @@ int rhizome_direct_conclude_sync_request(rhizome_direct_sync_request *r) return 0; } +rhizome_direct_bundle_cursor *rhizome_direct_get_fill_response +(unsigned char *buffer,int size) +{ + if (size<10) return NULL; + + rhizome_direct_bundle_cursor *c=calloc(sizeof(rhizome_direct_bundle_cursor),1); + if (rhizome_direct_bundle_iterator_unpickle_range(c,buffer,10)) + { + DEBUGF("Couldn't unpickle range"); + rhizome_direct_bundle_iterator_free(&c); + return NULL; + } + DEBUGF("unpickled size_high=%lld, limit_size_high=%lld", + c->size_high,c->limit_size_high); + + rhizome_direct_bundle_iterator_free(&c); + return NULL; + +} + + int app_rhizome_direct_sync(int argc, const char *const *argv, struct command_line_option *o) { diff --git a/rhizome_direct_http.c b/rhizome_direct_http.c index d7e21032..b8ea23b5 100644 --- a/rhizome_direct_http.c +++ b/rhizome_direct_http.c @@ -44,43 +44,130 @@ int rhizome_direct_form_received(rhizome_http_request *r) */ /* XXX process completed form based on the set of fields seen */ - switch(r->fields_seen) { - case RD_MIME_STATE_MANIFESTHEADERS - |RD_MIME_STATE_DATAHEADERS: - /* A bundle to import */ - DEBUGF("Call bundle import for rhizomedata.%d.{data,file}", - r->alarm.poll.fd); - char cmd[1024]; - snprintf(cmd,1024, - "servald rhizome import bundle rhizomedirect.%d.data rhizomedirect.%d.manifest", - r->alarm.poll.fd,r->alarm.poll.fd); - cmd[1023]=0; - int rv=system(cmd); - int status=-1; + if (!strcmp(r->path,"/rhizome/import")) + { + switch(r->fields_seen) { + case RD_MIME_STATE_MANIFESTHEADERS + |RD_MIME_STATE_DATAHEADERS: + /* A bundle to import */ + DEBUGF("Call bundle import for rhizomedata.%d.{data,file}", + r->alarm.poll.fd); + char cmd[1024]; + snprintf(cmd,1024, + "servald rhizome import bundle rhizomedirect.%d.data rhizomedirect.%d.manifest", + r->alarm.poll.fd,r->alarm.poll.fd); + cmd[1023]=0; + int rv=system(cmd); + int status=-1; + + if (rv!=-1) status=WEXITSTATUS(rv); + + DEBUGF("Import returned %d",status); + + /* clean up after ourselves */ + rhizome_direct_clear_temporary_files(r); + /* and report back to caller. + 200 = ok, which is probably appropriate for when we already had the bundle. + 201 = content created, which is probably appropriate for when we successfully + import a bundle (or if we already have it). + 403 = forbidden, which might be appropriate if we refuse to accept it, e.g., + the import fails due to malformed data etc. + (should probably also indicate if we have a newer version if possible) + + For now we are just returning "no content" as a place-holder while debugging. + */ + rhizome_server_simple_http_response(r, 204, "Move along. Nothing to see."); + break; + default: + /* Clean up after ourselves */ + rhizome_direct_clear_temporary_files(r); + } + } else if (!strcmp(r->path,"/rhizome/enquiry")) { + int fd=-1; + char file[1024]; + switch(r->fields_seen) { + case RD_MIME_STATE_DATAHEADERS: + /* Read data buffer in, pass to rhizome direct for comparison with local + rhizome database, and send back responses. */ + snprintf(file,1024,"rhizomedirect.%d.%s",r->alarm.poll.fd,"data"); + fd=open(file,O_RDONLY); + if (fd == -1) { + /* Clean up after ourselves */ + rhizome_direct_clear_temporary_files(r); + return rhizome_server_simple_http_response(r,500,"Couldn't read a file"); + } + struct stat stat; + if (fstat(fd,&stat)) { + /* Clean up after ourselves */ + close(fd); + rhizome_direct_clear_temporary_files(r); + return rhizome_server_simple_http_response(r,500,"Couldn't stat a file"); + } + unsigned char *addr = mmap(NULL, stat.st_size, PROT_READ, + MAP_FILE|MAP_SHARED, fd, 0); + if (addr==MAP_FAILED) { + /* Clean up after ourselves */ + close(fd); + rhizome_direct_clear_temporary_files(r); + return rhizome_server_simple_http_response(r,500,"Couldn't mmap() a file"); + } + rhizome_direct_bundle_cursor *c=rhizome_direct_get_fill_response(addr,stat.st_size); + munmap(addr,stat.st_size); + close(fd); - if (rv!=-1) status=WEXITSTATUS(rv); + if (c) + { + /* TODO: Write out_buffer as the body of the response. + We should be able to do this using the async framework fairly easily. + */ + + int bytes=c->buffer_offset_bytes+c->buffer_used; + r->buffer=malloc(bytes+1024); + r->buffer_size=bytes+1024; + r->buffer_offset=0; + assert(r->buffer); - DEBUGF("Import returned %d",status); + /* Write HTTP response header */ + struct http_response hr; + hr.result_code=200; + hr.content_type="binary/octet-stream"; + hr.content_length=bytes; + r->request_type=0; + rhizome_server_set_response(r,&hr); + assert(r->buffer_offset<1024); - /* clean up after ourselves */ - rhizome_direct_clear_temporary_files(r); - /* and report back to caller. - 201 = content created, which is probably appropriate for when we successfully - import a bundle (or if we already have it). - 403 = forbidden, which might be appropriate if we refuse to accept it, e.g., - the import fails due to malformed data etc. + /* Now append body and send it back. */ + bcopy(c->buffer,&r->buffer[r->buffer_offset],bytes); + r->buffer_length+=bytes; + r->buffer_offset=0; + + /* Clean up cursor after sending response */ + rhizome_direct_bundle_iterator_free(&c); + /* Clean up after ourselves */ + rhizome_direct_clear_temporary_files(r); + + return 0; + } + else + { + return rhizome_server_simple_http_response(r,500,"Could not get response to enquiry"); + } + + /* Clean up after ourselves */ + rhizome_direct_clear_temporary_files(r); + break; + default: + /* Clean up after ourselves */ + rhizome_direct_clear_temporary_files(r); + + return rhizome_server_simple_http_response(r, 404, "/rhizome/enquiry requires 'data' field"); + } - For now we are just returning "no content" as a place-holder while debugging. - */ - rhizome_server_simple_http_response(r, 204, "Move along. Nothing to see."); - break; - default: - /* Clean up after ourselves */ - rhizome_direct_clear_temporary_files(r); - - } + /* Clean up after ourselves */ + rhizome_direct_clear_temporary_files(r); + /* Report error */ return rhizome_server_simple_http_response(r, 500, "Something went wrong. Probably a missing data or manifest part, or invalid combination of URI and data/manifest provision."); } diff --git a/rhizome_http.c b/rhizome_http.c index b3bed7ed..17280ae1 100644 --- a/rhizome_http.c +++ b/rhizome_http.c @@ -570,13 +570,6 @@ static const char *httpResultString(int response_code) { } } -struct http_response { - unsigned int result_code; - const char * content_type; - unsigned long long content_length; - const char * body; -}; - static strbuf strbuf_build_http_response(strbuf sb, const struct http_response *h) { strbuf_sprintf(sb, "HTTP/1.0 %03u %s\r\n", h->result_code, httpResultString(h->result_code)); @@ -588,7 +581,7 @@ static strbuf strbuf_build_http_response(strbuf sb, const struct http_response * return sb; } -static int rhizome_server_set_response(rhizome_http_request *r, const struct http_response *h) +int rhizome_server_set_response(rhizome_http_request *r, const struct http_response *h) { strbuf b = strbuf_local((char *) r->buffer, r->buffer_size); strbuf_build_http_response(b, h);