|
|
|
|
@ -36,7 +36,6 @@
|
|
|
|
|
#include <string.h> |
|
|
|
|
#include <stdarg.h> |
|
|
|
|
#include <time.h> |
|
|
|
|
#include <unistd.h> |
|
|
|
|
|
|
|
|
|
#define CH_ID "4242424242424242" |
|
|
|
|
|
|
|
|
|
@ -208,9 +207,9 @@ static int dm_msg_has(struct UTUN_INSTANCE* inst, const char* needle) {
|
|
|
|
|
/* количество блобов в dm_mail для recipient=B от sender=A (одна проверка) */ |
|
|
|
|
static int dm_mail_count(struct UTUN_INSTANCE* inst) { |
|
|
|
|
sqlite3_stmt* s = NULL; |
|
|
|
|
int n = 0; |
|
|
|
|
int n = -1; |
|
|
|
|
if (sqlite3_prepare_v2(inst->topo_sqlite_db, |
|
|
|
|
"SELECT COUNT(*) FROM dm_mail WHERE recipient=? AND sender=?", |
|
|
|
|
"SELECT COUNT(*) FROM dm_pending_messages WHERE recipient=? AND sender=?", |
|
|
|
|
-1, &s, NULL) == SQLITE_OK) { |
|
|
|
|
sqlite3_bind_int64(s, 1, (sqlite3_int64)g_sh.nid[IDX_B]); |
|
|
|
|
sqlite3_bind_int64(s, 2, (sqlite3_int64)g_sh.nid[IDX_A]); |
|
|
|
|
@ -248,7 +247,7 @@ static void member_put_placeholder(struct UTUN_INSTANCE* inst, int idx, const ch
|
|
|
|
|
/* мембер C со флагом storage=yes (adm_tags подписан канальным ключом) */ |
|
|
|
|
static void member_put_storage(struct UTUN_INSTANCE* inst, int idx, const char* name) { |
|
|
|
|
char userinfo[256]; snprintf(userinfo, sizeof(userinfo), "{\"name\":\"%s\"}", name); |
|
|
|
|
char adm_tags[64]; snprintf(adm_tags, sizeof(adm_tags), "{\"storage\":\"yes\",\"ver\":\"1\"}"); |
|
|
|
|
char adm_tags[80]; snprintf(adm_tags, sizeof(adm_tags), "{\"storage\":\"yes\",\"supernode\":\"yes\",\"ver\":\"1\"}"); |
|
|
|
|
uint8_t ats[64]; |
|
|
|
|
uint8_t amsg[256]; size_t off = strlen(adm_tags); |
|
|
|
|
memcpy(amsg, adm_tags, off); |
|
|
|
|
@ -279,6 +278,7 @@ static void do_setup(struct UTUN_INSTANCE* inst, int role) {
|
|
|
|
|
case IDX_C: |
|
|
|
|
channel_put_shared(inst, 0); |
|
|
|
|
member_put_self(inst, "C"); |
|
|
|
|
member_put_storage(inst, IDX_C, "C"); |
|
|
|
|
member_put_placeholder(inst, IDX_A, "A"); |
|
|
|
|
member_put_placeholder(inst, IDX_B, "B"); |
|
|
|
|
member_sync_start(inst, g_sh.nid[IDX_A], CH_ID, NULL, NULL); |
|
|
|
|
@ -447,7 +447,23 @@ static void dm2_tick(void* arg) {
|
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case S2_WAIT_MAIL: |
|
|
|
|
if (dm_mail_count(C) > 0) t->phase = S2_RECONNECT; |
|
|
|
|
if (dm_mail_count(C) > 0) { |
|
|
|
|
/* У отправителя больше нет процесса; очередь суперузла также проходит restart. */ |
|
|
|
|
utun_instance_destroy(A); |
|
|
|
|
t->inst[IDX_A] = NULL; |
|
|
|
|
utun_instance_destroy(C); |
|
|
|
|
t->inst[IDX_C] = NULL; |
|
|
|
|
char cfg[512]; |
|
|
|
|
snprintf(cfg, sizeof(cfg), "%s/c.conf", getenv("UTUN_TEST_DIR")); |
|
|
|
|
t->inst[IDX_C] = utun_instance_create(t->ua, cfg); |
|
|
|
|
if (!t->inst[IDX_C] || utun_instance_init(t->inst[IDX_C]) != 0) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_DM, "s2: supernode restart failed"); |
|
|
|
|
t->result = 2; |
|
|
|
|
uasync_stop(t->ua); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
t->phase = S2_RECONNECT; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case S2_RECONNECT: { |
|
|
|
|
char cfg[512]; |
|
|
|
|
@ -554,10 +570,10 @@ int main(int argc, char** argv) {
|
|
|
|
|
char dir2[512]; snprintf(dir2, sizeof(dir2), "/tmp/utun_dm_e2e2_XXXXXX"); |
|
|
|
|
if (test_mkdtemp(dir2) != 0) { fprintf(stderr, "mkdtemp dir2 failed\n"); return 1; } |
|
|
|
|
test_setenv("UTUN_TEST_DIR", dir2, 1); |
|
|
|
|
fill_shared(70000 + (getpid() % 2000)); |
|
|
|
|
fill_shared(61000 + (getpid() % 1000)); |
|
|
|
|
write_configs(dir2); |
|
|
|
|
|
|
|
|
|
TEST("first message offline: mailbox delivery without prior conversation"); { |
|
|
|
|
TEST("first offline DM: supernode restart, sender remains offline"); { |
|
|
|
|
struct UASYNC* ua = uasync_create(); |
|
|
|
|
if (!ua) { FAIL("uasync_create failed"); return 1; } |
|
|
|
|
|
|
|
|
|
|