bigsnitch/session.cpp

243 lines
6.8 KiB
C++
Raw Normal View History

2020-08-08 11:44:16 +00:00
#include "session.h"
Session::Session(QObject *parent) : QObject(parent)
{
}
Session::~Session() {
unload();
}
2020-08-13 21:25:04 +00:00
void Session::open_db(std::filesystem::path path) {
2020-08-08 11:44:16 +00:00
if(db) {
unload();
}
2020-08-13 21:25:04 +00:00
2020-08-08 11:44:16 +00:00
auto rc = sqlite3_open(path.c_str(), &db);
2020-08-13 21:25:04 +00:00
if(rc != SQLITE_OK) {
2020-08-08 11:44:16 +00:00
qDebug("cannot open database");
2020-08-09 12:07:14 +00:00
qDebug() << sqlite3_errmsg(db);
2020-08-08 11:44:16 +00:00
unload();
throw;
}
2020-08-13 21:25:04 +00:00
}
void Session::prepare(const char* query, sqlite3_stmt** stmt) {
auto rc = sqlite3_prepare_v2(db, query, strlen(query), stmt, 0);
if(rc != SQLITE_OK) {
qDebug() << "cannot prepare statement";
qDebug() << query;
qDebug() << sqlite3_errmsg(db);
unload();
throw;
}
}
bool Session::prepare_and_exec(const char* query) {
sqlite3_stmt* res;
prepare(query, &res);
bool result = sqlite3_step(res)==SQLITE_OK;
sqlite3_finalize(res);
return result;
}
void Session::prepare_tables() {
sqlite3_stmt* res;
prepare(check_tbl, &res);
auto s = "session";
sqlite3_bind_text(res, 1, s, strlen(s), nullptr);
auto rc = sqlite3_step(res);
sqlite3_finalize(res);
if(rc == SQLITE_ROW) {
prepare(check_session_info, &res);
auto v = "version";
sqlite3_bind_text(res, 1, v, strlen(v), nullptr);
rc = sqlite3_step(res);
if(rc == SQLITE_ROW) {
const char* version = (const char*)sqlite3_column_text(res, 1);
if(std::atoi(version) != LITTLESNITCH_VERSION) {
qDebug() << "version " << version << " is not supported!";
unload();
throw;
}
qDebug() << "loaded session with version " << version;
sqlite3_finalize(res);
return;
} else {
qDebug("broken database, was not able to check session info");
qDebug() << sqlite3_errmsg(db);
unload();
throw;
}
}
prepare_and_exec(create_request_tbl);
prepare_and_exec(create_request_header_tbl);
prepare_and_exec(create_response_tbl);
prepare_and_exec(create_response_header_tbl);
prepare_and_exec(create_flow_tbl);
prepare_and_exec(create_session_tbl);
prepare(insert_request, &stmt_insert_request);
prepare(insert_request_header, &stmt_insert_request_header);
prepare(insert_response, &stmt_insert_response);
prepare(insert_response_header, &stmt_insert_response_header);
prepare(insert_flow, &stmt_insert_flow);
prepare(insert_session, &stmt_insert_session);
}
void Session::load(std::filesystem::path path)
{
open_db(path);
prepare_tables();
loaded = true;
2020-08-08 11:44:16 +00:00
}
void Session::unload() {
if(db) {
sqlite3_close(db);
}
2020-08-13 21:25:04 +00:00
loaded = false;
}
bool Session::isLoaded() {
return loaded;
}
void Session::bind_text(sqlite3_stmt* stmt, int id, std::string text) {
//qDebug() << id << " " << text.c_str() << " " << strlen(text.c_str());
2020-08-13 21:25:04 +00:00
sqlite3_bind_text(stmt, id, text.c_str(), -1, SQLITE_TRANSIENT);
2020-08-08 11:44:16 +00:00
}
2020-08-09 12:07:14 +00:00
int Session::saveRequest(http::Flow flow) {
2020-08-14 16:54:43 +00:00
sqlite3_reset(stmt_insert_request);
int j = 1;
bind_text(stmt_insert_request, j++, flow.request.server_ip_address);
sqlite3_bind_int(stmt_insert_request, j++, flow.request.tls);
bind_text(stmt_insert_request, j++, flow.request.content);
bind_text(stmt_insert_request, j++, flow.request.scheme);
bind_text(stmt_insert_request, j++, flow.request.method);
bind_text(stmt_insert_request, j++, flow.request.host);
bind_text(stmt_insert_request, j++, flow.request.address);
sqlite3_bind_int(stmt_insert_request, j++, flow.request.port);
bind_text(stmt_insert_request, j++, flow.request.http_version);
bind_text(stmt_insert_request, j++, flow.request.path);
sqlite3_bind_double(stmt_insert_request, j++, flow.request.timestamp_start);
sqlite3_bind_double(stmt_insert_request, j++, flow.request.timestamp_end);
bind_text(stmt_insert_request, j++, flow.request.error);
2020-08-13 21:25:04 +00:00
auto rc = sqlite3_step(stmt_insert_request);
if(rc != SQLITE_DONE) {
qDebug() << "inserting request failed" << rc;
qDebug() << sqlite3_errmsg(db);
2020-08-14 16:54:43 +00:00
return -1;
2020-08-13 21:25:04 +00:00
}
int id = sqlite3_last_insert_rowid(db);
for(auto&[k,v] : flow.request.headers) {
saveRequestHeader(k,v,id);
}
return id;
}
2020-08-14 16:54:43 +00:00
int Session::saveRequestHeader(std::string key, std::string value, int id) {
sqlite3_reset(stmt_insert_request_header);
2020-08-14 16:54:43 +00:00
int j = 1;
bind_text(stmt_insert_request_header, j++, key);
bind_text(stmt_insert_request_header, j++, value);
sqlite3_bind_int(stmt_insert_request_header, j++, id);
auto rc = sqlite3_step(stmt_insert_request_header);
if(rc != SQLITE_DONE) {
qDebug() << "inserting request header failed" << rc;
qDebug() << sqlite3_errmsg(db);
return -1;
}
return sqlite3_last_insert_rowid(db);
2020-08-09 12:07:14 +00:00
}
2020-08-14 01:37:33 +00:00
2020-08-14 16:54:43 +00:00
int Session::saveResponse(http::Flow flow) {
sqlite3_reset(stmt_insert_response);
int j = 1;
sqlite3_bind_int(stmt_insert_response, j++, flow.response.status_code);
bind_text(stmt_insert_response, j++, flow.response.http_version);
bind_text(stmt_insert_response, j++, flow.response.reason);
bind_text(stmt_insert_response, j++, flow.response.content);
sqlite3_bind_double(stmt_insert_response, j++, flow.response.timestamp_start);
sqlite3_bind_double(stmt_insert_response, j++, flow.response.timestamp_end);
2020-08-14 16:54:43 +00:00
auto rc = sqlite3_step(stmt_insert_response);
if(rc != SQLITE_DONE) {
qDebug() << "inserting response failed" << rc;
qDebug() << sqlite3_errmsg(db);
return -1;
}
int id = sqlite3_last_insert_rowid(db);
for(auto&[k,v] : flow.response.headers) {
saveResponseHeader(k,v,id);
}
return id;
}
int Session::saveResponseHeader(std::string key, std::string value, int id) {
sqlite3_reset(stmt_insert_response_header);
int j = 1;
bind_text(stmt_insert_response_header, j++, key);
bind_text(stmt_insert_response_header, j++, value);
sqlite3_bind_int(stmt_insert_response_header, j++, id);
auto rc = sqlite3_step(stmt_insert_response_header);
if(rc != SQLITE_DONE) {
qDebug() << "inserting response header failed" << rc;
qDebug() << sqlite3_errmsg(db);
return -1;
}
return sqlite3_last_insert_rowid(db);
}
int Session::saveFlow(http::Flow flow) {
int request_id = saveRequest(flow);
int response_id = saveResponse(flow);
int j = 1;
bind_text(stmt_insert_flow, j++, flow.uid);
sqlite3_bind_int(stmt_insert_flow, j++, request_id);
sqlite3_bind_int(stmt_insert_flow, j++, response_id);
auto rc = sqlite3_step(stmt_insert_flow);
sqlite3_reset(stmt_insert_flow);
if(rc != SQLITE_DONE) {
qDebug() << "inserting flow failed" << rc;
qDebug() << sqlite3_errmsg(db);
return -1;
}
return sqlite3_last_insert_rowid(db);
2020-08-14 01:37:33 +00:00
}