commit d1a6ac474d731b74ea1b191a76471b698687a278
parent b880617514f9e64e991cb8d6fcff74ce3f292e36
Author: TheJackiMonster <thejackimonster@gmail.com>
Date: Mon, 12 Jul 2021 00:21:25 +0200
Most of the file handling and necessary disk io calls
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
Diffstat:
11 files changed, 612 insertions(+), 113 deletions(-)
diff --git a/include/gnunet_chat_lib.h b/include/gnunet_chat_lib.h
@@ -194,6 +194,7 @@ typedef int
* TODO
*
* @param cfg
+ * @param directory
* @param name
* @param warn_cb
* @param warn_cls
@@ -201,6 +202,7 @@ typedef int
*/
struct GNUNET_CHAT_Handle*
GNUNET_CHAT_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *directory,
const char *name,
GNUNET_CHAT_WarningCallback warn_cb, void *warn_cls,
GNUNET_CHAT_ContextMessageCallback msg_cb, void *msg_cls);
@@ -398,8 +400,9 @@ GNUNET_CHAT_group_get_context (struct GNUNET_CHAT_Group *group);
*
* @param context
* @param text
+ * @return
*/
-void
+int
GNUNET_CHAT_context_send_text (struct GNUNET_CHAT_Context *context,
const char *text);
@@ -408,8 +411,9 @@ GNUNET_CHAT_context_send_text (struct GNUNET_CHAT_Context *context,
*
* @param context
* @param path
+ * @return
*/
-void
+int
GNUNET_CHAT_context_send_file (struct GNUNET_CHAT_Context *context,
const char *path);
@@ -418,8 +422,9 @@ GNUNET_CHAT_context_send_file (struct GNUNET_CHAT_Context *context,
*
* @param context
* @param uri
+ * @return
*/
-void
+int
GNUNET_CHAT_context_send_uri (struct GNUNET_CHAT_Context *context,
const char *uri);
@@ -428,8 +433,9 @@ GNUNET_CHAT_context_send_uri (struct GNUNET_CHAT_Context *context,
*
* @param context
* @param file
+ * @return
*/
-void
+int
GNUNET_CHAT_context_share_file (struct GNUNET_CHAT_Context *context,
const struct GNUNET_CHAT_File *file);
@@ -437,17 +443,6 @@ GNUNET_CHAT_context_share_file (struct GNUNET_CHAT_Context *context,
* TODO
*
* @param context
- * @param hash
- * @param delay
- */
-void
-GNUNET_CHAT_context_delete_message (const struct GNUNET_CHAT_Message *message,
- struct GNUNET_TIME_Relative delay);
-
-/**
- * TODO
- *
- * @param context
* @param callback
* @param cls
* @return
@@ -528,6 +523,17 @@ GNUNET_CHAT_message_get_invitation (const struct GNUNET_CHAT_Message *message);
/**
* TODO
*
+ * @param message
+ * @param delay
+ * @return
+ */
+int
+GNUNET_CHAT_message_delete (const struct GNUNET_CHAT_Message *message,
+ struct GNUNET_TIME_Relative delay);
+
+/**
+ * TODO
+ *
* @param file
* @return
*/
@@ -593,6 +599,15 @@ GNUNET_CHAT_file_stop_download (struct GNUNET_CHAT_File *file);
/**
* TODO
*
+ * @param file
+ * @return
+ */
+int
+GNUNET_CHAT_file_unindex (struct GNUNET_CHAT_File *file);
+
+/**
+ * TODO
+ *
* @param invitation
*/
void
diff --git a/src/gnunet_chat_context.c b/src/gnunet_chat_context.c
@@ -24,6 +24,8 @@
#include "gnunet_chat_context.h"
+#include "gnunet_chat_context_intern.c"
+
struct GNUNET_CHAT_Context*
context_create_from_room (struct GNUNET_CHAT_Handle *handle,
struct GNUNET_MESSENGER_Room *room)
@@ -47,6 +49,14 @@ context_create_from_room (struct GNUNET_CHAT_Handle *handle,
void
context_destroy (struct GNUNET_CHAT_Context* context)
{
+ GNUNET_CONTAINER_multihashmap_iterate(
+ context->messages, it_destroy_context_messages, NULL
+ );
+
+ GNUNET_CONTAINER_multihashmap_iterate(
+ context->messages, it_destroy_context_invites, NULL
+ );
+
GNUNET_CONTAINER_multihashmap_destroy(context->messages);
GNUNET_CONTAINER_multihashmap_destroy(context->invites);
GNUNET_CONTAINER_multihashmap_destroy(context->files);
diff --git a/src/gnunet_chat_context_intern.c b/src/gnunet_chat_context_intern.c
@@ -0,0 +1,48 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2021 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/*
+ * @author Tobias Frisch
+ * @file gnunet_chat_context_intern.c
+ */
+
+#include "gnunet_chat_invitation.h"
+#include "gnunet_chat_message.h"
+
+#define GNUNET_UNUSED __attribute__ ((unused))
+
+int
+it_destroy_context_messages (GNUNET_UNUSED void *cls,
+ GNUNET_UNUSED const struct GNUNET_HashCode *key,
+ void *value)
+{
+ struct GNUNET_CHAT_Message *message = value;
+ message_destroy(message);
+ return GNUNET_YES;
+}
+
+int
+it_destroy_context_invites (GNUNET_UNUSED void *cls,
+ GNUNET_UNUSED const struct GNUNET_HashCode *key,
+ void *value)
+{
+ struct GNUNET_CHAT_Invitation *invitation = value;
+ invitation_destroy(invitation);
+ return GNUNET_YES;
+}
diff --git a/src/gnunet_chat_file.c b/src/gnunet_chat_file.c
@@ -39,6 +39,12 @@ file_create_from_message (struct GNUNET_CHAT_Handle *handle,
GNUNET_memcpy(&(file->key), &(message->key), sizeof(file->key));
GNUNET_memcpy(&(file->hash), &(message->hash), sizeof(file->hash));
+ file->published = 0;
+ file->downloaded = 0;
+ file->unindexed = 0;
+
+ file->meta = GNUNET_CONTAINER_meta_data_create();
+
file->uri = GNUNET_FS_uri_parse(message->uri, NULL);
file->download = NULL;
file->publish = NULL;
@@ -47,12 +53,43 @@ file_create_from_message (struct GNUNET_CHAT_Handle *handle,
return file;
}
+struct GNUNET_CHAT_File*
+file_create_from_disk (struct GNUNET_CHAT_Handle *handle,
+ const char *name, const struct GNUNET_HashCode *hash,
+ const struct GNUNET_CRYPTO_SymmetricSessionKey *key)
+{
+ struct GNUNET_CHAT_File* file = GNUNET_new(struct GNUNET_CHAT_File);
+
+ file->handle = handle;
+
+ file->name = GNUNET_strndup(name, NAME_MAX);
+
+ GNUNET_memcpy(&(file->key), key, sizeof(file->key));
+ GNUNET_memcpy(&(file->hash), hash, sizeof(file->hash));
+
+ file->published = 0;
+ file->downloaded = 0;
+ file->unindexed = 0;
+
+ file->meta = GNUNET_CONTAINER_meta_data_create();
+
+ file->uri = NULL;
+ file->download = NULL;
+ file->publish = NULL;
+ file->unindex = NULL;
+
+ return file;
+}
+
void
file_destroy (struct GNUNET_CHAT_File* file)
{
if (file->uri)
GNUNET_FS_uri_destroy(file->uri);
+ if (file->meta)
+ GNUNET_CONTAINER_meta_data_destroy(file->meta);
+
if (file->name)
GNUNET_free(file->name);
diff --git a/src/gnunet_chat_file.h b/src/gnunet_chat_file.h
@@ -43,6 +43,12 @@ struct GNUNET_CHAT_File
struct GNUNET_HashCode hash;
struct GNUNET_CRYPTO_SymmetricSessionKey key;
+ uint64_t published;
+ uint64_t downloaded;
+ uint64_t unindexed;
+
+ struct GNUNET_CONTAINER_MetaData *meta;
+
struct GNUNET_FS_Uri* uri;
struct GNUNET_FS_DownloadContext* download;
struct GNUNET_FS_PublishContext* publish;
@@ -53,6 +59,11 @@ struct GNUNET_CHAT_File*
file_create_from_message (struct GNUNET_CHAT_Handle *handle,
const struct GNUNET_MESSENGER_MessageFile* message);
+struct GNUNET_CHAT_File*
+file_create_from_disk (struct GNUNET_CHAT_Handle *handle,
+ const char *name, const struct GNUNET_HashCode *hash,
+ const struct GNUNET_CRYPTO_SymmetricSessionKey *key);
+
void
file_destroy (struct GNUNET_CHAT_File* file);
diff --git a/src/gnunet_chat_handle.c b/src/gnunet_chat_handle.c
@@ -28,7 +28,8 @@
struct GNUNET_CHAT_Handle*
handle_create_from_config (const struct GNUNET_CONFIGURATION_Handle* cfg,
- const char* name,
+ const char *directory,
+ const char *name,
GNUNET_CHAT_ContextMessageCallback msg_cb,
void *msg_cls,
GNUNET_CHAT_WarningCallback warn_cb,
@@ -38,6 +39,12 @@ handle_create_from_config (const struct GNUNET_CONFIGURATION_Handle* cfg,
handle->cfg = cfg;
+ if ((directory) &&
+ (GNUNET_YES == GNUNET_DISK_directory_test(directory, GNUNET_YES)))
+ handle->directory = GNUNET_strdup(directory);
+ else
+ handle->directory = NULL;
+
handle->msg_cb = msg_cb;
handle->msg_cls = msg_cls;
@@ -58,7 +65,7 @@ handle_create_from_config (const struct GNUNET_CONFIGURATION_Handle* cfg,
on_handle_arm_connection(handle, GNUNET_NO);
handle->fs = GNUNET_FS_start(
- handle->cfg, name, // TODO: raw name?
+ handle->cfg, name, // TODO: raw name? (NULL?)
notify_handle_fs_progress, handle,
GNUNET_FS_FLAGS_NONE,
GNUNET_FS_OPTIONS_END
@@ -85,10 +92,29 @@ handle_destroy (struct GNUNET_CHAT_Handle* handle)
if (handle->arm)
GNUNET_ARM_disconnect(handle->arm);
+ GNUNET_CONTAINER_multihashmap_iterate(
+ handle->groups, it_destroy_handle_groups, NULL
+ );
+
+ GNUNET_CONTAINER_multishortmap_iterate(
+ handle->contacts, it_destroy_handle_contacts, NULL
+ );
+
+ GNUNET_CONTAINER_multihashmap_iterate(
+ handle->contexts, it_destroy_handle_contexts, NULL
+ );
+
+ GNUNET_CONTAINER_multihashmap_iterate(
+ handle->files, it_destroy_handle_files, NULL
+ );
+
GNUNET_CONTAINER_multihashmap_destroy(handle->groups);
GNUNET_CONTAINER_multishortmap_destroy(handle->contacts);
GNUNET_CONTAINER_multihashmap_destroy(handle->contexts);
GNUNET_CONTAINER_multihashmap_destroy(handle->files);
+ if (handle->directory)
+ GNUNET_free(handle->directory);
+
GNUNET_free(handle);
}
diff --git a/src/gnunet_chat_handle.h b/src/gnunet_chat_handle.h
@@ -40,6 +40,8 @@ struct GNUNET_CHAT_Handle
{
const struct GNUNET_CONFIGURATION_Handle* cfg;
+ char *directory;
+
GNUNET_CHAT_ContextMessageCallback msg_cb;
void *msg_cls;
@@ -58,7 +60,8 @@ struct GNUNET_CHAT_Handle
struct GNUNET_CHAT_Handle*
handle_create_from_config (const struct GNUNET_CONFIGURATION_Handle* cfg,
- const char* name,
+ const char *directory,
+ const char *name,
GNUNET_CHAT_ContextMessageCallback msg_cb,
void *msg_cls,
GNUNET_CHAT_WarningCallback warn_cb,
diff --git a/src/gnunet_chat_handle_intern.c b/src/gnunet_chat_handle_intern.c
@@ -24,8 +24,10 @@
#include "gnunet_chat_contact.h"
#include "gnunet_chat_context.h"
+#include "gnunet_chat_file.h"
#include "gnunet_chat_group.h"
#include "gnunet_chat_handle.h"
+#include "gnunet_chat_invitation.h"
#include "gnunet_chat_message.h"
#include "gnunet_chat_util.h"
@@ -67,79 +69,70 @@ notify_handle_fs_progress(void* cls, const struct GNUNET_FS_ProgressInfo* info)
switch (info->status) {
case GNUNET_FS_STATUS_PUBLISH_START: {
- /*publication_t* publication = (publication_t*) info->value.publish.cctx;
- publication->progress = 0.0f;
+ struct GNUNET_CHAT_File *file = info->value.publish.cctx;
- GNUNET_SCHEDULER_add_now(&CGTK_publication_progress, publication);
+ file->published = 0;
- return publication;*/
- break;
+ return file;
} case GNUNET_FS_STATUS_PUBLISH_PROGRESS: {
- /*publication_t* publication = (publication_t*) info->value.publish.cctx;
- publication->progress = 1.0f * info->value.publish.completed / info->value.publish.size;
+ struct GNUNET_CHAT_File *file = info->value.publish.cctx;
- GNUNET_SCHEDULER_add_now(&CGTK_publication_progress, publication);
+ file->published = info->value.publish.completed;
- return publication;*/
- break;
+ return file;
} case GNUNET_FS_STATUS_PUBLISH_COMPLETED: {
- /*publication_t* publication = (publication_t*) info->value.publish.cctx;
- publication->uri = GNUNET_FS_uri_dup(info->value.publish.specifics.completed.chk_uri);
- publication->progress = 1.0f;
+ struct GNUNET_CHAT_File *file = info->value.publish.cctx;
+
+ file->uri = GNUNET_FS_uri_dup(
+ info->value.publish.specifics.completed.chk_uri
+ );
- GNUNET_SCHEDULER_add_now(&CGTK_publication_finish, publication);*/
+ file->published = info->value.publish.size;
+ file->publish = NULL;
break;
} case GNUNET_FS_STATUS_PUBLISH_ERROR: {
- /*publication_t* publication = (publication_t*) info->value.publish.cctx;
-
- GNUNET_SCHEDULER_add_now(&CGTK_publication_error, publication);*/
break;
} case GNUNET_FS_STATUS_DOWNLOAD_START: {
- /*request_t* request = (request_t*) info->value.download.cctx;
- request->progress = 0.0f;
+ struct GNUNET_CHAT_File *file = info->value.download.cctx;
- return request;*/
- break;
+ file->downloaded = 0;
+
+ return file;
} case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE: {
return info->value.download.cctx;
} case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE: {
return info->value.download.cctx;
} case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: {
- /*request_t* request = (request_t*) info->value.download.cctx;
- request->progress = 1.0f * info->value.download.completed / info->value.download.size;
+ struct GNUNET_CHAT_File *file = info->value.download.cctx;
- GNUNET_SCHEDULER_add_now(&CGTK_request_progress, request);
+ file->downloaded = info->value.download.completed;
- return request;*/
- break;
+ return file;
} case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED: {
- /*request_t* request = (request_t*) info->value.download.cctx;
- request->progress = 1.0f;
+ struct GNUNET_CHAT_File *file = info->value.download.cctx;
- GNUNET_SCHEDULER_add_now(&CGTK_request_finish, request);*/
+ file->downloaded = info->value.download.size;
+ file->download = NULL;
break;
} case GNUNET_FS_STATUS_DOWNLOAD_ERROR: {
- /*request_t *request = (request_t *) info->value.download.cctx;
-
- GNUNET_SCHEDULER_add_now(&CGTK_request_error, request);*/
break;
} case GNUNET_FS_STATUS_UNINDEX_START: {
- /*publication_t* publication = (publication_t*) info->value.unindex.cctx;
- publication->progress = 0.0f;
+ struct GNUNET_CHAT_File *file = info->value.unindex.cctx;
- return publication;*/
- break;
+ file->unindexed = 0;
+
+ return file;
} case GNUNET_FS_STATUS_UNINDEX_PROGRESS: {
- /*publication_t* publication = (publication_t*) info->value.unindex.cctx;
- publication->progress = 1.0f * info->value.unindex.completed / info->value.unindex.size;
+ struct GNUNET_CHAT_File *file = info->value.unindex.cctx;
- return publication;*/
- break;
+ file->unindexed = info->value.unindex.completed;
+
+ return file;
} case GNUNET_FS_STATUS_UNINDEX_COMPLETED: {
- /*publication_t* publication = (publication_t*) info->value.unindex.cctx;
- publication->progress = 1.0f;
+ struct GNUNET_CHAT_File *file = info->value.unindex.cctx;
- GNUNET_SCHEDULER_add_now(&CGTK_publication_unindex_finish, publication);*/
+ file->unindexed = info->value.unindex.size;
+ file->unindex = NULL;
break;
} default: {
break;
@@ -290,10 +283,45 @@ on_handle_message (void *cls,
);
if (message)
- goto process_callback;
+ return;
message = message_create_from_msg(context, hash, msg);
+ switch (msg->header.kind)
+ {
+ case GNUNET_MESSENGER_KIND_INVITE:
+ {
+ struct GNUNET_CHAT_Invitation *invitation = invitation_create_from_message(
+ context, &(msg->body.invite)
+ );
+
+ if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
+ context->invites, hash, invitation,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
+ invitation_destroy(invitation);
+ break;
+ }
+ case GNUNET_MESSENGER_KIND_FILE:
+ {
+ GNUNET_CONTAINER_multihashmap_put(
+ context->files, hash, NULL,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST
+ );
+
+ struct GNUNET_CHAT_File *file = file_create_from_message(
+ context->handle, &(msg->body.file)
+ );
+
+ if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
+ context->handle->files, &(file->hash), file,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
+ file_destroy(file);
+ break;
+ }
+ default:
+ break;
+ }
+
if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
context->messages, hash, message,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
@@ -302,7 +330,46 @@ on_handle_message (void *cls,
return;
}
-process_callback:
if (handle->msg_cb)
handle->msg_cb(handle->msg_cls, context, message);
}
+
+int
+it_destroy_handle_groups (GNUNET_UNUSED void *cls,
+ GNUNET_UNUSED const struct GNUNET_HashCode *key,
+ void *value)
+{
+ struct GNUNET_CHAT_Group *group = value;
+ group_destroy(group);
+ return GNUNET_YES;
+}
+
+int
+it_destroy_handle_contacts (GNUNET_UNUSED void *cls,
+ GNUNET_UNUSED const struct GNUNET_ShortHashCode *key,
+ void *value)
+{
+ struct GNUNET_CHAT_Contact *contact = value;
+ contact_destroy(contact);
+ return GNUNET_YES;
+}
+
+int
+it_destroy_handle_contexts (GNUNET_UNUSED void *cls,
+ GNUNET_UNUSED const struct GNUNET_HashCode *key,
+ void *value)
+{
+ struct GNUNET_CHAT_Context *context = value;
+ context_destroy(context);
+ return GNUNET_YES;
+}
+
+int
+it_destroy_handle_files (GNUNET_UNUSED void *cls,
+ GNUNET_UNUSED const struct GNUNET_HashCode *key,
+ void *value)
+{
+ struct GNUNET_CHAT_File *file = value;
+ file_destroy(file);
+ return GNUNET_YES;
+}
diff --git a/src/gnunet_chat_lib.c b/src/gnunet_chat_lib.c
@@ -40,6 +40,7 @@
struct GNUNET_CHAT_Handle*
GNUNET_CHAT_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *directory,
const char *name,
GNUNET_CHAT_WarningCallback warn_cb, void *warn_cls,
GNUNET_CHAT_ContextMessageCallback msg_cb, void *msg_cls)
@@ -47,11 +48,10 @@ GNUNET_CHAT_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
if (!cfg)
return NULL;
- if (!name)
- return NULL;
-
return handle_create_from_config(
- cfg, name, msg_cb, msg_cls, warn_cb, warn_cls
+ cfg, directory, name,
+ msg_cb, msg_cls,
+ warn_cb, warn_cls
);
}
@@ -332,6 +332,7 @@ GNUNET_CHAT_group_invite_contact (struct GNUNET_CHAT_Group *group,
GNUNET_MESSENGER_send_message(contact->context->room, &msg, contact->member);
}
+
int
GNUNET_CHAT_group_iterate_contacts (struct GNUNET_CHAT_Group *group,
GNUNET_CHAT_GroupContactCallback callback,
@@ -360,12 +361,13 @@ GNUNET_CHAT_group_get_context (struct GNUNET_CHAT_Group *group)
return group->context;
}
-void
+
+int
GNUNET_CHAT_context_send_text (struct GNUNET_CHAT_Context *context,
const char *text)
{
if ((!context) || (!text))
- return;
+ return GNUNET_SYSERR;
struct GNUNET_MESSENGER_Message msg;
msg.header.kind = GNUNET_MESSENGER_KIND_TEXT;
@@ -374,42 +376,109 @@ GNUNET_CHAT_context_send_text (struct GNUNET_CHAT_Context *context,
GNUNET_MESSENGER_send_message(context->room, &msg, NULL);
GNUNET_free(msg.body.text.text);
+ return GNUNET_OK;
}
-void
+int
GNUNET_CHAT_context_send_file (struct GNUNET_CHAT_Context *context,
const char *path)
{
if ((!context) || (!path))
- return;
+ return GNUNET_SYSERR;
+
+ if (!(context->handle->directory))
+ return GNUNET_SYSERR;
+
+ struct GNUNET_HashCode hash;
+ if (GNUNET_OK != util_hash_file(path, &hash))
+ return GNUNET_SYSERR;
+
+ char *filename;
+ util_get_filename (context->handle->directory, &hash, &filename);
+
+ if ((GNUNET_OK != GNUNET_DISK_directory_create_for_file(filename)) ||
+ (GNUNET_OK != GNUNET_DISK_file_copy(path, filename)))
+ {
+ GNUNET_free(filename);
+ return GNUNET_SYSERR;
+ }
+
+ struct GNUNET_CRYPTO_SymmetricSessionKey key;
+ GNUNET_CRYPTO_symmetric_create_session_key(&key);
+
+ if (GNUNET_OK != util_encrypt_file(filename, &key))
+ {
+ GNUNET_free(filename);
+ return GNUNET_SYSERR;
+ }
+
+ char* p = GNUNET_strdup(path);
- // TODO: encrypt file, publish file, share file
+ struct GNUNET_CHAT_File *file = file_create_from_disk(
+ context->handle, basename(p), &hash, &key
+ );
+
+ GNUNET_free(p);
+
+ struct GNUNET_FS_BlockOptions bo;
+
+ bo.anonymity_level = 1;
+ bo.content_priority = 100;
+ bo.replication_level = 1;
+
+ bo.expiration_time = GNUNET_TIME_absolute_add(
+ GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_get_hour_()
+ );
+
+ struct GNUNET_FS_FileInformation* fi = GNUNET_FS_file_information_create_from_file(
+ context->handle->fs,
+ file,
+ filename,
+ NULL,
+ file->meta,
+ GNUNET_YES,
+ &bo
+ );
+
+ file->publish = GNUNET_FS_publish_start(
+ context->handle->fs, fi,
+ NULL, NULL, NULL,
+ GNUNET_FS_PUBLISH_OPTION_NONE
+ );
+
+ GNUNET_free(filename);
+
+ // TODO: share file
+
+ return GNUNET_OK;
}
-void
+int
GNUNET_CHAT_context_send_uri (struct GNUNET_CHAT_Context *context,
const char *uri)
{
if ((!context) || (!uri))
- return;
+ return GNUNET_SYSERR;
struct GNUNET_FS_Uri *furi = GNUNET_FS_uri_parse(uri, NULL);
if (!furi)
- return;
+ return GNUNET_SYSERR;
// TODO: download file, hash file, share file
+
+ return GNUNET_SYSERR;
}
-void
+int
GNUNET_CHAT_context_share_file (struct GNUNET_CHAT_Context *context,
const struct GNUNET_CHAT_File *file)
{
if ((!context) || (!file) || (strlen(file->name) > NAME_MAX))
- return;
+ return GNUNET_SYSERR;
struct GNUNET_MESSENGER_Message msg;
msg.header.kind = GNUNET_MESSENGER_KIND_FILE;
@@ -421,26 +490,10 @@ GNUNET_CHAT_context_share_file (struct GNUNET_CHAT_Context *context,
GNUNET_MESSENGER_send_message(context->room, &msg, NULL);
GNUNET_free(msg.body.file.uri);
+ return GNUNET_OK;
}
-void
-GNUNET_CHAT_context_delete_message (const struct GNUNET_CHAT_Message *message,
- struct GNUNET_TIME_Relative delay)
-{
- if (!message)
- return;
-
- struct GNUNET_MESSENGER_Message msg;
- msg.header.kind = GNUNET_MESSENGER_KIND_DELETE;
- GNUNET_memcpy(&(msg.body.delete.hash), &(message->hash), sizeof(message->hash));
- msg.body.delete.delay = GNUNET_TIME_relative_hton(delay);
-
- GNUNET_MESSENGER_send_message(message->context->room, &msg, NULL);
-}
-
-
-
int
GNUNET_CHAT_context_iterate_messages (struct GNUNET_CHAT_Context *context,
GNUNET_CHAT_ContextMessageCallback callback,
@@ -571,6 +624,23 @@ GNUNET_CHAT_message_get_invitation (const struct GNUNET_CHAT_Message *message)
}
+int
+GNUNET_CHAT_message_delete (const struct GNUNET_CHAT_Message *message,
+ struct GNUNET_TIME_Relative delay)
+{
+ if (!message)
+ return GNUNET_SYSERR;
+
+ struct GNUNET_MESSENGER_Message msg;
+ msg.header.kind = GNUNET_MESSENGER_KIND_DELETE;
+ GNUNET_memcpy(&(msg.body.delete.hash), &(message->hash), sizeof(message->hash));
+ msg.body.delete.delay = GNUNET_TIME_relative_hton(delay);
+
+ GNUNET_MESSENGER_send_message(message->context->room, &msg, NULL);
+ return GNUNET_OK;
+}
+
+
const struct GNUNET_HashCode*
GNUNET_CHAT_file_get_hash (const struct GNUNET_CHAT_File *file)
{
@@ -590,11 +660,15 @@ GNUNET_CHAT_file_get_size (const struct GNUNET_CHAT_File *file)
if (file->uri)
return GNUNET_FS_uri_chk_get_file_size(file->uri);
- const char *path = ""; // TODO: path = download_directory + file->name
+ char *filename;
+ util_get_filename (file->handle->directory, &(file->hash), &filename);
- // TODO: check size through info or check locally?
+ uint64_t size;
+ if (GNUNET_OK != GNUNET_DISK_file_size(filename, &size, GNUNET_NO, GNUNET_YES))
+ size = 0;
- return 0;
+ GNUNET_free(filename);
+ return size;
}
@@ -604,11 +678,13 @@ GNUNET_CHAT_file_is_local (const struct GNUNET_CHAT_File *file)
if (!file)
return GNUNET_SYSERR;
- const char *path = ""; // TODO: path = download_directory + file->name
+ char *filename;
+ util_get_filename (file->handle->directory, &(file->hash), &filename);
- // TODO: check locally?
+ int result = GNUNET_DISK_file_test(filename);
- return GNUNET_SYSERR;
+ GNUNET_free(filename);
+ return result;
}
@@ -617,27 +693,44 @@ GNUNET_CHAT_file_start_download (struct GNUNET_CHAT_File *file,
GNUNET_CHAT_MessageFileDownloadCallback callback,
void *cls)
{
- if (!file)
+ if ((!file) || (!(file->uri)))
return GNUNET_SYSERR;
- // TODO: check if downloading?
+ if (file->download)
+ {
+ GNUNET_FS_download_resume(file->download);
+ return GNUNET_OK;
+ }
+
+ const uint64_t size = GNUNET_FS_uri_chk_get_file_size(file->uri);
- const char *path = ""; // TODO: path = download_directory + file->name
+ char *filename;
+ util_get_filename (file->handle->directory, &(file->hash), &filename);
+
+ uint64_t offset;
+ if (GNUNET_OK != GNUNET_DISK_file_size(filename, &offset, GNUNET_NO, GNUNET_YES))
+ offset = 0;
+
+ if (offset >= size)
+ return GNUNET_OK;
+
+ const uint64_t remaining = (size - offset);
file->download = GNUNET_FS_download_start(
file->handle->fs,
file->uri,
+ file->meta,
+ filename,
NULL,
- path,
- NULL,
- 0,
- 0,
- 0,
+ offset,
+ remaining,
+ 1,
GNUNET_FS_DOWNLOAD_OPTION_NONE,
- NULL,
+ file,
NULL
);
+ GNUNET_free(filename);
return GNUNET_OK;
}
@@ -676,6 +769,34 @@ GNUNET_CHAT_file_stop_download (struct GNUNET_CHAT_File *file)
}
+int
+GNUNET_CHAT_file_unindex (struct GNUNET_CHAT_File *file)
+{
+ if (!file)
+ return GNUNET_SYSERR;
+
+ if (file->publish)
+ {
+ GNUNET_FS_publish_stop(file->publish);
+ file->publish = NULL;
+ return GNUNET_OK;
+ }
+
+ if (file->unindex)
+ return GNUNET_OK;
+
+ char *filename;
+ util_get_filename (file->handle->directory, &(file->hash), &filename);
+
+ file->unindex = GNUNET_FS_unindex_start(
+ file->handle->fs, filename, file
+ );
+
+ GNUNET_free(filename);
+ return GNUNET_OK;
+}
+
+
void
GNUNET_CHAT_invitation_accept (struct GNUNET_CHAT_Invitation *invitation)
{
diff --git a/src/gnunet_chat_util.c b/src/gnunet_chat_util.c
@@ -26,14 +26,14 @@
void
util_shorthash_from_member (const struct GNUNET_MESSENGER_Contact *member,
- struct GNUNET_ShortHashCode* shorthash)
+ struct GNUNET_ShortHashCode *shorthash)
{
memset(shorthash, 0, sizeof(*shorthash));
GNUNET_memcpy(shorthash, &member, sizeof(member));
}
void
-util_set_name_field (const char *name, char** field)
+util_set_name_field (const char *name, char **field)
{
if (*field)
GNUNET_free(*field);
@@ -43,3 +43,147 @@ util_set_name_field (const char *name, char** field)
else
*field = NULL;
}
+
+int
+util_hash_file (const char *filename, struct GNUNET_HashCode *hash)
+{
+ uint64_t size;
+
+ if (GNUNET_OK != GNUNET_DISK_file_size(filename, &size, GNUNET_NO, GNUNET_YES))
+ return GNUNET_SYSERR;
+
+ struct GNUNET_DISK_FileHandle *file = GNUNET_DISK_file_open(
+ filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_USER_READ
+ );
+
+ if (!file)
+ return GNUNET_SYSERR;
+
+ struct GNUNET_DISK_MapHandle *mapping;
+ const void* data = GNUNET_DISK_file_map(
+ file, &mapping, GNUNET_DISK_MAP_TYPE_READ, size
+ );
+
+ if (!data)
+ {
+ GNUNET_DISK_file_close(file);
+ return GNUNET_SYSERR;
+ }
+
+ GNUNET_CRYPTO_hash(data, size, hash);
+
+ GNUNET_DISK_file_unmap(mapping);
+ GNUNET_DISK_file_close(file);
+
+ return GNUNET_OK;
+}
+
+int
+util_encrypt_file (const char *filename,
+ const struct GNUNET_CRYPTO_SymmetricSessionKey *key)
+{
+ uint64_t size;
+
+ if (GNUNET_OK != GNUNET_DISK_file_size(filename, &size, GNUNET_NO, GNUNET_YES))
+ return GNUNET_SYSERR;
+
+ struct GNUNET_DISK_FileHandle *file = GNUNET_DISK_file_open(
+ filename, GNUNET_DISK_OPEN_READWRITE,
+ GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE
+ );
+
+ if (!file)
+ return GNUNET_SYSERR;
+
+ struct GNUNET_DISK_MapHandle *mapping;
+ void* data = GNUNET_DISK_file_map(
+ file, &mapping, GNUNET_DISK_MAP_TYPE_READWRITE, size
+ );
+
+ if (!data)
+ {
+ GNUNET_DISK_file_close(file);
+ return GNUNET_SYSERR;
+ }
+
+ struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+ memset(&iv, 0, sizeof(iv));
+
+ ssize_t result = GNUNET_CRYPTO_symmetric_encrypt(data, size, key, &iv, data);
+
+ if (GNUNET_OK != GNUNET_DISK_file_unmap(mapping))
+ result = -1;
+
+ if (GNUNET_OK != GNUNET_DISK_file_sync(file))
+ result = -1;
+
+ if (GNUNET_OK != GNUNET_DISK_file_close(file))
+ result = -1;
+
+ if (result < 0)
+ return GNUNET_SYSERR;
+
+ return GNUNET_OK;
+}
+
+int
+util_decrypt_file (const char *filename,
+ const struct GNUNET_CRYPTO_SymmetricSessionKey *key)
+{
+ uint64_t size;
+
+ if (GNUNET_OK != GNUNET_DISK_file_size(filename, &size, GNUNET_NO, GNUNET_YES))
+ return GNUNET_SYSERR;
+
+ struct GNUNET_DISK_FileHandle *file = GNUNET_DISK_file_open(
+ filename, GNUNET_DISK_OPEN_READWRITE,
+ GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE
+ );
+
+ if (!file)
+ return GNUNET_SYSERR;
+
+ struct GNUNET_DISK_MapHandle *mapping;
+ void* data = GNUNET_DISK_file_map(
+ file, &mapping, GNUNET_DISK_MAP_TYPE_READWRITE, size
+ );
+
+ if (!data)
+ {
+ GNUNET_DISK_file_close(file);
+ return GNUNET_SYSERR;
+ }
+
+ struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+ memset(&iv, 0, sizeof(iv));
+
+ ssize_t result = GNUNET_CRYPTO_symmetric_decrypt(data, size, key, &iv, data);
+
+ if (GNUNET_OK != GNUNET_DISK_file_unmap(mapping))
+ result = -1;
+
+ if (GNUNET_OK != GNUNET_DISK_file_sync(file))
+ result = -1;
+
+ if (GNUNET_OK != GNUNET_DISK_file_close(file))
+ result = -1;
+
+ if (result < 0)
+ return GNUNET_SYSERR;
+
+ return GNUNET_OK;
+}
+
+int
+util_get_filename (const char *directory, const struct GNUNET_HashCode *hash,
+ char **filename)
+{
+ return GNUNET_asprintf (
+ filename,
+ "%s%s%c%s",
+ directory,
+ "files",
+ DIR_SEPARATOR,
+ GNUNET_h2s_full(hash)
+ );
+}
diff --git a/src/gnunet_chat_util.h b/src/gnunet_chat_util.h
@@ -27,14 +27,31 @@
#include <gnunet/platform.h>
#include <gnunet/gnunet_common.h>
+#include <gnunet/gnunet_crypto_lib.h>
+#include <gnunet/gnunet_disk_lib.h>
#include <gnunet/gnunet_messenger_service.h>
#include <gnunet/gnunet_util_lib.h>
void
util_shorthash_from_member (const struct GNUNET_MESSENGER_Contact *member,
- struct GNUNET_ShortHashCode* shorthash);
+ struct GNUNET_ShortHashCode *shorthash);
void
-util_set_name_field (const char *name, char** field);
+util_set_name_field (const char *name, char **field);
+
+int
+util_hash_file (const char *filename, struct GNUNET_HashCode *hash);
+
+int
+util_encrypt_file (const char *filename,
+ const struct GNUNET_CRYPTO_SymmetricSessionKey *key);
+
+int
+util_decrypt_file (const char *filename,
+ const struct GNUNET_CRYPTO_SymmetricSessionKey *key);
+
+int
+util_get_filename (const char *directory, const struct GNUNET_HashCode *hash,
+ char **filename);
#endif /* GNUNET_CHAT_UTIL_H_ */