@ -31,6 +31,7 @@
# include <string.h>
# include <sqlite3.h>
# include <openssl/evp.h>
# include <openssl/rand.h>
# ifdef __ANDROID__
# include <android/log.h>
# endif
@ -76,6 +77,7 @@ struct chat_sync {
/* Pending incoming invites (для ask/deny) */
uint64_t pending_inv_in_ch_id [ 4 ] ;
uint64_t pending_inv_in_node_id [ 4 ] ;
uint64_t pending_inv_in_key [ 4 ] ;
int pending_inv_in_count ;
} ;
@ -1403,6 +1405,10 @@ static void cs_handle_channel_invite(struct chat_sync* cs, uint64_t peer,
/* skip inviter_update_sig/ts/userinfo for now — verify channel sig only */
p + = 64 ; uint64_t inviter_update_ts ; memcpy ( & inviter_update_ts , p , 8 ) ; p + = 8 ;
uint8_t userinfo_len = * p + + ; p + = userinfo_len ;
/* join-ключ (зарегистрирован инвайтером) — хвостовые 8 байт */
uint64_t join_key = 0 ;
if ( p + 8 > pl + len ) { DEBUG_WARN ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: CHANNEL_INVITE truncated (no join_key) from=%016llx " , CS_ID , ( unsigned long long ) peer ) ; return ; }
memcpy ( & join_key , p , 8 ) ; p + = 8 ;
/* Verify channel signature */
uint8_t vmsg [ 1024 ] ; size_t vlen = 0 ;
@ -1440,13 +1446,26 @@ static void cs_handle_channel_invite(struct chat_sync* cs, uint64_t peer,
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: CHANNEL_INVITE channel_put rc=%d ch=%s ch_x25519=%016llx " ,
CS_ID , cprc , ch_id , * ( const uint64_t * ) x25519 ) ;
chat_core_ensure_channel_ready ( cs - > inst , ch_id ) ;
/* Initiate join: connect back and send CHANNEL_INFO_REQ */
/* Initiate join: connect back and send JOIN_INFO_REQ с зарегистрированным ключом */
cs - > pending_join_key = join_key ;
chat_sync_join_channel ( cs - > inst , ch_id , peer ) ;
return ;
}
/* policy == ask — post event to GUI */
{
/* сохранить join-ключ, чтобы принять инвайт позже через chat_sync_accept_invite */
uint64_t ch_num = strtoull ( ch_id , NULL , 10 ) ;
int slot = - 1 ;
for ( int i = 0 ; i < cs - > pending_inv_in_count ; i + + )
if ( cs - > pending_inv_in_ch_id [ i ] = = ch_num & & cs - > pending_inv_in_node_id [ i ] = = peer ) { slot = i ; break ; }
if ( slot < 0 & & cs - > pending_inv_in_count < 4 ) slot = cs - > pending_inv_in_count + + ;
if ( slot > = 0 ) {
cs - > pending_inv_in_ch_id [ slot ] = ch_num ;
cs - > pending_inv_in_node_id [ slot ] = peer ;
cs - > pending_inv_in_key [ slot ] = join_key ;
}
size_t inv_name_len = 0 ; char inv_name [ 128 ] = " " ;
{ sqlite3 * vdb = cs - > inst - > topo_sqlite_db ;
sqlite3_stmt * st = NULL ;
@ -1489,6 +1508,15 @@ static int cs_send_channel_invite(struct chat_sync* cs, struct UTUN_INSTANCE* in
int ulen = member_sync_build_update_msg ( join_sig , upd_ts , juser , umsg , ( int ) sizeof ( umsg ) ) ;
if ( ulen > = 0 ) cs_ed25519_sign ( inst - > my_ed25519_privkey , umsg , ( size_t ) ulen , upd_sig ) ;
}
/* join-ключ: генерируем и регистрируем локально (инвайтер == connection-узел),
ч т о б ы д ж о й н е р с м о г п р о й т и JOIN_INFO_REQ с в а л и д н ы м к л ю ч о м . */
uint64_t join_key = 0 ;
if ( RAND_bytes ( ( uint8_t * ) & join_key , sizeof ( join_key ) ) ! = 1 | | join_key = = 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: join_key generation failed ch=%s " , CS_ID , ch_id ) ;
return - 1 ;
}
chat_join_register_key ( inst , strtoull ( ch_id , NULL , 10 ) , 0 , join_key ) ;
uint8_t buf [ 1024 ] ; size_t boff = 0 ;
buf [ boff + + ] = CS_MSG_CHANNEL_INVITE ;
uint8_t cnl = ( uint8_t ) strlen ( ch_name ) ;
@ -1508,9 +1536,10 @@ static int cs_send_channel_invite(struct chat_sync* cs, struct UTUN_INSTANCE* in
char juser [ 256 ] ; snprintf ( juser , sizeof ( juser ) , " { \" name \" : \" %s \" } " , inst - > name [ 0 ] ? inst - > name : " " ) ;
uint8_t il = ( uint8_t ) strlen ( juser ) ;
buf [ boff + + ] = il ; memcpy ( buf + boff , juser , il ) ; boff + = il ;
memcpy ( buf + boff , & join_key , 8 ) ; boff + = 8 ;
int rc = cs_send ( cs , ch_id , target_node_id , buf , boff ) ;
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: sent CHANNEL_INVITE to 0x%016llx ch=%s rc=%d " ,
CS_ID , ( unsigned long long ) target_node_id , ch_id , rc ) ;
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: sent CHANNEL_INVITE to 0x%016llx ch=%s key=%016llx rc=%d " ,
CS_ID , ( unsigned long long ) target_node_id , ch_id , ( unsigned long long ) join_key , rc ) ;
return rc ;
}
@ -1716,16 +1745,31 @@ void chat_sync_invite_to_channel_with_addrs(
/* ─── accept/deny incoming invite ─── */
void chat_sync_accept_invite ( struct UTUN_INSTANCE * inst , uint64_t channel_id , uint64_t inviter_node_id ) {
if ( ! cs_of ( inst ) | | ! inst ) return ;
struct chat_sync * cs = cs_of ( inst ) ;
if ( ! cs | | ! inst ) return ;
char ch_id [ 64 ] ; snprintf ( ch_id , sizeof ( ch_id ) , " %llu " , ( unsigned long long ) channel_id ) ;
if ( channel_id = = 0 | | inviter_node_id = = 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: accept_invite invalid params ch=%llu node=%016llx " ,
CS_ID , ( unsigned long long ) channel_id , ( unsigned long long ) inviter_node_id ) ;
return ;
}
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: accept_invite ch=%llu inviter=0x%016llx " ,
CS_ID , ( unsigned long long ) channel_id , ( unsigned long long ) inviter_node_id ) ;
/* достать join-ключ, сохранённый при приёме CHANNEL_INVITE (ask) */
uint64_t join_key = 0 ;
for ( int i = 0 ; i < cs - > pending_inv_in_count ; i + + ) {
if ( cs - > pending_inv_in_ch_id [ i ] = = channel_id & & cs - > pending_inv_in_node_id [ i ] = = inviter_node_id ) {
join_key = cs - > pending_inv_in_key [ i ] ;
break ;
}
}
if ( join_key = = 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: accept_invite no join_key for ch=%llu inviter=0x%016llx " ,
CS_ID , ( unsigned long long ) channel_id , ( unsigned long long ) inviter_node_id ) ;
return ;
}
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: accept_invite ch=%llu inviter=0x%016llx key=%016llx " ,
CS_ID , ( unsigned long long ) channel_id , ( unsigned long long ) inviter_node_id , ( unsigned long long ) join_key ) ;
chat_core_ensure_channel_ready ( inst , ch_id ) ;
cs - > pending_join_key = join_key ;
chat_sync_join_channel ( inst , ch_id , inviter_node_id ) ;
}