diff --git a/src/client/libdistren.c b/src/client/libdistren.c --- a/src/client/libdistren.c +++ b/src/client/libdistren.c @@ -29,6 +29,8 @@ #include "libdistren.h" +#include +#include #include #include #include @@ -109,12 +111,100 @@ static void distren_init_cleanup(distren distren_free(distren); } -/** - * @todo Stub - */ +#ifdef _WIN32 +#define FOPEN_BINARY "b" +#else +#define FOPEN_BINARY "" +#endif int distren_submit_file(distren_t handle, distren_job_t *job, const char *filename) { - return 1; + FILE *in; + char buf[DISTREN_REQUEST_FILE_POST_DATA_LEN]; + size_t len; + void *data; + + struct distren_request *req; + struct distren_request_file_post data_header; + distren_request_file_post_context_t post_context; + + /* for basename() to play with */ + char *my_filename; + + errno = 0; + in = fopen(filename, "r" FOPEN_BINARY); + if(!in) + { + perror("fopen"); + return 1; + } + + fprintf(stderr, "info: Starting upload of %s...\n", filename); + + /* prepare the server for a file upload */ + my_filename = strdup(filename); + distren_request_file_post_start(&req, + &data, + &post_context, + handle->file_post_id, + basename(my_filename)); + free(my_filename); + distren_request_send(handle->rem, req, data); + distren_request_free_with_data(req, data); + handle->file_post_id ++; + + /* send file body */ + while(in + && !ferror(in) + && !feof(in) + && handle->rem) + { + len = fread(buf, 1, DISTREN_REQUEST_FILE_POST_DATA_LEN, in); + if(len == 0) + continue; + distren_request_file_post(&req, + &data_header, + post_context, + buf, + len); + remoteio_write(handle->rem, req, sizeof(struct distren_request)); + /* should we check of handle->rem is NULL or not here...? */ + remoteio_write(handle->rem, &data_header, sizeof(struct distren_request_file_post)); + remoteio_write(handle->rem, buf, len); + distren_request_free(req); + + /* ensure we have no more than a megabyte waiting to be sent. */ + while(handle->rem + && remoteio_sendq_len(handle->rem) / 3 > (1024 * 1024 / DISTREN_REQUEST_FILE_POST_DATA_LEN)) + { + fprintf(stderr, "info: %d packets waiting to be sent...\n", remoteio_sendq_len(handle->rem) / 3); + multiio_poll(handle->multiio, -1); + } + } + + /* + * declare the upload as finished, marking it as cancelled on I/O + * error. + */ + distren_request_file_post_finish(&req, &data, post_context, (!in || ferror(in)) ? 1 : 0); + if(handle->rem) + distren_request_send(handle->rem, req, data); + distren_request_free_with_data(req, data); + + if(in) + fclose(in); + if(!handle->rem) + return 1; + + /* let's block until the file's gone. */ + while(handle->rem + && remoteio_sendq_len(handle->rem)) + { + fprintf(stderr, "info: %d packets waiting to be sent...\n", remoteio_sendq_len(handle->rem) / 3); + multiio_poll(handle->multiio, -1); + } + fprintf(stderr, "info: %s successfully uploaded, as far as we know.\n", filename); + + return 0; } int distren_free(distren_t handle)