@ -6,6 +6,7 @@
*/
# include "chat_core.h"
# include "chat_sync.h"
# include "db_sync.h"
# include "gui_bridge.h"
# include "topo_node_sqlite.h"
@ -312,6 +313,9 @@ void chat_core_submit_message(struct chat_msg_submit* req) {
if ( ! g_cc . initialized ) { DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTIVITY , " %s: submit before init " , CC_ID ) ; return ; }
if ( ! req ) return ;
DEBUG_INFO ( DEBUG_CATEGORY_CONNECTIVITY , " %s: SUBMIT ch=%s ct=%s len=%u " ,
CC_ID , req - > channel_id , req - > content_type , req - > data_len ) ;
struct DB_SYNC_INSTANCE * si = si_find ( req - > channel_id ) ;
if ( ! si ) { DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTIVITY , " %s: no db_sync instance for ch=%s " , CC_ID , req - > channel_id ) ; return ; }
@ -390,7 +394,7 @@ int chat_core_chain_hash_at(const char* ch_id, uint32_t pos, uint8_t* hash_out)
}
int chat_core_insert_record ( const char * ch_id , const uint8_t * rec , size_t len ) {
if ( ! g_cc . initialized | | ! rec | | len < 29 ) return - 1 ;
if ( ! g_cc . initialized | | ! rec | | len < 29 ) { DEBUG_WARN ( DEBUG_CATEGORY_CONNECTIVITY , " %s: insert_record malformed (len=%zu < 29) ch=%s " , CC_ID , len , ch_id ) ; return - 1 ; }
const uint8_t * p = rec ;
size_t rem = len ;
@ -398,16 +402,16 @@ int chat_core_insert_record(const char* ch_id, const uint8_t* rec, size_t len) {
memcpy ( & ts , p , 8 ) ; p + = 8 ; rem - = 8 ;
memcpy ( & dh , p , 8 ) ; p + = 8 ; rem - = 8 ;
memcpy ( & nid , p , 8 ) ; p + = 8 ; rem - = 8 ;
if ( rem < 1 ) return - 1 ;
if ( rem < 1 ) { DEBUG_WARN ( DEBUG_CATEGORY_CONNECTIVITY , " %s: insert_record truncated at ct_len ch=%s " , CC_ID , ch_id ) ; return - 1 ; }
uint8_t ct_len = * p ; p + + ; rem - - ;
if ( rem < ct_len ) return - 1 ;
if ( rem < ct_len ) { DEBUG_WARN ( DEBUG_CATEGORY_CONNECTIVITY , " %s: insert_record truncated at ct ch=%s " , CC_ID , ch_id ) ; return - 1 ; }
char ct_buf [ 64 ] ; memcpy ( ct_buf , p , ct_len ) ; ct_buf [ ct_len ] = ' \0 ' ;
p + = ct_len ; rem - = ct_len ;
if ( rem < 4 ) return - 1 ;
if ( rem < 4 ) { DEBUG_WARN ( DEBUG_CATEGORY_CONNECTIVITY , " %s: insert_record truncated at dlen ch=%s " , CC_ID , ch_id ) ; return - 1 ; }
uint32_t dlen ; memcpy ( & dlen , p , 4 ) ; p + = 4 ; rem - = 4 ;
if ( rem < dlen ) return - 1 ;
const uint8_t * data = p ; p + = dlen ; rem - = dlen ;
if ( rem < 32 ) return - 1 ;
if ( rem < dlen ) { DEBUG_WARN ( DEBUG_CATEGORY_CONNECTIVITY , " %s: insert_record truncated at data ch=%s " , CC_ID , ch_id ) ; return - 1 ; }
const uint8_t * r data = p ; p + = dlen ; rem - = dlen ;
if ( rem < 32 ) { DEBUG_WARN ( DEBUG_CATEGORY_CONNECTIVITY , " %s: insert_record truncated at chain_hash ch=%s " , CC_ID , ch_id ) ; return - 1 ; }
uint8_t peer_ch [ 32 ] ; memcpy ( peer_ch , p , 32 ) ;
@ -429,10 +433,10 @@ int chat_core_insert_record(const char* ch_id, const uint8_t* rec, size_t len) {
" VALUES(?,?,?,?,?,?,?,0,1) " , tbl ) ;
sqlite3_stmt * stmt = NULL ;
if ( sqlite3_prepare_v2 ( g_cc . db , sql , - 1 , & stmt , NULL ) ! = SQLITE_OK ) return - 1 ;
if ( sqlite3_prepare_v2 ( g_cc . db , sql , - 1 , & stmt , NULL ) ! = SQLITE_OK ) { DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTIVITY , " %s: insert_record prepare failed ch=%s " , CC_ID , ch_id ) ; return - 1 ; }
sqlite3_bind_int64 ( stmt , 1 , ( sqlite3_int64 ) nid ) ;
sqlite3_bind_text ( stmt , 2 , ct_buf , ct_len , SQLITE_STATIC ) ;
sqlite3_bind_blob ( stmt , 3 , data , ( int ) dlen , SQLITE_STATIC ) ;
sqlite3_bind_blob ( stmt , 3 , r data, ( int ) dlen , SQLITE_STATIC ) ;
sqlite3_bind_int64 ( stmt , 4 , ts ) ;
sqlite3_bind_int64 ( stmt , 5 , ( sqlite3_int64 ) dh ) ;
sqlite3_bind_blob ( stmt , 6 , peer_ch , 32 , SQLITE_STATIC ) ;
@ -448,6 +452,8 @@ int chat_core_insert_record(const char* ch_id, const uint8_t* rec, size_t len) {
return 0 ;
}
if ( rc = = SQLITE_CONSTRAINT ) return 1 ;
DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTIVITY , " %s: insert_record step failed rc=%d ch=%s ts=%lld dh=0x%016llx " ,
CC_ID , rc , ch_id , ( long long ) ts , ( unsigned long long ) dh ) ;
return - 1 ;
}
@ -1005,7 +1011,7 @@ static void on_db_sync_insert(struct DB_SYNC_INSTANCE* si, const char* data, siz
/* parse JSON: {"n":<uint64>,"ch":"<str>","ct":"<str>","d":"<str>"} */
const char * p = data ; const char * end = data + len ; uint64_t jn = 0 ;
{ /* "n" */
const char * n = strstr ( p , " \" n \" : " ) ; if ( ! n ) return ;
const char * n = strstr ( p , " \" n \" : " ) ; if ( ! n ) { DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTIVITY , " %s: on_db_sync_insert JSON parse fail: no ' \" n \" ' field ch=%s " , CC_ID , ch_id ) ; return ; }
n + = 4 ; jn = strtoull ( n , NULL , 0 ) ; p = n ;
}
const char * jct = " text/plain " ; size_t jct_len = 10 ;
@ -1016,7 +1022,7 @@ static void on_db_sync_insert(struct DB_SYNC_INSTANCE* si, const char* data, siz
{ /* "d" */
const char * d = strstr ( p , " \" d \" : \" " ) ; if ( d ) { d + = 5 ; const char * de = d ; while ( de < end ) { if ( * de = = ' " ' & & ( de = = d | | * ( de - 1 ) ! = ' \\ ' ) ) break ; de + + ; } if ( de < end ) { jd_start = d ; jd_len = ( size_t ) ( de - d ) ; } }
}
if ( ! jd_start ) return ;
if ( ! jd_start ) { DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTIVITY , " %s: on_db_sync_insert JSON parse fail: no ' \" d \" ' field ch=%s " , CC_ID , ch_id ) ; return ; }
uint64_t dh ; compute_datahash ( ( const uint8_t * ) jd_start , jd_len , & dh ) ;
uint64_t ts = get_time_us ( ) ;
@ -1027,7 +1033,7 @@ static void on_db_sync_insert(struct DB_SYNC_INSTANCE* si, const char* data, siz
" INSERT OR IGNORE INTO \" %s \" (node_id,content_type,data,timestamp,datahash,chain_hash,signature,is_outgoing,is_read,sync_flags) "
" VALUES(?,?,?,?,?,?,?,?,?,?) " , tbl ) ;
sqlite3_stmt * st = NULL ;
if ( sqlite3_prepare_v2 ( g_cc . db , sql , - 1 , & st , NULL ) ! = SQLITE_OK ) return ;
if ( sqlite3_prepare_v2 ( g_cc . db , sql , - 1 , & st , NULL ) ! = SQLITE_OK ) { DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTIVITY , " %s: on_db_sync_insert prepare failed ch=%s " , CC_ID , ch_id ) ; return ; }
sqlite3_bind_int64 ( st , 1 , ( sqlite3_int64 ) jn ) ;
sqlite3_bind_text ( st , 2 , jct , ( int ) jct_len , SQLITE_STATIC ) ;
sqlite3_bind_blob ( st , 3 , jd_start , ( int ) jd_len , SQLITE_STATIC ) ;
@ -1041,6 +1047,13 @@ static void on_db_sync_insert(struct DB_SYNC_INSTANCE* si, const char* data, siz
if ( rc = = SQLITE_DONE ) {
uint8_t evt [ 65 ] ; uint8_t cl = ( uint8_t ) strlen ( ch_id ) ; evt [ 0 ] = cl ; memcpy ( evt + 1 , ch_id , cl ) ;
gui_bridge_post ( GUI_EVT_MSG_RECEIVED , evt , 1 + cl ) ;
chat_sync_push ( g_cc . inst , ch_id , jn , jct , ( const uint8_t * ) jd_start , ( uint32_t ) jd_len , ts , dh ) ;
} else if ( rc = = SQLITE_CONSTRAINT ) {
DEBUG_WARN ( DEBUG_CATEGORY_CONNECTIVITY , " %s: on_db_sync_insert duplicate ch=%s ts=%lld dh=0x%016llx " ,
CC_ID , ch_id , ( long long ) ts , ( unsigned long long ) dh ) ;
} else {
DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTIVITY , " %s: on_db_sync_insert step failed rc=%d ch=%s " ,
CC_ID , rc , ch_id ) ;
}
}