From d2e062d03de8a99a340673499cbdb371e4467054 Mon Sep 17 00:00:00 2001 From: Wirlaburla Date: Thu, 17 Oct 2024 20:02:54 -0500 Subject: [PATCH] Add proper logging --- conf/ftp.conf | 3 +++ src/client.cpp | 18 +++++++++--------- src/filer.cpp | 12 ++++++------ src/logger.h | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 32 +++++++++++++++---------------- src/main.h | 7 +++++++ 6 files changed, 92 insertions(+), 31 deletions(-) create mode 100644 src/logger.h diff --git a/conf/ftp.conf b/conf/ftp.conf index 85ccd42..0fa9ded 100644 --- a/conf/ftp.conf +++ b/conf/ftp.conf @@ -2,6 +2,9 @@ server_name=My FTP Server motd_file=motd auth_engine=noauth +[logging] +file=digftp.log +level=0 [net] listen_address=127.0.0.1 control_port=21 diff --git a/src/client.cpp b/src/client.cpp index f741f70..6e06a43 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -96,7 +96,7 @@ public: sscanf(config->getValue("net", "listen_address", "127.0.0.1").c_str(), "%d.%d.%d.%d", &netaddr[0], &netaddr[1], &netaddr[2], &netaddr[3]); dataport = ntohs(data_address.sin_port); memcpy(&netport[0], &dataport, 2); - printf("[i] D(%i) PASV initialized: %u.%u.%u.%u:%u\n", data_fd, netaddr[0], netaddr[1], netaddr[2], netaddr[3], dataport); + logger->print(LOGLEVEL_DEBUG, "D(%i) PASV initialized: %u.%u.%u.%u:%u", data_fd, netaddr[0], netaddr[1], netaddr[2], netaddr[3], dataport); } else { perror("pasv getpeername() failed"); close(data_fd); @@ -119,7 +119,7 @@ public: free(pasvok); if ((data_sock = accept(data_fd, NULL, NULL)) >= 0) { - printf("[i] D(%i) PASV accepted: %i\n", data_fd, data_sock); + logger->print(LOGLEVEL_INFO, "D(%i) PASV accepted: %i", data_fd, data_sock); state = 2; } else { perror("accept() failed"); @@ -135,7 +135,7 @@ public: sscanf(argstr.c_str(), "%d,%d,%d,%d,%d,%d", &act_ip[0], &act_ip[1], &act_ip[2], &act_ip[3], (int*)&act_port[0], (int*)&act_port[1]); sprintf(ip_decimal, "%d.%d.%d.%d", act_ip[0], act_ip[1], act_ip[2], act_ip[3]); port_dec = act_port[0]*256+act_port[1]; - printf("[d] D(%i) PORT initialized: %s:%d\n", control_sock, ip_decimal, port_dec); + logger->print(LOGLEVEL_DEBUG, "D(%i) PORT initialized: %s:%d", control_sock, ip_decimal, port_dec); data_address.sin_family = AF_INET; data_address.sin_addr.s_addr = inet_addr(ip_decimal); @@ -217,7 +217,7 @@ public: submit(331, "Password required"); } else if (cmd == "PASS") { if (auth->check(name, argstr)) { - printf("[d] (%i) logged in as '%s'\n", control_sock, name.c_str()); + logger->print(LOGLEVEL_INFO, "(%i) logged in as '%s'", control_sock, name.c_str()); // We can now set the root safely (I hope). filer->setRoot(auth->getUserDirectory(name)); state = 1; @@ -240,26 +240,26 @@ public: std::string out = std::to_string(code)+" "+msg+"\r\n"; int bytes = send(control_sock, out.c_str(), out.size(), 0); if (bytes < 0) { - printf("[d] C(%i) !< %i %s\n", control_sock, code, msg.c_str()); + logger->print(LOGLEVEL_ERROR, "C(%i) !< %i %s", control_sock, code, msg.c_str()); return 1; } - printf("[d] C(%i) << %i %s\n", control_sock, code, msg.c_str()); + logger->print(LOGLEVEL_DEBUG, "C(%i) << %i %s", control_sock, code, msg.c_str()); return 0; } int data_submit(char* out, int size) { int bytes = send(data_sock, out, size, 0); if (bytes < 0) { - printf("[d] D(%i) !< %i\n", data_sock, size); + logger->print(LOGLEVEL_DEBUG, "D(%i) !< %i", data_sock, size); return 1; } - printf("[d] D(%i) << %i\n", data_sock, size); + logger->print(LOGLEVEL_DEBUG, "D(%i) << %i", data_sock, size); return 0; } int data_close() { if (data_sock <= 0) return 0; - printf("[d] D(%i) Closing...\n", data_sock); + logger->print(LOGLEVEL_DEBUG, "D(%i) Closing...", data_sock); close(data_sock); data_sock = -1; close(data_fd); diff --git a/src/filer.cpp b/src/filer.cpp index f6039cd..a6ad322 100644 --- a/src/filer.cpp +++ b/src/filer.cpp @@ -41,7 +41,7 @@ public: int traverse(std::string dir) { fs::path ndir = fs::weakly_canonical(cwd / dir); fs::path fdir = fullPath(dir); - printf("[i] Traversing: %s\n", ndir.c_str()); + logger->print(LOGLEVEL_INFO, "Traversing: %s", ndir.c_str()); if (fdir.string().rfind(root.string(), 0) != 0) return -2; else if (!fs::exists(fdir) || !fs::is_directory(fdir)) return -1; else { @@ -52,7 +52,7 @@ public: int setRoot(std::string _root) { fs::path froot = fs::weakly_canonical(_root); - printf("[i] Setting root: %s\n", froot.c_str()); + logger->print(LOGLEVEL_INFO, "Setting root: %s", froot.c_str()); if (!fs::exists(froot)) fs::create_directory(froot); root = fs::absolute(froot); cwd = "/"; @@ -89,7 +89,7 @@ public: int fileSize(std::string name) { fs::path nfile = fs::weakly_canonical(cwd / name); fs::path ffile = fullPath(name); - printf("[i] Retreiving filesize: %s\n", nfile.c_str()); + logger->print(LOGLEVEL_INFO, "Retreiving filesize: %s", nfile.c_str()); if (ffile.string().rfind(root.string(), 0) != 0) return -2; else if (!fs::exists(ffile)) return -1; else if (type == 'A') return -3; @@ -105,7 +105,7 @@ public: int deleteFile(std::string name) { fs::path nfile = fs::weakly_canonical(cwd / name); fs::path ffile = fullPath(name); - printf("[i] Deleting file: %s\n", nfile.c_str()); + logger->print(LOGLEVEL_INFO, "Deleting file: %s", nfile.c_str()); if (ffile.string().rfind(root.string(), 0) != 0) return -2; else if (!fs::exists(ffile)) return -1; else { @@ -119,7 +119,7 @@ public: fs::path nfile = fs::weakly_canonical(cwd / name); fs::path ffile = fullPath(name); - printf("[i] Retreiving file: %s\n", nfile.c_str()); + logger->print(LOGLEVEL_INFO, "Retreiving file: %s", nfile.c_str()); if (ffile.string().rfind(root.string(), 0) != 0) fd.ecode = -2; else if (!fs::exists(ffile)) fd.ecode = -1; else if (type != 'A') { @@ -142,7 +142,7 @@ public: int writeFile(std::string name, unsigned char* data, int size) { fs::path nfile = fs::weakly_canonical(cwd / name); fs::path ffile = fullPath(name); - printf("[i] Storing file: %s\n", nfile.c_str()); + logger->print(LOGLEVEL_INFO, "Storing file: %s", nfile.c_str()); if (ffile.string().rfind(root.string(), 0) != 0) return -2; else { std::ofstream outfile(ffile, std::ios::out|std::ios::binary); diff --git a/src/logger.h b/src/logger.h new file mode 100644 index 0000000..52ad26c --- /dev/null +++ b/src/logger.h @@ -0,0 +1,51 @@ +#ifndef LOGGER_H +#define LOGGER_H +#include + +#define LOGLEVEL_ERROR 3 +#define LOGLEVEL_WARNING 2 +#define LOGLEVEL_INFO 1 +#define LOGLEVEL_DEBUG 0 + +class Logger { +public: + Logger(const char* path) { + logfile.open(path, std::ios::binary|std::ios::app); + }; + + void setLevel(int level) { this->logLevel = level; } + + template + void print(int level, const char* message, Args... args) { + if (level >= this->logLevel) { + char* prepared; + char* formatted; + asprintf(&prepared, "[%c] %s\n", logTypeChar(level), message); + asprintf(&formatted, prepared, args...); + fprintf(stdout, formatted); + if (logfile.is_open()) { + logfile.write(formatted, strlen(formatted)); + logfile.flush(); + } + } + }; + + void close() { + logfile.close(); + } +private: + std::ofstream logfile; + int logLevel = 0; + + static const char logTypeChar(int level) { + switch(level) { + default: return ' '; + case LOGLEVEL_ERROR: return 'E'; + case LOGLEVEL_WARNING: return 'W'; + case LOGLEVEL_INFO: return 'I'; + case LOGLEVEL_DEBUG: return 'D'; + } + } +}; + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index b78f16e..55217f3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -22,8 +22,8 @@ using namespace std::chrono_literals; -const int max_clients = config->getInt("net", "max_clients", 255); -const int cport = config->getInt("net", "control_port", 21); +const uint16_t max_clients = config->getInt("net", "max_clients", 255); +const uint16_t cport = config->getInt("net", "control_port", 21); struct pollfd fds[65535]; struct clientfd { @@ -41,10 +41,9 @@ void runClient(struct clientfd* cfd) { //while (fcntl(cfd->client->control_sock, F_GETFD) != -1) { while (true) { if (cfd->client == nullptr) { break; } - printf("[d] C(%i) Attempting read...\n", cfd->client->control_sock); int rc = recv(cfd->client->control_sock, inbuf, sizeof(inbuf), 0); if (rc < 0) { - printf("[d] C(%i) Recieved empty packet\n", cfd->client->control_sock); + logger->print(LOGLEVEL_WARNING, "C(%i) Recieved empty packet", cfd->client->control_sock); if (errno != EWOULDBLOCK) { perror("recv() failed"); break; @@ -65,19 +64,20 @@ void runClient(struct clientfd* cfd) { std::string args = ""; if (len > cmdend) args = lin.substr(cmdend+1, len-cmdend-1); - printf("[d] C(%i) >> '%s' '%s'\n", cfd->client->control_sock, cmd.c_str(), args.c_str()); + logger->print(LOGLEVEL_DEBUG, "C(%i) >> '%s' '%s'", cfd->client->control_sock, cmd.c_str(), args.c_str()); if (cfd->client->receive(cmd, args) < 0) break; inbuf[0] = '\0'; } } catch (...) { - printf("[!] C(%i) Caught error!\n", cfd->client->control_sock); + logger->print(LOGLEVEL_ERROR, "C(%i) Caught error!", cfd->client->control_sock); } - //printf("[d] C(%i) Marking for deletion...\n", cfd->client->control_sock); cfd->close = true; } int main(int argc , char *argv[]) { + logger = new Logger(config->getValue("logging", "file", "digftp.log").c_str()); + logger->setLevel(config->getInt("logging", "level", 0)); std::string authType = config->getValue("main", "auth_engine", "plain"); auth = getAuthByName(authType); auth->setOptions(config->get(authType)); @@ -129,7 +129,7 @@ int main(int argc , char *argv[]) { fds[0].fd = master_socket; fds[0].events = POLLIN; - printf("[i] Server started.\n"); + logger->print(LOGLEVEL_INFO, "Server started."); while (run) { int pc = poll(fds, nfds, -1); @@ -139,7 +139,7 @@ int main(int argc , char *argv[]) { } if (pc == 0) { - printf("poll() timed out\n"); + perror("poll() timed out\n"); break; } @@ -149,7 +149,7 @@ int main(int argc , char *argv[]) { continue; if(fds[i].revents != POLLIN) { - printf("[!] C(%i) Error! revents = %d\n", fds[i].fd, fds[i].revents); + logger->print(LOGLEVEL_ERROR, "C(%i) Error! revents = %d", fds[i].fd, fds[i].revents); goto conn_close; } if (fds[i].fd == master_socket) { @@ -162,8 +162,7 @@ int main(int argc , char *argv[]) { } break; } - - printf("[d] C(%i) Accepted client\n", newsock); + logger->print(LOGLEVEL_DEBUG, "C(%i) Accepted client", newsock); fds[nfds].fd = newsock; fds[nfds].events = POLLIN; fdc[nfds].close = false; @@ -174,7 +173,7 @@ int main(int argc , char *argv[]) { } else { if (fdc[i].close) { conn_close: - printf("[d] C(%i) Deleting client...\n", fds[i].fd); + logger->print(LOGLEVEL_DEBUG, "C(%i) Deleting client...", fds[i].fd); close(fds[i].fd); fds[i].fd = -1; if (fdc[i].client->thread.joinable()) @@ -193,15 +192,15 @@ int main(int argc , char *argv[]) { if (fds[i].fd == -1) { for(int j = i; j < nfds; j++) { if (fds[j].fd == -1) { - printf("[d] Compressing: %i(fd:%i) <= %i(fd:%i)\n", j, fds[j].fd, j+1, fds[j+1].fd); + logger->print(LOGLEVEL_DEBUG, "Compressing: %i(fd:%i) <= %i(fd:%i)", j, fds[j].fd, j+1, fds[j+1].fd); fds[j].fd = fds[j+1].fd; fds[j].revents = fds[j+1].revents; fds[j+1].fd = -1; - printf("[d] Reinitialized fds of %i\n", j+1); + logger->print(LOGLEVEL_DEBUG, "Reinitialized fds of %i", j+1); fdc[j].client = fdc[j+1].client; fdc[j].close = fdc[j+1].close; fdc[j+1] = {}; - printf("[d] Reinitialized fdc of %i\n", j+1); + logger->print(LOGLEVEL_DEBUG, "[d] Reinitialized fdc of %i", j+1); } } i--; @@ -210,5 +209,6 @@ int main(int argc , char *argv[]) { } } } + logger->close(); return 0; } \ No newline at end of file diff --git a/src/main.h b/src/main.h index f31a0a1..631cd37 100644 --- a/src/main.h +++ b/src/main.h @@ -1,10 +1,17 @@ #ifndef MAIN_H #define MAIN_H + +#define CONF_DIR "conf" +#define LOG_DIR "log" + #include "conf.h" +#include "logger.h" + #include "auth.h" #include "auth/noauth.h" ConfigFile* config = new ConfigFile("conf/ftp.conf"); Auth* auth; +Logger* logger; #endif \ No newline at end of file