From 5515909c1e3481cc036c090bb66708773ddda17a Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 17 Jul 2015 10:47:21 -0700 Subject: [PATCH] Add a concept of an "instanceId" to the controller, which the OnePoint can use to determine whether it is the same running database instance it already knows. --- controller/SqliteNetworkController.cpp | 36 +++++++++++++++++++++++--- controller/SqliteNetworkController.hpp | 2 ++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index cc53d4d5e..51d5a3805 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -203,11 +203,33 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) : ||(sqlite3_prepare_v2(_db,"DELETE FROM Gateway WHERE networkId = ?",-1,&_sDeleteGateways,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"INSERT INTO Gateway (networkId,ip,ipVersion,metric) VALUES (?,?,?,?)",-1,&_sCreateGateway,(const char **)0) != SQLITE_OK) + /* Config */ + ||(sqlite3_prepare_v2(_db,"SELECT \"v\" FROM \"Config\" WHERE \"k\" = ?",-1,&_sGetConfig,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT OR REPLACE INTO \"Config\" (\"k\",\"v\") VALUES (?,?)",-1,&_sSetConfig,(const char **)0) != SQLITE_OK) + ) { //printf("!!! %s\n",sqlite3_errmsg(_db)); sqlite3_close(_db); throw std::runtime_error("SqliteNetworkController unable to initialize one or more prepared statements"); } + + /* Generate a 128-bit / 32-character "instance ID" if one isn't already + * defined. Clients can use this to determine if this is the same controller + * database they know and love. */ + sqlite3_reset(_sGetConfig); + sqlite3_bind_text(_sGetConfig,1,"instanceId",10,SQLITE_STATIC); + if (sqlite3_step(_sGetConfig) != SQLITE_ROW) { + char instanceId[32]; + for(int i=0;i<32;++i) + instanceId[i] = "0123456789abcdef"[(rand() >> 8) & 0xf]; + sqlite3_reset(_sSetConfig); + sqlite3_bind_text(_sSetConfig,1,"instanceId",10,SQLITE_STATIC); + sqlite3_bind_text(_sSetConfig,2,instanceId,32,SQLITE_STATIC); + if (sqlite3_step(_sSetConfig) != SQLITE_OK) { + sqlite3_close(_db); + throw std::runtime_error("SqliteNetworkController unable to read or initialize instanceId"); + } + } } SqliteNetworkController::~SqliteNetworkController() @@ -254,6 +276,8 @@ SqliteNetworkController::~SqliteNetworkController() sqlite3_finalize(_sDeleteGateways); sqlite3_finalize(_sCreateGateway); sqlite3_finalize(_sIncrementMemberRevisionCounter); + sqlite3_finalize(_sGetConfig); + sqlite3_finalize(_sSetConfig); sqlite3_close(_db); } } @@ -1611,10 +1635,14 @@ unsigned int SqliteNetworkController::_doCPGet( } else { // GET /controller returns status and API version if controller is supported - Utils::snprintf(json,sizeof(json),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now()); - responseBody = json; - responseContentType = "applicaiton/json"; - return 200; + sqlite3_reset(_sGetConfig); + sqlite3_bind_text(_sGetConfig,1,"instanceId",10,SQLITE_STATIC); + if (sqlite3_step(_sGetConfig) == SQLITE_ROW) { + Utils::snprintf(json,sizeof(json),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n\t\"instanceId\": \"%s\"\n}",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now(),(const char *)sqlite3_column_text(_sGetConfig,0)); + responseBody = json; + responseContentType = "applicaiton/json"; + return 200; + } else return 500; } return 404; diff --git a/controller/SqliteNetworkController.hpp b/controller/SqliteNetworkController.hpp index 90cddec07..95905bd11 100644 --- a/controller/SqliteNetworkController.hpp +++ b/controller/SqliteNetworkController.hpp @@ -138,6 +138,8 @@ private: sqlite3_stmt *_sDeleteGateways; sqlite3_stmt *_sCreateGateway; sqlite3_stmt *_sIncrementMemberRevisionCounter; + sqlite3_stmt *_sGetConfig; + sqlite3_stmt *_sSetConfig; Mutex _lock; };