From: Christian Grothoff Date: Tue, 25 Aug 2009 10:59:00 +0000 (+0000) Subject: hxing X-Git-Tag: initial-import-from-subversion-38251~23591 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=9cbff87bf9b68c08242b1a6a79221311dc157fc0;p=oweals%2Fgnunet.git hxing --- diff --git a/BUGS b/BUGS index a6339547e..6271eb2f1 100644 --- a/BUGS +++ b/BUGS @@ -6,6 +6,7 @@ sane end-user should care about this codebase yet anyway. * UTIL: - crypto_hash: use libgcrypt (supports SHA-512 since 2003) - container_bloomfilter: improve efficiency (see FIXME) + - no tests for BIO - Windows: use events instead of pipes to signal select()s [Nils] - only connect() sockets that are ready (select()) [Nils] [On W32, we need to select after calling socket before diff --git a/TODO b/TODO index 94fc5d4e5..889bdcea5 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,6 @@ Implementable right now (but not necessarily important), with caveats (unavailable components that will limit what can be implemented right away), in order in which they will likely be done: -* Buffered IO library (extend gnunet_disk_lib.h?) * TESTING * FS (DHT not available) * SETUP @@ -42,16 +41,16 @@ PHASE #2: (Goal: recover basic file-sharing functionality) - implement FS library + URI API -- DONE (but do more testing) + getopt API -- DONE (but do more testing) - + persistence mechanism + + persistence mechanism (design done) + sharing API - ~ file-information + ~ file-information (almost done, needs testing) ~ insert - ~ download ~ search - ~ unindex + ~ download + ~ unindex & list indexed!!! ~ namespaces ~ collection - + directory API + + directory API (builder API unclear) - design network structs (P2P) - datastore request queueing mechanism - implement FS service (needs DHT) diff --git a/src/fs/fs.c b/src/fs/fs.c index 0522b7941..157f4ef22 100644 --- a/src/fs/fs.c +++ b/src/fs/fs.c @@ -29,7 +29,6 @@ #include "fs.h" - /** * Setup a connection to the file-sharing service. * @@ -46,7 +45,35 @@ GNUNET_FS_start (struct GNUNET_SCHEDULER_Handle *sched, GNUNET_FS_ProgressCallback upcb, void *upcb_cls) { - return NULL; + struct GNUNET_FS_Handle *ret; + struct GNUNET_CLIENT_Connection *client; + + client = GNUNET_CLIENT_connect (sched, + "fs", + cfg); + if (NULL == client) + return NULL; + ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Handle)); + ret->sched = sched; + ret->cfg = cfg; + ret->client_name = GNUNET_strdup (client_name); + ret->upcb = upcb; + ret->upcb_cls = upcb_cls; + ret->client = client; + // FIXME: setup receive-loop with client + // FIXME: deserialize state; use client-name to find master-directory! + // Deserialize-Upload: + // * read FNs for upload FIs, deserialize each + // Deserialize Search: + // * read search queries + // * for each query, read file with search results + // * for each search result with active download, deserialize download + // * for each directory search result, check for active downloads of contents + // Deserialize Download: + // * always part of search??? + // Deserialize Unindex: + // * read FNs for unindex with progress offset + return ret; } @@ -60,6 +87,12 @@ GNUNET_FS_start (struct GNUNET_SCHEDULER_Handle *sched, void GNUNET_FS_stop (struct GNUNET_FS_Handle *h) { + // FIXME: serialize state!? (or is it always serialized???) + // FIXME: terminate receive-loop with client + GNUNET_CLIENT_disconnect (h->client); + GNUNET_free (h->client_name); + GNUNET_free (h); } + /* end of fs.c */ diff --git a/src/fs/fs.h b/src/fs/fs.h index 0c82d5831..1a8a6b0f7 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h @@ -279,4 +279,43 @@ struct GNUNET_FS_FileInformation }; +/** + * Master context for most FS operations. + */ +struct GNUNET_FS_Handle +{ + /** + * Scheduler. + */ + struct GNUNET_SCHEDULER_Handle *sched; + + /** + * Configuration to use. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Name of our client. + */ + char *client_name; + + /** + * Function to call with updates on our progress. + */ + GNUNET_FS_ProgressCallback upcb; + + /** + * Closure for upcb. + */ + void *upcb_cls; + + /** + * Connection to the FS service. + */ + struct GNUNET_CLIENT_Connection *client; + + +}; + + #endif diff --git a/src/fs/fs_file_information.c b/src/fs/fs_file_information.c index 9b806184b..540b518dc 100644 --- a/src/fs/fs_file_information.c +++ b/src/fs/fs_file_information.c @@ -24,7 +24,6 @@ * @author Christian Grothoff * * TODO: - * - publishing progress update API (increment offset, serialize) * - serialization/deserialization (& deserialization API) * - metadata filename clean up code * - metadata/ksk generation for directories from contained files @@ -36,15 +35,15 @@ /** - * Create a temporary file disk to store the current + * Create a temporary file on disk to store the current * state of "fi" in. */ -static void -fi_sync (struct GNUNET_FS_FileInformation * fi) +void +GNUNET_FS_file_information_sync (struct GNUNET_FS_FileInformation * fi) { if (NULL == fi->serialization) { - fi->serialization = NULL; // FIXME + fi->serialization = NULL; // FIXME -- need cfg! } // FIXME... } @@ -57,8 +56,8 @@ fi_sync (struct GNUNET_FS_FileInformation * fi) * @param filename name of the file to use * @return NULL on error */ -static struct GNUNET_FS_FileInformation * -fi_load (const char *filename) +struct GNUNET_FS_FileInformation * +GNUNET_FS_file_information_recover (const char *name) { struct GNUNET_FS_FileInformation *ret; // FIXME! @@ -66,6 +65,25 @@ fi_load (const char *filename) } +/** + * Obtain the name under which this file information + * structure is stored on disk. Only works for top-level + * file information structures. + * + * @param s structure to get the filename for + * @return NULL on error, otherwise filename that + * can be passed to "GNUNET_FS_file_information_recover" + * to read this fi-struct from disk. + */ +const char * +GNUNET_FS_file_information_get_id (struct GNUNET_FS_FileInformation *s) +{ + if (NULL != s->dir) + return NULL; + return s->serialization; +} + + /** * Closure for "data_reader_file". */ @@ -320,7 +338,7 @@ GNUNET_FS_file_information_create_from_reader (void *client_info, ret->data.file.do_index = do_index; ret->anonymity = anonymity; ret->priority = priority; - fi_sync (ret); + GNUNET_FS_file_information_sync (ret); return ret; } @@ -609,10 +627,10 @@ GNUNET_FS_file_information_create_from_directory (void *client_info, while (dc.entries != NULL) { dc.entries->dir = ret; - fi_sync (dc.entries); + GNUNET_FS_file_information_sync (dc.entries); dc.entries = dc.entries->next; } - fi_sync (ret); + GNUNET_FS_file_information_sync (ret); return ret; } @@ -651,7 +669,7 @@ GNUNET_FS_file_information_create_empty_directory (void *client_info, ret->is_directory = GNUNET_YES; ret->anonymity = anonymity; ret->priority = priority; - fi_sync (ret); + GNUNET_FS_file_information_sync (ret); return ret; } @@ -683,8 +701,8 @@ GNUNET_FS_file_information_add (struct GNUNET_FS_FileInformation *dir, dir->data.dir.entries = ent; dir->data.dir.dir_size = 0; dir->publish_offset = 0; - fi_sync (ent); - fi_sync (dir); + GNUNET_FS_file_information_sync (ent); + GNUNET_FS_file_information_sync (dir); return GNUNET_OK; } diff --git a/src/include/gnunet_bio_lib.h b/src/include/gnunet_bio_lib.h index 02b04570e..2765b4695 100644 --- a/src/include/gnunet_bio_lib.h +++ b/src/include/gnunet_bio_lib.h @@ -71,12 +71,12 @@ int GNUNET_BIO_read_close (struct GNUNET_BIO_ReadHandle *h, * @param what describes what is being read (for error message creation) * @param result the buffer to write the result to * @param len the number of bytes to read - * @return len on success, GNUNET_SYSERR on failure + * @return GNUNET_OK on success, GNUNET_SYSERR on failure */ -ssize_t GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h, - const char *what, - void *result, - size_t len); +int GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h, + const char *what, + void *result, + size_t len); /** * Read 0-terminated string from a file. @@ -85,11 +85,13 @@ ssize_t GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h, * @param what describes what is being read (for error message creation) * @param result the buffer to store a pointer to the (allocated) string to * (note that *result could be set to NULL as well) + * @param maxLen maximum allowed length for the string * @return GNUNET_OK on success, GNUNET_SYSERR on failure */ int GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h, const char *what, - char **result); + char **result, + size_t maxLen); /** @@ -198,9 +200,9 @@ int GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h); * @param n number of bytes to write * @return GNUNET_OK on success, GNUNET_SYSERR on error */ -ssize_t GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h, - const void *buffer, - size_t n); +int GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h, + const void *buffer, + size_t n); /** @@ -244,7 +246,7 @@ int GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h, * @param h hande to open file * @param f double to write (must be a variable) */ -#define GNUNET_BIO_write_float(h, f) (sizeof(double) == GNUNET_BIO_write (h, &f, sizeof(double))) +#define GNUNET_BIO_write_double(h, f) (sizeof(double) == GNUNET_BIO_write (h, &f, sizeof(double))) /** @@ -254,7 +256,7 @@ int GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h, * @param i address of 32-bit integer to write * @return GNUNET_OK on success, GNUNET_SYSERR on error */ -int GNUNET_BIO_write_int32 (struct GNUNET_BIO_ReadHandle *h, +int GNUNET_BIO_write_int32 (struct GNUNET_BIO_WriteHandle *h, int32_t i); @@ -265,7 +267,7 @@ int GNUNET_BIO_write_int32 (struct GNUNET_BIO_ReadHandle *h, * @param i address of 64-bit integer to write * @return GNUNET_OK on success, GNUNET_SYSERR on error */ -int GNUNET_BIO_write_int64 (struct GNUNET_BIO_ReadHandle *h, +int GNUNET_BIO_write_int64 (struct GNUNET_BIO_WriteHandle *h, int64_t i); diff --git a/src/include/gnunet_fs_service.h b/src/include/gnunet_fs_service.h index 45cd1e77e..7c6fc0549 100644 --- a/src/include/gnunet_fs_service.h +++ b/src/include/gnunet_fs_service.h @@ -1414,6 +1414,42 @@ typedef int (*GNUNET_FS_FileInformationProcessor)(void *cls, void **client_info); +/** + * Recover file information structure from disk. + * + * @param name filename for the structure on disk + * @return NULL on error + */ +struct GNUNET_FS_FileInformation * +GNUNET_FS_file_information_recover (const char *name); + + +/** + * Obtain the name under which this file information + * structure is stored on disk. Only works for top-level + * file information structures. + * + * @param s structure to get the filename for + * @return NULL on error, otherwise filename that + * can be passed to "GNUNET_FS_file_information_recover" + * to read this fi-struct from disk. + */ +const char * +GNUNET_FS_file_information_get_id (struct GNUNET_FS_FileInformation *s); + + +/** + * Synchronize this file-information struct with its mirror + * on disk. Note that all internal FS-operations that change + * file information data should already call "sync" internally, + * so this function is likely not useful for clients. + * + * @param s the struct to sync + */ +void +GNUNET_FS_file_information_sync (struct GNUNET_FS_FileInformation *s); + + /** * Create an entry for a file in a publish-structure. * diff --git a/src/util/bio.c b/src/util/bio.c index 060b6f94b..8c3daed15 100644 --- a/src/util/bio.c +++ b/src/util/bio.c @@ -17,8 +17,6 @@ Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - - /** * @file util/bio.c * @brief functions for buffering IO @@ -26,13 +24,23 @@ */ #include "platform.h" #include "gnunet_bio_lib.h" +#include "gnunet_disk_lib.h" + +#define BIO_BUFFER_SIZE 65536 +#define MAX_META_DATA (1024 * 1024) /** * Handle for buffered reading. */ struct GNUNET_BIO_ReadHandle { + struct GNUNET_DISK_FileHandle *fd; + char *emsg; + char *buffer; + size_t have; + size_t size; + off_t pos; }; @@ -42,9 +50,20 @@ struct GNUNET_BIO_ReadHandle * @param fn file name to be opened * @return IO handle on success, NULL on error */ -struct GNUNET_BIO_ReadHandle *GNUNET_BIO_read_open (const char *fn) +struct GNUNET_BIO_ReadHandle * +GNUNET_BIO_read_open (const char *fn) { - return NULL; + struct GNUNET_DISK_FileHandle *fd; + struct GNUNET_BIO_ReadHandle *h; + + fd = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READ); + if (NULL == fd) + return NULL; + h = GNUNET_malloc (sizeof(struct GNUNET_BIO_ReadHandle) + BIO_BUFFER_SIZE); + h->buffer = (char*) &h[1]; + h->size = BIO_BUFFER_SIZE; + h->fd = fd; + return h; } @@ -59,7 +78,10 @@ struct GNUNET_BIO_ReadHandle *GNUNET_BIO_read_open (const char *fn) int GNUNET_BIO_read_close (struct GNUNET_BIO_ReadHandle *h, char **emsg) { - return GNUNET_SYSERR; + *emsg = h->emsg; + GNUNET_DISK_file_close (h->fd); + GNUNET_free (h); + return (NULL == *emsg) ? GNUNET_OK : GNUNET_SYSERR; } @@ -70,13 +92,61 @@ int GNUNET_BIO_read_close (struct GNUNET_BIO_ReadHandle *h, * @param what describes what is being read (for error message creation) * @param result the buffer to write the result to * @param len the number of bytes to read - * @return len on success, GNUNET_SYSERR on failure + * @return GNUNET_OK on success, GNUNET_SYSERR on failure */ -ssize_t GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h, - const char *what, - void *result, - size_t len) +int GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h, + const char *what, + void *result, + size_t len) { + char *dst = result; + size_t min; + size_t pos; + ssize_t ret; + + if (h->emsg != NULL) + return GNUNET_SYSERR; + pos = 0; + do + { + /* first, use buffer */ + min = h->have - h->pos; + if (min > 0) + { + if (min > len - pos) + min = len - pos; + memcpy (&dst[pos], &h->buffer[h->pos], min); + h->pos += min; + pos += min; + } + if (pos == len) + return GNUNET_OK; /* done! */ + GNUNET_assert (h->have == h->pos); + /* fill buffer */ + ret = GNUNET_DISK_file_read (h->fd, + h->buffer, + h->size); + if (ret == -1) + { + GNUNET_asprintf (&h->emsg, + _("Error reading `%s': %s"), + what, + STRERROR (errno)); + return GNUNET_SYSERR; + } + if (ret == 0) + { + GNUNET_asprintf (&h->emsg, + _("Error reading `%s': %s"), + what, + _("End of file")); + return GNUNET_SYSERR; + } + h->pos = 0; + h->have = ret; + } + while (pos < len); /* should always be true */ + return GNUNET_OK; } @@ -87,12 +157,42 @@ ssize_t GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h, * @param what describes what is being read (for error message creation) * @param result the buffer to store a pointer to the (allocated) string to * (note that *result could be set to NULL as well) + * @param maxLen maximum allowed length for the string * @return GNUNET_OK on success, GNUNET_SYSERR on failure */ int GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h, const char *what, - char **result) + char **result, + size_t maxLen) { + char *buf; + uint32_t big; + + if (! GNUNET_BIO_read_int32 (h, &big)) + return GNUNET_SYSERR; + if (big == 0) + { + *result = NULL; + return GNUNET_OK; + } + if (big > maxLen) + { + GNUNET_asprintf (&h->emsg, + _("String `%s' longer than allowed (%u > %u)"), + what, + big, + maxLen); + return GNUNET_SYSERR; + } + buf = GNUNET_malloc (big); + buf[--big] = '\0'; + if (big != GNUNET_BIO_read (h, what, buf, big)) + { + GNUNET_free (buf); + return GNUNET_SYSERR; + } + *result = buf; + return GNUNET_OK; } @@ -108,6 +208,42 @@ int GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h, const char *what, struct GNUNET_CONTAINER_MetaData **result) { + uint32_t size; + char *buf; + struct GNUNET_CONTAINER_MetaData *meta; + + if (GNUNET_BIO_read_int32__ (h, + what, + (int32_t*) &size) != GNUNET_OK) + return GNUNET_SYSERR; + if (size > MAX_META_DATA) + { + GNUNET_asprintf (&h->emsg, + _("Serialized metadata `%s' larger than allowed (%u > %u)"), + what, + size, + MAX_META_DATA); + return GNUNET_SYSERR; + } + buf = GNUNET_malloc (size); + if (size != + GNUNET_BIO_read (h, what, buf, size)) + { + GNUNET_free (buf); + return GNUNET_SYSERR; + } + meta = GNUNET_CONTAINER_meta_data_deserialize (buf, size); + if (meta == NULL) + { + GNUNET_free (buf); + GNUNET_asprintf (&h->emsg, + _("Metadata `%s' failed to deserialize"), + what); + return GNUNET_SYSERR; + } + GNUNET_free (buf); + *result = meta; + return GNUNET_OK; } @@ -121,7 +257,19 @@ int GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h, */ int GNUNET_BIO_read_int32__ (struct GNUNET_BIO_ReadHandle *h, const char *what, - int32_t *i); + int32_t *i) +{ + int32_t big; + + if (sizeof (int32_t) != + GNUNET_BIO_read (h, + what, + &big, + sizeof (int32_t))) + return GNUNET_SYSERR; + *i = ntohl (big); + return GNUNET_OK; +} /** @@ -134,13 +282,30 @@ int GNUNET_BIO_read_int32__ (struct GNUNET_BIO_ReadHandle *h, */ int GNUNET_BIO_read_int64__ (struct GNUNET_BIO_ReadHandle *h, const char *what, - int64_t *i); + int64_t *i) +{ + int64_t big; + + if (sizeof (int64_t) != + GNUNET_BIO_read (h, + what, + &big, + sizeof (int64_t))) + return GNUNET_SYSERR; + *i = GNUNET_ntohll (big); + return GNUNET_OK; +} + /** * Handle for buffered writing. */ struct GNUNET_BIO_WriteHandle { + struct GNUNET_DISK_FileHandle *fd; + char *buffer; + size_t have; + size_t size; }; @@ -152,7 +317,19 @@ struct GNUNET_BIO_WriteHandle */ struct GNUNET_BIO_WriteHandle *GNUNET_BIO_write_open (const char *fn) { - return NULL; + struct GNUNET_DISK_FileHandle *fd; + struct GNUNET_BIO_WriteHandle *h; + + fd = GNUNET_DISK_file_open (fn, + GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_TRUNCATE | GNUNET_DISK_OPEN_CREATE, + GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); + if (NULL == fd) + return NULL; + h = GNUNET_malloc (sizeof(struct GNUNET_BIO_WriteHandle) + BIO_BUFFER_SIZE); + h->buffer = (char*) &h[1]; + h->size = BIO_BUFFER_SIZE; + h->fd = fd; + return h; } @@ -162,7 +339,22 @@ struct GNUNET_BIO_WriteHandle *GNUNET_BIO_write_open (const char *fn) * @param h file handle * @return GNUNET_OK on success, GNUNET_SYSERR otherwise */ -int GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h); +int GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h) +{ + int ret; + + if (NULL == h->fd) + { + ret = GNUNET_SYSERR; + } + else + { + GNUNET_DISK_file_close (h->fd); + ret = GNUNET_OK; + } + GNUNET_free (h); + return ret; +} /** @@ -173,9 +365,42 @@ int GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h); * @param n number of bytes to write * @return GNUNET_OK on success, GNUNET_SYSERR on error */ -ssize_t GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h, - const void *buffer, - size_t n); +int GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h, + const void *buffer, + size_t n) +{ + const char *src = buffer; + size_t min; + size_t pos; + ssize_t ret; + + if (NULL == h->fd) + return GNUNET_SYSERR; + pos = 0; + do + { + /* first, just use buffer */ + min = h->size - h->have; + if (min > n - pos) + min = n - pos; + memcpy (&h->buffer[h->have], &src[pos], min); + pos += min; + h->have += min; + if (pos == n) + return GNUNET_OK; /* done */ + GNUNET_assert (h->have == h->size); + ret = GNUNET_DISK_file_write (h->fd, h->buffer, h->size); + if (ret != h->size) + { + GNUNET_DISK_file_close (h->fd); + h->fd = NULL; + return GNUNET_SYSERR; /* error */ + } + h->have = 0; + } + while (pos < n); /* should always be true */ + return GNUNET_OK; +} /** @@ -186,9 +411,18 @@ ssize_t GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h, * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h, - const char *s); - + const char *s) +{ + uint32_t slen; + slen = (uint32_t) ((s == NULL) ? 0 : strlen(s) + 1); + if (GNUNET_OK != + GNUNET_BIO_write_int32 (h, slen)) + return GNUNET_SYSERR; + if (0 != slen) + return GNUNET_BIO_write (h, s, slen - 1); + return GNUNET_OK; +} /** @@ -199,27 +433,34 @@ int GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h, * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h, - const struct GNUNET_CONTAINER_MetaData *m); - - - -/** - * Write a float. - * - * @param h hande to open file - * @param f float to write (must be a variable) - */ -#define GNUNET_BIO_write_float(h, f) (sizeof(float) == GNUNET_BIO_write (h, &f, sizeof(float))) - - + const struct GNUNET_CONTAINER_MetaData *m) +{ + unsigned int size; + char *buf; -/** - * Write a double. - * - * @param h hande to open file - * @param f double to write (must be a variable) - */ -#define GNUNET_BIO_write_float(h, f) (sizeof(double) == GNUNET_BIO_write (h, &f, sizeof(double))) + size = GNUNET_CONTAINER_meta_data_get_serialized_size (m, + GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL + | + GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS); + if (size > MAX_META_DATA) + size = MAX_META_DATA; + buf = GNUNET_malloc (size); + GNUNET_CONTAINER_meta_data_serialize (m, + buf, + size, + GNUNET_CONTAINER_META_DATA_SERIALIZE_PART | + GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS); + if ( (GNUNET_OK != + GNUNET_BIO_write_int32 (h, size)) || + (GNUNET_OK != + GNUNET_BIO_write (h, buf, size)) ) + { + GNUNET_free (buf); + return GNUNET_SYSERR; + } + GNUNET_free (buf); + return GNUNET_OK; +} /** @@ -229,8 +470,13 @@ int GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h, * @param i address of 32-bit integer to write * @return GNUNET_OK on success, GNUNET_SYSERR on error */ -int GNUNET_BIO_write_int32 (struct GNUNET_BIO_ReadHandle *h, - int32_t i); +int GNUNET_BIO_write_int32 (struct GNUNET_BIO_WriteHandle *h, + int32_t i) +{ + int32_t big; + big = htonl (i); + return GNUNET_BIO_write (h, &big, sizeof (int32_t)); +} /** @@ -240,306 +486,13 @@ int GNUNET_BIO_write_int32 (struct GNUNET_BIO_ReadHandle *h, * @param i address of 64-bit integer to write * @return GNUNET_OK on success, GNUNET_SYSERR on error */ -int GNUNET_BIO_write_int64 (struct GNUNET_BIO_ReadHandle *h, - int64_t i); - - - - - -typedef struct +int GNUNET_BIO_write_int64 (struct GNUNET_BIO_WriteHandle *h, + int64_t i) { - int fd; - unsigned int have; - unsigned int size; - char *buffer; -} WriteBuffer; - -static void -write_buffered (WriteBuffer * wb, const void *s, unsigned int size) -{ - const char *src = s; - unsigned int min; - unsigned int pos; - int ret; - - if (wb->fd == -1) - return; - pos = 0; - do - { - /* first, just use buffer */ - min = wb->size - wb->have; - if (min > size - pos) - min = size - pos; - memcpy (&wb->buffer[wb->have], &src[pos], min); - pos += min; - wb->have += min; - if (pos == size) - return; /* done */ - GNUNET_GE_ASSERT (NULL, wb->have == wb->size); - ret = WRITE (wb->fd, wb->buffer, wb->size); - if (ret != wb->size) - { - CLOSE (wb->fd); - wb->fd = -1; - return; /* error */ - } - wb->have = 0; - } - while (pos < size); /* should always be true */ + int64_t big; + big = GNUNET_htonll (i); + return GNUNET_BIO_write (h, &big, sizeof (int64_t)); } -static void -WRITEINT (WriteBuffer * wb, int val) -{ - int big; - big = htonl (val); - write_buffered (wb, &big, sizeof (int)); -} - -static void -WRITELONG (WriteBuffer * wb, long long val) -{ - long long big; - big = GNUNET_htonll (val); - write_buffered (wb, &big, sizeof (long long)); -} - -static void -writeURI (WriteBuffer * wb, const struct GNUNET_ECRS_URI *uri) -{ - char *buf; - unsigned int size; - - buf = GNUNET_ECRS_uri_to_string (uri); - size = strlen (buf); - WRITEINT (wb, size); - write_buffered (wb, buf, size); - GNUNET_free (buf); -} - -static void -WRITESTRING (WriteBuffer * wb, const char *name) -{ - GNUNET_GE_BREAK (NULL, name != NULL); - WRITEINT (wb, strlen (name)); - write_buffered (wb, name, strlen (name)); -} - -static void -writeMetaData (struct GNUNET_GE_Context *ectx, - WriteBuffer * wb, const struct GNUNET_MetaData *meta) -{ - unsigned int size; - char *buf; - - size = GNUNET_meta_data_get_serialized_size (meta, - GNUNET_SERIALIZE_FULL - | - GNUNET_SERIALIZE_NO_COMPRESS); - if (size > 1024 * 1024) - size = 1024 * 1024; - buf = GNUNET_malloc (size); - GNUNET_meta_data_serialize (ectx, - meta, - buf, - size, - GNUNET_SERIALIZE_PART | - GNUNET_SERIALIZE_NO_COMPRESS); - WRITEINT (wb, size); - write_buffered (wb, buf, size); - GNUNET_free (buf); -} - - -static void -writeFileInfo (struct GNUNET_GE_Context *ectx, WriteBuffer * wb, - const GNUNET_ECRS_FileInfo * fi) -{ - writeMetaData (ectx, wb, fi->meta); - writeURI (wb, fi->uri); -} - - - - -typedef struct -{ - int fd; - unsigned int have; - unsigned int size; - unsigned int pos; - char *buffer; -} ReadBuffer; - -static int -read_buffered (ReadBuffer * rb, void *d, unsigned int size) -{ - char *dst = d; - unsigned int min; - unsigned int pos; - int ret; - - if (rb->fd == -1) - return -1; - pos = 0; - do - { - /* first, use buffer */ - min = rb->have - rb->pos; - if (min > 0) - { - if (min > size - pos) - min = size - pos; - memcpy (&dst[pos], &rb->buffer[rb->pos], min); - rb->pos += min; - pos += min; - } - if (pos == size) - return pos; /* done! */ - GNUNET_GE_ASSERT (NULL, rb->have == rb->pos); - /* fill buffer */ - ret = READ (rb->fd, rb->buffer, rb->size); - if (ret == -1) - { - CLOSE (rb->fd); - rb->fd = -1; - return -1; - } - if (ret == 0) - return 0; - rb->pos = 0; - rb->have = ret; - } - while (pos < size); /* should always be true */ - return pos; -} - - -static int -read_int (ReadBuffer * rb, int *val) -{ - int big; - - if (sizeof (int) != read_buffered (rb, &big, sizeof (int))) - return GNUNET_SYSERR; - *val = ntohl (big); - return GNUNET_OK; -} - -static unsigned int -read_uint (ReadBuffer * rb, unsigned int *val) -{ - unsigned int big; - - if (sizeof (unsigned int) != - read_buffered (rb, &big, sizeof (unsigned int))) - return GNUNET_SYSERR; - *val = ntohl (big); - return GNUNET_OK; -} - -#define READINT(a) if (GNUNET_OK != read_int(rb, (int*) &a)) return GNUNET_SYSERR; - -static int -read_long (ReadBuffer * rb, long long *val) -{ - long long big; - - if (sizeof (long long) != read_buffered (rb, &big, sizeof (long long))) - return GNUNET_SYSERR; - *val = GNUNET_ntohll (big); - return GNUNET_OK; -} - -#define READLONG(a) if (GNUNET_OK != read_long(rb, (long long*) &a)) return GNUNET_SYSERR; - -static struct GNUNET_ECRS_URI * -read_uri (struct GNUNET_GE_Context *ectx, ReadBuffer * rb) -{ - char *buf; - struct GNUNET_ECRS_URI *ret; - unsigned int size; - - if (GNUNET_OK != read_uint (rb, &size)) - return NULL; - buf = GNUNET_malloc (size + 1); - buf[size] = '\0'; - if (size != read_buffered (rb, buf, size)) - { - GNUNET_free (buf); - return NULL; - } - ret = GNUNET_ECRS_string_to_uri (ectx, buf); - GNUNET_GE_BREAK (ectx, ret != NULL); - GNUNET_free (buf); - return ret; -} - -#define READURI(u) if (NULL == (u = read_uri(ectx, rb))) return GNUNET_SYSERR; - -static char * -read_string (ReadBuffer * rb, unsigned int maxLen) -{ - char *buf; - unsigned int big; - - if (GNUNET_OK != read_uint (rb, &big)) - return NULL; - if (big > maxLen) - return NULL; - buf = GNUNET_malloc (big + 1); - buf[big] = '\0'; - if (big != read_buffered (rb, buf, big)) - { - GNUNET_free (buf); - return NULL; - } - return buf; -} - -#define READSTRING(c, max) if (NULL == (c = read_string(rb, max))) return GNUNET_SYSERR; - -/** - * Read file info from file. - * - * @return GNUNET_OK on success, GNUNET_SYSERR on error - */ -static struct GNUNET_MetaData * -read_meta (struct GNUNET_GE_Context *ectx, ReadBuffer * rb) -{ - unsigned int size; - char *buf; - struct GNUNET_MetaData *meta; - - if (read_uint (rb, &size) != GNUNET_OK) - { - GNUNET_GE_BREAK (ectx, 0); - return NULL; - } - if (size > 1024 * 1024) - { - GNUNET_GE_BREAK (ectx, 0); - return NULL; - } - buf = GNUNET_malloc (size); - if (size != read_buffered (rb, buf, size)) - { - GNUNET_free (buf); - GNUNET_GE_BREAK (ectx, 0); - return NULL; - } - meta = GNUNET_meta_data_deserialize (ectx, buf, size); - if (meta == NULL) - { - GNUNET_free (buf); - GNUNET_GE_BREAK (ectx, 0); - return NULL; - } - GNUNET_free (buf); - return meta; -} - /* end of bio.c */