@ -22,6 +22,9 @@
# include "../../lib/debug_config.h"
# include "../../lib/debug_config.h"
# include "../../lib/mem.h"
# include "../../lib/mem.h"
# include "../../lib/platform_compat.h"
# include "../../lib/platform_compat.h"
# ifdef UTUN_HAVE_STANDBY
# include "standby.h"
# endif
# include <string.h>
# include <string.h>
# include <sqlite3.h>
# include <sqlite3.h>
@ -46,6 +49,7 @@ struct chat_sync {
struct channel_cache * channels ;
struct channel_cache * channels ;
int channel_count ;
int channel_count ;
void * refresh_timer ;
void * refresh_timer ;
void * refresh_wait ; /* standby_wait handle (Android) */
void * info_req_timer ;
void * info_req_timer ;
void * join_timer ;
void * join_timer ;
void * sync_timer ;
void * sync_timer ;
@ -600,6 +604,13 @@ static void cs_refresh_channels(struct chat_sync* cs) {
static void refresh_timer_cb ( void * arg ) {
static void refresh_timer_cb ( void * arg ) {
( void ) arg ;
( void ) arg ;
if ( ! g_cs | | ! g_cs - > initialized ) return ;
if ( ! g_cs | | ! g_cs - > initialized ) return ;
# ifdef UTUN_HAVE_STANDBY
if ( standby_get_sleep_tb ( ) > 0 ) {
g_cs - > refresh_wait = standby_wait ( g_cs , refresh_timer_cb ) ;
return ;
}
g_cs - > refresh_wait = NULL ;
# endif
cs_refresh_channels ( g_cs ) ;
cs_refresh_channels ( g_cs ) ;
g_cs - > refresh_timer = uasync_set_timeout ( g_cs - > inst - > ua ,
g_cs - > refresh_timer = uasync_set_timeout ( g_cs - > inst - > ua ,
30u * 10000u , g_cs , refresh_timer_cb , " cs_refresh " ) ;
30u * 10000u , g_cs , refresh_timer_cb , " cs_refresh " ) ;
@ -649,6 +660,9 @@ void chat_sync_destroy(struct UTUN_INSTANCE* inst) {
etcp_unbind ( inst , ETCP_RT_ID_CHAT_SYNC ) ;
etcp_unbind ( inst , ETCP_RT_ID_CHAT_SYNC ) ;
etcp_remove_conn_status_cbk ( inst , cs_on_conn_status , NULL ) ;
etcp_remove_conn_status_cbk ( inst , cs_on_conn_status , NULL ) ;
if ( cs - > refresh_timer ) { uasync_cancel_timeout ( inst - > ua , cs - > refresh_timer ) ; cs - > refresh_timer = NULL ; }
if ( cs - > refresh_timer ) { uasync_cancel_timeout ( inst - > ua , cs - > refresh_timer ) ; cs - > refresh_timer = NULL ; }
# ifdef UTUN_HAVE_STANDBY
if ( cs - > refresh_wait ) { standby_wait_cancel ( cs - > refresh_wait ) ; cs - > refresh_wait = NULL ; }
# endif
cs_cancel_proto_timers ( cs ) ;
cs_cancel_proto_timers ( cs ) ;
for ( int i = 0 ; i < cs - > channel_count ; i + + )
for ( int i = 0 ; i < cs - > channel_count ; i + + )
@ -979,14 +993,12 @@ static void cs_handle_channel_info_req(struct chat_sync* cs, uint64_t peer,
{
{
sqlite3 * vdb = cs - > inst - > topo_sqlite_db ;
sqlite3 * vdb = cs - > inst - > topo_sqlite_db ;
if ( topo_node_sqlite_member_get_join ( vdb , ch_id , myid , my_join_sig , & my_join_ts ) ! = 0 ) {
if ( topo_node_sqlite_member_get_join ( vdb , ch_id , myid , my_join_sig , & my_join_ts ) ! = 0 ) {
uint8_t join_msg [ 256 ] ; size_t mlen = 0 ;
uint8_t join_msg [ 128 ] ;
memcpy ( join_msg + mlen , x25519 , 32 ) ; mlen + = 32 ;
memcpy ( join_msg + mlen , ed_pub , 32 ) ; mlen + = 32 ;
memcpy ( join_msg + mlen , & myid , 8 ) ; mlen + = 8 ;
memcpy ( join_msg + mlen , cs - > inst - > my_keys . public_key , 32 ) ; mlen + = 32 ;
my_join_ts = ( uint64_t ) ntp_time_get_seconds ( cs - > inst ) ;
my_join_ts = ( uint64_t ) ntp_time_get_seconds ( cs - > inst ) ;
memcpy ( join_msg + mlen , & my_join_ts , 8 ) ; mlen + = 8 ;
int jmlen = member_sync_build_join_msg ( x25519 , ed_pub , myid ,
cs_ed25519_sign ( cs - > inst - > my_ed25519_privkey , join_msg , mlen , my_join_sig ) ;
cs - > inst - > my_keys . public_key , my_join_ts ,
join_msg , ( int ) sizeof ( join_msg ) ) ;
if ( jmlen > = 0 ) cs_ed25519_sign ( cs - > inst - > my_ed25519_privkey , join_msg , ( size_t ) jmlen , my_join_sig ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: CHANNEL_INFO_RESP created NEW join_sig: myid=%016llx ts=%llu " ,
DEBUG_DEBUG ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: CHANNEL_INFO_RESP created NEW join_sig: myid=%016llx ts=%llu " ,
CS_ID , ( unsigned long long ) myid , ( unsigned long long ) my_join_ts ) ;
CS_ID , ( unsigned long long ) myid , ( unsigned long long ) my_join_ts ) ;
}
}
@ -996,12 +1008,11 @@ static void cs_handle_channel_info_req(struct chat_sync* cs, uint64_t peer,
{
{
char juser [ 256 ] ; snprintf ( juser , sizeof ( juser ) , " { \" name \" : \" %s \" } " ,
char juser [ 256 ] ; snprintf ( juser , sizeof ( juser ) , " { \" name \" : \" %s \" } " ,
cs - > inst - > name [ 0 ] ? cs - > inst - > name : " " ) ;
cs - > inst - > name [ 0 ] ? cs - > inst - > name : " " ) ;
uint8_t umsg [ 256 ] ; size_t ulen = 0 ;
memcpy ( umsg + ulen , my_join_sig , 64 ) ; ulen + = 64 ;
my_update_ts = ( uint64_t ) ntp_time_get_seconds ( cs - > inst ) ;
my_update_ts = ( uint64_t ) ntp_time_get_seconds ( cs - > inst ) ;
memcpy ( umsg + ulen , & my_update_ts , 8 ) ; ulen + = 8 ;
uint8_t umsg [ 256 ] ;
size_t jl = strlen ( juser ) ; memcpy ( umsg + ulen , juser , jl ) ; umsg [ ulen + jl ] = ' \0 ' ; ulen + = jl + 1 ;
int ulen = member_sync_build_update_msg ( my_join_sig , my_update_ts , juser ,
cs_ed25519_sign ( cs - > inst - > my_ed25519_privkey , umsg , ulen , my_update_sig ) ;
umsg , ( int ) sizeof ( umsg ) ) ;
if ( ulen > = 0 ) cs_ed25519_sign ( cs - > inst - > my_ed25519_privkey , umsg , ( size_t ) ulen , my_update_sig ) ;
}
}
uint8_t buf [ 1024 ] ; size_t boff = 0 ;
uint8_t buf [ 1024 ] ; size_t boff = 0 ;
@ -1085,48 +1096,17 @@ static void cs_handle_channel_info_resp(struct chat_sync* cs, uint64_t peer,
}
}
const uint8_t * inv_x25519 = inv_conn - > crypto_ctx . peer_public_key ;
const uint8_t * inv_x25519 = inv_conn - > crypto_ctx . peer_public_key ;
const uint8_t * inv_ed = inv_conn - > peer_ed25519_pubkey ;
const uint8_t * inv_ed = inv_conn - > peer_ed25519_pubkey ;
uint8_t ivmsg [ 256 ] ; size_t ilen = 0 ;
static const uint8_t zero_sig [ 64 ] = { 0 } ;
if ( inviter_join_sig ) memcpy ( ivmsg + ilen , inviter_join_sig , 64 ) ; else memset ( ivmsg + ilen , 0 , 64 ) ;
const uint8_t * jsig = inviter_join_sig ? inviter_join_sig : zero_sig ;
ilen + = 64 ;
uint8_t ivmsg [ 256 ] ;
memcpy ( ivmsg + ilen , & inviter_update_ts , 8 ) ; ilen + = 8 ;
int ilen = member_sync_build_update_msg ( jsig , inviter_update_ts ,
{ const char * nm = inv_userinfo [ 0 ] ? inv_userinfo : " " ;
inv_userinfo [ 0 ] ? inv_userinfo : " " ,
size_t nl2 = strlen ( nm ) ; memcpy ( ivmsg + ilen , nm , nl2 + 1 ) ; ilen + = nl2 + 1 ; }
ivmsg , ( int ) sizeof ( ivmsg ) ) ;
if ( cs_ed25519_verify ( inv_ed , ivmsg , ilen , inviter_update_sig ) ! = 0 ) {
if ( ilen < 0 | | cs_ed25519_verify ( inv_ed , ivmsg , ( size_t ) ilen , inviter_update_sig ) ! = 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: CHANNEL_INFO_RESP invalid inviter_update_sig peer=%016llx ts=%llu " ,
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: CHANNEL_INFO_RESP invalid inviter_update_sig peer=%016llx ts=%llu " ,
CS_ID , ( unsigned long long ) peer , ( unsigned long long ) inviter_update_ts ) ;
CS_ID , ( unsigned long long ) peer , ( unsigned long long ) inviter_update_ts ) ;
}
}
sqlite3 * vdb = cs - > inst - > topo_sqlite_db ;
sqlite3 * vdb = cs - > inst - > topo_sqlite_db ;
/* save inviter's address from ETCP connection */
{ DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: [ADDR_SYNC] INFO_RESP save inviter peer=%016llx " , CS_ID , ( unsigned long long ) peer ) ;
struct ETCP_LINK * lk = inv_conn - > links ;
int lk_count = 0 , lk_written = 0 ;
while ( lk ) { lk_count + + ;
if ( lk - > initialized & & lk - > remote_addr . ss_family = = AF_INET ) {
struct sockaddr_in * sin = ( struct sockaddr_in * ) & lk - > remote_addr ;
uint8_t ip [ 4 ] ; memcpy ( ip , & sin - > sin_addr , 4 ) ; uint16_t port = ntohs ( sin - > sin_port ) ;
int sock_id = lk - > conn ? ( int ) lk - > conn - > sock_id : 0 ;
char sql [ 256 ] ; snprintf ( sql , sizeof ( sql ) ,
" INSERT OR REPLACE INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id) VALUES(?,4,1,?,?,?,?) " ) ;
sqlite3_stmt * as = NULL ;
if ( sqlite3_prepare_v2 ( vdb , sql , - 1 , & as , NULL ) = = SQLITE_OK ) {
sqlite3_bind_int64 ( as , 1 , ( sqlite3_int64 ) peer ) ;
sqlite3_bind_blob ( as , 2 , ip , 4 , SQLITE_STATIC ) ;
sqlite3_bind_int ( as , 3 , port ) ;
sqlite3_bind_int ( as , 4 , addr_type_from_ip ( 4 , ip ) ) ;
sqlite3_bind_int ( as , 5 , sock_id ) ;
sqlite3_step ( as ) ; sqlite3_finalize ( as ) ;
lk_written + + ;
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: [ADDR_SYNC] INFO_RESP INSERT peer=%016llx sock=%d %d.%d.%d.%d:%d " ,
CS_ID , ( unsigned long long ) peer , sock_id , ip [ 0 ] , ip [ 1 ] , ip [ 2 ] , ip [ 3 ] , port ) ;
}
} else if ( lk - > initialized ) {
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: [ADDR_SYNC] INFO_RESP SKIP non-IPv4 link for peer=%016llx " , CS_ID , ( unsigned long long ) peer ) ;
}
lk = lk - > next ;
}
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: [ADDR_SYNC] INFO_RESP DONE peer=%016llx: %d links, %d written " ,
CS_ID , ( unsigned long long ) peer , lk_count , lk_written ) ;
}
int rc = topo_node_sqlite_member_put ( vdb , ch_id , peer , inviter_join_sig , inviter_join_ts , inviter_update_sig , inviter_update_ts , inv_x25519 , inv_ed , inv_userinfo , inviter_join_sig , NULL , NULL , 0 ) ;
int rc = topo_node_sqlite_member_put ( vdb , ch_id , peer , inviter_join_sig , inviter_join_ts , inviter_update_sig , inviter_update_ts , inv_x25519 , inv_ed , inv_userinfo , inviter_join_sig , NULL , NULL , 0 ) ;
if ( rc ! = 0 ) DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: member_put(inviter) FAILED ch=%s peer=%016llx rc=%d " , CS_ID , ch_id , ( unsigned long long ) peer , rc ) ;
if ( rc ! = 0 ) DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: member_put(inviter) FAILED ch=%s peer=%016llx rc=%d " , CS_ID , ch_id , ( unsigned long long ) peer , rc ) ;
char inv_name [ 128 ] ; json_flat_get ( inv_userinfo , " name " , inv_name , sizeof ( inv_name ) ) ;
char inv_name [ 128 ] ; json_flat_get ( inv_userinfo , " name " , inv_name , sizeof ( inv_name ) ) ;
@ -1139,14 +1119,11 @@ static void cs_handle_channel_info_resp(struct chat_sync* cs, uint64_t peer,
memcpy ( my_x25519 , cs - > inst - > my_keys . public_key , 32 ) ;
memcpy ( my_x25519 , cs - > inst - > my_keys . public_key , 32 ) ;
uint8_t join_sig [ 64 ] ; uint64_t join_ts ;
uint8_t join_sig [ 64 ] ; uint64_t join_ts ;
{
{
uint8_t msg [ 256 ] ; size_t mlen = 0 ;
uint8_t msg [ 128 ] ;
memcpy ( msg + mlen , x25519 , 32 ) ; mlen + = 32 ;
memcpy ( msg + mlen , ed_pub , 32 ) ; mlen + = 32 ;
memcpy ( msg + mlen , & myid , 8 ) ; mlen + = 8 ;
memcpy ( msg + mlen , my_x25519 , 32 ) ; mlen + = 32 ;
join_ts = ( uint64_t ) ntp_time_get_seconds ( cs - > inst ) ;
join_ts = ( uint64_t ) ntp_time_get_seconds ( cs - > inst ) ;
memcpy ( msg + mlen , & join_ts , 8 ) ; mlen + = 8 ;
int mlen = member_sync_build_join_msg ( x25519 , ed_pub , myid , my_x25519 , join_ts ,
cs_ed25519_sign ( cs - > inst - > my_ed25519_privkey , msg , mlen , join_sig ) ;
msg , ( int ) sizeof ( msg ) ) ;
if ( mlen > = 0 ) cs_ed25519_sign ( cs - > inst - > my_ed25519_privkey , msg , ( size_t ) mlen , join_sig ) ;
}
}
/* send JOIN_CHANNEL */
/* send JOIN_CHANNEL */
@ -1161,47 +1138,6 @@ static void cs_handle_channel_info_resp(struct chat_sync* cs, uint64_t peer,
cs - > inst - > name [ 0 ] ? cs - > inst - > name : " " ) ;
cs - > inst - > name [ 0 ] ? cs - > inst - > name : " " ) ;
uint8_t nml = ( uint8_t ) strlen ( juser2 ) ;
uint8_t nml = ( uint8_t ) strlen ( juser2 ) ;
jbuf [ joff + + ] = nml ; memcpy ( jbuf + joff , juser2 , nml ) ; joff + = nml ;
jbuf [ joff + + ] = nml ; memcpy ( jbuf + joff , juser2 , nml ) ; joff + = nml ;
/* add local addresses */
uint8_t addr_cnt = 0 ; size_t ac_pos = joff ;
jbuf [ joff + + ] = 0 ;
struct ETCP_SOCKET * sock = cs - > inst - > etcp_sockets ;
while ( sock & & addr_cnt < 255 ) {
struct sockaddr_storage * sa = NULL ;
if ( sock - > nat_addr . ss_family ) {
sa = & sock - > nat_addr ;
int is_zero = 0 ;
if ( sa - > ss_family = = AF_INET ) { if ( ( ( struct sockaddr_in * ) sa ) - > sin_addr . s_addr = = 0 ) is_zero = 1 ; }
else { static const uint8_t z [ 16 ] ; if ( ! memcmp ( & ( ( struct sockaddr_in6 * ) sa ) - > sin6_addr , z , 16 ) ) is_zero = 1 ; }
if ( is_zero ) sa = NULL ;
}
if ( ! sa & & sock - > interface_addr . ss_family ) sa = & sock - > interface_addr ;
if ( ! sa ) { sock = sock - > next ; continue ; }
if ( sa - > ss_family = = AF_INET ) {
struct sockaddr_in * sin = ( struct sockaddr_in * ) sa ;
if ( joff + 9 > sizeof ( jbuf ) ) break ;
jbuf [ joff + + ] = 4 ;
jbuf [ joff + + ] = sock - > sock_id ;
jbuf [ joff + + ] = 1 ;
memcpy ( jbuf + joff , & sin - > sin_addr , 4 ) ; joff + = 4 ;
uint16_t p = ntohs ( sin - > sin_port ) ;
jbuf [ joff + + ] = ( uint8_t ) ( ( p > > 8 ) & 0xFF ) ;
jbuf [ joff + + ] = ( uint8_t ) ( p & 0xFF ) ;
addr_cnt + + ;
} else if ( sa - > ss_family = = AF_INET6 ) {
struct sockaddr_in6 * sin6 = ( struct sockaddr_in6 * ) sa ;
if ( joff + 21 > sizeof ( jbuf ) ) break ;
jbuf [ joff + + ] = 6 ;
jbuf [ joff + + ] = sock - > sock_id ;
jbuf [ joff + + ] = 1 ;
memcpy ( jbuf + joff , & sin6 - > sin6_addr , 16 ) ; joff + = 16 ;
uint16_t p = ntohs ( sin6 - > sin6_port ) ;
jbuf [ joff + + ] = ( uint8_t ) ( ( p > > 8 ) & 0xFF ) ;
jbuf [ joff + + ] = ( uint8_t ) ( p & 0xFF ) ;
addr_cnt + + ;
}
sock = sock - > next ;
}
jbuf [ ac_pos ] = addr_cnt ;
cs_send ( cs , ch_id , peer , jbuf , joff ) ;
cs_send ( cs , ch_id , peer , jbuf , joff ) ;
cs - > join_timer = uasync_set_timeout ( cs - > inst - > ua ,
cs - > join_timer = uasync_set_timeout ( cs - > inst - > ua ,
CS_JOIN_TIMEOUT_MS * 10 , cs , cs_join_timeout_cb , " cs_join " ) ;
CS_JOIN_TIMEOUT_MS * 10 , cs , cs_join_timeout_cb , " cs_join " ) ;
@ -1211,7 +1147,7 @@ static void cs_handle_channel_info_resp(struct chat_sync* cs, uint64_t peer,
static void cs_handle_channel_join ( struct chat_sync * cs , uint64_t peer ,
static void cs_handle_channel_join ( struct chat_sync * cs , uint64_t peer ,
const char * ch_id , const uint8_t * pl , size_t len ) {
const char * ch_id , const uint8_t * pl , size_t len ) {
if ( len < 8 + 32 + 32 + 64 + 8 + 1 + 1 ) { DEBUG_WARN ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: CHANNEL_JOIN too short len=%zu peer=%016llx " , CS_ID , len , ( unsigned long long ) peer ) ; return ; }
if ( len < 8 + 32 + 32 + 64 + 8 + 1 ) { DEBUG_WARN ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: CHANNEL_JOIN too short len=%zu peer=%016llx " , CS_ID , len , ( unsigned long long ) peer ) ; return ; }
const uint8_t * p = pl ;
const uint8_t * p = pl ;
uint64_t node_id ; memcpy ( & node_id , p , 8 ) ; p + = 8 ;
uint64_t node_id ; memcpy ( & node_id , p , 8 ) ; p + = 8 ;
DEBUG_TRACE ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: JOIN ch=%s node=%016llx from=%016llx " , CS_ID , ch_id , ( unsigned long long ) node_id , ( unsigned long long ) peer ) ;
DEBUG_TRACE ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: JOIN ch=%s node=%016llx from=%016llx " , CS_ID , ch_id , ( unsigned long long ) node_id , ( unsigned long long ) peer ) ;
@ -1222,7 +1158,6 @@ static void cs_handle_channel_join(struct chat_sync* cs, uint64_t peer,
uint8_t userinfo_len = * p + + ;
uint8_t userinfo_len = * p + + ;
char joiner_userinfo [ 128 ] = " " ;
char joiner_userinfo [ 128 ] = " " ;
if ( p + userinfo_len < = pl + len ) { memcpy ( joiner_userinfo , p , userinfo_len ) ; joiner_userinfo [ userinfo_len ] = ' \0 ' ; p + = userinfo_len ; }
if ( p + userinfo_len < = pl + len ) { memcpy ( joiner_userinfo , p , userinfo_len ) ; joiner_userinfo [ userinfo_len ] = ' \0 ' ; p + = userinfo_len ; }
uint8_t addr_cnt = * p + + ;
/* verify join_sig */
/* verify join_sig */
uint8_t ch_x25519 [ 32 ] , ch_ed25519 [ 32 ] ;
uint8_t ch_x25519 [ 32 ] , ch_ed25519 [ 32 ] ;
@ -1231,13 +1166,10 @@ static void cs_handle_channel_join(struct chat_sync* cs, uint64_t peer,
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: JOIN channel not in DB ch=%s " , CS_ID , ch_id ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: JOIN channel not in DB ch=%s " , CS_ID , ch_id ) ;
return ;
return ;
}
}
uint8_t vmsg [ 256 ] ; size_t vlen = 0 ;
uint8_t vmsg [ 128 ] ;
memcpy ( vmsg + vlen , ch_x25519 , 32 ) ; vlen + = 32 ;
int vlen = member_sync_build_join_msg ( ch_x25519 , ch_ed25519 , node_id , x25519 , join_ts ,
memcpy ( vmsg + vlen , ch_ed25519 , 32 ) ; vlen + = 32 ;
vmsg , ( int ) sizeof ( vmsg ) ) ;
memcpy ( vmsg + vlen , & node_id , 8 ) ; vlen + = 8 ;
if ( vlen < 0 | | cs_ed25519_verify ( ed_pub , vmsg , ( size_t ) vlen , join_sig ) ! = 0 ) {
memcpy ( vmsg + vlen , x25519 , 32 ) ; vlen + = 32 ;
memcpy ( vmsg + vlen , & join_ts , 8 ) ; vlen + = 8 ;
if ( cs_ed25519_verify ( ed_pub , vmsg , vlen , join_sig ) ! = 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: JOIN invalid sig node=0x%016llx ch=%s — signed(node=%016llx x25519=%016llx ed=%016llx ts=%llu) " , CS_ID ,
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: JOIN invalid sig node=0x%016llx ch=%s — signed(node=%016llx x25519=%016llx ed=%016llx ts=%llu) " , CS_ID ,
( unsigned long long ) node_id , ch_id ,
( unsigned long long ) node_id , ch_id ,
( unsigned long long ) node_id , * ( const uint64_t * ) x25519 , * ( const uint64_t * ) ed_pub , ( unsigned long long ) join_ts ) ;
( unsigned long long ) node_id , * ( const uint64_t * ) x25519 , * ( const uint64_t * ) ed_pub , ( unsigned long long ) join_ts ) ;
@ -1250,40 +1182,6 @@ static void cs_handle_channel_join(struct chat_sync* cs, uint64_t peer,
{ char j_name [ 128 ] ; json_flat_get ( joiner_userinfo , " name " , j_name , sizeof ( j_name ) ) ;
{ char j_name [ 128 ] ; json_flat_get ( joiner_userinfo , " name " , j_name , sizeof ( j_name ) ) ;
topo_node_sqlite_node_update_verified ( db , node_id , j_name , x25519 , ed_pub , join_ts , ntp_time_get_seconds ( cs - > inst ) ) ; }
topo_node_sqlite_node_update_verified ( db , node_id , j_name , x25519 , ed_pub , join_ts , ntp_time_get_seconds ( cs - > inst ) ) ; }
/* save/update node addresses */
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: [ADDR_SYNC] JOIN save addrs node=0x%016llx addr_cnt=%d " , CS_ID , ( unsigned long long ) node_id , addr_cnt ) ;
for ( uint8_t i = 0 ; i < addr_cnt & & p + 2 < = pl + len ; i + + ) {
uint8_t fm = * p + + ;
uint8_t sid = * p + + ;
uint8_t proto = * p + + ;
int ip_len = ( fm = = 4 ) ? 4 : 16 ;
if ( p + ip_len + 2 > pl + len ) { DEBUG_WARN ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: JOIN addr truncated node=0x%016llx fm=%u i=%u " , CS_ID , ( unsigned long long ) node_id , fm , i ) ; break ; }
const uint8_t * ip = p ; p + = ip_len ;
uint16_t port = ( ( uint16_t ) p [ 0 ] < < 8 ) | p [ 1 ] ; p + = 2 ;
char sql [ 256 ] ; snprintf ( sql , sizeof ( sql ) ,
" INSERT OR REPLACE INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id) "
" VALUES(?,?,?,?,?,?,?) " ) ;
sqlite3_stmt * stmt = NULL ;
if ( sqlite3_prepare_v2 ( db , sql , - 1 , & stmt , NULL ) = = SQLITE_OK ) {
sqlite3_bind_int64 ( stmt , 1 , ( sqlite3_int64 ) node_id ) ;
sqlite3_bind_int ( stmt , 2 , fm ) ;
sqlite3_bind_int ( stmt , 3 , ( int ) proto ) ;
sqlite3_bind_blob ( stmt , 4 , ip , ip_len , SQLITE_STATIC ) ;
sqlite3_bind_int ( stmt , 5 , ( int ) port ) ;
sqlite3_bind_int ( stmt , 6 , addr_type_from_ip ( fm , ip ) ) ;
sqlite3_bind_int ( stmt , 7 , ( int ) sid ) ;
sqlite3_step ( stmt ) ; sqlite3_finalize ( stmt ) ;
}
if ( fm = = 4 )
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: [ADDR_SYNC] JOIN INSERT node=0x%016llx sock=%d %d.%d.%d.%d:%d " ,
CS_ID , ( unsigned long long ) node_id , sid , ip [ 0 ] , ip [ 1 ] , ip [ 2 ] , ip [ 3 ] , port ) ;
else
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: [ADDR_SYNC] JOIN INSERT v6 node=0x%016llx sock=%d port=%d " ,
CS_ID , ( unsigned long long ) node_id , sid , port ) ;
}
/* build WELCOME with all current peers */
/* build WELCOME with all current peers */
uint8_t wbuf [ 8192 ] ;
uint8_t wbuf [ 8192 ] ;
{
{
@ -1309,12 +1207,6 @@ static void cs_handle_channel_join(struct chat_sync* cs, uint64_t peer,
memcpy ( ubuf + uoff , & join_ts , 8 ) ; uoff + = 8 ;
memcpy ( ubuf + uoff , & join_ts , 8 ) ; uoff + = 8 ;
ubuf [ uoff + + ] = userinfo_len ;
ubuf [ uoff + + ] = userinfo_len ;
memcpy ( ubuf + uoff , joiner_userinfo , userinfo_len ) ; uoff + = userinfo_len ;
memcpy ( ubuf + uoff , joiner_userinfo , userinfo_len ) ; uoff + = userinfo_len ;
ubuf [ uoff + + ] = addr_cnt ;
size_t addr_data_sz = ( size_t ) ( p - ( pl + 8 + 32 + 32 + 64 + 8 + 1 + userinfo_len + 1 ) ) ;
if ( uoff + addr_data_sz < = sizeof ( ubuf ) ) {
memcpy ( ubuf + uoff , pl + 8 + 32 + 32 + 64 + 8 + 1 + userinfo_len + 1 , addr_data_sz ) ;
uoff + = addr_data_sz ;
}
cs_propagate ( cs , ch_id , peer , ubuf , uoff ) ;
cs_propagate ( cs , ch_id , peer , ubuf , uoff ) ;
}
}
@ -1352,8 +1244,8 @@ static void cs_handle_channel_join(struct chat_sync* cs, uint64_t peer,
if ( cs - > invite_send_timer ) { uasync_cancel_timeout ( cs - > inst - > ua , cs - > invite_send_timer ) ; cs - > invite_send_timer = NULL ; }
if ( cs - > invite_send_timer ) { uasync_cancel_timeout ( cs - > inst - > ua , cs - > invite_send_timer ) ; cs - > invite_send_timer = NULL ; }
}
}
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: JOIN accepted node=0x%016llx ch=%s addrs=%d " ,
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: JOIN accepted node=0x%016llx ch=%s " ,
CS_ID , ( unsigned long long ) node_id , ch_id , addr_cnt ) ;
CS_ID , ( unsigned long long ) node_id , ch_id ) ;
}
}
/* ─── WELCOME (0x0C): inviter → joiner with full peer list ─── */
/* ─── WELCOME (0x0C): inviter → joiner with full peer list ─── */
@ -1369,7 +1261,7 @@ static void cs_handle_welcome(struct chat_sync* cs, uint64_t peer,
uint16_t pc ; memcpy ( & pc , p , 2 ) ; p + = 2 ;
uint16_t pc ; memcpy ( & pc , p , 2 ) ; p + = 2 ;
DEBUG_TRACE ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: WELCOME ch=%s from=%016llx peers=%u " , CS_ID , ch_id , ( unsigned long long ) peer , pc ) ;
DEBUG_TRACE ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: WELCOME ch=%s from=%016llx peers=%u " , CS_ID , ch_id , ( unsigned long long ) peer , pc ) ;
for ( uint16_t i = 0 ; i < pc ; i + + ) {
for ( uint16_t i = 0 ; i < pc ; i + + ) {
if ( ( size_t ) ( p - pl ) + 8 + 32 + 32 + 1 + 64 + 8 + 1 > len ) { DEBUG_WARN ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: WELCOME peer[%u] truncated at %td len=%zu " , CS_ID , i , p - pl , len ) ; break ; } /* min: id+x25519+ed+flags+update_sig(64+8)+nl+ac */
if ( ( size_t ) ( p - pl ) + 8 + 32 + 32 + 1 + 64 + 8 + 1 + 1 + 64 > len ) { DEBUG_WARN ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: WELCOME peer[%u] truncated at %td len=%zu " , CS_ID , i , p - pl , len ) ; break ; } /* min: id+x25519+ed+flags+update_sig(64+8)+nl+atl+adm_tags_sig(64) */
uint64_t node_id ; memcpy ( & node_id , p , 8 ) ; p + = 8 ;
uint64_t node_id ; memcpy ( & node_id , p , 8 ) ; p + = 8 ;
const uint8_t * x25519 = p ; p + = 32 ;
const uint8_t * x25519 = p ; p + = 32 ;
const uint8_t * ed_pub = p ; p + = 32 ;
const uint8_t * ed_pub = p ; p + = 32 ;
@ -1386,7 +1278,6 @@ static void cs_handle_welcome(struct chat_sync* cs, uint64_t peer,
uint8_t nl = * p + + ;
uint8_t nl = * p + + ;
char peer_userinfo [ 256 ] = " " ;
char peer_userinfo [ 256 ] = " " ;
if ( nl & & p + nl < = pl + len ) { memcpy ( peer_userinfo , p , nl ) ; peer_userinfo [ nl ] = ' \0 ' ; p + = nl ; }
if ( nl & & p + nl < = pl + len ) { memcpy ( peer_userinfo , p , nl ) ; peer_userinfo [ nl ] = ' \0 ' ; p + = nl ; }
uint8_t ac = * p + + ;
uint8_t atl = * p + + ;
uint8_t atl = * p + + ;
if ( atl > 0 & & p + atl < = pl + len ) p + = atl ;
if ( atl > 0 & & p + atl < = pl + len ) p + = atl ;
p + = 64 ; /* adm_tags_sig */
p + = 64 ; /* adm_tags_sig */
@ -1400,25 +1291,12 @@ static void cs_handle_welcome(struct chat_sync* cs, uint64_t peer,
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: WELCOME channel not in DB ch=%s " , CS_ID , ch_id ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: WELCOME channel not in DB ch=%s " , CS_ID , ch_id ) ;
continue ;
continue ;
}
}
uint8_t vmsg [ 256 ] ; size_t vlen = 0 ;
uint8_t vmsg [ 128 ] ;
memcpy ( vmsg + vlen , ch_x2 , 32 ) ; vlen + = 32 ;
int vlen = member_sync_build_join_msg ( ch_x2 , ch_ed2 , node_id , x25519 , join_ts ,
memcpy ( vmsg + vlen , ch_ed2 , 32 ) ; vlen + = 32 ;
vmsg , ( int ) sizeof ( vmsg ) ) ;
memcpy ( vmsg + vlen , & node_id , 8 ) ; vlen + = 8 ;
if ( vlen < 0 | | cs_ed25519_verify ( ed_pub , vmsg , ( size_t ) vlen , join_sig ) ! = 0 ) {
memcpy ( vmsg + vlen , x25519 , 32 ) ; vlen + = 32 ;
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: WELCOME invalid join_sig node=0x%016llx — skipping " , CS_ID , ( unsigned long long ) node_id ) ;
memcpy ( vmsg + vlen , & join_ts , 8 ) ; vlen + = 8 ;
continue ;
EVP_PKEY * pkey = EVP_PKEY_new_raw_public_key ( EVP_PKEY_ED25519 , NULL , ed_pub , 32 ) ;
if ( pkey ) {
EVP_MD_CTX * ver = EVP_MD_CTX_new ( ) ;
if ( ver ) {
if ( EVP_DigestVerifyInit ( ver , NULL , NULL , NULL , pkey ) ! = 1
| | EVP_DigestVerify ( ver , join_sig , 64 , vmsg , vlen ) ! = 1 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: WELCOME invalid join_sig node=0x%016llx — skipping " , CS_ID , ( unsigned long long ) node_id ) ;
EVP_MD_CTX_free ( ver ) ; EVP_PKEY_free ( pkey ) ;
continue ;
}
EVP_MD_CTX_free ( ver ) ;
}
EVP_PKEY_free ( pkey ) ;
}
}
}
}
@ -1427,40 +1305,6 @@ static void cs_handle_welcome(struct chat_sync* cs, uint64_t peer,
{ char pn [ 256 ] ; json_flat_get ( peer_userinfo , " name " , pn , sizeof ( pn ) ) ;
{ char pn [ 256 ] ; json_flat_get ( peer_userinfo , " name " , pn , sizeof ( pn ) ) ;
topo_node_sqlite_node_update_verified ( db , node_id , pn , x25519 , ed_pub , join_ts , ntp_time_get_seconds ( cs - > inst ) ) ; }
topo_node_sqlite_node_update_verified ( db , node_id , pn , x25519 , ed_pub , join_ts , ntp_time_get_seconds ( cs - > inst ) ) ; }
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: [ADDR_SYNC] WELCOME save addrs node=0x%016llx ac=%d " , CS_ID , ( unsigned long long ) node_id , ac ) ;
for ( uint8_t j = 0 ; j < ac ; j + + ) {
if ( p + 2 > pl + len ) { DEBUG_WARN ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: WELCOME addr[%u] header truncated node=0x%016llx " , CS_ID , j , ( unsigned long long ) node_id ) ; break ; }
uint8_t fm = * p + + ;
uint8_t sid = * p + + ;
uint8_t proto = * p + + ;
int ip_len = ( fm = = 4 ) ? 4 : 16 ;
if ( p + ip_len + 2 > pl + len ) { DEBUG_WARN ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: WELCOME addr[%u] ip truncated node=0x%016llx fm=%u " , CS_ID , j , ( unsigned long long ) node_id , fm ) ; break ; }
const uint8_t * ip = p ; p + = ip_len ;
uint16_t port = ( ( uint16_t ) p [ 0 ] < < 8 ) | p [ 1 ] ; p + = 2 ;
char sql [ 256 ] ; snprintf ( sql , sizeof ( sql ) ,
" INSERT OR REPLACE INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id) "
" VALUES(?,?,?,?,?,?,?) " ) ;
sqlite3_stmt * stmt2 = NULL ;
if ( sqlite3_prepare_v2 ( db , sql , - 1 , & stmt2 , NULL ) = = SQLITE_OK ) {
sqlite3_bind_int64 ( stmt2 , 1 , ( sqlite3_int64 ) node_id ) ;
sqlite3_bind_int ( stmt2 , 2 , fm ) ;
sqlite3_bind_int ( stmt2 , 3 , ( int ) proto ) ;
sqlite3_bind_blob ( stmt2 , 4 , ip , ip_len , SQLITE_STATIC ) ;
sqlite3_bind_int ( stmt2 , 5 , ( int ) port ) ;
sqlite3_bind_int ( stmt2 , 6 , addr_type_from_ip ( fm , ip ) ) ;
sqlite3_bind_int ( stmt2 , 7 , ( int ) sid ) ;
sqlite3_step ( stmt2 ) ; sqlite3_finalize ( stmt2 ) ;
}
if ( fm = = 4 )
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: [ADDR_SYNC] WELCOME INSERT node=0x%016llx sock=%d %d.%d.%d.%d:%d " ,
CS_ID , ( unsigned long long ) node_id , sid , ip [ 0 ] , ip [ 1 ] , ip [ 2 ] , ip [ 3 ] , port ) ;
else
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: [ADDR_SYNC] WELCOME INSERT v6 node=0x%016llx sock=%d port=%d " ,
CS_ID , ( unsigned long long ) node_id , sid , port ) ;
}
member_sync_cancel ( g_cs - > inst , node_id , ch_id ) ;
member_sync_cancel ( g_cs - > inst , node_id , ch_id ) ;
}
}
@ -1520,7 +1364,7 @@ static void cs_handle_welcome(struct chat_sync* cs, uint64_t peer,
static void cs_handle_peer_upsert ( struct chat_sync * cs , uint64_t peer ,
static void cs_handle_peer_upsert ( struct chat_sync * cs , uint64_t peer ,
const char * ch_id , const uint8_t * pl , size_t len ) {
const char * ch_id , const uint8_t * pl , size_t len ) {
if ( len < 8 + 32 + 32 + 64 + 8 + 1 + 1 + 1 ) { DEBUG_WARN ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: PEER_UPSERT too short len=%zu " , CS_ID , len ) ; return ; }
if ( len < 8 + 32 + 32 + 64 + 8 + 1 ) { DEBUG_WARN ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: PEER_UPSERT too short len=%zu " , CS_ID , len ) ; return ; }
const uint8_t * p = pl ;
const uint8_t * p = pl ;
uint64_t node_id ; memcpy ( & node_id , p , 8 ) ; p + = 8 ;
uint64_t node_id ; memcpy ( & node_id , p , 8 ) ; p + = 8 ;
const uint8_t * x25519 = p ; p + = 32 ;
const uint8_t * x25519 = p ; p + = 32 ;
@ -1530,7 +1374,6 @@ static void cs_handle_peer_upsert(struct chat_sync* cs, uint64_t peer,
uint8_t userinfo_len = * p + + ;
uint8_t userinfo_len = * p + + ;
char peer_userinfo [ 128 ] = " " ;
char peer_userinfo [ 128 ] = " " ;
if ( p + userinfo_len < = pl + len ) { memcpy ( peer_userinfo , p , userinfo_len ) ; peer_userinfo [ userinfo_len ] = ' \0 ' ; p + = userinfo_len ; }
if ( p + userinfo_len < = pl + len ) { memcpy ( peer_userinfo , p , userinfo_len ) ; peer_userinfo [ userinfo_len ] = ' \0 ' ; p + = userinfo_len ; }
uint8_t ac = * p + + ;
/* verify join_sig */
/* verify join_sig */
uint8_t ch_x3 [ 32 ] , ch_ed3 [ 32 ] ;
uint8_t ch_x3 [ 32 ] , ch_ed3 [ 32 ] ;
@ -1539,13 +1382,10 @@ static void cs_handle_peer_upsert(struct chat_sync* cs, uint64_t peer,
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: PEER_UPSERT channel not in DB ch=%s " , CS_ID , ch_id ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: PEER_UPSERT channel not in DB ch=%s " , CS_ID , ch_id ) ;
return ;
return ;
}
}
uint8_t vmsg [ 256 ] ; size_t vlen = 0 ;
uint8_t vmsg [ 128 ] ;
memcpy ( vmsg + vlen , ch_x3 , 32 ) ; vlen + = 32 ;
int vlen = member_sync_build_join_msg ( ch_x3 , ch_ed3 , node_id , x25519 , join_ts ,
memcpy ( vmsg + vlen , ch_ed3 , 32 ) ; vlen + = 32 ;
vmsg , ( int ) sizeof ( vmsg ) ) ;
memcpy ( vmsg + vlen , & node_id , 8 ) ; vlen + = 8 ;
if ( vlen < 0 | | cs_ed25519_verify ( ed_pub , vmsg , ( size_t ) vlen , join_sig ) ! = 0 ) {
memcpy ( vmsg + vlen , x25519 , 32 ) ; vlen + = 32 ;
memcpy ( vmsg + vlen , & join_ts , 8 ) ; vlen + = 8 ;
if ( cs_ed25519_verify ( ed_pub , vmsg , vlen , join_sig ) ! = 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: PEER_UPSERT invalid sig node=0x%016llx " , CS_ID ,
DEBUG_ERROR ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: PEER_UPSERT invalid sig node=0x%016llx " , CS_ID ,
( unsigned long long ) node_id ) ;
( unsigned long long ) node_id ) ;
return ;
return ;
@ -1558,40 +1398,6 @@ static void cs_handle_peer_upsert(struct chat_sync* cs, uint64_t peer,
{ char pn2 [ 128 ] ; json_flat_get ( peer_userinfo , " name " , pn2 , sizeof ( pn2 ) ) ;
{ char pn2 [ 128 ] ; json_flat_get ( peer_userinfo , " name " , pn2 , sizeof ( pn2 ) ) ;
topo_node_sqlite_node_update_verified ( db , node_id , pn2 , x25519 , ed_pub , join_ts , ntp_time_get_seconds ( cs - > inst ) ) ; }
topo_node_sqlite_node_update_verified ( db , node_id , pn2 , x25519 , ed_pub , join_ts , ntp_time_get_seconds ( cs - > inst ) ) ; }
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: [ADDR_SYNC] PEER_UPSERT save addrs node=0x%016llx ac=%d " , CS_ID , ( unsigned long long ) node_id , ac ) ;
for ( uint8_t i = 0 ; i < ac ; i + + ) {
if ( p + 2 > pl + len ) { DEBUG_WARN ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: PEER_UPSERT addr[%u] header truncated node=0x%016llx " , CS_ID , i , ( unsigned long long ) node_id ) ; break ; }
uint8_t fm = * p + + ;
uint8_t sid = * p + + ;
uint8_t proto = * p + + ;
int ip_len = ( fm = = 4 ) ? 4 : 16 ;
if ( p + ip_len + 2 > pl + len ) { DEBUG_WARN ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: PEER_UPSERT addr[%u] ip truncated node=0x%016llx fm=%u " , CS_ID , i , ( unsigned long long ) node_id , fm ) ; break ; }
const uint8_t * ip = p ; p + = ip_len ;
uint16_t port = ( ( uint16_t ) p [ 0 ] < < 8 ) | p [ 1 ] ; p + = 2 ;
char sql [ 256 ] ; snprintf ( sql , sizeof ( sql ) ,
" INSERT OR REPLACE INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id) "
" VALUES(?,?,?,?,?,?,?) " ) ;
sqlite3_stmt * stmt = NULL ;
if ( sqlite3_prepare_v2 ( db , sql , - 1 , & stmt , NULL ) = = SQLITE_OK ) {
sqlite3_bind_int64 ( stmt , 1 , ( sqlite3_int64 ) node_id ) ;
sqlite3_bind_int ( stmt , 2 , fm ) ;
sqlite3_bind_int ( stmt , 3 , ( int ) proto ) ;
sqlite3_bind_blob ( stmt , 4 , ip , ip_len , SQLITE_STATIC ) ;
sqlite3_bind_int ( stmt , 5 , ( int ) port ) ;
sqlite3_bind_int ( stmt , 6 , addr_type_from_ip ( fm , ip ) ) ;
sqlite3_bind_int ( stmt , 7 , ( int ) sid ) ;
sqlite3_step ( stmt ) ; sqlite3_finalize ( stmt ) ;
}
if ( fm = = 4 )
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: [ADDR_SYNC] PEER_UPSERT INSERT node=0x%016llx sock=%d %d.%d.%d.%d:%d " ,
CS_ID , ( unsigned long long ) node_id , sid , ip [ 0 ] , ip [ 1 ] , ip [ 2 ] , ip [ 3 ] , port ) ;
else
DEBUG_INFO ( DEBUG_CATEGORY_MEMBER_SYNC , " %s: [ADDR_SYNC] PEER_UPSERT INSERT v6 node=0x%016llx sock=%d port=%d " ,
CS_ID , ( unsigned long long ) node_id , sid , port ) ;
}
cs_refresh_channels ( cs ) ;
cs_refresh_channels ( cs ) ;
{ uint8_t mevt [ 1 + 64 + 1 + CHAT_MEMBER_DISPLAY_SIZE ] ; uint8_t ml = ( uint8_t ) strlen ( ch_id ) ;
{ uint8_t mevt [ 1 + 64 + 1 + CHAT_MEMBER_DISPLAY_SIZE ] ; uint8_t ml = ( uint8_t ) strlen ( ch_id ) ;
@ -1735,11 +1541,9 @@ static int cs_send_channel_invite(struct chat_sync* cs, struct UTUN_INSTANCE* in
uint8_t upd_sig [ 64 ] = { 0 } ; uint64_t upd_ts = ( uint64_t ) ntp_time_get_seconds ( inst ) ;
uint8_t upd_sig [ 64 ] = { 0 } ; uint64_t upd_ts = ( uint64_t ) ntp_time_get_seconds ( inst ) ;
{
{
char juser [ 256 ] ; snprintf ( juser , sizeof ( juser ) , " { \" name \" : \" %s \" } " , inst - > name [ 0 ] ? inst - > name : " " ) ;
char juser [ 256 ] ; snprintf ( juser , sizeof ( juser ) , " { \" name \" : \" %s \" } " , inst - > name [ 0 ] ? inst - > name : " " ) ;
uint8_t umsg [ 256 ] ; size_t ulen = 0 ;
uint8_t umsg [ 256 ] ;
memcpy ( umsg + ulen , join_sig , 64 ) ; ulen + = 64 ;
int ulen = member_sync_build_update_msg ( join_sig , upd_ts , juser , umsg , ( int ) sizeof ( umsg ) ) ;
memcpy ( umsg + ulen , & upd_ts , 8 ) ; ulen + = 8 ;
if ( ulen > = 0 ) cs_ed25519_sign ( inst - > my_ed25519_privkey , umsg , ( size_t ) ulen , upd_sig ) ;
size_t jl = strlen ( juser ) ; memcpy ( umsg + ulen , juser , jl ) ; umsg [ ulen + jl ] = ' \0 ' ; ulen + = jl + 1 ;
cs_ed25519_sign ( inst - > my_ed25519_privkey , umsg , ulen , upd_sig ) ;
}
}
uint8_t buf [ 1024 ] ; size_t boff = 0 ;
uint8_t buf [ 1024 ] ; size_t boff = 0 ;
buf [ boff + + ] = CS_MSG_CHANNEL_INVITE ;
buf [ boff + + ] = CS_MSG_CHANNEL_INVITE ;