diff --git a/src/ssb.rpc.c b/src/ssb.rpc.c index fb656aff..5d4f1bc2 100644 --- a/src/ssb.rpc.c +++ b/src/ssb.rpc.c @@ -1202,16 +1202,98 @@ static void _tf_ssb_rpc_ebt_replicate_server( tf_ssb_connection_add_request(connection, -request_number, "ebt.replicate", _tf_ssb_rpc_ebt_replicate, NULL, NULL, NULL); } +typedef struct _invite_use_t +{ + tf_ssb_t* ssb; + char author[k_id_base64_len]; + ; + uint8_t private_key[512]; + char previous_id[64]; + int64_t previous_sequence; + + char host[256]; + int port; + char pub[k_id_base64_len]; +} invite_use_t; + +static void _tf_ssb_rpc_get_previous_work(tf_ssb_connection_t* connection, void* user_data) +{ + invite_use_t* work = user_data; + tf_ssb_t* ssb = work->ssb; + tf_ssb_db_get_latest_message_by_author(ssb, work->author, &work->previous_sequence, work->previous_id, sizeof(work->previous_id)); +} + +static void _tf_ssb_invite_use_pub_message_store_callback(const char* id, bool verified, bool is_new, void* user_data) +{ + invite_use_t* work = user_data; + tf_free(work); +} + +static void _tf_ssb_invite_use_contact_message_store_callback(const char* id, bool verified, bool is_new, void* user_data) +{ + /* + ** 2. Post a pub message: + ** { "type": "pub", "address": { "host": "one.butt.nz", "port": 8008, "key": "@VJM7w1W19ZsKmG2KnfaoKIM66BRoreEkzaVm/J//wl8=.ed25519" } } + */ + invite_use_t* work = user_data; + tf_ssb_t* ssb = work->ssb; + JSContext* context = tf_ssb_get_context(ssb); + + JSValue content = JS_NewObject(context); + JS_SetPropertyStr(context, content, "type", JS_NewString(context, "pub")); + JSValue address = JS_NewObject(context); + JS_SetPropertyStr(context, address, "host", JS_NewString(context, work->host)); + JS_SetPropertyStr(context, address, "port", JS_NewInt32(context, work->port)); + JS_SetPropertyStr(context, address, "key", JS_NewString(context, work->pub)); + JS_SetPropertyStr(context, content, "address", address); + + JSValue message = tf_ssb_sign_message(ssb, work->author, work->private_key, content, id, work->previous_sequence + 1); + JSValue json = JS_JSONStringify(context, message, JS_NULL, JS_NULL); + JS_FreeValue(context, json); + tf_ssb_verify_strip_and_store_message(ssb, message, _tf_ssb_invite_use_pub_message_store_callback, work); + JS_FreeValue(context, message); + + JS_FreeValue(context, content); +} + +static void _tf_ssb_rpc_get_previous_after_work(tf_ssb_connection_t* connection, int status, void* user_data) +{ + invite_use_t* work = user_data; + tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection); + + JSContext* context = tf_ssb_connection_get_context(connection); + JSValue content = JS_NewObject(context); + JS_SetPropertyStr(context, content, "type", JS_NewString(context, "contact")); + JS_SetPropertyStr(context, content, "contact", JS_NewString(context, work->pub)); + JS_SetPropertyStr(context, content, "following", JS_TRUE); + + JSValue message = tf_ssb_sign_message(ssb, work->author, work->private_key, content, work->previous_id, work->previous_sequence); + JSValue json = JS_JSONStringify(context, message, JS_NULL, JS_NULL); + JS_FreeValue(context, json); + tf_ssb_verify_strip_and_store_message(ssb, message, _tf_ssb_invite_use_contact_message_store_callback, work); + JS_FreeValue(context, message); + + JS_FreeValue(context, content); +} + static void _tf_ssb_rpc_invite_use_callback( tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) { /* - ** Follow the pub back: + ** 1. Follow the pub back: ** { "type": "contact", "contact": "@VJM7w1W19ZsKmG2KnfaoKIM66BRoreEkzaVm/J//wl8=.ed25519", "following": true } - ** - ** Post a pub message: - ** { "type": "pub", "address": { "host": "one.butt.nz", "port": 8008, "key": "@VJM7w1W19ZsKmG2KnfaoKIM66BRoreEkzaVm/J//wl8=.ed25519" } } */ + tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection); + invite_use_t* work = tf_malloc(sizeof(invite_use_t)); + *work = (invite_use_t) { + .ssb = ssb, + .port = tf_ssb_connection_get_port(connection), + }; + snprintf(work->host, sizeof(work->host), "%s", tf_ssb_connection_get_host(connection)); + tf_ssb_whoami(ssb, work->author, sizeof(work->author)); + tf_ssb_get_private_key(ssb, work->private_key, sizeof(work->private_key)); + tf_ssb_connection_get_id(connection, work->pub, sizeof(work->pub)); + tf_ssb_connection_run_work(connection, _tf_ssb_rpc_get_previous_work, _tf_ssb_rpc_get_previous_after_work, work); } static void _tf_ssb_rpc_send_invite_use(tf_ssb_connection_t* connection) diff --git a/src/ssb.tests.c b/src/ssb.tests.c index b730dec2..e0da8c62 100644 --- a/src/ssb.tests.c +++ b/src/ssb.tests.c @@ -1371,7 +1371,7 @@ void tf_ssb_test_invite(const tf_test_options_t* options) tf_printf("waiting for messages\n"); tf_ssb_set_main_thread(ssb0, true); tf_ssb_set_main_thread(ssb1, true); - while (count0 != 1 || count1 != 1) + while (count0 != 3 || count1 != 3) { uv_run(&loop, UV_RUN_ONCE); }