@ -2,6 +2,7 @@
# include "topo_node.h"
# include "etcp_connections.h"
# include "../lib/debug_config.h"
# include "../lib/mem.h"
# include <string.h>
# include <stdio.h>
@ -248,30 +249,39 @@ int topo_node_sqlite_channel_put(sqlite3* db, const char* channel_id,
if ( ! db | | ! channel_id | | ! name | | ! x25519_pub | | ! ed25519_pub | | ! signature ) return - 1 ;
char peers_tbl [ 80 ] ; peers_table_name ( channel_id , peers_tbl , sizeof ( peers_tbl ) ) ;
char sql [ 512 ] ;
snprintf ( sql , sizeof ( sql ) ,
" CREATE TABLE IF NOT EXISTS \" %s \" ( " // таблица мемберов канала
const char * ddl_tmpl =
" CREATE TABLE IF NOT EXISTS \" %s \" ( "
" id INTEGER PRIMARY KEY AUTOINCREMENT, "
" node_id INTEGER NOT NULL UNIQUE, " // ид мембера группы
" x25519_pubkey BLOB NOT NULL, " // ключ мембера для шифрования
" ed25519_pubkey BLOB NOT NULL, " // ключ мембера для подписи
" join_sig BLOB NOT NULL, " // подпись мембера неизменяемая (при присоединении) сh_x25519_pubkey(32) || ch_ed25519_pubkey(32) || node_id(8 LE) || node_x25519_pubkey(32) || join_ts(8 LE)
" join_ts INTEGER NOT NULL, " // время присоединения
" update_sig BLOB, " // подпись мембера изменяемая join_sig(64) || update_ts(8) || userinfo (NUL-terminated)
" update_ts INTEGER DEFAULT 0, " // время подписи
" userinfo TEXT NOT NULL DEFAULT '', " // имя/метаданные узла в канале (json_flat style)
" creator_sig BLOB, " // валидация мембера админом канала
" adm_tags TEXT, " // тэги которые может менять админ (json_flat style)
" adm_tags_sig BLOB, " // подпись тэгов adm_tags (может быть подписана ключом суперадмина или админов - проверяем перебором)
" node_type INTEGER NOT NULL DEFAULT 0, " // ENUM(0-'PRIV',1-'NAT',2-'EIM-NAT',3-'PUBLIC',4-SUPERNODE) тип ноды - private (только нода подключается), nat (односторонние подключения), eim-nat (доступны подключения но надо запрашивать ip), public - на прямых ip (но может быть недоступна в чебурнетах), supernode - на прямых ip, рекомендуемая для подключения
" node_RTT INTEGER " // задержка в ms
" ) " , peers_tbl ) ;
char * err = NULL ;
sqlite3_exec ( db , sql , NULL , NULL , & err ) ;
if ( err ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_node_sqlite_channel_put peers: %s " , err ) ; sqlite3_free ( err ) ; }
snprintf ( sql , sizeof ( sql ) ,
" node_id INTEGER NOT NULL UNIQUE, "
" x25519_pubkey BLOB NOT NULL, "
" ed25519_pubkey BLOB NOT NULL, "
" join_sig BLOB NOT NULL, "
" join_ts INTEGER NOT NULL, "
" update_sig BLOB, "
" update_ts INTEGER DEFAULT 0, "
" userinfo TEXT NOT NULL DEFAULT '', "
" creator_sig BLOB, "
" adm_tags TEXT, "
" adm_tags_sig BLOB, "
" node_type INTEGER NOT NULL DEFAULT 0, "
" node_RTT INTEGER "
" ) " ;
int ddl_sz = snprintf ( NULL , 0 , ddl_tmpl , peers_tbl ) ;
char * ddl = u_malloc ( ddl_sz + 1 ) ;
if ( ddl ) {
snprintf ( ddl , ddl_sz + 1 , ddl_tmpl , peers_tbl ) ;
char * err = NULL ;
sqlite3_exec ( db , ddl , NULL , NULL , & err ) ;
if ( err ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_node_sqlite_channel_put peers: %s " , err ) ; sqlite3_free ( err ) ; }
u_free ( ddl ) ;
}
char idx_sql [ 128 ] ;
snprintf ( idx_sql , sizeof ( idx_sql ) ,
" CREATE INDEX IF NOT EXISTS \" idx_%s_type_rtt \" ON \" %s \" (node_type, node_RTT) " , peers_tbl , peers_tbl ) ;
sqlite3_exec ( db , sql , NULL , NULL , NULL ) ;
sqlite3_exec ( db , idx_ sql, NULL , NULL , NULL ) ;
sqlite3_stmt * stmt = NULL ;
if ( sqlite3_prepare_v2 ( db ,
@ -324,17 +334,24 @@ int topo_node_sqlite_member_put(sqlite3* db, const char* channel_id, uint64_t no
int topo_node_sqlite_node_update_verified ( sqlite3 * db , uint64_t node_id ,
const char * name , const uint8_t * x25519 , const uint8_t * ed25519 , uint64_t update_ts ) {
if ( ! db | | ! name | | ! x25519 | | ! ed25519 ) return - 1 ;
if ( ! db | | ! x25519 | | ! ed25519 ) return - 1 ;
sqlite3_stmt * stmt = NULL ;
if ( sqlite3_prepare_v2 ( db ,
" UPDATE nodes SET name=?, x25519_pubkey=?, ed25519_pubkey=?, update_ts=? "
" WHERE node_id=? AND (update_ts IS NULL OR update_ts < ?) " , - 1 , & stmt , NULL ) ! = SQLITE_OK ) return - 1 ;
sqlite3_bind_text ( stmt , 1 , name , - 1 , SQLITE_STATIC ) ;
sqlite3_bind_blob ( stmt , 2 , x25519 , 32 , SQLITE_STATIC ) ;
sqlite3_bind_blob ( stmt , 3 , ed25519 , 32 , SQLITE_STATIC ) ;
sqlite3_bind_int64 ( stmt , 4 , ( sqlite3_int64 ) update_ts ) ;
sqlite3_bind_int64 ( stmt , 5 , ( sqlite3_int64 ) node_id ) ;
sqlite3_bind_int64 ( stmt , 6 , ( sqlite3_int64 ) update_ts ) ;
" INSERT INTO nodes(node_id, name, x25519_pubkey, ed25519_pubkey, update_ts) "
" VALUES(?,?,?,?,?) "
" ON CONFLICT(node_id) DO UPDATE SET "
" name=CASE WHEN excluded.name IS NOT NULL AND excluded.name != '' "
" THEN excluded.name ELSE nodes.name END, "
" x25519_pubkey=excluded.x25519_pubkey, "
" ed25519_pubkey=excluded.ed25519_pubkey, "
" update_ts=CASE WHEN nodes.update_ts IS NULL OR excluded.update_ts > nodes.update_ts "
" THEN excluded.update_ts ELSE nodes.update_ts END " ,
- 1 , & stmt , NULL ) ! = SQLITE_OK ) return - 1 ;
sqlite3_bind_int64 ( stmt , 1 , ( sqlite3_int64 ) node_id ) ;
sqlite3_bind_text ( stmt , 2 , name & & name [ 0 ] ? name : " " , - 1 , SQLITE_STATIC ) ;
sqlite3_bind_blob ( stmt , 3 , x25519 , 32 , SQLITE_STATIC ) ;
sqlite3_bind_blob ( stmt , 4 , ed25519 , 32 , SQLITE_STATIC ) ;
sqlite3_bind_int64 ( stmt , 5 , ( sqlite3_int64 ) update_ts ) ;
sqlite3_step ( stmt ) ;
sqlite3_finalize ( stmt ) ;
return 0 ;
@ -584,3 +601,43 @@ int topo_node_sqlite_nodeinfo_updated(sqlite3* db, uint64_t node_id) {
( unsigned long long ) node_id , best_at , base_type ) ;
return 0 ;
}
void topo_node_sqlite_update_rtt ( sqlite3 * db , uint64_t node_id , uint16_t rtt ) {
if ( ! db ) return ;
{
sqlite3_stmt * s = NULL ;
if ( sqlite3_prepare_v2 ( db ,
" UPDATE node_addresses SET rtt=? WHERE node_id=? " ,
- 1 , & s , NULL ) = = SQLITE_OK ) {
sqlite3_bind_int ( s , 1 , ( int ) rtt ) ;
sqlite3_bind_int64 ( s , 2 , ( sqlite3_int64 ) node_id ) ;
sqlite3_step ( s ) ;
sqlite3_finalize ( s ) ;
}
}
{
sqlite3_stmt * s = NULL ;
if ( sqlite3_prepare_v2 ( db ,
" SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'peers \\ _%' ESCAPE ' \\ ' " ,
- 1 , & s , NULL ) ! = SQLITE_OK ) return ;
char sql [ 256 ] ;
while ( sqlite3_step ( s ) = = SQLITE_ROW ) {
const char * tbl = ( const char * ) sqlite3_column_text ( s , 0 ) ;
snprintf ( sql , sizeof ( sql ) ,
" UPDATE \" %s \" SET node_RTT=? WHERE node_id=? " , tbl ) ;
sqlite3_stmt * u = NULL ;
if ( sqlite3_prepare_v2 ( db , sql , - 1 , & u , NULL ) = = SQLITE_OK ) {
sqlite3_bind_int ( u , 1 , ( int ) rtt ) ;
sqlite3_bind_int64 ( u , 2 , ( sqlite3_int64 ) node_id ) ;
sqlite3_step ( u ) ; sqlite3_finalize ( u ) ;
}
}
sqlite3_finalize ( s ) ;
}
DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " sqlite_update_rtt: node=%016llx rtt=%u " ,
( unsigned long long ) node_id , ( unsigned ) rtt ) ;
}