#include #include #include #include #include #include #include #include "controller_dbo.h" #include "globals.h" controller_dbo::~controller_dbo() { if(this->relays) { relay_dbo::free_list(this->relays); } } static bool controller_db_update_insert(controller_dbo *controller, sqlite3_stmt *stmt) { int rc; sqlite3_bind_blob(stmt, 1, controller->id, sizeof(uuid_t), SQLITE_STATIC); sqlite3_bind_text(stmt, 2, controller->name, -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 3, controller->ip, -1, SQLITE_STATIC); sqlite3_bind_int(stmt, 4, controller->active); sqlite3_bind_int(stmt, 5, controller->port); sqlite3_bind_int(stmt, 6, controller->relay_count); sqlite3_bind_text(stmt, 7, controller->tag, -1, SQLITE_STATIC); rc = sqlite3_step(stmt); if (rc != SQLITE_DONE) { printf("ERROR inserting data: %s\n", sqlite3_errmsg(globals::db)); return false; } sqlite3_finalize(stmt); return true; } static controller_dbo* controller_db_select_mapper(sqlite3_stmt *stmt) { auto *new_controller = new controller_dbo(); const char* new_tag; for(int i = 0; i < sqlite3_column_count(stmt); i++) { const char *name = sqlite3_column_name(stmt, i); switch(name[0]) { case 'a': // active new_controller->active = (bool)sqlite3_column_int(stmt, i); break; case 'i': switch(name[1]) { case 'd': // id uuid_copy(new_controller->id, (const unsigned char*)sqlite3_column_blob(stmt, i)); break; case 'p': // ip strncpy(new_controller->ip, (const char*)sqlite3_column_text(stmt, i), 16); break; default: // ignore columns not implemented break; } break; case 'n': // name strncpy(new_controller->name, (const char*)sqlite3_column_text(stmt, i), 127); break; case 'p': // port new_controller->port = sqlite3_column_int(stmt, i); break; case 'r': // relay_count new_controller->relay_count = sqlite3_column_int(stmt, i); break; case 't': // tag new_tag = (const char*)sqlite3_column_text(stmt, i); new_controller->tag[0] = '\0'; if(new_tag) { strncpy(new_controller->tag, (const char*)sqlite3_column_text(stmt, i), 63); } break; default: // ignore columns not implemented break; } } return new_controller; } static controller_dbo** controller_db_select(sqlite3_stmt *stmt) { auto **all_controllers = (controller_dbo**)malloc(sizeof(controller_dbo*)); int row = 0; while(true) { int s; s = sqlite3_step(stmt); if (s == SQLITE_ROW) { controller_dbo *new_controller = controller_db_select_mapper(stmt); new_controller->relays = relay_dbo::get_by_simple("controller_id", new_controller->id, (intptr_t)&sqlite3_bind_blob, sizeof(uuid_t)); row++; all_controllers = (controller_dbo**)realloc(all_controllers, sizeof(controller_dbo*) * (row + 1)); all_controllers[row - 1] = new_controller; } else { if (s == SQLITE_DONE) { break; } else { LOG_ERROR << "Error Selecting controllers from database"; sqlite3_finalize(stmt); return nullptr; } } } sqlite3_finalize(stmt); all_controllers[row] = nullptr; return all_controllers; } bool controller_dbo::update() { sqlite3_stmt *stmt; sqlite3_prepare_v2(globals::db, "UPDATE controllers set name = ?2, ip = ?3, active = ?4, port = ?5, relay_count = ?6, tag = ?7 WHERE id = ?1;", -1, &stmt, nullptr); return controller_db_update_insert(this, stmt); } bool controller_dbo::insert() { sqlite3_stmt *stmt; sqlite3_prepare_v2(globals::db, "INSERT INTO controllers(id, name, ip, active, port, relay_count, tag) values (?1, ?2, ?3, ?4, ?5, ?6, ?7);", -1, &stmt, nullptr); return controller_db_update_insert(this, stmt); } bool controller_dbo::remove() { sqlite3_stmt *stmt; int rc; sqlite3_prepare_v2(globals::db, "DELETE FROM controllers WHERE id=?1;", -1, &stmt, nullptr); sqlite3_bind_blob(stmt, 1, this->id, sizeof(uuid_t), SQLITE_STATIC); rc = sqlite3_step(stmt); sqlite3_finalize(stmt); return rc == SQLITE_DONE; } Json::Value controller_dbo::to_json() { char id_str[37]; uuid_unparse(this->id, id_str); Json::Value controller_json; controller_json["name"] = this->name; controller_json["id"] = id_str; controller_json["ip"] = this->ip; controller_json["relay_count"] = this->relay_count; controller_json["active"] = this->active; controller_json["tag"] = this->tag; controller_json["relays"] = Json::arrayValue; for(int i = 0; this->relays[i] != nullptr; i++) { controller_json["relays"].append(this->relays[i]->to_json()); } return controller_json; } controller_dbo** controller_dbo::get_all() { sqlite3_stmt *stmt; sqlite3_prepare_v2(globals::db, "SELECT * FROM controllers;", -1, &stmt, nullptr); return controller_db_select(stmt); } controller_dbo** controller_dbo::get_by_simple(const char *key, const void *value, intptr_t bind_func, int bind_func_param) { helpers::sql_filter_builder *filters[1]; helpers::sql_filter_builder filter { key, value, bind_func, bind_func_param, ";" }; filters[0] = &filter; sqlite3_stmt *stmt = helpers::create_sql_filtered_query("SELECT * FROM controllers WHERE", filters); return controller_db_select(stmt); } controller_dbo** controller_dbo::get_by(helpers::sql_filter_builder **filters) { sqlite3_stmt *stmt = helpers::create_sql_filtered_query("SELECT * FROM controllers WHERE", filters); return controller_db_select(stmt); } bool controller_dbo::command(int command_code, const char *payload) { char port_str[6]; sprintf(port_str, "%d", this->port); int controller_socket = helpers::open_tcp_connection(this->ip, port_str); if(!controller_socket) { LOG_ERROR << "Can't open command socket " << this->ip << ":" << port_str; return false; } LOG_DEBUG << "Commanding (" << command_code << ") " << payload; send(controller_socket, &command_code, 1, 0); send(controller_socket, payload, strlen(payload), 0); close(controller_socket); return true; } void controller_dbo::free_list(controller_dbo **controllers_list) { for(int i = 0; controllers_list[i] != nullptr; i++) { delete controllers_list[i]; } free(controllers_list); }