Make storing messages async. Phew.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4355 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
124
src/ssb.c
124
src/ssb.c
@ -237,6 +237,8 @@ typedef struct _tf_ssb_t
|
||||
|
||||
void (*hitch_callback)(const char* name, uint64_t duration, void* user_data);
|
||||
void* hitch_user_data;
|
||||
|
||||
tf_ssb_store_queue_t store_queue;
|
||||
} tf_ssb_t;
|
||||
|
||||
typedef struct _tf_ssb_connection_message_request_t
|
||||
@ -1666,7 +1668,7 @@ static bool _tf_ssb_connection_box_stream_recv(tf_ssb_connection_t* connection)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tf_ssb_append_message_with_keys(tf_ssb_t* ssb, const char* author, const uint8_t* private_key, JSValue message, char* out_id, size_t out_id_size)
|
||||
JSValue tf_ssb_sign_message(tf_ssb_t* ssb, const char* author, const uint8_t* private_key, JSValue message)
|
||||
{
|
||||
char previous_id[crypto_hash_sha256_BYTES * 2];
|
||||
int64_t previous_sequence = 0;
|
||||
@ -1675,14 +1677,7 @@ bool tf_ssb_append_message_with_keys(tf_ssb_t* ssb, const char* author, const ui
|
||||
JSContext* context = ssb->context;
|
||||
JSValue root = JS_NewObject(context);
|
||||
|
||||
if (have_previous)
|
||||
{
|
||||
JS_SetPropertyStr(context, root, "previous", JS_NewString(context, previous_id));
|
||||
}
|
||||
else
|
||||
{
|
||||
JS_SetPropertyStr(context, root, "previous", JS_NULL);
|
||||
}
|
||||
JS_SetPropertyStr(context, root, "previous", have_previous ? JS_NewString(context, previous_id) : JS_NULL);
|
||||
JS_SetPropertyStr(context, root, "author", JS_NewString(context, author));
|
||||
JS_SetPropertyStr(context, root, "sequence", JS_NewInt64(context, previous_sequence + 1));
|
||||
|
||||
@ -1696,53 +1691,29 @@ bool tf_ssb_append_message_with_keys(tf_ssb_t* ssb, const char* author, const ui
|
||||
JSValue jsonval = JS_JSONStringify(context, root, JS_NULL, JS_NewInt32(context, 2));
|
||||
size_t len = 0;
|
||||
const char* json = JS_ToCStringLen(context, &len, jsonval);
|
||||
JS_FreeValue(context, jsonval);
|
||||
|
||||
uint8_t signature[crypto_sign_BYTES];
|
||||
unsigned long long siglen;
|
||||
bool valid = crypto_sign_detached(signature, &siglen, (const uint8_t*)json, len, private_key) == 0;
|
||||
JS_FreeCString(context, json);
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
tf_printf("crypto_sign_detached failed\n");
|
||||
}
|
||||
|
||||
char signature_base64[crypto_sign_BYTES * 2];
|
||||
tf_base64_encode(signature, sizeof(signature), signature_base64, sizeof(signature_base64));
|
||||
strcat(signature_base64, ".sig.ed25519");
|
||||
JSValue sigstr = JS_NewString(context, signature_base64);
|
||||
JS_SetPropertyStr(context, root, "signature", sigstr);
|
||||
|
||||
bool stored = false;
|
||||
char id[sodium_base64_ENCODED_LEN(crypto_hash_sha256_BYTES, sodium_base64_VARIANT_ORIGINAL) + 7 + 1];
|
||||
if (valid && tf_ssb_verify_and_strip_signature(ssb->context, root, id, sizeof(id), NULL, 0, NULL))
|
||||
{
|
||||
if (tf_ssb_db_store_message(ssb, ssb->context, id, root, signature_base64, false))
|
||||
{
|
||||
tf_ssb_notify_message_added(ssb, id);
|
||||
snprintf(out_id, out_id_size, "%s", id);
|
||||
stored = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
tf_printf("message not stored.\n");
|
||||
}
|
||||
JS_FreeValue(context, root);
|
||||
root = JS_UNDEFINED;
|
||||
}
|
||||
else
|
||||
{
|
||||
tf_printf("Failed to verify message signature.\n");
|
||||
tf_printf("json = %s\n", json);
|
||||
tf_printf("sig = %s\n", signature_base64);
|
||||
char signature_base64[crypto_sign_BYTES * 2];
|
||||
tf_base64_encode(signature, sizeof(signature), signature_base64, sizeof(signature_base64));
|
||||
strcat(signature_base64, ".sig.ed25519");
|
||||
JSValue sigstr = JS_NewString(context, signature_base64);
|
||||
JS_SetPropertyStr(context, root, "signature", sigstr);
|
||||
}
|
||||
|
||||
if (!stored && out_id && out_id_size)
|
||||
{
|
||||
*out_id = '\0';
|
||||
}
|
||||
|
||||
JS_FreeCString(context, json);
|
||||
JS_FreeValue(context, jsonval);
|
||||
|
||||
JS_FreeValue(context, root);
|
||||
return stored;
|
||||
return root;
|
||||
}
|
||||
|
||||
static void _tf_ssb_connection_dispatch_scheduled(tf_ssb_connection_t* connection)
|
||||
@ -2123,7 +2094,7 @@ tf_ssb_t* tf_ssb_create(uv_loop_t* loop, JSContext* context, const char* db_path
|
||||
JS_NewClass(JS_GetRuntime(ssb->context), _connection_class_id, &def);
|
||||
|
||||
ssb->db_path = tf_strdup(db_path);
|
||||
sqlite3_open_v2(db_path, &ssb->db_writer, SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI, NULL);
|
||||
sqlite3_open_v2(db_path, &ssb->db_writer, SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI | SQLITE_OPEN_CREATE, NULL);
|
||||
tf_ssb_db_init(ssb);
|
||||
|
||||
if (loop)
|
||||
@ -3419,32 +3390,54 @@ tf_ssb_blob_wants_t* tf_ssb_connection_get_blob_wants_state(tf_ssb_connection_t*
|
||||
return connection ? &connection->blob_wants : NULL;
|
||||
}
|
||||
|
||||
bool tf_ssb_verify_strip_and_store_message(tf_ssb_t* ssb, JSValue value, bool* out_is_new)
|
||||
typedef struct _store_t
|
||||
{
|
||||
tf_ssb_t* ssb;
|
||||
bool verified;
|
||||
bool stored;
|
||||
char id[crypto_hash_sha256_BYTES * 2 + 1];
|
||||
|
||||
tf_ssb_verify_strip_store_callback_t* callback;
|
||||
void* user_data;
|
||||
} store_t;
|
||||
|
||||
static void _tf_ssb_verify_strip_and_store_finish(store_t* store)
|
||||
{
|
||||
if (store->callback)
|
||||
{
|
||||
store->callback(store->id, store->verified, store->stored, store->user_data);
|
||||
}
|
||||
tf_free(store);
|
||||
}
|
||||
|
||||
static void _tf_ssb_verify_strip_and_store_callback(const char* id, bool stored, void* user_data)
|
||||
{
|
||||
store_t* store = user_data;
|
||||
store->stored = stored;
|
||||
_tf_ssb_verify_strip_and_store_finish(store);
|
||||
}
|
||||
|
||||
void tf_ssb_verify_strip_and_store_message(tf_ssb_t* ssb, JSValue value, tf_ssb_verify_strip_store_callback_t* callback, void* user_data)
|
||||
{
|
||||
JSContext* context = tf_ssb_get_context(ssb);
|
||||
store_t* async = tf_malloc(sizeof(store_t));
|
||||
*async = (store_t)
|
||||
{
|
||||
.ssb = ssb,
|
||||
.callback = callback,
|
||||
.user_data = user_data,
|
||||
};
|
||||
char signature[crypto_sign_BYTES + 128] = { 0 };
|
||||
char id[crypto_hash_sha256_BYTES * 2 + 1] = { 0 };
|
||||
bool sequence_before_author = false;
|
||||
if (out_is_new)
|
||||
if (tf_ssb_verify_and_strip_signature(context, value, async->id, sizeof(async->id), signature, sizeof(signature), &sequence_before_author))
|
||||
{
|
||||
*out_is_new = false;
|
||||
}
|
||||
if (tf_ssb_verify_and_strip_signature(context, value, id, sizeof(id), signature, sizeof(signature), &sequence_before_author))
|
||||
{
|
||||
if (tf_ssb_db_store_message(ssb, context, id, value, signature, sequence_before_author))
|
||||
{
|
||||
tf_ssb_notify_message_added(ssb, id);
|
||||
if (out_is_new)
|
||||
{
|
||||
*out_is_new = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
async->verified = true;
|
||||
tf_ssb_db_store_message(ssb, context, async->id, value, signature, sequence_before_author, _tf_ssb_verify_strip_and_store_callback, async);
|
||||
}
|
||||
else
|
||||
{
|
||||
tf_printf("failed to verify message\n");
|
||||
return false;
|
||||
printf("nope\n");
|
||||
_tf_ssb_verify_strip_and_store_finish(async);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3555,3 +3548,8 @@ void tf_ssb_set_hitch_callback(tf_ssb_t* ssb, void (*callback)(const char* name,
|
||||
ssb->hitch_callback = callback;
|
||||
ssb->hitch_user_data = user_data;
|
||||
}
|
||||
|
||||
tf_ssb_store_queue_t* tf_ssb_get_store_queue(tf_ssb_t* ssb)
|
||||
{
|
||||
return &ssb->store_queue;
|
||||
}
|
||||
|
Reference in New Issue
Block a user