#include "TcpSocket.hpp" #include "sql.hpp" #include "values/DnaManager.hpp" #include "checker.hpp" #include #include #include #include #include #include // use pthread rw_lock to lock db so you can safy clone .db file class BlockedList { private: std::mutex m; sqlite3 *db; sqlite3_stmt *sel_stmt; sqlite3_stmt *ins_stmt; sqlite3_stmt *upd_stmt; public: void init() { int rc = sql::open(DB_NAME, &db); if (rc) { fprintf(stderr, "Can't open database: %s\n", sql::errmsg(db)); return; } sql::prepare_v2(db, get_warnings, -1, &sel_stmt, NULL); sql::prepare_v2(db, insert_warnings, -1, &ins_stmt, NULL); sql::prepare_v2(db, set_warnings, -1, &upd_stmt, NULL); } bool isBlocked(uint32_t id) { std::scoped_lock lock(m); sql::bind_int64(sel_stmt, 1, id); int64_t found = 0; if (sql::step(sel_stmt) == SQLITE_ROW) { int type = sql::column_type(sel_stmt, 0); if (type != SQL_NULL) found = sql::column_int64(sel_stmt, 0); } sql::reset(sel_stmt); return found >= 3; } void addWarning(uint32_t id) { std::scoped_lock lock(m); sql::bind_int64(sel_stmt, 1, id); int64_t found = 0; int res = sql::step(sel_stmt); if (res == SQLITE_ROW) { int type = sql::column_type(sel_stmt, 0); if (type != SQL_NULL) { found = sql::column_int64(sel_stmt, 0); } sql::reset(sel_stmt); } else if (res == SQL_DONE) { sql::bind_int64(ins_stmt, 1, id); sql::step(ins_stmt); sql::reset(ins_stmt); sql::reset(sel_stmt); return; } sql::bind_int64(upd_stmt, 1, found + 1); sql::bind_int64(upd_stmt, 2, id); sql::step(upd_stmt); sql::reset(upd_stmt); } }; BlockedList blockedList; // When a new client connected: void call(int sock, sockaddr_in newSocketInfo) { std::string add = TcpSocket::remoteAddress(newSocketInfo); //printf("new: %s\n", add.c_str()); int64_t conf, id; Message message; TcpSocket::recvt(sock, &conf, sizeof(conf)); TcpSocket::recvt(sock, &id, sizeof(id)); if (conf != StartHeader) { //printf("StartHeader ERROR\n"); TcpSocket::closet(sock); //blockedList.addWarning(newSocketInfo.sin_addr.s_addr); return; } if (id == 0) { //printf("ID ERROR\n"); TcpSocket::closet(sock); //blockedList.addWarning(newSocketInfo.sin_addr.s_addr); return; } bool ok = true; sqlite3 *db; sqlite3_stmt *max_gen_stmt; int rc = sql::open(DB_NAME, &db); if (rc) { fprintf(stderr, "Can't open database: %s\n", sql::errmsg(db)); ok = false; } sql::prepare_v2(db, max_gen, -1, &max_gen_stmt, NULL); sql::bind_int64(max_gen_stmt, 1, id); int64_t gen = 0; while (sql::step(max_gen_stmt) != SQL_DONE) { int type = sql::column_type(max_gen_stmt, 0); if (type == SQL_NULL) break; gen = sql::column_int64(max_gen_stmt, 0); gen++; } sql::finalize(max_gen_stmt); sqlite3_stmt *insert_liked_stmt; sql::prepare_v2(db, insert_like_data, -1, &insert_liked_stmt, NULL); sqlite3_stmt *insert_user_stmt; sql::prepare_v2(db, insert_user_data, -1, &insert_user_stmt, NULL); // limit how many gen they can send so some cant just come to here and start sendding random data. while (ok) { message.mess = Mess::REQ_SEND_GEN; message.data = gen; //printf("requesting gen %ld\n", gen); TcpSocket::sendt(sock, &message, sizeof(Message)); TcpSocket::recvt(sock, &message, sizeof(Message)); if (message.mess == Mess::RES_NO) { break; } std::vector list; list.resize(NUM_PER_GEN); TcpSocket::recvt(sock, list.data(), NUM_PER_GEN * sizeof(NetUnit)); sql::bind_int64(insert_user_stmt, 1, id); sql::bind_int64(insert_user_stmt, 2, gen); sql::step(insert_user_stmt); sql::reset(insert_user_stmt); int64_t user_table_id = sql::last_insert_rowid(db); for (size_t i = 0; i < list.size(); i++) { sql::bind_int64(insert_liked_stmt, 1, user_table_id); sql::bind_int64(insert_liked_stmt, 2, list[i].hash); sql::bind_int64(insert_liked_stmt, 3, list[i].index); sql::bind_int64(insert_liked_stmt, 4, list[i].liked); sql::step(insert_liked_stmt); sql::reset(insert_liked_stmt); } gen++; } sql::finalize(insert_user_stmt); sql::finalize(insert_liked_stmt); sql::close(db); //printf("del\n"); TcpSocket::closet(sock); } void send_key(int sock, sockaddr_in newSocketInfo) { TcpSocket::sendt(sock, &StartHeader, sizeof(StartHeader)); TcpSocket::closet(sock); } void listen_key() { int err = TcpSocket::listent("0.0.0.0", keyPort, send_key); if (err < 0) { printf("ERROR %d", err); } } int main() { sql::init(); sql::create_tables(); blockedList.init(); //std::thread t(checker); std::thread l(listen_key); // Bind the server to a port. int err = TcpSocket::listent("0.0.0.0", serverPort, call); if (err < 0) { printf("ERROR %d", err); return 0; } return 0; }