#include #include #include #include #include #include "json.hpp" #include #include #include #include using Db = std::vector>; void save_database(Db& database, std::string file_name) { nlohmann::json json_data = database; std::string serialised_json_data = json_data.dump(); std::ofstream db_file(file_name); db_file << serialised_json_data; db_file.close(); } void load_database(Db& database, std::string file_name) { std::ifstream db_file(file_name); std::stringstream raw_file_text; raw_file_text << db_file.rdbuf(); db_file.close(); database = nlohmann::json::parse(raw_file_text.str()); } void add_entry(Db& database, std::string key, std::string value) { database.push_back({key, value}); } void remove_entry(Db& database, std::string key) { int index = 0; for (std::vector& entry : database) { index++; if (entry[0] == key) { database.erase(database.begin() + index); } } } // void prompt_user(Db& database) { // std::string mode; // std::cin >> mode; // if (mode == "add") { // std::string key; // std::string value; // std::cin >> key; // std::cin >> value; // add_entry(database, key, value); // } else if (mode == "rem") { // std::string key; // std::cin >> key; // remove_entry(database, key); // } else if (mode == "save") { // std::string file; // std::cin >> file; // save_database(database, file); // } else if (mode == "load") { // std::string file; // std::cin >> file; // load_database(database, file); // } else { // prompt_user(database); // } // } std::vector parse_resp_request(char* request) { std::string request_str(request); std::string delimiter = "\r\n"; std::vector split_request; size_t pos = 0; while ((pos = request_str.find(delimiter)) != std::string::npos) { split_request.push_back(request_str.substr(0, pos)); request_str.erase(0, pos + delimiter.length()); } if (request_str.length() > 0) { split_request.push_back(request_str); } for (std::string entry: split_request) { if (entry.contains("*")) { split_request.erase(find(split_request.begin(), split_request.end(), entry)); } } for (std::string entry: split_request) { if (entry.contains("$")) { split_request.erase(find(split_request.begin(), split_request.end(), entry)); } } return split_request; } int main() { std::cout << "[i] Starting blueis server..." << std::endl; Db database; load_database(database, "db.json"); int listening_socket = socket(AF_INET, SOCK_STREAM, 0 ); if (listening_socket < 0) { std::cerr << "[E] Failed to create socket." << std::endl; return 1; } int optval = 1; if (setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) { std::cerr << "[W] Failed to use SO_REUSEADDR. Continuing." << std::endl; } sockaddr_in server_address; server_address.sin_family = AF_INET; server_address.sin_port = htons(6379); server_address.sin_addr.s_addr = INADDR_ANY; if (bind(listening_socket, (sockaddr*)&server_address, sizeof(server_address)) < 0) { std::cerr << "[E] Failed to bind to port 6379. Check for any other running redis or blueis instances." << std::endl; close(listening_socket); return 1; } if (listen(listening_socket, 5) < 0) { std::cerr << "[E] Failed to listen on socket." << std::endl; close(listening_socket); return 1; } std::cout << "[i] Server listening on port 6379..." << std::endl; sockaddr_in client_address; socklen_t client_size = sizeof(client_address); while (true) { int client_socket = accept(listening_socket, (sockaddr*)&client_address, &client_size); if (client_socket < 0) { std::cerr << "[E] Failed to accept connection." << std::endl; close(listening_socket); return 1; } std::cout << "[i] Client connected." << std::endl; while (true) { char buffer[4096]; int bytes_received = recv(client_socket, buffer, 4096, 0); if (bytes_received > 0) { buffer[bytes_received] = '\0'; std::cout << "[i] Received: " << buffer << std::endl; std::vector parsed = parse_resp_request(buffer); for (std::string& var: parsed) { } if (parsed[0] == "GET") { bool found = false; for (const auto& inner_vec: database) { if (!inner_vec.empty() && inner_vec[0] == parsed[1]) { int length = inner_vec[1].length(); std::string return_string = std::format("${}\r\n{}\r\n", length, inner_vec[1]); std::cout << "[d] Sending: " << return_string << std::endl; send(client_socket, return_string.data(), return_string.length(), 0); found = true; } } if (!found) { send(client_socket, "$-1\r\n", strlen("$-1\r\n"), 0); } } else if (parsed[0] == "SET") { bool found = false; for (auto& inner_vec: database) { if (!inner_vec.empty() && inner_vec[0] == parsed[1]) { inner_vec[1] = parsed[2]; send(client_socket, "+OK\r\n", strlen("+OK\r\n"), 0); found = true; } if (!found) { std::vector new_kv = { parsed[1], parsed[2] }; database.push_back(new_kv); send(client_socket, "+OK\r\n", strlen("+OK\r\n"), 0); found = true; } } } else { send(client_socket, "+OK\r\n", strlen("+OK\r\n"), 0); } } else { close(client_socket); std::cout << "[i] Client disconnected." << std::endl; break; } } } return 0; }